Differenze tra le versioni di "Eseguire una traccia di un CD audio con le funzioni esterne del API di libcdio e di ALSA"

Da Gambas-it.org - Wikipedia.
 
(Una versione intermedia di uno stesso utente non è mostrata)
Riga 2: Riga 2:
  
 
Sarà necessario, dunque, avere installate nel sistema e richiamare nell'applicazione Gambas le seguenti librerie dinamiche condivise:
 
Sarà necessario, dunque, avere installate nel sistema e richiamare nell'applicazione Gambas le seguenti librerie dinamiche condivise:
* ''libcdio.so.13.0.0''
+
* ''libcdio.so.18.0.0''
 
* ''libasound.so.2.0.0''
 
* ''libasound.so.2.0.0''
  
Riga 8: Riga 8:
 
Con le funzioni della libreria di ''CDIO'' verranno individuati in particolare gli indirizzi sul CD-Audio di ciascuna traccia audio ivi presente. Tali indirizzi rappresentano il punto ove iniziano i dati audio grezzi di ogni traccia audio.
 
Con le funzioni della libreria di ''CDIO'' verranno individuati in particolare gli indirizzi sul CD-Audio di ciascuna traccia audio ivi presente. Tali indirizzi rappresentano il punto ove iniziano i dati audio grezzi di ogni traccia audio.
  
Poiché i dati audio grezzi di ciascuna traccia sono memorizzati sul CD-Audio in gruppi (Settori) formati ciascuno da 2352 byte, la differenza fra il valore che rappresenta l'indirizzo di una traccia e quello della traccia immeditamente successiva, indica quanti Settori (formati da 2352 byte di dati audio) compongono la traccia in cosiderazione. In altre parole i dati audio grezzi di una taccia sono suddivisi e memorizzati sul CD-Audio in blocchi formati ciascuno da 2352 byte.
+
Poiché i dati audio grezzi di ciascuna traccia sono memorizzati sul CD-Audio in gruppi (Settori) formati ciascuno da 2352 byte, la differenza fra il valore che rappresenta l'indirizzo di una traccia e quello della traccia immediatamente successiva, indica quanti Settori (formati da 2352 byte di dati audio) compongono la traccia in considerazione. In altre parole i dati audio grezzi di una taccia sono suddivisi e memorizzati sul CD-Audio in blocchi formati ciascuno da 2352 byte.
  
L'indirizzo della traccia, presa in considerazione, rappresentando, dunque, l'inizio dei dati audio della traccia, rappresenta ovviamente anche il primo Settore. I seguenti dati audio della traccia sono memorizzati nei successivi Settori, scorrendo l'indice di un'unità ciascuna. Così, ad esempio, se l'indirizzo iniziale di una traccia è ''12345'', il primo blocco (Settore) di dati si troverà  quell'indirizzo (dunque i primi 2352 byte di dati audio della traccia in csiderazione saranno prelevabili a quell'indirizzo iniziale); il secondo blocco di dati audio di quella traccia si troverà all'indirizzo di valore d'indice immediatamente superiore di un'unità: 1234'''6'''; il terzo a 1234'''7''', e così via, finché non si raggiungerà l'indirizzo iniziale della traccia ''successiva''.  
+
L'indirizzo della traccia, presa in considerazione, rappresentando, dunque, l'inizio dei dati audio della traccia, rappresenta ovviamente anche il primo Settore. I seguenti dati audio della traccia sono memorizzati nei successivi Settori, scorrendo l'indice di un'unità ciascuna. Così, ad esempio, se l'indirizzo iniziale di una traccia è ''12345'', il primo blocco (Settore) di dati si troverà  quell'indirizzo (dunque i primi 2352 byte di dati audio della traccia in considerazione saranno prelevabili a quell'indirizzo iniziale); il secondo blocco di dati audio di quella traccia si troverà all'indirizzo di valore d'indice immediatamente superiore di un'unità: 1234'''6'''; il terzo a 1234'''7''', e così via, finché non si raggiungerà l'indirizzo iniziale della traccia ''successiva''.  
  
 
I dati audio dell'ultima traccia terminano finché non si raggiungerà l'indirizzo iniziale della speciale traccia chiamata ''Leadout''.
 
I dati audio dell'ultima traccia terminano finché non si raggiungerà l'indirizzo iniziale della speciale traccia chiamata ''Leadout''.
Riga 16: Riga 16:
  
 
Di seguito il codice:
 
Di seguito il codice:
  Library "libcdio:13.0.0"
+
  Library "libcdio:18.0.0"
 
   
 
   
  Private Enum DRIVER_UNKNOWN = 0, DRIVER_AIX, DRIVER_BSDI, DRIVER_FREEBSD, DRIVER_NETBSD, DRIVER_LINUX, DRIVER_SOLARIS,
+
  Private Enum DRIVER_UNKNOWN = 0, DRIVER_AIX, DRIVER_FREEBSD, DRIVER_NETBSD, DRIVER_LINUX, DRIVER_SOLARIS,
               DRIVER_OS2, DRIVER_OSX, DRIVER_WIN32, DRIVER_CDRDAO, DRIVER_BINCUE, DRIVER_NRG, DRIVER_DEVICE
+
               DRIVER_OSX, DRIVER_WIN32, DRIVER_CDRDAO, DRIVER_BINCUE, DRIVER_NRG, DRIVER_DEVICE
 
  Private Const CDIO_INVALID_LSN As Integer = -45301
 
  Private Const CDIO_INVALID_LSN As Integer = -45301
 
  Private Const CDIO_CDROM_LEADOUT_TRACK As Integer = &AA
 
  Private Const CDIO_CDROM_LEADOUT_TRACK As Integer = &AA
Riga 84: Riga 84:
 
    
 
    
 
  <FONT Color=gray>' ''Impostiamo il numero di una traccia che intendiamo far eseguire:''</font>
 
  <FONT Color=gray>' ''Impostiamo il numero di una traccia che intendiamo far eseguire:''</font>
  traccia = 4
+
  traccia = 4
 
    
 
    
 
  <FONT Color=gray>' ''Il valore della variabile "cbf" è data dal prodotto del numero dei canali per la risoluzione in bit per la frequenza della traccia audio:''</font>
 
  <FONT Color=gray>' ''Il valore della variabile "cbf" è data dal prodotto del numero dei canali per la risoluzione in bit per la frequenza della traccia audio:''</font>
  cbf = 2 * 16 * 44100
+
  cbf = 2 * 16 * 44100
 
    
 
    
  cd = cdio_open(Null, DRIVER_LINUX)
+
  cd = cdio_open(Null, DRIVER_LINUX)
  If cd = 0 Then Error.Raise("Impossibile trovare il driver per il cd-audio !")
+
  If cd == 0 Then Error.Raise("Impossibile trovare il driver per il cd-audio !")
 
    
 
    
  tracce = cdio_get_num_tracks(cd)
+
  tracce = cdio_get_num_tracks(cd)
  Print "Tracce del CD-Audio (1 - "; tracce; ")"
+
  Print "Tracce del CD-Audio (1 - "; tracce; ")"
  Print " #:  Durata"
+
  Print " #:  Durata"
 
  <FONT Color=gray>' ''Individua l'indirizzo del settore logico di ciascuna traccia:''</font>
 
  <FONT Color=gray>' ''Individua l'indirizzo del settore logico di ciascuna traccia:''</font>
  For i = 1 To tracce
+
  For i = 1 To tracce
    lsn.Push(cdio_get_track_lsn(cd, i))
+
    lsn.Push(cdio_get_track_lsn(cd, i))
  Next
+
  Next
  lsn.Push(cdio_get_track_lsn(cd, CDIO_CDROM_LEADOUT_TRACK))
+
  lsn.Push(cdio_get_track_lsn(cd, CDIO_CDROM_LEADOUT_TRACK))
  For i = 0 To tracce - 1
+
  For i = 0 To tracce - 1
    If i + 1 = traccia Then esec = "< in esecuzione"
+
    If i + 1 = traccia Then esec = "< in esecuzione"
    If (CDIO_INVALID_LSN <> lsn[i]) Then
+
    If (CDIO_INVALID_LSN <> lsn[i]) Then
      Print Format(i + 1, "#0:"), Date(0, 0, 0, 0, 0, 0, ((((lsn[i + 1] - lsn[i]) * 2352) * 8) / cbf) * 1000), esec
+
      Print Format(i + 1, "#0:"), Date(0, 0, 0, 0, 0, 0, ((((lsn[i + 1] - lsn[i]) * 2352) * 8) / cbf) * 1000), esec
    Endif
+
    Endif
    esec = Null
+
    esec = Null
  Next
+
  Next
 
    
 
    
  lsn.Push(cdio_get_track_lsn(cd, CDIO_CDROM_LEADOUT_TRACK))
+
  lsn.Push(cdio_get_track_lsn(cd, CDIO_CDROM_LEADOUT_TRACK))
 
    
 
    
  Esecuzione(cd, lsn, traccia)
+
  Esecuzione(cd, lsn, traccia)
 
      
 
      
 
  <FONT Color=gray>' ''Va in chiusura:''</font>
 
  <FONT Color=gray>' ''Va in chiusura:''</font>
  cdio_destroy(cd)
+
  cdio_destroy(cd)
 
      
 
      
 
  '''End'''
 
  '''End'''
Riga 124: Riga 124:
 
   Dim buf As Byte[]
 
   Dim buf As Byte[]
 
    
 
    
  err = snd_pcm_open(VarPtr(handle), "default", SND_PCM_STREAM_PLAYBACK, 0)
+
  err = snd_pcm_open(VarPtr(handle), "default", SND_PCM_STREAM_PLAYBACK, 0)
  If err < 0 Then Error.Raise("Errore nell'apertura del subsistema PCM: " & snd_strerror(err))
+
  If err < 0 Then Error.Raise("Errore nell'apertura del subsistema PCM: " & snd_strerror(err))
 
    
 
    
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 2, 44100, 1, 500000)
+
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 2, 44100, 1, 500000)
  If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri audio: " & snd_strerror(err))
+
  If err < 0 Then
 +
    snd_pcm_close(handle)
 +
    Error.Raise("Errore nell'impostazione dei parametri audio: " & snd_strerror(err))
 +
  Endif
 
    
 
    
  buf = New Byte[2352]
+
  buf = New Byte[2352]
 
    
 
    
  For i = 0 To (sett[tr] - sett[tr - 1]) - 1
+
  For i = 0 To (sett[tr] - sett[tr - 1]) - 1
    cdio_read_audio_sector(pcd, buf, sett[tr - 1] + i)
+
    cdio_read_audio_sector(pcd, buf, sett[tr - 1] + i)
    frames = snd_pcm_writei(handle, buf.Data, 2352 / 4)
+
    frames = snd_pcm_writei(handle, buf.Data, 2352 / 4)
    somma_frames += frames
+
    somma_frames += frames
    Write #File.Out, "\rTempo trascorso: " & Date(0, 0, 0, 0, 0, 0, (somma_frames / 44100) * 1000)
+
    Write #File.Out, "\rTempo trascorso: " & Date(0, 0, 0, 0, 0, 0, (somma_frames / 44100) * 1000)
    Sleep 0.01
+
    Sleep 0.01
  Next
+
  Next
 
    
 
    
  snd_pcm_drain(handle)
+
  snd_pcm_drain(handle)
 
    
 
    
 
  <FONT Color=gray>' ''Alla fine dell'esecuzione chiude il subsistema PCM:''</font>
 
  <FONT Color=gray>' ''Alla fine dell'esecuzione chiude il subsistema PCM:''</font>
  err = snd_pcm_close(handle)
+
  err = snd_pcm_close(handle)
  If err = 0 Then Print "\nChiusura dell'interfaccia PCM: regolare."
+
  If err == 0 Then Print "\nChiusura dell'interfaccia PCM: regolare."
 
      
 
      
 
  '''End'''
 
  '''End'''
Riga 152: Riga 155:
 
===Eseguire una traccia oppure tutte le tracce del CD audio===
 
===Eseguire una traccia oppure tutte le tracce del CD audio===
 
Di seguito mostriamo il precedente codice, opportunamente modificato per consntire all'utente di scegliere di eseguire una particolare traccia oppure l'intero CD audio.
 
Di seguito mostriamo il precedente codice, opportunamente modificato per consntire all'utente di scegliere di eseguire una particolare traccia oppure l'intero CD audio.
  Library "libcdio:13.0.0"
+
  Library "libcdio:18.0.0"
 
   
 
   
  Private Enum DRIVER_UNKNOWN = 0, DRIVER_AIX, DRIVER_BSDI, DRIVER_FREEBSD, DRIVER_NETBSD, DRIVER_LINUX, DRIVER_SOLARIS,
+
  Private Enum DRIVER_UNKNOWN = 0, DRIVER_AIX, DRIVER_FREEBSD, DRIVER_NETBSD, DRIVER_LINUX, DRIVER_SOLARIS,
               DRIVER_OS2, DRIVER_OSX, DRIVER_WIN32, DRIVER_CDRDAO, DRIVER_BINCUE, DRIVER_NRG, DRIVER_DEVICE
+
               DRIVER_OSX, DRIVER_WIN32, DRIVER_CDRDAO, DRIVER_BINCUE, DRIVER_NRG, DRIVER_DEVICE
 
  Private Const CDIO_INVALID_LSN As Integer = -45301
 
  Private Const CDIO_INVALID_LSN As Integer = -45301
 
  Private Const CDIO_CDROM_LEADOUT_TRACK As Integer = &AA
 
  Private Const CDIO_CDROM_LEADOUT_TRACK As Integer = &AA
Riga 221: Riga 224:
 
  <FONT Color=gray>' ''Il valore della variabile "cbf" è data dal prodotto del numero dei canali per la risoluzione in bit per la frequenza della traccia audio:''
 
  <FONT Color=gray>' ''Il valore della variabile "cbf" è data dal prodotto del numero dei canali per la risoluzione in bit per la frequenza della traccia audio:''
 
  '  canali bit frequenza</font>
 
  '  canali bit frequenza</font>
  cbf = 2 * 16 * 44100
+
  cbf = 2 * 16 * 44100
 
    
 
    
  cd = cdio_open(Null, DRIVER_LINUX)
+
  cd = cdio_open(Null, DRIVER_LINUX)
  If cd = 0 Then Error.Raise("Impossibile trovare il driver per il cd-audio !")
+
  If cd == 0 Then Error.Raise("Impossibile trovare il driver per il cd-audio !")
 
    
 
    
  tracce = cdio_get_num_tracks(cd)
+
  tracce = cdio_get_num_tracks(cd)
  Print "Tracce del CD-Audio (1 - "; tracce; ")"
+
  Print "Tracce del CD-Audio (1 - "; tracce; ")"
  Print " #:  Durata"
+
  Print " #:  Durata"
 
  <FONT Color=gray>' ''Individua l'indirizzo del settore logico di ciascuna traccia:''</font>
 
  <FONT Color=gray>' ''Individua l'indirizzo del settore logico di ciascuna traccia:''</font>
  For i = 1 To tracce
+
  For i = 1 To tracce
    lsn.Push(cdio_get_track_lsn(cd, i))
+
    lsn.Push(cdio_get_track_lsn(cd, i))
  Next
+
  Next
  lsn.Push(cdio_get_track_lsn(cd, CDIO_CDROM_LEADOUT_TRACK))
+
  lsn.Push(cdio_get_track_lsn(cd, CDIO_CDROM_LEADOUT_TRACK))
 
    
 
    
  For i = 0 To tracce - 1
+
  For i = 0 To tracce - 1
    If (CDIO_INVALID_LSN <> lsn[i]) Then
+
    If (CDIO_INVALID_LSN <> lsn[i]) Then
      Print Format(i + 1, "#0:"), Date(0, 0, 0, 0, 0, 0, ((((lsn[i + 1] - lsn[i]) * 2352) * 8) / cbf) * 1000)
+
      Print Format(i + 1, "#0:"), Date(0, 0, 0, 0, 0, 0, ((((lsn[i + 1] - lsn[i]) * 2352) * 8) / cbf) * 1000)
    Endif
+
    Endif
  Next
+
  Next
 
        
 
        
 
  <FONT Color=gray>''''''''''''''''''''''''</font>
 
  <FONT Color=gray>''''''''''''''''''''''''</font>
  n_tr = 1
+
  n_tr = 1
 
    
 
    
 
  <FONT Color=gray>' ''Si sceglie se eseguire una sola traccia e l'intero CD audio:''</font>
 
  <FONT Color=gray>' ''Si sceglie se eseguire una sola traccia e l'intero CD audio:''</font>
  Print "\nPer eseguire una sola traccia, inviare il numero corrispondente."
+
  Print "\nPer eseguire una sola traccia, inviare il numero corrispondente."
  Print "Per eseguire tutte le tracce del CD audio, premere 'Invio.'\n"
+
  Print "Per eseguire tutte le tracce del CD audio, premere 'Invio.'\n"
  Input s
+
  Input s
 
    
 
    
 
  <FONT Color=gray>' ''Se si è scelto di eseguire solo una traccia, imposta il suo numero:''</font>
 
  <FONT Color=gray>' ''Se si è scelto di eseguire solo una traccia, imposta il suo numero:''</font>
  If IsDigit(s) Then
+
  If IsDigit(s) Then
    n_tr = Val(s)
+
    n_tr = Val(s)
    tracce = n_tr
+
    tracce = n_tr
  Endif
+
  Endif
 
    
 
    
  For traccia = n_tr To tracce
+
  For traccia = n_tr To tracce
    For i = 0 To tracce - 1
+
    For i = 0 To tracce - 1
      If i + 1 = traccia Then
+
      If i + 1 = traccia Then
        Print Format(i + 1, "#0:"), Date(0, 0, 0, 0, 0, 0, ((((lsn[i + 1] - lsn[i]) * 2352) * 8) / cbf) * 1000)
+
        Print Format(i + 1, "#0:"), Date(0, 0, 0, 0, 0, 0, ((((lsn[i + 1] - lsn[i]) * 2352) * 8) / cbf) * 1000)
      Endif
+
      Endif
    Next
+
    Next
    lsn.Push(cdio_get_track_lsn(cd, CDIO_CDROM_LEADOUT_TRACK))
+
    lsn.Push(cdio_get_track_lsn(cd, CDIO_CDROM_LEADOUT_TRACK))
    Esecuzione(cd, lsn, traccia)
+
    Esecuzione(cd, lsn, traccia)
  Next
+
  Next
 
    
 
    
 
  <FONT Color=gray>' ''Va in chiusura:''</font>
 
  <FONT Color=gray>' ''Va in chiusura:''</font>
  cdio_destroy(cd)
+
  cdio_destroy(cd)
 
    
 
    
 
  '''End'''
 
  '''End'''
Riga 277: Riga 280:
 
   Dim buf As Byte[]
 
   Dim buf As Byte[]
 
    
 
    
  err = snd_pcm_open(VarPtr(handle), "default", SND_PCM_STREAM_PLAYBACK, 0)
+
  err = snd_pcm_open(VarPtr(handle), "default", SND_PCM_STREAM_PLAYBACK, 0)
  If err < 0 Then Error.Raise("Errore nell'apertura del subsistema PCM: " & snd_strerror(err))
+
  If err < 0 Then Error.Raise("Errore nell'apertura del subsistema PCM: " & snd_strerror(err))
 
    
 
    
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 2, 44100, 1, 500000)
+
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 2, 44100, 1, 500000)
  If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri audio: " & snd_strerror(err))
+
  If err < 0 Then
 +
    snd_pcm_close(handle)
 +
    Error.Raise("Errore nell'impostazione dei parametri audio: " & snd_strerror(err))
 +
  Endif
 +
 
 +
  buf = New Byte[2352]
 
    
 
    
  buf = New Byte[2352]
+
  For i = 0 To (sett[tr] - sett[tr - 1]) - 1
 
+
    cdio_read_audio_sector(pcd, buf, sett[tr - 1] + i)
  For i = 0 To (sett[tr] - sett[tr - 1]) - 1
+
    frames = snd_pcm_writei(handle, buf.Data, 2352 / 4)
    cdio_read_audio_sector(pcd, buf, sett[tr - 1] + i)
+
    somma_frames += frames
    frames = snd_pcm_writei(handle, buf.Data, 2352 / 4)
+
    Write #File.Out, "\rTempo trascorso: " & Date(0, 0, 0, 0, 0, 0, (somma_frames / 44100) * 1000)
    somma_frames += frames
+
    Sleep 0.01
    Write #File.Out, "\rTempo trascorso: " & Date(0, 0, 0, 0, 0, 0, (somma_frames / 44100) * 1000)
+
  Next
    Sleep 0.01
 
  Next
 
 
    
 
    
  snd_pcm_drain(handle)
+
  snd_pcm_drain(handle)
 
    
 
    
 
  <FONT Color=gray>' ''Alla fine dell'esecuzione chiude il subsistema PCM:''</font>
 
  <FONT Color=gray>' ''Alla fine dell'esecuzione chiude il subsistema PCM:''</font>
  err = snd_pcm_close(handle)
+
  err = snd_pcm_close(handle)
  If err = 0 Then Print "\nChiusura dell'interfaccia PCM: regolare."
+
  If err = 0 Then Print "\nChiusura dell'interfaccia PCM: regolare."
 
        
 
        
 
  '''End'''
 
  '''End'''
 
  
  

Versione attuale delle 01:09, 14 ago 2020

In questa pagina mostreremo un codice per leggere ed eseguire una traccia audio di un CD-Audio mediante le funzioni esterne del API di Libcdio e del API di ALSA.

Sarà necessario, dunque, avere installate nel sistema e richiamare nell'applicazione Gambas le seguenti librerie dinamiche condivise:

  • libcdio.so.18.0.0
  • libasound.so.2.0.0


Con le funzioni della libreria di CDIO verranno individuati in particolare gli indirizzi sul CD-Audio di ciascuna traccia audio ivi presente. Tali indirizzi rappresentano il punto ove iniziano i dati audio grezzi di ogni traccia audio.

Poiché i dati audio grezzi di ciascuna traccia sono memorizzati sul CD-Audio in gruppi (Settori) formati ciascuno da 2352 byte, la differenza fra il valore che rappresenta l'indirizzo di una traccia e quello della traccia immediatamente successiva, indica quanti Settori (formati da 2352 byte di dati audio) compongono la traccia in considerazione. In altre parole i dati audio grezzi di una taccia sono suddivisi e memorizzati sul CD-Audio in blocchi formati ciascuno da 2352 byte.

L'indirizzo della traccia, presa in considerazione, rappresentando, dunque, l'inizio dei dati audio della traccia, rappresenta ovviamente anche il primo Settore. I seguenti dati audio della traccia sono memorizzati nei successivi Settori, scorrendo l'indice di un'unità ciascuna. Così, ad esempio, se l'indirizzo iniziale di una traccia è 12345, il primo blocco (Settore) di dati si troverà quell'indirizzo (dunque i primi 2352 byte di dati audio della traccia in considerazione saranno prelevabili a quell'indirizzo iniziale); il secondo blocco di dati audio di quella traccia si troverà all'indirizzo di valore d'indice immediatamente superiore di un'unità: 12346; il terzo a 12347, e così via, finché non si raggiungerà l'indirizzo iniziale della traccia successiva.

I dati audio dell'ultima traccia terminano finché non si raggiungerà l'indirizzo iniziale della speciale traccia chiamata Leadout.


Di seguito il codice:

Library "libcdio:18.0.0"

Private Enum DRIVER_UNKNOWN = 0, DRIVER_AIX, DRIVER_FREEBSD, DRIVER_NETBSD, DRIVER_LINUX, DRIVER_SOLARIS,
             DRIVER_OSX, DRIVER_WIN32, DRIVER_CDRDAO, DRIVER_BINCUE, DRIVER_NRG, DRIVER_DEVICE
Private Const CDIO_INVALID_LSN As Integer = -45301
Private Const CDIO_CDROM_LEADOUT_TRACK As Integer = &AA

' CdIo_t * cdio_open (const char *psz_source, driver_id_t driver_id)
' Sets up to read from place specified by psz_source and driver_id.
Private Extern cdio_open(psz_source As String, driver_id As Integer) As Pointer

' track_t cdio_get_num_tracks(const CdIo_t * p_cdio)
' Get the number of tracks on the CD.
Private Extern cdio_get_num_tracks(p_cdio As Pointer) As Byte
 
' lsn_t cdio_get_track_lsn(const CdIo_t * p_cdio, track_t u_track)
' Return the starting LSN for track number i_track in p_cdio.
Private Extern cdio_get_track_lsn(p_cdio As Pointer, u_track As Integer) As Integer

' driver_return_code_t cdio_read_audio_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn)
' Read an audio sector.
Private Extern cdio_read_audio_sector(p_cdio As Pointer, p_buf As Byte[], i_lsn As Integer) As Integer

' void cdio_destroy(CdIo_t * p_cdio)
' Free any resources associated with p_cdio.
Private Extern cdio_destroy(p_cdio As Pointer)


Library "libasound:2"

Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0
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, 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, 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, buffer 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(pcm 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 cd As Pointer
 Dim traccia, tracce, i As Byte
 Dim cbf As Integer
 Dim lsn As New Integer[]
 Dim esec As String
 
' Impostiamo il numero di una traccia che intendiamo far eseguire:
 traccia = 4
  
' Il valore della variabile "cbf" è data dal prodotto del numero dei canali per la risoluzione in bit per la frequenza della traccia audio:
 cbf = 2 * 16 * 44100
 
 cd = cdio_open(Null, DRIVER_LINUX)
 If cd == 0 Then Error.Raise("Impossibile trovare il driver per il cd-audio !")
  
 tracce = cdio_get_num_tracks(cd)
 Print "Tracce del CD-Audio (1 - "; tracce; ")"
 Print " #:  Durata"
' Individua l'indirizzo del settore logico di ciascuna traccia:
 For i = 1 To tracce
   lsn.Push(cdio_get_track_lsn(cd, i))
 Next
 lsn.Push(cdio_get_track_lsn(cd, CDIO_CDROM_LEADOUT_TRACK))
 For i = 0 To tracce - 1
   If i + 1 = traccia Then esec = "< in esecuzione"
   If (CDIO_INVALID_LSN <> lsn[i]) Then
     Print Format(i + 1, "#0:"), Date(0, 0, 0, 0, 0, 0, ((((lsn[i + 1] - lsn[i]) * 2352) * 8) / cbf) * 1000), esec
   Endif
   esec = Null
 Next
  
 lsn.Push(cdio_get_track_lsn(cd, CDIO_CDROM_LEADOUT_TRACK))
  
 Esecuzione(cd, lsn, traccia)
   
' Va in chiusura:
 cdio_destroy(cd)
   
End
  
  
Private Procedure Esecuzione(pcd As Pointer, sett As Integer[], tr As Byte)
  
 Dim handle As Pointer
 Dim err, i, frames, somma_frames As Integer
 Dim buf As Byte[]
  
 err = snd_pcm_open(VarPtr(handle), "default", SND_PCM_STREAM_PLAYBACK, 0)
 If err < 0 Then Error.Raise("Errore nell'apertura del subsistema PCM: " & snd_strerror(err))
  
 err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 2, 44100, 1, 500000)
 If err < 0 Then
   snd_pcm_close(handle)
   Error.Raise("Errore nell'impostazione dei parametri audio: " & snd_strerror(err))
 Endif
  
 buf = New Byte[2352]
  
 For i = 0 To (sett[tr] - sett[tr - 1]) - 1
   cdio_read_audio_sector(pcd, buf, sett[tr - 1] + i)
   frames = snd_pcm_writei(handle, buf.Data, 2352 / 4)
   somma_frames += frames
   Write #File.Out, "\rTempo trascorso: " & Date(0, 0, 0, 0, 0, 0, (somma_frames / 44100) * 1000)
   Sleep 0.01
 Next
  
 snd_pcm_drain(handle)
  
' Alla fine dell'esecuzione chiude il subsistema PCM:
 err = snd_pcm_close(handle)
 If err == 0 Then Print "\nChiusura dell'interfaccia PCM: regolare."
    
End


Eseguire una traccia oppure tutte le tracce del CD audio

Di seguito mostriamo il precedente codice, opportunamente modificato per consntire all'utente di scegliere di eseguire una particolare traccia oppure l'intero CD audio.

Library "libcdio:18.0.0"

Private Enum DRIVER_UNKNOWN = 0, DRIVER_AIX, DRIVER_FREEBSD, DRIVER_NETBSD, DRIVER_LINUX, DRIVER_SOLARIS,
             DRIVER_OSX, DRIVER_WIN32, DRIVER_CDRDAO, DRIVER_BINCUE, DRIVER_NRG, DRIVER_DEVICE
Private Const CDIO_INVALID_LSN As Integer = -45301
Private Const CDIO_CDROM_LEADOUT_TRACK As Integer = &AA

' CdIo_t * cdio_open (const char *psz_source, driver_id_t driver_id)
' Sets up to read from place specified by psz_source and driver_id.
Private Extern cdio_open(psz_source As String, driver_id As Integer) As Pointer

' track_t cdio_get_num_tracks(const CdIo_t * p_cdio)
' Get the number of tracks on the CD.
Private Extern cdio_get_num_tracks(p_cdio As Pointer) As Byte
 
' lsn_t cdio_get_track_lsn(const CdIo_t * p_cdio, track_t u_track)
' Return the starting LSN for track number i_track in p_cdio.
Private Extern cdio_get_track_lsn(p_cdio As Pointer, u_track As Integer) As Integer

' driver_return_code_t cdio_read_audio_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn)
' Read an audio sector.
Private Extern cdio_read_audio_sector(p_cdio As Pointer, p_buf As Byte[], i_lsn As Integer) As Integer

' void cdio_destroy(CdIo_t * p_cdio)
' Free any resources associated with p_cdio.
Private Extern cdio_destroy(p_cdio As Pointer)


Library "libasound:2"

Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0
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, 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, 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, buffer 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(pcm 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 cd As Pointer
 Dim traccia, tracce, n_tr, i As Byte
 Dim cbf As Integer
 Dim lsn As New Integer[]
 Dim s As String
 
' Il valore della variabile "cbf" è data dal prodotto del numero dei canali per la risoluzione in bit per la frequenza della traccia audio:
'   canali bit frequenza
 cbf = 2 * 16 * 44100
 
 cd = cdio_open(Null, DRIVER_LINUX)
 If cd == 0 Then Error.Raise("Impossibile trovare il driver per il cd-audio !")
 
 tracce = cdio_get_num_tracks(cd)
 Print "Tracce del CD-Audio (1 - "; tracce; ")"
 Print " #:  Durata"
' Individua l'indirizzo del settore logico di ciascuna traccia:
 For i = 1 To tracce
   lsn.Push(cdio_get_track_lsn(cd, i))
 Next
 lsn.Push(cdio_get_track_lsn(cd, CDIO_CDROM_LEADOUT_TRACK))
 
 For i = 0 To tracce - 1
   If (CDIO_INVALID_LSN <> lsn[i]) Then
     Print Format(i + 1, "#0:"), Date(0, 0, 0, 0, 0, 0, ((((lsn[i + 1] - lsn[i]) * 2352) * 8) / cbf) * 1000)
   Endif
 Next
     
'''''''''''''''''''
 n_tr = 1
  
' Si sceglie se eseguire una sola traccia e l'intero CD audio:
 Print "\nPer eseguire una sola traccia, inviare il numero corrispondente."
 Print "Per eseguire tutte le tracce del CD audio, premere 'Invio.'\n"
 Input s
  
' Se si è scelto di eseguire solo una traccia, imposta il suo numero:
 If IsDigit(s) Then
   n_tr = Val(s)
   tracce = n_tr
 Endif
  
 For traccia = n_tr To tracce
   For i = 0 To tracce - 1
     If i + 1 = traccia Then
       Print Format(i + 1, "#0:"), Date(0, 0, 0, 0, 0, 0, ((((lsn[i + 1] - lsn[i]) * 2352) * 8) / cbf) * 1000)
     Endif
   Next
   lsn.Push(cdio_get_track_lsn(cd, CDIO_CDROM_LEADOUT_TRACK))
   Esecuzione(cd, lsn, traccia)
 Next
  
' Va in chiusura:
 cdio_destroy(cd)
  
End
 
 
Private Procedure Esecuzione(pcd As Pointer, sett As Integer[], tr As Byte)
 
 Dim handle As Pointer
 Dim err, i, frames, somma_frames As Integer
 Dim buf As Byte[]
 
 err = snd_pcm_open(VarPtr(handle), "default", SND_PCM_STREAM_PLAYBACK, 0)
 If err < 0 Then Error.Raise("Errore nell'apertura del subsistema PCM: " & snd_strerror(err))
 
 err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 2, 44100, 1, 500000)
 If err < 0 Then
   snd_pcm_close(handle)
   Error.Raise("Errore nell'impostazione dei parametri audio: " & snd_strerror(err))
 Endif
 
 buf = New Byte[2352]
  
 For i = 0 To (sett[tr] - sett[tr - 1]) - 1
   cdio_read_audio_sector(pcd, buf, sett[tr - 1] + i)
   frames = snd_pcm_writei(handle, buf.Data, 2352 / 4)
   somma_frames += frames
   Write #File.Out, "\rTempo trascorso: " & Date(0, 0, 0, 0, 0, 0, (somma_frames / 44100) * 1000)
   Sleep 0.01
 Next
 
 snd_pcm_drain(handle)
 
' Alla fine dell'esecuzione chiude il subsistema PCM:
 err = snd_pcm_close(handle)
 If err = 0 Then Print "\nChiusura dell'interfaccia PCM: regolare."
     
End


Riferimenti