MP3 Header
-
Ich versuche den Header einer MP3 auszulesen.
Funktioniert auch schon ganz gut.Habe ein kleines Problem:
Eine MP3 besteht aus mehreren Frames, mit je einen Header.
Lese ich alle Header der MP3 und Werte diese aus, so kommen unterschiedliche
Ergebnisse bezüglich Bitrate und Samplingrate raus.Ist das normal?
Oder hab ich einen Bug im Code?
-
Nönö, das kann schon sein. mp3s können seit gerauner Zeit variable Codierungen. Aber was hat das mit ANSI-C zu tun?
-
ANSI C: Ich programmiers in C
Wie berechnet dann Beispielsweise iTunes die Bitrate?
Soll ich den Durchschnitt aller Bitraten ausrechnen?
-
Sisko86 schrieb:
ANSI C: Ich programmiers in C
ANSI-C ist ein Standard der Sprache, der systemunabhängig ist.
Und meines Wissens nach sind in diesen Standard keine
Bibliotheken zur MP3-Bearbeitung enthalten.
->Also kein ANSI-CAber könntest du mir vielleicht verraten, was für eine Bibliothek
und was für einen Compiler du nutzt?
-
Soll ich den Durchschnitt aller Bitraten ausrechnen?
Hammer Idee. Würd ich gleich umsetzten!!!
-
Bibliothek nur stdio.h
Programmieren in XCode -> Entwicklungsumgebung in Mac OSX, weiß nicht welcher Compiler da drin ist.Ist alles selbst geschrieben -> Betriebssystemunabhängig.
Das mit dem Durchschnitt mache ich auch.
-
Oh, du machst vom Grundsatz her selber ?!!
Dann hoffe ich, dass du mir meine "Anschuldigung" nicht böse nimmst!Wie genau realisierst du das dann?
Kannst du irgendwelche Websites empfehlen, auf denen so etwas gut dokumentiert ist,
oder wärst du sogar so frei Code zu posten?
-
Quelle hatte ich wikipedia, darin steht eine Tabelle wo was zu finden ist im Header.
Da ich alles von Grund auf mache, bin ich mir nicht sicher ob alles Fehlerfrei ist.
Uns so lese ich byte für byte aus:
#include <stdio.h> const char* id[4] = { "MPEG Version 2.5", "reserviert", "MPEG Version 2", "MPEG Version 1" }; const char* layer[4] = { "reserviert", "Layer III", "Layer II", "Layer I" }; const int bitrate[][5] = { /* *M: MPEG Version *L: Layer Version *M1L1 M1L2 M1L3 M2/2.4L1 M2/2.5L2/3 */ {999,999,999,999,999}, { 32, 32, 32, 32, 8}, { 64, 48, 40, 48, 16}, { 96, 56, 48, 56, 24}, {128, 64, 56, 64, 32}, {160, 80, 64, 80, 40}, {192, 96, 80, 96, 48}, {224,112, 96,112, 56}, {256,128,112,128, 64}, {288,160,128,144, 80}, {320,192,160,160, 96}, {352,224,192,176,112}, {384,256,224,192,128}, {416,320,256,224,144}, {448,384,320,256,160}, {999,999,999,999,999} }; const int id_layer_to_bitrate[][4] = { {-1,4,4,3}, {-1,-1,-1,-1}, {-1,4,4,3}, {-1,2,1,0} }; /* Returns the index of MPEG Version * needed for the sampling table */ const int id_to_mpeg[] = {2, -1, 1, 0}; const int sampling[][4] = { /* MPEG1 MPEG2 MPEG2.5*/ {44100, 48000, 32000}, {22050, 24000, 16000}, {11025, 12000, 8000}, {-1, -1, -1, -1} }; int main (int argc, const char * argv[]) { FILE* file; unsigned char byte = 0, tmp = 0; int b_id, b_layer, b_sampling; int rate = 0; int bitratecount = 0; int avg_bitrate = 0; file = fopen("/song.mp3", "rb"); if (file != NULL) { while (fread(&byte, sizeof(byte), 1, file)) { if (tmp == 255 && ((byte & 0xe0) == 0xe0)) { byte &= 0x1f; printf("--------- Sync - Header found ---------\n"); b_id = byte >> 3; printf("ID: %s\n", id[b_id]); byte &= 7; b_layer = byte >> 1; printf("Layer: %s\n", layer[b_layer]); // Read next Byte fread(&byte, sizeof(byte), 1, file); b_sampling = (byte & 0xf) >> 2; printf("Samplingfrequenz: %dHz\n", sampling[b_sampling][id_to_mpeg[b_id]]); byte = byte >> 4; rate = bitrate[byte][id_layer_to_bitrate[b_id][b_layer]]; if (rate != 999) { avg_bitrate += rate; bitratecount++; } printf("Bitrate: %d kbps\n", rate); tmp = 0; } tmp = byte; } printf("Durchschnittliche Bitrate: %d kbps\n", avg_bitrate / bitratecount); } else { printf("Datei nicht gefunden"); return 1; } return 0; }
Für Codeerklärungen einfach melden, habe den Quelltext leider noch nicht so gut dokumentiert.
-
Kurze Erläuterung:
1. Suche nach dem ersten vorkommen nach 11 Bits, die hintereinander mit 1 belegt sind. Dies zeigt mir, dass der Header beginnt.
tmp == 255 && ((byte & 0xe0) == 0xe0)
tmp muss 11111111 und byte muss 111xxxxx sein
2. Nächsten zwei Bits sind die ID also die MPEG Version (siehe ID Tabelle)
3. Nächsten zwei Bits ist der Wert des Layer (siehe Layer Tabelle)
4. Nächstes Byte auslesen, darin steht in den ersten 4 Bits die Bitraten ID
-
Cool! Danke.
Werd ich mir die Tage mal angucken.
-
Und deine Frage war noch einmal... ?
-
Meine Frage war, ob es normal ist, dass die Bitrate der einzelnen Header variiert.
Habe schon mehrere MP3 getestet, eine konstante Bitrate hab ich noch nicht gefunden.
-
Ganz alte mp3s sollten konstante Bitraten haben. Ich kenne das nur von den Encodern, wo irgendwann einmal Optionen für variable Raten aufgetaucht sind. Die sind mittlerweile fast überall voreingestellt.
-
OK, dann gehe ich mal davon aus, dass mein Programm funktioniert.
Danke.
-
Ich hab noch kurz meinen lame-encoder angeschaut. Da steht folgendes in der Hilfe:
--abr n average bitrate encoding
Turns on encoding with a targeted average bitrate of n kbits, allowing to use frames of different sizes. The allowed range of n is 8-310, you can use any integer value within that range.
It can be combined with the -b and -B switches like:
lame --abr 123 -b 64 -B 192 a.wav a.mp3
which would limit the allowed frame sizes between 64 and 192 kbits.* --cbr enforce use of constant bitrate
This switch enforces the use of constant bitrate encoding.
Da dürfte ich also recht haben.