Swadge 2024 2.0.0
APIs to develop games for the Magfest Swadge
Loading...
Searching...
No Matches
midiPlayer.h File Reference

Detailed Description

Design Philosophy

This code is provided to play MIDI songs via the DAC speaker. MIDI songs are loaded with midiFileParser.h.

Two system-wide MIDI players are provided by default and can be used to playback BGM and SFX independently. They will automatically be initialized if swadgeMode_t.fnDacCb is NULL. Each MIDI player supports 16 channels and can simultaneously play up to 24 melodic notes and 8 percussion notes, shared across all channels. All 128 General MIDI instruments are supported, as well as the full General MIDI percussion range.

// Load a MIDI file
midiFile_t ode_to_joy;
loadMidiFile("ode.mid", &ode_to_joy, true);
// Play the song on the BGM channel
// Pause both BGM and SFX
globalMidiPauseAll();
// Unpause
globalMidiUnpauseAll();
// Stop and save the player state
void* data = globalMidiSave();
// Restore the player state
// Get a pointer to a particular global MIDI player for advanced usage
// Turn on the sustain pedal for channel 1
midiSustain(player, 0, 0x7F);
// Pitch-bend channel 3 down by one half-step
midiPitchWheel(player, 2, 0x1000);
// Play an A3 note at half velocity on channel 3
midiNoteOn(player, 2, 69, 0x40);
// Turn the note off
midiNoteOff(player, 2, 69, 0x7F);
// Play a drum kit sound at full velocity on channel 10, which is reserved for percussion
midiNoteOn(player, 9, ACOUSTIC_SNARE, 0x7F);
void globalMidiRestore(void *data)
Resume MIDI playback from the state stored in the given pointer. The data will be freed after this ca...
Definition midiFileParser.c:1049
bool loadMidiFile(const char *name, midiFile_t *file, bool spiRam)
Load a MIDI file from the filesystem.
Definition midiFileParser.c:794
void * globalMidiSave(void)
Stop all MIDI playback and return a pointer containing the full playback state. This state must be pa...
Definition midiFileParser.c:1018
Contains information which applies to the entire MIDI file.
Definition midiFileParser.h:84
void midiSustain(midiPlayer_t *player, uint8_t channel, uint8_t val)
Set the hold pedal status.
Definition midiPlayer.c:1811
void globalMidiPlayerPlaySong(midiFile_t *song, uint8_t songIdx)
Play a song on one of the system-wide MIDI players, either BGM or SFX.
Definition midiPlayer.c:2425
void midiPitchWheel(midiPlayer_t *player, uint8_t channel, uint16_t value)
Set the pitch wheel value on a given MIDI channel.
Definition midiPlayer.c:2227
void midiNoteOff(midiPlayer_t *player, uint8_t channel, uint8_t note, uint8_t velocity)
Stop playing a particular note on a given MIDI channel.
Definition midiPlayer.c:1732
midiPlayer_t * globalMidiPlayerGet(uint8_t songIdx)
Return a pointer to the system-wide MIDI player for the given track type, either MIDI_SFX or MIDI_BGM...
Definition midiPlayer.c:2490
void midiNoteOn(midiPlayer_t *player, uint8_t chanId, uint8_t note, uint8_t velocity)
Begin playing a note on a given MIDI channel.
Definition midiPlayer.c:1488
#define MIDI_BGM
Definition midiPlayer.h:83
@ ACOUSTIC_SNARE
Definition midiPlayer.h:172
#define MIDI_SFX
Definition midiPlayer.h:81
Tracks the state of the entire MIDI apparatus.
Definition midiPlayer.h:638

Go to the source code of this file.

Data Structures

struct  envelope_t
 Describes the characteristics of a particular timbre while. More...
 
struct  timbreEffects_t
 
struct  midiTimbre_t
 Defines the sound characteristics of a particular instrument. More...
 
struct  midiVoice_t
 Tracks the state of a single voice, playing a single note. More...
 
struct  voiceStates_t
 Holds several bitfields that track the state of each voice for fast access. This may be used for dynamic voice allocation, and to minimize the impact of note stealing if we run out of voices. More...
 
struct  midiChannel_t
 Tracks the state of a single MIDI channel. More...
 
struct  midiPlayer_t
 Tracks the state of the entire MIDI apparatus. More...
 
union  midiTimbre_t.__unnamed7__
 
struct  midiTimbre_t.__unnamed7__.__unnamed9__
 
struct  midiTimbre_t.__unnamed7__.sample
 
union  midiTimbre_t.__unnamed7__.sample.__unnamed13__
 The frequency of the base sample to be used when pitch shifting. More...
 
struct  midiTimbre_t.__unnamed7__.sample.__unnamed13__.__unnamed15__
 
struct  midiTimbre_t.__unnamed7__.sample.__unnamed13__.config
 
struct  midiTimbre_t.__unnamed7__.percussion
 
union  midiVoice_t.__unnamed18__
 
struct  midiVoice_t.__unnamed18__.__unnamed20__
 

Macros

#define MIDI_CHANNEL_COUNT   16
 
#define POOL_VOICE_COUNT   24
 
#define PERCUSSION_VOICES   8
 
#define OSC_PER_VOICE   1
 
#define NUM_GLOBAL_PLAYERS   2
 
#define MIDI_SFX   0
 
#define MIDI_BGM   1
 
#define MAX_VOLUME   13
 
#define MIDI_TRUE   0x7F
 
#define MIDI_FALSE   0x00
 
#define MIDI_TO_BOOL(val)   (val > 63)
 
#define BOOL_TO_MIDI(val)   (val ? MIDI_TRUE : MIDI_FALSE)
 
#define MIDI_DEF_HEADROOM   0x2666
 
#define PITCH_BEND_CENTER   0x2000
 
#define SAMPLES_TO_MIDI_TICKS(n, tempo, div)   ((n) * 1000000 * (div) / DAC_SAMPLE_RATE_HZ / (tempo))
 Convert the sample count to MIDI ticks.
 
#define SAMPLES_TO_MS(samp)   (((samp) * 1000) / DAC_SAMPLE_RATE_HZ)
 Convert samples to milliseconds.
 
#define SAMPLES_TO_US(samp)   (((samp) * 1000000) / DAC_SAMPLE_RATE_HZ)
 Convert samples to microseconds.
 
