Estrarre i dati audio di una traccia di un CD audio e crearne un file WAV con le risorse del API di libcdio paranoia
Da Gambas-it.org - Wikipedia.
Versione del 4 giu 2024 alle 07:25 di Vuott (Discussione | contributi)
Usando alcune risorse esterne della libreria "libcdio_paranoia" è possibile anche estrarre i dati audio grezzi di una traccia di un CD audio e crearne un file WAV.
E' necessario avere installate nel proprio sistema le librerie condivise "libcdio.so.19.0.0", "libcdio_cdda.so.2.0.0" e "libcdio_paranoia.so.2.0.0".
Nel codice che segue sarà richiamata la sola libreria condivisa: libcdio_paranoia.so.2.0.0
Private Const TRACCIA As Integer = 4 '' Imposta il numero della traccia audio di cui estrarre i dati audio Private Const SEEK_SET As Integer = 0 Library "libcdio_paranoia:2.0.0" Private Const CDIO_CD_FRAMESIZE_RAW As Integer = 2352 Private Enum CDIO_FS_AUDIO = 1, CDIO_FS_HIGH_SIERRA, CDIO_FS_ISO_9660, CDIO_FS_INTERACTIVE, CDIO_FS_HFS, CDIO_FS_UFS Private Enum CDDA_MESSAGE_FORGETIT = 0, CDDA_MESSAGE_PRINTIT, CDDA_MESSAGE_LOGIT, CD_FRAMESAMPLES = 588, MAXTRK = 100 Private Enum PARANOIA_MODE_DISABLE = 0, PARANOIA_MODE_VERIFY = 1, PARANOIA_MODE_FRAGMENT = 2, PARANOIA_MODE_OVERLAP = 4, PARANOIA_MODE_SCRATCH = 8, PARANOIA_MODE_REPAIR = 16, PARANOIA_MODE_NEVERSKIP = 32, PARANOIA_MODE_FULL = 255 ' char ** cdio_get_devices_with_cap (char *ppsz_search_devices[], cdio_fs_anal_t capabilities, bool b_any) ' Get an array of device names in search_devices that have at least the capabilities listed by the capabities parameter. Private Extern cdio_get_devices_with_cap(ppsz_search_devices As Pointer, capabilities As Integer, b_any As Boolean) As Pointer ' cdrom_drive_t *cdio_cddap_identify(const char *psz_device, int messagedest, char **ppsz_message) ' Returns a paranoia CD-ROM drive object with a CD-DA. Private Extern cdio_cddap_identify(psz_device As String, messagedest As Integer, ppsz_message As Pointer) As Pointer ' void cdio_free_device_list (char * device_list[]) ' Free device list returned. Private Extern cdio_free_device_list(device_list As Pointer) ' void cdio_cddap_verbose_set(cdrom_drive_t *d, int err_action, int mes_action) Private Extern cdio_cddap_verbose_set(d As Pointer, err_action As Integer, mes_action As Integer) ' int cdio_cddap_open(cdrom_drive_t *d) Private Extern cdio_cddap_open(d As Pointer) As Integer ' cdrom_paranoia_t *cdio_paranoia_init(cdrom_drive_t *d) ' Get and initialize a new cdrom_paranoia object from cdrom_drive. Private Extern cdio_paranoia_init(d As Pointer) As Pointer ' lsn_t cdio_cddap_track_firstsector(cdrom_drive_t *d, track_t i_track) ' Return the lsn for the start of track i_track. Private Extern cdio_cddap_track_firstsector(d As Pointer, i_track As Integer) As Integer ' int cdio_cddap_sector_gettrack(cdrom_drive_t *d, lsn_t lsn) ' Return the track containing the given LSN. Private Extern cdio_cddap_sector_gettrack(d As Pointer, lsn As Integer) As Integer ' lsn_t cdio_cddap_track_lastsector(cdrom_drive_t *d, track_t i_track) ' Get last lsn of the track. Private Extern cdio_cddap_track_lastsector(d As Pointer, i_track As Integer) As Integer ' void cdio_paranoia_modeset(cdrom_paranoia_t *p, int mode_flags) ' Set the kind of repair you want to on for reading. Private Extern cdio_paranoia_modeset(p As Pointer, mode_flags As Integer) ' lsn_t cdio_paranoia_seek(cdrom_paranoia_t *p, int32_t seek, int whence) ' Reposition reading offset. Private Extern cdio_paranoia_seek(p As Pointer, _seek As Integer, whence As Integer) As Integer ' int16_t *cdio_paranoia_read(cdrom_paranoia_t *p, void(*callback)(long int, paranoia_cb_mode_t)) ' Reads the next sector of audio data. Private Extern cdio_paranoia_read(p As Pointer, callback As Pointer) As Pointer ' char *cdio_cddap_errors(cdrom_drive_t *d) ' Returns the current error buffer. Private Extern cdio_cddap_errors(d As Pointer) As Pointer ' char *cdio_cddap_messages(cdrom_drive_t *d) ' Returns the current message buffer. Private Extern cdio_cddap_messages(d As Pointer) As Pointer ' void cdio_paranoia_free(cdrom_paranoia_t *p) ' Free any resources associated with p. Private Extern cdio_paranoia_free(p As Pointer) ' int cdio_cddap_close(cdrom_drive_t *d) ' Closes d and releases all storage associated with it. Private Extern cdio_cddap_close(d As Pointer) As Integer Public Sub Main() Dim drives, cdd, p, buf As Pointer Dim err, mes As Pointer Dim lsn, cur, tra, llsn As Integer Dim fl As File ' Cerca un dispositivo con un CD-DA caricato: drives = cdio_get_devices_with_cap(0, CDIO_FS_AUDIO, False) If (drives > 0) And (Not IsNull(String@(Pointer@(drives)))) Then ' Se ha trovato un CD-ROM con un CD-DA caricato, allora utilizza la prima unità nell'elenco: cdd = cdio_cddap_identify(String@(Pointer@(drives)), 1, 0) Print "Unità CD-Da trovata e utilizzata: "; String@(Pointer@(drives)) Else Error.Raise("Impossibile cercare o accedere ad un drive CD-ROM contenente un CD audio !") Endif ' Non si ha più bisogno della lista dei dispositivi, pertanto si libera la memoria: cdio_free_device_list(drives) If cdd == 0 Then Error.Raise("Impossibile identificare il disco CD audio !") cdio_cddap_verbose_set(cdd, CDDA_MESSAGE_PRINTIT, CDDA_MESSAGE_PRINTIT) If cdio_cddap_open(cdd) <> 0 Then Error.Raise("Impossibile aprire il disco !") ' Ora si leggono i frame del numero della traccia audio, indicato nella Costante "TRACCIA", del CD audio: p = cdio_paranoia_init(cdd) If p == 0 Then Error.Raise("Errore !") lsn = cdio_cddap_track_firstsector(cdd, TRACCIA) If lsn == -1 Then Error.Raise("Problemi nell'avvio dell'LSN !") tra = cdio_cddap_sector_gettrack(cdd, lsn) llsn = cdio_cddap_track_lastsector(cdd, tra) ' Il file WAV sarà salvato nella cartella "/tmp": fl = Open "/tmp/wave.wav" For Create cdio_paranoia_modeset(p, PARANOIA_MODE_FULL Xor PARANOIA_MODE_NEVERSKIP) cdio_paranoia_seek(p, lsn, SEEK_SET) Scrive_WAV_header(fl, (llsn - lsn + 1) * CDIO_CD_FRAMESIZE_RAW) For cur = lsn To llsn - 1 buf = cdio_paranoia_read(p, 0) err = cdio_cddap_errors(cdd) mes = cdio_cddap_messages(cdd) If mes > 0 Then Print String@(mes) If err > 0 Then Print String@(err) If buf == 0 Then Error.Raise("Errore lettura di Paranoia !") Write #fl, buf, CDIO_CD_FRAMESIZE_RAW Next fl.Close cdio_paranoia_free(p) cdio_cddap_close(cdd) End Private Procedure Scrive_WAV_header(fl As File, byte As Integer) ' Indice: Write #fl, "RIFF" ' 0- 3 Numeri(byte + 44 - 8, fl, 4) ' 4- 7 Write #fl, "WAVEfmt " ' 8-15 Numeri(16, fl, 4) ' 16-19 Numeri(1, fl, 2) ' 20-21 Numeri(2, fl, 2) ' 22-23 Numeri(44100, fl, 4) ' 24-27 Numeri(44100 * 2 * 2, fl, 4) ' 28-31 Numeri(4, fl, 2) ' 32-33 Numeri(16, fl, 2) ' 34-35 Write #fl, "data" ' 36-39 Numeri(byte, fl, 4) ' 40-43 End Private Procedure Numeri(num As Long, fi As File, bt As Integer) Dim i As Integer Dim b As Byte Repeat b = Shr(num, Shl(i, 3)) And &FF Write #fi, b As Byte Inc i Dec bt Until bt == 0 End