Die ersten 32Bit einer File auslesen
-
@peter
mir faellt noch was auf.
bei deiner pruefung fuer die 3 bits musst du natuerlich
die anderen 5 bits rausmaskieren, denn diese koennen beliebig
sein.
du suchst nach einer bitfolge: 1111 1111 111x xxxx
(jetzt mal unabhaengig von meinem post zu big/little endian,
also nicht irritiert sein :)).
also musst du, nachdem du die bitfolge 1111 1111 gefunden
hast, das naechste byte mit 224 verunden:eingelesenes bit: 111x xxxx maske: &1110 0000 (224) ---------------------------- 111000000 (224)
und testen, ob das ergebnis der bitweisen und verknuepfung 224 ergibt.
-
Mitlerweile bin ich ein wenig durcheinander gekommen was das das einlesen und abspeichern anbelangt. Ich denke ich sollte eine grundlegene sache klären. Was ist der Unterschied zwischen der Reihenfolge wie die 4Byte in meiner mp3 liegen und den 4Byte wie ich sie in meinem Programm abspeichere? Der momentane Code ist der hier:
#include <iostream> #include <conio.h> #include <fstream> using namespace std; int main () { long int First4x8Bit; //Speicher fuer 32 Bit=4 Byte short int Bits[32]; //Char- Vektor fuer Bit- Zustand short int Bits2[8]; char OneByte; int count = 0; const unsigned char FILLED_BITS = '0xFF'; const unsigned char FILLED_BITS2 = '0xE0'; FILE * FilePointer; //File Header erst einmal finden FilePointer = fopen("C:\\Music\\d-12 - devil's night\\d12 - 11 - fight music.mp3", "rb"); while (fread(&OneByte,1,1,FilePointer )==1) //Ein Byte lesen { if (OneByte==char(0xFF)) //alle Bits gesetzt? { fread(&OneByte,1,1,FilePointer); if (OneByte>=char(0xE0)) { cout << "8Bits Set gefunden"<<endl; break; } } count++; } cout << "File Header located at Byte" << count << endl; fclose(FilePointer); //4Bytes nach finden des Mp3 Headers einlesen FilePointer = fopen("C:\\Music\\d-12 - devil's night\\d12 - 11 - fight music.mp3", "rb"); fseek (FilePointer, count, SEEK_SET); for (int j=0;j<4;j++) //4 Bytes { fread(&First4x8Bit,1,1,FilePointer ); //Block- Lesen!!!(Binaerdatei) for (int i=0 ; i<8 ; i++) //Alle 8 Bits durchgehen { if ((First4x8Bit&(1<<i)) > 0) Bits[i + 24 - 8 * j] = 1; //Charvektor belegen else Bits[i + 24 - 8 * j] = 0; } } fclose(FilePointer); //Ausgeben der 32Bit for (int i=0 ; i<32; i++) { cout << "Bit " << i << ": " << Bits[i] << endl; } }
Nehmen wir mal an der Header in meiner Mp3 sieht so aus:
Byte1 Byte 2 Byte 3 Byte 4 00110011 00001111 01010111 1111111 |frame sync|
wenn ich es mit meinem code ausgebe, kommt es auch in dieser reihenfolge raus.
aber wie wird es abgespeichert? das ist doch anders rum oder nicht?[ Dieser Beitrag wurde am 31.03.2003 um 20:36 Uhr von Peter Piksa editiert. ]
-
peter.... lol ich hoffe ich hab dich nicht zusehr verwirrt .
also was deine einlesen-schleife angeht ... ui... sieht kompliziert
aus; und ich hab keine ahnung was du da machst...
ich poste dir unten mal einen programmteil, der dir die ersten
32 bits ausgibt, schau es dir mal an, es sollte einfacher
zu verstehen sein als dein bissheriger code.das programm liefert dir als ausgabe:
(1111 1111) (0101 1111) (0000 1001) (0000 0010)
die klammern sind wieder die bytegrenzen.wenn du jetzt den header suchen willst, musst du immer ein
byte einlesen. das eingelsenen byte vergleichst du mit 255
(-> alle bits 1, also if ( byte == 255 ) ).
hast du ein solches byte gefunden, musst du schauen, ob das
naechste byte die form 111x xxx hat.
also:
if ( (byte & 224) == 224 )
/* die ersten 3 byte sind 111 -> header gefunden */das funktioniert auf jeden fall; egal wie die bytes intern
angeordnet sind.hast du den header gefunden, und willst nun die einzelnen
bits abfragen taucht wahrscheinlich ein problem auf.
jetzt kann es sein das ich ein bisschen muell erzaehle :),
das musst du mal mit deinem programm nachpruefen.
es sieht so aus als seien in den mp3 dateien die einzelnen
bits wie folgt angeordnet:5 6 7 8 1 2 3 4 (bitnr) 1 1 1 1 0 1 0 1 (bits) (---EIN BYTE---) sollte das so sein, so musst du die beiden halbbytes zuerst vertauschen, bevor du abfragen kannst, ob z.b. das 1. bit gesetzt ist (weil das erste bit ja von links gesehen an 5. stelle steht).
so nun zum code
schau dir mal folgende zeilen an:
(der header BEGINNT mit den syn-bits und endet nicht
damit, schau nochmal in die definition der mp3s!)#define BITSET_BYTESIZE 8 /* Prueft, ob das bit an der Stelle bitnr * gesetzt ist oder nicht. * * Bit Nr. 1 steht links. */ int bitset_isset( const unsigned char* bytes, int bitnr ) { const short int MASKE = 1; while ( bitnr > BITSET_BYTESIZE ) { ++bytes; bitnr -= BITSET_BYTESIZE; } --bitnr; return ( (*bytes) & ( MASKE << bitnr ) ); } .... char puffer[4]; fread( puffer, 1, 4, mp3 ); for ( i = 1; i <= 32; ++i ) { if ( bitset_isset( puffer, i ) ) printf( "%d", 1 ); else printf( "%d", 0 ); if ( i % 4 == 0 ) printf( " " ); } printf( "\n" ); fclose( mp3 );
[ Dieser Beitrag wurde am 31.03.2003 um 19:17 Uhr von entelechie editiert. ]
-
@entelelchie:
Der Header beginnt nicht mit den 11Bits Frame Sync.
Er endet mit ihnen.
Schau mal hier: http://home.swipnet.se/grd/mp3info/frmheader/index.html
da stehts schwarz auf organge *g*
Position: 21-31.Könnte ich denn nicht auch wenn das hier stimmt,
5 6 7 8 1 2 3 4 (bitnr) 1 1 1 1 0 1 0 1 (bits) (---EIN BYTE---)
einfach den RechtsShiftOperator verwenden?
[ Dieser Beitrag wurde am 31.03.2003 um 20:56 Uhr von Peter Piksa editiert. ]
-
Hi alle zusammen
Irgendwas scheint mit der Bit / Byte- Anordnung nicht zu stimmen.
So wie ich das sehe (getestet hab):
Die Suche nach dem Header mueste so gehen, wie gepostet (Bei mir findet der die Header - z.T. mehrere in der Datei)
Die 2 zu testenden Byte stehen DIREKT hintereinander!!!
d.h.: wenn du das Byte 0xff gefunden hast, muss das FOLGENDE Byte 0xe0 oder groesser sein! Da das die 3 hoechsten Bit im Byte sind, geht das ohne Maskierung.(Jedes weitere Bit vergroessert den Wert)Das Auslesen des Headers muesste so gehen, wie wir das 3 Seiten vorher im Thema hatten! Dazu muss der Header komplett gelesen werden: Die 2 Testbyte gehoeren dazu!!! Deshalb Filepointer neu setzen - muss 2 Byte zurueck.
Die Auswertung der 4 Headerbytes war in 'verdrehter Reihenfolge'
Du sagst, mit dem Test (letzte variante) findet der die Header. Die Auswertung klappte wie Du sagst auch.
Also muesste das doch richtig sein! Wenn das klappt bis auf EINE EINZIGE Datei, wuerde ich sagen ok, die Datei hat ev. einen Fehler oder ein Neues Foermat?
-
Original erstellt von DerAltenburger:
**Hi alle zusammen
Die 2 zu testenden Byte stehen DIREKT hintereinander!!!
d.h.: wenn du das Byte 0xff gefunden hast, muss das FOLGENDE Byte 0xe0 oder groesser sein! Da das die 3 hoechsten Bit im Byte sind, geht das ohne Maskierung.(Jedes weitere Bit vergroessert den Wert)
**Die 11 Bits Frame Sync sind die letzen der 32Bits Header.
dass heisst mann muss wenn überhaupt dann erstmal ein Byte suchen bei dem die drei LowBits 1 sind und daraufhin testen ob das nächste byte 0xFF ist!Es sieht doch so aus:
(xxxx xxxx) (xxxx xxxx) (xxxx x111) (1111 1111)
Ich meine da steht doch auf der von mir verlinkten seite beschrieben dass die 11 Bits position 21-31 des Headers belegen...
-
Hi Peter Piksa
Das macht mich jetzt irgendwie irre??? (Kann ja gar nicht mehrpassieren :p )
Wir hatten Doch mal die von Dir gepostete Datei untersucht. Da steht der Header (wie bei vielen mp3s) ganz am Anfang!
Das 1. Byte DER DATEI ist 0xff
Das 2. Byte DER DATEI ist 0xe?Dadurch sind wir doch drauf gekommen, dass die 4 Byte DES HEADER (zu dem die beiden gehoeren) 'verkehrtrum stehen und haben die Awertung DES HEADER umgedreht. Seitdem sagst Du, der Header wird RICHTIG erkannt! - bis auf die eine Datei.
Du darfst die Suche nach dem Header und dessen Auswertung nicht verwechseln!!!
In der MP3 stehen die HOEHEREN Bytes zuerst, das NIEDRIGSTE Byte zuletzt!
Ich seh jetzt Dein Problem nicht!
Du findest (fast immer) den Header und die Auswertung geht???
-
hummmmm *grübeltnachundwurdeüberzeugt*
Ich werde heute wenn ich wieder zu Hause bin mal 50 mp3s testen und schauen wie zuverlässig das ganze wirklich arbeitet. Die ergebnisse werde ich dann hier posten und fragen was ihr davon haltet.
-
Hi Peter Piksa
Ich hab das ganze nochmal zusammengefasst:
//Datentyp zum Speichern einer 4 byte Zahl //Zugriff moeglich: //als DoppelWord //als 4 Byte Vektor typedef union //Datentyp fuer { unsigned char Bytes[4]; //Byte- zugriff oder unsigned long DWords; //DWord- zugriff }HeaderTyp; //Type- Name //Routine zum Suchen, Lesen und Auswerten des Headers in MP3- Dateien //Die Reihenfolge der Bytes in MP3- Files ist: //Hoeherwertigstes Byte ... niederwertigstes Byte //Deshalb werden die 4 Bytes 'rueckwaerts' in den Puffer gelesen! //Die Auswertung aller 32 Bit = 4 Byte kann 'normal' erfolgen! FILE *fp; //File Pointer HeaderTyp Header; //Header- Variable (4 Byte) int i; unsigned long HPos=0; //Headerposition fp=fopen(FileListBoxWatch1->FileName.c_str(),"rb"); //Datei oeffnen if (fp) //falls Datei geoeffnet { while ((i=fread(&Header.Bytes[3],1,1,fp))==1) //Solange Byte lesbar { if (Header.Bytes[3]==0xFF) //Alle Bit gesetzt? { if (i=fread(&Header.Bytes[2],1,1,fp)==1) //Naechstes Byte gelesen? { if (Header.Bytes[2]>=0xE0) //Obere 3Bit gesetzt? { break; //Header gefunden } fseek(fp,-1,SEEK_CUR); //Filepointer zurueck HPos++; //Position hochzaehlen } } else //Nicht alle Bits { HPos++; //Position hochzaehlen } } //Schleifenende if (i==1) //Bytes wurden gelesen { /* fseek(fp,HPos,SEEK_SET); i=fread(&Header.Bytes[3],1,1,fp); i=fread(&Header.Bytes[2],1,1,fp); */ i=fread(&Header.Bytes[1],1,1,fp); //noch 2 Byte i=fread(&Header.Bytes[0],1,1,fp); //lesen } fclose(fp); //Datei schliessen if (i==1) //Header wurde gelesen? { for (i=0;i<32;i++) //Alle 32 Bit auswerten { if ((Header.DWords&(1<<i))==(1<<i)) { //Das i. Bit ist gesetzt } else //Das i. Bit ist nicht gesetzt } } else { //Header not found } } else { //Datei nicht geoeffnet }
Genau so funzt das bei mir 1a! Liefert den Header und die Position in der Datei.
Getestet mit 144 MP3- Dateien!(Was genau im Header steht, hab ich nicht getestet! Nur die oberen 11 Bit.
-
Ok, 50 ist ein wenig übertrieben gewesen, ich habe mal 15 Mp3s, querbeet rausgepickt und die Winamp-FileInfo mit den Informationen aus meinem Programm verglichen. Hier sind die Ergebnisse. Für mich sind sie auf jeden fall sehr zufriedenstellend
........Song............................................|.Ergebnis| | Typ | ------------------------------------------------------------------------------- 5th Element - Lucia Di Lammermoor.......................| OK | | VBR | 5th Element - The Diva Dance............................| OK | | VBR | Adam Sandler - Uses of the Word Fuck....................| OK | | CBR | Afroman - Crazy Rap.....................................| OK | | CBR | Audiobastards - Slipknot Surfacing High Speed Remix.....| OK | | CBR | Bloodhound Gang - Ballad Of Chasey Lain.................| OK | | CBR | Burial - Failure Of Technology..........................| OK | | CBR | Burial - Heaven Street..................................| OK | | CBR | Burial - Inner Hostility................................| OK | | CBR | Busta Rhymes - Fire it up (Knight Rider Remix)..........| OK | | CBR | Coolio - Ooh la la......................................| OK | | CBR | Giovanni Trappatoni - Flasche Leer Konferenz............| OK | | CBR | Eminem feat. Marilyn Manson - The Way I Am..............| OK | | CBR | Panjabi MC - Mundian To Bach Ke.........................| OK | | VBR | TCPA-Bericht von Chaosradio.............................| OK | | CBR |
:|: Ausschliesslich bei den VBR mp3s hat das dingen mir fehler in der Bitrate produziert, aber ansonsten läuft es anstandslos. Ich denke dass die eine Mp3 von Cannibal Corpse feat. Tori Amos falsch encodiert wurde oder sowas in der art. Die Mp3 ist schuld nicht das Programm! *fg*
[ Dieser Beitrag wurde am 01.04.2003 um 16:06 Uhr von Peter Piksa editiert. ]