Changing frequency of .wav?

Hi,
I'm experimenting with changing the frequency of an imported .wav file. I've looked on the mathworks fora and haven't found a working solution. Someone pointed out (in 2005) that an easy solution of changing the frequency is to use Hilbert transformation. Well, i tried, the code worked, but the 'frequency shifting' didn't work as flawless as i'd hoped. What is want to achieve is to import for example an 'A-tone' of frequency 220 Hz and change the tone to 'C-note' of frequency 261.6 Hz. I used the FFT() function to get the frequency of the .wav file. I used a piano sound of frequency 440Hz and didn't succeed at changing the frequency of the audio vector. Does anyone know how to do this in a proper way? Any information relating to changing the frequency is much appreciated.
Thanks for the help!

 Accepted Answer

One way to do what I believe you want to do is to heterodyne your initial signal with the difference between it and the the new frequency. This is called ‘amplitude modulation’, and specifically here ‘double sideband suppressed carrier’ modulation. I then filter out the lower sideband to produce a ‘single-sideband suppressed carrier’ signal at the desired (upper sideband) frequency.
Don’t worry about the details. I’m simply explaining what my code does and how it works. My code requires the Signal Processing Toolbox to design and implement the filter.
The modulation technique multiplies two sinusoids of different frequencies together to produce sinusiods with the sum and difference of those frequencies. The mathmatical background is given in the Wikipedia entry on Product-to-sum and sum-to-product identities.
The code:
Fs = 4.41E4; % Sampling Frequency (Hz)
tmax = 5; % Time Duration Of Signal (sec)
t = linspace(0, tmax, tmax*Fs); % Time Vector
f = 220; % Original Frequency
s = sin(2*pi*f*t + cos(15*pi*t)*pi/2); % Original Signal
sound(s, Fs) % Listen To Original Signal
pause(tmax*2) % Wait For It To Finish
Fc = 261.6; % Desired Output Frequency
carrier = sin(2*pi*(Fc-f)*t); % Generate Carrier
sm = s .* carrier; % Modulate (Produces Upper & Lower Sidebands
Fn = Fs/2; % Design High-Pass Filter To Eliminate Lower Sideband
Wp = Fc/Fn;
Ws = Wp*0.8;
[n,Wn] = buttord(Wp, Ws, 1, 10);
[b,a] = butter(n,Wn,'high');
[sos,g] = tf2sos(b,a);
smf = 2*filtfilt(sos,g,sm); % Output Is Suppressed-Carrier Upper Sideband Signal
sound(smf, Fs) % Listen To New Signal
Fn1 = Fs/2; % Compute & Plot Fourier Series Of Both
Ft1 = fft(s)/length(s);
Fv1 = linspace(0, 1, fix(length(Ft1)/2)+1)*Fn1;
Ix1 = 1:length(Fv1);
Fn2 = Fs/2;
Ft2 = fft(smf)/length(smf);
Fv2 = linspace(0, 1, fix(length(Ft2)/2)+1)*Fn2;
Ix2 = 1:length(Fv2);
figure(1)
plot(Fv1, abs(Ft1(Ix1)))
grid
hold on
plot(Fv2, abs(Ft2(Ix2)))
hold off
axis([0 500 ylim])

2 Comments

J. Boog
J. Boog on 27 Sep 2015
Edited: J. Boog on 27 Sep 2015
Thanks for your reply. It works great if the sound has a known frequency. A .wav file however is a mix of various unknown sinuses and cosines. Is this method also possible with a .wav audio sample of for example a piano note? As in, if I know the note frequency of the piano sample, can I change the sample to a higher note frequency?
My pleasure.
‘Is this method also possible with a .wav audio sample of for example a piano note?’
Yes. I created my ‘original signal’ ‘s’ to be a mixture of frequencies (actually, a phase-modulated sine wave), so you can see it has a broad spectrum. If your piano note, with a fundamental frequency of 220 Hz, is substituted for ‘s’, you should hear essentially the same sound, but (in this example) centred around 261.6 Hz. All the harmonics (overtones) and other component frequencies will be heterodyned appropriately as well. That is what the fft plot of the original and shifted signals illustrates. The heterodyned (shifted) sound is simply a shifted version of the original ‘s’ signal.
You can shift (heterodyne) your 220 Hz piano note to essentially any frequency (an upper limit is the Nyquist frequency) by just setting an appropriate frequency for ‘Fc’. It will not sound exactly like the piano tone created by hitting middle ‘C’, because the physics of the strings for the two notes are not the same. It will sound like ‘A’ heterodyned to ‘C’.
The only difficult part of this is designing the filter that eliminates the lower sideband of the shifted signal. I used a Butterworth high-pass filter here for simplicity, but a Chebyshev Type II high-pass or a bandstop filter (centred on the lower sideband frequency, and with an appropriate stopband range) might be more appropriate, if slightly more difficult to design. (I have outlined my filter design strategy here.)
This is an interesting problem! I enjoyed working on it.

Sign in to comment.

More Answers (1)

Walter Roberson
Walter Roberson on 26 Sep 2015
Read the file and play it or write it out with a sampling frequency 261.4/220 times higher.

3 Comments

J. Boog
J. Boog on 26 Sep 2015
Edited: J. Boog on 26 Sep 2015
Thanks for your reply. Although, this is not what i'm looking for. When changing the sampling frequency, the duration of the audio fragment decreases. I want to keep the same length. Do you have any idea how to do this?
Pad the result with 0 until it would play back at the same duration.
Remember, you are dealing with an audio file. That is a fixed duration object that might potentially have a mix of frequencies. Techniques such as fft followed ifft with a different number of points rely upon the signal being periodic. To have the signal be higher frequency and same duration you need to extend the signal, which can be done validly if you assume periodicity and not if you do not assume it.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!