How I can i audioread all files in a folder - matlab

I have a folder with files named like this: "speaker1_001.wav". It goes From 001 to speaker1_020. How can I do a for loop to "audioread" all the files and storing the value in variables with different names?
This is what I got, but I only obtain one variable instead of 20.
mypath = fullfile('TrainVoices', 'speaker1');
for idx = 1:20
filename = fullfile(mypath, sprintf('speaker1_%d.wav', idx));
nameSpeaker = sprintf('speaker1_%d', idx);
[nameSpeaker, fs] = audioread(filename);
end

In your code, you try to dinamically create the name of the output variable nameSpeaker with the instruction nameSpeaker = sprintf('speaker1_%d', idx); in order to use it as output variable in the call to audioread.
This is not correct since you actually assign the string created with sprintf to the variable nameSpeaker rather then "change" the name of it.
Also, you have to manage the "zeros" included in the filename.
A part from this error (which can be fixed), in general it is not a good practice to use dinamically created variable.
A possible solution could be to store the wav data in a struct which allows to dinamically create the name of the field.
Moreover, since according to the code you've posted you know in advance the path and the root name of the inout files, you can create the complete filename by simply appending the different strings rather than using fullfile
In the following you can find a possible implementaton of the proposed solution.
The output will be a struct named nameSpeaker with a set of fields named speaker1_1, speaker1_2, speaker1_3 ... etc after the name of the input file in which, for semplicity the "zeros"have been removed.
Each of this fields is a struct with the field: data and fs containing the data of the wav file.
For example:
the data of speaker1_001.wav arfe stored in the struct
nameSpeaker.speaker1_1.data
nameSpeaker.speaker1_1.fa
the data of speaker1_002.wav arfe stored in the struct
nameSpeaker.speaker1_2.data
nameSpeaker.speaker1_2.fs
and so on.
% Defina the path
mypath='TrainVoices\speaker1'
% Define the file root name
f_root_name='speaker1_'
% Define the extension of the input file\
ext='.wav'
% Loop over the input filess
for idx = 1:20
%& add the proper number of "0" to tjhe filename
if(idx <= 9)
f_name=[f_root_name '00' num2str(idx)]
else
f_name=[f_root_name '0' num2str(idx)]
end
% Build the filename
filename=fullfile(mypath,[f_name ext])
% Read the wav file
[data,fs] = audioread(filename);
% Store the wav file data in a struct
nameSpeaker.([f_root_name num2str(idx)]).data=data;
nameSpeaker.([f_root_name num2str(idx)]).fs=fs;
end
You can make access to the data by simply specify the "idx" of the file.
For example, to make access to the data of speaker1_001.wav, you can simply define the file "idx" and then build the names of the fields accordingly:
file_idx=3
data=nameSpeaker.([f_root_name num2str(file_idx)]).data
fs=nameSpeaker.([f_root_name num2str(file_idx)]).fs

Related

Saving data to .mat file in MATLAB

