Class MusicMath
Bulk pitch/velocity/timing operations over a NoteBuffer, plus MIDI
note-name conversions. Timing is in whole-note units.
public static class MusicMath
- Inheritance
-
MusicMath
- Inherited Members
Methods
MidiToNoteName(int)
Convert MIDI pitch to note name (e.g., 60 -> "C4").
public static string MidiToNoteName(int midiPitch)
Parameters
midiPitchint
Returns
NoteNameToMidi(string)
Convert note name to MIDI pitch (e.g., "C4" -> 60).
public static int NoteNameToMidi(string noteName)
Parameters
noteNamestring
Returns
Exceptions
- ArgumentNullException
noteNameis null.
Quantize(NoteBuffer, Rational)
Quantize note start times to a grid (round to nearest grid step, half-way cases round up).
public static void Quantize(NoteBuffer buffer, Rational grid)
Parameters
bufferNoteBuffergridRational
Remarks
Start times only: a note keeps the length it had, so on a grid coarser than the material it still ends off the grid. And notes closer together than one grid step land on the same step and sound together — four sixteenths quantized to a quarter become two pairs — which is what quantizing to that grid means, not a fault in the arithmetic. Choose a grid no coarser than the shortest note that should stay distinct.
Exceptions
- ArgumentNullException
bufferis null.
ScaleVelocity(NoteBuffer, float)
SIMD scaling of velocity, using a portable Vector<T> loop that the JIT widens to the platform's widest vector unit.
The result is clamped into Velocity's documented 0..1 range, so a factor of 2 saturates rather than storing a loudness the type says cannot exist. That makes the operation lossy at the ends: scaling up and back down does not restore the original velocities.
public static void ScaleVelocity(NoteBuffer buffer, float factor)
Parameters
bufferNoteBufferfactorfloat
Exceptions
- ArgumentNullException
bufferis null.- ArgumentException
factoris NaN.
Transpose(NoteBuffer, int)
Adds semitones to every pitch. Results are NOT clamped to the MIDI
0-127 range; callers that need valid MIDI pitches must clamp afterwards.
Rests are left where they are: RestPitch is silence, and silence has no pitch to move. Because that value is reserved, a note transposed exactly onto it reads as a rest from then on — clamp, or transpose back, before analysing a buffer that has been moved below the bottom of the keyboard.
The single-note reading takes the other contract: pitch.Transpose(ChromaticInterval)
throws when the pitch or the result leaves 0-127. This one moves a whole buffer and cannot
stop partway through, so it moves everything and leaves the range to the caller.
public static void Transpose(NoteBuffer buffer, int semitones)
Parameters
bufferNoteBuffersemitonesint
Exceptions
- ArgumentNullException
bufferis null.