In an assignment A(I) = B, the number of elements in B and I must be the same. (For Loop)

Hello, I am getting the error in the title with this code
EDU>> for i=1:6
note(i)=[3,2,1,3,2,1];
xtemp=[];
x=[xtemp note(i)];
end
Outside for loop note = [ sin wave, sin wave, sin wave here] replace sin wave with an actual sin wave which is my code.
I do not understand what is going on. i goes from 1-6 so it has 6 elements and i put 6 numbers inside note(i).
Help would be appreciated.

Réponses (2)

Star Strider
Star Strider le 10 Août 2012
Modifié(e) : Star Strider le 10 Août 2012
I'm not quite sure what you want to do, so I'll take a guess.
One problem with the code you posted is that:
note(i)=[3,2,1,3,2,1];
assigns a vector of six values to a single scalar element of vector note. That won't work.
In these lines in your loop:
xtemp=[];
x = [xtemp note(i)];
the first line will reset xtemp to an empty matrix on every iteration of the loop. In the second line, variable x will continuously overwrite its previous value and will (because of the first line) concatanate note(i) with an empty xtemp instead of the previous values of xtemp.
With respect to your loop, I suggest these changes:
xtemp=[];
for ki=1:6
note(:,ki) = [3,2,1,3,2,1]';
xtemp = [xtemp note(:,ki)];
end
When you concatanate vectors to form matrices, be sure your vectors are the orientation (as column or row vectors) you want them. In my code here, I specified that note is a matrix of column vectors. I'm not quite sure what you are doing, but this seems to match with the code you posted. If you want a 1 x 36 vector of repeating [3,2,1,3,2,1] vectors, I refer you to the repmat function.
It's also worth mentioning that xtemp will be a [6 x 21] matrix, while note (in the code I suggested) will be a [6 x 6] matrix.

19 commentaires

