In an assignment A(I) = B, the number of elements in B and I must be the same. (For Loop)
Afficher commentaires plus anciens
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.
1 commentaire
Azzi Abdelmalek
le 10 Août 2012
what do you want to get?
Réponses (2)
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
Elton
le 12 Août 2012
Modifié(e) : Walter Roberson
le 12 Août 2012
Walter Roberson
le 12 Août 2012
Watch out for matrix multiplication (the "*" operator) versus element-by-element multiplication (the ".*" operator).
Star Strider
le 12 Août 2012
Modifié(e) : Star Strider
le 12 Août 2012
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.
Elton
le 19 Août 2012
Star Strider
le 19 Août 2012
Modifié(e) : Star Strider
le 19 Août 2012
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.
Elton
le 19 Août 2012
Star Strider
le 19 Août 2012
Modifié(e) : Star Strider
le 20 Août 2012
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!
Elton
le 24 Août 2012
Star Strider
le 24 Août 2012
Modifié(e) : Star Strider
le 24 Août 2012
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.
Elton
le 24 Août 2012
Star Strider
le 24 Août 2012
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.)
Elton
le 2 Sep 2012
Star Strider
le 2 Sep 2012
Modifié(e) : Star Strider
le 2 Sep 2012
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.
Elton
le 6 Sep 2012
Star Strider
le 6 Sep 2012
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.
Elton
le 7 Sep 2012
Star Strider
le 7 Sep 2012
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.
Elton
le 12 Sep 2012
Star Strider
le 12 Sep 2012
Modifié(e) : Star Strider
le 12 Sep 2012
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.
Azzi Abdelmalek
le 19 Août 2012
Modifié(e) : Azzi Abdelmalek
le 12 Sep 2012
maybe you want do this
xtemp=[];
for i=1:6
note(i,:)=[3,2,1,3,2,1];
xtemp=[xtemp note(i)];
end
Catégories
En savoir plus sur Audio and Video Data dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!