├── IIR_Filter ├── 400Hz_bandpass.fda ├── Makefile ├── README.md ├── coefs.h ├── filter.c ├── filter.h ├── in.wav ├── main.c └── out.wav ├── Magnitude_Estimate ├── README.md ├── magnitude_estimate.cpp └── main.cpp ├── README.md └── envlop.m /IIR_Filter/400Hz_bandpass.fda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wonwinnn/signal-processing/d43381d6506a724df5cde5899a4d22f14cba3f80/IIR_Filter/400Hz_bandpass.fda -------------------------------------------------------------------------------- /IIR_Filter/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = filter 2 | 3 | HEADERS = $(wildcard *.h) 4 | SRC = $(wildcard *.c) 5 | OBJS = $(SRC:.c=.o) 6 | 7 | CC = gcc 8 | #CFLAGS = -Wall -std=gnu99 9 | 10 | #can be deleted, .c can be translated to .o automatically 11 | #use this to "@echo" 12 | %.o:%.c 13 | @$(CC) -g -o $@ -c $< 14 | 15 | $(TARGET) : $(OBJS) 16 | @$(CC) -g -o $@ $^ 17 | 18 | $(OBJS) : $(HEADERS) 19 | 20 | .PHONY : clean 21 | clean : 22 | rm $(TARGET) $(OBJS) 23 | 24 | -------------------------------------------------------------------------------- /IIR_Filter/README.md: -------------------------------------------------------------------------------- 1 | ## An IIR filter designed with MATLAB and implemented in C 2 | 3 | The transfer function of a biquad filter can be written as: H(z)=(b₀+b₁z⁻¹+b₂z⁻²)/(a₀+a₁z⁻¹+a₂z⁻²). 4 | 5 | Use Filter Designer in MATLAB to design a 400 Hz bandpass IIR filter: 6 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190601212647210.png) 7 | 8 | Analysis->Filter Coeffients : 9 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190601213027484.png) 10 | Numerator,from top to bottom: b₀,b₁ and b₂. 11 | Denominator, from top to bottom: a₀,a₁ and a₂,a₀ is always 1. 12 | 13 | Use arrays to store filter coeffients: 14 | ```c 15 | //8-order IIR filter with 4 sections 16 | const int sections = 4; 17 | 18 | //nominator 19 | const float b[4][3] = { 20 | { 1, -1.984454421, 1 }, 21 | { 1, -1.999405318, 1 }, 22 | { 1, -1.993167556, 1 }, 23 | { 1, -1.998644244, 1 } 24 | }; 25 | 26 | //denominator 27 | const float a[4][3] = { 28 | { 1, -1.984532740, 0.9884094716 }, 29 | { 1, -1.988571923, 0.9909378613 }, 30 | { 1, -1.991214225, 0.9962624248 }, 31 | { 1, -1.995917854, 0.9977478940 } 32 | }; 33 | 34 | const float gain[4] = { 0.583805364, 0.583805364, 0.170388576, 0.170388576 }; 35 | ``` 36 | 37 | Store filter states: 38 | ```c 39 | float w[sections][2]; //filter states 40 | ``` 41 | 42 | Initialize filter: 43 | ```c 44 | for (int i = 0; i < sections; i++) { 45 | w[i][0] = 0; //w[n-1] 46 | w[i][1] = 0; //w[n-2] 47 | } 48 | ``` 49 | 50 | Calculate filter output: 51 | ```c 52 | y[0] = pcmIn[i]; 53 | for (j = 0; j < sections; j++) { 54 | tmp[j] = y[j] - a[j][1] * w[j][0] - a[j][2] * w[j][1]; //calculate w[n] 55 | y[j+1] = tmp[j] + b[j][1] * w[j][0] + b[j][2] * w[j][1]; //calculate the j-th section filter output y[n] 56 | w[j][1] = w[j][0]; //move w[n-1] -> w[n-2] 57 | w[j][0] = tmp[j]; //move w[n] -> w[n-1] 58 | y[j+1] = gain[j] * y[j+1]; //multiply with gain 59 | } 60 | 61 | out = y[j]; 62 | ``` 63 | -------------------------------------------------------------------------------- /IIR_Filter/coefs.h: -------------------------------------------------------------------------------- 1 | #ifndef _COEFS_H 2 | #define _COEFS_H 3 | 4 | //8-order IIR filter with 4 sections 5 | const int sections = 4; 6 | 7 | //nominator 8 | const float b[4][3] = { 9 | { 1, -1.984454421, 1 }, 10 | { 1, -1.999405318, 1 }, 11 | { 1, -1.993167556, 1 }, 12 | { 1, -1.998644244, 1 } 13 | }; 14 | 15 | //denominator 16 | const float a[4][3] = { 17 | { 1, -1.984532740, 0.9884094716 }, 18 | { 1, -1.988571923, 0.9909378613 }, 19 | { 1, -1.991214225, 0.9962624248 }, 20 | { 1, -1.995917854, 0.9977478940 } 21 | }; 22 | 23 | const float gain[4] = { 0.583805364, 0.583805364, 0.170388576, 0.170388576 }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /IIR_Filter/filter.c: -------------------------------------------------------------------------------- 1 | #include "coefs.h" 2 | #include "filter.h" 3 | 4 | void filter_reset(float w[][2]) 5 | { 6 | for (int i = 0; i < sections; i++) { 7 | w[i][0] = 0; 8 | w[i][1] = 0; 9 | } 10 | } 11 | 12 | void filter(short* pcmIn, short* pcmOut, float w[][2], int sample_size) 13 | { 14 | float y[sections+1], tmp[sections], out; 15 | int i,j; 16 | 17 | for (i = 0; i < sample_size; i++) { 18 | y[0] = pcmIn[i]; 19 | for (j = 0; j < sections; j++) { 20 | tmp[j] = y[j] - a[j][1] * w[j][0] - a[j][2] * w[j][1]; //calculate w[n] 21 | y[j+1] = tmp[j] + b[j][1] * w[j][0] + b[j][2] * w[j][1]; //calculate the j-th section filter output y[n] 22 | w[j][1] = w[j][0]; //move w[n-1] -> w[n-2] 23 | w[j][0] = tmp[j]; //move w[n] -> w[n-1] 24 | y[j+1] = gain[j] * y[j+1]; //multiply with gain 25 | } 26 | 27 | out = y[j]; 28 | 29 | if (out > 32767) 30 | out = 32767; 31 | 32 | if (out < -32768) 33 | out = -32768; 34 | 35 | pcmOut[i] = (short)(out); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /IIR_Filter/filter.h: -------------------------------------------------------------------------------- 1 | #ifndef _FILTER_H 2 | #define _FILTER_H 3 | 4 | //WAVE PCM soundfile format 5 | typedef struct 6 | { 7 | char chunk_id[4]; 8 | int chunk_size; 9 | char format[4]; 10 | char subchunk1_id[4]; 11 | int subchunk1_size; 12 | short int audio_format; 13 | short int num_channels; 14 | int sample_rate; //sample_rate denotes the sampling rate. 15 | int byte_rate; 16 | short int block_align; 17 | short int bits_per_sample; 18 | char subchunk2_id[4]; 19 | int subchunk2_size; //subchunk2_size denotes the number of samples. 20 | } wav_header; 21 | 22 | void filter_reset(float w[][2]); 23 | void filter(short* pcmIn, short* pcmOut, float w[][2], int sample_size); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /IIR_Filter/in.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wonwinnn/signal-processing/d43381d6506a724df5cde5899a4d22f14cba3f80/IIR_Filter/in.wav -------------------------------------------------------------------------------- /IIR_Filter/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "filter.h" 3 | 4 | #define WSIZE 512 5 | 6 | short bufferIn[WSIZE] = {0}; 7 | short bufferOut[WSIZE] = {0}; 8 | 9 | int main() 10 | { 11 | FILE * fp_in, *fp_out; 12 | int i = 0, nb; 13 | wav_header wav_header_buf; 14 | 15 | float w[sections][2]; //filter states 16 | 17 | fp_in = fopen("in.wav", "rb"); 18 | fp_out = fopen("out.wav", "wb"); 19 | 20 | fread(&wav_header_buf, 1, sizeof(wav_header), fp_in); 21 | fwrite(&wav_header_buf,1, sizeof(wav_header), fp_out); 22 | 23 | while (!feof(fp_in)) { 24 | 25 | nb = fread(bufferIn, 2, WSIZE, fp_in); 26 | 27 | filter_reset(w); 28 | filter(bufferIn, bufferOut, w, WSIZE); 29 | 30 | fwrite(bufferOut, 2, nb, fp_out); //writing read data into output file 31 | } 32 | 33 | printf("completed\n"); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /IIR_Filter/out.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wonwinnn/signal-processing/d43381d6506a724df5cde5899a4d22f14cba3f80/IIR_Filter/out.wav -------------------------------------------------------------------------------- /Magnitude_Estimate/README.md: -------------------------------------------------------------------------------- 1 | ## DSP Trick: Magnitude Estimation 2 | Alpha-max-plus-beta-min algorithm 3 | References: 4 | [1] Lyons, Richard G.. “Understanding Digital Signal Processing (2nd Edition).” (2004). 5 | [2] Smyk, Robert and Maciej Czyzak. “Improved magnitude estimation of complex numbers using alpha max and beta min algorithm.” (2016). 6 | -------------------------------------------------------------------------------- /Magnitude_Estimate/magnitude_estimate.cpp: -------------------------------------------------------------------------------- 1 | /**************** 2 | Alpha-max-plus-beta-min algorithm with 3 regions 3 | 4 | [0, π/12) α= 0.9957, β= 0.1311 5 | [π/12,π/6) α= 0.9278, β= 0.3843 6 | [π/6,π/4] α= 0.7968, β= 0.6114 7 | ****************/ 8 | 9 | #define BITS 15 10 | #define TAN1 8780 11 | #define TAN2 18919 12 | #define ALPHA1 32627 13 | #define BETA1 4296 14 | #define ALPHA2 30402 15 | #define BETA2 12593 16 | #define ALPHA3 26110 17 | #define BETA3 20034 18 | 19 | unsigned int magnitudeEstimateS16(short x, short y) 20 | { 21 | unsigned int mag; 22 | 23 | if (x < 0) 24 | x = -x; 25 | if (y < 0) 26 | y = -y; 27 | if (x < y) { 28 | short t = x; 29 | x = y; 30 | y = t; 31 | } 32 | 33 | if (x * TAN1 > (y << BITS)) 34 | mag = (x * ALPHA1 + y * BETA1) >> BITS; 35 | else if (x * TAN2 > (y << BITS)) 36 | mag = (x * ALPHA2 + y * BETA2) >> BITS; 37 | else 38 | mag = (x * ALPHA3 + y * BETA3) >> BITS; 39 | 40 | return mag; 41 | } 42 | -------------------------------------------------------------------------------- /Magnitude_Estimate/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern unsigned int magnitudeEstimateS16(short x, short y); 5 | 6 | int main() 7 | { 8 | for (short x = -10000; x < 10000; x += 2550) { 9 | for (short y = -10000; y < 10000; y += 2550) { 10 | unsigned int magRef = std::sqrt(x * x + y * y); 11 | unsigned int magEst = magnitudeEstimateS16(x, y); 12 | int err = magRef - magEst; 13 | double rel = double(err) / double(magRef); 14 | std::cout << x << " " << y << " " << magRef << " " 15 | << magEst << " " << err << " " << rel << std::endl; 16 | } 17 | } 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Signal Processing 2 | -------------------------------------------------------------------------------- /envlop.m: -------------------------------------------------------------------------------- 1 | function envlop(s, n) 2 | 3 | signal = s; 4 | w = hamming(length(signal)); 5 | winsignal = w.*signal; 6 | sspec = fft(winsignal); 7 | logsspec = log(abs(sspec)); 8 | rcep = real(ifft(logsspec)); 9 | wzp = [ones(n,1);zeros(length(rcep)-2*n,1);ones(n,1)]; 10 | %wzp = ones(length(rcep),1); 11 | wrcep = wzp.*rcep; 12 | rcepenv = real(fft(wrcep)); 13 | rcepenv2 = ifft(wrcep); 14 | nrcepenv = rcepenv-mean(rcepenv); 15 | nrcepenv2 = rcepenv2-mean(rcepenv2); 16 | plot(nrcepenv); 17 | hold on; 18 | plot(nrcepenv2, 'r'); 19 | hold on; 20 | plot(logsspec, 'g'); 21 | --------------------------------------------------------------------------------