Audio CD: Track auslesen
-
Hi!
Wurschtele momentan mit Audio-CDs rum und komme nicht weiter. Habe alles an Code gewälzt, was ich gefunden habe und hab mir was schönes zusammengebastelt:
Erstmal ein bisschen Ramsch vorneweg, hatte die Include-Datei dazu nicht.
// Ist alles aus irgendner Include, die ich aber nicht hab #define IOCTL_CDROM_RAW_READ 0x2403E #define IOCTL_CDROM_READ_TOC 0x24000 typedef struct _TRACK_DATA { UCHAR Reserved; UCHAR Control : 4; UCHAR Adr : 4; UCHAR TrackNumber; UCHAR Reserved1; UCHAR Address[4]; } TRACK_DATA; typedef struct _CDROM_TOC { UCHAR Length[2]; UCHAR FirstTrack; UCHAR LastTrack; TRACK_DATA TrackData[100]; } CDROM_TOC; typedef enum _TRACK_MODE_TYPE { YellowMode2, XAForm2, CDDA } TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; typedef struct __RAW_READ_INFO { LARGE_INTEGER DiskOffset; ULONG SectorCount; TRACK_MODE_TYPE TrackMode; } RAW_READ_INFO, *PRAW_READ_INFO;
So, jetzt der Code, wo der Fehler auftritt:
// Diese Funktion ist 1:1 übernommen, stimmt mit ziemlicher Sicherheit ULONG MSFToBlocks( UCHAR Msf[4] ) { ULONG Block = Msf[1]*75*60 + Msf[2]*75 + Msf[3]; return Block - 150; } #define SECTOR_SIZE 2352 struct CDTRACK { ULONG Address; ULONG Length; }; int main( ... ) { HANDLE m_hCD; std::vector<CDTRACK> m_aTracks; // Open drive-handle if ( INVALID_HANDLE_VALUE == ( m_hCD = CreateFile( "\\\\.\\H:", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ) ) ) { printf( "CreateFile\n" ); return 0; } // Get track-table and add it to the intern array ULONG BytesRead; CDROM_TOC Table; if ( 0 == DeviceIoControl( m_hCD, IOCTL_CDROM_READ_TOC, NULL, 0, &Table, sizeof(Table), &BytesRead, NULL ) ) { CloseHandle( m_hCD ); m_hCD = NULL; return FALSE; } for ( ULONG i=Table.FirstTrack-1; i<Table.LastTrack; i++ ) { CDTRACK NewTrack; NewTrack.Address = MSFToBlocks( Table.TrackData[i].Address ); NewTrack.Length = MSFToBlocks( Table.TrackData[i+1].Address ) - NewTrack.Address; m_aTracks.push_back( NewTrack ); } printf( "Track-Count: %i\n", m_aTracks.size() ); ULONG nr = 8; CDTRACK& Track = m_aTracks.at(nr); char* Buf = (char*)malloc( Track.Length * SECTOR_SIZE ); RAW_READ_INFO Info = { Track.Address*2048, Track.Length, CDDA }; ULONG Dummy; if ( 0 == DeviceIoControl( m_hCD, IOCTL_CDROM_RAW_READ, &Info, sizeof(Info), Buf, Track.Length*SECTOR_SIZE, &Dummy, NULL ) ) printf( "RAW_READ: %i\n", GetLastError() ); free( Buf ); return 0; }
Also, "H" ist mein CD-Rom Laufwerk. Da liegt eine CD mit 14 Liedern drin. Die Ausgabe "Track-Count: 14" scheint das auch zu bestätigen.
Zum Fehler: Der letzte Aufruf von DeviceIoControl gibt 0 zurück, was einen Fehler bedeutet. GetLastError sagt "87: ERROR_INVALID_PARAMETER".Habe alles mögliche ausprobiert, weiß aber nicht, was an meinen Parametern so schrecklich falsch sein soll
Hoffe, irgendwer kann mir helfen,
mit freundlichen Grüßen,
Badestrand
-
Bin ein bisschen weiter
Der letzte Teil sieht nun so aus:
ULONG BytesToRead = Track.Length*SECTOR_SIZE; char* Buf = (char*)malloc( BytesToRead ); RAW_READ_INFO Info; Info.TrackMode = CDDA; Info.DiskOffset.QuadPart = (ULONG64)Track.Address * SECTOR_SIZE; Info.SectorCount = Track.Length; ULONG Dummy; if ( 0 == DeviceIoControl( m_hCD, IOCTL_CDROM_RAW_READ, &Info, sizeof(Info), Buf, BytesToRead, &Dummy, NULL ) ) printf( "RAW_READ: %i\n", GetLastError() );
Das erste Lied kann damit auch von der CD geladen werden, alle anderen allerdings nicht. GetLastError sagt dann nämlich ERROR_END_OF_MEDIA
Kann mir denn keiner helfen?
-
Falls es wen interressiert: Ich habs raus
Ich finde es absolut unlogisch, dass es so funktioniert, aber es tuts! Außer dass mit dem teilweisen einlesen, das macht Sinn. Dummerweise war auf meiner CD das erste Lied das kürzeste, unter 1 Minute. Da hatte ich keinen Zusammenhang gesehen...
Aber das mit dem 2048 vs 2352 versteh ich nicht... Naja, solange es jetzt funktioniert *FREU*Man siehe:
RAW_READ_INFO Info; Info.TrackMode = CDDA; Info.SectorCount = SECTORS_AT_READ; ULONG BytesToRead = Track.Length*SECTOR_SIZE; char* Buf = (char*)malloc( BytesToRead ); #define SECTORS_AT_READ 13 ULONG PartCount = Track.Length / SECTORS_AT_READ; for ( ULONG i=0; i<PartCount; i++ ) { Info.DiskOffset.QuadPart = Track.Address*2048 + i*SECTORS_AT_READ*2048; ULONG Dummy; if ( 0 == DeviceIoControl( m_hCD, IOCTL_CDROM_RAW_READ, &Info, sizeof(Info), Buf+i*SECTORS_AT_READ*SECTOR_SIZE, SECTORS_AT_READ*SECTOR_SIZE, &Dummy, NULL ) ) { printf( "RAW_READ: %s\n", StrGetLastError() ); break; } } ULONG Remaining = Track.Length % SECTORS_AT_READ; Info.DiskOffset.QuadPart = Track.Address*2048 + i*SECTORS_AT_READ*2048; Info.SectorCount = Remaining; ULONG Dummy; if ( 0 == DeviceIoControl( m_hCD, IOCTL_CDROM_RAW_READ, &Info, sizeof(Info), Buf+i*SECTORS_AT_READ*SECTOR_SIZE, Remaining*SECTOR_SIZE, &Dummy, NULL ) ) { printf( "RAW_READ: %s\n", StrGetLastError() ); break; } CWaveFile Wave; Wave.Save( "C:\\Song.wav", 44100, 16, 2, Buf, BytesToRead );
-
Also ich muss sagen: Ich find deinen Code echt interessant...kannste mir den mal schicken ?
-
Klar, gerne! Hab auch ne Klasse draus gemacht. Kann man aber nur verwenden, um Audio-CDs einzulesen. Als Waves.
Naja, und man kann das CD-Laufwerk auf- und zumachen
-
Und CWaveFile ist auch dabei ? (-> auch von dir) ?
-
Kann ich mitschicken
Brauche aber erstmal deine E-Mail-Addresse und muss gucken, welche Dateien ich alle reinpacken muss. Mache ich dann aber heut abend noch!
-
Supähr^^ ...:
Voila: cpp[Minus]coding[At]arcor[Punkt]de
-
Wer noch nen paar Infos will -> Hab mal sowas wie ein Tutorial auf CodeProject gepostet. Hier klicken
Wer den Artikel mag, darf auch gerne voten
-
Badestrand schrieb:
Wer den Artikel mag, darf auch gerne voten
Hab da gleich mal für dich gevoted
.
-
hehe^^ Hab ich schon gesehen. Danke Danke!!!
-
wow du bist ja voll der profi