---
# System prepended metadata

title: 數位信號系統實習
tags: [matlab]

---

# 數位信號系統實習
###### 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)

