Ripping AUDIO CD tracks with Perl using Linux ioctl(2)

Sorry for my ugly English!

./rippatutto.pl /dev/cdrom 1
extract the first track in file "traccia.wav"

The experience in http://robbs-forum.netfirms.com/ioctl/ioctl.html

Ciao a tutti!
Roberto

------------------------------------------------------- ---------------- codice: rippatutto.pl ---------------- #!/usr/bin/perl use strict; sysopen my $cdrom, $ARGV[0], 0; $|++; my $ioctl3par = ""; my $track = pack "C", ($ARGV[1] % 100); my $audiotrack = undef(); # FASE 1): scopriamo quante tracce ha il nostro CD e di che tipo: Dati + o CDDA $ioctl3par = "\x00" x 512; ioctl $cdrom, 0x5305, $ioctl3par; # CDROMREADTOCHDR == 0x5305 my $firsttrackpacked = substr $ioctl3par, 0, 1; my $lasttrackpacked = substr $ioctl3par, 1, 1; my $firsttrack = ord $firsttrackpacked; my $lasttrack = ord $lasttrackpacked; print "il CD in $ARGV[0] ha tracce da $firsttrack a $lasttrack\n"; if ((($ARGV[1]) < $firsttrack) || (($ARGV[1]) > $lasttrack)) { die "traccia $ARGV[1] non trovata in CD $ARGV[0]\n"; } # dove inizia la traccia richiesta .... $ioctl3par = $track . "\x00\x01\x00" . ("\x00" x 8); ioctl $cdrom, 0x5306, $ioctl3par; # CDROMREADTOCENTRY == 0x5306 my $trackbegin = unpack "V", (substr $ioctl3par, 4, 4); $audiotrack = ord substr $ioctl3par, 2, 1; if ($audiotrack == 1) { print "traccia $ARGV[1] di tipo CDDA\n"; } elsif ($audiotrack == 41) { die "traccia $ARGV[1] di tipo DATA\nEstraggo solo tracce di tipo C +DDA\n"; } else { die "cosa potra' essere traccia $ARGV[1] di tipo $audiotrack?\n"; +} # dove termina la traccia richiesta .... if ($ARGV[1] == $lasttrack) # l' ultima traccia termina alla LEADOUT t +rack (0xAA) { $ioctl3par = "\xaa\x00\x01\x00" . ("\x00" x 8); ioctl $cdrom, 0x5306, $ioctl3par; # CDROMREADTOCENTRY == 0x5306 } else # la traccia termina dove inizia la prossima { $ioctl3par = pack "C", ($ARGV[1] + 1) . "\x00\x01\x00" . ("\x00" x 8 +); ioctl $cdrom, 0x5306, $ioctl3par; # CDROMREADTOCENTRY == 0x5306 } my $trackend = unpack "V", (substr $ioctl3par, 4, 4); print "la traccia $ARGV[1] richiesta inizia da frame $trackbegin e ter +mina a frame " . ($trackend - 1) . "\n"; # FINE FASE 1): abbiamo $trackbegin e $trackend della traccia richiest +a. # sappiamo inoltre che la traccia e' di tipo CDDA ($audiotrack == 1). # per tracce DATA ($audiotrack == 41) l' arg. a ioctl e' diverso come +pure # la lunghezza delle frames # # -------------------------------------------------------------------- +-- # fase 2): estraiamo le frames di 2352 a 64 per chiamata ioctl. open my $trackfile, ">traccia.wav"; if ($audiotrack == 1) { my $filelength = (($trackend - $trackbegin) * 2352); # 44 bytes di interstazione traccia.wav # | RIFF | | LENGHT | + | WAVE | my $waveheader = "\x52\x49\x46\x46" . (pack "V", ($filelength + 36)) + . "\x57\x41\x56\x45" . # | "fmt_" | | sempre 0x10 | | 0x01 + + Stereo | "\x66\x6d\x74\x20" . "\x10\x00\x00\x00" . "\x01\x00 +\x02\x00" . # | 44100 Hz | | bytes/sec | | bytes x + sample | "\x44\xac\x00\x00" . "\x10\xb1\x02\x00" . "\x04\x00 +\x10\x00" . # | DATA | | LENGHT DATA == LENGHT - 36 | "\x64\x61\x74\x61" . (pack "V", $filelength); syswrite $trackfile, $waveheader; } # /* This struct is used by the CDROMREADAUDIO ioctl */ # struct cdrom_read_audio # { # union cdrom_addr addr; /* frame address */ # __u8 addr_format; /* CDROM_LBA or CDROM_MSF */ # int nframes; /* number of 2352-byte-frames to read at on +ce */ # __u8 __user *buf; /* frame buffer (size: nframes*2352 bytes) +*/ # }; # attenti al word-alignment !!!! my $frameindex = $trackbegin; my $packedidx = pack 'V', $frameindex; my $frames = "\x00" x (2352 * 128); # sovraddimensionato! # 128 frames non si possono legger +e! ne leggeremo 64! my $nframes = (($trackend - $frameindex) >= 64) ? 64 : ($trackend - $f +rameindex); $ioctl3par = pack('V', $frameindex) . # leggiamo da questo indice di +frame. "\x01\x00\x00\x00" . # indirizziamo in LBA. pack('V', $nframes) . # leggiamo questo numero di fra +mes. pack('P', $frames) . # mettiamo nello scalare puntat +o da ... ("\00" x 16); # sovraddimensioniamo... :) $! = 0; while ($nframes) { ioctl $cdrom, 0x530e, $ioctl3par; # CDROMREADAUDIO == 0x530e syswrite $trackfile, $frames, (2352 * $nframes); $frameindex += $nframes; $nframes = (($trackend - $frameindex) >= 64) ? 64 : ($trackend - $fr +ameindex); $ioctl3par = pack('V', $frameindex) . # leggiamo da questo indice d +i frame. "\x01\x00\x00\x00" . # indirizziamo in LBA. pack('V', $nframes) . # leggiamo questo numero di f +rames. pack('P', $frames) . # mettiamo nello scalare punt +ato da ... ("\00" x 16); # sovraddimensioniamo... :) } close $trackfile; close $cdrom; ------------- fine codice: rippatutto.pl -------------- -------------------------------------------------------

In reply to Ripping AUDIO CD tracks with Perl using Linux ioctl(2) by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.