#define MS_TO_SAMPLES(ms)   ((ms) * DAC_SAMPLE_RATE_HZ / 1000)
 Calculate the number of DAC samples in the given number of milliseconds.
 
#define MIDI_TICKS_TO_US(ticks, tempo, div)   (int64_t)((int64_t)((int64_t)(ticks) * (int64_t)(tempo)) / ((int64_t)(div)))
 Convert MIDI ticks to microseconds.
 

Typedefs

typedef void(* songFinishedCbFn) (void)
 Callback function used to provide feedback when a song finishes playing.
 
typedef int8_t(* percussionFunc_t) (percussionNote_t drum, uint32_t idx, bool *done, uint32_t scratch[4], void *data)
 A function that returns samples for a percussion timbre rather than a melodic one.
 
typedef void(* midiTextCallback_t) (metaEventType_t type, const char *text, uint32_t length)
 A function to handle text meta-messages from playing MIDI files.
 
typedef bool(* midiStreamingCallback_t) (midiEvent_t *event)
 A function to return MIDI events in streaming mode.
 

Enumerations

enum  midiPlayerMode_t { MIDI_STREAMING , MIDI_FILE }
 Represents the source of MIDI data. More...
 
enum  timbreType_t { WAVETABLE , SAMPLE , NOISE , WAVE_SHAPE }
 The sample source for an instrument. More...
 
enum  timbreFlags_t { TF_NONE = 0 , TF_PERCUSSION = 1 , TF_MONO = 2 }
 A bitfield which may contain various flags for a timbre. More...
 
enum  percussionNote_t {
  ACOUSTIC_BASS_DRUM_OR_LOW_BASS_DRUM = 35 , ELECTRIC_BASS_DRUM_OR_HIGH_BASS_DRUM = 36 , SIDE_STICK = 37 , ACOUSTIC_SNARE = 38 ,
  HAND_CLAP = 39 , ELECTRIC_SNARE_OR_RIMSHOT = 40 , LOW_FLOOR_TOM = 41 , CLOSED_HI_HAT = 42 ,
  HIGH_FLOOR_TOM = 43 , PEDAL_HI_HAT = 44 , LOW_TOM = 45 , OPEN_HI_HAT = 46 ,
  LOW_MID_TOM = 47 , HIGH_MID_TOM = 48 , CRASH_CYMBAL_1 = 49 , HIGH_TOM = 50 ,
  RIDE_CYMBAL_1 = 51 , CHINESE_CYMBAL = 52 , RIDE_BELL = 53 , TAMBOURINE = 54 ,
  SPLASH_CYMBAL = 55 , COWBELL = 56 , CRASH_CYMBAL_2 = 57 , VIBRASLAP = 58 ,
  RIDE_CYMBAL_2 = 59 , HIGH_BONGO = 60 , LOW_BONGO = 61 , MUTE_HIGH_CONGA = 62 ,
  OPEN_HIGH_CONGA = 63 , LOW_CONGA = 64 , HIGH_TIMBALE = 65 , LOW_TIMBALE = 66 ,
  HIGH_AGOGO = 67 , LOW_AGOGO = 68 , CABASA = 69 , MARACAS = 70 ,
  SHORT_WHISTLE = 71 , LONG_WHISTLE = 72 , SHORT_GUIRO = 73 , LONG_GUIRO = 74 ,
  CLAVES = 75 , HIGH_WOODBLOCK = 76 , LOW_WOODBLOCK = 77 , MUTE_CUICA = 78 ,
  OPEN_CUICA = 79 , MUTE_TRIANGLE = 80 , OPEN_TRIANGLE = 81
}
 Defines the MIDI note numbers mapped to by the General MIDI percussion note names. More...
 
enum  midiControl_t {
  MCC_BANK_MSB = 0 , MCC_MODULATION_WHEEL_MSB = 1 , MCC_BREATH_MSB = 2 , MCC_FOOT_PEDAL_MSB = 4 ,
  MCC_PORTAMENTO_TIME_MSB = 5 , MCC_DATA_ENTRY_MSB = 6 , MCC_VOLUME_MSB = 7 , MCC_BALANCE_MSB = 8 ,
  MCC_PAN_MSB = 10 , MCC_EXPRESSION_MSB = 11 , MCC_EFFECT_1_MSB = 12 , MCC_EFFECT_2_MSB = 13 ,
  MCC_GP_SLIDER_1 = 16 , MCC_GP_SLIDER_2 = 17 , MCC_GP_SLIDER_3 = 18 , MCC_GP_SLIDER_4 = 19 ,
  MCC_BANK_LSB = 32 , MCC_MODULATION_WHEEL_LSB = 33 , MCC_BREATH_LSB = 34 , MCC_FOOT_PEDAL_LSB = 36 ,
  MCC_PORTAMENTO_TIME_LSB = 37 , MCC_DATA_ENTRY_LSB = 38 , MCC_VOLUME_LSB = 39 , MCC_BALANCE_LSB = 40 ,
  MCC_PAN_LSB = 42 , MCC_EXPRESSION_LSB = 43 , MCC_EFFECT_1_LSB = 44 , MCC_EFFECT_2_LSB = 45 ,
  MCC_HOLD_PEDAL = 64 , MCC_PORTAMENTO = 65 , MCC_SUSTENUTO_PEDAL = 66 , MCC_SOFT_PEDAL = 67 ,
  MCC_LEGATO_PEDAL = 68 , MCC_HOLD_2_PEDAL = 69 , MCC_SOUND_VARIATION = 70 , MCC_SOUND_TIMBRE = 71 ,
  MCC_SOUND_RELEASE_TIME = 72 , MCC_SOUND_ATTACK_TIME = 73 , MCC_SOUND_BRIGHTNESS = 74 , MCC_SOUND_CONTROL_6 = 75 ,
  MCC_SOUND_CONTROL_7 = 76 , MCC_SOUND_CONTROL_8 = 77 , MCC_SOUND_CONTROL_9 = 78 , MCC_SOUND_CONTROL_10 = 79 ,
  MCC_GP_BUTTON_1 = 80 , MCC_GP_BUTTON_2 = 81 , MCC_GP_BUTTON_3 = 82 , MCC_GP_BUTTON_4 = 83 ,
  MCC_EFFECTS_LEVEL = 91 , MCC_TREMOLO_LEVEL = 92 , MCC_CHORUS_LEVEL = 93 , MCC_DETUNE_LEVEL = 94 ,
  MCC_PHASER_LEVEL = 95 , MCC_DATA_BUTTON_INC = 96 , MCC_DATA_BUTTON_DEC = 97 , MCC_NON_REGISTERED_PARAM_LSB = 98 ,
  MCC_NON_REGISTERED_PARAM_MSB = 99 , MCC_REGISTERED_PARAM_LSB = 100 , MCC_REGISTERED_PARAM_MSB = 101 , MCC_ALL_SOUND_OFF = 120 ,
  MCC_ALL_CONTROLS_OFF = 121 , MCC_LOCAL_KEYBOARD = 122 , MCC_ALL_NOTE_OFF = 123 , MCC_OMNI_MODE_OFF = 124 ,
  MCC_OMNI_MODE_ON = 125 , MCC_MONO_OPERATION = 126 , MCC_POLY_OPERATION = 127
}
 Defines the MIDI continuous controller registers. More...
 