Subscripted assignment dimension mismatch. was the error I got when I tried your first solution.
Below is a long array of what is supposed to be a 1x3 array.
note=[.346*sin(2*pi*261.626*[0:.000125:8])+ .0628 *sin(2*2*pi*261.626*[0:.000125:8])+ .0616*sin(3*2*pi*261.626*[0:.000125:8])+ .1073*sin(4*2*pi*261.626*[0:.000125:8])+ .0802*sin(5*2*pi*261.626*[0:.000125:8]),.346*sin(2*pi*293.665*[0:.000125:8])+ .0628 *sin(2*2*pi*293.665*[0:.000125:8])+ .0616*sin(3*2*pi*293.665*[0:.000125:8])+ .1073*sin(4*2*pi*293.665*[0:.000125:8])+ .0802*sin(5*2*pi*293.665*[0:.000125:8]), .399*sin(2*pi*329.628*[0:.000125:8])+ .1257 *sin(2*2*pi*329.628*[0:.000125:8])+ .2617*sin(3*2*pi*329.628*[0:.000125:8])+ .0868*sin(4*2*pi*329.628*[0:.000125:8])+ .0410*sin(5*2*pi*329.628*[0:.000125:8])+ .0410*sin(6*2*pi*329.628*[0:.000125:8])];
As you can see here by my earlier definition of note, I was trying to make an array of 3 notes. But somehow, it becomes a 1x192003 double.
I'm trying to do this so that when my for loop runs, it calls one of the three notes in this array, through the numbers 1-3.
Watch out for matrix multiplication (the "*" operator) versus element-by-element multiplication (the ".*" operator).
If you already defined note in your code and then tried the code I posted earlier further down in your code, the reason you got a subscript assignment dimension mismatch is that note already existed. Renaming note to noten to avoid that problem, my code does what I intended it to, according to the original code segment you posted:
xtemp=[];
for ki=1:6
noten(:,ki) = [3,2,1,3,2,1]';
xtemp = [xtemp noten(:,ki)];
end
The noten and xtemp arrays are the same.
Remember that note has 1 row and 192003 columns, so that no matter how you orient note, it is not going to be compatible with the assignment in the loop you posted.
I am still a bit lost. Now that I know that note is composed of sine functions, I plotted a spectrogram of note and discovered that it is a 6-component signal, some of the frequencies of which change from segment to segment.
Here is what I did to create a [6 x 3200] double matrix from it (that I called note6):
notelen = fix(length(note)/6);
for k1 = 1:6
note6(k1,:) = note([1:notelen]+(k1-1)*notelen);
end
Is this what you want to do?
I figured out that you intend a sample rate of 8000 Hz, so I tried this:
for k1 = 1:6
soundsc(note6(k1,:),8000)
end
with pleasant results.
I have no idea what you mean by wanting your result to be a [1 x 3] array. The best you could hope for is a [3 x 96000] array.
I tried your 6x3200 matrix, and it played C,C,D,D,E,E. Can you explain how you did that? I do not understand the syntax of your solution, and I would like to synthesize a very long song with this basic solution.
I deleted that code from my test script so I can't reproduce it (it's been over a week), but I'll do my best to describe what I did. I'm not sure precisely what you're asking, so I'll go into some detail.
First, when I discovered from the spectrogram plot that your note vector contained 6 separate tones of approximately equal length, I took the one long vector of note and divided it up into a [6 x 3200] matrix with this code:
notelen = fix(length(note)/6);
for k1 = 1:6
note6(k1,:) = note([1:notelen]+(k1-1)*notelen);
end
The notelen variable determines the row length (number of columns) in note6. In order to be sure it was an integer number and didn't contain any fractional parts (MATLAB doesn't like fractional indices), I used the fix function.
This line:
note6(k1,:) = note([1:notelen]+(k1-1)*notelen);
is a bit harder to describe. In order to be sure each row of note6 had sequential values of note, I selected sections of note that were notelen elements long, and on each iteration of the loop incremented the start of that subscript by multiplying it by k1, the index value of the loop. Since I wanted to be sure I started at the beginning of note, the initial value of the multiplier, (k1-1)*notelen was 0, and the last was 5. If you run the code and look specifically at the value of (k1-1)*notelen, you will see how that works.
Second, as far as playing the notes, that was the easy part. I simply iterated through note6 and used soundsc. I refer you to the documentation on soundsc for details. As far as guessing about the 8000 Hz sample frequency, I noted by looking at your code that every sin argument contained 0.000125.
Does this answer your question? I apologize if I got a bit too detailed and basic, but I wasn't sure what answer you wanted. I'll keep this open for a few hours in case you have any further questions.
Sorry, I am still confused about the coding. I understand it is playing 6 notes in succession because of 1:6. But how come it is playing in the order of 1st note, 1st note, 2nd note, 2nd note, 3rd note, 3rd note?
That's the way I have it set up. To play it in the [ 3 2 1 3 2 1] order, change the loop to:
for k1 = [3 2 1 3 2 1]
soundsc(note6(k1,:),8000)
end
I just now tried that and it sounded correct.
--------------------------
I found this information serendipitously the other day. I coded it for fun and decided to share it with you, since it seems relevant:
fprintf(1,'\n\n\tEqually-Tempered Scale:\n')
noteltr = {'A' 'A#' 'B' 'C' 'C#' 'D' 'D#' 'E' 'F' 'F#' 'G' 'G#'};
notefrq = 440 * 2.^([0:11]/12);
for k1 = 1:size(notefrq,2)
fprintf(1,'\n\t\tNow playing note %s\n', char(noteltr(k1)))
note1(k1,:) = sin(2*pi* [1:6144]/8192 * notefrq(k1));
soundsc(note1(k1,:), 8192)
end
fprintf(1,'\n\n')
It may make what you want to do a bit easier.
And for an encore ...
fprintf(1,'\n\t')
for k1 = [3 3 10 10 12 12 10 10 8 8 7 7 5 5 3]
fprintf(1,' %s ', char(noteltr(k1)) )
soundsc(note1(k1,:), 8192)
end
fprintf(1,'\n\n')
Have fun!
I tried the for k1 = [3 2 1 3 2 1] soundsc(note6(k1,:),8000) end
but somehow, the sound that plays is D,C,C,D,C,C.
Now that I have some idea of what you want to do, try this:
notelen = fix(length(note)/3);
for k1 = 1:3
note3(k1,:) = note([1:notelen] + (k1-1)*notelen);
end
for k1 = [3 2 1 3 2 1]
soundsc(note3(k1,:), 8000)
end
Does that do what you want it to? (It sounds good to me.)
I also wrote you a script that will generate the full Equally-Tempered Scale and play whatever you want. I even provided a demonstration of how to do that.
I don't completely understand, but I now know how to build onto your formula with more notes. Thanks.
Also, do you know how to put the for loop into a wav file?
Another thing that is bugging me, but I'm not sure if it can be easily solved. After each note, there is a slight pause. Is there a way to remove that pause?
My pleasure to help!
I'm not sure what you mean by ‘put the for loop in a wav file’. If you want to create a vector of continuous notes, do this:
catnote = [];
for k1 = [3 2 1 3 2 1]
catnote = [catnote note3(k1,:)];
end
soundsc(catnote, 8000)
This also removes the pause between the notes. You can create a wav file out of catnote or whatever you want to call your array. (I called it catnote because it concatanates the notes into one vector.)
Hello again. I have been working on my piece of music using your formulas. And i've gotten to understand them better. I've added more notes to the formula, and have gotten it to work. However, when I add a note that lasts a different duration, the notelen formula > notelen = fix(length(note)/(# of notes here);does not work, because it evenly divides the notes in the note array by the number of notes to obtain each individual note. Thus, it does not seperate the notes properly when I for example add a note of duration .8 seconds instead of 8 seconds. Is there a way around this? Thanks again.
There probably is not a way around it as you have written your intial code. My code divided your 3-note vector into 3 different notes so you could play them in whatever order you wanted to. If you want to play notes of different lengths, you may have to create them in a loop.
For example, here is what I did just now to improve on the song my previous little routine created:
% notefrq = 440 * 2.^([0:11]/12); % I incorporated this
% into ‘notecreate’ but include it here for reference
tones = [3 3 10 10 12 12 10 8 8 7 7 5 5 3]';
durations = [6000 6000 6000 6000 6000 6000 12000 6000 6000 6000 6000 6000 6000 12000]';
song = [];
for k1 = 1:size(tones,1)
notecreate = @(frq,dur) sin(2*pi* [1:dur]/8192 * (440*2.^((frq-1)/12)));
song = [song; notecreate(tones(k1),durations(k1))'; zeros(750,1)];
end
soundsc(song,8192)
It took some experimenting to get the rests between the notes to sound correct (the zeros(750,1) vectors), so you will also have to experiment.
I understand your new formula. But I cannot implement it to my notes. Since each note I used has a varying multitude of frequency sin-waves, I cannot compose a general notecreate formula like you did. Is there a way to maybe initialize a dummy variable (for duration) in each note that could somehow be changed while the for loop runs? In other words, could I try setting the dummy variable to durations(k1) throughout the loop?
I am again not certain that I understand what you want to do. You can certainly set durations to a constant outside the loop, so it will be the same for all notes. If you do that, remove the (k1) subscript from durations. However if you want to vary it within the loop, simply set up a nested loop inside the k1 loop, then create a second k2 loop, something like this:
for k1 = 1:size(tones,1)
for k2 = 1:notelen
notecreate = @(frq,dur) sin(2*pi* [1:dur]/8192 * (440*2.^((frq-1)/12)));
song = [song; notecreate(tones(k1),durations(k2))'; zeros(750,1)];
end
end
You will have to define notelen outside the loop.
Allow me to clarify myself. //song is the array that decides which notes are played in what order //duration is how long it will play each note //b8 is the duration variable which I have initialized in each note's formula. //note15 contains the formula of the notes
mysong=[];
EDU>> for k1=1:6
song =[1 2 3 4 5 6];
duration=[8 5 4 3 2 1];
b8=duration(k1);
mysong=[mysong note15(song(k1),:)];
end
I am trying to define what the duration of each note will be during the for loop. However, it somehow does not change the duration to the durations in the duration array. It remains the same as the initialized value.
Without knowing the code for your note15 function, I cannot tell with any certainty what the problem is. However in your line:
mysong=[mysong note15(song(k1),:)];
you do not appear to be passing it the value of b8 that you specify in your loop.
I simply let note15 be for k1=1:6 note15(k1,:) = note([1:notelen]+(k1-1)*notelen); end And I defined note as 6 notes of equal length. But I let their total duration be a variable named b8 which I initialized as 8.
I tried seeing if the loop changes b8, and it does. But you were right, it still does not pass it to the note15. Is there a way to do so? Thanks again.
You have to write your note15 function to accept note and b8 as inputs.
I decided to write an example function for you to experiment with.
Try this example code:
Notes = [3 3 10 10 12 12 10 8 8 7 7 5 5 3]';
Durns = [1; 1; 1; 1; 1; 1; 2; 1; 1; 1; 1; 1; 1; 2]*0.35;
Song = [];
for k1 = 1:12
Song = [Song; Note(Notes(k1),Durns(k1)); zeros(250,1)];
end
soundsc(Song, 8192)
with this function:
function y = Note(Frq,Dur)
% FRQ is an integer referencing a particular frequency in the ‘Freq’ array
% DUR is the duration of each note in seconds
% ©StarStrider 2012 09 12
Ampl = [0.346; 0.0628; 0.0616; 0.1073; 0.0802];
Mult = [1:5]';
Freq = 220 * 2.^([0:11]/12);
Note = zeros(1,length([1:Dur*8192]));
for k2 = 1:5
NoteV = Ampl(k2) .* sin(2*pi*Mult(k2)*Freq(Frq)*[1:Dur*8192]/8192);
Note = Note + NoteV;
end
y = Note';
return
First, copy the function to a blank script and save it to the same directory you have the rest of your music files in. Experimnent with it to see how it works. It produces the notes you used earlier (that correspond to notes 4, 6, and 8 in my function), as well as the rest of the scale. It requires a function m-file because it is too complicated for an anonymous function.
It worked well for me, and sounds good with the little song I tried. You will have to write your own routine to fill in whatever pauses you want between notes, and of course their durations. My code should get you started.

Connectez-vous pour commenter.

maybe you want do this
xtemp=[];
for i=1:6
note(i,:)=[3,2,1,3,2,1];
xtemp=[xtemp note(i)];
end

Question posée :

le 9 Août 2012

Community Treasure Hunt

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

Start Hunting!

Translated by