Differenze tra le versioni di "Eseguire un file audio usando l'API di SndFile e di Alsa"
Da Gambas-it.org - Wikipedia.
(2 versioni intermedie di uno stesso utente non sono mostrate) | |||
Riga 2: | Riga 2: | ||
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. | 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. | ||
− | <BR>A tal fine è necessario avere installate nel sistema e richiamare in Gambas le libreria condivise: "''libsndfile.so.1.0. | + | <BR>A tal fine è necessario avere installate nel sistema e richiamare in Gambas le libreria condivise: "''libsndfile.so.1.0.31'' " e "''libasound.so.2.0.0'' ". |
Mostreremo di seguito un semplice codice per l'esecuzione di un file WAV, AIFF, FLAC oppure OGG: | Mostreremo di seguito un semplice codice per l'esecuzione di un file WAV, AIFF, FLAC oppure OGG: | ||
− | Library "<FONT color=blue>libsndfile:1.0. | + | Library "<FONT color=blue>libsndfile:1.0.31</font>" |
Public Struct SF_INFO | Public Struct SF_INFO | ||
Riga 65: | Riga 65: | ||
'''Public''' Sub Main() | '''Public''' Sub Main() | ||
− | Dim fileaudio As String | + | Dim fileaudio, s As String |
Dim infile, buffer, handle As Pointer | Dim infile, buffer, handle As Pointer | ||
Dim sfinfo As New SF_INFO | Dim sfinfo As New SF_INFO | ||
Riga 72: | Riga 72: | ||
fileaudio = "<FONT color=gray>''/percorso/del/file/audio''</font>" | fileaudio = "<FONT color=gray>''/percorso/del/file/audio''</font>" | ||
− | + | s = File.Load(fileaudio) | |
+ | lun = Len(s) | ||
− | <FONT color=darkorange><B>buffer</b></font> = Alloc(BUFFER_LEN * 4) | + | <FONT color=darkorange><B>buffer</b></font> = Alloc(SizeOf(gb.Byte), BUFFER_LEN * 4) |
− | <FONT color=gray>' ''Apre il file | + | <FONT color=gray>' ''Apre il file audio:''</font> |
infile = sf_open(fileaudio, SFM_READ, sfinfo) | infile = sf_open(fileaudio, SFM_READ, sfinfo) | ||
− | If infile = 0 Then Error.Raise("Errore nell'apertura del file audio !") | + | If infile == 0 Then Error.Raise("Errore nell'apertura del file audio !") |
− | <FONT color=gray>' ''Ricava la frequenza di campionamento ed il numero di canali del file | + | <FONT color=gray>' ''Ricava la frequenza di campionamento ed il numero di canali del file audio:''</font> |
With sfinfo | With sfinfo | ||
frequenza = .samplerate | frequenza = .samplerate | ||
Riga 90: | Riga 91: | ||
Print "Numero canali: "; canali | Print "Numero canali: "; canali | ||
durata = (sfinfo.frames / frequenza) | durata = (sfinfo.frames / frequenza) | ||
− | Print "Risoluzione: "; Fix(((lun * 8) / (frequenza * canali)) / durata); " bit" | + | If Mid(File.Load(fileaudio), 9, 4) = "WAVE" Then |
+ | Print "Risoluzione: "; Fix(((lun * 8) / (frequenza * canali)) / durata); " bit" | ||
+ | Endif | ||
Print "Campioni: "; sfinfo.frames | Print "Campioni: "; sfinfo.frames | ||
Print "Durata: "; Time(0, 0, 0, durata * 1000) | Print "Durata: "; Time(0, 0, 0, durata * 1000) | ||
+ | Print | ||
<FONT color=gray>''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' | <FONT color=gray>''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' | ||
Riga 123: | Riga 127: | ||
snd_pcm_drain(handle) | snd_pcm_drain(handle) | ||
− | + | <FONT color=gray>' ''Va in chiusura:''</font> | |
snd_pcm_close(handle) | snd_pcm_close(handle) | ||
sf_close(infile) | sf_close(infile) | ||
Riga 133: | Riga 137: | ||
=Riferimenti= | =Riferimenti= | ||
− | * | + | * http://www.mega-nerd.com/libsndfile/api.html |
+ | * https://xiph.org/flac/format.html#stream |
Versione attuale delle 16:37, 1 mag 2023
SndFile è una libreria, scritta in C, per leggere e scrivere file che contengono suono campionato (come i formati: WAV, AIFF, FLAC e OGG) 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.
A tal fine è necessario avere installate nel sistema e richiamare in Gambas le libreria condivise: "libsndfile.so.1.0.31 " e "libasound.so.2.0.0 ".
Mostreremo di seguito un semplice codice per l'esecuzione di un file WAV, AIFF, FLAC oppure OGG:
Library "libsndfile:1.0.31" Public Struct SF_INFO frames As Long samplerate As Integer channels As Integer format_ As Integer sections As Integer seekable As Integer End Struct Private Const BUFFER_LEN As Short = 1024 Private Const SFM_READ As Byte = 16 ' SNDFILE * sf_open (const char *path, int mode, SF_INFO *sfinfo) ' Open the specified file for read, write or both. 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) ' Read the data chunk in terms of frames (in the native short format). Private Extern sf_read_short(sndfile As Pointer, ptr As Pointer, items As Integer) As Integer ' int sf_close (SNDFILE *sndfile) ' Close the SNDFILE and clean up all memory allocations associated with this file. Private Extern sf_close(sndfile As Pointer) As Integer Library "libasound:2.0.0" 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 ' 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(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, format_ As Byte, access_ 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) ' Write interleaved frames to a PCM. Private Extern snd_pcm_writei(pcmP As Pointer, buffP 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(pcmP As Pointer) As Integer ' int snd_pcm_close(snd_pcm_t **pcm) ' Close PCM handle. Private Extern snd_pcm_close(pcmP As Pointer) Public Sub Main() Dim fileaudio, s As String Dim infile, buffer, handle As Pointer Dim sfinfo As New SF_INFO Dim err, lun, frequenza, frames, canali, somma As Integer Dim durata As Single fileaudio = "/percorso/del/file/audio" s = File.Load(fileaudio) lun = Len(s) buffer = Alloc(SizeOf(gb.Byte), BUFFER_LEN * 4) ' Apre il file audio: infile = sf_open(fileaudio, SFM_READ, sfinfo) If infile == 0 Then Error.Raise("Errore nell'apertura del file audio !") ' Ricava la frequenza di campionamento ed il numero di canali del file audio: With sfinfo frequenza = .samplerate canali = .channels End With Print "File audio: "; fileaudio Print "Frequenza: "; frequenza; " hertz" Print "Numero canali: "; canali durata = (sfinfo.frames / frequenza) If Mid(File.Load(fileaudio), 9, 4) = "WAVE" Then Print "Risoluzione: "; Fix(((lun * 8) / (frequenza * canali)) / durata); " bit" Endif Print "Campioni: "; sfinfo.frames Print "Durata: "; Time(0, 0, 0, durata * 1000) Print '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Qui inizia la parte relativa alle funzioni di Alsa: err = snd_pcm_open(VarPtr(handle), "default", 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: Repeat ' Legge i dati del file wav e li carica nel buffer: lun = 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)) somma += frames Write "\r\e[31m" & Str(Time(0, 0, 0, (somma / frequenza) * 1000)) Until lun = 0 ' Impedisce che al termine l'esecuzione venga troncata inaspettatamente: snd_pcm_drain(handle) ' Va in chiusura: snd_pcm_close(handle) sf_close(infile) Free(buffer) End