enum  midiManufacturerId_t { MMFR_EDUCATIONAL_USE = 0x807D , MMFR_UNIVERSAL_NON_REAL_TIME = 0x807E , MMFR_UNIVERSAL_REAL_TIME = 0x807F }
 Values that can be directly compared against midiSysexEvent_t::manufacturerId. More...
 

Functions

void midiPlayerInit (midiPlayer_t *player)
 Initialize the MIDI player.
 
void midiPlayerReset (midiPlayer_t *player)
 Reset the MIDI player state.
 
int32_t midiPlayerStep (midiPlayer_t *player)
 Calculate and return the next MIDI sample, stepping the player state forward by one sample.
 
void midiPlayerFillBuffer (midiPlayer_t *player, uint8_t *samples, int16_t len)
 Fill a buffer with the next set of samples from the MIDI player. This should be called by the callback passed into initDac(). Samples are generated at sampling rate of DAC_SAMPLE_RATE_HZ.
 
void midiPlayerFillBufferMulti (midiPlayer_t *players, uint8_t playerCount, uint8_t *samples, int16_t len)
 Fill a buffer with the next set of samples from an array of MIDI players.
 
void midiAllSoundOff (midiPlayer_t *player)
 Stop all sound immediately. This is not affected by the sustain pedal.
 
void midiResetChannelControllers (midiPlayer_t *player, uint8_t channel)
 Reset all controllers on a MIDI channel.
 
void midiGmOn (midiPlayer_t *player)
 Activate General MIDI mode on a MIDI player.
 
void midiGmOff (midiPlayer_t *player)
 Deactivate General MIDI mode on a MIDI player.
 
void midiAllNotesOff (midiPlayer_t *player, uint8_t channel)
 Tun off all notes which are currently on, as though midiNoteOff() were called for each note. This respects the sustain pedal.
 
void midiNoteOn (midiPlayer_t *player, uint8_t channel, uint8_t note, uint8_t velocity)
 Begin playing a note on a given MIDI channel.
 
void midiAfterTouch (midiPlayer_t *player, uint8_t channel, uint8_t note, uint8_t velocity)
 Change the velocity of a note on a given MIDI channel, after the note starts playing.
 
void midiNoteOff (midiPlayer_t *player, uint8_t channel, uint8_t note, uint8_t velocity)
 Stop playing a particular note on a given MIDI channel.
 
void midiSetProgram (midiPlayer_t *player, uint8_t channel, uint8_t program)
 Change the program (instrument) on a given MIDI channel.
 
void midiSustain (midiPlayer_t *player, uint8_t channel, uint8_t val)
 Set the hold pedal status.
 
void midiSustenuto (midiPlayer_t *player, uint8_t channel, uint8_t val)
 Set the sustenuto pedal status.
 
void midiControlChange (midiPlayer_t *player, uint8_t channel, midiControl_t control, uint8_t val)
 Set a MIDI control value.
 
uint8_t midiGetControlValue (midiPlayer_t *player, uint8_t channel, midiControl_t control)
 Get the value of a MIDI control.
 
uint16_t midiGetControlValue14bit (midiPlayer_t *player, uint8_t channel, midiControl_t control)
 Get the combined value of two MIDI control registers.
 
void midiSetParameter (midiPlayer_t *player, uint8_t channel, bool registered, uint16_t param, uint16_t value)
 Set a registered or non-registered parameter value.
 
uint16_t midiGetParameterValue (midiPlayer_t *player, uint8_t channel, bool registered, uint16_t param)
 Get the value of a registered or non-registered parameter.
 
void midiPitchWheel (midiPlayer_t *player, uint8_t channel, uint16_t value)
 Set the pitch wheel value on a given MIDI channel.
 
void midiSetTempo (midiPlayer_t *player, uint32_t tempo)
 Change the MIDI playback tempo.
 
void midiSetFile (midiPlayer_t *player, const midiFile_t *file)
 Configure this MIDI player to read from a MIDI file.
 
void midiPause (midiPlayer_t *player, bool pause)
 Set the paused state of a MIDI song.
 
void midiSeek (midiPlayer_t *player, uint32_t ticks)
 Seek to a given time offset within a file.
 
void initGlobalMidiPlayer (void)
 Initialize the system-wide MIDI players for both BGM and SFX.
 
void deinitGlobalMidiPlayer (void)
 Deinitialize and free memory associated with the system-wide MIDI players.
 
void globalMidiPlayerFillBuffer (uint8_t *samples, int16_t len)
 Fill the given sample buffer with samples from both the BGM and SFX system-wide MIDI players.
 
void globalMidiPlayerPlaySong (midiFile_t *song, uint8_t trackType)
 Play a song on one of the system-wide MIDI players, either BGM or SFX.
 
void globalMidiPlayerPlaySongCb (midiFile_t *song, uint8_t trackType, songFinishedCbFn cb)
 Play a song on noe of the system-wide MIDI players, with a callback once the song finishes.
 
void globalMidiPlayerSetVolume (uint8_t trackType, int32_t volumeSetting)
 Set the volume using a value from 0 to 13.
 
void globalMidiPlayerPauseAll (void)
 Pause all songs currently being played by the system-wide MIDI players.
 
void globalMidiPlayerResumeAll (void)
 Resume all songs currently being played by the system-wide MIDI players.
 
void globalMidiPlayerStop (bool reset)
 Stop all songs currently being played by the system-wide MIDI players, optionally resetting their state to the beginning of the song.
 
void * globalMidiSave (void)
 Stop all MIDI playback and return a pointer containing the full playback state. This state must be passed to globalMidiRestore() later to restore the previous state.
 
void globalMidiRestore (void *data)
 Resume MIDI playback from the state stored in the given pointer. The data will be freed after this call and cannot be reused.
 
midiPlayer_tglobalMidiPlayerGet (uint8_t trackType)
 Return a pointer to the system-wide MIDI player for the given track type, either MIDI_SFX or MIDI_BGM.
 

Data Structure Documentation

◆ envelope_t

struct envelope_t
Data Fields
int32_t attackTime Base time taken to ramp up to full volume.
q24_8 attackTimeVel This value will be multiplied by the note velocity and added to the attack time,.
int32_t decayTime Base time taken for the volume to fade to the sustain volume.
q24_8 decayTimeVel This value will be multiplied by the note velocity and added to the decay time.
int32_t releaseTime Base time it takes to silence the note after release, in DAC samples.
q24_8 releaseTimeVel This value will be multiplied by the note velocity and added to the attack time.
uint8_t sustainVol The base volume of the sustained note, proportional to the sample volume.
q24_8 sustainVolVel This value will be multiplied by the note velocity and added to the attack time.

◆ timbreEffects_t

struct timbreEffects_t
Data Fields
uint8_t chorus The number of chorused voices to mix.

◆ midiTimbre_t

struct midiTimbre_t
Data Fields
timbreType_t type The source of samples for this instrument.
timbreFlags_t flags Flags bitfield for this timbre.
union midiTimbre_t.__unnamed7__ __unnamed__
envelope_t envelope The ASDR characteristics of this timbre.
timbreEffects_t effects Various effects applied to this timbre. May be ignored by percussion timbres.
const char * name The name of this timbre, if any.

◆ midiVoice_t

struct midiVoice_t
Data Fields
uint32_t transitionTicks The number of samples remaining before transitioning to the next state.
uint32_t transitionTicksTotal The number of samples remaining before the next volume adjustment.
uint8_t transitionStartVol The volume at the start of the transition time.
uint8_t targetVol The target volume of this tick.
uint32_t sampleTick The monotonic tick counter for playback of sampled timbres.
uint8_t note The MIDI note number for the sound being played.
uint8_t velocity The MIDI note velocity of the playing note.
uint8_t channel The index of the MIDI channel that owns the currently playing note.
synthOscillator_t oscillators[OSC_PER_VOICE] The synthesizer oscillators used to generate the sounds.
union midiVoice_t.__unnamed18__ __unnamed__
const midiTimbre_t * timbre A pointer to the timbre of this voice, which defines its musical characteristics.

◆ voiceStates_t

struct voiceStates_t
Data Fields
uint32_t on Whether this note is set to on via MIDI, regardless of if it's making sound.
uint32_t attack Bitfield of voices currently in the attack stage.
uint32_t sustain Bitfield of voices currently in the sustain stage.
uint32_t decay Bitfield of voices currently in the decay stage.
uint32_t release Bitfield of voices currently in the release stage.
uint32_t held Bitfield of voices which are being held by the pedal.
uint32_t sustenuto Bitfield of voices which are being held by the sustenuto pedal.

◆ midiChannel_t

struct midiChannel_t
Data Fields
uint16_t volume The 14-bit volume level for this channel only.
uint16_t bank The bank to use for program changes on this channel.
uint8_t program The ID of the program (timbre) set for this channel.
bool registeredParameter Whether selectedParameter represents a registered or non-registered parameter.
uint16_t selectedParameter The ID of the currently selected registered or non-registered parameter.
midiTimbre_t timbre The actual current timbre definition which the program ID corresponds to.
uint32_t allocedVoices A bitmap of which voices have been allocated to this channel.
uint16_t pitchBend The 14-bit pitch wheel value.
bool percussion Whether this channel is reserved for percussion.
bool held Whether notes will be held after release.
bool sustenuto Whether certain notes will be held after release.
bool ignore If set, events on this channel will be completely ignored.

◆ midiPlayer_t

struct midiPlayer_t
Data Fields
uint16_t volume The global 14-bit volume level.
midiChannel_t channels[MIDI_CHANNEL_COUNT] The state of all MIDI channels.
midiVoice_t percVoices[PERCUSSION_VOICES] The voices reserved for percussion.
voiceStates_t percVoiceStates The percussion voice state bitmaps.
uint32_t percSpecialStates A bitmap to track which percussion voices have special notes playing This includes all 3 hi-hats (open, closed, and pedal), short and long whistle and guiro, and mute and open cuica and triangle. This value contains 5 separate 6-bit fields, each of which contains either the index of the voice used by that instrument group (0 to 31) or has all 6 bits set to indicate that the instrument group has no voice allocated.
midiVoice_t poolVoices[POOL_VOICE_COUNT] The global voice pool for non-percussion channels.
voiceStates_t poolVoiceStates The global voice pool state bitmaps.
synthOscillator_t * allOscillators[(POOL_VOICE_COUNT+PERCUSSION_VOICES) *OSC_PER_VOICE] An array holding a pointer to every oscillator.
uint16_t oscillatorCount The total number of oscillators in the allOscillators array.
midiPlayerMode_t mode Whether this player is playing a song or a MIDI stream.
midiFileReader_t reader A MIDI reader to use for file playback, when in MIDI_FILE mode.
midiStreamingCallback_t streamingCallback A callback function to retrieve the next event, when in MIDI_STREAMING mode.
midiTextCallback_t textMessageCallback A callback to call when a text meta-message is received.
songFinishedCbFn songFinishedCallback A callback to call when the playing song is finished.
int32_t headroom The constant value to multiply each frame's samples by, before being shifted right 16 bits This value must be between 0x0000 (muted) and 0x7FFF (100% volume). The default value is 0x2666 (30%), and something around this value should be considered "full volume" with values higher than that being much more likely to clip for louder sounds.
uint32_t clipped Number of samples that were clipped Note: This is not set when using midiPlayerFillBufferMulti()
uint64_t sampleCount The number of samples elapsed in the playing song.
midiEvent_t pendingEvent The next event in the MIDI file, which occurs after the current time.
bool eventAvailable True if pendingEvent is valid, false if it must be updated.
uint32_t tempo The number of microseconds per quarter note.
bool paused True when playback of the current file is paused.
bool seeking True when the MIDI player is seeking, and will not produce sound.
bool loop If true, the playing file will automatically repeat when complete.

