Binär-Daten einlesen



  • Hallo polofreak,

    also wenn ich das richtig verstanden habe, dann willst du eine wav-datei einlesen und die werte dann bearbeiten. (Info zum Aufbau einer Wav-datei:
    http://www.aculab.com/support/ting/an-wav.html)

    Also wenn du nur die Werte brauchst, dann würd ich die ersten 8192 Character aus der Datei erst mal nich einlesen. Soweit ich weiss, steht da nämlich lauter Header-Info drin, die Sampling-Rate, die Anzahl an Kanälen, usw.
    Die eigentlichen Daten dann in einen charbuffer einlesen. Und mit folgender Funktion bearbeiten:

    ......
    signed short
    ByteRangeToInt16
    (
       unsigned char* t_data,
       unsigned long t_offset
    )
    { 
       short res;
       res = t_data[ t_offset + 1 ];
       res = ( res<<8 );
       res += t_data[ t_offset ];
       return res;
    }
    

    Aufruf der Funktion erfolgt so:
    (tmpData ist der charbuffer)

    for( unsigned long i=0; i < m_Length; i++ )
             {
    				valData[i] = ByteRangeToInt16( tmpData, i*2)/32768.0;
             }
    

    So, ich hoffe, das hilft dir weiter.

    Gruß,
    Amalthea



  • virtuell Realisticer schrieb:

    Aehm...wie kommt ihr darauf, dass in der Datei die Daten in Binaer (01) stehen?

    Mir ist klar dass da keine 01 strings stehen nur wie bezeichnest du eben solche daten die in einer "binären datei" stehen ?
    Kurt



  • Hi! Sorry wenn ich jetzt hier herein platze, aber meine Frage passt hier gut rein und ich denke keiner würde es mögen wenn ich noch nen Thread dafür eröffne... 😉
    Also:
    Ich habe (wie auch in dem Listing in der oben geposteten FAQ, das wo ein struct "PERSON" binär gespeichert und gelesen wird (das Listing kompiliert übrigens unter Dev-CPP nicht, obwohl ich natürlich die Headers included habe...)) ein struct und eine write / read funtkion, sowie eine Funktion, die alles mit sauberen Werten initialisiert:

    struct A
    {
        int a;
        int b;
        std::string dummy;
    }
    
    void write(struct A *inst, std::string filename)
    {  
       std::fstream file(filename.c_str(), ios_base::out | ios::binary);
       if(!file)
          exit(0);
       file.write((const char*)&inst, sizeof(inst));
       //ich kann das & vor inst auch weglassen, ändert nichts
       file.close();
    }
    
    void read(struct A *read_to, std::string filename)
       std::fstream file(filename.c_str(), ios_base::in | ios::binary);
       if(!file)
          exit(0);
       file.read((char*)&read_to, sizeof(read_to));
       file.close();
    }
    
    void fill(struct A *fill)
    {
       fill->a = 0;
       fill->b = 0;
       fill->dummy = "";
    }
    

    Das wird folgendermaßen implementiert:

    //includes...
    int main()
    {
       A source;
       fill(&instance);
       B dest;
       fill(&dest);
    
       std::string filename = "my_file.x";
       write(&source, filename);
       read(&dest, filename);
    
       //ausgabe von dest...
    }
    

    Jetzt werden leider nur die Werte aus fill() ausgegeben... Was mache ich falsch? Würde mich sehr über Antworten freuen! 🙂

    btw: Ich hasse einfach binäre dateien^^



  • ZuK schrieb:

    virtuell Realisticer schrieb:

    Aehm...wie kommt ihr darauf, dass in der Datei die Daten in Binaer (01) stehen?

    Mir ist klar dass da keine 01 strings stehen nur wie bezeichnest du eben solche daten die in einer "binären datei" stehen ?
    Kurt

    Die Daten werden Byteweise gelesen, daran aendert sich nichts, wohl aber aendert sich die Art und Weise, wie spezielle Character interpretiert werden.

    mfg
    v R



  • some_binary_file schrieb:

    Hi! Sorry wenn ich jetzt hier herein platze, aber meine Frage passt hier gut rein und ich denke keiner würde es mögen wenn ich noch nen Thread dafür eröffne... 😉
    Also:
    Ich habe (wie auch in dem Listing in der oben geposteten FAQ, das wo ein struct "PERSON" binär gespeichert und gelesen wird (das Listing kompiliert übrigens unter Dev-CPP nicht, obwohl ich natürlich die Headers included habe...))

    Meine Glaskugel verweigert mir die Auskunft auf die Frage, was denn als
    Fehlermeldung ausgegeben wird.

    ein struct und eine write / read funtkion, sowie eine Funktion, die alles mit sauberen Werten initialisiert:

    struct A
    {
        int a;
        int b;
        std::string dummy;
    }
    
    void write(struct A *inst, std::string filename)
    {  
       std::fstream file(filename.c_str(), ios_base::out | ios::binary);
       if(!file)
          exit(0);
       file.write((const char*)&inst, sizeof(inst));
       //ich kann das & vor inst auch weglassen, ändert nichts
       file.close();
    }
    
    void read(struct A *read_to, std::string filename)
       std::fstream file(filename.c_str(), ios_base::in | ios::binary);
       if(!file)
          exit(0);
       file.read((char*)&read_to, sizeof(read_to));
       file.close();
    }
    
    void fill(struct A *fill)
    {
       fill->a = 0;
       fill->b = 0;
       fill->dummy = "";
    }
    

    Das wird folgendermaßen implementiert:

    //includes...
    int main()
    {
       A source;
       fill(&instance);
       B dest;
       fill(&dest);
    
       std::string filename = "my_file.x";
       write(&source, filename);
       read(&dest, filename);
    
       //ausgabe von dest...
    }
    

    Jetzt werden leider nur die Werte aus fill() ausgegeben... Was mache ich falsch?

    Der Dateizeiger zeigt auf das Ende der Datei, folglich kannst du den Inhalt
    der Datei nicht anzeigen, ohne den Dateizeiger zurueck auf den Anfang der
    Datei zu setzen.

    mfg
    v R



  • Zuerst mal danke für die Antwort! 🙂

    Der Dateizeiger zeigt auf das Ende der Datei, folglich kannst du den Inhalt
    der Datei nicht anzeigen, ohne den Dateizeiger zurueck auf den Anfang der
    Datei zu setzen.

    Wie meinst du das jetzt? Der Zeiger wird doch immer beim Schließen (file.close() in write) zurückgesetzt und sollte wieder auf den Anfang der Datei zeigen. Und die Daten werden ja in read() wieder direkt in ein struct eingelesen. Wozu brauche ich dann zum Anzeigen noch den Stream? Was hat das noch mit dem Zeiger zu tun? 😕
    Außerdem hab ich so was noch nie irgendwo gesehen...
    Und wie kann ich nochmal den Zeiger auf den Anfang setzten? mit file.seekdir(std::ios::beg)?



  • Nabend,

    ja, sorry, das ist mein Fehler. Hab nicht drauf geachtet, dass 'write' und
    'read' selbst implementierte Funktionen sind.

    Aber:

    A source;
    fill(&instance);
    B dest;
    fill(&dest);
    
    std::string filename = "my_file.x";
    write(&source, filename);
    read(&dest, filename);
    

    Ich nehme mal an, 'instance' sollte 'source' sein? In dem Falle schreibst du
    das in die Datei, womit 'source' durch Hilfe von 'fill' gefuellt worden ist.

    Im anderen Falle schreibst du irgendwas in die Datei.

    Hinzukommt, dass du ein std::string-Objekt nicht einfach abspeichern und
    wieder laden kannst. Du ueberschreibst dir dann das Objekt mit irgendwelchen
    Daten.

    Das Programm wird wahrscheinlich abstuertzen.

    mfg
    v R



  • Amalthea schrieb:

    ...

    ......
    signed short
    ByteRangeToInt16
    (
       unsigned char* t_data,
       unsigned long t_offset
    )
    { 
       short res;
       res = t_data[ t_offset + 1 ];
       res = ( res<<8 );
       res += t_data[ t_offset ];
       return res;
    }
    

    Aufruf der Funktion erfolgt so:
    (tmpData ist der charbuffer)

    for( unsigned long i=0; i < m_Length; i++ )
             {
    				valData[i] = ByteRangeToInt16( tmpData, i*2)/32768.0;
             }
    

    Kannst du mir das erklären? Ok du nimmst jetzt mal ein 16 Bit OK drum auch 1*2 als Offset auch noch OK aber wo kommt die 32768.0 her (wieso eigentlich ein float wert?) Gibt es dafür ne logische erklärung?



  • Polofreak schrieb:

    Kannst du mir das erklären? Ok du nimmst jetzt mal ein 16 Bit OK drum auch 1*2 als Offset auch noch OK aber wo kommt die 32768.0 her (wieso eigentlich ein float wert?) Gibt es dafür ne logische erklärung?

    32768 ist der maximale positive Wert, den ein short aufnehmen kann. Warum es eine
    Division mit einem Floatwert sein soll, kann ich dir auch nicht verraten.

    mfg
    v R



  • Ja, kann ich dir erklären.

    Hm, was ich gestern vergessen hatte zu schreiben: Das, was ich dir hier beschrieben habe, funktioniert deshalb, weil die wav-dateien die ich verwende immer aus zwei Bytes per Sample bestehen. Die Info bekommst du aus dem Header der wave-Datei. Deshalb werden hier auch immer zwei chars in einen Integer umgewandelt (-->zwei Bytes/Sample). Die 32768.0 deshalb, weil man damit die Werte auf einen Wertebereich von +/-1 normiert.

    Also res ist ein short (16Bit). Ein char hat 8Bit. In der Funktion ByteRangeToInt16 wird nun aus zwei char ein int16 gemacht. Und zwar wird zuerst der Teil aus t_data[ offset + 1] in res geschrieben. Nun sind also sozusagen von rechts angefangen 8 Stellen in res belegt. Mit dem Bitshift( <<) werden dann diese Bits, die gerade in res geschrieben wurden um 8 Stellen nach links verschoben. Anschließend wird dann t_data[ offset ] auf res aufaddiert. Nun sind alle stellen in res belegt und die zwei chars sind nun ein int16.

    Vorsicht, nicht 1*2 sondern i*2, da ja immer zwei chars umgewandelt werden und folglich auch immer entsprechend die Schrittweite angepasst werden muss.

    Wenn du ein Byte per Sample hast, brauchst du das natürlich nicht so kompliziert zu machen, dann kannst du ja einfach den char in einen int umwandeln.

    Gruß,
    Amalthea



  • Bei der Zuweisung fallen die Nachkommastellen weg.

    mfg
    v R



  • Genau und die braucht man ja bei nem Wertebereich zwischen -1 und +1. Sonst macht das ja keinen Sinn.

    Gruß,
    Amalthea



  • Amalthea schrieb:

    Genau und die braucht man ja bei nem Wertebereich zwischen -1 und +1. Sonst macht das ja keinen Sinn.

    Gruß,
    Amalthea

    Wenn du die Nachkommastellen benoetigst, dann musst du Modulo rechnen, nicht
    Division, oder ich hab grad ein Brett vorm Kopf ;).

    mfg
    v R



  • Ja ich nehm an bei mir bleibt es beim 8Bit 1 Kanal aber das muss ich nochmal klären! Ich hoffe nur dass ich es nicht für alle varianten machen muss mono stereo 8Bit 16Bit...

    damit die Werte auf einen Wertebereich von +/-1 normiert.

    Und wieso das? warum arbeite ich nicht einfach in unsigned long?

    Was hast du mit denen Wave files gemacht? Nicht zufällig Fourier-Transformation? 😉



  • doch, u. a. auch ;).

    Ich hatte ein Matlab-Programm als Vorlage, das ich in c++ umsetzen musste. Und in dem Programm ist's halt so, dass dort die Werte normiert werden. Um Vergleiche machen zu können, habe ich meine Werte eben auch normiert. Du kannst natürlich auch mit den nicht normierten Werten rechnen... Mir fällt jetzt gerade nichts ein, was dagegen spricht.

    Gruß,
    Amalthea



  • virtuell Realisticer schrieb:

    Wenn du die Nachkommastellen benoetigst, dann musst du Modulo rechnen, nicht
    Division, oder ich hab grad ein Brett vorm Kopf .
    v R

    Na ja, es funktioniert so wie ich das brauche.... es kommen die Werte raus, die ich brauche (zwischen -1 und +1 ).



  • darf ich fragen was du gerechnet hast?

    Ich will Wav-Files einlesen, um dann nach bestimmten FFTs DFTs etc. bestimmte Soundstrukturen erkennen zu können. Ich hab ein immer recht ähnliches Geräusch eines Motors. Jetzt soll ich erkennen ob er schleift, zu hoch dreht ...

    Hast du irgendetwas das mir dabei evtl behilflich sein könnte? 😃

    //Edit was ich noch vergessen hab hast du deine FFTS selbst gebastelt oder über ne LIB?



  • hm, nee, ich hab zwar auch fft und ifft gemacht, aber bei mir geht das in ne andere Richtung. Ich verändere das Signal nur, indem es sozusagen mit einem anderen überlagert wird. Für die fft hab ich vorerst mal das Beispiel aus nem Buch genommen, da werd ich mir aber noch was anderes überlegen müssen, da die höchstwahrscheinlich zu langsam ist.

    Weißt du schon, wie du die fft implementierst?

    Gruß,
    Amalthea



  • Ich wollte sie nur im Notfall selbst implementieren schau mal hier
    Überlagern kann man meines Wissens aber auch mittels Win32 API oder direct X da brauchste nicht selbst transformieren.

    wenn du willst können wir uns aber auch außerhalb dieses Threads darüber unterhaten. Wenn du willst mail mir an benjamin.stubbe@trw.com



  • pharmacy;


Anmelden zum Antworten