Die ersten 32Bit einer File auslesen
-
@DerAltenburger:
Ich bin jetzt schon seid knapp 4 Stunden dabei eine Funktion zu schreiben, die mir die Position des MP3Headers ermittelt. Für den Anfang wollte ich es so machen dass er mir ein Byte einliest und halt die entsprechenden Werte (0/1) ein ein char array speichert aber leider scheitert es schon dabeiEines Beispiel von vielen Beispielen was ich schon versucht habe war das hier:
FilePointer = fopen("Guano Apes - Big In Japan.mp3","rb"); fread(&OneByte,1,1,FilePointer ); //Block- Lesen!!!(Binaerdatei) if(OneByte&(1<<0) > 0) Bits2[0] = 0; else Bits2[0] = 1; cout << Bits2[0]<<endl;
Ich hab das Ergebnis mit dem wahren Wert verglichen und er stimmte nicht.
Dann hab ich noch was anderes versucht:
FilePointer = fopen("Guano Apes - Big In Japan.mp3","rb"); fread(&OneByte,1,1,FilePointer ); //Block- Lesen!!!(Binaerdatei) if(OneByte == 0xFF) cout << "true" <<endl; else cout << "false" <<endl;
Das müsste ja eigentlich True sein aber es klappt vorne und hinten nicht
Was mache ich falsch?
-
hm ich poste mal ein paar funktionen aus meiner
bitsset-lib ;), die sollten funktionieren:#define BITSET_BYTESIZE 8 /* prueft, ob das bit an der stelle bitnr * gesetzt ist oder nicht */ 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 ) ); } /* setzten des bits an stelle bitnr */ void bitset_setbit( unsigned char* bytes, int bitnr ) { const short int MASKE = 1; while ( bitnr > BITSET_BYTESIZE ) { ++bytes; bitnr -= BITSET_BYTESIZE; } --bitnr; (*bytes) |= ( MASKE << bitnr ); } /* loeschen des bits an stelle bitnr */ void bitset_clearbit( unsigned char* bytes, int bitnr ) { const unsigned char MASKE = 254; while ( bitnr > BITSET_BYTESIZE ) { ++bytes; bitnr -= BITSET_BYTESIZE; } --bitnr; (*bytes) &= ( MASKE << bitnr ); } /* schreibt die bits als '0' und '1' aus bytes nach bits * len ist die groesse von bytes * * achtung: bits muss mind die groesse BITSET_BYTESIZE * len haben */ void bitset_tobits( char* bits, const unsigned char* bytes, int len ) { int i = 0; int j = 0; for ( i = 0; i < len; ++i, ++bytes ) { for ( j = 0; j < BITSET_BYTESIZE; ++j, ++bits ) { if ( bitset_isset( bytes, j + 1 ) ) *bits = '1'; else *bits = '0'; } } }
[ Dieser Beitrag wurde am 30.03.2003 um 03:26 Uhr von entelechie editiert. ]
-
Deine Funktionen sehen interessant aus (setzen, testen ... von Bits)
@Peter Piksa
Was soll Deine letzte 'Funktion' genau machen???
Du sagst, Du willst den 'MP3 Header' suchen!???
Dazu musst Du die Datei solange auslesen, bis Du zwei spezielle Bytes gefunden hast!
1. Byte : alle Bits gesetzt = 255 = 0xFF
2. Byte : die 3 hoechsten Bits gesetzt = 0xE0 oder groesser!int HeaderPos=0; bool HeaderFound=false; FilePointer = fopen("Guano Apes - Big In Japan.mp3","rb"); while (fread(&OneByte,1,1,FilePointer )==1) //Ein Byte lesen { if (OneByte==char(0xFF)) //alle Bits gesetzt? { if (fread(&OneByte,1,1,FilePointer )==1) //Noch ein Byte lesen { if ((OneByte&0xE0)==0xE0) //3 obere Bits gesetzt? { //Header gefunden HeaderFound=true; break; //Schleife abbrechen } HeaderPos++; //Byte- Position 'hochzaehlen' } } HeaderPos++; //Byte- Position 'hochzaehlen' } if(HeaderFound) //Nur wenn Header gefunden: { fseek(FilePointer,HeaderPos,0); //Filepointer setzen!!! //VOR die 2 gefundenen Bytes //Nun Header auslesen (4 Byte) //und auswerten! fclose(FilePointer) } else { fclose(FilePointer); //Header nicht gefunden!!! }
PS:
Sorry, im vorherigen, allgemeinen Post ist 'n Fehler!!!
if ((OneByte&0xE0)==0xE0) //3 obere Bits gesetzt
ist richtigNICHT
if ((OneByte&0xE0)>0) //testet ob 1,2 oder 3 obere Bits gesetzt
[ Dieser Beitrag wurde am 30.03.2003 um 17:30 Uhr von DerAltenburger editiert. ]
[ Dieser Beitrag wurde am 30.03.2003 um 17:45 Uhr von DerAltenburger editiert. ]
-
@DerAltenburger:
Ich habe jetzt einfach mal deinen Code um eine Kontrollzeile erweitert:while (fread(&OneByte,1,1,FilePointer )==1) //Ein Byte lesen { if (OneByte==char(0xFF)) //alle Bits gesetzt? { cout << "8Bits Set gefunden"<<endl;
Komischerweise zeigt er mir diese Nachricht nicht an obwohl sie kommen müsste.
Und was bedeutet OneByte==char(0xFF) ?
Mein Programmiernlehrer meinte man kann auch einfach schreiben OneByte == 0xFF...was macht dieses char davor?
-
Hi Peter Piksa
Dein Programmier(n)lehrer hat eigentlich Recht.
Der BCB, mit dem ich arbeite mag das aber nicht, der scheint 0xff zu erweitern (oder arbeitet mit Vorzeichen???) Mit OHNE typecast char(0xFF) klappt's im BCB nicht, k.a. warum.
Du kannst das theoretisch weglassen. Dein Compiler kann's dann vielleicht besser!
char(0xFF) erzwingt, dass ein EinByte- Wert kommt.(Wie gesagt, ist bei meinem BCB noetig, muesste eigentlich ohne gehen!!!)
Du musst dir den Inhalt von OneByte mal im Debugger anschauen!!!
Und mach den Typecast mal raus!!!
PS: Mit dem geposteten Code (etwas erweitert!) hab ich mehrere Header in MP3- Dateien gefunden!!! Genau wie das sein sollte!
[ Dieser Beitrag wurde am 30.03.2003 um 19:50 Uhr von DerAltenburger editiert. ]
-
Kann es vielleicht sein dass bei mir immer wieder "nicht gefunden" raus kommt, weil der FilePointer sich nicht weiterbewegt?
-
Neeeeee
Der Filepointer wird immer automatisch weitergeschoben um die gelesenen Bytes!
Wenn Du in der leseschleife nicht mit fseek(...) den Zeiger 'stoerst', mueste das klappen!
Probiermal die MP3- Datei die Du gelinkt hattest! Da ist der Header gleich am Anfang! Und dann mit dem Debuggerganz langsam durchgehen!
Haste den Typecast mal entfernt?
-
Hi
Euer Problem läst so lösen
const unsigned char FILLED_BITS = '\xFF';
Dann kannst du:
while (fread(&OneByte,1,1,FilePointer )==1) //Ein Byte lesen { if (OneByte==char(0xFF)) //alle Bits gesetzt? { cout << "8Bits Set gefunden"<<endl;
-
@DerAltenburger:
Ja ich habe den Typecast mal entfernt.
Das hat aber nichts gebracht.
Wenn ich dem FilePointer seine aktuelle Position gespeichert habe, muss ich die dann auch bei fread irgendwo angeben?
Ich bin die datei "Dreierbezeihung.mp3" mal durchgegangen und beim ersten durchlauf kam bei mir in der Variable (First4x8Bits) das rein -> 4657488. (ich weiss dass es First4x8Bits und nicht OneByte ist, aber das ist ja egal oder nicht?)while (fread(&OneByte,1,1,FilePointer )==1) //Ein Byte lesen { pos = ftell (datei); fseek (datei, pos+1, SEEK_SET); //pos+1 damit er ein byte weiter hüpft if (OneByte==0xFF) //alle Bits gesetzt? { cout << "8Bits Set gefunden"<<endl; break; } }
Die sache mitvon <DerAufDieSprüngeHelfer> hat übrigends gar nichts gebacht
[ Dieser Beitrag wurde am 30.03.2003 um 21:01 Uhr von Peter Piksa editiert. ]
-
Da haste 'n tollen Fehler drin!!!
Wenn in Variable (First4x8Bits) 4657488 steht, kanns net gehen!
Dann ist First4x8Bits keine 1 Byte Variable - 0..255 (-128 .. 127 erlaubt)
Wenn der Datentyp nicht stimmt, klappt der Vergleich nicht!!!
DU MUSST OneByte nehmen - und das muss ein 1 Byte Typ sein!!!
PS: DerAufDieSprüngeHelfer hat irgendwas weggelassen???
[ Dieser Beitrag wurde am 30.03.2003 um 21:09 Uhr von DerAltenburger editiert. ]
-
ich habe mal ne kurze zwischenfrage zu dem thema :).
wenn ich mir die ersten zwoelf bytes der datei (dreier....mp3) ausgeben
lasse, dann sind die bytes paarweise vertauscht.
ein hex dump liefert folgendes:
ff fa ....
mein program vertauscht die bits und liefert:
f f a f
1111 11111 0101 11111habt ihr das auch oder mach ich was falsch?!
-
WOAAAAH!!!! Ich geh kaputt!!! *freudensprungmach* !!!
Es Läuft!!!
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; long int pos; int count = 0; const unsigned char FILLED_BITS = '0xFF'; FILE * FilePointer = fopen("C:\\Emmanuel Top - Turkish Bazar 2002 (Radio MX).mp3", "rb"); while (fread(&OneByte,1,1,FilePointer )==1) //Ein Byte lesen { if (OneByte==char(0xFF)) //alle Bits gesetzt? { //cout << "8Bits Set gefunden"<<endl; break; } else //cout << "Bits nicht gefunden"<<endl; count++; } cout << "File Header located at Byte" << count << endl; fclose(FilePointer); FilePointer = fopen("C:\\Emmanuel Top - Turkish Bazar 2002 (Radio MX).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);
Ich raffs zwar nicht so ganz aber es geht *rofl*
-
@Peter Piksa
Na dann war die ganze Aufregung ja wenigstens nicht umsonst!
Das hatten wir auch! Die Bytes stehen so komisch drin.
Schau mal ca 2 Seiten weiter vorn nach, da haben wir das diskutiert!
-
Es wird ja gesagt dass wenn man das ff Byte gefunden hat, mann eigentlich noch die drauf folgenden drei Bits lesen sollte aber ich habe jetzt knapp 20 mp3s getestet und überall kam das richtige ergebnis raus
Meint ihr man sollte das trotzdem einbauen?
-
Ok, es ist geschen. *fg*
"Cannibal Corpse featuring Tori Amos - Stripped, Raped And Strangled .mp3" hat das Programm, so wie es jetzt ist an einen Fehler getrieben. Also werd ich wohl doch noch die Prüfung mit den drei bits hinzunehmen müssen. Ich hoffe ich schaff das...
-
@peter
mir ist grade was aufgefallen (was mir eigentlich haette
frueher auffallen sollen).
stichwort big und little endian.
das programm liesst zwar alles richtig ein, aber die
bytes werden intern anders dargestellt.
d.h. bei einer ausgabe der bytes sind die hoeherwertigen
bytes rechts, die niederen links.
in den mp3 dateien, ist es genau umgekehrt.
so wie es aussieht, muessen die bytes wohl erst gedreht werden.
-
@entelechie:
Gestern Abend hab ich mir genau darüber auch Gedanken gemacht *g*
weil ich lese ja erstmal ein Byte ein, prüfe auf 0xFF und dann noch ein Byte. (FrameSync). Die 11Bits für die FrameSync liegen aber am ende der 4Byte. Ich wollts nur nicht sagen weil ich mir dachte dass ihr das schon richtig gemacht habt...
Hmm muss ich eigentlich die einzelnen 4 Bytes einfach nur umdrehen wie hier:aus [1Byte] [2Byte] [3Byte] [4Byte]
wird [4Byte] [3Byte] [2Byte] [1Byte]oder muss ich die einzelnen Bits darum umdrehn wie hier:
aus [12345678] [12345678] [12345678] [12345678]
wird [87654321] [87654321] [87654321] [87654321]@DerAltenburger:
Wo ich schonmal dabei bin würd ich gern mal fragen ob das ganze hier korrekt ist. Es handelt sich um die Prüfung ob das nächte Byte (die drei einsen) nach dem 8x1Bits-Byte folgt.Bei mir läuft es eigentlich ganz gut, wie gesagt nur bei der einen Mp3 von Cannibal Corpse feat. Tori Amos macht er zicken...
const unsigned char FILLED_BITS = '0xFF'; const unsigned char FILLED_BITS2 = '0xE0'; FilePointer = fopen("C:\\Music\\d-12 - devil's night\\d12 - 06 - ain' t nuttin' but 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); count++; if (OneByte>=char(0xE0)) { cout << OneByte<<endl; cout << "8Bits Set gefunden"<<endl; break; } } count++; } count--; cout << "File Header located at Byte" << count << endl; fclose(FilePointer);
[ Dieser Beitrag wurde am 31.03.2003 um 15:16 Uhr von Peter Piksa editiert. ]
-
also peter meine antwort is nur mal unter vorbehalt.
nicht das du ein riesen programmieraufwand hast, weil
ich dir muell erzaehlt habe :).aber es sieht alles so aus als seien die hoeherwertigen
und niederwertigen bytes verdreht.
das einlesen, und testen der einzelnen bits funktioniert
auf jeden fall so wie ich es gepostet habe (den code von altenburger
hab ich nicht getestet).also zum beispiel deine mp3 datei:
die ersten 2 byte sind (als ascii-code) (255) (250).
als bitweise ausgabe kommt: (1111 1111) (0101 1111)
(in den klammern je ein byte).
wie du siehst am beispiel von 250 stehen die hoechstwertigen bits
innerhalb eines bytes rechts.
-
@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. ]