Waermeleitpaste Geschrieben 17. August 2004 Geschrieben 17. August 2004 Also, ich versuche grade ein Programm zu schreiben, das MP3 Tags auslesen kann. Ich möchte nun die ID3-Daten am anfang der Dateien auslesen. Dazu schreibe ich den Anfang der Datei in einen String, z.B. char temp [ 255 ]. Nach den ersten 10 Bytes kommen endlich die Frames mit den Infos. Jeder Frame ist folgendermaßen aufgebaut: Frameheader: 4 Bytes Schlüsselbegriff 4 Bytes Framebodysize 2 Bytes Flags Framebody: Text Damit ich nun den Text im Framebody genau auslesen kann brauch ich die Framebodysize. Dummerweise ist die bei mir in Strings mit 4 Byte Länge ( z.B. char xyz [ 3 ] ) gespeichert. Wie krieg ich die in eine Integerzahl? Zitieren
need-some-blood Geschrieben 17. August 2004 Geschrieben 17. August 2004 Kopiere die 4 Byte in einen seperaten String und nutze dann atoi. int main(void) { int n; char *str = "12345.67"; n = atoi(str); printf("string = %s integer = %d\n", str, n); return 0 } Sollte eigentlich funzen. MVG need-some-blood Zitieren
Klotzkopp Geschrieben 17. August 2004 Geschrieben 17. August 2004 Ich glaube nicht, dass die Länge als Text im Header steht. Sehr wahrscheinlich ist sie binär. Da hilft atoi nicht weiter. Man braucht nur einen Zeiger auf den Anfang der Framebodysize, wandelt den in einen Zeiger auf einen 32-Bit-Ganzzahltyp um (je nach Plattform z.B. unsigned int) und dereferenziert diesen. Man muss aber auf Big-/Little-Endian-Konflikte achten. Zitieren
Waermeleitpaste Geschrieben 17. August 2004 Autor Geschrieben 17. August 2004 Also, ich hab die Daten ausgelesen und in char cache [ 255 ] gespeichert. Daraufhin eine schleife erzeugt, die nach bestimmten Buchstabenfolgen (den Schlüsselwörtern) sucht. Hier ein Ausschnitt: //beta ist der counter der Hauptschleife if ( cache [ beta ] == 'T' ) { if ( cache [ beta + 1 ] == 'A' ) { if ( cache [ beta + 2 ] == 'L' ) if ( cache [ beta + 3 ] == 'B' ) //Prüfe nach Album (TALB) { for ( int xy = 0; xy < 4; xy ++ ) aalbum [ xy ] = cache [ beta + 4 + xy ]; } //aalbum enthält die Längenangabe des Framebodys für das Album Wie transferiere ich in diesem Beispiel den Wert von aalbum in eine Integervariable? Diese brauche ich dann um die Werte von cache in einen String album [ bodysize ] zu packen. Zitieren
Klotzkopp Geschrieben 17. August 2004 Geschrieben 17. August 2004 unsigned int framebodysize = *(reinterpret_cast<unsigned int*>(aalbum)); Wie gesagt, falls sizeof(unsigned int) == 4, und die "Endianness" deines Rechers dieselbe ist wie im Header. Zitieren
Waermeleitpaste Geschrieben 17. August 2004 Autor Geschrieben 17. August 2004 Hmmmm, das liefert mir einen Wert von 301989888 statt den 18, die aalbum laut quickwatch hat. input.seekg ( ios::beg ); char cache [ 255 ]; memset ( &cache, 0, sizeof ( cache ) ); input.read ( cache, sizeof ( cache ) ); // ID3v2 Sizeinformationen über die Framebodies char aalbum [ 3 ], agenre [ 3 ], atitel [ 3 ], ainterpret [ 3 ], atrack [ 3 ], ajahr [ 3 ], akommentar [ 3 ]; //ID3v2 Framebodyinformationen char album [ 31 ], genre [ 31 ], titel [ 31 ], interpret [ 31 ], track [ 3 ], jahr [ 3 ], kommentar [ 31 ]; if ( ( cache [ 0 ] == 'I' ) && ( cache [ 1 ] == 'D' ) && ( cache [ 2 ] == '3' ) ) //Prüfe ob ID3-Tag vorhanden { for ( int beta = 10; beta < 250; beta ++ ) { if ( ( cache [ beta ] == 'T' ) && ( cache [ beta + 1 ] == 'A' ) && ( cache [ beta + 2 ] == 'L' ) && ( cache [ beta + 3 ] == 'B' ) ) //Prüfe nach Album { for ( int xy = 0; xy < 4; xy ++ ) aalbum [ xy ] = cache [ beta + 4 + xy ]; unsigned int n = * ( reinterpret_cast < unsigned int* > ( aalbum ) ); for ( unsigned int yx = 0; yx < n; yx ++ ) album [ yx ] = cache [ beta + 10 + yx ]; } Zitieren
Klotzkopp Geschrieben 17. August 2004 Geschrieben 17. August 2004 Hmmmm, das liefert mir einen Wert von 301989888 statt den 18, die aalbum laut quickwatch hat. Ich habe mal nachgesehen. Das Binärformat ist Big Endian (d.h. das höchstwertige Byte kommt zuerst), dann passt der Wert, denn dein Computer ist offenbar Little Endian: dez. 301989888 hex 12000000 dez. 18 hex 00000012 [/code] Du musst also die Reihenfolge der Bytes umdrehen: [CODE]unsigned int framebodysize = *(reinterpret_cast<unsigned int*>(aalbum)); char* p = reinterpret_cast<char*>(&framebodysize); std::swap(p[0], p[3]); std::swap(p[1], p[2]); Danach sollte in framebodysize der richtige Wert stehen. Alternativ könntest du auch die Funktion htonl benutzen, die sollte das gleiche machen. Das hier: if ( ( cache [ 0 ] == 'I' ) && ( cache [ 1 ] == 'D' ) && ( cache [ 2 ] == '3' ) ) kannst du übrigens einfacher so schreiben: if(0 == memcmp(&cache[0], "ID3", 3)) Zitieren
Goos Geschrieben 17. August 2004 Geschrieben 17. August 2004 Willst du es denn zu Uebungszwecken wirklich komplett selbst machen, oder kommt es dir eher auf das Ergebnis an? Es gibt eine nette Lib die einem schon einiges erleichtert. (Ok, es gibt noch viel mehr davon, aber diese hab ich mal verwendet) Goos Zitieren
Waermeleitpaste Geschrieben 17. August 2004 Autor Geschrieben 17. August 2004 C:\Arbeitsordner\c++\projects\Mp3Tag\mp3tag.cpp(128) : error C2653: 'std' : is not a class or namespace name Welchen header muss ich da laden? Zitieren
Waermeleitpaste Geschrieben 17. August 2004 Autor Geschrieben 17. August 2004 C:\Arbeitsordner\c++\projects\Mp3Tag\mp3tag.cpp(129) : error C2039: 'swap' : is not a member of 'std' *g* Benutze den Visual C++ 6.0 Compiler. Zitieren
Klotzkopp Geschrieben 17. August 2004 Geschrieben 17. August 2004 Lass mich raten: Visual C++ 6? #include <xutility> Oder einfach selbst machen:template <typename T> void swap(T& t1, T& t2) { T temp(t1); t1 = t2; t2 = temp; }[/CODE] Zitieren
Waermeleitpaste Geschrieben 17. August 2004 Autor Geschrieben 17. August 2004 Danke. ^^ Ich probiers weiter. Und versuche mal soweit wie möglich alles selbst zu machen. Soll ja eine Übung sein um mit C++ mal etwas vertrauter zu werden. Außerdem kann ich dieses C++-in-21-Tagen-Buch net mehr sehn. Zitieren
kLeiner_HobBes Geschrieben 19. August 2004 Geschrieben 19. August 2004 Soweit ich weiß, ist bei id3 die Länge aber nicht komplett in allen 8 Bits eines Bytes gespeichert, sondern nur in sieben davon, das MSB muß glaub ich Null sein, wenn ich mich richtig erinnere. Sonst mußt du in der ID3v2-Spezifikation nachschauen. Zitieren
nic_power Geschrieben 19. August 2004 Geschrieben 19. August 2004 Hallo, Frameheader: 4 Bytes Schlüsselbegriff 4 Bytes Framebodysize 2 Bytes Flags Framebody: Text Ich würde bei diesem Headeraufbau nicht über ein char-Array gehen, sondern eine Struktur verwenden: struct header { char key[4]; int size; short flags; } Den Header kannst Du dann problemlos in die Struktur einlesen. Nachdem Du die Größe des Bodies ermittelt hast, läßt sich der Body mit einem weiteren Funktionsaufruf einlesen. GGf. auf htonl() zurückgreifen. Diese Macros sind portable und damit auf jeder Plattform verfügbar. Nic Zitieren
Waermeleitpaste Geschrieben 24. August 2004 Autor Geschrieben 24. August 2004 Da ich Anfänger bin und bisher nur schulmäßig in Pascal programmiert hab sind mir Strukturen noch nicht ganz geheuer. *g* Ich schätze ich werd mir das zu Herzen nehmen wenn mein Programm das Betastadium verlässt. ^^ Zumal ich momentan noch bei den Grundlagen so meine Probleme habe. Zitieren
kLeiner_HobBes Geschrieben 24. August 2004 Geschrieben 24. August 2004 Du wirst dich halt später über diverse Redundanzen totärgern.. :-/ Zitieren
Waermeleitpaste Geschrieben 24. August 2004 Autor Geschrieben 24. August 2004 Ach was, totärgern gehört wohl nicht standardmäßig zum FIAE-Berufsalltag? :confused: Da bin ich hier wohl falsch gelandet ... Zitieren
need-some-blood Geschrieben 24. August 2004 Geschrieben 24. August 2004 Mach dir keine Panik wegen den Strukturen. Die sind halb so wild. google dich mal durch das netz. da wirst du viel zu finden. Ist gar net so schwer. MVG need-some-blood Zitieren
Waermeleitpaste Geschrieben 24. August 2004 Autor Geschrieben 24. August 2004 Kennt sich einer hier mit den MP3-Strukturen aus? Ich hab da ein Problem: Das Kommentarfeld, der Frame ist folgendermaßen aufgebaut: Frameheader: - 4 Bytes COMM - 4 Bytes Framebodysize - 2 Bytes Flags Framebody: - Kommentar Nun, normalerweise klappt das sehr gut mit dem auslesen der Infos. Aber leider hab ich festgestellt, dass Winamp manchmal einfach noch ein paar Bytes vor den eigentlichen Kommentar schiebt. Sprich ein leeres Byte und zwei Bytes mit Informationen. Diese haben glaub ich irgendwas mit dem Inhalt des Kommentars zu tun. Aber noch nicht herausgefunden, was da zugrunde liegt. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.