Avatar billede stigc Nybegynder
04. juni 2000 - 20:21 Der er 13 kommentarer og
1 løsning

mp3 format

Jeg vil kunne læse fra en mp3 sang hvore lang den er. Eller bare finde bitdybden. Hvor læser man det i en mp3 fil?
Avatar billede steffen Nybegynder
04. juni 2000 - 23:56 #1
Der er en udmærket kort oversigt på:

http://home.swipnet.se/grd/mp3info/frmheader/index.html

der viser hvordan du trækker den ønskede information ud af headeren i en mp3 fil.

C++ source direkte på siden.
Avatar billede stigc Nybegynder
05. juni 2000 - 00:35 #2
lige hvad jeg søgte!
Avatar billede stigc Nybegynder
05. juni 2000 - 18:23 #3
har du selv prøvet den? Jeg synes ikke den virker. Jeg kan ikke få den til at godkende nogen at min mp3-header!
Avatar billede stigc Nybegynder
05. juni 2000 - 18:24 #4
jeg bruger Borland builder v4.0, og har prøvet med unsigned char!
Avatar billede steffen Nybegynder
05. juni 2000 - 22:15 #5
Hvordan passer udputtet ellers med indholdet af den mp3-fil du tester på - synes det passer fint her. Prøv at sende headeren fra din fil i HEX, sammen med udputtet af din analyse.
Avatar billede stigc Nybegynder
06. juni 2000 - 01:25 #6
ja det er også hen i vejret.
Forkert bitdybe, frekvens etc....

Kode den henter data:

        FILE *udfil;
        udfil = fopen("test2.mp3", "wb");

        FILE *indfil;
        indfil = fopen("test.mp3", "rb");

        fseek(indfil, 0, 0);
        fseek(udfil,  0, 0);

        unsigned  char Buffer[1024];
        int BytesRead=fread(Buffer, 1, 1024,  indfil);
        fwrite(Buffer, 1, BytesRead,  udfil);
        while (BytesRead==1024)
        {
        if (test(Buffer)) break;
        BytesRead=fread(Buffer, 1, 1024, indfil);
          fwrite(Buffer, 1, BytesRead, udfil);
        }

        fclose(indfil);
        fclose(udfil);

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

"test" er funktionen der finder headeren- Der ser således ud:


bool TForm1::test(unsigned  char buffer [])
{

        bool fundet;



        for (int i=0; i<1024; i++)
      {
        if (buffer[i]==225)
                {

                if ((buffer[i+1]&224)==224)
                        {
                        header[0]=buffer[i];
                        header[1]=buffer[i+1];
                        header[2]=buffer[i+2];
                        header[3]=buffer[i+3];
                        fundet=true;
                        }
                }
}
Avatar billede soepro Nybegynder
06. juni 2000 - 08:48 #7
Hvad er der galt med den fine kode der ligger på før-nævnte hjemmeside ??? Jeg har lavet en MP3 fil vha. nero-burn, og den vises al information fra uden problemer ?!?
Avatar billede soepro Nybegynder
06. juni 2000 - 09:31 #8
Følgende kører i TC++ 3.0 og ligeså under C++ Builder 4.0:

#include <conio.h>
#include <string.h>
#include <stdio.h>

#define  bool int

// MP3 file decoding.
unsigned long bithdr;

int getFrameSync()    { return ((bithdr>>21) & 2047); };
int getVersionIndex()  { return ((bithdr>>19) & 3);  };
int getLayerIndex()    { return ((bithdr>>17) & 3);  };
int getProtectionBit() { return ((bithdr>>16) & 1);  };
int getBitrateIndex()  { return ((bithdr>>12) & 15); };
int getFrequencyIndex(){ return ((bithdr>>10) & 3);  };
int getPaddingBit()    { return ((bithdr>> 9) & 1);  };
int getPrivateBit()    { return ((bithdr>> 8) & 1);  };
int getModeIndex()    { return ((bithdr>> 6) & 3);  };
int getModeExtIndex()  { return ((bithdr>> 4) & 3);  };
int getCoprightBit()  { return ((bithdr>> 3) & 1);  };
int getOrginalBit()    { return ((bithdr>> 2) & 1);  };
int getEmphasisIndex() { return ((bithdr    ) & 3);  };

void loadHeader(char c[4]) {
  // Turn the four bytes into a unsigned long.
  bithdr = (unsigned long)( ( (c[0] & 255) << 24) |
                            ( (c[1] & 255) << 16) |
                            ( (c[2] & 255) <<  8) |
                            ( (c[3] & 255)      )
                          );
} // Load header.

bool isValidHeader(void) {
  // Check that valid MP3 header.
  return ( ((getFrameSync()      & 2047)==2047) &&
          ((getVersionIndex()  &    3)!=  1) &&
          ((getLayerIndex()    &    3)!=  0) &&

          // due to lack of support of the .mp3 format
          // no "public" .mp3's should contain information
          // like this anyway... :)
          ((getBitrateIndex()  &  15)!=  0) &&
          ((getBitrateIndex()  &  15)!=  15) &&
          ((getFrequencyIndex() &    3)!=  3) &&
          ((getEmphasisIndex()  &    3)!=  2)    );
} // isValidHeader

// this returns the MPEG version [1.0-2.5]
float getVersion() {
  float table[4] = {
                    2.5, 0.0, 2.0, 1.0
                  };

  // return modified value
  return table[getVersionIndex()];
} // getVersion

// this returns the Layer [1-3]
int getLayer() {
  return ( 4 - getLayerIndex() );
} // getLayer

int getBitrate() {
  const int table[2][3][16] = {
            {        //MPEG 2 & 2.5
              {0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0}, //Layer III
              {0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0}, //Layer II
              {0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256,0}  //Layer I
            },{      //MPEG 1
              {0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,0}, //Layer III
              {0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384,0}, //Layer II
              {0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448,0}  //Layer I
            }
          };

  // the bitrate is not only dependent of the bitrate index,
  // the bitrate also varies with the MPEG version and Layer version
  return table[(getVersionIndex() & 1)][(getLayerIndex() -1)][getBitrateIndex()];
} // getBitrate

unsigned int getFrequency() {
  unsigned int table[4][3] = {
                              {32000, 16000,  8000}, //MPEG 2.5
                              {    0,    0,    0}, //reserved
                              {22050, 24000, 16000}, //MPEG 2
                              {44100, 48000, 32000}  //MPEG 1
                            };
  // the frequency is not only dependent of the bitrate index,
  // the bitrate also varies with the MPEG version
  return table[getVersionIndex()][getFrequencyIndex()];
} // getFrequency

char *getMode(void) {
  switch(getModeIndex()) {
    case 1: return "Joint Stereo";
    case 2: return "Dual Channel";
    case 3: return "Single Channel";
  }
  return "Stereo";
} // getMode

int main(int argc, char *argv[])
{
  FILE *mp3File;
  char  mp3Hdr[4];

  if (argc < 2
  || (mp3File = fopen(argv[1], "rb"))          == NULL
  ||  fread(mp3Hdr, sizeof(mp3Hdr), 1, mp3File) != 1)
  {
    cprintf("Too few arguments (%d), non-existing or invalid file.(%s)\r\n",
            argc, argv[1]);
    return -1;
  };

  // Check if valid MP3 file.
  loadHeader(mp3Hdr);
  if (!isValidHeader())
  {
    cprintf("Header for %s not valid.\r\n", argv[1]);
    return -1;
  }

  // Then display all information about the MP3 file.
  cprintf("MP3 information for \'%s\':\r\n", argv[1]);
  cprintf("=====================%.*s==\r\n", strlen(argv[1]),
          "==============================");

  cprintf("Version    : %1.1f\r\n", getVersion());
  cprintf("Layer      : %d\r\n", getLayer());

  cprintf("Bit-rate  : %u\r\n", getBitrate());
  cprintf("Frequency  : %u\r\n", getFrequency());

  cprintf("Mode      : %s\r\n", getMode());

  return 0;
} // Main
Avatar billede stigc Nybegynder
07. juni 2000 - 00:52 #9
jammen jeg bruger også den kode. Men jeg skal jo selv skrive programmet der finde de fire header bytes....

Når jeg har fudnet dem (ved at finde 11 bit i træk), bruger jeg classen. Men jeg synes ikke den virker rigtigt
Avatar billede soepro Nybegynder
07. juni 2000 - 08:47 #10
Hvad mener du med at du selv skal skrive programmet der finder de fire bytes ??? De tre første statements (fra 'if argc < ...' til 'mp3File) != 1)' læser jo netop de første 4 bytes fra mp3 filen - det første er ikke engang nødvendigt, hvis du har fil-navnet et andet sted. (Jeg har blot ladet fil-navnet være første parameter til programmet.)
Avatar billede stigc Nybegynder
07. juni 2000 - 13:46 #11
Jeg finder ikke et eneste sted hvor der bruges et "if" udtryk i kildekoden!

Jeg har bare gjort som der står på siden:

"The frame header is constituted by the very first four bytes (32bits) in a frame. The first eleven bits of a frame header are always set and they are called "frame sync". Therefore, you can search through the file for the first occurence of frame sync (meaning that you have to find a byte with a value of 255, and followed by a byte with its three most significant bits set).
Then you read the whole header (all 32 bits). "
Avatar billede soepro Nybegynder
07. juni 2000 - 15:35 #12
Hallo - min kode ovenfor !
Avatar billede stigc Nybegynder
07. juni 2000 - 16:18 #13
Ok jeg forstår nu. Jeg prøver det! Men hvorfor skriver han at man skal lede efter de 11 bits, hvis de også altid optræder som de 11 første. Med andre ord er du helt sikker på at de fire første bytes, altid er en mp3 header?
Avatar billede soepro Nybegynder
08. juni 2000 - 09:05 #14
Nej, det er jeg ikke sikker på - men det passer på min fil. (Jeg vil tro problemet kun opstår når man har flere melodier i een MP3 fil.)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester