Differenze tra le versioni di "Ottenere un file WAV da un file Midi con le funzioni esterne del API di FluidSynth"

Da Gambas-it.org - Wikipedia.
(Creata pagina con "Con le risorse della libreria '''Libfluidsynth''' è possibile ottenere un file WAV da un file Midi. E' necessario avere istallata e richiamare in Gambas la libreria dinamica...")
 
 
(9 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
 
Con le risorse della libreria '''Libfluidsynth''' è possibile ottenere un file WAV da un file Midi.
 
Con le risorse della libreria '''Libfluidsynth''' è possibile ottenere un file WAV da un file Midi.
  
E' necessario avere istallata e richiamare in Gambas la libreria dinamica condivisa: "''libfluidsynth:1.5.2''"
+
E' necessario avere installata e richiamare in Gambas la libreria condivisa: "''libfluidsynth.so.3.2.2'' ".
  
  
 
Mostriamo di seguito un esempio ''a riga di comando'':
 
Mostriamo di seguito un esempio ''a riga di comando'':
 +
Library "libfluidsynth:3.2.2"
 +
 +
<FONT Color=gray>' ''fluid_settings_t* new_fluid_settings(void)''
 +
' ''Create a new settings object.''</font>
 +
Private Extern new_fluid_settings() As Pointer
 +
 +
<FONT Color=gray>' ''fluid_synth_t * new_fluid_synth(fluid_settings_t * settings)''
 +
' ''Create new FluidSynth instance.''</font>
 +
Private Extern new_fluid_synth(settings As Pointer) As Pointer
 +
 +
<FONT Color=gray>' ''int fluid_is_soundfont(const char * filename)''
 +
' ''Check if a file is a SoundFont file.''</font>
 +
Private Extern fluid_is_soundfont(filename As String) As Integer
 +
 +
<FONT Color=gray>' ''int fluid_synth_sfload(fluid_synth_t * synth, const char * filename, nt reset_presets)''
 +
' ''Load a SoundFont file.''</font>
 +
Private Extern fluid_synth_sfload(synth As Pointer, filename As String, reset_presets As Integer) As Integer
 +
 +
<FONT Color=gray>' ''int fluid_settings_getnum(fluid_settings_t* settings, const char *name, double* val)''
 +
' ''Get the numeric value of a named setting.''</font>
 +
Private Extern fluid_settings_getnum(settings As Pointer, name As String, dval As Pointer) As Integer
 +
 +
<FONT Color=gray>' ''void fluid_synth_set_gain(fluid_synth_t *synth, float gain)''
 +
' ''Set synth output gain value.''</font>
 +
Private Extern fluid_synth_set_gain(synth As Pointer, gain As Single)
 +
 +
<FONT Color=gray>' ''fluid_player_t* new_fluid_player(fluid_synth_t * synth)''
 +
' ''Create a new MIDI player.''</font>
 +
Private Extern new_fluid_player(synth As Pointer) As Pointer
 +
 +
<FONT Color=gray>' ''int fluid_is_midifile(const char *filename)''
 +
' ''Check if a file is a MIDI file.''</font>
 +
Private Extern fluid_is_midifile(filename As String) As Integer
 +
 +
<FONT Color=gray>' ''int fluid_player_add(fluid_player_t * player, Const char * midifile)''
 +
' ''Add a MIDI file to a player queue.''</font>
 +
Private Extern fluid_player_add(player As Pointer, midifile As String) As Integer
 +
 +
<FONT Color=gray>' ''int fluid_player_play(fluid_player_t * player)''
 +
' ''Activates play mode for a MIDI player if not already playing.''</font>
 +
Private Extern fluid_player_play(player As Pointer) As Integer
 +
 +
<FONT Color=gray>' ''int fluid_synth_write_s16(fluid_synth_t* synth, int len, void* lout, int loff, int lincr, void* rout, int roff, int rincr)''
 +
' ''Synthesize a block of 16 bit audio samples to audio buffers.''</font>
 +
Private Extern fluid_synth_write_s16(synth As Pointer, ilen As Integer, luot As Short[], loff As Integer, lincr As Integer, rout As Short[], forr As Integer, rincr As Integer) As Integer
 +
 +
<FONT Color=gray>' ''int fluid_player_get_status(fluid_player_t * player)''
 +
' ''Get MIDI player status.''</font>
 +
Private Extern fluid_player_get_status(player As Pointer) As Integer
 +
 +
<FONT Color=gray>' ''int delete_fluid_player(fluid_player_t * player)''
 +
' ''Delete a MIDI player instance.''</font>
 +
Private Extern delete_fluid_player(player As Pointer) As Integer
 +
 +
<FONT Color=gray>' ''int delete_fluid_synth(fluid_synth_t * synth)''
 +
' ''Delete a FluidSynth instance.''</font>
 +
Private Extern delete_fluid_synth(synth As Pointer) As Integer
 +
 +
<FONT Color=gray>' ''void delete_fluid_settings(fluid_settings_t * settings)''
 +
' ''Delete the provided settings object.''</font>
 +
Private Extern delete_fluid_settings(settings As Pointer)
 +
 +
 +
Public Sub Main()
 +
 +
  Dim sfb, fileMidi, dati_grezzi As String
 +
  Dim sett, syn, pl As Pointer
 +
  Dim i As Integer
 +
  Dim frequenza As Float
 +
  Dim buffer, dati As Short[]
 +
  Dim fl As File
 +
 
 +
<FONT Color=gray>' ''Imposta il file soundfont-bank che sarà utilizzato:''</font>
 +
  sfb = "/usr/share/sounds/sf2/FluidR3_GM.sf2"
 +
 
 +
<FONT Color=gray>' ''Verifica se il file caricato è effettivamente un soundfont-bank .sf2:''</font>
 +
  i = fluid_is_soundfont(sfb)
 +
  If i < 0 Then Error.Raise("Errore: il file non è un soundfont-bank !")
 +
 
 +
<FONT Color=gray>' ''Imposta il file Midi, dal quale si genererà un file audio wav:''</font>
 +
  fileMidi = "<FONT Color=gray>''/percorso/del/file.mid''</font>"
 +
   
 +
<FONT Color=gray>' ''Verifica se il file è effettivamente uno file Midi standard:''</font>
 +
  i = fluid_is_midifile(fileMidi)
 +
  If i < 0 Then Error.Raise("Errore: il file non è un file Midi standard !")
 +
   
 +
  sett = new_fluid_settings()
 +
  If sett == 0 Then Error.Raise("Impossibile creare un oggetto 'settings' !")
 +
   
 +
  syn = new_fluid_synth(sett)
 +
  If syn == 0 Then Error.Raise("Impossibile creare un'istanza di FluidSynth !")
 +
   
 +
  i = fluid_synth_sfload(syn, sfb, 1)
 +
  If i < 0 Then Error.Raise("Impossibile caricare il file soundfont-bank !")
 +
 
 +
  fluid_settings_getnum(sett, "synth.sample-rate", VarPtr(frequenza))
 +
   
 +
<FONT Color=gray>' ''Imposta il volume del file audio wav finale:''</font>
 +
  fluid_synth_set_gain(syn, 0.5)
 +
   
 +
  pl = new_fluid_player(syn)
 +
  If pl == 0 Then Error.Raise("Impossibile creare un esecutore Midi !")
 +
   
 +
  i = fluid_player_add(pl, fileMidi)
 +
  If i < 0 Then Error.Raise("Errore alla funzione 'fluid_player_add()' !")
 +
 
 +
  i = fluid_player_play(pl)
 +
  If i < 0 Then Error.Raise("Errore alla funzione 'fluid_player_play()' !")
 +
   
 +
  dati = New Short[frequenza * 2]
 +
   
 +
  Repeat
 +
    buffer = New Short[frequenza * 2]
 +
    fluid_synth_write_s16(syn, frequenza, buffer, 0, 2, buffer, 1, 2)
 +
    dati.Insert(buffer)
 +
  Until fluid_player_get_status(pl) <> 1
 +
 
 +
  dati_grezzi = "/tmp/dati_grezzi"
 +
  fl = Open dati_grezzi For Create
 +
  dati.Write(fl, 0, dati.Count)
 +
  fl.Close
 +
   
 +
<FONT Color=gray>' ''Va a generare il file audio wav:''</font>
 +
  Genera_File_wav(frequenza, dati_grezzi)
 +
   
 +
<FONT Color=gray>' ''Va in chiusura:''</font>
 +
  delete_fluid_player(pl)
 +
  delete_fluid_synth(syn)
 +
  delete_fluid_settings(sett)
 +
   
 +
  Print "\nTermine creazione del file audio wav."
 +
 
 +
End
 +
 +
 +
Private Procedure Genera_File_wav(freq As Float, dati_audio As String)
 +
 
 +
  Dim s, ini As String
 +
  Dim fl As File
 +
  Dim bh, bb As New Byte[]
 +
  Dim canali, risoluzione, blal As Byte
 +
  Dim i, i2, frequenza, brps As Integer
 +
 
 +
  s = File.Load(dati_audio)
 +
 
 +
  frequenza = CInt(freq)
 +
 
 +
<FONT Color=gray>' ''Vengono definiti gli elementi fondamentali del blocco d'intestazione del file wav: ''</font>
 +
  canali = 2
 +
  risoluzione = 16
 +
  Print "Caratteristiche del futuro file WAV:"
 +
  Print "- Frequenza:  "; frequenza; " hertz"
 +
  Print "- Canali:      "; canali
 +
  Print "- Risoluzione: "; risoluzione; " bit"
 +
 
 +
  fl = Open "/tmp/audio.wav" For Create
 +
 
 +
  ini = "RIFF"
 +
 
 +
  bb = Byte[].FromString(ini)
 +
 
 +
  i = Len(s)
 +
 
 +
  i2 = i + 36
 +
 
 +
<FONT Color=gray>' ''Imposta il valore dimensionale di 4 byte a partire dal 5° byte del futuro file:''</font>
 +
  bb.Push(i2 And &FF)
 +
  bb.Push(Shr(i2 And &FF00&, 8))
 +
  bb.Push(Shr(i2 And &FF0000&, 16))
 +
  bb.Push(Shr(i2 And &FF000000&, 24))
 +
 
 +
<FONT Color=gray>' ''Vengono aggiunti: il tipo di formato di file e l'identificativo del formato del blocco dei dati audio:''</font>
 +
  bb.Insert(bh.FromString("WAVEfmt "))
 +
 
 +
<FONT Color=gray>' ''Viene aggiunto il valore della lunghezza dei dati del formato (in questo caso il PCM):''</font>
 +
  bh = [&10, &00, &00, &00]
 +
  bb.Insert(bh)
 +
 
 +
<FONT Color=gray>' ''Viene aggiunto il valore del formato audio (1 = PCM):''</font>
 +
  bb.Insert(bh.FromString(Chr(&01) & Chr(&00)))
 +
 
 +
<FONT Color=gray>' ''Viene aggiunto il numero dei canali di uscita:''</font>
 +
  bb.Insert(bh.FromString(Chr(canali) & Chr(&00)))
 +
 
 +
<FONT Color=gray>' ''Viene aggiunto il valore della frequenza di campionamento:''</font>
 +
  bb.Push(frequenza And &FF)
 +
  bb.Push(Shr(frequenza And &FF00&, 8))
 +
  bb.Push(Shr(frequenza And &FF0000&, 16))
 +
  bb.Push(Shr(frequenza And &FF000000&, 24))
 +
 
 +
<FONT Color=gray>' ''Viene aggiunto il valore del "Byte rate per secondo":''</font>
 +
  brps = frequenza * canali * (risoluzione / 8)
 +
  bb.Push(brps And &FF)
 +
  bb.Push(Shr(brps And &FF00&, 8))
 +
  bb.Push(Shr(brps And &FF0000&, 16))
 +
  bb.Push(Shr(brps And &FF000000&, 24))
 +
 
 +
<FONT Color=gray>' ''Viene aggiunto il valore del "Block Align":''</font>
 +
  blal = canali * risoluzione / 8
 +
  bb.Insert(bh.FromString(Chr(blal) & Chr(&00)))
 +
 
 +
<FONT Color=gray>' ''Viene aggiunto il valore della risoluzione di campionamento:''</font>
 +
  bb.Insert(bh.FromString(Chr(risoluzione) & Chr(&00)))
 +
 
 +
<FONT Color=gray>' ''Viene aggiunto l'identificativo del Blocco dei dati audio grezzi:''</font>
 +
  bb.Insert(bh.FromString("data"))
 +
 
 +
<FONT Color=gray>' ''Imposta il valore dimensionale di 4 byte a partire dal 41° byte del futuro file e relativo alla dimensione dei dati audio grezzi:''</font>
 +
  bb.Push(i And &FF)
 +
  bb.Push(Shr(i And &FF00&, 8))
 +
  bb.Push(Shr(i And &FF0000&, 16))
 +
  bb.Push(Shr(i And &FF000000&, 24))
 +
 
 +
  bb.Insert(Byte[].FromString(s))
 +
 
 +
<FONT Color=gray>' ''Crea il nuovo file wav:''</font>
 +
  bb.Write(fl, 0, bb.Count)
 +
 
 +
  fl.Close
 +
 
 +
End
  
  
  
<FONT Color=Red size=4><B>Pagina in costruzione !</b></font>
+
=Riferimenti=
 +
* http://www.fluidsynth.org/
 +
* http://www.fluidsynth.org/api/index.html

Versione attuale delle 13:02, 13 gen 2024

Con le risorse della libreria Libfluidsynth è possibile ottenere un file WAV da un file Midi.

E' necessario avere installata e richiamare in Gambas la libreria condivisa: "libfluidsynth.so.3.2.2 ".


Mostriamo di seguito un esempio a riga di comando:

Library "libfluidsynth:3.2.2"

' fluid_settings_t* new_fluid_settings(void)
' Create a new settings object.
Private Extern new_fluid_settings() As Pointer

' fluid_synth_t * new_fluid_synth(fluid_settings_t * settings)
' Create new FluidSynth instance.
Private Extern new_fluid_synth(settings As Pointer) As Pointer

' int fluid_is_soundfont(const char * filename)
' Check if a file is a SoundFont file.
Private Extern fluid_is_soundfont(filename As String) As Integer

' int fluid_synth_sfload(fluid_synth_t * synth, const char * filename, nt reset_presets)
' Load a SoundFont file.
Private Extern fluid_synth_sfload(synth As Pointer, filename As String, reset_presets As Integer) As Integer

' int fluid_settings_getnum(fluid_settings_t* settings, const char *name, double* val)
' Get the numeric value of a named setting.
Private Extern fluid_settings_getnum(settings As Pointer, name As String, dval As Pointer) As Integer

' void fluid_synth_set_gain(fluid_synth_t *synth, float gain)
' Set synth output gain value.
Private Extern fluid_synth_set_gain(synth As Pointer, gain As Single)

' fluid_player_t* new_fluid_player(fluid_synth_t * synth)
' Create a new MIDI player.
Private Extern new_fluid_player(synth As Pointer) As Pointer

' int fluid_is_midifile(const char *filename)
' Check if a file is a MIDI file.
Private Extern fluid_is_midifile(filename As String) As Integer

' int fluid_player_add(fluid_player_t * player, Const char * midifile)
' Add a MIDI file to a player queue.
Private Extern fluid_player_add(player As Pointer, midifile As String) As Integer

' int fluid_player_play(fluid_player_t * player)
' Activates play mode for a MIDI player if not already playing.
Private Extern fluid_player_play(player As Pointer) As Integer

' int fluid_synth_write_s16(fluid_synth_t* synth, int len, void* lout, int loff, int lincr, void* rout, int roff, int rincr)
' Synthesize a block of 16 bit audio samples to audio buffers.
Private Extern fluid_synth_write_s16(synth As Pointer, ilen As Integer, luot As Short[], loff As Integer, lincr As Integer, rout As Short[], forr As Integer, rincr As Integer) As Integer

' int fluid_player_get_status(fluid_player_t * player)
' Get MIDI player status.
Private Extern fluid_player_get_status(player As Pointer) As Integer

' int delete_fluid_player(fluid_player_t * player)
' Delete a MIDI player instance.
Private Extern delete_fluid_player(player As Pointer) As Integer

' int delete_fluid_synth(fluid_synth_t * synth)
' Delete a FluidSynth instance.
Private Extern delete_fluid_synth(synth As Pointer) As Integer

' void delete_fluid_settings(fluid_settings_t * settings)
' Delete the provided settings object.
Private Extern delete_fluid_settings(settings As Pointer)


Public Sub Main()

 Dim sfb, fileMidi, dati_grezzi As String
 Dim sett, syn, pl As Pointer
 Dim i As Integer
 Dim frequenza As Float
 Dim buffer, dati As Short[]
 Dim fl As File
 
' Imposta il file soundfont-bank che sarà utilizzato:
 sfb = "/usr/share/sounds/sf2/FluidR3_GM.sf2"
  
' Verifica se il file caricato è effettivamente un soundfont-bank .sf2:
 i = fluid_is_soundfont(sfb)
 If i < 0 Then Error.Raise("Errore: il file non è un soundfont-bank !")
  
' Imposta il file Midi, dal quale si genererà un file audio wav:
 fileMidi = "/percorso/del/file.mid"
   
' Verifica se il file è effettivamente uno file Midi standard:
 i = fluid_is_midifile(fileMidi)
 If i < 0 Then Error.Raise("Errore: il file non è un file Midi standard !")
   
 sett = new_fluid_settings()
 If sett == 0 Then Error.Raise("Impossibile creare un oggetto 'settings' !")
   
 syn = new_fluid_synth(sett)
 If syn == 0 Then Error.Raise("Impossibile creare un'istanza di FluidSynth !")
   
 i = fluid_synth_sfload(syn, sfb, 1)
 If i < 0 Then Error.Raise("Impossibile caricare il file soundfont-bank !")
  
 fluid_settings_getnum(sett, "synth.sample-rate", VarPtr(frequenza))
   
' Imposta il volume del file audio wav finale:
 fluid_synth_set_gain(syn, 0.5)
   
 pl = new_fluid_player(syn)
 If pl == 0 Then Error.Raise("Impossibile creare un esecutore Midi !")
   
 i = fluid_player_add(pl, fileMidi)
 If i < 0 Then Error.Raise("Errore alla funzione 'fluid_player_add()' !")
  
 i = fluid_player_play(pl)
 If i < 0 Then Error.Raise("Errore alla funzione 'fluid_player_play()' !")
   
 dati = New Short[frequenza * 2]
   
 Repeat
   buffer = New Short[frequenza * 2]
   fluid_synth_write_s16(syn, frequenza, buffer, 0, 2, buffer, 1, 2)
   dati.Insert(buffer)
 Until fluid_player_get_status(pl) <> 1
  
 dati_grezzi = "/tmp/dati_grezzi"
 fl = Open dati_grezzi For Create
 dati.Write(fl, 0, dati.Count)
 fl.Close
   
' Va a generare il file audio wav:
 Genera_File_wav(frequenza, dati_grezzi)
    
' Va in chiusura:
 delete_fluid_player(pl)
 delete_fluid_synth(syn)
 delete_fluid_settings(sett)
   
 Print "\nTermine creazione del file audio wav."
  
End


Private Procedure Genera_File_wav(freq As Float, dati_audio As String)
 
 Dim s, ini As String
 Dim fl As File
 Dim bh, bb As New Byte[]
 Dim canali, risoluzione, blal As Byte
 Dim i, i2, frequenza, brps As Integer
  
 s = File.Load(dati_audio)
 
 frequenza = CInt(freq)
  
' Vengono definiti gli elementi fondamentali del blocco d'intestazione del file wav: 
 canali = 2
 risoluzione = 16
 Print "Caratteristiche del futuro file WAV:"
 Print "- Frequenza:   "; frequenza; " hertz"
 Print "- Canali:      "; canali
 Print "- Risoluzione: "; risoluzione; " bit"
  
 fl = Open "/tmp/audio.wav" For Create
  
 ini = "RIFF"
  
 bb = Byte[].FromString(ini)
  
 i = Len(s)
  
 i2 = i + 36
  
' Imposta il valore dimensionale di 4 byte a partire dal 5° byte del futuro file: 
 bb.Push(i2 And &FF)
 bb.Push(Shr(i2 And &FF00&, 8))
 bb.Push(Shr(i2 And &FF0000&, 16))
 bb.Push(Shr(i2 And &FF000000&, 24))
  
' Vengono aggiunti: il tipo di formato di file e l'identificativo del formato del blocco dei dati audio:
 bb.Insert(bh.FromString("WAVEfmt "))
  
' Viene aggiunto il valore della lunghezza dei dati del formato (in questo caso il PCM):
 bh = [&10, &00, &00, &00]
 bb.Insert(bh)
  
' Viene aggiunto il valore del formato audio (1 = PCM):
 bb.Insert(bh.FromString(Chr(&01) & Chr(&00)))
  
' Viene aggiunto il numero dei canali di uscita:
 bb.Insert(bh.FromString(Chr(canali) & Chr(&00)))
  
' Viene aggiunto il valore della frequenza di campionamento:
 bb.Push(frequenza And &FF)
 bb.Push(Shr(frequenza And &FF00&, 8))
 bb.Push(Shr(frequenza And &FF0000&, 16))
 bb.Push(Shr(frequenza And &FF000000&, 24))
  
' Viene aggiunto il valore del "Byte rate per secondo":
 brps = frequenza * canali * (risoluzione / 8)
 bb.Push(brps And &FF)
 bb.Push(Shr(brps And &FF00&, 8))
 bb.Push(Shr(brps And &FF0000&, 16))
 bb.Push(Shr(brps And &FF000000&, 24))
  
' Viene aggiunto il valore del "Block Align":
 blal = canali * risoluzione / 8
 bb.Insert(bh.FromString(Chr(blal) & Chr(&00)))
  
' Viene aggiunto il valore della risoluzione di campionamento:
 bb.Insert(bh.FromString(Chr(risoluzione) & Chr(&00)))
  
' Viene aggiunto l'identificativo del Blocco dei dati audio grezzi:
 bb.Insert(bh.FromString("data"))
  
' Imposta il valore dimensionale di 4 byte a partire dal 41° byte del futuro file e relativo alla dimensione dei dati audio grezzi:
 bb.Push(i And &FF)
 bb.Push(Shr(i And &FF00&, 8))
 bb.Push(Shr(i And &FF0000&, 16))
 bb.Push(Shr(i And &FF000000&, 24))
  
 bb.Insert(Byte[].FromString(s))
  
' Crea il nuovo file wav:
 bb.Write(fl, 0, bb.Count)
  
 fl.Close
  
End


Riferimenti