◆ midiTimbre_t.__unnamed7__

union midiTimbre_t.__unnamed7__
Data Fields
struct midiTimbre_t.__unnamed7__.__unnamed9__ __unnamed__
struct midiTimbre_t.__unnamed7__.sample sample
struct midiTimbre_t.__unnamed7__.percussion percussion
oscillatorShape_t shape The shape of this wave, when type is RAW_WAVE.

◆ midiTimbre_t.__unnamed7__.__unnamed9__

struct midiTimbre_t.__unnamed7__.__unnamed9__
Data Fields
uint16_t waveIndex The index of this timbre's wave in the table, when type is WAVETABLE.
waveFunc_t waveFunc The function to use to retrieve wavetable samples.

◆ midiTimbre_t.__unnamed7__.sample

struct midiTimbre_t.__unnamed7__.sample
Data Fields
union midiTimbre_t.__unnamed7__.sample.__unnamed13__ __unnamed__ The frequency of the base sample to be used when pitch shifting.
uint32_t rate The sample rate.
uq8_24 baseNote The base frequency, at which the sample plays at normal speed.
uint32_t loop 0 to loop forever, or the number of loops to play

◆ midiTimbre_t.__unnamed7__.sample.__unnamed13__

union midiTimbre_t.__unnamed7__.sample.__unnamed13__

◆ midiTimbre_t.__unnamed7__.sample.__unnamed13__.__unnamed15__

struct midiTimbre_t.__unnamed7__.sample.__unnamed13__.__unnamed15__
Data Fields
const uint8_t * data A pointer to this timbre's sample data.
uint32_t count The length of the sample in bytes.

◆ midiTimbre_t.__unnamed7__.sample.__unnamed13__.config

struct midiTimbre_t.__unnamed7__.sample.__unnamed13__.config
Data Fields
const char * sampleName The name of the sample to load into data.

◆ midiTimbre_t.__unnamed7__.percussion

struct midiTimbre_t.__unnamed7__.percussion
Data Fields
percussionFunc_t playFunc A callback to call for drum data.
void * data User data to pass to the drumkit.

◆ midiVoice_t.__unnamed18__

union midiVoice_t.__unnamed18__
Data Fields
uint32_t percScratch[4] An array of scratch data for percussion functions to use.
struct midiVoice_t.__unnamed18__.__unnamed20__ __unnamed__

◆ midiVoice_t.__unnamed18__.__unnamed20__

struct midiVoice_t.__unnamed18__.__unnamed20__
Data Fields
uint32_t sampleError The number of fractional samples remaining.
uint32_t sampleLoops The number of loops remaining.

Macro Definition Documentation

◆ MIDI_CHANNEL_COUNT

#define MIDI_CHANNEL_COUNT   16

◆ POOL_VOICE_COUNT

#define POOL_VOICE_COUNT   24

◆ PERCUSSION_VOICES

#define PERCUSSION_VOICES   8

◆ OSC_PER_VOICE

#define OSC_PER_VOICE   1

◆ NUM_GLOBAL_PLAYERS

#define NUM_GLOBAL_PLAYERS   2

◆ MIDI_SFX

#define MIDI_SFX   0

◆ MIDI_BGM

#define MIDI_BGM   1

◆ MAX_VOLUME

#define MAX_VOLUME   13

◆ MIDI_TRUE

#define MIDI_TRUE   0x7F

◆ MIDI_FALSE

#define MIDI_FALSE   0x00

◆ MIDI_TO_BOOL

#define MIDI_TO_BOOL ( val)    (val > 63)

◆ BOOL_TO_MIDI

#define BOOL_TO_MIDI ( val)    (val ? MIDI_TRUE : MIDI_FALSE)

◆ MIDI_DEF_HEADROOM

#define MIDI_DEF_HEADROOM   0x2666

◆ PITCH_BEND_CENTER

#define PITCH_BEND_CENTER   0x2000

◆ SAMPLES_TO_MIDI_TICKS

#define SAMPLES_TO_MIDI_TICKS ( n,
tempo,
div )   ((n) * 1000000 * (div) / DAC_SAMPLE_RATE_HZ / (tempo))

Convert the sample count to MIDI ticks.

◆ SAMPLES_TO_MS

#define SAMPLES_TO_MS ( samp)    (((samp) * 1000) / DAC_SAMPLE_RATE_HZ)

Convert samples to milliseconds.

◆ SAMPLES_TO_US

#define SAMPLES_TO_US ( samp)    (((samp) * 1000000) / DAC_SAMPLE_RATE_HZ)

Convert samples to microseconds.

◆ MS_TO_SAMPLES

#define MS_TO_SAMPLES ( ms)    ((ms) * DAC_SAMPLE_RATE_HZ / 1000)

Calculate the number of DAC samples in the given number of milliseconds.

◆ MIDI_TICKS_TO_US

#define MIDI_TICKS_TO_US ( ticks,
tempo,
div )   (int64_t)((int64_t)((int64_t)(ticks) * (int64_t)(tempo)) / ((int64_t)(div)))

Convert MIDI ticks to microseconds.

Typedef Documentation

◆ songFinishedCbFn

typedef void(* songFinishedCbFn) (void)

Callback function used to provide feedback when a song finishes playing.

◆ percussionFunc_t

typedef int8_t(* percussionFunc_t) (percussionNote_t drum, uint32_t idx, bool *done, uint32_t scratch[4], void *data)

A function that returns samples for a percussion timbre rather than a melodic one.

Parameters
drumThe percussion instrument to generate sound for
idxThe monotonic sample index within this note. Will not repeat for any particular note.
[out]doneA pointer to a boolean to be set to 1 when the drum sample is finished playing
[in,out]scratchA pointer to an array of 4 uint32_t that will persist for the duration of the note
dataA pointer to user-defined data which may be used in sample generation

◆ midiTextCallback_t

typedef void(* midiTextCallback_t) (metaEventType_t type, const char *text, uint32_t length)

A function to handle text meta-messages from playing MIDI files.

Parameters
typeThe type of meta-message
textThe message text - NOT NUL-terminated
lengthThe length of the text

◆ midiStreamingCallback_t

typedef bool(* midiStreamingCallback_t) (midiEvent_t *event)

A function to return MIDI events in streaming mode.

Enumeration Type Documentation

◆ midiPlayerMode_t