I'm new to MATLAB, and I can't manage to make my function work in order to save my data into a .mat file.
The input:
A structure, with 5 fields:
data: 3D matrix of 19x1000x143
labels: 1x143 matrix with 1 or -1 in it
subject_number: an integer
sampling_rate: an integer, 500 Hz
channel_names: 1x19 matrix with text in it
name: a string for the name of the file
clean: a matrix 1x143 with 1 or 0 in it.
The idea is to save only the clean data, marked as 1 in the clean matrix.
If clean(i) is equal to 1:
save data(:,:,i) and labels(:,i)
This is the code I've tried to implement in the saving.m file:
function saving(EEG_struct, clean, name)
subject_number = EEG_struct.subject_number;
fs = EEG_struct.sampling_rate;
chan_names = EEG_struct.channel_names;
nb_epoch = size(EEG_struct.data, 3);
for j=1:nb_epoch
if clean(j) == 1
% Keep the epoch and label
data = cat(3, data, EEG_struct.data(:,:,j));
labels = cat(2, labels, EEG_struct.labels(:,j));
end
end
save(name, data, labels, subject_number, fs, chan_names)
As you can see, I would like to save the data as a structure with the same shape as the EEG_struct input.
Moreover, I would like to use a parfor instead of a for, but it raised me an error I didn't quite get:
An UndefinedFunction error was thrown on the workers for 'data'. This might be because the file containing 'data' is not accessible on the workers. Use addAttachedFiles(pool, files) to specify the required files to be attached. See the documentation for 'parallel.Pool/addAttachedFiles' for more details. Caused by: Undefined function or variable 'data'.
Thanks for the help !
You can use your clean variable as a logical index and parse out your data and labels at once. So there is no need for a loop.
Also the save command needs the "names" of the vars to save not the variables themselves. So I just put ' ' around each one.
function saving(EEG_struct, clean, name)
subject_number = EEG_struct.subject_number;
fs = EEG_struct.sampling_rate;
chan_names = EEG_struct.channel_names;
nb_epoch = size(EEG_struct.data, 3);
%No need for a loop at all
data = EEG_struct.data(:,:,logical(clean));
labels = EEG_struct.labels(logical(clean)); %This is a 1xN so I removed the extra colon operator
save(name, 'data', 'labels', 'subject_number', 'fs', 'chan_names');
EDIT:
Per you comment if you want to just leave everything in the structure. I gave you 2 options for how to save it.
function saving(EEG_struct, clean, name)
%Crop out ~clead data
EEG_struct.data = EEG_struct.data(:,:,logical(clean));
EEG_struct.labels = EEG_struct.labels(logical(clean)); %This is a 1xN so I removed the extra colon operator
% Option 1
save(name, 'EEG_struct');
% Option2
save(name, '-struct', 'EEG_struct');
Option 1 will directly save the struct to the MAT file. So if you were to load the data back like this:
test = load(name);
test =
EEG_struct: [1x1 struct]
You would get your structure placed inside another structure ... which might not be ideal or require an extra line to de-nest it. On the other hand just loading the MAT file with no outputs load(name) would put EEG_struct into your current workspace. But if in a function then it sort of springs into existence without every being declared which makes code a bit harder to follow.
Option 2 uses the '-struct' option which breaks out each field automatically into separate vars in the MAT file. So loading like this:
EEG_struct = load(name);
Will put all the fields back together again. To me at least this looks cleaner when done within a function but is probably just my preference
So comment out which ever you prefer. Also, not I did not include clean in the save. You could either append it to the MAT or add it to your structure.
To get a structure the same as EEG_struct but with only the data/labels corresponding with the clean variable, you can simply make a copy of the existing structure and remove the rows where clean=0
function saving(EEG_struct, clean, name)
newstruct = EEG_struct;
newstruct.data(:,:,logical(~clean)) = '';
newstruct.labels(logical(~clean)) = '';
save(name,'newstruct');

MATLAB: Loop through the values of a list from 'who' function

I have a long list of variables in my workspace.
First, I'm finding the potential variables I could be interested in using the who function. Next, I'd like to loop through this list to find the size of each variable, however who outputs only the name of the variables as a string.
How could I use this list to refer to the values of the variables, rather than just the name?
Thank you,
list = who('*time*')
list =
'time'
'time_1'
'time_2'
for i = 1:size(list,1);
len(i,1) = length(list(i))
end
len =
1
1
1
If you want details about the variables, you can use whos instead which will return a struct that contains (among other things) the dimensions (size) and storage size (bytes).
As far as getting the value, you could use eval but this is not recommended and you should instead consider using cell arrays or structs with dynamic field names rather than dynamic variable names.
S = whos('*time*');
for k = 1:numel(S)
disp(S(k).name)
disp(S(k).bytes)
disp(S(k).size)
% The number of elements
len(k) = prod(S(k).size);
% You CAN get the value this way (not recommended)
value = eval(S(k).name);
end
#Suever nicely explained the straightforward way to get this information. As I noted in a comment, I suggest that you take a step back, and don't generate those dynamically named variables to begin with.
You can access structs dynamically, without having to resort to the slow and unsafe eval:
timestruc.field = time;
timestruc.('field1') = time_1;
fname = 'field2';
timestruc.(fname) = time_2;
The above three assignments are all valid for a struct, and so you can address the fields of a single data struct by generating the field strings dynamically. The only constraint is that field names have to be valid variable names, so the first character of the field has to be a letter.
But here's a quick way out of the trap you got yourself into: save your workspace (well, the relevant part) in a .mat file, and read it back in. You can do this in a way that will give you a struct with fields that are exactly your variable names:
time = 1;
time_1 = 2;
time_2 = rand(4);
save('tmp.mat','time*'); % or just save('tmp.mat')
S = load('tmp.mat');
afterwards S will be a struct, each field will correspond to a variable you saved into 'tmp.mat':
>> S
S =
time: 1
time_1: 2
time_2: [4x4 double]
An example writing variables from workspace to csv files:
clear;
% Writing variables of myfile.mat to csv files
load('myfile.mat');
allvars = who;
for i=1:length(allvars)
varname = strjoin(allvars(i));
evalstr = strcat('csvwrite(', char(39), varname, '.csv', char(39), ', ', varname, ')');
eval(evalstr);
end

