Annoiati e stanchi del solito beep di sistema? Le API nostre amiche (da sempre), ci offrono una valida alternativa! Ecco qui un sistema semplice ed efficace per gestire e sfruttare al meglio le capacità MIDI della nostra scheda audio.
Option Explicit
#If Win64 Then
Private Declare PtrSafe Function midiOutOpen _
Lib "winmm.dll" (lphMidiOut As LongPtr, _
ByVal uDeviceID As Long, _
ByVal dwCallback As LongPtr, _
ByVal dwInstance As LongPtr, _
ByVal dwflags As Long) As Long
Private Declare PtrSafe Function midiOutClose _
Lib "winmm.dll" (ByVal hMidiOut As LongPtr) As Long
Private Declare PtrSafe Function midiOutShortMsg _
Lib "winmm.dll" (ByVal hMidiOut As LongPtr, ByVal dwMsg As Long) As Long
#Else
Private Declare Function midiOutOpen _
Lib "winmm.dll" (lphMidiOut As Long, _
ByVal uDeviceID As Long, _
ByVal dwCallback As Long, _
ByVal dwInstance As Long, _
ByVal dwflags As Long) As Long
Private Declare Function midiOutClose _
Lib "winmm.dll" (ByVal hMidiOut As Long) As Long
Private Declare Function midiOutShortMsg Lib _
"winmm.dll" (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long
#End If
#If Win64 Then
Private hMidiOut1 As LongLong
#Else
Private hMidiOut1 As Long
#End If
Public Sub MidiOpen()
MidiClose
midiOutOpen hMidiOut1, 0, 0, 0, 0
'DEBUG PURPOSES ONLY
Debug.Print "Opened "; hMidiOut1
End Sub
Public Sub MidiClose()
midiOutClose hMidiOut1
hMidiOut1 = 0
End Sub
Public Sub MidiSetInstrument(ByVal InstrumentID As Long)
If hMidiOut1 = 0 Then MidiOpen
midiOutShortMsg hMidiOut1, (256 * InstrumentID) + 192
End Sub
Public Sub MidiPlayNote(ByVal Note As Integer, ByVal Volume As Integer)
If hMidiOut1 = 0 Then MidiOpen
midiOutShortMsg hMidiOut1, RGB(144, Note, Volume)
End Sub
Public Sub MidiPlayNoteEx(ByVal InstrumentID As Long, _
ByVal Note As Integer, _
ByVal Volume As Integer, _
ByVal Wait As Integer)
Dim dWait As Double
If hMidiOut1 = 0 Then MidiOpen
MidiSetInstrument InstrumentID
MidiPlayNote Note, Volume
dWait = Timer + CDbl(Wait) / 16
While Timer < dWait
DoEvents
Wend
If Wait > 0 Then MidiPlayNote Note, 0
End Sub
Sub test()
Dim v As Variant
If hMidiOut1 = 0 Then MidiOpen
'ta daaaa
MidiPlayNoteEx 55, 44, 127, 2
MidiPlayNoteEx 55, 56, 127, 4
Application.Wait Now + TimeValue("00:00:03")
'uccellini
MidiPlayNoteEx 123, 64, 120, 0
Application.Wait Now + TimeValue("00:00:03")
'accordo do-mi
MidiSetInstrument 1
For Each v In Array(60, 62)
MidiPlayNote v, 120
Next
Application.Wait Now + TimeValue("00:00:03")
'scale
For Each v In Array(60, 62, 64, 65, 67, 69, 71, 72)
MidiPlayNoteEx 50, v, 120, 5
Next
For Each v In Array(72, 71, 69, 67, 65, 64, 62, 60)
MidiPlayNoteEx 50, v, 120, 5
Next
End Sub
MidiOpen e MidiClose servono per creare un handle midi che serve per la durata della sessione.
MidiSetInstrument imposta lo strumento corrente (viene mantenuto per ogni nota successiva se non diversamente specificato da un’altra istruzione MidiSetInstrument o MidiPlayNoteEx).
MidiPlayNote permette di suonare una nota singola, al volume desiderato (0-muto, 127-alto).
MidiPlayNoteEx è la versione sofisticata della precedente e permette di impostare contemporaneamente lo strumento e la durata della nota.
I valori delle note sono definiti nel range da 1 a 127, dalla nota minore a quella maggiore. La nota più bassa su un piano da 88 tasti ha il valore 21 e la più alta 108. Il DO centrale vale 60.
Anche il valore della velocità (tempo) varia da 1 (più morbido) a 128 (più elevato).
In MIDI, il suono dello strumento o “programma” per ciascuno dei 16 canali MIDI possibili è selezionato con il “messaggio” API di Program Change, che dispone di un parametro del numero di programma.
All’indirizzo https://en.wikipedia.org/wiki/General_MIDI troviamo una tabella che mostra quale suono dello strumento corrisponde a ciascuno dei 128 numeri di programma possibile (solo per General MIDI). I numeri possono essere visualizzati come valori da 1 a 128 (la numerazione da 0 a 127 è di solito utilizzato solo internamente dal sintetizzatore); la stragrande maggioranza dei dispositivi MIDI, workstation audio digitali e sequencer MIDI professionale visualizza questi numeri di programma come indicato nella tabella (1-128).
Per esempio, il Pianoforte classico ha valore strumento pari a 1, mentre la Celesta vale 9. La Fisarmonica (Accordion) vale 22 e il Violino 41.
Possiamo divertirci a fare le variazioni che desideriamo.
Il file allegato (in cui compare il codice visto sopra) mostra uno spezzone di una tastiera di pianoforte e la tabella di conversione tra le note (notazione anglosassone) e i valori da passare alla routine. Fate partire la sub di test o divertitevi a ricopiare l’Inno alla gioia 🙂
Scarica il file: API sonore
› Come riprodurre effetti e suoni midi con le API sonore
LoginRegistrati