Represents the source of MIDI data.

Enumerator
MIDI_STREAMING 

Streaming over USB.

MIDI_FILE 

Reading from a midiFileReader_t.

◆ timbreType_t

The sample source for an instrument.

Enumerator
WAVETABLE 

Samples are generated by sampling a particular wave shape.

SAMPLE 
NOISE 
WAVE_SHAPE 

◆ timbreFlags_t

A bitfield which may contain various flags for a timbre.

Enumerator
TF_NONE 

No flags.

TF_PERCUSSION 

This timbre plays percussion sounds (percussionNote_t) rather than melodic notes.

TF_MONO 

This timbre represents a monophonic instrument.

◆ percussionNote_t

Defines the MIDI note numbers mapped to by the General MIDI percussion note names.

Enumerator
ACOUSTIC_BASS_DRUM_OR_LOW_BASS_DRUM 
ELECTRIC_BASS_DRUM_OR_HIGH_BASS_DRUM 
SIDE_STICK 
ACOUSTIC_SNARE 
HAND_CLAP 
ELECTRIC_SNARE_OR_RIMSHOT 
LOW_FLOOR_TOM 
CLOSED_HI_HAT 

This note supersedes any CLOSED_HI_HAT, PEDAL_HI_HAT, or OPEN_HI_HAT notes playing.

HIGH_FLOOR_TOM 
PEDAL_HI_HAT 

This note supersedes any CLOSED_HI_HAT, PEDAL_HI_HAT, or OPEN_HI_HAT notes playing.

LOW_TOM 
OPEN_HI_HAT 

This note supersedes any CLOSED_HI_HAT, PEDAL_HI_HAT, or OPEN_HI_HAT notes playing.

LOW_MID_TOM 
HIGH_MID_TOM 
CRASH_CYMBAL_1 
HIGH_TOM 
RIDE_CYMBAL_1 
CHINESE_CYMBAL 
RIDE_BELL 
TAMBOURINE 
SPLASH_CYMBAL 
COWBELL 
CRASH_CYMBAL_2 
VIBRASLAP 
RIDE_CYMBAL_2 
HIGH_BONGO 
LOW_BONGO 
MUTE_HIGH_CONGA 
OPEN_HIGH_CONGA 
LOW_CONGA 
HIGH_TIMBALE 
LOW_TIMBALE 
HIGH_AGOGO 
LOW_AGOGO 
CABASA 
MARACAS 
SHORT_WHISTLE 

This note supersedes any SHORT_WHISTLE or LONG_WHISTLE notes playing.

LONG_WHISTLE 

This note supersedes any SHORT_WHISTLE or LONG_WHISTLE notes playing.

SHORT_GUIRO 

This note supersedes any SHORT_GUIRO or LONG_GUIRO notes playing.

LONG_GUIRO 

This note supersedes any SHORT_GUIRO or LONG_GUIRO notes playing.

CLAVES 
HIGH_WOODBLOCK 
LOW_WOODBLOCK 
MUTE_CUICA 

This note supersedes any SHORT_GUIRO or LONG_GUIRO notes playing.

OPEN_CUICA 

This note supersedes any SHORT_GUIRO or LONG_GUIRO notes playing.

MUTE_TRIANGLE 

This note supersedes any MUTE_TRIANGLE or OPEN_TRIANGLE notes playing.

OPEN_TRIANGLE 

This note supersedes any MUTE_TRIANGLE or OPEN_TRIANGLE notes playing.

◆ midiControl_t

Defines the MIDI continuous controller registers.

Values suffixed with _MSB and _LSB represent the upper and lower 7 bits of two separate MIDI controller values. Some values are designated as switches, which will be considered off when set between 0 and 63, and on when set from 64 to 127. All other values represent a single 7-bit value with a range of 0 to 127 inclusive unless otherwise specified.

Enumerator
MCC_BANK_MSB 
MCC_MODULATION_WHEEL_MSB 
MCC_BREATH_MSB 
MCC_FOOT_PEDAL_MSB 
MCC_PORTAMENTO_TIME_MSB 
MCC_DATA_ENTRY_MSB 
MCC_VOLUME_MSB 
MCC_BALANCE_MSB 
MCC_PAN_MSB 
MCC_EXPRESSION_MSB 
MCC_EFFECT_1_MSB 
MCC_EFFECT_2_MSB 
MCC_GP_SLIDER_1 
MCC_GP_SLIDER_2 
MCC_GP_SLIDER_3 
MCC_GP_SLIDER_4 
MCC_BANK_LSB 
MCC_MODULATION_WHEEL_LSB 
MCC_BREATH_LSB 
MCC_FOOT_PEDAL_LSB 
MCC_PORTAMENTO_TIME_LSB 
MCC_DATA_ENTRY_LSB 
MCC_VOLUME_LSB 
MCC_BALANCE_LSB 
MCC_PAN_LSB 
MCC_EXPRESSION_LSB 
MCC_EFFECT_1_LSB 
MCC_EFFECT_2_LSB 
MCC_HOLD_PEDAL 
MCC_PORTAMENTO 
MCC_SUSTENUTO_PEDAL 
MCC_SOFT_PEDAL 
MCC_LEGATO_PEDAL 
MCC_HOLD_2_PEDAL 
MCC_SOUND_VARIATION 
MCC_SOUND_TIMBRE 
MCC_SOUND_RELEASE_TIME 
MCC_SOUND_ATTACK_TIME 
MCC_SOUND_BRIGHTNESS 
MCC_SOUND_CONTROL_6 
MCC_SOUND_CONTROL_7 
MCC_SOUND_CONTROL_8 
MCC_SOUND_CONTROL_9 
MCC_SOUND_CONTROL_10 
MCC_GP_BUTTON_1 
MCC_GP_BUTTON_2 
MCC_GP_BUTTON_3 
MCC_GP_BUTTON_4 
MCC_EFFECTS_LEVEL 
MCC_TREMOLO_LEVEL 
MCC_CHORUS_LEVEL 
MCC_DETUNE_LEVEL 
MCC_PHASER_LEVEL 
MCC_DATA_BUTTON_INC 
MCC_DATA_BUTTON_DEC 
MCC_NON_REGISTERED_PARAM_LSB 
MCC_NON_REGISTERED_PARAM_MSB 
MCC_REGISTERED_PARAM_LSB 
MCC_REGISTERED_PARAM_MSB 
MCC_ALL_SOUND_OFF 
MCC_ALL_CONTROLS_OFF 
MCC_LOCAL_KEYBOARD 
MCC_ALL_NOTE_OFF 
MCC_OMNI_MODE_OFF 
MCC_OMNI_MODE_ON 
MCC_MONO_OPERATION 
MCC_POLY_OPERATION 

