diff --git a/chanvocoder.m b/chanvocoder.m new file mode 100644 index 0000000..88a5cfa --- /dev/null +++ b/chanvocoder.m @@ -0,0 +1,66 @@ +function y = chanvocoder(carrier, modul, chan, numband, overlap) +% y = chanvocoder(carrier, modul, chan, numband, overlap) +% The Channel Vocoder modulates the carrier signal with the modulation signal +% chan = number of channels (e.g., 512) +% numband = number of bands (chan + error('# bands must be < # channels') +end + +[rc, cc] = size(carrier); +if cc>rc + carrier = carrier'; +end + +[rm, cm] = size(modul); +if cm>rm + modul = modul'; +end + +st = min(rc,cc); % stereo or mono? +if st~= min(rm,cm) + error('carrier and modulator must have same number of tracks'); +end + +len = min(length(carrier),length(modul)); % find shortest length +carrier = carrier(1:len,1:st); % shorten carrier if needed +modul = modul(1:len,1:st); % shorten modulator if needed +L = 2*chan; % window length/FFT length +w = hanning(L); +if st==2 + w=[w w]; +end % window/ stereo window + +bands = 1:round(chan/numband):chan; % indices for frequency bands +bands(end) = chan; +y = zeros(len,st); % output vector + +ii = 0; +while ii*L*overlap+L <= len + ind = round([1+ii*L*overlap:ii*L*overlap+L]); + FFTmod = fft( modul(ind,:) .* w ); % window & take FFT of modulator + FFTcar = fft( carrier(ind,:) .* w ); % window & take FFT of carrier + syn = zeros(chan,st); % place for synthesized output + for jj = 1:numband-1 % for each frequency band + b = [bands(jj):bands(jj+1)-1]; % current band + syn(b,:) = FFTcar(b,:)*diag(mean(abs(FFTmod(b,:)))); + end % take product of spectra + midval = FFTmod(1+L/2,:).*FFTcar(1+L/2,:); % midpoint is special + synfull = [syn; midval; flipud( conj( syn(2:end,:) ) );]; % + and - frequencies + timsig = real( ifft(synfull) ); % invert back to time + y(ind,:) = y(ind,:) + timsig; % add back into time waveform + ii = ii+1; +end +y = 0.8*y/max(max(abs(y))); % normalize output + +figure; +set(gcf, 'name','a vs b'); +title('a vs b'); +plot(t_downsample,y_downsampled,'b'); +hold on; +plot(t_decimate,y_decimated,'g'); +xlabel('time(s)'); +ylabel('amplitude(n.u)'); +legend('o','i',"location","southeastoutside"); diff --git a/chanvocoder2.m b/chanvocoder2.m new file mode 100644 index 0000000..8b22e02 --- /dev/null +++ b/chanvocoder2.m @@ -0,0 +1,83 @@ + +function [y, modul, carrier, output] = chanvocoder(carrier, modul, chan, numband, overlap) +% y = chanvocoder(carrier, modul, chan, numband, overlap) +% The Channel Vocoder modulates the carrier signal with the modulation signal +% chan = number of channels (e.g., 512) +% numband = number of bands (chan + error('# bands must be < # channels') +end + +[rc, cc] = size(carrier); +if cc>rc + carrier = carrier'; +end + +[rm, cm] = size(modul); +if cm>rm + modul = modul'; +end + +st = min(rc,cc); % stereo or mono? +if st~= min(rm,cm) + error('carrier and modulator must have the same number of tracks'); +end + +len = min(length(carrier),length(modul)); % find shortest length +carrier = carrier(1:len,1:st); % shorten carrier if needed +modul = modul(1:len,1:st); % shorten modulator if needed +L = 2*chan; % window length/FFT length +w = hanning(L); +if st==2 + w=[w w]; +end % window/ stereo window + +bands = 1:round(chan/numband):chan; % indices for frequency bands +bands(end) = chan; +y = zeros(len,st); % output vector +modul_out = zeros(len,st); % modulator signal for output +carrier_out= zeros(len,st); % carrier signal for output + +ii = 0; +while ii*L*overlap+L <= len + ind = round([1+ii*L*overlap:ii*L*overlap+L]); + FFTmod = fft( modul(ind,:) .* w ); % window & take FFT of modulator + FFTcar = fft( carrier(ind,:) .* w ); % window & take FFT of carrier + syn = zeros(chan,st); % place for synthesized output + for jj = 1:numband-1 % for each frequency band + b = [bands(jj):bands(jj+1)-1]; % current band + syn(b,:) = FFTcar(b,:)*diag(mean(abs(FFTmod(b,:)))); + end % take product of spectra + midval = FFTmod(1+L/2,:).*FFTcar(1+L/2,:); % midpoint is special + synfull = [syn; midval; flipud( conj( syn(2:end,:) ) );]; % + and - frequencies + timsig = real( ifft(synfull) ); % invert back to time + y(ind,:) = y(ind,:) + timsig; % add back into time waveform + modul_out(ind,:) = modul(ind,:); % save modulator signal for output + carrier_out(ind,:) = carrier(ind,:); % save carrier signal for output + ii = ii+1; +end +y = 0.8*y/max(max(abs(y))); % normalize output + +% Plotting +t = (0:len-1) / st; % time vector + +% Plot modulator, carrier, and output signals +subplot(3,1,1); +plot(t, modul_out); +title('Modulator Signal'); +xlabel('Time (s)'); +ylabel('Amplitude'); + +subplot(3,1,2); +plot(t, carrier_out); +title('Carrier Signal'); +xlabel('Time (s)'); +ylabel('Amplitude'); + +subplot(3,1,3); +plot(t, y); +title('Output Signal'); +xlabel('Time (s)'); +ylabel('Amplitude'); diff --git a/data/carrier22.wav b/data/carrier22.wav new file mode 100644 index 0000000..8b2526c Binary files /dev/null and b/data/carrier22.wav differ diff --git a/data/modulator22_chanvocoder.wav b/data/modulator22_chanvocoder.wav new file mode 100644 index 0000000..fd619ff Binary files /dev/null and b/data/modulator22_chanvocoder.wav differ diff --git a/main.m b/main.m new file mode 100644 index 0000000..4cd56ba --- /dev/null +++ b/main.m @@ -0,0 +1 @@ +modfile='./data/modulator22.wav'; carfile='./data/carrier22.wav'; outfile='./data/vocodedsound.wav'; [modul, sr1]=audioread(modfile); [carrier, sr2]=audioread(carfile); if sr1~=sr2, disp('your sampling rates dont match'); end y= chanvocoder2(carrier, modul, 512, 16, .2) srl=sr1; audiowrite('./data/modulator22_chanvocoder.wav', y , sr1); spectrogram(y,srl,5,30); spectrogram(y,srl,5,5); \ No newline at end of file diff --git a/spectrogram.m b/spectrogram.m index 2e578ac..08834bc 100644 --- a/spectrogram.m +++ b/spectrogram.m @@ -8,7 +8,7 @@ function spectrogram(signal, samplingFreq, step_size, window_size) % Inputs: % -signal: temporal signal to analyse % -samplingFreq: sampling frequency of the temporal signal -% -step_size: how often the power spectrum will be computed in ms +% -step_size: how often the power spectrum will be computed in ms % -window_size: size of the analysing window in ms % % Ouput: None diff --git a/speech_analysis.m b/speech_analysis.m index 6d3f300..b03e00a 100644 --- a/speech_analysis.m +++ b/speech_analysis.m @@ -35,8 +35,8 @@ t_speedown=0:1/fs_speedown:length(y_speedown)/fs_speedown-1/fs_speedown; %frequencySpectrum(y_speedown, fs_speedown, true); %Illustrate the spectogram of the speed down version at 2 windows values (1 for a precise frequency read and 1 for a precise time domain) -%spectrogram(y_speedown, fs_speedown, 5, 30); -%spectrogram(y_speedown, fs_speedown, 5, 5); +spectrogram(y_speedown, fs_speedown, 5, 30); +spectrogram(y_speedown, fs_speedown, 5, 5); %Lowering the sampling frequency using the downsample() function ##y_downsampled = downsample(y, 2);