passing a filename as argument in matlab

In matlab I have a function which should take in a file name.
This file has a struct in it, later this file should be executed with in the function so that the struct will be loaded to the work space.
For example:
My function is hello(a), where 'a' is a file name, this file has a struct.
On executing the file in command window this struct will be loaded in the workspace.
Same way I want the struct to be loaded in to the workspace when I call the function.
I tried eval(a), but this is not loading the struct in the file to the workspace.
From the file name how will I obtain the struct name, even though I know that there is a struct in the file, but this is going to vary dynamically.
So how should I return the structure in function?
I am not sure whether you want the struct (or structs) inside the file to be copied automatically to the workspace, or if you want to assign the data yourself.
The following solution copies all variables from file a to the "base"-workspace automatically using the assignin() function. The solution also assumes that you give it a file for a .mat file.
function hello(a)
all_structs = load('-mat', a);
var_names = fieldnames(all_structs);
for k = 1:length(var_names)
assignin('base', var_names{k}, all_structs.(var_names{k}));
end
end
Try eval:
function mystruct = readstruct(filename)
% ... read in text from file here ...
eval(text)
For example, assume your file contains text 'mystruct.myval = 1', then after reading the file contents into string text, eval(text) returns
mystruct =
myval: 1
To load the structure into the workspace, the function should return the structure.
If the file contains arbitrary data (presumably but not necessarily in ascii format) then you can simply assign it to a structure after the file is read:
function mystruct = readstruct(filename)
% ... read in text from file here ...
% ... perform conversion of data type ...
mystruct.value = values

Load Multiple .mat Files to Matlab workspace

I'm trying to load several .mat files to the workspace. However, they seem to overwrite each other. Instead, I want them to append. I am aware that I can do something like:
S=load(file1)
R=load(file2)
etc.
and then append the variables manually.
But there's a ton of variables, and making an append statement for each one is extremely undesirable (though possible as a last resort). Is there some way for me to load .mat files to the workspace (by using the load() command without assignment) and have them append?
Its not entirely clear what you mean by "append" but here's a way to get the data loaded into a format that should be easy to deal with:
file_list = {'file1';'file2';...};
for file = file_list'
loaded.(char(file)) = load(file);
end
This makes use of dynamic field references to load the contents of each file in the list into its own field of the loaded structure. You can iterate over the fields and manipulate the data however you'd like from here.
It sounds like you have a situation in which each file contains a matrix variable A and you want to load into memory the concatenation of all these matrices along some dimension. I had a similar need, and wrote the following function to handle it.
function var = loadCat( dim, files, varname )
%LOADCAT Concatenate variables of same name appearing in multiple MAT files
%
% where dim is dimension to concatenate along,
% files is a cell array of file names, and
% varname is a string containing the name of the desired variable
if( isempty( files ) )
var = [];
return;
end
var = load( files{1}, varname );
var = var.(varname);
for f = 2:numel(files),
newvar = load( files{f}, varname );
if( isfield( newvar, varname ) )
var = cat( dim, var, newvar.(varname) );
else
warning( 'loadCat:missingvar', [ 'File ' files{f} ' does not contain variable ' varname ] );
end
end
end
Clark's answer and function actually solved my situation perfectly... I just added the following bit of code to make it a little less tedious. Just add this to the beginning and get rid of the "files" argument:
[files,pathname] = uigetfile('*.mat', 'Select MAT files (use CTRL/COMM or SHIFT)', ...
'MultiSelect', 'on');
Alternatively, it could be even more efficient to just start with this bit:
[pathname] = uigetdir('C:\');
files = dir( fullfile(pathname,'*.mat') ); %# list all *.mat files
files = {files.name}'; %# file names
data = cell(numel(files),1); %# store file contents
for i=1:numel(files)
fname = fullfile(pathname,files{i}); %# full path to file
data{i} = load(fname); %# load file
end
(modified from process a list of files with a specific extension name in matlab).
Thanks,
Jason

Save mat file from MATLAB

I want to save variables in a loop with different image names, like
for i = 1:length(imagefile)
name = imagefile{i};
var = rand(100); % Just for example
save name var
end
It will save var as name, but how do I save it with a value of name, for example Canon101?
Sayyad, you don't have to use eval. You can simply use the function form of save, i.e., save(filename,variables). This will use the value of filename. Remember that the variables need to be entered as strings. So, in your example, it would be
save(name,'var')