# 數位信號系統實習 ###### tags: `matlab` :::danger >**因為PPT上傳了,所以有些東西有稍微改一下,也些打錯的地方都以刪除線刪除了。** >[name=黃英睿][time=Sun, Jan 8, 2017 10:03 PM][color=#ff0000] > 有發現錯誤和英睿說!!感謝!! ::: [TOC] # 1.雙變數回歸 題目:$y = w1x1+w2x2+b,已知x1,x2,y,求 w1,w2,b,在TwoVariables.mat裡面,各100,000筆。 ## 程式碼 ```python= clear; clc; load('TwoVariables.mat'); %資料筆數 m = 100000; %執行次數 time = 1000; %預先宣告w1,w2,b w1 = rand; w2 = rand; b = rand; %設定步距 u = 0.1 ; %設J的初始值 J = 0; jw1 = 0; jw2 = 0; jb = 0; for i = 1:time J = 1/(2*m)*sum(((w1*x1+w2*x2+b)-y).^2) jw1 = mean(((w1*x1+w2*x2+b)-y).*x1); jw2 = mean(((w1*x1+w2*x2+b)-y).*x2); jb = mean((w1*x1+w2*x2+b)-y); w1 = w1 - (u*jw1); w2 = w2 - (u*jw2); b = b - (u*jb); end ``` >*註解* >sum():加總 >mean():取平均 ## 結果(本題J的收斂值) J = 2.0145 # 2.分析頻率響應並設計逆系統(並分析其頻率響應,理解方塊圖、差分方程式和Z轉換與辨識頻率響應之關係) 差分方程式 例: y[n]=(x[n]+x[n-1]+x[n-2])/3 Z轉換 例: ![](https://i.imgur.com/tPlrQmr.png) 方塊圖 例: ![](https://i.imgur.com/ID7eQHM.png) 將以上三樣求其頻率響應 ![](https://i.imgur.com/XWZrQlX.png) H1為求得的頻率響應,H2則是其逆系統的頻率響應,兩者互為倒數 ## 程式碼 ```python= clear;clc f=8000; [y,fs]=audioread('test.mp4'); t=floor((size(y,1)/fs)*f); tt=[1 round((1:t)/f*fs)]; for i=1:2 yy(:,i)=y(tt,i); end d=2; h=zeros(1,d*f); h(1)=1;h(d*f)=0.5; for i=1:2 yn(:,i)=conv(yy(:,i),h); end Y=zeros(1,d*f); Y(1)=1;Y(d*f)=0.5; for i=1:2 y1(:,i)=filter(1,Y,yn(:,i)); end ``` 以聲音這題為例 這部分的差分方程式為 y[n]=x[n]+0.5x[n-D] D為延遲的時間,即秒數d乘上取樣頻率f ```python=10 d=2; h=zeros(1,d*f); h(1)=1;h(d*f)=0.5; for i=1:2 yn(:,i)=conv(yy(:,i),h); end ``` 而這部分的差分方程式則為 y[n]+0.5y[n-D]=x[n] ```python=17 Y=zeros(1,d*f); Y(1)=1;Y(d*f)=0.5; for i=1:2 y1(:,i)=filter(1,Y,yn(:,i)); end ``` --- ```python=2 f=8000; [y,fs]=audioread('test.mp4'); t=floor((size(y,1)/fs)*f); tt=[1 round((1:t)/f*fs)]; for i=1:2 yy(:,i)=y(tt,i); end ``` 這一段是做把test.mp4的取樣頻率改成8k。 * 第 2 行:設定變數f(新的取樣頻率)。 * 第 3 行:做audioread這個方法,取出test.mp4中的y(聲音資料)和fs(test.mp4的取樣頻率)。 * 第 4 行:設定變數t,計算從fs(44.1K)換成f(8K)後共有多少點,取無條件捨去。 * 第 5 行:設定變數tt,把所有要從y中取出來值的位置都列出來,從1開始。(tt這個**陣列**後面的中括弧中放入兩個值,分別是一個**數字**,和一個**陣列**。大概是以下這種感覺) ```python= a = [4 5 6]; b = [1 a]; ``` ``` b = [1 4 5 6] ``` * 第 6~8 行:做雙聲道的處理。 >註解: >* [y,fs]=audioread(filename):讀檔,y為讀出來的資料,fs為該資料的取樣頻率,filename為資料名稱。 >* audiowrite(y,fs,filename):存檔,y為輸入來的資料,fs為該資料的取樣頻率,filename為資料名稱(***注意:matlab2013中如果要存成.mp4檔案的話,取樣頻率只能設44100~48000***)。 >* floor(a):無條件捨去,將a做無條件捨去。 >* ceil(a):無條件進位,將a做無條件進位。 >* round(a):四捨五入,將a做四捨五入。 >[name=黃英睿][time=Mon, Jan 9, 2017 9:44 PM] --- # 3.估計多路徑延遲 >題目:只給x[n]和y[n]求Delay。 ![](https://i.imgur.com/HzIqtT4.png) 解法: 1. 先猜有幾個Delay,先給Delay範圍(本題8000,P),調整b~0~,b~1~,...,b~8000~ X[n-8000]。 2. $\mathrm{\hat{y}[n]-y[n] = e[n]}$,根據e[n]去做調整,其中$\mathrm{\hat{y}[n]}$是猜的。 ![](https://i.imgur.com/XcwuX2R.png) 3. 用filter把$\mathrm{\hat{y}[n]}$代入。 4. 計算方程式: >$\mathrm{\hat{y}[n] = \sum^{P-1}_{k=0}b_{k}x[n-k]=b_{0}x[n]+b_{1}x[n-1]+...+b_{P-1}x[n-(p-1)]\\ >e[n]=y[n]-\hat{y}[n]=y[n]-\sum^{P-1}_{k=0}b_{k}x[n-k]\\ >E = (e[n])^{2}=(y[n]-\sum^{P-1}_{k=0}b_{k}x[n-k])^{2}\\ >\frac{dE}{dbm}=2×(y[n]-\sum^{P-1}_{k=0}b_{k}x[n-k])×(-x[n-m])=2e[n]x[n-m]\\ >~\\ >new\{b_{0},...,b_{P-1}\}\\ >~=old\{b_{0},...,b_{P-1}\}+u×2×e[n]×\{x[n],x[n-1],...,x[n-(P+1)]\}\\ >=>bm=bm+2×u(y[n]-\hat{y}[n])×x[n-m]}$ 5. 把以上方程式轉換成以下程式碼 ## Steepest Descend(梯度下降法) 是一個一階最佳化算法,通常也稱為最速下降法。 要使用梯度下降法找到一個函數的局部極小值,必須向函數上當前點對應梯度(或者是近似梯度)的反方向的規定步長距離點進行疊代搜索。如果相反地向梯度正方向疊代進行搜索,則會接近函數的局部極大值點;這個過程則被稱為梯度上升法。---[維基百科](https://zh.wikipedia.org/wiki/%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D%E6%B3%95) ## 程式碼 ```python= clear; clc; load('TwoDelay.mat'); P = 8000; bm = zeros(1,P); u = 0.001; for xStart = 0:size(x,1)-P for loop = 1:100 y_cap = bm*flipud(x(xStart+1:xStart+P)); e = y(xStart+P)-y_cap; bm = bm + 2*u*e *flipud(x(xStart+1:xStart+P))'; end plot(bm) pause(0.00001) end ``` 11~13也可以用以下寫法,結果是一樣的。 ```python=11 y_cap = filter(bm,1,x(xStart+1:xStart+P)); e = sum(y(xStart+1:xStart+P)-y_cap); bm = bm + u * e.*flipud(x(xStart+1:xStart+P))'; ``` >*註解* >flipud():將陣列反轉,例:A=[1 2 3],flipud(A)=[3 2 1]。 > >Y = filter(b,a,X):卷積,X是卷積前的值x,Y是卷積後的值y,b是x的係數,a是y的係數。 > > ```python= #矩陣轉置 a = [1 2 3] a' = 1 2 3 ``` ## 程式解析 ```python=3 load('TwoDelay.mat'); ``` * 第 3 行:load "TwoDelay.mat"裡面的參數,分別是x和y的值。 --- ```python=5 P = 8000; bm = zeros(1,P); u = 0.001; ``` * 第 5 行:設定參數的初始值P,P是猜的Delay的數量,猜8000是因為電磁波在真空中的傳輸速率大概是3×10^8^(m/s),所以以取樣頻率8K來看,經過8000點後的值已經繞過了3×10^8^m了,這樣的值已經不值得參考了,所以取8000就已經足夠了。 * 第 6 行:設定參數的初始值bm,bm是我們要猜的x的係數,一開始都全部設為0。 * 第 7 行:設定參數的初始值u,u是步伐(step),不能設太大,否則會無法收斂到最小值,但設太小就會跑很久。 --- ```python=9 for xStart = 0:size(x,1)-P for loop = 1:100 ``` * 第 9 行:xStart是每次開始取x的位置,size是算x的陣列大小(本題是48112),後面減P(本題是8000)是因為每次從xStart的位置向後取出P個點出來做運算,假設我們沒有減P這樣他會一直取到xStart = 48112(x的size),然後向後取8000點,但是後面已經沒有點了,所以算出來會錯。對應第 17 行的end。 * 第 10 行:每次取P個點來做運算的次數。對應第 14 行的end。 --- ```python=11 y_cap = bm*flipud(x(xStart+1:xStart+P)); e = y(xStart+P)-y_cap; bm = bm + 2*u*e .*flipud(x(xStart+1:xStart+P))'; ``` 基本上就是把方程式寫成程式碼。 >方程式 >$\mathrm{\hat{y}[n] = b_{0}x[n]+b_{1}x[n-1]+...+b_{P-1}x[n-(p-1)]\\ >e[n]=y[n]-\hat{y}[n]\\ >b_m=b_m+2×u×e[n]×x[n-m]}$ * 第 11 行:這裡的 \* 不是一般的乘法,而是做矩陣的乘法。參考下面。 >bm = >  [b~0~ b~1~ ... b~P-2~ b~P-1~] >x = >  x[1] >  x[2] >  $~~\vdots$ >  x[n - 1] >  x[n] >bm * x = >  b~0~x[1] + b~1~x[2] + ... + b~P-2~x[n-1] + b~P-1~x[n] >bm * flipud(x) = >  b~0~x[n] + b~1~x[n-1] + ... + b~P-2~x[2] + b~P-1~x[1] * 第 12 行:照方程式的打。 * 第 13 行:照方程式的打,最後面 分號(**;**) 前有一個 單引號(**'**), 單引號(**'**)可以把這矩陣做矩陣轉置。做這行的目的是為了讓bm後面那串(u * e.\*flipud(x(xStart+1:xStart+P)))的陣列型態和bm相同,這樣才可以做矩陣的加法。 --- ```python=14 end plot(bm) pause(0.00001) end ``` * 第 14 行:對應第 10 行的for * 第 15~16 行:把每次做完就把bm plot出來看結果,pause是暫停時間,讓程式有時間把圖畫出來。 * 第 17 行:對應第 9 行的for ## 結果 約跑6分鐘後,在大約1200及4800有明顯的值。 ![](https://i.imgur.com/4ejCNyJ.png) # 4.偵測頻率orDTMF訊號(內含混音雜訊) ## 偵測頻率 ### 程式碼 ```python= clear; clc; f1 = 3e3; f2 = 5e3; fs = 20e3; t = 0:1/fs:0.1; N = 2^10 f=(1:N)/N*fs; x = cos(2*pi*f1*t)+cos(2*pi*f2*t); y = fft(x,N); plot(f,abs(y)); axis([0 10000 200 550]); ``` >*註解* >fft(x,N):快速傅立葉轉換,可以取出此x的頻率,N是取樣點,通常設成2的指數,但不能超過x的點數(**出來的值是複數**)。 >abs():取絕對值,在複數上是取大小,例 :a = 3+4j,abs(a)=5;b = -1,abs(b) = 1。 >第 9 行:f=(1:N)/N\*fs,是讓1到N的刻度變成1到fs的刻度。 >這題如果沒有打第 14 行也可以,會看到4個地方有值,如下圖,但後面兩個是不對的(老師說的但是忘記是為什麼了XD),只要看前面兩根的頻率就好了。 >![](https://i.imgur.com/CoW9Ey1.png) ### 結果 ![](https://i.imgur.com/UWAsfiC.png) ## DTMF >**雙音多頻信號**(**D**ual-**T**one **M**ulti-**F**requency, **DTMF**),電話系統中電話機與交換機之間的一種用戶信令,通常用於發送被叫號碼。 > >在使用雙音多頻信號之前,電話系統中使用一連串的斷續脈衝來傳送被叫號碼,稱為脈衝撥號。脈衝撥號需要電信局中的操作員手工完成長途接續。---[維基百科](https://zh.wikipedia.org/wiki/%E5%8F%8C%E9%9F%B3%E5%A4%9A%E9%A2%91 "雙音多頻 - 維基百科,自由的百科全書") ### DTMF.mat中Tone內容 ![](https://i.imgur.com/Vzc9nrq.png) 題目:~~總時間10秒~~,取樣頻率(Fs)=8kHZ,共有10個號碼,每個號碼持續0.5秒並間隔0.5秒。 >刪除線處說明:這裡應該是不會給總時間,但可以自己算出來,總時間的算法是總點數÷取樣頻率(Fs)[name=黃英睿][time=Sun, Jan 8, 2017 10:00 PM] 解法: 1. 找出總點數:~~10(總時間(秒))\*8k(每秒取8k點)=80k(80,000)點~~ 載入DTMF.mat後看裡面Tone的大小。 2. 每個號碼持續0.5秒並間隔0.5秒,所以每個號碼有 0.5(持續時間)\*8K(取樣頻率) = 4000個點,每次只要取4000點出來做FFT分析出頻率。 ### 程式碼 ```python= clear; clc; load('DTMF.mat'); fs = 8e3; N = 2^11; for a =0:9 f = (1:N)/N*fs; T=Tone(fs*a+1:fs*a+4001); y = fft(T,N); ny = abs(y); subplot(5,2,a+1); plot(f,ny); axis([500 2000 0 1500]); end ``` >*註解* >axis([Xmin Xmax Ymin Ymax]),設定plot中xy軸的顯示範圍。 ### 結果 ![](https://i.imgur.com/efZN4gY.png) 對照下表得出:0277387411 ### DTMF表 |\\|1209HZ|1336HZ|1447HZ|1633Hz| |:--:|:--:|:--:|:--:|:--:|:--:| |**697HZ**|1|2|3|A| |**770HZ**|4|5|6|B| |**852HZ**|7|8|9|C| |**941HZ**|\*|0|#|D| # 5.設計濾波器(低通、高通、帶通、帶斥),包含脈衝響應(h)與頻率響應(H) **題目:** 以20K作為取樣頻率(Fs)設計出以下四個Filter 1. 截止頻率(Fc)為**3k**的**Low-Pass Filter** 2. 截止頻率(Fc)為**5k**的**High-Pass Filter** 3. 截止頻率(Fc)範圍為**3k~5k**的**Band-Pass Filter** 4. 截止頻率(Fc)範圍為**3k~5k**的**Band-Rejection Filter** ## Filter * Low-Pass Filter:$h_{lp}[n] = \frac{\Omega_{c}}{\pi}sinc(\frac{\Omega_{c}}{\pi}(n-L))$ * High-Pass Filter:$h_{hp}[n] = \delta[n-L] - \frac{\Omega_{c}}{\pi}sinc(\frac{\Omega_{c}}{\pi}(n-L))$ * Band-Pass Filter:$h_{bp}[n] = \frac{\Omega_{c1}}{\pi}sinc(\frac{\Omega_{c1}}{\pi}(n-L)) *(\delta[n-L] - \frac{\Omega_{c2}}{\pi}sinc(\frac{\Omega_{c2}}{\pi}(n-L)))$ * Band-Rejection Filter:$h_{br}[n] = \delta[n-L] - (\frac{\Omega_{c1}}{\pi}sinc(\frac{\Omega_{c1}}{\pi}(n-L)) *(\delta[n-L] - \frac{\Omega_{c2}}{\pi}sinc(\frac{\Omega_{c2}}{\pi}(n-L)))$ ## Other Windowing Effect >在信號處理中,Window function(窗口函數)是一個數學函數是零值的一些選擇的外面間隔。例如,一個功能是時間間隔內常數和零別處被稱為矩形窗口,其描述了它的圖形表示的形狀。當另一個函數或波形/數據序列乘以窗口函數時,乘積也在間隔之外為零值:剩下的是它們重疊的部分,即“通過窗口查看”。 > >在典型的應用中,所使用的窗口函數是非負的平滑的“鐘形”曲線。矩形,也可以使用三角形,以及其它功能。窗口函數的更一般的定義,不要求它們是相同的零的時間間隔以外,只要在窗口乘以其參數的乘積為平方可積,並且,更具體地,該功能是為足夠迅速趨向零。---[維基百科](https://en.wikipedia.org/wiki/Window_function "Window function - Wikipedia") > Hanning:$w(k) = 0.5 - 0.5cos(2\pi\frac{k}{N})$,for k=0,...,N-1 Hamming:$w(k) = 0.54 - 0.46cos(2\pi\frac{k}{N})$,for k=0,...,N-1 Blackman:$w(k) = 0.42 - 0.5cos(2\pi\frac{k-1}{N})+0.08cos(4\pi\frac{k-1}{N})$,for k=0,...,N-1 ### 程式碼 ```python= clear; clc; Fs=20e3; OmegaC1 = pi/((Fs/2)/3e3); %3K OmegaC2 = pi/2; %5K L = 20; n = 0:2*L; N1 = 2*L+1; k1 = 0:N1-1; N2 = 4*L+1; k2 = 0:N2-1; Hanning1 = 0.5 - 0.5*cos(2*pi*k1/N1); Hanning2 = 0.5 - 0.5*cos(2*pi*k2/N2); dat = zeros(1,2*L+1); dat(L+1) = 1; dat2 = zeros(1,4*L+1); dat2(2*L+1) = 1; h_lp = (OmegaC1/pi*sinc(OmegaC1/pi*(n-L))); h_hp = dat - (OmegaC2/pi*sinc(OmegaC2/pi*(n-L))); h_bp = conv((OmegaC2/pi*sinc(OmegaC2/pi*(n-L))),dat - (OmegaC1/pi*sinc(OmegaC1/pi*(n-L)))); h_br = dat2 - h_bp; [Hlp,w]=freqz(h_lp .* Hanning1); wf = w/pi*Fs/2; subplot(2,2,1) plot(wf,abs(Hlp)); title('低通,Ωc=3K'); [Hhp,w]=freqz(h_hp .* Hanning1); wf = w/pi*Fs/2; subplot(2,2,2) plot(wf,abs(Hhp)); title('高通,Ωc=5K'); [Hbp,w]=freqz(h_bp .* Hanning2); wf = w/pi*Fs/2; subplot(2,2,3) plot(wf,abs(Hbp)); title('帶通,Ωc1=3K、Ωc2=5K'); [Hbr,w]=freqz(h_br .* Hanning2); wf = w/pi*Fs/2; subplot(2,2,4) plot(wf,abs(Hbr)); title('帶斥,Ωc1=3K、Ωc2=5K'); ``` >*註解* >~~截止頻率(fh)的算法(假設截止頻率是5k、取樣頻率為20K): $OmegaC = \frac{\pi}{\frac{f_{sh}}{f_{h}}} = \frac{\pi}{\frac{10kHZ}{5kHZ}} = \frac{\pi}{2}$~~ >上面的方程式打錯了,雖然答案會一樣,但是以下才是正確的寫法(來源:老師的PPT)[name=黃英睿][time=Sun, Jan 8, 2017 8:45 PM] >$\Omega$c的算法:fc(截止頻率,假設5k)、fs(取樣頻率,假設20k) >$OmegaC = fc\frac{2\pi}{fs} = 5k\frac{2\pi}{20k} = \frac{\pi}{2}$ > ```python=7 OmegaC2 = pi/2; ``` >顯示頻率,取樣頻率的一半:$f_{sh} = \frac{fs}{2}$ >>[H,w]=freqz(h),計算**h**(脈衝響應)的**H**(頻率響應,為複數)和**W**(角頻率,值為0~$\pi$)[color=#ff0000] ### 結果脈衝響應圖(H)(沒有使用Windowing Effect) ![](https://i.imgur.com/FDp47VD.png) ### 結果脈衝響應圖(H)(使用Hanning、Hamming和Blackman) ![](https://i.imgur.com/LsoXQho.png)