Differenze tra le versioni di "Eseguire un file WAV mediante le funzioni esterne del API di PulseAudio"

Da Gambas-it.org - Wikipedia.
(Creata pagina con 'Per la esigua quantità di funzioni necessarie e la loro semplicità d'uso mostreremo di seguito direttamente un codice esemplificativo, ma debitamente spiegato, con il quale ...')
 
 
(17 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
 
Per la esigua quantità di funzioni necessarie e la loro semplicità d'uso mostreremo di seguito direttamente un codice esemplificativo, ma debitamente spiegato, con il quale eseguire un file WAV.
 
Per la esigua quantità di funzioni necessarie e la loro semplicità d'uso mostreremo di seguito direttamente un codice esemplificativo, ma debitamente spiegato, con il quale eseguire un file WAV.
  Library "libpulse-simple:0.0.4"
+
 
 +
E' necessario avere installata nel sistema e richiamare in Gambas la libreria condivisa: "''libpulse-simple.so.0.1.1''".
 +
  Library "libpulse-simple:0.1.1"
 
   
 
   
 
  <FONT color=gray>' ''Dichiariamo una "Struttura" per passare i valori dei campioni audio necessari per l'esecuzione dei dati audio del file WAV:''</font>
 
  <FONT color=gray>' ''Dichiariamo una "Struttura" per passare i valori dei campioni audio necessari per l'esecuzione dei dati audio del file WAV:''</font>
 
  Public Struct pa_sample_spec
 
  Public Struct pa_sample_spec
   formato As Byte
+
   formato As Integer
 
   rate As Integer
 
   rate As Integer
 
   channels As Byte
 
   channels As Byte
Riga 12: Riga 14:
 
  Private Const PA_SAMPLE_S16LE As Byte = 3      <FONT color=gray>' ''Signed 16 Bit PCM, little endian (PC)''</font>
 
  Private Const PA_SAMPLE_S16LE As Byte = 3      <FONT color=gray>' ''Signed 16 Bit PCM, little endian (PC)''</font>
 
   
 
   
  <FONT color=gray size=1>' ''pa_simple* pa_simple_new (const char *server, const char *name, pa_stream_direction_t dir, const char *dev, const char *stream_name, const pa_sample_spec *ss, const pa_channel_map *map, const pa_buffer_attr *attr, int *error)''
+
  <FONT color=gray size=1>' ''pa_simple* pa_simple_new (const char *server, const char *name, pa_stream_direction_t dir, const char *dev, const char *stream_name, const pa_sample_spec *ss, const pa_channel_map *map, const pa_buffer_attr *attr, int *error)''</font>
  ' ''Crea una connessione col server sonoro.''</font>
+
  <FONT color=gray size=2>' ''Crea una connessione col server sonoro.''</font>
  <FONT size=1>Private Extern pa_simple_new(server$ As String, name As String, direct As Byte, dev As String, stream_name As String, ss As Pa_sample_spec, map As Pointer, attr As Pointer, err As Pointer) As Pointer</font>
+
  <FONT size=2>Private Extern pa_simple_new(server$ As String, name As String, direct As Byte, dev As String, stream_name As String, ss As Pa_sample_spec, map As Pointer, attr As Pointer, err As Pointer) As Pointer</font>
 
   
 
   
 
  <FONT color=gray>' ''int pa_simple_write (pa_simple *s, const void *data, size_t bytes, int *error)''
 
  <FONT color=gray>' ''int pa_simple_write (pa_simple *s, const void *data, size_t bytes, int *error)''
 
  ' ''Scrive una certa quantità di dati nel server sonoro.''</font>
 
  ' ''Scrive una certa quantità di dati nel server sonoro.''</font>
  Private Extern pa_simple_write(sP As Pointer, dataB As Byte[], bytes As Integer, err As Pointer) As Pointer
+
  Private Extern pa_simple_write(sP As Pointer, data As Pointer, bytes As Integer, err As Pointer) As Integer
 
   
 
   
 
  <FONT color=gray>' ''int pa_simple_drain (pa_simple *s, int *error)''
 
  <FONT color=gray>' ''int pa_simple_drain (pa_simple *s, int *error)''
 
  ' ''Attende sino a quando tutti i dati scritti nel server sonoro vengono eseguiti.''</font>
 
  ' ''Attende sino a quando tutti i dati scritti nel server sonoro vengono eseguiti.''</font>
  Private Extern pa_simple_drain(sP As Pointer, err As Pointer) As Pointer
+
  Private Extern pa_simple_drain(sP As Pointer, err As Pointer) As Integer
 
   
 
   
 
  <FONT color=gray>' ''void pa_simple_free (pa_simple *s)''
 
  <FONT color=gray>' ''void pa_simple_free (pa_simple *s)''
Riga 29: Riga 31:
 
   
 
   
 
   
 
   
  '''Public''' Sub Button1_Click()
+
  Public Sub Main()
 
   
 
   
 
   Dim pss As New Pa_sample_spec
 
   Dim pss As New Pa_sample_spec
Riga 36: Riga 38:
 
   Dim fileWAV As String
 
   Dim fileWAV As String
 
   Dim p As Pointer
 
   Dim p As Pointer
   Dim dimensione As Integer
+
   Dim dimensione, obr As Integer
 
   Dim buf As Byte[]
 
   Dim buf As Byte[]
 
   Dim fl As File
 
   Dim fl As File
 
   
 
   
  fileWAV = "''/percorso/del/file.wav''"
+
  fileWAV = "<FONT color=darkgreen>>''/percorso/del/file.wav''</font>"
 
    
 
    
  fl = Open fileWAV For Read
+
  fl = Open fileWAV For Read
 
   
 
   
  dimensione = Lof(fl)
+
  dimensione = Lof(fl)
 
   
 
   
  <FONT color=gray>' ''Vengono assegati ai rispettivi membri della "Struttura" i necessari valori per l'esecuzione del file wav.''
+
  <FONT color=gray>' ''Vengono assegnati ai rispettivi membri della "Struttura" i necessari valori per l'esecuzione del file wav.''
 
  ' ''Vengono, altresì, mostrate alcune informazioni sul file wav:''</font>
 
  ' ''Vengono, altresì, mostrate alcune informazioni sul file wav:''</font>
  With pss
+
  With pss
    .formato = PA_SAMPLE_S16LE
+
    .formato = PA_SAMPLE_S16LE
    Seek #fl, 22
+
    Seek #fl, 22
    .channels = Read #fl As Short
+
    .channels = Read #fl As Short
    .rate = Read #fl As Integer
+
    .rate = Read #fl As Integer
    Print "File wav: "; Null, fileWAV
+
    Print "File wav:   "; fileWAV
    Print "Canali: "; Null, .channels
+
    Print "Canali:     "; .channels
    Print "Frequenza: "; Null, .rate; " hertz"
+
    Print "Frequenza:   "; .rate; " hertz"
    Seek #fl, 34
+
    Seek #fl, 34
    bit = Read #fl As Short
+
    bit = Read #fl As Short
    Print "Risoluzione: "; Null, bit; " bit"
+
    Print "Risoluzione: "; bit; " bit"
    Print "Durata: "; Null, Date(0, 0, 0, 0, 0, 0, ((Lof(fl) * 8) / (.rate * bit * .channels)) * 1000)
+
    obr = .rate * bit * .channels
  End With
+
    Print "Durata:     "; Time(0, 0, 0, ((dimensione * 8) / obr) * 1000)
 +
  End With
 +
  Print
 
    
 
    
 
  <FONT color=gray>' ''Viene quindi creata una connessione con il server sonoro per il flusso di dati audio da eseguire.''
 
  <FONT color=gray>' ''Viene quindi creata una connessione con il server sonoro per il flusso di dati audio da eseguire.''
Riga 66: Riga 70:
 
  ' ''- NUll: viene usato il server sonoro di default;''
 
  ' ''- NUll: viene usato il server sonoro di default;''
 
  ' ''- "nome qualsiasi": il nome dell'applicazione;''
 
  ' ''- "nome qualsiasi": il nome dell'applicazione;''
  ' ''- PA_STREAM_PLAYBACK: stabilisce che il flussosarà in uscita, ossia in esecuzione di un file WAV;''
+
  ' ''- PA_STREAM_PLAYBACK: stabilisce che il flusso sarà in uscita, ossia in esecuzione di un file WAV;''
 
  ' ''- Null: viene usato il dispositivo sonoro di default;''
 
  ' ''- Null: viene usato il dispositivo sonoro di default;''
 
  ' ''- "testo qualsiasi": una testo descrittivo del flusso dati audio del file;''
 
  ' ''- "testo qualsiasi": una testo descrittivo del flusso dati audio del file;''
Riga 73: Riga 77:
 
  ' ''- Null: vengono usati attributi di buffering di default;''
 
  ' ''- Null: vengono usati attributi di buffering di default;''
 
  ' ''- Null: vengono ignorati i codici di errore sollevati.''</font>
 
  ' ''- Null: vengono ignorati i codici di errore sollevati.''</font>
  p = pa_simple_new(Null, "nome qualsiasi", PA_STREAM_PLAYBACK, Null, "testo qualsiasi", pss, Null, Null, Null)
+
  p = pa_simple_new(Null, "nome qualsiasi", PA_STREAM_PLAYBACK, Null, "testo qualsiasi", pss, 0, 0, 0)
 +
  If p == 0 Then Error.Raise("Impossible inizializzare la libreria 'Pulseaudio' !")
 +
 
 +
  Seek #fl, 0
 
   
 
   
  Seek #fl, 0
+
  buf = New Byte[DimBuffer]
 
  buf = New Byte[DimBuffer]
 
 
   
 
   
 
  <FONT color=gray>' ''Viene eseguito un ciclo per la lettura dei dati audio dal file, e per la successiva scrittura nel server sonoro:''</font>
 
  <FONT color=gray>' ''Viene eseguito un ciclo per la lettura dei dati audio dal file, e per la successiva scrittura nel server sonoro:''</font>
  Do
+
  Repeat
+
   
 
  <FONT color=gray>' ''Viene evitato l'errore di "Out of bound" nel vettore "buf[]":''</font>
 
  <FONT color=gray>' ''Viene evitato l'errore di "Out of bound" nel vettore "buf[]":''</font>
    If dimensione - Seek(fl) < DimBuffer Then DimBuffer = dimensione - Seek(fl)
+
    If dimensione - Seek(fl) < DimBuffer Then DimBuffer = dimensione - Seek(fl)
 
 
<FONT color=gray>' ''La successiva funzione "pa_simple_write" prevede un ''Puntatore'' al buffer contenente i dati da scrivere,''
 
' ''è possibile anche utilizzare un vettore di tipo "Byte[]", che verrà ad ogni ciclo riempito da una quantità di dati''
 
' ''pari al valore stabilito nel terzo parametro della predetta funzione di scrittura:''</font>
 
    buf.Read(fl, 0, DimBuffer)
 
 
      
 
      
    pa_simple_write(p, buf, DimBuffer, Null)
+
<FONT color=gray>' ''Usa un vettore di tipo "Byte[]", che viene ad ogni ciclo riempito da una quantità di dati pari al valore stabilito:''</font>
     
+
    buf.Read(fl, 0, DimBuffer)
  <FONT color=gray>' ''Poiché la funzione di scrittura dei dati nel server sonoro è bloccante,''
+
  <FONT color=gray>' ''La funzione "pa_simple_write" prevede un ''Puntatore'' al buffer contenente i dati da scrivere:''</font>
' ''imponiamo un'attesa di al minimo per consentire all'utente di agire su eventuali oggetti posti sul Form.''
+
    pa_simple_write(p, buf.Data, DimBuffer, 0)
' ''Nel caso di applicazione "a riga di comando" questa istruzione ovviamente non è necessaria.''</font>
+
   
    Wait 0.001
+
<FONT color=gray>' ''Mostra il tempo trascorso dall'inizio dell'esecuzione del file audio:''</font>
 +
    Write "\r" & CStr(Time(0, 0, 0, ((Seek(fl) * 8) / obr) * 1000))
 
    
 
    
  Loop Until Seek(fl) >= dimensione
+
  Until Seek(fl) >= dimensione
+
 
  pa_simple_drain(p, Null)
+
  pa_simple_drain(p, 0)
+
 
 
 
  <FONT color=gray>' ''Va in Chiusura:''</font>
 
  <FONT color=gray>' ''Va in Chiusura:''</font>
  fl.Close
+
  Print "Esecuzione terminata !"
  pa_simple_free(p)
+
  fl.Close
+
  pa_simple_free(p)
  '''End'''
+
 
 +
  End
 +
 
 +
 
 +
 
 +
=Riferimenti=
 +
* http://www.freedesktop.org/wiki/Software/PulseAudio/

Versione attuale delle 10:35, 26 nov 2023

Per la esigua quantità di funzioni necessarie e la loro semplicità d'uso mostreremo di seguito direttamente un codice esemplificativo, ma debitamente spiegato, con il quale eseguire un file WAV.

E' necessario avere installata nel sistema e richiamare in Gambas la libreria condivisa: "libpulse-simple.so.0.1.1".

Library "libpulse-simple:0.1.1"

' Dichiariamo una "Struttura" per passare i valori dei campioni audio necessari per l'esecuzione dei dati audio del file WAV:
Public Struct pa_sample_spec
  formato As Integer
  rate As Integer
  channels As Byte
End Struct
 
Private Const PA_STREAM_PLAYBACK As Byte = 1
Private Const PA_SAMPLE_S16LE As Byte = 3       ' Signed 16 Bit PCM, little endian (PC)

' pa_simple* pa_simple_new (const char *server, const char *name, pa_stream_direction_t dir, const char *dev, const char *stream_name, const pa_sample_spec *ss, const pa_channel_map *map, const pa_buffer_attr *attr, int *error)
' Crea una connessione col server sonoro.
Private Extern pa_simple_new(server$ As String, name As String, direct As Byte, dev As String, stream_name As String, ss As Pa_sample_spec, map As Pointer, attr As Pointer, err As Pointer) As Pointer

' int pa_simple_write (pa_simple *s, const void *data, size_t bytes, int *error)
' Scrive una certa quantità di dati nel server sonoro.
Private Extern pa_simple_write(sP As Pointer, data As Pointer, bytes As Integer, err As Pointer) As Integer

' int pa_simple_drain (pa_simple *s, int *error)
' Attende sino a quando tutti i dati scritti nel server sonoro vengono eseguiti.
Private Extern pa_simple_drain(sP As Pointer, err As Pointer) As Integer

' void pa_simple_free (pa_simple *s)
' Chiude e libera la connessione con il server sonoro. 
Private Extern pa_simple_free(sP As Pointer)


Public Sub Main()

 Dim pss As New Pa_sample_spec
 Dim DimBuffer As Short = 1024
 Dim bit As Short
 Dim fileWAV As String
 Dim p As Pointer
 Dim dimensione, obr As Integer
 Dim buf As Byte[]
 Dim fl As File

 fileWAV = ">/percorso/del/file.wav"
 
 fl = Open fileWAV For Read

 dimensione = Lof(fl)

' Vengono assegnati ai rispettivi membri della "Struttura" i necessari valori per l'esecuzione del file wav.
' Vengono, altresì, mostrate alcune informazioni sul file wav:
 With pss
   .formato = PA_SAMPLE_S16LE
   Seek #fl, 22
   .channels = Read #fl As Short
   .rate = Read #fl As Integer
   Print "File wav:    "; fileWAV
   Print "Canali:      "; .channels
   Print "Frequenza:   "; .rate; " hertz"
   Seek #fl, 34
   bit = Read #fl As Short
   Print "Risoluzione: "; bit; " bit"
   obr = .rate * bit * .channels
   Print "Durata:      "; Time(0, 0, 0, ((dimensione * 8) / obr) * 1000)
 End With
 Print
 
' Viene quindi creata una connessione con il server sonoro per il flusso di dati audio da eseguire.
' Riguardo ai parametri impostati nella seguente funzione si precisa che:
' - NUll: viene usato il server sonoro di default;
' - "nome qualsiasi": il nome dell'applicazione;
' - PA_STREAM_PLAYBACK: stabilisce che il flusso sarà in uscita, ossia in esecuzione di un file WAV;
' - Null: viene usato il dispositivo sonoro di default;
' - "testo qualsiasi": una testo descrittivo del flusso dati audio del file;
' - pss: le caratteristiche dei campioni audio del flusso di dati;
' - Null: viene usata la mappatura dei canali di default;
' - Null: vengono usati attributi di buffering di default;
' - Null: vengono ignorati i codici di errore sollevati.
 p = pa_simple_new(Null, "nome qualsiasi", PA_STREAM_PLAYBACK, Null, "testo qualsiasi", pss, 0, 0, 0)
 If p == 0 Then Error.Raise("Impossible inizializzare la libreria 'Pulseaudio' !")
 
 Seek #fl, 0

 buf = New Byte[DimBuffer]

' Viene eseguito un ciclo per la lettura dei dati audio dal file, e per la successiva scrittura nel server sonoro:
 Repeat
   
' Viene evitato l'errore di "Out of bound" nel vettore "buf[]":
   If dimensione - Seek(fl) < DimBuffer Then DimBuffer = dimensione - Seek(fl)
   
' Usa un vettore di tipo "Byte[]", che viene ad ogni ciclo riempito da una quantità di dati pari al valore stabilito:
   buf.Read(fl, 0, DimBuffer)
' La funzione "pa_simple_write" prevede un Puntatore al buffer contenente i dati da scrivere:
   pa_simple_write(p, buf.Data, DimBuffer, 0)
    
' Mostra il tempo trascorso dall'inizio dell'esecuzione del file audio:
   Write "\r" & CStr(Time(0, 0, 0, ((Seek(fl) * 8) / obr) * 1000))
  
 Until Seek(fl) >= dimensione
 
 pa_simple_drain(p, 0)
 
' Va in Chiusura:
 Print "Esecuzione terminata !"
 fl.Close
 pa_simple_free(p)
 
End


Riferimenti