Basically I have a school project where I must create a new wave file from a given wave file. This new wave must be created in Matlab and the only difference is that a sine wave is to be mixed with the given wav file (not concatenated onto the end..). The sine wave is to be of 500hz.
My code so far is:
clear;
filename = 'C:\Documents and Settings\cmh0007\My Documents\rofl.wav';
[y, Fs, nbits, readinfo] = wavread(filename);
duration = numel(y) / Fs;
sinefs = 0:0.002:duration;
sinwave = 0.5*sin(2*pi*sinefs);
disp(size(y));
disp(size(sinwave));
newsignal = y + sinwave;
subplot(2,2,1), plot(y), title('Entire waveform');
subplot(2,2,3), plot(sinwave), title('sine waveform');
subplot(2,2,2), plot(newsignal), title('added waveform');
however, this code fails on creating the newsignal variable. The issue is that the two matrices are of different sizes due to the sampling rates differing between the two waves.
The output of the size calls are as follows:
797696 2
1 18089
Seeing as these files differ in sizes by a factor of ~44 I figured I could simply use the same sample from the sin wave 44 times over for each sample of the given wave file. However, because the difference is not exactly 44 I don't know if this is even an option.
Does anyone have any suggestions on how to go about mixing these two files?
Try changing 0.002 to 1/Fs. That way you'll have the same sampling rate. You should also choose only one of the stereo channels for y and do an appropriate transpose.
You might also consider changing the name sinefs to sinet or something as it represents the time parameter and not the sampling frequency.
Related
I am writing a piece of code that figures out what frequencies(notes) are being played at any given time of a song (note currently I am testing it grabbing only the first second of the song). To do this I break the first second of the audio file into 8 different chunks. Then I perform an FFT on each chunk and plot it with the following code:
% Taking a second of an audio file and breaking it into n many chunks and
% figuring out what frequencies make up each of those chunks
clear all;
% Read Audio
fs = 44100; % sample frequency (Hz)
full = audioread('song.wav');
% Perform fft and get frequencies
chunks = 8; % How many chunks to break wave into
for i = 1:chunks
beginningChunk = (i-1)*fs/chunks+1
endChunk = i*fs/chunks
x = full(beginningChunk:endChunk);
y = fft(x);
n = length(x); % number of samples in chunk
amp = abs(y)/n; % amplitude of the DFT
%%%amp = amp(1:fs/2/chunks); % note this is my attempt that I think is wrong
f = (0:n-1)*(fs/n); % frequency range
%%%f = f(1:fs/2/chunks); % note this is my attempt that I think is wrong
figure(i);
plot(f,amp)
xlabel('Frequency')
ylabel('amplitude')
end
When I do that I get graphs that look like these:
It looks like I am plotting too many points because the frequencies go up in magnitude at the far right of graphs so I think I am using the double sided spectrum. I think I need to only use the samples from 1:fs/2, the problem is I don't have a big enough matrix to grab that many points. I tried going from 1:fs/2/chunks, but I am unconvinced those are the right values so I commented those out. How can I find the single sided spectrum when there are less than fs/2 samples?
As a side note when I plot all the graphs I notice the frequencies given are almost exactly the same. This is surprising to me because I thought I made the chunks small enough that only the frequency that's happening at the exact time should be grabbed -- and therefore I would be getting the current note being played. If anyone knows how I can single out what note is being played at each time better that information would be greatly appreciated.
For a single-sided FT simply take the first half of the output of the FFT algorithm. The other half (the nagative frequencies) is redundant given that your input is real-valued.
1/8 second is quite long. Note that relevant frequencies are around 160-1600 Hz, if I remeber correctly (music is not my specialty). Those will be in the left-most region of your FT. The highest frequency you compute (after dropping the right half of FFT) is half your sampling frequency, 44.1/2 kHz. The lowest frequency, and the distance between samples, is given by the length of your transform (44.1 kHz / number of samples).
Here is the context of the problem: I have a DTMF signal in wav format, I have to identify the number sequence it has encoded. I must do so using fast fourier transform in Matlab, implying that I read the wav file using wavread and to identify each number that is seperated by 40ms silence or more.
Here is my code so far:
[signal, fs] = wavread( 'C:\Temp\file.wav' ); % here, fs = 8000Hz
N = 512;
T = 1/fs;
L = length( signal )
samples = fs / 1000 * 40
windows = floor(L / samples)
t = (1:L)/fs;
figure(1), plot(t, signal);
Here is what the figure 1 looks like, that is the signal read from the wav:
How can I effectively split the signal into pieces so that I can then do an FFT on each of the 10 pieces seperately to decode the corresponding numbers?
I would recommend the following approach:
Find the envelope of the signal in the time domain (see Hilbert transform).
Smooth the envelope a bit.
Take the diff and find peaks to get the onsets of the tones.
Use the onsets to pick frames and find the spectrum using fft.
Find the index of the max in each of the spectrums and convert them to a frequency.
The tricky part in this is to get a robust onset detector in point 3. The peaks in the difference you pick, has to be of a certain size in order to qualify as on onset. If your tones are of varying strength this might pose a problem, but from your image of the time signal it doesn't seem like a problem.
Regards
This worked for me:
windowSize = 256;
nbWindows = floor(L / windowSize);
for i=1:nbWindows
coeffs = fft(signal((i-1)*windowSize+1:i*windowSize));
plot(abs(coeffs(1:N)));
waitforbuttonpress
end;
This way it is possible to shift the window until the end of the input signal
I'm writing a Matlab program to perform a convoluted sum of two signals. I first started out creating a simple sinusoidal signal and a carrier signal. I convoluted the two and created the convoluted signal. You can see that my (x) axis is specified in the time domain. My code and a screen shot of my plot is shown below for clarity.
MY CODE:
note: This program doesn't use the .wav file and instead uses a simple sinusoidal signal.
mySignalFreq = 1E3;
%T = 1/f;
T = 1/mySignalFreq;
tmin = 0;
tmax = 5*T;%i want to graph 5 time periods
dt = T/60;%used 60 to specify spaceing of time domain
t = tmin:dt:tmax;
myCarrierFreq = 560E3;
Bandwidth = 10E3;
omega_mySignal = 2*pi*mySignalFreq;%determine angular frequency
omega_myCarrier = 2*pi*myCarrierFreq;%determine angular frequency
modIndex = 0.8;%modulation index
myCarrierAmp = 4.0;%amplitude of carrier signal
ys = sin(omega_mySignal*t);
yc = sin(omega_myCarrier*t);
convSum = myCarrierAmp*(1+modIndex.*ys).*yc;%Convolution Sum
%create txt file with Write permissions
convolutionData.txt = fopen('convolutionData.txt','w');
%7.5 specifies 7digits and 5digits to the right of decimal
%have to use \r\n for readability
%array of values need to be in [x;y1;y2;y3] format
%comma in the function denotes the seperator
fprintf(convolutionData.txt,'%7.5f,%7.5f,%7.5f,%7.5f\r\n',[t;ys;yc;convSum]);
%close out file
fclose(convolutionData.txt);
%creating a basic plot of all three signals
plot(t,ys,'r',t,yc,'g',t,convSum,'b');
title('Convoluted Signal');
xlabel('Time Periods');
ylabel('Amplitude (Volts)');
grid on;
This is the picture of the plot above. You can see that i'm using the variable 't' as my x axis data.
I have finally figured out some code that plots my .wav file i created with a recorder. However, it's plots it in the frequency domain. As you can see in the code i'm reading the data in the .wav file into what I'm understanding is an array. Not quite understanding this part so if someone could explain more on that as a side note that would be great.
My main question is how do I incorporate the data from my .wav file into my original code above so it can be plotted in the time domain like my plot above? Just can't figure that part out because the code below is just doing it in the frequency domain.
Here is the code and plot of the .wav file
[wave,fs]=audioread('myvoice1.wav');
t=0:1/fs:(length(wave)-1)/fs;
subplot(2,1,1);
plot(t,wave);
n=length(wave)-1;
f=0:fs/n:fs;
wavefft=abs(fft(wave));
subplot(2,1,2);
plot(f,wavefft);
The upper subfigure in your last plot already is the right signal, so the t and wave are the right variables.
Only the second subfigure in your last plot is the frequency domain (represented in the wavefft variable).
Just use the wave variable and you should have what you want.
Here is the context of the problem: I have a DTMF signal in wav format, I have to identify the number sequence it has encoded. I must do so using fast fourier transform in Matlab, implying that I read the wav file using wavread and to identify each number that is seperated by 40ms silence or more.
Here is my code so far:
[signal, fs] = wavread( 'C:\Temp\file.wav' ); % here, fs = 8000Hz
N = 512;
T = 1/fs;
L = length( signal )
samples = fs / 1000 * 40
windows = floor(L / samples)
t = (1:L)/fs;
figure(1), plot(t, signal);
Here is what the figure 1 looks like, that is the signal read from the wav:
How can I effectively split the signal into pieces so that I can then do an FFT on each of the 10 pieces seperately to decode the corresponding numbers?
I would recommend the following approach:
Find the envelope of the signal in the time domain (see Hilbert transform).
Smooth the envelope a bit.
Take the diff and find peaks to get the onsets of the tones.
Use the onsets to pick frames and find the spectrum using fft.
Find the index of the max in each of the spectrums and convert them to a frequency.
The tricky part in this is to get a robust onset detector in point 3. The peaks in the difference you pick, has to be of a certain size in order to qualify as on onset. If your tones are of varying strength this might pose a problem, but from your image of the time signal it doesn't seem like a problem.
Regards
This worked for me:
windowSize = 256;
nbWindows = floor(L / windowSize);
for i=1:nbWindows
coeffs = fft(signal((i-1)*windowSize+1:i*windowSize));
plot(abs(coeffs(1:N)));
waitforbuttonpress
end;
This way it is possible to shift the window until the end of the input signal
Question is as stated in the title.
After i decimate an audio signal that take every nth point out it in turns speeds up the audio clip at a factor of n. I want the decimated and original clips to have the same length in time.
Heres my code, analyzing and decimated piano .wav
[piano,fs]=wavread('piano.wav'); % loads piano
play=piano(:,1); % Renames the file as "play"
t = linspace(0,time,length(play)); % Time vector
x = play;
y = decimate(x,2);
stem(x(1:30)), axis([0 30 -2 2]) % Original signal
title('Original Signal')
figure
stem(y(1:30)) % Decimated signal
title('Decimated Signal')
%changes the sampling rate
fs1 = fs/2;
fs2 = fs/3;
fs3 = fs/4;
fs4 = fs*2;
fs5 = fs*3;
fs6 = fs*4;
wavwrite(y,fs,'PianoDecimation');
possible solutions: Double each of the remaining points since the new decimated clip is 2x shorter then the original.
I just want to be able to have a side by side comparison of the 2 clips.
here is the audio file: http://www.4shared.com/audio/11xvNmkd/piano.html
Although #sage's answer has a lot of good information, I think the answer to the question is as simple as changing your last line to:
wavplay(y,fs/2,'PianoDecimation')
You have removed half the samples in the file, so in order to play it back over the same time period as the original, you need to set the playback frequency to half as many samples per second.
Are you using wavplay, audioplayer, or something else to play the decimated signals? Are you explicitly specifying the sample frequencies?
The functions take the sample frequency as one of the parameters (the second parameter). You are decreasing the sample frequency as you decimate, so you need to update that parameter accordingly.
Also, when you are plotting the data, you should:
plot N times as many points on the original data (when decimating by N)
provide a corresponding x axis input - I recommend t = (1/Fs:1/Fs:maxT) where maxT is the maximum time you want to plot, which will address #1 if you use the updated Fs, which will result in larger time steps (and make sure to transpose t if it does not match your signal)
I have added an example that plays chirp and decimated chirp (this chirp is part of the standard MATLAB install). I amplified the decimated version. The tic and toc show that the elapsed time is equivalent (within variations in processor loading, etc.) - note that this also works for decim = 3, etc:
load chirp
inWav = y;
inFs = Fs;
decim = 2;
outWav = decimate(inWav,decim);
outFs = inFs/decim;
tic, wavplay(inWav,inFs),toc
pause(0.2)
tic,wavplay(outWav*decim^2,outFs),toc
The function 'decimate' really messes up the chirp sound (the sample rate of which is not very high frequency to begin with), but perhaps you are trying to show something like this...