Die ersten 32Bit einer File auslesen



  • Original erstellt von Peter Piksa:
    @Noesis: Ja stimmt. Danke dass du mich drauf hingewiesen hast. 🙂
    Ich hab aus dem char eben ein short int gemacht 🙂
    Hast du vielleicht ne Idee wie ich herausfinden kann an welcher Position in einer Mp3 sich der Header befindet?

    nimm am besten long double dann spart es noch mehr Platz 😃 . Ne mal im Ernst, in den MSDN gibts ne ganz gute Tabelle mit den einzelnen Datentypen. Lohnt sich mal da reinzugucken...

    Kannst dir ja auch ne struct machen die nur ein Bit speichert 😃 *lol*

    struct bit{
      unsigned val:1;
    };
    

    Bringt aber nix...

    Ein Bitset benutzt auch bool und das hat auch 8 Bit, also genau wie char... Die "resourcenschonendste" Lösung (und nervenaufreibenste dazu) ist mit << und & die Bits auszulesen...

    [ Dieser Beitrag wurde am 25.03.2003 um 13:18 Uhr von MaSTaH editiert. ]



  • Um noch mal auf das Aufspüren des Headers zurückzukommen.

    Ich habe mich in einem Forum angemeldet, wo leute sich speziell nur über Soundformate wie MP3, ogg-Vorbis und Konsorten unterhalten. Als ich dort die Frage stellte wie ich den Header aufspüren kann, erhielt ich folgende Antwort:

    It is very easy to locate the sync-block of the header. It consists of 11 set bits. So just serach for 0xFF, it you found it, check if the next byte have the first 3 bits set (byte&0xE0 == 0xE0), if yes you found it.

    Ich kann dem Autor leider nicht so ganz folgen.
    Die 11 gesetzen Bits treten bei mir am ende auf. Die Finde ich bei mir. Das passt also. Aber was er dann anschliessend versucht zu erklären, dass ist für mich nicht so ganz verständlich. Stellt dieses 0xFF meine 11 Bits dar? Wenn diese 11 Bits am ende der 32Bit liegen, dann muesste ich ja nur 21Bit zurückspringen und wäre somit am anfang. Verstehe ich das korrekt?



  • 0xFF stellt 8 gesetzte bit dar: 11111111
    der block beginnt dort, wo 11 bits nacheinander gesetzt sind. also fehlen noch drei

    11111111 111XXXXX
       |         |
     1.Byte    2.Byte
    

    Also suchst du ein byte mit 0xFF und das zweite muss die ersten drei bits gesetzt haben (byte2 & 0xE0 == 0xE0, denn 0xE0 == 11100000)



  • Genau so, wie der Erklaerer das erklaert, muste das machen!!! 😃

    1. Datei oefnen;
    2. solange (wiederholt) 1 Byte lesen
    3. Inhalt == 0xff ??? testen
    -- wenn ja
    -- -- noch ein Byte lesen
    -- -- ((Inhal & 0xe0)>0) testen //
    -- -- wenn ja : HEADER gefunden!!! (Die 2 letzten Bytegehoeren dazu!!!
    -- -- -- noch 2Byte lesen: (Die gefundenen 2 Byte + die 2 neu gelesenen
    -- -- -- sind der Header (Auswerteung haben wir schon gemacht!
    -- -- sonst :bei 2. weitermachen (wiederholt) //war nicht der Header
    -- sonst: bei 2. weitermachen (wiederholt) //war nicht der Header



  • nur am Rande: ich nannte mich "erkärer" nicht "Erklärer" 🙄



  • @DerAltenburger:
    Ok, das Prinzip habe ich verstanden.
    Jetzt muss ich den Code, den ich fürs erste Einlesen verwendet habe eigentlich nur noch ein bisschen abändern, denke ich.
    Könntest du mir erklären was in diesem Quellcode an den von mir markierten stellen genau passiert?

    for (int j=0;j<4;j++)    // 4Bytes sollen gelesen werden aber immer nur eines auf ein mal, right?
    {
        fread(&First4x8Bit,1,1,FilePointer );   // In First4x8Bit wird 1Byte eingelesen?
        for (int i=0 ; i<8 ; i++)        //Alle 8 Bits durchgehen
        {
            if ((First4x8Bit&(1<<i))>0)    // Hier blicke ich absolut nicht durch :(
                Bits[i + 24 - 8 * j] = 1;   // Hier auch nicht
            else
                Bits[i + 24 - 8 * j] = 0;   // Demzufolge auch hier nicht
        }
    }
    

    [ Dieser Beitrag wurde am 26.03.2003 um 21:26 Uhr von Peter Piksa editiert. ]



  • Original erstellt von Peter Piksa:
    **@DerAltenburger:
    Ok, das Prinzip habe ich verstanden.
    Jetzt muss ich den Code, den ich fürs erste Einlesen verwendet habe eigentlich nur noch ein bisschen abändern, denke ich.
    Könntest du mir erklären was in diesem Quellcode an den von mir markierten stellen genau passiert?

    for (int j=0;j<4;j++)    // 4Bytes sollen gelesen werden aber immer nur eines auf ein mal, right?
    {
        fread(&First4x8Bit,1,1,FilePointer );   // In First4x8Bit wird 1Byte eingelesen?
        for (int i=0 ; i<8 ; i++)        //Alle 8 Bits durchgehen
        {
            if ((First4x8Bit&(1<<i))>0)    // Hier wird Bit i gelesen
               Bits[i + 24 - 8 * j] = 1;   // Hier wird eine 1 in das Array geschrieben
            else
                Bits[i + 24 - 8 * j] = 0;   // Hier eine 0
        }
    }
    

    **



  • Hi Peter Piksa

    klar kann ich 😉

    1  for (int j=0;j<4;j++)    // 4Bytes sollen gelesen werden ..., right?
    2  {
    3    fread(&First4x8Bit,1,1,FilePointer );   // In First4x8Bit wird 1Byte...?
    4    for (int i=0 ; i<8 ; i++)        //Alle 8 Bits durchgehen
    5    {
    6       if ((First4x8Bit&(1<<i))>0)    // Hier blicke ich absolut nicht durch :(
    7            Bits[i + 24 - 8 * j] = 1;   // Hier auch nicht
    8        else
    9            Bits[i + 24 - 8 * j] = 0;   // Demzufolge auch hier nicht
    10   }
    11 }
    
    1. Zeile: 4 mal lesen (was auch immer); hier 4x1 Byte
    3. Zeile: 1 x 1 Byte lesen in Variable
    4. Zeile: Alle 4 Bit durchgehen
    6. Zeile: (1<<i) bedeutet 
                 Wert 1 um i Stellen (binaer) nach links schieben
                 entspricht i mal mit 2 multiplizieren
                 -> 1 2 4 8 16 .... = Wertigkeiten der Bits!!!
               First4x8Bit&(1<<i) bedeutet
                 Inhalt der Variablen binaer UND verknuepfen mit Wertigkeit
                 entspricht Maskierung des jeweiligen Bits
                 -> Wertigkeit des Bits oder 0
               d.h. Ergebnis ist >0, wenn Bit gesetzt, sonst null
    7. Zeile:  Bits[i + 24 - 8 * j] = 1;
               Bits[Index] ist ein Eintrag in den char-Vector (32+1 Byte)
               i ist der Bit- Zaehler
               j ist der Byte- Zaehler
               -> Bei 1. Byte: (j=0)
                  i=0 .. 7
                  Index = 24 .. 31
               -> Bei 2. Byte  (j=1)
                  Index = 16 .. 23
    
               -> Bei 4. Byte  (j=3)
                  Index = 0 .. 7
       -> dadurch werden die Bits in richtiger Reihe in Vektor gespeichert, fuer
          die Bytes aber jeweils anders 'rum!!!! (wie fuer Datei noetig)
    9. Zeile:  dito 
       ->in Zeile 7 / 9 wird jeweils '1' / '0' eingetragen (Bit gesetzt / nicht
    

    :: Ergebnis : Die Bytes werden 'in falscher' Folge bitweise aber jeweils richtiger Reihenfolge in Vektor gespeichert!

    :: Die Variable First4x8Bit braucht nur noch EIN BYTE (unsigned char)

    PS: Ich hoffe, das hilft!? 😉

    [ Dieser Beitrag wurde am 26.03.2003 um 22:01 Uhr von DerAltenburger editiert. ]



  • @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 dabei 😞

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



  • @entelechie

    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 richtig

    NICHT

    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 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*


Anmelden zum Antworten