Differenze tra le versioni di "Convertire la frequenza di campionamento di un file WAV con le funzioni esterne del API di SDL2"

Da Gambas-it.org - Wikipedia.
 
(15 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
 
La libreria '''''SDL 2''''' è un [http://it.wikipedia.org/wiki/Application_programming_interface API] multi-piattaforma contenente funzioni per la gestione multimediale dell'audio e del video.
 
La libreria '''''SDL 2''''' è un [http://it.wikipedia.org/wiki/Application_programming_interface API] multi-piattaforma contenente funzioni per la gestione multimediale dell'audio e del video.
  
 +
Sarà necessario avere installate nel sistema e richiamare in Gambas la libreria condivisa: "''libSDL2-2.0.so.0.3000.0'' ".
  
Mostriamo di seguito un esempio di codice per convertire la frequenza di campionamento di un file WAV. In tal caso sarà necessario richiamare le seguenti librerie dell'API di ''SDL2'':
+
Mostriamo di seguito un esempio di codice per convertire la frequenza di campionamento di un file WAV da 44100 hertz a 22050 hertz:
* ''libSDL2-2.0.so.0.2.0''
+
  Library "libSDL2-2.0:0.3000.0"
* ''libSDL2_mixer-2.0.so.0.0.0''
 
Inoltre, poiché questo esempio richiede l'utilizzo di una ''Struttura'' molto complessa della libreria di ''SDL2'', ossia la ''Struttura'' "SDL_RWops", provvederemo a creare una nostra apposita libreria dinamica condivisa esterna, scritta in C e che chiameremo ad esempio ''libadhoc.c'', per effettuare una [[Gestire_con_sicurezza_le_Strutture_esterne|gestione sicura di quella ''Struttura'' esterna]].
 
 
 
 
 
Pertanto, il codice Gambas sarà:
 
  Library "libSDL2-2.0:0.2.0"
 
 
   
 
   
 
  Public Struct SDL_AudioSpec
 
  Public Struct SDL_AudioSpec
Riga 55: Riga 50:
 
  ' ''Converts audio data to a desired audio format.''</font>
 
  ' ''Converts audio data to a desired audio format.''</font>
 
  Private Extern SDL_ConvertAudio(SDL_cvt As SDL_AudioCVT) As Integer
 
  Private Extern SDL_ConvertAudio(SDL_cvt As SDL_AudioCVT) As Integer
 
<FONT Color=gray>' ''size_t SDL_WriteLE32(SDL_RWops* dst, Uint32 value)''
 
' ''Writes 32 bits in native format to a SDL_RWops as little-endian data.''</font>
 
Private Extern SDL_WriteLE32(SDL_RWops As Pointer, value As Integer) As Integer
 
 
<FONT Color=gray>' ''size_t SDL_WriteLE16(SDL_RWops* dst, Uint16 value)''
 
' ''Writes 16 bits in native format to a SDL_RWops as little-endian data.''</font>
 
Private Extern SDL_WriteLE16(SDL_RWops As Pointer, value As Short) As Integer
 
 
   
 
   
 
  <FONT Color=gray>' ''void SDL_Quit(void)''
 
  <FONT Color=gray>' ''void SDL_Quit(void)''
 
  ' ''Clean up all initialized subsystems.''</font>
 
  ' ''Clean up all initialized subsystems.''</font>
 
  Private Extern SDL_Quit()
 
  Private Extern SDL_Quit()
 
 
   
 
   
 
  <FONT Color=gray>' ''SDL_RWops * SDL_RWFromFile(const char *file, const char *mode)''
 
  <FONT Color=gray>' ''SDL_RWops * SDL_RWFromFile(const char *file, const char *mode)''
  ' ''Create a new SDL_RWops structure for reading from and/or writing to a named file. ''</font>
+
  ' ''Create a new SDL_RWops structure for reading from and/or writing to a named file.''</font>
  Private Extern SDL_RWFromFile(filewav As String, mode As String) As Pointer In "libSDL2_mixer-2.0:0.0.0"
+
  Private Extern SDL_RWFromFile(filewav As String, mode As String) As Pointer In "libSDL2_mixer-2.0"
+
 
 
<FONT Color=gray>' ''void *memcpy(void *str1, const void *str2, size_t n)''
 
' ''Copies n characters from memory area str2 to memory area str1.''</font>
 
Private Extern memcpy(str1 As Pointer, str2 As Pointer, n As Integer) In "libc:6"
 
 
   
 
   
 +
Public Sub Main()
 
   
 
   
<FONT Color=gray>' ''int Scrive_Chiude_WAV(SDL_RWops * io, Uint8 *buf, int len_cvt)''
+
   Dim wav, convertito As String
' ''La nostra apposita libreria .so per la gestione sicura della Struttura esterna "SDL_RWops".''</font>
+
   Dim data, pbb As Pointer
Private Extern Scrive_Chiude_WAV(SDL_RWops As Pointer, buffer As Pointer, lung As Integer) As Integer In "/tmp/libadhoc"
+
   Dim lun, cvtfreq, bitsize, blockalign, avgbytes As Integer
 
 
'''Public''' Sub Main()
 
 
   Dim filename As String = "''/percorso/del/file.wav''"
 
  Dim convertito As String = "/percorso/del/file.wav/convertito''"
 
   Dim data, io As Pointer
 
   Dim lun, cvtfreq, err As Integer
 
  Dim bitsize, blockalign, avgbytes As Integer
 
 
   Dim spec As New SDL_AudioSpec
 
   Dim spec As New SDL_AudioSpec
 
   Dim cvt As New SDL_AudioCVT
 
   Dim cvt As New SDL_AudioCVT
 +
  Dim fl As File
 +
  Dim bb As Byte[]
 +
  Dim st As Stream
 
    
 
    
<FONT Color=gray>' ''Crea la nostra apposita libreria per la gestione sicura della Struttura "SDL_RWops":''</font>
+
  wav = "<FONT Color=darkgreen>''/percorso/del/file.wav''</font>"
  Creaso()
+
  convertito = "<FONT Color=darkgreen>''/percorso/del/file.wav/convertito''</font>"
 
    
 
    
 
  <FONT Color=gray>' ''Imposta la nuova frequenza di campionamento, nella quale il file wav sarà convertito:''</font>
 
  <FONT Color=gray>' ''Imposta la nuova frequenza di campionamento, nella quale il file wav sarà convertito:''</font>
  cvtfreq = 22050
+
  cvtfreq = 22050
+
 
 
  <FONT Color=gray>' ''Inizializza la libreria SDL2:''</font>
 
  <FONT Color=gray>' ''Inizializza la libreria SDL2:''</font>
  If SDL_Init(SDL_INIT_AUDIO) < 0 Then Error.Raise("Impossibile inizializzare la libreria SDL2 !")
+
  If SDL_Init(SDL_INIT_AUDIO) < 0 Then Error.Raise("Impossibile inizializzare la libreria SDL2 !")
 
    
 
    
  If IsNull(SDL_LoadWAV_RW(SDL_RWFromFile(filename, "rb"), 1, spec, VarPtr(data), VarPtr(lun))) Then  
+
  If IsNull(SDL_LoadWAV_RW(SDL_RWFromFile(wav, "rb"), 1, spec, VarPtr(data), VarPtr(lun))) Then  
    Error.Raise("Impossibile caricare il file audio: " & filename & " !")
+
    Error.Raise("Impossibile caricare il file audio: " & wav & " !")
  Endif
+
  Endif
 
    
 
    
  If SDL_BuildAudioCVT(cvt, spec.format, spec.channels, spec.freq, spec.format, spec.channels, cvtfreq) = -1 Then
+
  If SDL_BuildAudioCVT(cvt, spec.format, spec.channels, spec.freq, spec.format, spec.channels, cvtfreq) = -1 Then
    Error.Raise("Impossibile realizzare il CVT !")
+
    Error.Raise("Impossibile realizzare il CVT !")
  Endif
+
  Endif
+
 
  cvt.len = lun
+
  cvt.len = lun
  cvt.buf = Alloc(lun * cvt.len_mult)
+
  cvt.buf = Alloc(SizeOf(gb.Short), cvt.len)
   
+
 
  memcpy(cvt.buf, data, lun)
+
<FONT Color=gray>' ''Inizia la procedura per trasferire con sicurezza i dati dall'area di memoria, puntata dal Puntatore "data", all'area di memoria puntata dal Puntatore "cvt.buf".''
 
+
  ' ''Per velocizzare tale procedura si utilizzerà il Metodo "Write" di un vettore di tipo "Byte[]".''</font>
  If SDL_ConvertAudio(cvt) = -1 Then Error.Raise("Conversione fallita !")
+
  bb = New Byte[cvt.len]
+
 
 +
<FONT Color=gray>' ''Innanzitutto vengono usati i "Memory Stream" per leggere i dati contenuti dal puntatore "data":''</font>
 +
  st = Memory data For Read
 +
<FONT Color=gray>' ''I dati letti sono caricati nel vettore "bb" di tipo "Byte[]":''</font>
 +
  bb.Read(st, 0, bb.Count)
 +
  st.Close
 +
 
 +
<FONT Color=gray>' ''I dati ora presenti nel vettore "bb" vengono, quindi, scritti nell'area di memoria puntata dal Puntatore "cvt.buf":''</font>
 +
  st = Memory cvt.buf For Write
 +
  bb.Write(st, 0, bb.Count)
 +
  st.Close
 +
 
 +
  If SDL_ConvertAudio(cvt) = -1 Then Error.Raise("Conversione fallita !")
 +
 
 +
  bitsize = spec.format And SDL_AUDIO_MASK_BITSIZE
 +
  blockalign = (bitsize / 8) * spec.channels
 +
  avgbytes = cvtfreq * blockalign
 +
 
 
  <FONT Color=gray>' ''Scrive l'header del file WAV in uscita:''</font>
 
  <FONT Color=gray>' ''Scrive l'header del file WAV in uscita:''</font>
  io = SDL_RWFromFile(convertito, "wb")
+
  fl = Open convertito For Create
  If io = 0 Then Error.Raise("Impossibile salvare il file audio convertito: " & convertito & " !")
+
  Write #fl, &46464952 As Integer  <FONT Color=gray>' ''RIFF''</font>
   
+
  Write #fl, (cvt.len_cvt + 36) As Integer
  bitsize = spec.format And SDL_AUDIO_MASK_BITSIZE
+
  Write #fl, &45564157 As Integer  <FONT Color=gray>' ''WAVE''</font>
  blockalign = (bitsize / 8) * spec.channels
+
  Write #fl, &20746D66 As Integer  <FONT Color=gray>' ''fmt''</font>
  avgbytes = cvtfreq * blockalign
+
  Write #fl, 16 As Integer  <FONT Color=gray>' ''chunk size''</font>
   
+
  Write #fl, 1 As Short  <FONT Color=gray>' ''uncompressed''</font>
  SDL_WriteLE32(io, &46464952' RIFF
+
  Write #fl, spec.channels As Short  <FONT Color=gray>' ''channels''</font>
  SDL_WriteLE32(io, lun * cvt.len_mult + 36)
+
  Write #fl, cvtfreq As Integer  <FONT Color=gray>' ''sample rate''</font>
  SDL_WriteLE32(io, &45564157' WAVE
+
  Write #fl, avgbytes As Integer  <FONT Color=gray>' ''average bytes per second''</font>
  SDL_WriteLE32(io, &20746D66' fmt
+
  Write #fl, blockalign As Short  <FONT Color=gray>' ''block align''</font>
  SDL_WriteLE32(io, 16) ' chunk size
+
  Write #fl, bitsize As Short  <FONT Color=gray>' ''significant bits per sample''</font>
  SDL_WriteLE16(io, 1' uncompressed
+
  Write #fl, &61746164 As Integer  <FONT Color=gray>' ''data''</font>
  SDL_WriteLE16(io, spec.channels' channels
+
  Write #fl, cvt.len_cvt As Integer  <FONT Color=gray>' ''size''</font>
  SDL_WriteLE32(io, cvtfreq' sample rate
+
 
  SDL_WriteLE32(io, avgbytes) ' average bytes per second
+
  bb = New Byte[cvt.len_cvt]
  SDL_WriteLE16(io, blockalign) ' block align
+
 
  SDL_WriteLE16(io, bitsize' significant bits per sample
+
<FONT Color=gray>' ''Vengono usati i "Memory Stream" per far leggere dal vettore "bb" i dati (ormai convertiti) contenuti dal puntatore "cvt.buf":''</font>
  SDL_WriteLE32(io, &61746164' data
+
  st = Memory cvt.buf For Read
  SDL_WriteLE32(io, cvt.len_cvt)  ' size
+
  bb.Read(st, 0, bb.Count)
 +
 
 +
  <FONT Color=gray>' ''Scrive i valori contenuti dal vettore "bb" nel file precedentemente aperto:''</font>
 +
  bb.Write(fl, 0, bb.Count)
 
    
 
    
<FONT Color=gray>' ''Viene invocata la nostra apposta libreria per la scrittura e la chiusura del file WAV convertito:''</font>
 
  err = Scrive_Chiude_WAV(io, cvt.buf, cvt.len_cvt)
 
  If err = -1 Then Error.Raise("Impossibile chiudere il file audio convertito: " & convertito & " !")
 
 
 
  <FONT Color=gray>' ''Va in chiusura:''</font>
 
  <FONT Color=gray>' ''Va in chiusura:''</font>
  Free(cvt.buf)
+
  st.Close
  SDL_Quit()
+
  Free(cvt.buf)
+
  fl.Close
'''End'''
+
   SDL_Quit()
 
 
'''Private''' Procedure Creaso()
 
 
 
  File.Save("/tmp/libadhoc.c", "#include <SDL2/SDL.h>" &
 
              "\n\n" &
 
              "int Scrive_Chiude_WAV(SDL_RWops * io, Uint8 *buf, int len_cvt) {\n" &
 
              "   SDL_RWwrite(io, buf, len_cvt, 1);\n" &
 
              "  if (SDL_RWclose(io) == -1)\n" &
 
              "    return -1;\n" &
 
              "  return 0;\n}")
 
 
 
  Shell "gcc -o /tmp/libadhoc.so /tmp/libadhoc.c -shared" Wait
 
 
    
 
    
  '''End'''
+
  End
 
 
  
  

Versione attuale delle 16:38, 18 mar 2024

La libreria SDL 2 è un API multi-piattaforma contenente funzioni per la gestione multimediale dell'audio e del video.

Sarà necessario avere installate nel sistema e richiamare in Gambas la libreria condivisa: "libSDL2-2.0.so.0.3000.0 ".

Mostriamo di seguito un esempio di codice per convertire la frequenza di campionamento di un file WAV da 44100 hertz a 22050 hertz:

Library "libSDL2-2.0:0.3000.0"

Public Struct SDL_AudioSpec
  freq As Integer
  format As Short
  channels As Byte
  silence As Byte
  samples As Short
  padding As Short
  size As Integer
  callback As Pointer
  userdata As Pointer
End Struct

Public Struct SDL_AudioCVT
  needed As Integer
  src_format As Short
  dst_format As Short
  rate_incr As Float
  buf As Pointer
  len As Integer
  len_cvt As Integer
  len_mult As Integer
  len_ratio As Float
  filters[10] As Pointer
  filter_index As Integer
End Struct

Private Const SDL_INIT_AUDIO As Integer = 16
Private Const SDL_AUDIO_MASK_BITSIZE As Integer = 127

' int SDL_Init(Uint32 flags)
' Initialize the SDL library.
Private Extern SDL_Init(flags As Integer) As Integer

' SDL_AudioSpec* SDL_LoadWAV_RW(SDL_RWops * src, int freesrc, SDL_AudioSpec* spec, Uint8** audio_buf, Uint32* audio_len)
' Loads a WAVE from the data source.
Private Extern SDL_LoadWAV_RW(SDL_RWops As Pointer, freesrc As Integer, SDL_spec As SDL_AudioSpec, audio_buf As Pointer, audio_len As Pointer) As SDL_AudioSpec

' int SDL_BuildAudioCVT(SDL_AudioCVT * cvt, SDL_AudioFormat src_format, Uint8 src_channels, int src_rate, SDL_AudioFormat dst_format, Uint8 dst_channels, int dst_rate)
' Initialize an SDL_AudioCVT structure for conversion.
Private Extern SDL_BuildAudioCVT(SDL_cvt As SDL_AudioCVT, src_format As Integer, src_channels As Byte, src_rate As Integer, dst_format As Integer, dst_channels As Byte, dst_rate As Integer) As Integer

' int SDL_ConvertAudio(SDL_AudioCVT* cvt)
' Converts audio data to a desired audio format.
Private Extern SDL_ConvertAudio(SDL_cvt As SDL_AudioCVT) As Integer

' void SDL_Quit(void)
' Clean up all initialized subsystems.
Private Extern SDL_Quit()

' SDL_RWops * SDL_RWFromFile(const char *file, const char *mode)
' Create a new SDL_RWops structure for reading from and/or writing to a named file.
Private Extern SDL_RWFromFile(filewav As String, mode As String) As Pointer In "libSDL2_mixer-2.0"
 

Public Sub Main()

 Dim wav, convertito As String
 Dim data, pbb As Pointer
 Dim lun, cvtfreq, bitsize, blockalign, avgbytes As Integer
 Dim spec As New SDL_AudioSpec
 Dim cvt As New SDL_AudioCVT
 Dim fl As File
 Dim bb As Byte[]
 Dim st As Stream
 
 wav = "/percorso/del/file.wav"
 convertito = "/percorso/del/file.wav/convertito"
 
' Imposta la nuova frequenza di campionamento, nella quale il file wav sarà convertito:
 cvtfreq = 22050
 
' Inizializza la libreria SDL2:
 If SDL_Init(SDL_INIT_AUDIO) < 0 Then Error.Raise("Impossibile inizializzare la libreria SDL2 !")
  
 If IsNull(SDL_LoadWAV_RW(SDL_RWFromFile(wav, "rb"), 1, spec, VarPtr(data), VarPtr(lun))) Then 
   Error.Raise("Impossibile caricare il file audio: " & wav & " !")
 Endif
  
 If SDL_BuildAudioCVT(cvt, spec.format, spec.channels, spec.freq, spec.format, spec.channels, cvtfreq) = -1 Then
   Error.Raise("Impossibile realizzare il CVT !")
 Endif
 
 cvt.len = lun
 cvt.buf = Alloc(SizeOf(gb.Short), cvt.len)
 
' Inizia la procedura per trasferire con sicurezza i dati dall'area di memoria, puntata dal Puntatore "data", all'area di memoria puntata dal Puntatore "cvt.buf".
' Per velocizzare tale procedura si utilizzerà il Metodo "Write" di un vettore di tipo "Byte[]".
 bb = New Byte[cvt.len]
 
' Innanzitutto vengono usati i "Memory Stream" per leggere i dati contenuti dal puntatore "data":
 st = Memory data For Read
' I dati letti sono caricati nel vettore "bb" di tipo "Byte[]":
 bb.Read(st, 0, bb.Count)
 st.Close
 
' I dati ora presenti nel vettore "bb" vengono, quindi, scritti nell'area di memoria puntata dal Puntatore "cvt.buf":
 st = Memory cvt.buf For Write
 bb.Write(st, 0, bb.Count)
 st.Close
 
 If SDL_ConvertAudio(cvt) = -1 Then Error.Raise("Conversione fallita !")
 
 bitsize = spec.format And SDL_AUDIO_MASK_BITSIZE
 blockalign = (bitsize / 8) * spec.channels
 avgbytes = cvtfreq * blockalign
 
' Scrive l'header del file WAV in uscita:
 fl = Open convertito For Create
 Write #fl, &46464952 As Integer   ' RIFF
 Write #fl, (cvt.len_cvt + 36) As Integer
 Write #fl, &45564157 As Integer   ' WAVE
 Write #fl, &20746D66 As Integer   ' fmt
 Write #fl, 16 As Integer   ' chunk size
 Write #fl, 1 As Short   ' uncompressed
 Write #fl, spec.channels As Short   ' channels
 Write #fl, cvtfreq As Integer   ' sample rate
 Write #fl, avgbytes As Integer   ' average bytes per second
 Write #fl, blockalign As Short   ' block align
 Write #fl, bitsize As Short   ' significant bits per sample
 Write #fl, &61746164 As Integer   ' data
 Write #fl, cvt.len_cvt As Integer   ' size
 
 bb = New Byte[cvt.len_cvt]
 
' Vengono usati i "Memory Stream" per far leggere dal vettore "bb" i dati (ormai convertiti) contenuti dal puntatore "cvt.buf":
 st = Memory cvt.buf For Read
 bb.Read(st, 0, bb.Count)
 
' Scrive i valori contenuti dal vettore "bb" nel file precedentemente aperto:
 bb.Write(fl, 0, bb.Count)
  
' Va in chiusura:
 st.Close
 Free(cvt.buf)
 fl.Close
 SDL_Quit()
 
End


Riferimenti