-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
baa9720
commit 258ef22
Showing
8 changed files
with
296 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Thu Feb 04 17:59:00 2016 | ||
from Matlab | ||
@author: Tobias Heinl, Gerald Schuller | ||
Function extracts analysis baseband impulse response (reverse window function) | ||
from the folding matrix Fa of a cosine | ||
modulated filter bank, with modulation function for the analysis IR : | ||
h_k(n)=h(n)*cos(pi/N*(k+0.5)*(L-1-n+0.5-N/2)); | ||
""" | ||
|
||
|
||
def Fa2h(Fa): | ||
""" Function extracts analysis baseband impulse response (reverse window function) | ||
from the folding matrix Fa of a cosine modulated filter bank. | ||
""" | ||
import numpy as np | ||
from polmatmult import polmatmult | ||
[N,y,blocks] = np.shape(Fa) | ||
h0 = np.zeros(blocks * N) | ||
#First column of DCT-4: | ||
T = np.zeros((N,1,1)) | ||
T[:,0,0]=np.cos(np.pi/N*(0.5)*(np.arange(N)+0.5)) | ||
#Compute first column of Polyphase matrix Pa(z): | ||
Pa = polmatmult(Fa,T) | ||
#Extract impulse response h0(n): | ||
for m in range(blocks): | ||
h0[m*N+np.arange(N)] = np.flipud(Pa[:,0,m]) | ||
#Baseband prototype h(n), divide by modulation func.: | ||
#h = h0 / np.cos(np.pi/N*0.5*(np.arange(blocks*N)+ 0.5+(N/2))) | ||
h = -h0 / np.cos(np.pi/N*0.5*(np.arange(blocks*N-1,-1,-1)+ 0.5-(N/2))) | ||
return h; | ||
|
||
|
||
#Testing: | ||
if __name__ == '__main__': | ||
import numpy as np | ||
from symFmatrix import * | ||
from Dmatrix import * | ||
from polmatmult import * | ||
f=np.arange(1,7) | ||
print("f=", f) | ||
Fa=symFmatrix(f) | ||
N=4 | ||
D=Dmatrix(N) | ||
Faz=polmatmult(Fa,D) | ||
print("Faz=", Faz[:,:,0],"\n", Faz[:,:,1]) | ||
h=Fa2h(Faz) | ||
print("h=", h) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Program to optimize cosine modulated low delay filter banks. | ||
Gerald Schuller, July 2018 | ||
""" | ||
|
||
import numpy as np | ||
import scipy as sp | ||
import scipy.signal as sig | ||
from symFmatrix import symFmatrix | ||
from polmatmult import polmatmult | ||
from Dmatrix import Dmatrix | ||
from Fa2h import Fa2h | ||
from Gmatrix import Gmatrix | ||
|
||
def optimfuncLDFB(x,N): | ||
'''function for optimizing an MDCT type filter bank. | ||
x: unknown matrix coefficients, N: Number of subbands. | ||
''' | ||
#Analysis folding matrix: | ||
Fa = symFmatrix(x[0:int(1.5*N)]) | ||
Faz = polmatmult(Fa,Dmatrix(N)) | ||
Faz = polmatmult(Faz,Gmatrix(x[int(1.5*N):(2*N)])) | ||
#baseband prototype function h: | ||
h = Fa2h(Faz) | ||
#'Fa2h is returning 2D array. Squeeze to make it 1D' | ||
#h= np.squeeze(h) | ||
|
||
#Frequency response of the the baseband prototype function at 1024 frequency sampling points | ||
#between 0 and Nyquist: | ||
w,H = sig.freqz(h,1,1024) | ||
#desired frequency response | ||
#Limit of desired pass band (passband is between -pb and +pb, hence ../2) | ||
pb = int(1024/N/2.0) | ||
#Ideal desired frequency response: | ||
Hdes = np.concatenate((np.ones(pb),np.zeros(1024-pb))) | ||
#transition band width to allow filter transition from pass band to stop band: | ||
tb = int(np.round(1.0*pb)) | ||
#Weights for differently weighting errors in pass band, transition band and stop band: | ||
weights = np.concatenate((1.0*np.ones(pb), np.zeros(tb),1000*np.ones(1024-pb-tb))) | ||
#Resulting total error number as the sum of all weighted errors: | ||
err = np.sum(np.abs(H-Hdes)*weights) | ||
return err | ||
|
||
if __name__ == '__main__': #run the optimization | ||
import scipy as sp | ||
import scipy.signal | ||
import matplotlib.pyplot as plt | ||
|
||
N=4 #number of subbands | ||
s=2*N | ||
bounds=[(-14,14)]*s | ||
xmin = sp.optimize.differential_evolution(optimfuncLDFB, bounds, args=(N,), disp=True) | ||
print("error after optim.=",xmin.fun) | ||
print("optimized coefficients=",xmin.x) | ||
np.savetxt("LDFBcoeff.txt", xmin.x) | ||
x=xmin.x; | ||
#Baseband Impulse Response: | ||
Fa = symFmatrix(x[0:int(1.5*N)]) | ||
#print("Fa=", Fa[:,:,0]) | ||
Faz = polmatmult(Fa,Dmatrix(N)) | ||
Faz = polmatmult(Faz,Gmatrix(x[int(1.5*N):(2*N)])) | ||
h = Fa2h(Faz) | ||
plt.plot(h) | ||
plt.xlabel('Sample') | ||
plt.ylabel('Value') | ||
plt.title('Baseband Impulse Response of the Low Delay Filter Bank') | ||
#Magnitude Response: | ||
w,H=sp.signal.freqz(h) | ||
plt.figure() | ||
plt.plot(w,20*np.log10(abs(H))) | ||
plt.axis([0, 3.14, -60,20]) | ||
plt.xlabel('Normalized Frequency') | ||
plt.ylabel('Magnitude (dB)') | ||
plt.title('Mag. Frequency Response of the Low Delay Filter Bank') | ||
plt.show() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Program for optimizing an MDCT type filter bank with N subbands. | ||
Gerald Schuller, July 2018 | ||
""" | ||
|
||
|
||
def optimfuncMDCT(x, N): | ||
"""Computes the error function for the filter bank optimization | ||
for coefficients x, a 1-d array, N: Number of subbands""" | ||
import numpy as np | ||
import scipy.signal as sig | ||
from polmatmult import polmatmult | ||
from Dmatrix import Dmatrix | ||
from symFmatrix import symFmatrix | ||
from Fa2h import Fa2h | ||
|
||
#x = np.transpose(x) | ||
Fa = symFmatrix(x) | ||
D = Dmatrix(N) | ||
Faz = polmatmult(Fa,D) | ||
h = Fa2h(Faz) | ||
h = np.hstack(h) | ||
w, H = sig.freqz(h,1,1024) | ||
pb = int(1024/N/2) | ||
Hdes = np.concatenate((np.ones((pb,1)) , np.zeros(((1024-pb, 1)))), axis = 0) | ||
tb = np.round(pb) | ||
weights = np.concatenate((np.ones((pb,1)) , np.zeros((tb, 1)), 1000*np.ones((1024-pb-tb,1))), axis = 0) | ||
err = np.sum(np.abs(H-Hdes)*weights) | ||
return err | ||
|
||
if __name__ == '__main__': #run the optimization | ||
import numpy as np | ||
import scipy as sp | ||
import scipy.optimize | ||
import scipy.signal | ||
import matplotlib.pyplot as plt | ||
from symFmatrix import symFmatrix | ||
from polmatmult import polmatmult | ||
from Dmatrix import Dmatrix | ||
from Fa2h import Fa2h | ||
|
||
N=4 | ||
#Start optimization with some starting point: | ||
x0 = -np.random.rand(int(1.5*N)) | ||
print("starting error=", optimfuncMDCT(x0, N)) #test optim. function | ||
xmin = sp.optimize.minimize(optimfuncMDCT, x0, args=(N,), options={'disp':True}) | ||
print("optimized coefficients=", xmin.x) | ||
np.savetxt("MDCTcoeff.txt", xmin.x) | ||
print("error after optim.=", optimfuncMDCT(xmin.x, N)) | ||
#Baseband Impulse Response: | ||
Fa = symFmatrix(xmin.x) | ||
Faz = polmatmult(Fa, Dmatrix(N)) | ||
h = Fa2h(Faz) | ||
print("h=", h) | ||
plt.plot(h) | ||
plt.xlabel('Sample') | ||
plt.ylabel('Value') | ||
plt.title('Baseband Impulse Response of our Optimized MDCT Filter Bank') | ||
plt.figure() | ||
#Magnitude Response: | ||
w,H=sp.signal.freqz(h) | ||
plt.plot(w,20*np.log10(abs(H))) | ||
plt.axis([0, 3.14, -60,20]) | ||
plt.xlabel('Normalized Frequency') | ||
plt.ylabel('Magnitude (dB)') | ||
plt.title('Mag. Frequency Response of the MDCT Filter Bank') | ||
plt.show() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Python programs to optimize an PQMF filter bank with N subbands | ||
Gerald Schuller, July 2018 | ||
""" | ||
|
||
|
||
from __future__ import print_function | ||
def optimfuncQMF(x,N): | ||
"""Optimization function for a PQMF Filterbank | ||
x: coefficients to optimize (first half of prototype h), N: Number of subbands | ||
err: resulting total error | ||
""" | ||
import numpy as np | ||
import scipy as sp | ||
import scipy.signal as sig | ||
|
||
h = np.append(x,np.flipud(x)); | ||
#H = sp.freqz(h,1,512,whole=True) | ||
f,H_im = sig.freqz(h) | ||
H=np.abs(H_im) #only keeping the real part | ||
posfreq = np.square(H[0:int(512/N)]); | ||
#Negative frequencies are symmetric around 0: | ||
negfreq = np.flipud(np.square(H[0:int(512/N)])) | ||
#Sum of magnitude squared frequency responses should be close to unity (or N) | ||
unitycond = np.sum(np.abs(posfreq+negfreq - 2*(N*N)*np.ones(int(512/N))))/512; | ||
#plt.plot(posfreq+negfreq); | ||
#High attenuation after the next subband: | ||
att = np.sum(np.abs(H[int(1.5*512/N):]))/512; | ||
#Total (weighted) error: | ||
err = unitycond + 100*att; | ||
return err | ||
|
||
if __name__ == '__main__': #run the optimization | ||
from scipy.optimize import minimize | ||
import scipy as sp | ||
import matplotlib.pyplot as plt | ||
|
||
N=4 #Number of subbands | ||
#Start optimization with "good" starting point: | ||
x0 = 16*sp.ones(4*N) | ||
print("starting error=", optimfuncQMF(x0,N)) #test optim. function | ||
xmin = minimize(optimfuncQMF,x0, args=(N,), method='SLSQP') | ||
print("error after optim.=",xmin.fun) | ||
print("optimized coefficients=",xmin.x) | ||
#Store the found coefficients in a text file: | ||
sp.savetxt("QMFcoeff.txt", xmin.x) | ||
#we compute the resulting baseband prototype function: | ||
h = sp.concatenate((xmin.x,sp.flipud(xmin.x))) | ||
plt.plot(h) | ||
plt.xlabel('Sample') | ||
plt.ylabel('Value') | ||
plt.title('Baseband Impulse Response of the Optimized PQMF Filter Bank') | ||
#plt.xlim((0,31)) | ||
plt.show() | ||
#The corresponding frequency response: | ||
w,H=sp.signal.freqz(h) | ||
plt.plot(w,20*sp.log10(abs(H))) | ||
plt.axis([0, 3.14, -100,20]) | ||
plt.xlabel('Normalized Frequency') | ||
plt.ylabel('Magnitude (dB)') | ||
plt.title('Mag. Frequency Response of the PQMF Filter Bank') | ||
plt.show() | ||
#Checking the "unity condition": | ||
posfreq = sp.square(abs(H[0:int(512/N)])); | ||
negfreq = sp.flipud(sp.square(abs(H[0:int(512/N)]))) | ||
plt.plot(posfreq+negfreq) | ||
plt.xlabel('Frequency (512 is Nyquist)') | ||
plt.ylabel('Magnitude') | ||
plt.title('Unity Condition, Sum of Squared Magnitude of 2 Neigh. Subbands') | ||
plt.show() | ||
|