del sistema sonoro ALSA per eseguire quei dati grezzi.
di Gambas.
Private Const BUFFER As Long = 512
Library "libc:6"
Private Const SEEK_SET As Integer = 0
Private Const SEEK_CUR As Integer = 1
Private Const SEEK_END As Integer = 2
Private Const SIGKILL As Integer = 9
' FILE *fopen (const char *__restrict __filename, const char *__restrict __modes)
' Open a file and create a new stream for it.
Private Extern fopen(__filename As String, __modes As String) As Pointer
' int printf (const char *__restrict __format, ...)
' Write formatted output to stdout.
Private Extern printf(__format As String) As Integer
Private Extern printf_2(__format As String, param1 As Integer, param2 As Integer, param3 As Float) As Integer Exec "printf"
' int kill (__pid_t __pid, int __sig)
' Send signal SIG to process number PID.
Private Extern kill_c(__pid As Integer, __sig As Integer) As Integer Exec "kill"
' int fseek (FILE *__stream, long int __off, int __whence)
' Seek to a certain position on STREAM.
Private Extern fseek(__stream As Pointer, __off As Long, __whence As Integer) As Integer
' long int ftell (FILE *__stream)
' Return the current position of STREAM.
Private Extern ftell(__stream As Pointer) As Long
' void *malloc (size_t __size)
' Allocate SIZE bytes of memory.
Private Extern malloc(__size As Long) As Pointer
' size_t fread (void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __stream)
' Read chunks of generic data from STREAM.
Private Extern fread(__ptr As Pointer, __size As Long, __n As Long, __stream As Pointer) As Long
' int sprintf (char *__restrict __s, const char *__restrict __format, ...)
' Write formatted output to S.
Private Extern sprintf(__str As Pointer, __format As String, param1 As Pointer) As Integer
' int strncmp (const char *__s1, const char *__s2, size_t __n)
' Compare N characters of S1 and S2.
Private Extern strncmp(__s1 As Pointer, __s2 As String, __n As Long) As Integer
' size_t fwrite (const void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __s)
' Write chunks of generic data to STREAM.
Private Extern fwrite(__ptr As Pointer, __size As Long, __n As Long, __stream As Pointer) As Long
' int fclose (FILE *__stream)
' Close STREAM.
Private Extern fclose(__stream As Pointer) As Integer
' void free (void *__ptr)
' Free a block allocated by `malloc'.
Private Extern free_c(__ptr As Pointer) Exec "free"
'''''''''''''''''''''''''''''''''''''''''''''''''''
Library "libasound:2"
Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0
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, nome As String, stream As Integer, mode As Integer) As Integer
' const char * snd_strerror (int errnum)
' Returns the message for an Error code.
Private Extern snd_strerror(errnum As Integer) As String
' int snd_pcm_set_params (snd_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int canali, 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, buffer As Pointer, uframes As Long) As Integer
' int snd_pcm_drain (snd_pcm_t *pcm)
' Stop a PCM preserving pending frames.
Private Extern snd_pcm_drain(pcm 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 filewav As String
Dim ent, ptr, usc, pcm As Pointer
Dim lun, sp, off As Long
Dim ii As New Integer[1]
Dim err, tot As Integer
Dim cc As New Short[1]
Dim h, m As Short
Dim sec As Float
filewav = "/percorso/del/file.wav"
' Apre il file "wav" in sola "lettura" binaria:
ent = fopen(filewav, "r")
If ent == 0 Then
printf("ERRORE in lettura del file wav!")
kill_c(0, SIGKILL)
Endif
' Posiziona il puntatore nell'area di memoria, puntata dalla variabile "ent", alla fine del flusso:
fseek(ent, 0, SEEK_END)
' Ritorna la quantità di dati contenuti nell'area di memoria, puntata dalla variabile "ent":
lun = ftell(ent)
' Alloca un'area di memoria di lunghezza pari al valore contenuto dalla varibile "lun":
ptr = malloc(lun)
' Riposiziona il Puntatore all'inizio del file, per poter leggere tutti i suoi dati:
fseek(ent, 0, SEEK_SET)
' Legge l'intera quantità di dati del file wav:
fread(ptr, 1, lun, ent)
' Assegna un numero di byte, presenti nell'area puntata dal Puntatore "ptr", pari alla quantità di byte occupata da un "Intero Corto".
' L'assegnazione comincia dal byte di indice 22 per estrarre il numero dei canali del file wav.
sprintf(cc.Data, "%s", ptr + 22)
' Assegna un numero di byte, presenti nell'area puntata dal Puntatore "ptr", pari alla quantità di byte occupata da un "Intero".
' L'assegnazione comincia dal byte di indice 24 per estrarre il valore della frequenza di campionamento del file wav.
sprintf(ii.Data, "%s", ptr + 24)
sp = 35
Repeat
' Legge il file a cominciare dal 37° byte (indice 36), sino a quando non trova i caratteri "data":
Inc sp
Until strncmp(ptr + sp, "data", 4) == 0
' Incrementa di otto unità la variabile "sp", per raggiungere l'indice del byte di inizio dei dati audio grezzi:
sp += 8
' Apre il file dei dati grezzi wav in sola "scrittura" binaria:
usc = fopen("/tmp/datigrezzi", "w")
If ent == 0 Then
printf("ERRORE in scrittura del file wav!")
kill_c(0, SIGKILL)
Endif
' Scrive i dati, precedentemente letti, in un nuovo file contenente i soli dati audio wav:
fwrite(ptr + sp, 1, lun - sp, usc)
' Chiude il flusso di dati in uscita per consentire la scrittura tottale dei dati grezzi nel file:
fclose(usc)
'''' ALSA ''''
' Apre il sub-sistema "PCM" di ALSA:
err = snd_pcm_open(VarPtr(pcm), "default", SND_PCM_STREAM_PLAYBACK, 0)
If err < 0 Then
printf("Errore nell'apertura del subsistema PCM: " & snd_strerror(err))
kill_c(0, SIGKILL)
Endif
' Imposta gli opportuni parametri:
err = snd_pcm_set_params(pcm, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, cc[0], ii[0], 1, 500000)
If err < 0 Then
printf("Errore nell'impostazione dei parametri audio: " & snd_strerror(err))
kill_c(0, SIGKILL)
Endif
Repeat
' Scrive i dati letti nel sub-sistema "PCM" di ALSA.
' Ad ogni giro il Puntatore avanza di BUFFER byte in avanti nell'area di memoria puntata.
err = snd_pcm_writei(pcm, ptr + sp + off, BUFFER / 4)
tot += err
sec = tot / ii[0]
h = (sec / 3600)
m = (sec - (3600 * h)) / 60
' Mostra il tempo trascorso:
printf_2("\rTempo trascorso: %d:%d:%.3lf ", h, m, (sec - (3600 * h) - (m * 60)))
off += BUFFER
Until tot >= lun / 4
' Impedisce che avvenga un troncamento inaspettato del processo dei dati audio finali:
snd_pcm_drain(pcm)
' Libera la memoria precedentemente allocata:
snd_pcm_close(pcm)
free_c(ptr)
fclose(ent)
End