Why am I unable to add these elements to an array?

I'm currently working on a project where I am creating music from the intensities of an image, and I'm able to produce the overall sounds through a for loop, but I am running into a new error -- I am trying to take all of these frequencies and write them using audiowrite, but I am getting an error that says "Unable to perform assignment because the size of the left side is 1-by-4096 and the size of the right side is 1-by-8192." I am using code from a previous project where I did something similar in creating an array of sounds, so I don't understand why I am getting this error now.
%% SNIPPET OF CODE FROM MAIN FUNCTION
for currentImage = 1:length(allImgs)
filename = allImgs(currentImage) + ".wav";
img = imread(allImgs(currentImage));
[imGray, histMtx, binEdge, notes, songLength] = mus306GenerateNotes(img);
fs = 44100;
time = 1;
values = 0:1/fs:time;
rate = 32768;
for i = 1:songLength
currentNote = notes(i);
singleNote = mus306NoteFinder(currentNote);
[currentOct, ~] = mus306NoteFinder2(currentNote);
octaves(i) = currentOct;
finalNotes(i) = singleNote;
end
secondImg = img;
secondImg(:) = ones(size(secondImg)) * 255;
[r,c,~] = size(img);
for i = 1:songLength
noteLength = durations(randi(durationOption));
octToHear = octaves(i);
note = @(t,freq,oct) sin(linspace(0,2*pi*t*freq*2^oct,round(t*rate)));
% noteSound = sin(linspace(0,2*pi*noteLength*finalNotes(i),...
% round(noteLength*rate)));
noteSound = note(noteLength, finalNotes(i), octToHear);
% ERROR IN LINE BELOW: Unable to perform assignment because the
% size of the left side is 1-by-4096 and the size of the right side
% is 1-by-8192. (i can't figure out how to change the color of this
% to red, apologies)
allNotes(i,:) = noteSound;
sound(noteSound, fs)
pause(0.1)
for row = 1:r
for col = 1:c
if (imGray(row, col) == i)
secondImg(row, col,:) = img(row, col, :);
end
end
end
audiowrite(filename, allNotes, fs);
end
%% CUSTOM FUNCTION MUS306GENERATENOTES.M
function [imGray, histMtx, binEdge, notes, songLength] = mus306GenerateNotes(imgToSee)
audibleMin = 200;
audibleMax = 1000;
imGray = rgb2gray(imgToSee);
[histCount, binEdge] = histcounts(imGray(:), 0:255);
histMtx = [binEdge(1:end-1)', histCount'];
figure(1)
notes = histMtx(:, 2);
songLength = length(notes);
for i = 1:songLength
audibleNote = notes(i);
if ((audibleNote / audibleMin) < 1)
audibleNote = audibleNote * 10;
if ((audibleNote / audibleMax) > 1)
audibleNote = audibleNote / 10;
end
elseif (((audibleNote / audibleMax) > 1))
audibleNote = audibleNote / 10;
if ((audibleNote / audibleMin) < 1)
audibleNote = audibleNote * 10;
end
end
notes(i) = audibleNote;
end
end

2 Comments

And the riddle for us is to find out in which line of your code the error happens ?
Apologies, I thought I added in a comment to show where my code is failing. The comment has now been added with the error my system is returning.

Sign in to comment.

 Accepted Answer

noteLength = durations(randi(durationOption));
A duration is randomly selected
note = @(t,freq,oct) sin(linspace(0,2*pi*t*freq*2^oct,round(t*rate)));
A function is constructed in which the size of the output vector depends on the first parameter.
noteSound = note(noteLength, finalNotes(i), octToHear);
The randomly-chosen duration is passed to the function in the slot the determins the length of the output vector. Therefore, noteSound is a random size.
allNotes(i,:) = noteSound;
The randomly-sized vector is written to a complete row of allNotes.
allNotes was not defined before that statement first executes, so that statement is going to succeed the first iteration. However, the next time that the statement executes with a different random length, the number of columns in noteSound (determined by the duration randomly chosen) is not going to match the number of columns in the existing allNotes array.
audiowrite(filename, allNotes, fs);
audiowrite() treats columns as channels. If everything went well then allNotes is a 2D array with rows according to number of notes, and columns containing the sin information for the note. That is clearly the wrong way around: the time series data for notes must be down columns rather than across columns in order for the time series data to be stored properly. If you were to audiowrite passing in allNotes.' then the individual notes would become different channels. You are writing a .wav file and audiowrite supports up to 1024 channels for .wav files.
I doubt this is what you want to do, but since you are constructing 2D arrays of the sine information, then maybe it is...

5 Comments

Oh, I see now. Would it still be possible for me to add the elements if I preallocate the size of allNotes before my loop, or is it still not possible? I really don't understand why I was able to implement this code in a project before and it worked perfectly, but when I try it with this new code it is failing. I can upload the previous project's code for reference if necessary. Thank you for all your help!
Please attach a file for which the code fails. Zip it up if you have to.
I have now attached my file -- thank you!
Before
for i = 1:songLength
insert
allNotes = cell(songLength,1);
Change
note = @(t,freq,oct) sin(linspace(0,2*pi*t*freq*2^oct,round(t*rate)));
to
note = @(t,freq,oct) sin(linspace(0,2*pi*t*freq*2^oct,round(t*rate))) .';
now change
allNotes(i,:) = noteSound;
to
allNotes{i} = noteSound;
Change
audiowrite(filename, allNotes, fs);
to
audiowrite(filename, cell2mat(allNotes), fs);
That worked perfectly!! Thank you so much for all your help!

Sign in to comment.

More Answers (0)

Asked:

on 28 Nov 2023

Commented:

on 28 Nov 2023

Community Treasure Hunt

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

Start Hunting!