Matlab read multiples samples with audioread - matlab

I'm trying to read multiple samples from a mp3 file with the function audioread.
let's say I have the following code :
samples = [1, 44100; 50000, 100000; 150000, 200000];
[signal, fe] = audioread(filepath, samples);
t = (1/fe:1/fe:lenght(signal)/fe);
signal = signal(:,1);
How can I make this work ? If samples contain only 1 row, it works just fine, but I have like 80 samples in the same mp3 file to work with.
I've tried this with a for loop, the audioread part works fine, but I don't know how to store the data since the duration of each sample isn't the same, the dimensions of matrices are not consistent and I can't concatenate them in a single matrix.
Plus, I've been told for loops are better avoided whenever possible in Matlab, so I'd like to do this by the rules (but i'll use them if there's no other way ofc).
Finally I'm very new to Matlab so I might miss something very obvious, but cound'nt find out reading through the doc.
Thks for your help :)

Related

How to read a complex 3D matrix (binary file) in Matlab without using interleaved/reshaping method?

I have a very huge 3D matrix, the data was written into disk for future use. Writing the matrix into a bin is easy, reading it back however have some issue.
Write to bin:
z=repmat(complex(rand(5),rand(5)),[1 1 5])
z_imag = imag(z);
z_real = real(z);
adjacent = [z_real z_imag];
fileID = fopen('complex.bin','w');
fwrite(fileID,adjacent,'double')
And now, I try to read it back using memmapfile:
m = memmapfile('complex.bin', 'Offset', 0, 'Format', {'double' [5,5,5] 'x'});
complexValues = complex(m.Data(:).x(1,:), m.Data(:).x(2,:)); %this line doesn't work though, just for explanation's sake
It gave me an error saying that
Error using memmapfile/subsref (line 764) A subscripting operation on
the Data field attempted to create a comma-separated list. The
memmapfile class does not support the use of comma-separated lists
when subscripting.
I was referring to the solution here, the suggested solution used the reshape to shape the matrix beforehand (as contrast to my method above). I try to avoid using reshape in my code as I'm dealing with very huge data and that might computationally expensive and takes a long time. Is there an alternative/better way to do this?
Thanks in advance!

Splitting an audio file in Matlab

