|
34 | 34 | % http://zafarrafii.com
|
35 | 35 | % https://github.com/zafarrafii
|
36 | 36 | % https://www.linkedin.com/in/zafarrafii/
|
37 |
| - % 01/21/21 |
| 37 | + % 01/22/21 |
38 | 38 |
|
39 | 39 | % Define the properties
|
40 | 40 | properties (Access = private, Constant = true)
|
|
92 | 92 | % Get the number of samples and channels in the audio signal
|
93 | 93 | [number_samples,number_channels] = size(audio_signal);
|
94 | 94 |
|
95 |
| - % Window length, window function, and step length for the STFT |
96 |
| - window_length = repet.windowlength(sampling_frequency); |
97 |
| - window_function = repet.windowfunction(window_length); |
98 |
| - step_length = repet.steplength(window_length); |
| 95 | + % Set the parameters for the STFT |
| 96 | + % (audio stationary around 40 ms, power of 2 for fast FFT and constant overlap-add (COLA), |
| 97 | + % periodic Hamming window for COLA, and step equal to half the window length for COLA) |
| 98 | + window_length = 2^nextpow2(0.04*sampling_frequency); |
| 99 | + window_function = hamming(window_length,'periodic'); |
| 100 | + step_length = window_length/2; |
99 | 101 |
|
100 |
| - % Number of time frames |
101 |
| - number_times = ceil((window_length-step_length+number_samples)/step_length); |
| 102 | + % Derive the number of time frames |
| 103 | + number_times = ceil(((number_samples+2*floor(window_length/2))-window_length) ... |
| 104 | + /step_length)+1; |
102 | 105 |
|
103 | 106 | % Initialize the STFT
|
104 | 107 | audio_stft = zeros(window_length,number_times,number_channels);
|
105 | 108 |
|
106 | 109 | % Loop over the channels
|
107 |
| - for channel_index = 1:number_channels |
| 110 | + for i = 1:number_channels |
108 | 111 |
|
109 |
| - % STFT of the current channel |
110 |
| - audio_stft(:,:,channel_index) ... |
111 |
| - = repet.stft(audio_signal(:,channel_index),window_function,step_length); |
| 112 | + % Compute the STFT of the current channel |
| 113 | + audio_stft(:,:,i) = repet.stft(audio_signal(:,i),window_function,step_length); |
112 | 114 |
|
113 | 115 | end
|
114 | 116 |
|
115 |
| - % Magnitude spectrogram (with DC component and without mirrored |
116 |
| - % frequencies) |
| 117 | + % Derive the magnitude spectrogram |
| 118 | + % (with the DC component and without the mirrored frequencies) |
117 | 119 | audio_spectrogram = abs(audio_stft(1:window_length/2+1,:,:));
|
118 | 120 |
|
119 |
| - % Beat spectrum of the spectrograms averaged over the channels |
120 |
| - % (squared to emphasize peaks of periodicitiy) |
| 121 | + % Compute the beat spectrum of the spectrograms averaged over |
| 122 | + % the channels (take the square to emphasize periodicity peaks) |
121 | 123 | beat_spectrum = repet.beatspectrum(mean(audio_spectrogram,3).^2);
|
122 | 124 |
|
123 |
| - % Period range in time frames for the beat spectrum |
| 125 | + % Get the period range in time frames for the beat spectrum |
124 | 126 | period_range = round(repet.period_range*sampling_frequency/step_length);
|
125 | 127 |
|
126 | 128 | % Repeating period in time frames given the period range
|
127 | 129 | repeating_period = repet.periods(beat_spectrum,period_range);
|
128 | 130 |
|
129 |
| - % Cutoff frequency in frequency channels for the dual high-pass |
130 |
| - % filtering of the foreground |
| 131 | + % Get the cutoff frequency in frequency channels for the dual |
| 132 | + % high-pass filtering of the foreground |
131 | 133 | cutoff_frequency = ceil(repet.cutoff_frequency*(window_length-1)/sampling_frequency);
|
132 | 134 |
|
133 | 135 | % Initialize the background signal
|
|
136 | 138 | % Loop over the channels
|
137 | 139 | for channel_index = 1:number_channels
|
138 | 140 |
|
139 |
| - % Repeating mask for the current channel |
| 141 | + % Compute the repeating mask for the current channel given |
| 142 | + % the repeating period |
140 | 143 | repeating_mask = repet.mask(audio_spectrogram(:,:,channel_index),repeating_period);
|
141 | 144 |
|
142 |
| - % High-pass filtering of the dual foreground |
| 145 | + % Perform a high-pass filtering of the dual foreground |
143 | 146 | repeating_mask(2:cutoff_frequency+1,:) = 1;
|
144 | 147 |
|
145 |
| - % Mirror the frequency channels |
| 148 | + % Recover the mirrored frequencies |
146 | 149 | repeating_mask = cat(1,repeating_mask,repeating_mask(end-1:-1:2,:));
|
147 | 150 |
|
148 |
| - % Estimated repeating background for the current channel |
| 151 | + % Synthesize the repeating background for the current |
| 152 | + % channel |
149 | 153 | background_signal1 ...
|
150 | 154 | = repet.istft(repeating_mask.*audio_stft(:,:,channel_index),window_function,step_length);
|
151 | 155 |
|
|
0 commit comments