Differenze tra le versioni di "Eseguire un file WAV mediante le funzioni esterne del API di libaudio e di Alsa"

Da Gambas-it.org - Wikipedia.
 
(17 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
 
E' possibile eseguire un file formato WAV utilizzando le risorse delle librerie ''Libaudio'' ed ''ALSA''. Con le funzioni della libreria ''Libaudio'' si provvederà ad aprire e leggere i dati del file audio WAV, mentre con le funzioni della libreria di ''ALSA'' si provvederà ad inviare i dati audio letti al sub-sistema PCM.
 
E' possibile eseguire un file formato WAV utilizzando le risorse delle librerie ''Libaudio'' ed ''ALSA''. Con le funzioni della libreria ''Libaudio'' si provvederà ad aprire e leggere i dati del file audio WAV, mentre con le funzioni della libreria di ''ALSA'' si provvederà ad inviare i dati audio letti al sub-sistema PCM.
  
Per fruire di tali risorse in Gambas bisognerà installare e richiamare le librerie dinamiche e condivise: "''libaudio.so.2.4''" e "''libasound.so.2''"
+
Per fruire di tali risorse in Gambas bisognerà installare e richiamare le librerie dinamiche e condivise: "''libaudio.so.2.4'' " e "''libasound.so.2.0.0'' "
 
 
  
 
Mostriamo un esempio pratico:
 
Mostriamo un esempio pratico:
Riga 8: Riga 7:
 
   
 
   
 
   
 
   
  Library "libaudio:2.4"
+
  Library "<FONT Color=blue>libaudio:2.4</font>"
 
   
 
   
 
  Public Struct WaveInfo
 
  Public Struct WaveInfo
Riga 42: Riga 41:
 
   
 
   
 
   
 
   
  Library "libasound:2"
+
  Library "<FONT Color=red>libasound:2.0.0</font>"
 
   
 
   
 
  Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0
 
  Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0
Riga 48: Riga 47:
 
  Private Const SND_PCM_FORMAT_S16_LE As Integer = 2
 
  Private Const SND_PCM_FORMAT_S16_LE As Integer = 2
 
  Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3
 
  Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3
+
 
 
  <FONT Color=gray>' ''int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''
 
  <FONT Color=gray>' ''int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''
 
  ' ''Opens a PCM.''</font>
 
  ' ''Opens a PCM.''</font>
Riga 60: Riga 59:
 
  ' ''Write interleaved frames to a PCM.''</font>
 
  ' ''Write interleaved frames to a PCM.''</font>
 
  Private Extern snd_pcm_writei(pcm As Pointer, buf As Pointer, size As Integer) As Integer
 
  Private Extern snd_pcm_writei(pcm As Pointer, buf As Pointer, size As Integer) As Integer
 +
 
 +
<FONT Color=gray>' ''int snd_pcm_drain (snd_pcm_t *pcm)''
 +
' ''Stop a PCM preserving pending frames.''</font>
 +
Private Extern snd_pcm_drain(pcmP As Pointer) As Integer
 
   
 
   
 
  <FONT Color=gray>' ''int snd_pcm_close (snd_pcm_t *pcm)''
 
  <FONT Color=gray>' ''int snd_pcm_close (snd_pcm_t *pcm)''
  ' ''Close PCM handle''</font>
+
  ' ''Close PCM handle.''</font>
 
  Private Extern snd_pcm_close(pcm As Pointer) As Integer
 
  Private Extern snd_pcm_close(pcm As Pointer) As Integer
 
   
 
   
Riga 70: Riga 73:
 
   Dim buf, handle As Pointer
 
   Dim buf, handle As Pointer
 
   Dim fileWav As String
 
   Dim fileWav As String
   Dim err, bit, msec, frames, n As Integer
+
   Dim err, bit, msec, obr, frames, i, n As Integer
 
   Dim info As New WaveInfo
 
   Dim info As New WaveInfo
 
   
 
   
Riga 78: Riga 81:
 
   If IsNull(info) Then Error.Raise("Errore nella lettura del file wav !")
 
   If IsNull(info) Then Error.Raise("Errore nella lettura del file wav !")
 
    
 
    
   buf = Alloc(BUFFER)
+
   buf = Alloc(SizeOf(gb.Byte), BUFFER)
   If IsNull(buf) Then Error.Raise("Impossibile allocare memoria !")
+
   If buf = 0 Then Error.Raise("Impossibile allocare memoria !")
   
+
 
 +
  Print "File audio:      "; fileWav
 
   Print "Numero canali:  "; info.channels
 
   Print "Numero canali:  "; info.channels
 
   Print "Risoluzione bit: "; info.bitsPerSample; " bit"
 
   Print "Risoluzione bit: "; info.bitsPerSample; " bit"
 
   Print "Frequenza camp.: "; info.sampleRate; " Hertz"
 
   Print "Frequenza camp.: "; info.sampleRate; " Hertz"
   Print "Overall BitRate: "; info.channels * info.bitsPerSample * info.sampleRate; " bps"
+
   obr = info.channels * info.bitsPerSample * info.sampleRate
   msec = Fix((info.dataSize * 8) / (info.sampleRate * info.bitsPerSample * info.channels) * 1000)
+
  Print "Overall BitRate: "; obr; " bps"
   Print "Durata:          "; CStr(Date(0, 0, 0, 0, 0, 0, msec))
+
   msec = Fix(((info.dataSize * 8) / obr) * 1000)
 +
   Print "Durata:          "; CStr(Time(0, 0, 0, msec))
 
   Print
 
   Print
 
   
 
   
Riga 102: Riga 107:
 
   If err < 0 Then Error.Raise("Impossibile impostare i parametri audio alla libreria Alsa !")
 
   If err < 0 Then Error.Raise("Impossibile impostare i parametri audio alla libreria Alsa !")
 
      
 
      
 +
  i = info.bitsPerSample / (8 / info.channels)
 
      
 
      
 
   While n < info.dataSize
 
   While n < info.dataSize
 
+
   
 
     err = WaveSeekFile(n, info)
 
     err = WaveSeekFile(n, info)
 
     If err Then Error.Raise("Impossibile posizionarsi nel file wav !")
 
     If err Then Error.Raise("Impossibile posizionarsi nel file wav !")
 
+
   
 
     WaveReadFile(buf, BUFFER, info)
 
     WaveReadFile(buf, BUFFER, info)
 
+
   
     frames = snd_pcm_writei(handle, buf, BUFFER / (info.bitsPerSample / (8 / info.channels)))
+
     frames = snd_pcm_writei(handle, buf, BUFFER / i)
     If frames < 0 Then
+
     If frames < 0 Then Error.Raise("Errore nella funzione 'snd_pcm_writei()' !")
      Error.Raise("Errore nella funzione 'snd_pcm_writei()' !")
+
      
     Else
 
      Write #File.Out, "\rTempo trascorso: " & Date(0, 0, 0, 0, 0, 0, (n * 8) / (info.sampleRate * info.bitsPerSample * info.channels) * 1000)
 
    Endif
 
 
 
 
     n += BUFFER
 
     n += BUFFER
 +
   
 +
    Write "\rTempo trascorso: " & Time(0, 0, 0, ((n * 8) / obr) * 1000)
 +
       
 +
  Wend
 +
 +
<FONT Color=gray>' ''Impedisce che al termine l'esecuzione venga troncata inaspettatamente:''</font>
 +
  snd_pcm_drain(handle)
 
    
 
    
  Wend
 
 
    
 
    
 
  <FONT Color=gray>' ''Va in chiusura:''</font>
 
  <FONT Color=gray>' ''Va in chiusura:''</font>
 
   snd_pcm_close(handle)
 
   snd_pcm_close(handle)
 +
  Free(buf)
 
   WaveCloseFile(info)
 
   WaveCloseFile(info)
  Free(buf)
 
 
    
 
    
 
  '''End'''
 
  '''End'''

Versione attuale delle 17:13, 22 ott 2021

E' possibile eseguire un file formato WAV utilizzando le risorse delle librerie Libaudio ed ALSA. Con le funzioni della libreria Libaudio si provvederà ad aprire e leggere i dati del file audio WAV, mentre con le funzioni della libreria di ALSA si provvederà ad inviare i dati audio letti al sub-sistema PCM.

Per fruire di tali risorse in Gambas bisognerà installare e richiamare le librerie dinamiche e condivise: "libaudio.so.2.4 " e "libasound.so.2.0.0 "

Mostriamo un esempio pratico:

Private Const BUFFER As Integer = 32


Library "libaudio:2.4"

Public Struct WaveInfo
  fp As Pointer
  comment As Pointer
  channels As Short
  bitsPerSample As Short
  sampleRate As Integer
  dataOffset As Integer
  numSamples As Integer
  fileSize As Integer
  dataSize As Integer
  sizeOffset As Integer
  writing As Integer
  formatSh As Short
End Struct

' WaveInfo * WaveOpenFileForReading(const char *name)
' Open an wave file for reading.
Private Extern WaveOpenFileForReading(name As String) As WaveInfo

' int WaveSeekFile(int n, WaveInfo *wi)
' Seek to a position in an wave file.
Private Extern WaveSeekFile(n As Integer, wi As WaveInfo) As Integer

' int WaveReadFile(char *p, int n, WaveInfo *wi)
' Read wave data from an audio file.
Private Extern WaveReadFile(p As Pointer, n As Integer, wi As WaveInfo) As Integer

' int WaveCloseFile(WaveInfo *wi)
' Close an wave file description.
Private Extern WaveCloseFile(wi As WaveInfo) As Integer


Library "libasound:2.0.0"

Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0
Private Const SND_PCM_FORMAT_U8 As Integer = 1
Private Const SND_PCM_FORMAT_S16_LE As Integer = 2
Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3
 
' int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)
' Opens a PCM.
Private Extern snd_pcm_open(pcm As Pointer, name As String, streamI As Integer, mode As Integer) As Integer

' int snd_pcm_set_params (snd_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency)
' Set the hardware and software parameters in a simple way.
Private Extern snd_pcm_set_params(pcm As Pointer, formatI As Integer, accessI As Integer, channels As Integer, rate As Integer, soft_resample As Integer, latency As Integer) As Integer

' snd_pcm_sframes_t snd_pcm_writei (snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
' Write interleaved frames to a PCM.
Private Extern snd_pcm_writei(pcm As Pointer, buf As Pointer, size As Integer) As Integer
 
' int snd_pcm_drain (snd_pcm_t *pcm)
' Stop a PCM preserving pending frames.
Private Extern snd_pcm_drain(pcmP As Pointer) As Integer

' int snd_pcm_close (snd_pcm_t *pcm)
' Close PCM handle.
Private Extern snd_pcm_close(pcm As Pointer) As Integer


Public Sub Main()

 Dim buf, handle As Pointer
 Dim fileWav As String
 Dim err, bit, msec, obr, frames, i, n As Integer
 Dim info As New WaveInfo

  fileWav = "/percorso/del/file.wav"

  info = WaveOpenFileForReading(fileWav)
  If IsNull(info) Then Error.Raise("Errore nella lettura del file wav !")
 
  buf = Alloc(SizeOf(gb.Byte), BUFFER)
  If buf = 0 Then Error.Raise("Impossibile allocare memoria !")
  
  Print "File audio:      "; fileWav
  Print "Numero canali:   "; info.channels
  Print "Risoluzione bit: "; info.bitsPerSample; " bit"
  Print "Frequenza camp.: "; info.sampleRate; " Hertz"
  obr = info.channels * info.bitsPerSample * info.sampleRate
  Print "Overall BitRate: "; obr; " bps"
  msec = Fix(((info.dataSize * 8) / obr) * 1000)
  Print "Durata:          "; CStr(Time(0, 0, 0, msec))
  Print

  err = snd_pcm_open(VarPtr(handle), "default", SND_PCM_STREAM_PLAYBACK, 0)
  If err < 0 Then Error.Raise("Impossibile inizializzare la libreria Alsa !")
   
  Select Case info.bitsPerSample
    Case 16
      bit = SND_PCM_FORMAT_S16_LE
    Case 8
      bit = SND_PCM_FORMAT_U8
  End Select
  
  err = snd_pcm_set_params(handle, bit, SND_PCM_ACCESS_RW_INTERLEAVED, info.channels, info.sampleRate, 1, 500000)
  If err < 0 Then Error.Raise("Impossibile impostare i parametri audio alla libreria Alsa !")
   
  i = info.bitsPerSample / (8 / info.channels)
   
  While n < info.dataSize
    
    err = WaveSeekFile(n, info)
    If err Then Error.Raise("Impossibile posizionarsi nel file wav !")
    
    WaveReadFile(buf, BUFFER, info)
    
    frames = snd_pcm_writei(handle, buf, BUFFER / i)
    If frames < 0 Then Error.Raise("Errore nella funzione 'snd_pcm_writei()' !")
    
    n += BUFFER
    
    Write "\rTempo trascorso: " & Time(0, 0, 0, ((n * 8) / obr) * 1000)
       
  Wend

' Impedisce che al termine l'esecuzione venga troncata inaspettatamente:
  snd_pcm_drain(handle)
  
  
' Va in chiusura:
  snd_pcm_close(handle)
  Free(buf)
  WaveCloseFile(info)
  
End



Riferimenti