-
Notifications
You must be signed in to change notification settings - Fork 0
Sequence Editing
Finding and replacing parameter changes uses the JavaScript iterator protocol.
search = phrase.find(param, minValue, maxValue, changeTypes, begin, from, to, reverse)
Where search
is an iterator, param
is a parameter number (Synth.Param.
xxx), minValue
is the smallest value to search for and maxValue
is the largest value to find. To find changes that set the parameter to one specific value make minValue
and maxValue
the same value. To search for all changes with values greater than or equal to some particular value set maxValue
to undefined
. To search for all changes with values less than or equal to some particular value set minValue
to undefined
. To search for all changes made to the parameter irrespective of the values it's changed to set both minValue
and maxValue
to undefined
.
changeTypes
is a Set
of Change Types. You must specify which change types the search should match against. There are some predefined sets for denoting common groups of change types.
Set of Change Types | Individual Change Types Contained Within this Set |
---|---|
Synth.ChangeTypes.SET |
Synth.ChangeType.SET |
Synth.ChangeTypes.NONE |
Synth.ChangeType.NONE |
Synth.ChangeTypes.ABSOLUTE |
Synth.ChangeType.SET , Synth.ChangeType.LINEAR , Synth.ChangeType.EXPONENTIAL
|
Synth.ChangeTypes.DELTA |
Synth.ChangeType.DELTA , Synth.ChangeType.DELTA + Synth.ChangeType.LINEAR , Synth.ChangeType.DELTA + Synth.ChangeType.EXPONENTIAL
|
Synth.ChangeTypes.MULTIPLY |
Synth.ChangeType.MULTIPLY , Synth.ChangeType.MULTIPLY + Synth.ChangeType.LINEAR , Synth.ChangeType.MULTIPLY + Synth.ChangeType.EXPONENTIAL
|
Synth.ChangeTypes.ALL |
Synth.ChangeType.SET , Synth.ChangeType.MARK , Synth.ChangeType.LINEAR , Synth.ChangeType.EXPONENTIAL , Synth.ChangeType.DELTA , Synth.ChangeType.DELTA + Synth.ChangeType.LINEAR , Synth.ChangeType.DELTA + Synth.ChangeType.EXPONENTIAL , Synth.ChangeType.MULTIPLY , Synth.ChangeType.MULTIPLY + Synth.ChangeType.LINEAR , Synth.ChangeType.MULTIPLY + Synth.ChangeType.EXPONENTIAL
|
The from
and to
parameters determine which block of rows within the phrase is searched. They can be omitted, in which case the entire phrase is searched. The row number denoted by to
can be lower than the row number denoted by from
. The search process will wrap around from the end of the phrase back to the beginning as needed. begin
is the row number from which to begin searching. begin
must refer to a row inside the range of rows denoted by from
and to
. Normally the current row number will increase as the search proceeds (except for when the search wraps around). Setting reverse
to true
searches the rows in the opposite order. The reverse
parameter is optional.
Once we have our iterator we can iterate over the search results.
let result = search.next();
while (!result.done) {
const rowNumber = result.value[0];
const change = result.value[1];
// Do something with the search result...
result = search.next(reverse);
}
The directionality of the search can be changed mid-process if needed.
findAll()
works in a similar way to find()
except that it returns an array containing every match from anywhere within the phrase that matches the search criteria and you don't have to manage the iterator object yourself because it's all handled internally.
// Results is an array of two element arrays.
results = phrase.findAll(param, minValue, maxValue, changeTypes);
The first stage of performing a Find & Replace is almost identical to performing a normal Find operation. However, the iterator's next()
method takes a two element array as its parameter. The first element is a Boolean that determines whether or not to perform replacement for the previous search result and the second element determines whether or not to traverse in the reversed direction.
search = phrase.replaceValues(param, minValue, maxValue, changeTypes, replacement, begin, from, to, reverse);
let result = search.next();
while (!result.done) {
let doReplace = false;
/* Determine if we want to replace the current instance and set doReplace = true; if we do want to perform replacement... */
result = search.next([doReplace, reverse]);
}
replacement
is a single, fixed value that is used to replace all existing values between minValue
and maxValue
.
Going beyond replaceValues()
, it's often useful to be able to search for a range of values and replace different values with a selection of alternative replacements. Various different mappings are supported between the original values and their replacements. Using any of these methods involves following the same essential protocol as I've demonstrated above for replaceValues()
, just using a different method name and some different parameters in place of the replacement
parameter used with replaceValues()
.
Method | Replacement Pattern |
---|---|
replaceValues() |
Replaces with a fixed value |
transposeValues() |
Adds or subtracts a fixed value from the original |
multiplyValues() |
Multiplies the original values by a fixed value |
quantizeValues() |
Rounds values |
randomizeValues() |
Adds random values to the original values |
mirrorValues() |
Flips values using their distance from a central value |
swapValues() |
Replaces value1 with value2 and value2 with value1
|
changeParameter() |
Alters the parameter change to affect a different parameter entirely |
A replace all operation is performed by first obtaining one of the same kinds of iterator as is used with the interactive replacement protocol and then passing the iterator to the Sequencer.replaceAll()
method to complete all possible replacements without further interaction with the user.
search = phrase.replaceValues(param, minValue, maxValue, changeTypes, replacement, begin, from, to);
Sequencer.replaceAll(search);
Two types of data can be copied and pasted, "notes" and "commands" (or both). Broadly speaking, "Notes" includes the pitches, durations, velocities, etc. that is all of the parameter changes necessary to convey the essential primary melodic or harmonic information and "commands" includes everything else. The commands convey most of the timbre information, although switching to a different instrument is considered note information for historical reasons.
There is no technical distinction between "notes" and "commands". Both are simply parameter changes. The distinction is only that some parameter names are considered to contribute to the description of the notes and others are not and are instead collectively called "commands". The distinction is partly logical, partly intuitive, partly historical legacy and partly arbitrary.
These parameters are the ones which are considered notes data by default.
Category | Parameters |
---|---|
Pitch |
NOTES , FREQUENCY , CHORD_PATTERN
|
Triggering |
GATE , VELOCITY
|
Timing | DURATION |
Instrument Selection | INSTRUMENT |
Phrases |
PHRASE , PHRASE_OFFSET , PHRASE_TRANSPOSE
|
According to whatever you feel is appropriate for your application you may reclassify some parameters either to add more note parameters or to demote existing note parameters to command parameters. The object assigned to Sequencer.noteParameters
is a JavaScript Set object which can be edited.
Method | Functionality |
---|---|
clearAll() |
Removes all content from a block of rows, leaving empty rows |
clearCommands() |
Removes all commands from a block, leaving the notes only |
clearNotes() |
Removes notes from a block, leaving only commands |
setLength() |
Shortens or lengthens a phrase by removing rows from or adding empty rows to the end of the phrase |
insertEmpty() |
Inserts some new empty rows at a chosen row position |
clone() |
Copies an entire phrase |
copy() |
Copies a block of rows |
insertAll() |
Adds additional rows to the phrase and pastes copied content into them (notes and commands) |
insertCommands() |
Adds additional rows to the phrase and pastes copied content into them (commands only) |
insertNotes() |
Adds additional rows to the phrase and pastes copied content into them (notes only) |
insertEmpty() |
Adds additional rows to the phrase and leaves them empty (no notes or commands) |
fill() |
Copies a single parameter change and pastes it onto every nth row. |
mergeAll() |
Combines copied rows with a block of rows starting from the current cursor position (preserves both sets of changes as much as possible) |