Creare un file Midi con le funzioni esterne del API di Libsmf

Da Gambas-it.org - Wikipedia.

Libsmf è una libreria per la lettura e la scrittura dei file Midi standard (.mid).

Per poter fruire delle sue risorse è necessario avere installata nel sistema e richiamare in Gambas la libreria dinamica condivisa: "libsmf.so.0.0.0"

La libreria possiede, fra l'altro, specifiche risorse per la gestione di dati Midi, anche finalizzata alla creazione di file Midi.

Mostriamo di seguito un semplice esempio per costruire un file Midi formato da una sola traccia:

Library "libsmf:0.0.0"

Public Struct smf_struct
  formati As Integer
  ppqn As Integer
  frames_per_second As Integer
  resolution As Integer
  number_of_tracks As Integer
  streamf As Pointer
  file_buffer As Pointer
  file_buffer_length As Integer
  next_chunk_offset As Integer
  expected_number_of_tracks As Integer
  tracks_array As Pointer
  last_seek_position As Float
  tempo_array As Pointer
End Struct

Public Struct smf_track_struct
  smf_t As Pointer
  track_number As Integer
  number_of_events As Integer
  file_buffer As Pointer
  file_buffer_length As Integer
  last_status As Integer
  next_event_offset As Integer
  next_event_number As Integer
  time_of_next_event As Integer
  events_array As Pointer
  user_pointer As Pointer
End Struct

Public Struct smf_event_struct
  track As Pointer
  event_number As Integer
  delta_time_pulses As Integer
  time_pulses As Integer
  time_seconds As Float
  track_number As Integer
  midi_buffer As Pointer
  midi_buffer_length As Integer
  user_pointer As Pointer
End Struct

' smf_t * smf_new (void)
' Allocates new smf_t structure.
Private Extern smf_new() As Smf_struct

' smf_track_t * smf_track_new (void)
' Allocates new smf_track_t structure.
Private Extern smf_track_new() As Smf_track_struct

' void smf_add_track (smf_t *smf, smf_track_t *track)
' Appends smf_track_t to smf.
Private Extern smf_add_track(smf As Smf_struct, track As Smf_track_struct)

' smf_event_t * smf_event_new_from_pointer (void *midi_data, int len)
' Allocates an smf_event_t structure and fills it with "len" bytes copied from "midi_data".
Private Extern smf_event_new_from_pointer(midi_data As Pointer, leni As Integer) As Smf_event_struct

' void smf_track_add_event_seconds (smf_track_t *track, smf_event_t *event, double seconds)
' Adds event to the track at the time "seconds" seconds from the start of song.
Private Extern smf_track_add_event_seconds(track As Smf_track_struct, evento As Smf_event_struct, seconds As Float)

' int smf_save (smf_t *smf, const char *file_name)
' Writes the contents of SMF to the file given.
Private Extern smf_save(smf As Smf_struct, file_name As String) As Integer

' void smf_delete (smf_t *smf)
' Frees smf and all it's descendant structures.
Private Extern smf_delete(smf As Smf_struct)


Public Sub Main()

 Dim sm As Smf_struct
 Dim tr As Smf_track_struct
 Dim ev As Smf_event_struct
 Dim i As Integer
 Dim nota As Byte
 Dim byte_evento As New Byte[3]
 Dim pausa As Float
 
   sm = smf_new()
   
   tr = smf_track_new()
   
   smf_add_track(sm, tr)
   
   For i = 0 To 15
     
     nota = &3C + i
     
     If i = 8 Then 
' Imposta i dati necessari per il Messaggio Midi "Program Change":
       byte_evento[0] = &C0
       byte_evento[1] = 48
' Inserisce i dati del singolo evento Midi nella Struttura dell'evento:
       ev = smf_event_new_from_pointer(byte_evento.Data, 2)
' Questo evento sarà posto nella traccia ad una posizione pari alla somma dei secondi trascorsi
' dall'inizio della traccia medesima, definito dal terzo parametro della seguente funzione:
       smf_track_add_event_seconds(tr, ev, i)
       pausa = 1.0
     Endif
     
' Imposta i dati necessari per il Messaggio Midi "NoteOn":
     byte_evento[0] = &90
     byte_evento[1] = nota
     byte_evento[2] = 100
     Print "Note-On: "; nota
     ev = smf_event_new_from_pointer(byte_evento.Data, 3)
     smf_track_add_event_seconds(tr, ev, i + pausa)
     
' Imposta i dati necessari per il Messaggio Midi "NoteOff":
     byte_evento[0] = &80
     byte_evento[1] = nota
     byte_evento[2] = 0
     Print "Note-Off: "; nota
     ev = smf_event_new_from_pointer(byte_evento.Data, 3)
     smf_track_add_event_seconds(tr, ev, i + 1 + pausa)
   
   Next
   
   smf_save(sm, "/tmp/midi.mid")
   
   smf_delete(sm)
  
End


Riferimenti: