Differenze tra le versioni di "Eseguire un file mp3 usando le risorse del API di Mpeg3 e di Alsa"

Da Gambas-it.org - Wikipedia.
Riga 148: Riga 148:
 
   cmp = mpeg3_audio_samples(mp3, 0)
 
   cmp = mpeg3_audio_samples(mp3, 0)
 
   Print "Campioni audio: "; cmp; " byte"
 
   Print "Campioni audio: "; cmp; " byte"
 +
  Write "Attendere, elaborazione in corso......"
 +
  Flush
 
    
 
    
 
  <FONT Color=gray>''''''''''''''''''''''''''''''''''''''''''''''''
 
  <FONT Color=gray>''''''''''''''''''''''''''''''''''''''''''''''''
Riga 157: Riga 159:
 
   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)
 +
  Write "\r" & Space(38)
 
   Print "Durata:        "; Date(0, 0, 0, 0, 0, 0, mpeg3_get_time(mp3) * 1000)
 
   Print "Durata:        "; Date(0, 0, 0, 0, 0, 0, mpeg3_get_time(mp3) * 1000)
   Print
+
   Write "\nAttendere, elaborazione in corso......"
 +
  Flush
 
    
 
    
 
   buf = Alloc(SizeOf(gb.Short), CInt(cmp) * can)
 
   buf = Alloc(SizeOf(gb.Short), CInt(cmp) * can)
Riga 169: Riga 173:
 
   Next
 
   Next
 
   st.Close
 
   st.Close
   
+
  Write "\r" & Space(38)
 +
  Print
 +
 
  <FONT Color=gray>''''''''''''''''''''''''''''''''''''''''
 
  <FONT Color=gray>''''''''''''''''''''''''''''''''''''''''
 
    
 
    

Versione delle 04:25, 17 ago 2018

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 (bisognerà attendere l'elaborazione dei dati per diversi secondi !):

Private Const QUANT As Integer = 1024

Library "libmpeg3"

Public Struct mpeg3_t
  fs As Pointer
  demuxer As Pointer
  total_astreams As Integer
  atrack[65536] As Pointer
  vtrack[65536] As Pointer
  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_U8 As Byte = 1
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, obr, stato As Integer
 Dim cmp As Long
 Dim mp3 As Mpeg3_t
 Dim cc1, cc2 As Short[]
 Dim buf, handle As Pointer
 Dim st As Stream
 Dim c As Short
 
 perc = "/percorso/del/file.mp3"
 
 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):
 cc1 = New Short[cmp]
 cc2 = New Short[cmp]
 
' 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)
 Write "\r" & Space(38)
 Print "Durata:         "; Date(0, 0, 0, 0, 0, 0, mpeg3_get_time(mp3) * 1000)
 Write "\nAttendere, elaborazione in corso......"
 Flush
 
 buf = Alloc(SizeOf(gb.Short), CInt(cmp) * can)
 st = Memory buf For Write
 
' I dati audio grezzi di ciascun canale vengono riuniti in un'unica area riservata della memoria:
 For i = 0 To cmp - 1
   Write #st, cc1[i] As Short
   If can = 2 Then Write #st, cc2[i] As Short    
 Next
 st.Close
 Write "\r" & Space(38)
 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))
 
 c = 16 / (8 / can)
 obr = freq * can * 16
 
' Scrive i dati nell'interfaccia PCM:
 While stato < (cmp * c)
   i = snd_pcm_writei(handle, buf + stato, QUANT / c)
   If i < 0 Then Break
' Mostra il tempo trascorso:
   Write "\rTempo trascorso: " & Date(0, 0, 0, 0, 0, 0, ((stato * 8) / obr) * 1000)
   stato += QUANT
 Wend
 
 Chiude(buf, handle, mp3)
  
End


Private Procedure Chiude(buff as pointer, han As Pointer, mpe As Mpeg3_t)
 
 Dim err As Integer
 
 Free(buff)
 
 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