Differenze tra le versioni di "Eseguire un file WAV usando l'API di SndFile e di Alsa"
Da Gambas-it.org - Wikipedia.
Riga 5: | Riga 5: | ||
Mostreremo di seguito un semplice codice per l'esecuzione di un file wav: | Mostreremo di seguito un semplice codice per l'esecuzione di un file wav: | ||
− | + | Public Struct SF_INFO | |
+ | frames As Long | ||
samplerate As Integer | samplerate As Integer | ||
− | channels As Integer | + | channels As Integer |
formatI As Integer | formatI As Integer | ||
sections As Integer | sections As Integer | ||
seekable As Integer | seekable As Integer | ||
− | + | End Struct | |
Riga 17: | Riga 18: | ||
<FONT color=gray>' ''SNDFILE * sf_open (const char *path, int mode, SF_INFO *sfinfo) --> Apre un file per la lettura''</font> | <FONT color=gray>' ''SNDFILE * sf_open (const char *path, int mode, SF_INFO *sfinfo) --> Apre un file per la lettura''</font> | ||
− | + | Private Extern sf_open(path As String, mode As Integer, SFinf As SF_INFO) As Pointer | |
<FONT color=gray>' ''sf_count_t sf_read_short(SNDFILE *sndfile, float *ptr, sf_count_t items) --> Legge i dati del file wav''</font> | <FONT color=gray>' ''sf_count_t sf_read_short(SNDFILE *sndfile, float *ptr, sf_count_t items) --> Legge i dati del file wav''</font> | ||
− | + | Private Extern sf_read_short(sndfile As Pointer, ptr As Pointer, items As Integer) As Integer | |
<FONT color=gray>' ''int sf_close (SNDFILE *sndfile) --> Chiude il file precedentemente aperto''</font> | <FONT color=gray>' ''int sf_close (SNDFILE *sndfile) --> Chiude il file precedentemente aperto''</font> | ||
− | + | Private Extern sf_close(sndfile As Pointer) As Integer | |
− | + | Private Const BUFFER_LEN As Short = 1024 | |
− | + | Private Const SFM_READ As Byte = 16 | |
Library "<FONT color=red>libasound:2</font>" | Library "<FONT color=red>libasound:2</font>" | ||
− | + | Private Const SND_PCM_STREAM_PLAYBACK As Byte = 0 | |
− | + | Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Byte = 3 | |
− | + | Private Const SND_PCM_FORMAT_U8 As Byte = 1 | |
− | + | Private Const nomen As String = "default" | |
<FONT color=gray>' ''int snd_pcm_open(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''</font> | <FONT color=gray>' ''int snd_pcm_open(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''</font> | ||
− | + | Private Extern snd_pcm_open(pcmP As Pointer, nome As String, stream As Integer, mode As Integer) As Integer | |
<FONT color=gray>' ''const char * snd_strerror (int errnum) --> Returns the message For an Error code.''</font> | <FONT color=gray>' ''const char * snd_strerror (int errnum) --> Returns the message For an Error code.''</font> | ||
− | + | Private Extern snd_strerror(errnum As Integer) As String | |
<FONT color=gray>' ''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) | <FONT color=gray>' ''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 aPrivate Const MPG123_ADD_FLAGS As Byte = 2 simple way.''</font> | ' ''Set the hardware And software parameters In aPrivate Const MPG123_ADD_FLAGS As Byte = 2 simple way.''</font> | ||
− | + | Private Extern snd_pcm_set_params(pcmP As Pointer, formatB As Byte, accessB As Byte, channels As Integer, rate As Integer, soft_resample As Integer, latency As Integer) As Integer | |
<FONT color=gray>' ''snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)''</font> | <FONT color=gray>' ''snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)''</font> | ||
− | + | Private Extern snd_pcm_writei(pcmP As Pointer, buffP As Pointer, uframes As Long) As Integer | |
<FONT color=gray>' ''int snd_pcm_close(snd_pcm_t **pcm)''</font> | <FONT color=gray>' ''int snd_pcm_close(snd_pcm_t **pcm)''</font> | ||
− | + | Private Extern snd_pcm_close(pcmP As Pointer) | |
− | + | ||
− | |||
− | |||
− | |||
− | |||
− | |||
'''Public''' Sub Button1_Click() | '''Public''' Sub Button1_Click() | ||
Riga 63: | Riga 59: | ||
Dim infile, buffer, handle As Pointer | Dim infile, buffer, handle As Pointer | ||
Dim sfinfo As New SF_INFO | Dim sfinfo As New SF_INFO | ||
− | Dim err, frequenza, conto, frames, canali | + | Dim err, frequenza, conto, frames, canali As Integer |
Riga 72: | Riga 68: | ||
<FONT color=gray>' ''Ricava la frequenza di campionamento ed il numero di canali del file wav:''</font> | <FONT color=gray>' ''Ricava la frequenza di campionamento ed il numero di canali del file wav:''</font> | ||
− | frequenza = | + | With sfinfo |
− | + | frequenza = .samplerate | |
+ | canali = .channels | ||
+ | End With | ||
<FONT color=gray>''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' | <FONT color=gray>''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' | ||
Riga 93: | Riga 91: | ||
<FONT color=gray>' ''I dati audio vengono inviati al sub-sistema "PCM" di Alsa, attraverso la lettura della variabile'' | <FONT color=gray>' ''I dati audio vengono inviati al sub-sistema "PCM" di Alsa, attraverso la lettura della variabile'' | ||
' ''qui denominata "buffer". La quantità unitaria di dati scritti nell'handle del sub-sistema PCM deve essere uguale'' | ' ''qui denominata "buffer". La quantità unitaria di dati scritti nell'handle del sub-sistema PCM deve essere uguale'' | ||
− | ' '' | + | ' ''al valore del 3° argomento della precedente funzione "sf_read_short" diviso il numero di canali del file audio:''</font> |
− | frames = snd_pcm_writei(handle, <FONT color=darkorange><B>buffer</b></font>, BUFFER_LEN / | + | frames = snd_pcm_writei(handle, <FONT color=darkorange><B>buffer</b></font>, BUFFER_LEN / sfinfo.channels) |
If (frames < 0) Then Error.Raise("Errore alla funzione 'snd_pcm_writei': " & snd_strerror(err)) | If (frames < 0) Then Error.Raise("Errore alla funzione 'snd_pcm_writei': " & snd_strerror(err)) | ||
Riga 105: | Riga 103: | ||
snd_pcm_close(handle) | snd_pcm_close(handle) | ||
sf_close(infile) | sf_close(infile) | ||
− | + | ||
− | |||
'''End''' | '''End''' | ||
Versione delle 15:42, 8 set 2014
SndFile è una libreria, scritta in C, per leggere e scrivere file che contengono suono campionato (come il formato WAV ed il formato AIFF) attraverso una libreria interfaccia standard.
Pertanto, coniugheremo le librerie di SndFile e di Alsa, assegnando a SndFile il compito di leggere ed estrarre i dati del file audio, ed ad Alsa quello di eseguire tali dati audio.
Mostreremo di seguito un semplice codice per l'esecuzione di un file wav:
Public Struct SF_INFO frames As Long samplerate As Integer channels As Integer formatI As Integer sections As Integer seekable As Integer End Struct Library "libsndfile:1.0.25" ' SNDFILE * sf_open (const char *path, int mode, SF_INFO *sfinfo) --> Apre un file per la lettura Private Extern sf_open(path As String, mode As Integer, SFinf As SF_INFO) As Pointer ' sf_count_t sf_read_short(SNDFILE *sndfile, float *ptr, sf_count_t items) --> Legge i dati del file wav Private Extern sf_read_short(sndfile As Pointer, ptr As Pointer, items As Integer) As Integer ' int sf_close (SNDFILE *sndfile) --> Chiude il file precedentemente aperto Private Extern sf_close(sndfile As Pointer) As Integer Private Const BUFFER_LEN As Short = 1024 Private Const SFM_READ As Byte = 16 Library "libasound:2" Private Const SND_PCM_STREAM_PLAYBACK As Byte = 0 Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Byte = 3 Private Const SND_PCM_FORMAT_U8 As Byte = 1 Private Const nomen As String = "default" ' int snd_pcm_open(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode) Private Extern snd_pcm_open(pcmP 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 channels, unsigned int rate, int soft_resample, unsigned int latency) ' Set the hardware And software parameters In aPrivate Const MPG123_ADD_FLAGS As Byte = 2 simple way. Private Extern snd_pcm_set_params(pcmP As Pointer, formatB As Byte, accessB As Byte, 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) Private Extern snd_pcm_writei(pcmP As Pointer, buffP As Pointer, uframes As Long) As Integer ' int snd_pcm_close(snd_pcm_t **pcm) Private Extern snd_pcm_close(pcmP As Pointer) Public Sub Button1_Click() Dim infile, buffer, handle As Pointer Dim sfinfo As New SF_INFO Dim err, frequenza, conto, frames, canali As Integer buffer = Alloc(BUFFER_LEN * 4) ' Apre il file wav: infile = sf_open("/percorso/del/file.wav", SFM_READ, sfinfo) ' Ricava la frequenza di campionamento ed il numero di canali del file wav: With sfinfo frequenza = .samplerate canali = .channels End With '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Qui inizia la parte relativa alle funzioni di Alsa: err = snd_pcm_open(VarPtr(handle), nomen, SND_PCM_STREAM_PLAYBACK, 0) If err < 0 Then Error.Raise("Playback open error: " & snd_strerror(err)) err = snd_pcm_set_params(handle, 2, SND_PCM_ACCESS_RW_INTERLEAVED, canali, frequenza, 1, 500000) If err < 0 Then Error.Raise("Playback open error: " & snd_strerror(err)) ' Inizia il ciclo per la scrittura dei dati e per l'esecuzione del file wav: Do ' Legge i dati del file wav e li carica nel buffer: conto = sf_read_short(infile, buffer, BUFFER_LEN) ' I dati audio vengono inviati al sub-sistema "PCM" di Alsa, attraverso la lettura della variabile ' qui denominata "buffer". La quantità unitaria di dati scritti nell'handle del sub-sistema PCM deve essere uguale ' al valore del 3° argomento della precedente funzione "sf_read_short" diviso il numero di canali del file audio: frames = snd_pcm_writei(handle, buffer, BUFFER_LEN / sfinfo.channels) If (frames < 0) Then Error.Raise("Errore alla funzione 'snd_pcm_writei': " & snd_strerror(err)) ' Si pone un brevissimo "Wait" per impedire che l'esecuzione audio blocchi l'uso di eventuali oggetti posti sul "Form": Wait 0.005 Loop While conto <> 0 ' Va in chiusura: snd_pcm_close(handle) sf_close(infile) End
Riferimenti
- Il sito del API di SndFile.