jeudi 23 juillet 2015

Matlab: randomly breaking a pattern with the insertion of an element then continuing

Matlab question:

I'm going to need to start with some context..

The rows of a matrix that I've created contains groups of 4 numbers that each represent musical notes, and all 4 together are related as they form musical chords. You don't need to understand anything about music for this question, but it is important to know that each row is an entity comprised of 4 connected elements. e.g.

76    72    67    52
60    67    64    43
65    69    72    45
74    77    71    53
67    72    64    40
65    60    69    36
72    69    64    40
69    72    76    45
71    67    64    40
71    77    74    53
65    74    69    45
69    65    74    45
77    74    69    45
65    69    72    41
71    74    67    43
64    67    72    48
72    64    69    40
65    69    62    38
64    72    69    48
60    65    69    36
71    76    67    47
64    72    67    40
65    71    74    41
76    79    71    52
65    69    74    41
69    65    60    41
71    76    79    47
79    76    71    47

Lets say that the list that this example comes from is called 'matrix_A,' I then turn this into a single row called 'MIDI' as follows:

A = matrix_A'; %lists final_chords by column
MIDI = A(:) % results in a long column list
MIDI = MIDI' % to turn the list into a row

A toolbox called miditoolbox will turn a list of numbers into a matrix that can be printed as a MIDI file (which means: it will turn it into a file that a computer can play as music). You don't need to know anything about how it works other than it creates an output that looks something like this (the numbers in this example don't match up to the example above)

620.4164    0.4167    1.0000   62.0000  100.0000  372.2500    0.2500
620.8331    0.4167    1.0000   67.0000  100.0000  372.5000    0.2500
621.2498    0.4167    1.0000   47.0000  100.0000  372.7500    0.2500
621.6664    0.4167    1.0000   64.0000  100.0000  373.0000    0.2500
622.0831    0.4167    1.0000   69.0000  100.0000  373.2500    0.2500
622.4998    0.4167    1.0000   72.0000  100.0000  373.5000    0.2500
622.9164    0.4167    1.0000   45.0000  100.0000  373.7500    0.2500
623.3331    0.4167    1.0000   76.0000  100.0000  374.0000    0.2500
623.7498    0.4167    1.0000   71.0000  100.0000  374.2500    0.2500
624.1664    0.4167    1.0000   67.0000  100.0000  374.5000    0.2500
624.5831    0.4167    1.0000   52.0000  100.0000  374.7500    0.2500
624.9997    0.4167    1.0000   71.0000  100.0000  375.0000    0.2500
625.4164    0.4167    1.0000   62.0000  100.0000  375.2500    0.2500
625.8331    0.4167    1.0000   65.0000  100.0000  375.5000    0.2500
626.2497    0.4167    1.0000   38.0000  100.0000  375.7500    0.2500
626.6664    0.4167    1.0000   77.0000  100.0000  376.0000    0.2500
627.0831    0.4167    1.0000   69.0000  100.0000  376.2500    0.2500
627.4997    0.4167    1.0000   74.0000  100.0000  376.5000    0.2500
627.9164    0.4167    1.0000   50.0000  100.0000  376.7500    0.2500
628.3331    0.4167    1.0000   64.0000  100.0000  377.0000    0.2500
628.7497    0.4167    1.0000   67.0000  100.0000  377.2500    0.2500
629.1664    0.4167    1.0000   71.0000  100.0000  377.5000    0.2500
629.5831    0.4167    1.0000   40.0000  100.0000  377.7500    0.2500

In this matrix, each column refers to the following (don't let the musical terminology put you off, it's not important to my question):

  1. ONSET (BEATS) - Which beat (time is divided here into 'beats' rather than seconds etc) the musical pitch in question starts on
  2. DURATION (BEATS) - How long this pitch lasts for (in beats)
  3. MIDI channel - Which channel, of a choice of 2, the note should be played through
  4. MIDI PITCH - what musical pitch will it result in (specified in MIDI numbers (i.e. the notes are assigned numbers)
  5. VELOCITY - how loud this musical pitch should be
  6. ONSET (SEC) Essentially the same as 'onset (beats)' but now specifying how long the beat is in seconds (don't worry too much about this)
  7. DURATION (SEC) Essentially the same as 'duration (beats)' but now specifying how long the beat is in seconds (again, don't worry too much about this)

To turn each of the 4 element rows from the original matrix (now a row vector) into musical chords I need them to each have the same note onset and duration (with the first one starting at an onset value of 0). To give each group of 4 the same note onset I've done the following:

g = (length(MIDI)/4)-1 % divides the length of the vector MIDI by 4 and then 
%takes away 1 as we start from a note onset of 0

note_onset=repmat(0:g,4,1); % for the numbers from 0 to (length(MIDI)/4)-1  repeat        
% each number 4 times before going on to the next number
note_onset=note_onset(:)
MIDI(: , 1) = note_onset % sets the note onset (every group of 4 notes is assigned
% the same note onset in order to create simultaneous chords) 

To give each 'MIDI PITCH' value the same duration of '1' I've done the following (technically each note already had the same duration in the MIDI matrix, however '1' is a more straightforward number, and results in a neater looking score if you choose to read the file in musical notation software):

MIDI(: , 2) = 1 % sets the duration for every note to 1 beat

However.... here (finally.. sorry) is my question:

At random points between these 4-musical-note groups (simultaneously sounding musical chords, each represented in the matrix as 4 rows where the 'MIDI PITCH' values tell us the 4 musical notes in each musical chord, and the corresponding 'ONSET (BEATS)' (for any given one of these groups of 4 musical notes) for all 4 values is the same) I would like to:

• insert the 'MIDI PITCH' number '69' in the 'MIDI PITCH' Column

• In the corresponding 'ONSET (BEATS)' column, this inserted '69' should be both preceded and followed by, lets say, 5 beats of silence, which we can do by:

  • N.B. 'ONSET (BEATS)' currently follows the pattern 0000111122223333...nnnn. To achieve 5 beats of silence before the value that corresponds to the inserted 'MIDI PITCH' number '69' we'd need to set this corresponding value to 'the previous value'+5

  • To achieve 5 beats of silence after the value that corresponds to the inserted 'MIDI PITCH' number '69' we'd need the remaining values in the 'ONSET (BEATS)' column to be added to ['the ONSET (BEATS) value corresponding to the inserted 69'+5].

Each insertion should result in changes in the 'ONSET (BEATS)' column that look something like this:

0
0
0
0
1
1
1
1
2
2
2
2
7 (this is the note onset for the inserted 69 MIDI PITCH number
12 (this is the note onset to set back into action the rest of the sequence)
12
12
12
13
13
13
13

• for every insertion of 'MIDI PITCH' 69 I'd also like to change the corresponding value in 'MIDI channel' column to the '2'

• Finally for each segment of the 'MIDI' matrix that is between each inserted 'MIDI PITCH' number 69, I would like to be able to add to the'MIDI PITCH' values a random number between, let's say, 1 and 12 (whichever random number is added should be added to entirety of any given segment, but the number added to each different segment should be random (i.e. one segment of the 'MIDI PITCH' column might be added to the random number 2, then following this there will be an inserted '69' (as per the above), then following this there will be another segment - this next segment might be added to the random number 5, then following this there will be an inserted '69' etc etc...))

Sorry for the slightly lumbering question.. can anyone help me with that?

Aucun commentaire:

Enregistrer un commentaire