◆ midiManufacturerId_t

Values that can be directly compared against midiSysexEvent_t::manufacturerId.

Enumerator
MMFR_EDUCATIONAL_USE 
MMFR_UNIVERSAL_NON_REAL_TIME 
MMFR_UNIVERSAL_REAL_TIME 

Function Documentation

◆ midiPlayerInit()

void midiPlayerInit ( midiPlayer_t * player)

Initialize the MIDI player.

Parameters
playerThe MIDI player to initialize

◆ midiPlayerReset()

void midiPlayerReset ( midiPlayer_t * player)

Reset the MIDI player state.

Parameters
playerThe MIDI player to reset

◆ midiPlayerStep()

int32_t midiPlayerStep ( midiPlayer_t * player)

Calculate and return the next MIDI sample, stepping the player state forward by one sample.

Parameters
playerThe player to step forward
Returns
int32_t The next signed 32-bit sample, without any headroom or clipping applied

◆ midiPlayerFillBuffer()

void midiPlayerFillBuffer ( midiPlayer_t * player,
uint8_t * samples,
int16_t len )

Fill a buffer with the next set of samples from the MIDI player. This should be called by the callback passed into initDac(). Samples are generated at sampling rate of DAC_SAMPLE_RATE_HZ.

Parameters
playerThe MIDI player to sample from
samplesAn array of unsigned 8-bit samples to fill
lenThe length of the array to fill

◆ midiPlayerFillBufferMulti()

void midiPlayerFillBufferMulti ( midiPlayer_t * players,
uint8_t playerCount,
uint8_t * samples,
int16_t len )

Fill a buffer with the next set of samples from an array of MIDI players.

Parameters
playersA pointer to an array of MIDI players
playerCountThe number of MIDI players in the array
samplesAn array of unsigned 8-bit samples to fill
lenThe length of the array to fill

◆ midiAllSoundOff()

void midiAllSoundOff ( midiPlayer_t * player)

Stop all sound immediately. This is not affected by the sustain pedal.

Parameters
playerThe player to stop

◆ midiResetChannelControllers()

void midiResetChannelControllers ( midiPlayer_t * player,
uint8_t channel )

Reset all controllers on a MIDI channel.

This includes:

  • Sustain Pedal
  • Legato, Vibrato, Sustenuto, etc.
Parameters
player
channel

◆ midiGmOn()

void midiGmOn ( midiPlayer_t * player)

Activate General MIDI mode on a MIDI player.

Parameters
playerThe MIDI player to set to General MIDI mode

◆ midiGmOff()

void midiGmOff ( midiPlayer_t * player)

Deactivate General MIDI mode on a MIDI player.

Parameters
playerThe MIDI player to take out of General MIDI mode

◆ midiAllNotesOff()

void midiAllNotesOff ( midiPlayer_t * player,
uint8_t channel )

Tun off all notes which are currently on, as though midiNoteOff() were called for each note. This respects the sustain pedal.

Parameters
playerThe MIDI player
channelThe MIDI channel on which to stop notes

◆ midiNoteOn()

void midiNoteOn ( midiPlayer_t * player,
uint8_t channel,
uint8_t note,
uint8_t velocity )

Begin playing a note on a given MIDI channel.

Using a velocity of 0 is equivalent to calling midiNoteOff()

Parameters
playerThe MIDI player
channelThe MIDI channel on which to start the note
noteThe note number to play
velocityThe note velocity which affects its volume and effects

◆ midiAfterTouch()

void midiAfterTouch ( midiPlayer_t * player,
uint8_t channel,
uint8_t note,
uint8_t velocity )

Change the velocity of a note on a given MIDI channel, after the note starts playing.

Parameters
playerThe MIDI player
channelThe MIDI channel on which to change the note velocity
noteThe currently-playing note number to modify
velocityThe note velocity which affects its volume and effects

◆ midiNoteOff()

void midiNoteOff ( midiPlayer_t * player,
uint8_t channel,
uint8_t note,
uint8_t velocity )

Stop playing a particular note on a given MIDI channel.

Parameters
playerThe MIDI player
channelThe MIDI channel on which to stop the note
noteThe note number to stop
velocity[NYI] The release velocity which affects the note's release time

◆ midiSetProgram()

void midiSetProgram ( midiPlayer_t * player,
uint8_t channel,
uint8_t program )

Change the program (instrument) on a given MIDI channel.

Parameters
playerThe MIDI player
channelThe MIDI channel whose program will be changed
programThe program ID, from 0-127, to set for this channel

◆ midiSustain()

void midiSustain ( midiPlayer_t * player,
uint8_t channel,
uint8_t val )

Set the hold pedal status.

When set, all notes that are currently on will be sustained until the pedal is unset, as well as all notes that are played after the pedal is set.

This is a convenience method for midiControlChange(player, channel, MCC_HOLD_PEDAL (64), val ? 127:0)

Parameters
playerThe MIDI player
channelThe MIDI channel to set the hold status for
valThe sustain pedal value. Values 0-63 are OFF, and 64-127 are ON.

◆ midiSustenuto()

void midiSustenuto ( midiPlayer_t * player,
uint8_t channel,
uint8_t val )

Set the sustenuto pedal status.

When set, only the notes that are currently on will be sustained until the pedal is unset. Notes that are played after the pedal is set will not be sustained.

Parameters
playerThe MIDI player
channelThe MIDI channel to set the sustenuto status for
valThe sustenuto pedal value. Values 0-63 are OFF, and 64-127 are ON.

◆ midiControlChange()

void midiControlChange ( midiPlayer_t * player,
uint8_t channel,
midiControl_t control,
uint8_t val )

Set a MIDI control value.

Parameters
playerThe MIDI player
channelThe channel to set the control on
controlThe control number to set
valThe control value, from 0-127 whose meaning depends on the control number

◆ midiGetControlValue()

uint8_t midiGetControlValue ( midiPlayer_t * player,
uint8_t channel,
midiControl_t control )

Get the value of a MIDI control.

