Differenze tra le versioni di "Eseguire un file mp3 usando le risorse del API di Mpeg3 e di Alsa"
Da Gambas-it.org - Wikipedia.
(12 versioni intermedie di uno stesso utente non sono mostrate) | |||
Riga 1: | Riga 1: | ||
E' possibile eseguire un file mp3 usando le risorse del API di ''Mpeg3'' e di ''Alsa'': la prima libreria provvedererà a estrarre dal file audio mp3 i dati audio grezzi, mentre la seconda libreria provvederà a eseguire tali dati audio grezzi. | E' possibile eseguire un file mp3 usando le risorse del API di ''Mpeg3'' e di ''Alsa'': la prima libreria provvedererà a estrarre dal file audio mp3 i dati audio grezzi, mentre la seconda libreria provvederà a eseguire tali dati audio grezzi. | ||
− | E' necessario avere installate nel proprio sistema e richiamare in Gambas le librerie condivise: "''libmpeg3.so.2.1.8''" e "''libasound.so.2.0.0''" | + | E' necessario avere installate nel proprio sistema e richiamare in Gambas le librerie condivise: "''libmpeg3.so.2.1.8'' " e "''libasound.so.2.0.0'' " |
− | Mostriamo un semplice esempio pratico | + | Mostriamo un semplice esempio pratico: |
− | Library "libmpeg3" | + | Private Const BUFFER As Long = 256 |
+ | |||
+ | Library "<FONT Color=blue>libmpeg3:2.1.8</font>" | ||
Public Struct mpeg3_t | Public Struct mpeg3_t | ||
Riga 12: | Riga 14: | ||
total_astreams As Integer | total_astreams As Integer | ||
atrack[65536] As Pointer | atrack[65536] As Pointer | ||
+ | total_vstreams As Integer | ||
vtrack[65536] As Pointer | vtrack[65536] As Pointer | ||
+ | total_sstreams As Integer | ||
strack[65536] As Pointer | strack[65536] As Pointer | ||
frame_offsets As Pointer | frame_offsets As Pointer | ||
Riga 40: | Riga 44: | ||
cpus As Integer | cpus As Integer | ||
seekable As Integer | seekable As Integer | ||
− | toc_fd As Pointer | + | toc_fd As Pointer |
− | |||
byte_pts As Long | byte_pts As Long | ||
have_palette As Integer | have_palette As Integer | ||
Riga 88: | Riga 91: | ||
− | Library "libasound:2" | + | Library "<FONT Color=red>libasound:2</font>" |
Private Const SND_PCM_STREAM_PLAYBACK As Byte = 0 | Private Const SND_PCM_STREAM_PLAYBACK As Byte = 0 | ||
− | |||
Private Const SND_PCM_FORMAT_S16_LE As Byte = 2 | Private Const SND_PCM_FORMAT_S16_LE As Byte = 2 | ||
Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Byte = 3 | Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Byte = 3 | ||
Riga 123: | Riga 125: | ||
Dim perc As String | Dim perc As String | ||
− | Dim i, can, freq, | + | Dim i, can, freq, n, x As Integer |
Dim cmp As Long | Dim cmp As Long | ||
Dim mp3 As Mpeg3_t | Dim mp3 As Mpeg3_t | ||
− | Dim cc1, cc2 As Short[] | + | Dim cc1, cc2, buf As Short[] |
Dim handle As Pointer | Dim handle As Pointer | ||
− | |||
perc = "<FONT Color=gray>''/percorso/del/file.mp3''</font>" | perc = "<FONT Color=gray>''/percorso/del/file.mp3''</font>" | ||
+ | If Not Exist(perc) Then Error.Raise("Errore: file inesistente !") | ||
i = mpeg3_check_sig(perc) | i = mpeg3_check_sig(perc) | ||
Riga 149: | Riga 151: | ||
Flush | Flush | ||
− | <FONT Color=gray>'''''''''''''''' | + | <FONT Color=gray>''''''Sezione per l'estrazione dei dati audio grezzi (PCM)'''''' |
− | ' '' | + | |
− | cc1 = New Short[cmp] | + | ' ''La dimensione dei vettori è aumentata del valore della Costante "BUFFER", per impedire che nella sezione,'' |
− | cc2 = New Short[cmp] | + | ' ''dedicata alla scrittura dei dati nel dispositivo PCM di Alsa, venga sollevato un errore di "Out of bound":''</font> |
+ | cc1 = New Short[cmp + BUFFER] | ||
+ | If can = 2 Then cc2 = New Short[cmp + BUFFER] | ||
<FONT Color=gray>' ''Vengono estratti i dati audio grezzi per ciascun canale:''</font> | <FONT Color=gray>' ''Vengono estratti i dati audio grezzi per ciascun canale:''</font> | ||
mpeg3_read_audio(mp3, 0, cc1.Data, 0, cmp, 0) | mpeg3_read_audio(mp3, 0, cc1.Data, 0, cmp, 0) | ||
If can = 2 Then mpeg3_reread_audio(mp3, 0, cc2.Data, 1, cmp, 0) | If can = 2 Then mpeg3_reread_audio(mp3, 0, cc2.Data, 1, cmp, 0) | ||
− | Print "\r" & Space(38); "\rDurata: "; | + | Print "\r" & Space(38); "\rDurata: "; Time(0, 0, 0, mpeg3_get_time(mp3) * 1000) |
Print | Print | ||
Riga 169: | Riga 173: | ||
If i < 0 Then Error.Raise("Errore nell'impostazione dei parametri audio: " & snd_strerror(i)) | If i < 0 Then Error.Raise("Errore nell'impostazione dei parametri audio: " & snd_strerror(i)) | ||
− | + | buf = New Short[] | |
− | |||
<FONT Color=gray>' ''Scrive i dati nell'interfaccia PCM:''</font> | <FONT Color=gray>' ''Scrive i dati nell'interfaccia PCM:''</font> | ||
− | While | + | While n < (cmp -1) |
− | i = snd_pcm_writei(handle, | + | buf.Clear |
+ | <FONT Color=gray>' ''Scrive progressivamente gruppi di 256 campioni audio di ciascun canale in un vettore,'' | ||
+ | ' ''per garantire l'accesso ai dati in formato "interleaved" <SUP>[[[#Note|Nota 1]]]</sup>:''</font> | ||
+ | For x = 1 To BUFFER | ||
+ | buf.Push(cc1[n]) | ||
+ | If can = 2 Then buf.Push(cc2[n]) | ||
+ | Inc n | ||
+ | Next | ||
+ | i = snd_pcm_writei(handle, buf.Data, BUFFER) | ||
If i < 0 Then Break | If i < 0 Then Break | ||
− | |||
<FONT Color=gray>' ''Mostra il tempo trascorso:''</font> | <FONT Color=gray>' ''Mostra il tempo trascorso:''</font> | ||
− | Write "\rTempo trascorso: " & | + | Write "\rTempo trascorso: " & Time(0, 0, 0, (n / freq) * 1000) |
− | |||
Wend | Wend | ||
Riga 202: | Riga 211: | ||
'''End''' | '''End''' | ||
+ | |||
+ | |||
+ | |||
+ | =Note= | ||
+ | [1] [https://www.alsa-project.org/main/index.php/PCM_Ring_Buffer PCM Ring Buffer], http://kom.aau.dk/group/05gr506/report/node21.html |
Versione attuale delle 14:43, 7 lug 2021
E' possibile eseguire un file mp3 usando le risorse del API di Mpeg3 e di Alsa: la prima libreria provvedererà a estrarre dal file audio mp3 i dati audio grezzi, mentre la seconda libreria provvederà a eseguire tali dati audio grezzi.
E' necessario avere installate nel proprio sistema e richiamare in Gambas le librerie condivise: "libmpeg3.so.2.1.8 " e "libasound.so.2.0.0 "
Mostriamo un semplice esempio pratico:
Private Const BUFFER As Long = 256 Library "libmpeg3:2.1.8" Public Struct mpeg3_t fs As Pointer demuxer As Pointer total_astreams As Integer atrack[65536] As Pointer total_vstreams As Integer vtrack[65536] As Pointer total_sstreams As Integer strack[65536] As Pointer frame_offsets As Pointer sample_offsets As Pointer keyframe_numbers As Pointer video_eof As Pointer audio_eof As Pointer total_frame_offsets As Pointer total_sample_offsets As Pointer total_samples As Pointer total_keyframe_numbers As Pointer channel_counts As Pointer indexes As Pointer total_indexes As Integer index_bytes As Long is_transport_stream As Integer is_program_stream As Integer is_ifo_file As Integer is_audio_stream As Integer is_video_stream As Integer is_bd As Integer packet_size As Integer last_type_read As Integer last_stream_read As Integer subtitle_track As Integer program As Integer cpus As Integer seekable As Integer toc_fd As Pointer byte_pts As Long have_palette As Integer palette[64] As Byte source_date As Long End Struct ' int mpeg3_check_sig(char *path) ' Check for file compatibility. Private Extern mpeg3_check_sig(path As String) As Integer ' mpeg3_t* mpeg3_open(char *path, int *error_return) ' Open the MPEG stream. Private Extern mpeg3_open(path As String, error_return As Pointer) As Mpeg3_t ' int64_t mpeg3_get_bytes(mpeg3_t *file) ' Total bytes. Private Extern mpeg3_get_bytes(mpeg3file As Mpeg3_t) As Long ' int mpeg3_audio_channels(mpeg3_t *file, int stream) Private Extern mpeg3_audio_channels(mpeg3file As Mpeg3_t, _stream As Integer) As Integer ' int mpeg3_sample_rate(mpeg3_t *file, int stream) Private Extern mpeg3_sample_rate(mpeg3file As Mpeg3_t, _stream As Integer) As Integer ' char* mpeg3_audio_format(mpeg3_t *file, int stream) Private Extern mpeg3_audio_format(mpeg3file As Mpeg3_t, _stream As Integer) As Pointer ' long mpeg3_audio_samples(mpeg3_t *file, int stream) Private Extern mpeg3_audio_samples(mpeg3file As Mpeg3_t, _stream As Integer) As Long ' int mpeg3_read_audio(mpeg3_t *file, float *output_f, short *output_i, int channel, long samples, int stream) ' Read a PCM buffer of audio from 1 channel and advance the position. Private Extern mpeg3_read_audio(mpeg3 As Mpeg3_t, f As Pointer, i As Pointer, can As Integer, sa As Long, st As Integer) ' int mpeg3_reread_audio(mpeg3_t *file, float *output_f, short *output_i, int channel, long samples, int stream) ' Reread a PCM buffer of audio from 1 channel and advance the position. Private Extern mpeg3_reread_audio(mpeg3 As Mpeg3_t, f As Pointer, i As Pointer, can As Integer, sa As Long, st As Integer) ' double mpeg3_get_time(mpeg3_t *file) ' Give the seconds time in the last packet read. Private Extern mpeg3_get_time(mpeg3 As Mpeg3_t) As Float ' int mpeg3_close(mpeg3_t *file) Private Extern mpeg3_close(mpeg3file As Mpeg3_t) As Integer Library "libasound:2" Private Const SND_PCM_STREAM_PLAYBACK As Byte = 0 Private Const SND_PCM_FORMAT_S16_LE As Byte = 2 Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Byte = 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, 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) ' 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_drop (snd_pcm_t *pcm) ' Stop a PCM dropping pending frames. Private Extern snd_pcm_drop(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 perc As String Dim i, can, freq, n, x As Integer Dim cmp As Long Dim mp3 As Mpeg3_t Dim cc1, cc2, buf As Short[] Dim handle As Pointer perc = "/percorso/del/file.mp3" If Not Exist(perc) Then Error.Raise("Errore: file inesistente !") i = mpeg3_check_sig(perc) If i = 0 Then Error.Raise("Tipo file incompatibile !") mp3 = mpeg3_open(perc, 0) Print "File audio: "; perc Print "Dimensione: "; mpeg3_get_bytes(mp3); " byte" can = mpeg3_audio_channels(mp3, 0) Print "Numero canali: "; can freq = mpeg3_sample_rate(mp3, 0) Print "Frequenza: "; freq; " hertz" Print "Formato audio: "; String@(mpeg3_audio_format(mp3, 0)) cmp = mpeg3_audio_samples(mp3, 0) Print "Campioni audio: "; cmp; " byte" Write "Attendere, elaborazione in corso......" Flush 'Sezione per l'estrazione dei dati audio grezzi (PCM)' ' La dimensione dei vettori è aumentata del valore della Costante "BUFFER", per impedire che nella sezione, ' dedicata alla scrittura dei dati nel dispositivo PCM di Alsa, venga sollevato un errore di "Out of bound": cc1 = New Short[cmp + BUFFER] If can = 2 Then cc2 = New Short[cmp + BUFFER] ' Vengono estratti i dati audio grezzi per ciascun canale: mpeg3_read_audio(mp3, 0, cc1.Data, 0, cmp, 0) If can = 2 Then mpeg3_reread_audio(mp3, 0, cc2.Data, 1, cmp, 0) Print "\r" & Space(38); "\rDurata: "; Time(0, 0, 0, mpeg3_get_time(mp3) * 1000) Print ''''''''''''''''''''''''''''''''''' ' Vengono utilizzate le funzioni esterne essenziali di Alsa: i = snd_pcm_open(VarPtr(handle), "default", SND_PCM_STREAM_PLAYBACK, 0) If i < 0 Then Error.Raise("Errore nell'apertura del subsistema PCM: " & snd_strerror(i)) i = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, can, freq, 1, 500000) If i < 0 Then Error.Raise("Errore nell'impostazione dei parametri audio: " & snd_strerror(i)) buf = New Short[] ' Scrive i dati nell'interfaccia PCM: While n < (cmp -1) buf.Clear ' Scrive progressivamente gruppi di 256 campioni audio di ciascun canale in un vettore, ' per garantire l'accesso ai dati in formato "interleaved" [Nota 1]: For x = 1 To BUFFER buf.Push(cc1[n]) If can = 2 Then buf.Push(cc2[n]) Inc n Next i = snd_pcm_writei(handle, buf.Data, BUFFER) If i < 0 Then Break ' Mostra il tempo trascorso: Write "\rTempo trascorso: " & Time(0, 0, 0, (n / freq) * 1000) Wend Chiude(handle, mp3) End Private Procedure Chiude(han As Pointer, mpe As Mpeg3_t) Dim err As Integer err = snd_pcm_drop(han) If err <> 0 Then Error.Raise("Impossibile fermare l'esecuzione dei dati audio !") Print "\nEsecuzione fermata !" ' Alla fine dell'esecuzione del file audio chiude il subsistema PCM ed il file: err = snd_pcm_close(han) If err = 0 Then Print "\nChiusura dell'interfaccia PCM: regolare." mpeg3_close(mpe) End
Note
[1] PCM Ring Buffer, http://kom.aau.dk/group/05gr506/report/node21.html