Die ersten 32Bit einer File auslesen



  • @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 11111

    habt 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! 😉

    @entelechie

    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. ]



  • 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'

    @Peter

    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. ]


Anmelden zum Antworten