I'm trying to split an audio file into 30 millisecond disjoint intervals using Matlab. I have the following code at the moment:
clear all
close all
% load the audio file and get its sampling rate
[y, fs] = audioread('JFK_ES156.wav');
for m = 1 : 6000
[t(m), fs] = audioread('JFK_ES156.wav', [(m*(0.03)*fs) ((m+1)*(0.03)*fs)]);
end
But the problem is that I get the following error:
In an assignment A(I) = B, the number of elements in B and I
must be the same.
Error in splitting (line 12)
[t(m), fs] = audioread('JFK_ES156.wav', [(m*(0.03)*fs)
((m+1)*(0.03)*fs)]);
I don't see why there's a mismatch in the number of elements in B and I and how to solve this. How can I get past this error? Or is there just an easier way to split the audio file (maybe another function I don't know about or something)?
I think the easiest way to split audio is to just load it and use the vec2mat function. so you would have something like this;
[X,Fs] = audioread('JFK_ES156.wav');
%Calculate how many samples you need to capture 30ms of audio
matSize = Fs*0.3;
%Pay attention to that apostrophe. Makes sure samples are stored in columns
%rather than rows.
output = vec2mat(x,matSize)';
%You can now have your audio split up into the different columns of your matrix.
%You can call them by using the column calling command for matrices.
%Plot first 30ms of audio
plot(output(:,1));
%You can join the audio back together using this command.
output = output(:);
Hope that helps. Another good thing about this method is that it keeps all your data in one place!
Edit : One thing I thought of, you may get a problem with this depending on your vector size. But I think vec2mat actually zeroPads your vector. Not a big thing, but if you're moving back and forth between the two, then it might be a good idea to have another variable that stores the original length of your signal.
You should just use the variable y and reshape it to form your split audio. For example,
chunk_size = fs*0.03;
y_chunks = reshape(y, chunk_size, 6000);
That will give you a matrix with each column a 30 ms chunk. This code will also be faster than reading small segments from file in a loop.
As hiandbaii suggested you could also use cell array. Make sure you clear your existing variables before that. Not clearing the array t is probably the reason you got the error "Cell contents assignment to a non-cell array object."
Your original error is because you cannot assign a vector with scalar indexing. That is, 'm' is a scalar, but your audioread call is returning a vector. This is what the error says about mismatch in size of I and B. You could also fix that by making t a 2-D array and use an assignment like
[t(m,:), fs] =
It appears that each 30 ms segment is not equal to one sample. That would be the only case where your code works. i.e. 0.03*fs != 1.
You could try using cells instead.. i.e. replace t(m) with t{m}

Quantization of .wav file

I am attempting to quantize a 16 bit .wav file to a lower bit rate using Matlab. I've opened the file using wavread() but I am unsure of how to proceed from here. I know that somehow I need to "round" each sample value to (for example) a 7 bit number. Here's the code that's reading the file:
[file,rate,bits] = wavread('smb.wav');
file is a 1 column matrix containing the values of each sample. I can loop through each item in that matrix like so:
for i=1 : length(file)
% not sure what to put here..
end
Could you point me in the right direction to quantize the data?
If you have int16 data, varying from -32768 to +32767, it can be as simple as
new_data = int8(old_data./2^8);
That won't even require a for loop.
For scaled doubles it would be
new_data = int8(old_data.*2^7);
The wavread documentation suggests that you might even be able retrieve the data in that format to begin with:
[file,rate,bits] = wavread('smb.wav','int8');
EDIT: Changing the bit rate:
After rereading the question, I realize that you also mentioned a lower bit rate which implies reducing the sample rate, not the quantization of the data. If that is the case, you should look at the documentation for downsample, decimate, and/or resample. They are all built in MATLAB functions that change the bit rate.
downsample(file,2)
would half the bit rate, for example.

fft on samples of an audio file in matlab

I'm trying to extract information from a sound file in order to use it in a video classification algorithm I'm working on.
My problem is that I don't know how to work exactly with audio files in Matlab.
Below is what I need to accomplish:
open the audio file and get the sampling rate/frequency
I need to work on a window of 2 seconds so I have to loop over the file and get each 2 seconds as a window and then do the ftt (Fast-Fourier-Transform) on each window.
After that it is my turn to use these values to do what I want
any help would be appreciated
Thanks.
Following code may only give you some idea. You may need to determine another fft size, a windowing function like hamming etc.
To read a wav file:
[data, Fs] = wavread('path.wav');
Splitting to 2 sec windows and getting fft:
frameFFT = [];
timeStep = Fs*2;
for i=1:timeStep:length(data)-timeStep
frameFFT = [frameFFT; fft(data(i:i+timeStep-1),1024)];
end

How to use data from .m file into another?

In the following code, I need 1 lakh samples in the array mydata. I don't know what I am getting out of mydata. Do I have to increase the range of t to get that. And how can I use the data in mydata into another .m file for further processing.
t = [ 1 : 1 : 500]; % Time Samples
f1=10000; % Input Signal Frequency
f2=20000;
f3=30000;
f4=f2+f3;
f5=f1+f3;
f6=f4+f2;
f7=f1+f6;
f8=45000;
f9=55000;
f10=35000;
mydata=[1:100000];
Fs = 100000; % Sampling Frequency
for i=1:100000
if(i<=10000)
mydata = sin(2*pi*f1/Fs*t);
elseif((i>10000)&&(i<=20000))
mydata=sin(2*pi*f2/Fs*t);
elseif((i>20000)&&(i<=30000))
mydata=sin(2*pi*f3/Fs*t);
elseif((i>30000)&&(i<=40000))
mydata=sin(2*pi*f4/Fs*t);
elseif((i>40000)&&(i<=50000))
mydata=sin(2*pi*f5/Fs*t);
elseif((i>50000)&&(i<=60000))
mydata=sin(2*pi*f6/Fs*t);
elseif((i>60000)&&(i<=70000))
mydata=sin(2*pi*f7/Fs*t);
elseif((i>70000)&&(i<=80000))
mydata=sin(2*pi*f8/Fs*t);
elseif((i>80000)&&(i<=90000))
mydata=sin(2*pi*f9/Fs*t);
elseif((i>90000)&&(i<=100000))
mydata=sin(2*pi*f10/Fs*t);
end
end
stem(mydata)
your code doesn't do very much; you know that, right?
if we don't know/understand what you want, we can't help..
and for anyone else: 1 lakh = 100 000 (http://en.wikipedia.org/wiki/Lakh)
edit: are you trying to produce an array of 100000 samples, consisting of a fixed number of points from different sine waves? aka:
[sin(1.0*pi*[0:10]) sin(2.0*pi*[0:10] sin(1.5*pi*[0:10] (etc) ]
edit2: you repeated your earlier question (which was already answered): How can I generate a sine wave with different frequencies using matlab?
I couldnt understand what you want to do with mydata, please be more specific, because your code is wrong and I cant figure what you want to create.
Whereas for the problem on having the data to be used on other script one simple way would just write mydata into disc,
by doing on your script:
save path_for_mydata/file_name.mat mydata
And on the other script:
load path_formydata/file_name.mat
One other way, would be to create a function, and pass it as a parameter.
Finally, you could just run the first script, and then the second script on command line or on one third script that would call this both scripts, the parameters from the first script will be saved on transient memory while the second script runs.