Mp3-Header auslesen (nicht die TAGS!)



  • Hi @ all

    Weiß jemand vielleicht wie ich die 32-Bits einer Mp3 Datei auslesen kann?

    Ich möchte die Bitrate, Copyright-Schutz, Frquenz, etc herausfinden, die als durch Bitcodierung in den ersten 32 Bits abgelegt wurden. Ich hab es bereits mir Filestreams und dem binären auslesen versucht, aber irgend wie unterscheiden sich meine Ergebnisse immer von anderen (zB: WindowsMediaPlayer)

    Wär cool wenn ihr mir helfen könntet 🙂

    ALSO hier mein Ansatz:

    #include <iostream>
    #include <fstream>
    #include <ShlWApi.h>
    
    #pragma comment (lib, "Shlwapi.lib")
    using namespace std;
    
    /***************************************************/
    
    // -----------------------------------------------
    // speichert die ausgelesenen Bits aus dem Header
    //
    typedef struct tagMP3COREHEADER
    {
    	union
    	{
    		struct
    		{
    			unsigned int Byte4: 8;
    			unsigned int Byte3: 8;
    			unsigned int Byte2: 8;
    			unsigned int Byte1: 8;
    
    		}BitInfo;
    
    		struct
    		{
    			unsigned int Emphasis		:  2;
    			unsigned int OriginalHome	:  1;
    			unsigned int Copyright		:  1;
    			unsigned int ModeExtension	:  2;
    			unsigned int Mode		:  2;
    			unsigned int PrivateBit		:  1;
    			unsigned int PaddingBit		:  1;
    			unsigned int SampleFrequence	:  2;
    			unsigned int Bitrate		:  4;
    			unsigned int ProtectionBit	:  1;
    			unsigned int MPEGLayer		:  2;
    			unsigned int MPEGVersion	:  1;
    			unsigned int SyncWord		: 12;
    
    		}CoreInfo;
    
    	}Mp3Info;
    
    } MP3COREHEADER, *PMP3COREHEADER;
    
    /***************************************************/
    
    #define MP3_HEADER_SIZE		(4)
    
    int main()
    {
    	char szInputBuffer[MAX_PATH + 64];	
    
    	cout << "Geben Sie den Dateipfad an: " << endl;
    	cin.getline(szInputBuffer, MAX_PATH + 64);
    	// gültiger Pfad ?
    	if(PathFileExists(szInputBuffer))
    	{
    		cout << "Mp3-Datei gefunden..." << endl;
    
    		// Datei im Binärmodus öffnen
    		ifstream isFileStream(szInputBuffer, ios::in | ios::binary);
    		if(!isFileStream)
    		{
    			cerr << "Fehler beim Initialisieren der Datei in den File-Stream..." << endl;
    			return (-1);
    		}
    
    		// Leseposition (get-Zeiger) an den Anfang
    		if(isFileStream.seekg(0))
    			cout << "Lese-Position an den Anfang gesetzt..."
    			     << endl<< endl;
    
    		cout << "Analysie des Mp3-Headers:" << endl << endl;
    
    		// ersten 4 Bytes in die Struktur lesen
    		MP3COREHEADER mp3core;
    		isFileStream.read((char*)&mp3core.Mp3Info.BitInfo,                           
                                      MP3_HEADER_SIZE);    
    
    		// da in der Struktur 2 Unions definiert sind (also gemeinsame     
                    // Speicherplatznutzung) kann über die zweite Teilstruktur
    		// zugegriffen werden
    		cout << "MPEGVersion:\t\t"
                         << mp3core.Mp3Info.CoreInfo.MPEGVersion << endl;
    		cout << "MPEGLayer:\t\t"
                         << mp3core.Mp3Info.CoreInfo.MPEGLayer << endl;
    		cout << "Bitrate:\t\t"
                         << mp3core.Mp3Info.CoreInfo.Bitrate << endl;
    		cout << "Copyright:\t\t"
                         << mp3core.Mp3Info.CoreInfo.Copyright << endl;
    		cout << "Emphasis:\t\t"
                         << mp3core.Mp3Info.CoreInfo.Emphasis << endl;
    		cout << "Mode:\t\t\t"
                         << mp3core.Mp3Info.CoreInfo.Mode << endl;
    		cout << "ModeExtension:\t\t"
    		     << mp3core.Mp3Info.CoreInfo.ModeExtension << endl;	
    		cout << "OriginalHome:\t\t"
                         << mp3core.Mp3Info.CoreInfo.OriginalHome << endl;
    		cout << "PaddingBit:\t\t"
                         << mp3core.Mp3Info.CoreInfo.PaddingBit << endl;
                    cout << "PrivateBit:\t\t"
                         << mp3core.Mp3Info.CoreInfo.PrivateBit << endl;
    		cout << "ProtectionBit:\t\t"
                         << mp3core.Mp3Info.CoreInfo.ProtectionBit << endl;
    		cout << "SampleFrequence:\t"
                         << mp3core.Mp3Info.CoreInfo.SampleFrequence << endl;
    		cout << "SyncWord:\t\t"
                         << mp3core.Mp3Info.CoreInfo.SyncWord << endl;
    
    		cout << "\n\n\n\n";
    	}
    	return (0);
    }
    

    Nochwas zum Code:
    Alle ausgegebenen Ergebnisse sollen lediglich Index-Werte sein.
    Die Bedeutung findest man beispielsweise hier:
    [url]
    http://193.23.168.186/pc_pool/lernmodule/multimediadateien/Kapitel32.htm
    [/url]



  • mp3 is nen streaming format. die header stehen nicht zwangsläufig am anfang der datei, sondern zu anfang jedes blocks. du musst also erstmal das file von anfang durchlaufen, bis du nen gültigen header gefunden hast.



  • ersmal danke für deine Antwort,

    Woher weißt ich an welcher Stelle ein (gültiger) Header steht ?

    (Auslesen dann wie in meinem geposteten Code ?)

    danke für weitere Hilfe 🙂



  • das ist ne berechtigte frage 😉

    du kannst davon ausgehen, dass das erste bit des headers immer gesetzt sein wird. "SyncWord" wird also bei nem gültigen header größergleich 0x400 sein.

    zusätzlich vielleicht mal paar andere bits angucken. "Bitrate" sollte z.b. kleiner als 0xff sein, da dieser wert reserviert ist.

    blockweise durchlaufen kannst du die datei ungefähr so:

    int pos = 0;
    isFileStream.seekg(0);
    do
    {
     isFileStream.read((char*)&mp3core.Mp3Info.BitInfo, MP3_HEADER_SIZE);
     isFileStream.seekg(pos);
     ++pos;
    }
    while(!isValidHeader(mp3core)) // boole'sche funktion, die den header auf gültigkeit prüft
    

    achtung: dabei kann das ende der datei erreicht werden. ne sinnvolle überprüfung auf eof() einschieben.

    was mir an deinem code grad auffällt, wieso sind die bytes und header infos alle rückwärts deklariert? müsste eigentlich andersrum sein.

    [hier war ne längere pause, in der der autor sich gedacht hat, er implementiere son reader mal eben fix]

    mein beispielprogramm liefert auch nur müll 😉 die meisten meiner mp3s entsprechen offenbar "MPEG 2.5". für manche stimmt die bitrate, für manche nicht... komische sache. das syncword war auch völlig unterschiedlich gesetzt...

    ich häng mal meinen code ran, vielleicht hilft er dir weiter.

    #include <iostream>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    union MP3Header
    {
        char bytes[4];
        struct
        {
            unsigned Syncword : 11;
            unsigned FuzzyBit : 1;
            unsigned MPEGVersion : 1;
            unsigned MPEGLayer : 2;
            unsigned ProtectionBit : 1;
            unsigned Bitrate : 4;
            unsigned SamplingFrequency : 2;
            unsigned Padding : 1;
            unsigned Private : 1;
            unsigned Mode : 2;
            unsigned ModeExtension : 2;
            unsigned Copyright : 1;
            unsigned OriginalHome : 1;
            unsigned Emphasis : 2;
        } InfoBits;
    };
    
    bool validHeader(MP3Header &header)
    {
        return header.InfoBits.Syncword > 0x400 &&
               header.InfoBits.Bitrate && header.InfoBits.Bitrate < 0xff &&
               header.InfoBits.SamplingFrequency < 0x4;
    }
    
    int main(int argc, char *argv[])
    {    
        string file = "foo.mp3";
    
        ifstream fs(file.c_str(), ios::binary);
    
        if(!fs) return 1;
    
        int pos = 0;    
        fs.seekg(pos);
        MP3Header header;
    
        do
        {
            fs.read(header.bytes, 4); // error prone!
            ++pos;
            fs.seekg(pos);
        }
        while(!fs.eof() && !validHeader(header));
    
        fs.close();
    
        if(!validHeader(header))
        {
            cerr << "invalid header" << endl;
            return 1;
        }
    
        cout << "found header at block " << pos - 1 << endl;
    
        cout << file << endl;
    
        if(!header.InfoBits.FuzzyBit)
            cout << "MPEG 2.5" << endl;
        else    
            switch(header.InfoBits.MPEGVersion)
            {
                case 0 : cout << "MPEG 2" << endl; break;
                case 1 : cout << "MPEG 1" << endl; break;
            }
    
        cout << "MPEG Layer " << (4 - header.InfoBits.MPEGLayer) << endl;
    
        cout << header.InfoBits.Bitrate << endl;
    
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    


  • hi hi,

    hab dein proggy mal ausprobiert und festgestellt, das der einen gültigen Header-Block immer bei 0 findet also am anfang :p , ich hab auf vielen seiten schon gelesen, dass am anfang immer der Header steht.... 😕 😕

    Dann mal ne Frage:

    unsigned Syncword       : 11;
        unsigned FuzzyBit       : 1;
        unsigned MPEGVersion    : 1;
    

    Wieso hast du denn da ein FuzzyBit eingebaut, bzw den SyncWord auf 11 gekürzt ?
    ->>

    Syncword (12 Bit)
    Diese 12 Bits werden zur Synchronisierung verwendet und meist auf 0xFFF gesetzt. Beim Betrachten unterschiedlicher MP3 Dateien erkennt man aber auch Abweichungen von diesem Standardwert.

    auf http://193.23.168.186/pc_pool/lernmodule/multimediadateien/Kapitel32.htm

    Ach ja, hab noch ne 'andere' Idee: 💡
    Wenn wir über ne funktionierende Funktion 🤡 auf die Bits der Datei direkt zugreifen könnten, kann man doch (mal von einem gültigem Header ausgehen 😉 ) die Bitsets direkt untersuchen oder ? ... Habs nur noch nit aufe Reihe bekommen mir son Ding zu schreiben... 😞

    Zählt man eigentlich das 0.te Bit schon mit oder beginnt man bei 1 an zu zählen ?

    danke nochmal für dein Posting 👍



  • das fuzzy bit ist für mpeg 2.5. drei formate lassen sich mit einem bit für "MPEGVersion" halt nicht abdecken, also haben sich paar leute ausgedacht, dass sie dafür einfach das letzte bit vom SyncFrame (bzw. Syncword) nehmen. ist das auf 0 gesetzt, so hat man es mit mpeg 2.5 zu tun. deshalb "fuzzy" bit, weils am standard vorbei ist.

    dass die header meist am anfang der datei gefunden werden liegt daran, dass man es meist nur mit "intakten" mp3 files zu tun hat. hatte da zuerst den fehler vermutet, aber offensichtlich liegt er doch woanders. möglicherweise einfach daran, dass sich so gut wie niemand an den standard hält.

    rein theoretisch kannst du an den anfang ner mp3 datei ne menge bullshit schreiben und das ganze funzt trotzdem noch, da player sich erstmal den ersten gültigen block (frame) suchen und ab da spielen.

    rührt, wie erwähnt, vom streaming her. wenn man sich in so einen mp3 stream einklingt, dann fängt der halt irgendwo an und nicht direkt mit nem gültigen frame.

    was du mal machen kannst, um deinen code generell auf gültigkeit zu überprüfen, ist eigentlich ganz einfach.
    schnapp dir nen hex-editor und bastel dir nen gültigen mp3 header zusammen, speicher das ganze und jag es durch dein programm 😉



  • der Titel sagt alles .... 🙂 ....wenn ich das mal irg wann raus hab...willse dann ne Funktion haben ? 😉



  • ich komm mir grad bisschen blöd vor *G

    das problem ist die endianess 😉 windows systeme arbeiten mit little endian. hab mich durch die verwendung von union wohl blenden lassen 😉

    also: stell dir vor dein header sieht so aus: 0xFFF0ABFD

    eigentlich erwartet man, dass dann das syncword 0xFFF entspricht. tut es aber nicht, da durch die little endian interpretation die bytes blockweise "vertauscht" werden. ein block entspricht dabei 8 bit und das höchstwertige steht dabei ganz rechts. das syncword wird also mit 0x0FF belegt.

    anderes beispiel, das es vielleicht klarer macht:

    0xABCD wird in 16 bit word geschaufelt -> word == 0xCDAB

    hätte mir eigentlich sofort auffallen sollen, als ich deine umgedrehten member gesehen hab ^^ das umdrehen allein reicht nicht wegen der blockweisen vertauschung



  • Gut wenn das :

    hätte mir eigentlich sofort auffallen sollen, als ich deine umgedrehten member gesehen hab ^^ das umdrehen allein reicht nicht wegen der blockweisen vertauschung

    'nicht reicht' ^^; was kann ich dann machen um den Schmand aufe Reihe zu bekommen ...irgend wie muss das doch gehen 😡



  • ich hab noch einen funktionierenden VB-Code der genau diesen Kack macht, das problem is nur, das ich kein bisschen VB kann... der is auch gar nit so lang...soll ich den mal posten ? 🙄



  • CodeFinder schrieb:

    Gut wenn das :

    hätte mir eigentlich sofort auffallen sollen, als ich deine umgedrehten member gesehen hab ^^ das umdrehen allein reicht nicht wegen der blockweisen vertauschung

    'nicht reicht' ^^; was kann ich dann machen um den Schmand aufe Reihe zu bekommen ...irgend wie muss das doch gehen 😡

    indem du auf diesen union krams verzichtest und z.b. nen bitset verwendest.

    #include <bitset>
    // filestream fs öffnen etc. pp
    unsigned char bytes[4];
    fs.read((char*)bytes, 4);
    // char bytes von hand in nen long schieben
    unsigned long longbytes = 0;
    for(int i = 0; i < 3; ++i)
    {
     longbytes += bytes[i];
     longbytes <<= 8;
    }
    longbytes += bytes[3];
    std::bitset<32> bits(longbytes); // erzeugt ein bitset von long
    

    und _der_ header ist dann tatsächlich umgedreht 😉 syncframe is also auf bits 31-21 (bits[31] bis bits[21]).



  • muhaha, ok danke nochmal für deine Antwort, ich bin schon weiter...wenn ich ne Fkt fertig hab werde ich die mal posten 😉



  • Also habs jetzt raus, kannst den Code ja mal ausprobieren, bei mir funzt der einwandfrei, is n bissl anders gelößt; aber er läuft und der Rest is mir wurscht
    (ich weiß n bissl unschön: C und C++ gemixt aber egal 🤡 )

    ⚠ ACHTUNG: das ist nur eine Funktion, kein ganzes Proggy 😉

    #include <iostream>
    #include <fstream>
    using namespace std;
    
    /***************************************************/
    
    // ASC - Audio Sound Channel
    #define ASC_UNKNOWN		(0x00)
    #define ASC_STEREO		(0x01)
    #define ASC_JOINT_STEREO	(0x02)
    #define ASC_DUAL_CHANNEL	(0x03)
    #define ASC_SINGLE_CHANNEL	(0x04)
    
    // EMPHASIS Modes
    #define EMPHASIS_UNKNOWN	(0x00)
    #define EMPHASIS_NONE		(0x01)
    #define EMPHASIS_50_15_MS	(0x02)
    #define EMPHASIS_CCITT_J_17	(0x03)
    
    typedef struct tagMP3COREHEADER // mp3core
    {	
    	long	lFileSize;		/* Bytes    */
    	long	lFirstFrameOffset;	/* Bytes    */
    	long	lTotalFrames;		/* Frames   */
    	long	lTrackLength;		/* Sekunden */
    	long	lBitrate;		/* kBit/s   */
    	long	lFrequence;		/* Hz       */
    	long	lMPEGVersion;
    	long	lMPEGLayer;
    	bool	fCRCProtected;
    	bool	fPadding;
    	bool	fPrivate;
    	bool	fCopyright;
    	bool	fOriginal;
    	bool	fErrorAppeared;
    	UINT	uiEmphasis;
    	UINT	uiSoundMode;
    
    } MP3COREHEADER, *PMP3COREHEADER/*, NEAR *NPMP3COREHEADER, FAR *LPMP3COREHEADER*/;
    
    bool GetMp3HeaderInformation(const PSTR pszFilepath, PMP3COREHEADER pMp3CoreHeader)
    {
    	// => Parameter überprüfen
    	if(pszFilepath == NULL || pMp3CoreHeader == NULL)
    		return (false);
    
    	// => Lokale Variablen
    	FILE	*pfMp3File;
    	int		iCharCode;
    	bool	fStatusFlag = false;
    
    	// => noch keine Fehler aufgetreten
    	pMp3CoreHeader->fErrorAppeared = false;
    
    	// => Datei öffnen
    	pfMp3File = fopen(pszFilepath, TEXT("rb"));
    	if(pfMp3File == NULL)
    	{
    		pMp3CoreHeader->fErrorAppeared = true;
    		return (false);
    	}
    
        // => Dateigröße bestimmen:
    	std::ifstream ifsMp3File(pszFilepath, std::ios::binary);
    	if(!ifsMp3File)
    
    		return (false);
    	ifsMp3File.seekg(0, std::ios::end);
    	pMp3CoreHeader->lFileSize = (long)ifsMp3File.tellg();
    	ifsMp3File.close();
    
    	// => Ersten Frame des MPEG 1 Layer III suchen
        do
    	{
    		iCharCode = fgetc(pfMp3File);
    		if(iCharCode == 255)
    		{
    			iCharCode = fgetc(pfMp3File);
    			if(tolower(iCharCode / 16) == 15)
    				fStatusFlag = true;
    
    		}
    	}
    	while(!fStatusFlag);
    
    	// => Den ersten Frame Header ermitteln
    	fpos_t fpMp3FilePos;
        fgetpos(pfMp3File, &fpMp3FilePos);
    	fpMp3FilePos -= 2;
        pMp3CoreHeader->lFirstFrameByteOffset = fpMp3FilePos;
    
    	// => MPEG Version ermitteln (1/2)
    	int iMPEGVersion = tolower(((iCharCode % 16) / 4) / 2);
    	switch(iMPEGVersion)
    	{
    		case 0:
    			pMp3CoreHeader->lMPEGVersion = 2L; // MPEG-2
    			break;
    		case 1:
    			pMp3CoreHeader->lMPEGVersion = 1L; // MPEG-1
    			break;
    		default:
    			pMp3CoreHeader->fErrorAppeared = true; // Unknown
    			break;
    	}
    
        // => MPEG Layer ermitteln
    	int iMPEGLayer = tolower((((iCharCode % 16) / 4) % 2) * 2 + (((iCharCode % 16) % 4) / 2));
    	switch(iMPEGLayer)
    	{
    		case 0:
    			pMp3CoreHeader->lMPEGLayer = 0; // Reserved
    			break;
    		case 1:
    			pMp3CoreHeader->lMPEGLayer = 3; // Layer III
    			break;
    		case 2:
    			pMp3CoreHeader->lMPEGLayer = 2; // Layer II
    			break;
    		case 3:
    			pMp3CoreHeader->lMPEGLayer = 1; // Layer I
    			break;
    		default:
    			pMp3CoreHeader->fErrorAppeared = true; // Unknown
    			break;
    	}
    
    	if(iMPEGLayer != 1)
    		return (true);
    
        // => CRC-Protection ermitteln
    	int iProtectionBit = tolower(((iCharCode % 16) % 4) % 2);
    	switch(iProtectionBit)
    	{
    		case 1:
    			pMp3CoreHeader->fCRCProtected = false; // CRC-Protection: No
    			break;
    		case 0:
    			pMp3CoreHeader->fCRCProtected = true; // CRC-Protection: Yes
    			break;
    		default:
    			pMp3CoreHeader->fErrorAppeared = true; // Unknown
    			break;
    	}
    
    	// => Das nächste Byte einlesen, um das 3. des Frame-Headers zu analysieren
    	iCharCode = fgetc(pfMp3File);
    
    	// => Bitrate ermitteln
    	int iBitrateTable[2][16] =
    	{
    		0x000,0x008,0x010,0x018,
    		0x020,0x040,0x050,0x038,
    		0x040,0x080,0x0A0,0x070,
    		0x080,0x100,0x140,0x000,
    		0x000,0x020,0x028,0x030,
    		0x038,0x040,0x050,0x060,
    		0x070,0x080,0x0A0,0x0C0,
    		0x0E0,0x100,0x140,0x000
    	};
    	pMp3CoreHeader->lBitrate = iBitrateTable[iMPEGVersion][(tolower(iCharCode / 16))]; // in Kbps
    
    	// => Frequenz ermitteln
    	long lFrequencyTable[2][4] =
    	{
    		0x05622,0x05DC0,0x03E80,0x00000,
    		0x0AC44,0x0BB80,0x07D00,0x00000
    	};
    	pMp3CoreHeader->lFrequence = lFrequencyTable[pMp3CoreHeader->lMPEGVersion][(tolower((iCharCode % 16) / 4))]; // in Hz    
    
    	// => Padding ermitteln
    	int iPaddingBit = tolower(((iCharCode % 16) % 4) / 2);
    	switch(iPaddingBit)
    	{
    		case 0:
    			pMp3CoreHeader->fPadding = false; // Padding: No
    			break;
    		case 1:
    			pMp3CoreHeader->fPadding = true; // Padding: Yes
    			break;
    		default:
    			pMp3CoreHeader->fErrorAppeared = true; // Unknown
    			break;
    	}
    
    	// => Private Bit ermitteln
        int iPrivateBit = tolower(((iCharCode % 16) % 4) % 2);
    	switch(iPrivateBit)
    	{
    		case 0:
    			pMp3CoreHeader->fPrivate = false; // Private: No
    			break;
    		case 1:
    			pMp3CoreHeader->fPrivate = true; // Private: Yes
    			break;
    		default:
    			pMp3CoreHeader->fErrorAppeared = true; // Unknown
    			break;
    	}
    
    	// => Das nächste Byte einlesen, um das 4. des Frame-Headers zu analysieren
        iCharCode = fgetc(pfMp3File);
    
    	// Sound Channel ermitteln
        int iChannelMode = tolower((iCharCode / 16) / 4);
    	switch(iChannelMode)
    	{
    		case 0:
    			pMp3CoreHeader->uiSoundMode = ASC_STEREO; // Stereo
    			break;
    		case 1:
    			pMp3CoreHeader->uiSoundMode = ASC_JOINT_STEREO; // Joint Stereo
    			break;
    		case 2:
    			pMp3CoreHeader->uiSoundMode = ASC_DUAL_CHANNEL; // Dual Channel
    			break;
    		case 3:
    			pMp3CoreHeader->uiSoundMode = ASC_SINGLE_CHANNEL; // Single Channel
    			break;
    		default:
    			pMp3CoreHeader->uiSoundMode = ASC_UNKNOWN; // Unknown
    			pMp3CoreHeader->fErrorAppeared = true;
    			break;
    	}
    
    	// => Copyright ermitteln
    	int iCopyrightBit = tolower(((iCharCode % 16) / 4) / 2);
    	switch(iCopyrightBit)
    	{
    		case 0:
    			pMp3CoreHeader->fCopyright = false; // Copyrighted: No
    			break;
    		case 1:
    			pMp3CoreHeader->fCopyright = true; // Copyrighted: Yes
    			break;
    		default:
    			pMp3CoreHeader->fErrorAppeared = true; // Unknown
    			break;
    	}
    
    	// => Originale Mp3 Datei
    	int iOriginalBit = tolower(((iCharCode % 16) / 4) % 2);
    	switch(iOriginalBit)
    	{
    		case 0:
    			pMp3CoreHeader->fOriginal = false; // Original: No
    			break;
    		case 1:
    			pMp3CoreHeader->fOriginal = true; // Original: Yes
    			break;
    		default:
    			pMp3CoreHeader->fErrorAppeared = true; // Unknown
    			break;
    	}
    
    	// => Emphasis ermitteln
    	int iEmphasis = tolower((iCharCode % 16) % 4);
    	switch(iEmphasis)
    	{
    		case 0:
    			pMp3CoreHeader->uiEmphasis = EMPHASIS_NONE; // Emphasis: None
    			break;
    		case 1:
    			pMp3CoreHeader->uiEmphasis = EMPHASIS_50_15_MS; // Emphasis: 50/15 ms
    			break;
    		case 3:
    			pMp3CoreHeader->uiEmphasis = EMPHASIS_CCITT_J_17; // Emphasis: CCITT J.17
    			break;
    		default:
    			pMp3CoreHeader->uiEmphasis = EMPHASIS_UNKNOWN; // Unknown
    			pMp3CoreHeader->fErrorAppeared = true;
    			break;
    	}
    
    	// => Frame-Size berechnen
    	long lFrameSize = (144000 * pMp3CoreHeader->lBitrate / pMp3CoreHeader->lFrequence) + iPaddingBit;
    
    	// => Anzahl der Frames
    	pMp3CoreHeader->lTotalFrames = (pMp3CoreHeader->lFileSize - pMp3CoreHeader->lFirstFrameByteOffset) / lFrameSize;
    
    	// => Track Länge in Sekunden
    	pMp3CoreHeader->lTrackLength = toupper(pMp3CoreHeader->lTotalFrames * 26 / 1000);
    
    	// => Datei Handle wieder schließen
    	fclose(pfMp3File);
    
    	return (!pMp3CoreHeader->fErrorAppeared);
    }
    
    /***************************************************/
    

    PS: Hab das ganze jetzt mal mit Flags gelößt; Also Emphasis und Sound-Modi, dann is das ganze n bissl universeller 😉

    hmm vll. was für die FAQ ? 😕



  • Hab noch 2 kleine Bugs gefunden:

    Das...

    // => Dateigröße bestimmen:
        std::ifstream ifsMp3File(pszFilepath, std::ios::binary);
        if(!ifsMp3File)
            return (false);
        ifsMp3File.seekg(0, std::ios::end);
        pMp3CoreHeader->lFileSize = (long)ifsMp3File.tellg();
        ifsMp3File.close();
    

    wird zu...

    // => Dateigröße bestimmen:
        std::ifstream ifsMp3File(pszFilepath, std::ios::binary);
        if(!ifsMp3File)
        {
            fclose(pfMp3File);
            return (false);
        }
        ifsMp3File.seekg(0, std::ios::end);
        pMp3CoreHeader->lFileSize = (long)ifsMp3File.tellg();
        ifsMp3File.close();
    

    -------------------------------------

    Das...

    if(iMPEGLayer != 1)
            return (true);
    

    wird zu...

    if(iMPEGLayer != 1)
        {
            fclose(pfMp3File);
            return (true); 
        }
    

    Bitte vielmals um Entschuldigung 🤡



  • öhm kann das sein dass du irgendwelche eigenen typen verwendet hast?

    bekomme ne tonne fehler!

    UINT = unsigned int? (UINT uiEmphasis;)

    PSTR = ? (const PSTR pszFilepath)

    und dann gibts ne tonne weiterer fehler. ein paar davon kommen sicher von dem hier, habe aber nicht alle angeschaut.



  • UINT und PSTR sind afaik WinAPI-typedefs für unsigned int bzw. char*.



  • soweit binich mittlerweile auch gekommen leider bekomm ich n crash wenn ich da stattdessen einfach unsigned int und char * schreibe.

    habe diese typedefs ausserdem in der winnt.h gefunden.

    da drin steht auch wo was von TEXT("rb"), sehe aber den sinn davon nicht.

    das TEXT... habich auch weggelassen und einfach "rb" geschrieben.

    die winnt.h kannich nicht inkludieren weil 1. muss das unter linux und windows funzen und 2. kommt dann noch n neuer fehler.

    schaut bei mir jetzt so aus:

    *.h:

    #pragma once
    #ifndef MP3_HEADER
    #define MP3_HEADER
    
    #include <iostream> 
    #include <fstream> 
    using namespace std; 
    
    /***************************************************/ 
    
    // ASC - Audio Sound Channel 
    #define ASC_UNKNOWN        (0x00) 
    #define ASC_STEREO        (0x01) 
    #define ASC_JOINT_STEREO    (0x02) 
    #define ASC_DUAL_CHANNEL    (0x03) 
    #define ASC_SINGLE_CHANNEL    (0x04) 
    
    // EMPHASIS Modes 
    #define EMPHASIS_UNKNOWN    (0x00) 
    #define EMPHASIS_NONE        (0x01) 
    #define EMPHASIS_50_15_MS    (0x02) 
    #define EMPHASIS_CCITT_J_17    (0x03) 
    
    typedef struct tagMP3COREHEADER // mp3core 
    {    
        long    lFileSize;        /* Bytes    */ 
        long    /*lFirstFrameOffset;*/ lFirstFrameByteOffset;    /* Bytes    */ 
        long    lTotalFrames;        /* Frames   */ 
        long    lTrackLength;        /* Sekunden */ 
        long    lBitrate;        /* kBit/s   */ 
        long    lFrequence;        /* Hz       */ 
        long    lMPEGVersion; 
        long    lMPEGLayer; 
        bool    fCRCProtected; 
        bool    fPadding; 
        bool    fPrivate; 
        bool    fCopyright; 
        bool    fOriginal; 
        bool    fErrorAppeared; 
        unsigned int /* UINT */    uiEmphasis; 
        unsigned int /* UINT */    uiSoundMode; 
    
    } MP3COREHEADER, *PMP3COREHEADER/*, NEAR *NPMP3COREHEADER, FAR *LPMP3COREHEADER*/; 
    
    bool GetMp3HeaderInformation(const char /*PSTR*/ *pszFilepath, PMP3COREHEADER pMp3CoreHeader);
    
    /***************************************************/ 
    #endif
    

    .cpp

    #include "includes.h"
    
    bool GetMp3HeaderInformation(const char /*PSTR*/ *pszFilepath, PMP3COREHEADER pMp3CoreHeader) 
    { 
        // => Parameter überprüfen 
        if(pszFilepath == NULL || pMp3CoreHeader == NULL) 
            return (false); 
    
        // => Lokale Variablen 
        FILE    *pfMp3File; 
        int        iCharCode; 
        bool    fStatusFlag = false; 
    
        // => noch keine Fehler aufgetreten 
        pMp3CoreHeader->fErrorAppeared = false; 
    
        // => Datei öffnen 
        pfMp3File = fopen(pszFilepath, /*TEXT(*/"rb"/*)*/); 
        if(pfMp3File == NULL) 
        { 
            pMp3CoreHeader->fErrorAppeared = true; 
            return (false); 
        } 
    
        // => Dateigröße bestimmen: 
        std::ifstream ifsMp3File(pszFilepath, std::ios::binary); 
        if(!ifsMp3File) 
        { 
            fclose(pfMp3File); 
            return (false); 
        } 
        ifsMp3File.seekg(0, std::ios::end); 
        pMp3CoreHeader->lFileSize = (long)ifsMp3File.tellg(); 
        ifsMp3File.close(); 
    
        // => Ersten Frame des MPEG 1 Layer III suchen 
        do 
        { 
            iCharCode = fgetc(pfMp3File); 
            if(iCharCode == 255) 
            { 
                iCharCode = fgetc(pfMp3File); 
                if(tolower(iCharCode / 16) == 15) 
                    fStatusFlag = true; 
    
            } 
        } 
        while(!fStatusFlag); 
    
        // => Den ersten Frame Header ermitteln 
        fpos_t fpMp3FilePos; 
        fgetpos(pfMp3File, &fpMp3FilePos); 
        fpMp3FilePos -= 2; 
        pMp3CoreHeader->lFirstFrameByteOffset = fpMp3FilePos; 
    
        // => MPEG Version ermitteln (1/2) 
        int iMPEGVersion = tolower(((iCharCode % 16) / 4) / 2); 
        switch(iMPEGVersion) 
        { 
            case 0: 
                pMp3CoreHeader->lMPEGVersion = 2L; // MPEG-2 
                break; 
            case 1: 
                pMp3CoreHeader->lMPEGVersion = 1L; // MPEG-1 
                break; 
            default: 
                pMp3CoreHeader->fErrorAppeared = true; // Unknown 
                break; 
        } 
    
        // => MPEG Layer ermitteln 
        int iMPEGLayer = tolower((((iCharCode % 16) / 4) % 2) * 2 + (((iCharCode % 16) % 4) / 2)); 
        switch(iMPEGLayer) 
        { 
            case 0: 
                pMp3CoreHeader->lMPEGLayer = 0; // Reserved 
                break; 
            case 1: 
                pMp3CoreHeader->lMPEGLayer = 3; // Layer III 
                break; 
            case 2: 
                pMp3CoreHeader->lMPEGLayer = 2; // Layer II 
                break; 
            case 3: 
                pMp3CoreHeader->lMPEGLayer = 1; // Layer I 
                break; 
            default: 
                pMp3CoreHeader->fErrorAppeared = true; // Unknown 
                break; 
        } 
    
        if(iMPEGLayer != 1) 
        { 
            fclose(pfMp3File); 
            return (true); 
        }  
    
        // => CRC-Protection ermitteln 
        int iProtectionBit = tolower(((iCharCode % 16) % 4) % 2); 
        switch(iProtectionBit) 
        { 
            case 1: 
                pMp3CoreHeader->fCRCProtected = false; // CRC-Protection: No 
                break; 
            case 0: 
                pMp3CoreHeader->fCRCProtected = true; // CRC-Protection: Yes 
                break; 
            default: 
                pMp3CoreHeader->fErrorAppeared = true; // Unknown 
                break; 
        } 
    
        // => Das nächste Byte einlesen, um das 3. des Frame-Headers zu analysieren 
        iCharCode = fgetc(pfMp3File); 
    
        // => Bitrate ermitteln 
        int iBitrateTable[2][16] = 
        { 
            0x000,0x008,0x010,0x018, 
            0x020,0x040,0x050,0x038, 
            0x040,0x080,0x0A0,0x070, 
            0x080,0x100,0x140,0x000, 
            0x000,0x020,0x028,0x030, 
            0x038,0x040,0x050,0x060, 
            0x070,0x080,0x0A0,0x0C0, 
            0x0E0,0x100,0x140,0x000 
        }; 
        pMp3CoreHeader->lBitrate = iBitrateTable[iMPEGVersion][(tolower(iCharCode / 16))]; // in Kbps 
    
        // => Frequenz ermitteln 
        long lFrequencyTable[2][4] = 
        { 
            0x05622,0x05DC0,0x03E80,0x00000, 
            0x0AC44,0x0BB80,0x07D00,0x00000 
        }; 
        pMp3CoreHeader->lFrequence = lFrequencyTable[pMp3CoreHeader->lMPEGVersion][(tolower((iCharCode % 16) / 4))]; // in Hz     
    
        // => Padding ermitteln 
        int iPaddingBit = tolower(((iCharCode % 16) % 4) / 2); 
        switch(iPaddingBit) 
        { 
            case 0: 
                pMp3CoreHeader->fPadding = false; // Padding: No 
                break; 
            case 1: 
                pMp3CoreHeader->fPadding = true; // Padding: Yes 
                break; 
            default: 
                pMp3CoreHeader->fErrorAppeared = true; // Unknown 
                break; 
        } 
    
        // => Private Bit ermitteln 
        int iPrivateBit = tolower(((iCharCode % 16) % 4) % 2); 
        switch(iPrivateBit) 
        { 
            case 0: 
                pMp3CoreHeader->fPrivate = false; // Private: No 
                break; 
            case 1: 
                pMp3CoreHeader->fPrivate = true; // Private: Yes 
                break; 
            default: 
                pMp3CoreHeader->fErrorAppeared = true; // Unknown 
                break; 
        } 
    
        // => Das nächste Byte einlesen, um das 4. des Frame-Headers zu analysieren 
        iCharCode = fgetc(pfMp3File); 
    
        // Sound Channel ermitteln 
        int iChannelMode = tolower((iCharCode / 16) / 4); 
        switch(iChannelMode) 
        { 
            case 0: 
                pMp3CoreHeader->uiSoundMode = ASC_STEREO; // Stereo 
                break; 
            case 1: 
                pMp3CoreHeader->uiSoundMode = ASC_JOINT_STEREO; // Joint Stereo 
                break; 
            case 2: 
                pMp3CoreHeader->uiSoundMode = ASC_DUAL_CHANNEL; // Dual Channel 
                break; 
            case 3: 
                pMp3CoreHeader->uiSoundMode = ASC_SINGLE_CHANNEL; // Single Channel 
                break; 
            default: 
                pMp3CoreHeader->uiSoundMode = ASC_UNKNOWN; // Unknown 
                pMp3CoreHeader->fErrorAppeared = true; 
                break; 
        } 
    
        // => Copyright ermitteln 
        int iCopyrightBit = tolower(((iCharCode % 16) / 4) / 2); 
        switch(iCopyrightBit) 
        { 
            case 0: 
                pMp3CoreHeader->fCopyright = false; // Copyrighted: No 
                break; 
            case 1: 
                pMp3CoreHeader->fCopyright = true; // Copyrighted: Yes 
                break; 
            default: 
                pMp3CoreHeader->fErrorAppeared = true; // Unknown 
                break; 
        } 
    
        // => Originale Mp3 Datei 
        int iOriginalBit = tolower(((iCharCode % 16) / 4) % 2); 
        switch(iOriginalBit) 
        { 
            case 0: 
                pMp3CoreHeader->fOriginal = false; // Original: No 
                break; 
            case 1: 
                pMp3CoreHeader->fOriginal = true; // Original: Yes 
                break; 
            default: 
                pMp3CoreHeader->fErrorAppeared = true; // Unknown 
                break; 
        } 
    
        // => Emphasis ermitteln 
        int iEmphasis = tolower((iCharCode % 16) % 4); 
        switch(iEmphasis) 
        { 
            case 0: 
                pMp3CoreHeader->uiEmphasis = EMPHASIS_NONE; // Emphasis: None 
                break; 
            case 1: 
                pMp3CoreHeader->uiEmphasis = EMPHASIS_50_15_MS; // Emphasis: 50/15 ms 
                break; 
            case 3: 
                pMp3CoreHeader->uiEmphasis = EMPHASIS_CCITT_J_17; // Emphasis: CCITT J.17 
                break; 
            default: 
                pMp3CoreHeader->uiEmphasis = EMPHASIS_UNKNOWN; // Unknown 
                pMp3CoreHeader->fErrorAppeared = true; 
                break; 
        } 
    
        // => Frame-Size berechnen 
        long lFrameSize = (144000 * pMp3CoreHeader->lBitrate / pMp3CoreHeader->lFrequence) + iPaddingBit; 
    
        // => Anzahl der Frames 
        pMp3CoreHeader->lTotalFrames = (pMp3CoreHeader->lFileSize - pMp3CoreHeader->lFirstFrameByteOffset) / lFrameSize; 
    
        // => Track Länge in Sekunden 
        pMp3CoreHeader->lTrackLength = toupper(pMp3CoreHeader->lTotalFrames * 26 / 1000); 
    
        // => Datei Handle wieder schließen 
        fclose(pfMp3File); 
    
        return (!pMp3CoreHeader->fErrorAppeared); 
    }
    


  • sry hab meinen Beitrag lange nicht beachtet, dachte das hatte sich erledigt...

    ALSO:
    eigentlich solltest du durch folgenden Code das auch ohne Windows.h compilieren können

    #define UINT unsigned int
    #define PSTR char*
    

    PS: wenn nicht dann mach noch mal n post (mit Fehlermeldungen büdde 😉 )

    MfG CodeFinder



  • hm kompilieren ging schon aber es is gecrasht.
    hat sich eh erledigt habs jetzt so:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-145320-and-postdays-is-0-and-postorder-is-asc-and-start-is-0.html



  • HiHi,

    Hassu ne Funktion geschrieben, kannst die mal posten ?...würd mich mal interessieren^^...wär cool...!!

    MfG CodeFinder


Anmelden zum Antworten