Iluminado por el Santo, semper benedictus, escribí un código simple y corto que, utilizando exclusivamente las funciones externas del lenguaje C, lee un archivo de audio WAV, extrapola solo los datos de audio que finalmente va a escribir en un nuevo archivo. Luego, usando las funciones externas de ALSA ejecuta estos datos de audio.
En resumen, no he utilizado ninguna función nativa de gambas, sólo funciones externas.
Código comentado en italiano, disculpe.
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 = "/ruta/del/archivo.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
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 = "/ruta/del/archivo.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