My group is developing a simple MATLAB Graphical User Interface (GUI) that is supposed to record audio from a microphone - plugged in or built in to the computer - and play back the signal. So far we have that completed. Our GUI also can load a sample (a .wav file, etc..) and play it back using the same "Play" pushbutton on the GUI. We have a Play, Record, Load, and Save push button. Now for the pitch-shifting of loaded or recorded samples... We know we need a peak-picking algorithm to find the fundamental frequencies of the signals. We were then thinking that we could multiply each of those values by a constant to shift the pitch of all those frequencies. What we aim to do it use this algorithm and assign the separate shifts to different Pushbuttons or radiobuttons, in which we can load our sample, press the button and manipulate the pitch by doing so, then play it back. Will using a peak-picking algorithm sufficiently shift the pitch of our signals, or will the signal be screwed up during playback?
(THIS IS NOT REAL-TIME PROCESSING)
As mentioned in my comments above, there are really two approaches you can use, Phase Vocoders or higher sampling rates. The first method, using a vocoder will maintain signal length while shifting the contained frequencies higher. I am not going to go through the algorithm on how to do this, but code is openly available for this from Columbia University - http://www.ee.columbia.edu/ln/labrosa/matlab/pvoc/
The second method is simply writing the *.wav file to a higher sampling rate.
say you have a 440 Hz signal you want to be 880 Hz, simply double the sampling rate.
so instead of say wavwrite(signal,fs,'file')
, use wavwrite(signal,2*fs,'file')
This however, will shorten the length of the audio file by whatever factor you increased the sampling rate.
Overall I think the better and more impressive method is the vocoder, I would not recommend just blindly using the code from Columbia, but actually taking time to understand it and being able to explain the logic behind it all mathematically
Something a bit simpler than the Columbia algorithm (not as high performing, but maybe gives you an appreciation of how it works) would go something like this:
- Take the FFT
- Use
interp1
to re-sample the FFT at a higher sample rate; for example, to shift up by 1 full note (2 half notes), you could do
F1 = fft(originalSignal);
N = numel(F1);
F1a = F1(1:N/2); % the lower half of the fft
F1b = F1(end:-1:N/2+1); % the upper half of the fft - flipped "the right way around"
t1 = 1:N/2; % indices of the lower half
t2 = 1+ (t1-1) / (1 + 2.^(2/12)); % finer sampling... will make peaks appear higher
F2a = interp1(t1, F1a, t2); % perform sampling of lower half
F2b = interp1(t1, F1b, t2); % resample upper half
F2 = [F2a F2b(end:-1:1)]; % put the two together again
shiftedSignal = ifft(F2); % and do the inverse FFT
I did not do any windowing etc, so this is "approximate". In reality you want to process little overlapping chunks of data one at a time, rather than the entire file at once. So the above should be considered really "for illustration only", and not working code.
A strong characteristic of a Pitch Shift is change the pitch without change the speed of the sound, if you change the sample rate your speed is changed and you will need resample your signal.
If your input from microphone is always monophonic, you should consider the PSOLA method, works in time-domain and you can get nice results in voice signals
来源:https://stackoverflow.com/questions/20076218/matlab-pitch-shifting-an-audio-signal