Getting matrix dimension error while modulating audio waveform on matlab - matlab

I am getting the matrix dimension error for the following code. What I am trying to do below is modulation of an audio waveform but I could not get passed the error I specified. I have checked the length of the sample.wav and adjusted time axis(t) accordingly but I must have done something wrong. I appreciate if anyone could help. Thanks in advance!.
function [sm]= modulation(ss,fc,mtype)
ss= audioread('C:\Users\furka\Documents\MATLAB\sample.wav'); %audio waveform to be modulated is loaded.
plot(ss)
length(ss)
t=linspace(0,3e6,3161538);
fc= input('Carrier Frequency='); %carrier frequency will be determined by the user
mtype= menu('Modulation type?','dsb','dsbsc','ssb','fm'); %modulation type will be determined by the user
%fs=44100; %sampling frequency is determined for common audio waveform.(44.1kHz)
%t= 0:1/fs:(2e-5)-1/fs;
if mtype==1
ka= 0.7;
sm= ss.*(1+ka*cos(2*pi*fc*t));
plot(t,sm)
elseif mtype==2 %if doublesideband suppress carrier is selected the statements below will be carried out.
y = ss.*cos(2*pi*fc*t);
plot(y)
% sm = fftshift(fft(abs(y)));
% frequency_axis= (-fs/2):(fs/length(sm)):(fs/2-fs/length(sm));
%plot(frequency_axis,sm)
elseif mtype==3
sm=0.5*[ss.*cos(2*pi*fc*t)-hilbert(ss).*sin(2*pi*fc*t)];
plot(t,sm)
elseif mtype==4
kf=0.7; %frequency sensitivity.
sm= cos(2*pi*fc*t+2*pi*kf*int(ss,t,0,t));
plot(t,sm)
end
end

I can't access the link provided for the sound file but a time length of 3e6 seconds seems like a really long sound. I figure that's something around 30 days long.
Using the handel.mat example provided by MathWorks I get this.
load handel.mat
audiowrite('sample.wav', y, Fs);
[ss, Fs] = audioread('sample.wav');
t = linspace(0, length(ss) / Fs, length(ss));
t = t'; % this is important to match ss <-- this is your matrix dimension error I think
fc = 2000;
ka = 0.7
sm = ss .* (1 + ka * cos(2 * pi * fc * t));
The error of mismatched dimensions comes from linspace output being a row vector and audioread output being a column vector. Transpose one or the other. In my case: t = t'

Related

Filtering a single sample in MATLAB

I'm attempting to create a reverb function in MATLAB and would like to filter the repeats to make them sound more natural. I have the signal processing toolbox however I get an error telling me that I cannot use the lowpass() function on single samples and MATLAB wigs out. The idea is to filter the signal every time it enters the feedback loop to simulate the absorption of high frequencies every time the sound reflects off a surface. My code looks like this:
[x,Fs] = audioread('Clap.mp3');
%Calculate delay length
secOfDelay = 0.03; %units of seconds
samplesOfDelay = secOfDelay * Fs; %sec * samples/sec = samples
%Gain for wet mix
g = 0.9;
for n = 1:length(x)
if (n - samplesOfDelay) < 1 %For no past samples, don't add the delay yet.
out(n,1) = x(n,1);
else
a(n,1) = x(n,1);
b(n,1) = x(n,1) + (g * b(n-samplesOfDelay,1));
end
end
%Add wet mix and dry mix together
out = a+b;
sound(out,Fs);
Any help would be greatly appreciated!
JDB

Finding fundamental frequency .wav file Matlab

I have to extract the fundamental frequency from a .wav file of 1 second long.
I have looked over several options like finding the peaks or doing a complex cepstrum but no luck so far. I have read over the last couple of weeks a lot about it but still i cannot find a viable and optimal way of doing it. I am new to Matlab and Signal Processing.
filedir = dir('*.wav');
[y, Fs] = audioread(filedir.name);
x = y(y ~= 0) % removing the zeroes from the array
psdest = psd(spectrum.periodogram,x,'Fs',Fs,'NFFT',length(x));
[~,I] = max(psdest.Data);
fprintf('Maximum occurs at %d Hz.\n',psdest.Frequencies(I));
The output is for example: Maximum occurs at 5.758645e+02 Hz
I will probably need to actually transform that number into Hz.
For the complex cepstrum:
load mtlb
dt = 1/Fs;
I0 = round(0.1/dt);
Iend = round(1/dt);
x = mtlb(I0:Iend);
c = cceps(x);
t = 0:dt:length(x)*dt-dt;
trng = t(t>=2e-3 & t<=10e-3);
crng = c(t>=2e-3 & t<=10e-3);
[~,I] = max(crng);
fprintf('Complex cepstrum F0 estimate is %3.2f Hz.\n',1/trng(I))
clearvars
The output values is the same for all the files I load so clearly something is wrong.
I have been struggling for a while and I really need to figure this out. To extract that fundamental frequency. I use Matlab 2016b.
Thanks a lot!

