I was curious as to what all the default MIDI soundfont patches sounded like, and I also wanted to put together a way of grabbing those sounds somehow in code to use, so this function is the result. It just grabs 1 midi note. I don't think I'm calculating the ticks and duration right, but at least I can hear the sound patches available. There's some real neat ones. I'm probably not making a valid MIDI data file here, but at least it loads/plays.
- Dav
NOTE: Get the lastest version, now called MidiNotes, HERE
- Dav
NOTE: Get the lastest version, now called MidiNotes, HERE
Code: (Select All)
'Exploring QB64-PE default soundfont patches.
'Makes MIDI a note and play's it from memory.
'Dav, SEP/2024
'Cycles throuh all default sound patchs 127-0
$Unstable:Midi
$MidiSoundFont: Default
'cycle through all sounds, press any key to quit.
For patch = 127 To 0 Step -1
Print "Patch#"; patch
note$ = MidiNote$(60, patch, 60, 1)
midisound& = _SndOpen(note$, "memory")
_SndPlay midisound&
_Delay 1
_SndStop midisound&
_SndClose midisound&
If InKey$ <> "" Then End
Next
Function MidiNote$ (tempo&, patch, note, duration&)
TicksPerQuarterNote = 96
'Make MIDI Header Chunk (MThd)
MThd$ = Chr$(77) + Chr$(84) + Chr$(104) + Chr$(100) ' "MThd"
'Make Header size
MThd$ = MThd$ + Chr$(0) + Chr$(0) + Chr$(0) + Chr$(6)
'Make format type (1 = single track)
MThd$ = MThd$ + Chr$(0) + Chr$(1)
'Make number of tracks (1)
MThd$ = MThd$ + Chr$(0) + Chr$(1)
'Make division = 96 (ticks per quarter note)
MThd$ = MThd$ + Chr$(0) + Chr$(96)
'calculate microseconds per beat from tempo& in BPM
MicroSecsPerBeat& = 60000000 \ tempo& '(converts BPM to microseconds per beat)
'Get msb/mb/lsb from MicroSecsPerBeat& for saving tempo
'(midi requires 3 bytes for this info)
msb = (MicroSecsPerBeat& \ 65536) And 255 'most Significant Byte
middle = (MicroSecsPerBeat& \ 256) And 255 'middle Byte
lsb = MicroSecsPerBeat& And 255 'least Significant Byte
'Make the tempo data + the 3 bytes
TrackData$ = TrackData$ + Chr$(0) + Chr$(255) + Chr$(81) + Chr$(3) + Chr$(msb) + Chr$(middle) + Chr$(lsb)
'Set Program number (patch) to use
TrackData$ = TrackData$ + Chr$(0) + Chr$(192) + Chr$(patch)
'Set Note On: play note value (with velocity 127)
TrackData$ = TrackData$ + Chr$(0) + Chr$(144) + Chr$(note) + Chr$(127)
'convert duration& in beats to ticks& (how long to play the note)
ticks& = duration& * TicksPerQuarterNote
'Set Note Off: Stop playing note after specified duration& in ticks&
TrackData$ = TrackData$ + Chr$(ticks&) + Chr$(128) + Chr$(note) + Chr$(64)
'Make track end event
TrackData$ = TrackData$ + Chr$(0) + Chr$(255) + Chr$(47) + Chr$(0)
'Make the MTrk header
MTrk$ = Chr$(77) + Chr$(84) + Chr$(114) + Chr$(107) ' MTrk
'Make the track data length (4 bytes)
TrackLen& = Len(TrackData$)
TrackLength$ = Chr$((TrackLen& \ 16777216) And 255) + Chr$((TrackLen& \ 65536) And 255) + Chr$((TrackLen& \ 256) And 255) + Chr$(TrackLen& And 255)
'Put it all together
MidiNote$ = MThd$ + MTrk$ + TrackLength$ + TrackData$
End Function