Eseguire un file WAV mediante le funzioni esterne del API di libaudio e di Alsa
Da Gambas-it.org - Wikipedia.
Versione del 22 ott 2021 alle 17:13 di Vuott (Discussione | contributi)
E' possibile eseguire un file formato WAV utilizzando le risorse delle librerie Libaudio ed ALSA. Con le funzioni della libreria Libaudio si provvederà ad aprire e leggere i dati del file audio WAV, mentre con le funzioni della libreria di ALSA si provvederà ad inviare i dati audio letti al sub-sistema PCM.
Per fruire di tali risorse in Gambas bisognerà installare e richiamare le librerie dinamiche e condivise: "libaudio.so.2.4 " e "libasound.so.2.0.0 "
Mostriamo un esempio pratico:
Private Const BUFFER As Integer = 32 Library "libaudio:2.4" Public Struct WaveInfo fp As Pointer comment As Pointer channels As Short bitsPerSample As Short sampleRate As Integer dataOffset As Integer numSamples As Integer fileSize As Integer dataSize As Integer sizeOffset As Integer writing As Integer formatSh As Short End Struct ' WaveInfo * WaveOpenFileForReading(const char *name) ' Open an wave file for reading. Private Extern WaveOpenFileForReading(name As String) As WaveInfo ' int WaveSeekFile(int n, WaveInfo *wi) ' Seek to a position in an wave file. Private Extern WaveSeekFile(n As Integer, wi As WaveInfo) As Integer ' int WaveReadFile(char *p, int n, WaveInfo *wi) ' Read wave data from an audio file. Private Extern WaveReadFile(p As Pointer, n As Integer, wi As WaveInfo) As Integer ' int WaveCloseFile(WaveInfo *wi) ' Close an wave file description. Private Extern WaveCloseFile(wi As WaveInfo) As Integer Library "libasound:2.0.0" Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0 Private Const SND_PCM_FORMAT_U8 As Integer = 1 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, name As String, streamI As Integer, mode As Integer) As Integer ' 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 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, buf As Pointer, size As Integer) 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(pcm As Pointer) As Integer Public Sub Main() Dim buf, handle As Pointer Dim fileWav As String Dim err, bit, msec, obr, frames, i, n As Integer Dim info As New WaveInfo fileWav = "/percorso/del/file.wav" info = WaveOpenFileForReading(fileWav) If IsNull(info) Then Error.Raise("Errore nella lettura del file wav !") buf = Alloc(SizeOf(gb.Byte), BUFFER) If buf = 0 Then Error.Raise("Impossibile allocare memoria !") Print "File audio: "; fileWav Print "Numero canali: "; info.channels Print "Risoluzione bit: "; info.bitsPerSample; " bit" Print "Frequenza camp.: "; info.sampleRate; " Hertz" obr = info.channels * info.bitsPerSample * info.sampleRate Print "Overall BitRate: "; obr; " bps" msec = Fix(((info.dataSize * 8) / obr) * 1000) Print "Durata: "; CStr(Time(0, 0, 0, msec)) Print err = snd_pcm_open(VarPtr(handle), "default", SND_PCM_STREAM_PLAYBACK, 0) If err < 0 Then Error.Raise("Impossibile inizializzare la libreria Alsa !") Select Case info.bitsPerSample Case 16 bit = SND_PCM_FORMAT_S16_LE Case 8 bit = SND_PCM_FORMAT_U8 End Select err = snd_pcm_set_params(handle, bit, SND_PCM_ACCESS_RW_INTERLEAVED, info.channels, info.sampleRate, 1, 500000) If err < 0 Then Error.Raise("Impossibile impostare i parametri audio alla libreria Alsa !") i = info.bitsPerSample / (8 / info.channels) While n < info.dataSize err = WaveSeekFile(n, info) If err Then Error.Raise("Impossibile posizionarsi nel file wav !") WaveReadFile(buf, BUFFER, info) frames = snd_pcm_writei(handle, buf, BUFFER / i) If frames < 0 Then Error.Raise("Errore nella funzione 'snd_pcm_writei()' !") n += BUFFER Write "\rTempo trascorso: " & Time(0, 0, 0, ((n * 8) / obr) * 1000) Wend ' Impedisce che al termine l'esecuzione venga troncata inaspettatamente: snd_pcm_drain(handle) ' Va in chiusura: snd_pcm_close(handle) Free(buf) WaveCloseFile(info) End