Fourier Transform Of male and female voice

I'm doing fourier transform using matlab R2014a, first I have read two audio files of femal and male, then I initialized the magnitude and phase for each. A Task in my report requires to Mix female speech amplitude with phase spectrum of the other signal-male phase-, or viceversa, So I wrote a code and I keep getting this error:
Error using *
Inner matrix dimensions must agree.
out1 = Mag_Male*exp(1i*Phase_Fem);
And even using.*
Error in Untitled9 (line 183)
out1 = Mag_Male.*exp(1i*Phase_Fem);
or .* in both operators
The full error
>> Untitled9
Error using .*
Matrix dimensions must agree.
Error in Untitled9 (line 183)
out1 = Mag_Male.*(exp(1i.*Phase_Fem));
Output of m and f size using size function
code:
maleAudio_row = size(m);
femaleAudio_row = size(f);
display(maleAudio_row);
display(femaleAudio_row);
Output:
maleAudio_row =
119855 2
femaleAudio_row =
119070 1
although my other colleagues worked fine with them :(
This is my Code:
Fs = 11025;
Ts = 1/Fs;
t = 0:Ts:0.1;
[m, Fs]=audioread('hamid1.wav');
[f, Fs]=audioread('myvoice.wav');
player = audioplayer(m,Fs);
player2 = audioplayer(f,Fs);
%play(player2);
%---- Frquency Domain Sampling-----%
Fem = fft(f);
Phase_Fem = angle(Fem);
Mag_Fem = abs(Fem);
%-----------------------------------%
Male = fft(m);
Mag_Male = abs(Male);
Phase_Male = angle(Male);
%-----------------------------------%
out1 = Mag_Male*exp(1i*Phase_Fem); % this step for putting female phase on male mag.
out2 = ifft(out1); % this step is convert the previus step to time domain so i can
%play the audio
Nx = length(out2);
F0 = 1/(Ts*Nx2);
result = audioplayer(out2);
play(result);
Your 'hamid1.wav' is two-channel wav file whereas 'myvoice.wav' is one-channel wav. As mentioned in Matlab manual (http://nl.mathworks.com/help/matlab/ref/audioread.html)
Audio data in the file, returned as an m-by-n matrix, where m is the number of audio samples read and n is the number of audio channels in the file.
Just convert m to one channel as m = 0.5*(m(:,1)+m(:,2)), adjust other dimension and use .* product (as people suggested in the comments).
clear all;
m = randn(1000,2); %dummy signal
f = randn(999,1); %dummy signal
N = min(size(m,1),size(f,1));
Male = fft(0.5*(m(1:N,1)+m(1:N,2)));
Fem = fft(f(1:N,1));
Mag_Male = abs(Male);
Phase_Male = angle(Male);
Phase_Fem = angle(Fem);
Mag_Fem = abs(Fem);
out1 = Mag_Male.*exp(1i*Phase_Fem);
If you use a * it will try and do matrix multiplication. What you probably want to use is an element by element operator, which is a . before the *. This will multiply the first element in the vector with the first element in the other vector, the second with the second, etc. etc.
out1 = Mag_Male.*exp(1i*Phase_Fem);
This assumes that the result from your FFT is the same length. This will be the case if the original samples are the same length.

adjusting swept signal equation

When I do a spectrogram in matlab / octave I can create a swept signal that looks like the RED plot line below. But how can I create a swept signal like the BLUE line in the 1st plot using the equation below.
thanks to Daniel and David for getting me this far with the code is below
startfreq=200;
fs=44100;
endfreq=20;
dursec= 10;%duration of signal in seconds
t=(0:dursec*fs)/fs; %Time vector
alpha=log(startfreq/endfreq)/dursec;
sig = exp(-j*2*pi*startfreq/alpha*exp(-alpha*t));
sig=(sig/max(abs(sig))*.8); %normalize signal
wavwrite([sig'] ,fs,32,strcat('/tmp/del.wav')); %export file
specgram(sig,150,400);
1st plot
2nd plot
How can I fix the the equation in the variable sig to get it to look like the BLUE line in the 1st plot?
3rd plot
This question is almost an month old, so you might have figured this out by now. Here's an answer in case you are still interested.
It appears that your current model for the frequency is
freq(t) = b*exp(-alpha*t)
with
freq(0) = b = startfreq
freq(dursec) = b*exp(-alpha*dursec) = endfreq
There are two free parameters (b and alpha), and two equations. The first equation, b = startfreq, gives us b (trivially).
Solving the last equation for alpha gives
alpha = -log(endfreq/startfreq)/dursec
= log(startfreq/endfreq)/dursec
So
freq(t) = startfreq * exp(-alpha*t)
To use this as the instantaneous frequency of a frequency-swept signal,
we need the integral, which I'll call phase(t):
phase(t) = -(startfreq/alpha) * exp(-alpha*t)
The (complex) frequency-swept signal is then
sig(t) = exp(2*pi*j * phase(t))
The real part of this signal is
sig(t) = cos(2*pi*phase(t))
That explains your current code. To generate a chirp whose frequency varies like the blue curve, you need a different model for the frequency. A more general model than the one used above is
freq(t) = a + b*exp(-alpha*t)
The requirements at t=0 and t=dursec are
freq(0) = a + b = startfreq
freq(dursec) = a + b*exp(-alpha*dursec) = endfreq
That's two equation, but we now have three parameters: a, b, and alpha. I'll use the two equations to determine a and b, and leave alpha as a free parameter. Solving gives
b = (startfreq - endfreq)/(1 - exp(-alpha*dursec))
a = startfreq - b
Integrating the model gives
phase(t) = a*t - (b/alpha)*exp(-alpha*t)
alpha is an arbitrary parameter. Following the formula from the first model, I'll use:
alpha = abs(log(startfreq/endfreq))/dursec
The following is a complete script. Note that I also changed the use of exp(-j*2*pi*...) to cos(2*pi*...). The factor 0.8 is there to match your code.
startfreq = 20;
endfreq = 200;
fs = 44100;
dursec = 10; % duration of signal in seconds
t = (0:dursec*fs)/fs; % Time vector
if (startfreq == endfreq)
phase = startfreq * t;
else
alpha = abs(log(endfreq/startfreq))/dursec;
b = (startfreq - endfreq)/(1 - exp(-alpha*dursec));
a = startfreq - b;
phase = a*t - (b/alpha)*exp(-alpha*t);
endif
sig = 0.8 * cos(2*pi*phase);
wavwrite([sig'] ,fs,32,strcat('del.wav')); % export file
specgram(sig,150,400);

MATLAB code for Harmonic Product Spectrum

Can someone tell me how I can implement Harmonic Product Spectrum using MATLAB to find the fundamental frequency of a note in the presence of harmonics?? I know I'm supposed to downsample my signal a number of times (after performing fft of course) and then multiply them with the original signal.
Say my fft signal is "FFT1"
then the code would roughly be like
hps1 = downsample(FFT1,2);
hps2 = downsample(FFT1,3);
hps = FFT1.*hps1.*hps2;
Is this code correct??? I want to know if I've downsampled properly and since each variable has a different length multiplying them results in matrix dimension error.. I really need some real quick help as its for a project work... Really desperate....
Thanx in advance....
OK you can't do "hps = FFT1.*hps1.*hps2;" for each downsampled data, do you have different sizes ...
I did a example for you how make a very simple Harmonic Product Spectrum (HPS) using 5 harmonics decimation (downsample), I just test in sinusoidal signals, I get very near fundamental frequency in my tests.
This code only shows how to compute the main steps of the algorithm, is very likely that you will need improve it !
Source:
%[x,fs] = wavread('ederwander_IN_250Hz.wav');
CorrectFactor = 0.986;
threshold = 0.2;
%F0 start test
f = 250;
fs = 44100;
signal= 0.9*sin(2*pi*f/fs*(0:9999));
x=signal';
framed = x(1:4096);
windowed = framed .* hann(length(framed));
FFT = fft(windowed, 4096);
FFT = FFT(1 : size(FFT,1) / 2);
FFT = abs(FFT);
hps1 = downsample(FFT,1);
hps2 = downsample(FFT,2);
hps3 = downsample(FFT,3);
hps4 = downsample(FFT,4);
hps5 = downsample(FFT,5);
y = [];
for i=1:length(hps5)
Product = hps1(i) * hps2(i) * hps3(i) * hps4(i) * hps5(i);
y(i) = [Product];
end
[m,n]=findpeaks(y, 'SORTSTR', 'descend');
Maximum = n(1);
%try fix octave error
if (y(n(1)) * 0.5) > (y(n(2))) %& ( ( m(2) / m(1) ) > threshold )
Maximum = n(length(n));
end
F0 = ( (Maximum / 4096) * fs ) * CorrectFactor
plot(y)
HPS usually generates an error showing the pitch one octave up, I change a bit a code, see above :-)