Parameters
playerThe MIDI player
channelThe channel to retrieve the control from
controlThe MIDI control number of the control
Returns
uint8_t The value of the specified control, or 0 if the specified controller is not implemented

◆ midiGetControlValue14bit()

uint16_t midiGetControlValue14bit ( midiPlayer_t * player,
uint8_t channel,
midiControl_t control )

Get the combined value of two MIDI control registers.

Parameters
playerThe MIDI player
channelThe channel to retrieve the control from
controlThe MIDI control number of either of the two controls that make up the value
Returns
uint16_t The value of the specified control, or 0 if the specified controller is not implemented

◆ midiSetParameter()

void midiSetParameter ( midiPlayer_t * player,
uint8_t channel,
bool registered,
uint16_t param,
uint16_t value )

Set a registered or non-registered parameter value.

Parameters
playerThe MIDI player
channelThe channel to set the parameter on
registeredtrue if param refers to a registered parameter number and false if it refers to a non-registered
paramThe registered or non-registered MIDI parameter to set the value of
valueThe 14-bit value to set the parameter to

◆ midiGetParameterValue()

uint16_t midiGetParameterValue ( midiPlayer_t * player,
uint8_t channel,
bool registered,
uint16_t param )

Get the value of a registered or non-registered parameter.

Parameters
playerThe MIDI player
channelThe channel to retrieve the parameter from
registeredtrue if param refers to a registered parameter number and false if it refers to a non-registered
paramThe registered or non-registered MIDI parameter number to retrieve the value for
Returns
The current 14-bit value of the given registered or non-registered parameter, or 0 if the parameter is unsupported

◆ midiPitchWheel()

void midiPitchWheel ( midiPlayer_t * player,
uint8_t channel,
uint16_t value )

Set the pitch wheel value on a given MIDI channel.

By default, the center of the pitch wheel is 0x2000. A value of 0x0000 transposes one step down, while a value of 0x3FFF transposes one step down.

[NYI] The range of the pitch wheel can be changed using the registered parameters, with MSB being the range in (+/-)semitones and LSB being the range in (+/-) cents

Parameters
playerThe MIDI player
channelThe MIDI channel to change the pitch wheel for
valueThe pitch wheel value, from 0 to 0x3FFF (14-bits)

◆ midiSetTempo()

void midiSetTempo ( midiPlayer_t * player,
uint32_t tempo )

Change the MIDI playback tempo.

Parameters
playerThe player to change the tempo of
tempoThe new tempo to set, in microseconds per quarter note

◆ midiSetFile()

void midiSetFile ( midiPlayer_t * player,
const midiFile_t * file )

Configure this MIDI player to read from a MIDI file.

Parameters
playerThe MIDI player
fileA pointer to the MIDI file to be played

◆ midiPause()

void midiPause ( midiPlayer_t * player,
bool pause )

Set the paused state of a MIDI song.

Parameters
playerThe player
pauseTrue to pause, false to play

◆ midiSeek()

void midiSeek ( midiPlayer_t * player,
uint32_t ticks )

Seek to a given time offset within a file.

Note that in the current implementation, seeking backwards by any amount requires re-reading the file from the beginning, and so may be very slow, particularly for large MIDI files.

Parameters
playerThe MIDI player to seek on
ticksThe absolute number of MIDI ticks to seek to. If this is -1, it will seek to the end of the song

◆ initGlobalMidiPlayer()

void initGlobalMidiPlayer ( void )

Initialize the system-wide MIDI players for both BGM and SFX.

◆ deinitGlobalMidiPlayer()

void deinitGlobalMidiPlayer ( void )

Deinitialize and free memory associated with the system-wide MIDI players.

◆ globalMidiPlayerFillBuffer()

void globalMidiPlayerFillBuffer ( uint8_t * samples,
int16_t len )

Fill the given sample buffer with samples from both the BGM and SFX system-wide MIDI players.

Parameters
[out]samplesA pointer to the array of unsigned 8-bit samples to be filled
lenThe number of samples

◆ globalMidiPlayerPlaySong()

void globalMidiPlayerPlaySong ( midiFile_t * song,
uint8_t trackType )

Play a song on one of the system-wide MIDI players, either BGM or SFX.

Parameters
songA pointer to the song to play
trackTypeThe player to use, either MIDI_SFX or MIDI_BGM

◆ globalMidiPlayerPlaySongCb()

void globalMidiPlayerPlaySongCb ( midiFile_t * song,
uint8_t trackType,
songFinishedCbFn cb )

Play a song on noe of the system-wide MIDI players, with a callback once the song finishes.

Parameters
songA pointer to the song to play
trackTypeThe player to use, either MIDI_SFX or MIDI_BGM
cbThe function to be called once the song completes

◆ globalMidiPlayerSetVolume()

void globalMidiPlayerSetVolume ( uint8_t trackType,
int32_t volumeSetting )

Set the volume using a value from 0 to 13.

Parameters
trackTypeThe player to set the volume for, either MIDI_SFX or MIDI_BGM
volumeSettingThe volume value

◆ globalMidiPlayerPauseAll()

void globalMidiPlayerPauseAll ( void )

Pause all songs currently being played by the system-wide MIDI players.

◆ globalMidiPlayerResumeAll()

void globalMidiPlayerResumeAll ( void )

Resume all songs currently being played by the system-wide MIDI players.

◆ globalMidiPlayerStop()

void globalMidiPlayerStop ( bool reset)

Stop all songs currently being played by the system-wide MIDI players, optionally resetting their state to the beginning of the song.

Parameters
resetif true, the players will be reset to the beginning of the song

◆ globalMidiSave()

void * globalMidiSave ( void )

Stop all MIDI playback and return a pointer containing the full playback state. This state must be passed to globalMidiRestore() later to restore the previous state.

Returns
void* A void-pointer containing the full MIDI playback state

◆ globalMidiRestore()

void globalMidiRestore ( void * data)

Resume MIDI playback from the state stored in the given pointer. The data will be freed after this call and cannot be reused.

Parameters
dataThe playback state data returned by globalMidiSave()

◆ globalMidiPlayerGet()

midiPlayer_t * globalMidiPlayerGet ( uint8_t trackType)

Return a pointer to the system-wide MIDI player for the given track type, either MIDI_SFX or MIDI_BGM.

Parameters
trackTypeWhich MIDI player to return, either MIDI_SFX or MIDI_BGM
Returns
midiPlayer_t*