/* I don't know what's the License for this file, I sent Michiel Bronswijk a email, but I didn't get any response yet. */ /* This file is taken from the program mp3studio by Sander Steffann & Michiel Bronswijk ! */ /* *** mpeg_format *** *** Filename: mpeg_format.c *** History: 19980111 Ver 1.00 | Michiel Bronswijk *** 19980112 Ver 1.01 | Michiel Bronswijk *** 19980115 Ver 1.02 | Michiel Bronswijk *** 19980225 Release version 1.00 *** Description: MPEG audio bitstream identification *** Remarks: Ver 1.00 Rev A : The definitions below are not based *** on the official documents so there could be some hidden *** problems if MPEG decides to change things. *** MPEG 1 and 2 will be detected correctly, the special *** Fraunhofer MPEG "2.5" or MPEG 3 will cause *** incorrect results *** Ver 1.01 : since I use the ISO source now there *** should be no problems for MPEG 1 and 2 *** Ver 1.02 : haven't calculated frame size for layer II *** yet, also haven't considered crc-checking and ancillary *** data, dual_channel could also be a problem *** Changes: Ver 1.01 : used ISO source for frame header *** Ver 1.02 : added framesize determination, added tables */ #include #include #include "mpeg_format.h" struct mpegFrameHeader { unsigned char synch; unsigned char synch_v_l_e; unsigned char bri_sf_p_x; unsigned char mo_mx_c_o_em; }; /* The exact frame header looks like this: |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | SYNCH |V| L |E| BRI | SF|P|X| MO| MX|C|O| EM| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ SYNCH = synchronisation (all 1's) V = MPEG version (1=MPEG 1, 0=MPEG 2) L = layer (11=I, 10=II, 01=III) E = use error-protection BRI = bitrate index SF = sample frequency P = padding X = extension MO = mode (11=single_channel, 10=dual_channel, 01=joint_stereo, 00=stereo) MX = mode extension C = copyright O = original EM = emphasis */ /* table with samplesrates */ int samplerates[2][4] = { /* MPEG 2 */ {22050, 24000, 16000, 0}, /* MPEG 1 */ {44100, 48000, 32000, 0} }; /* table with bitrates */ int bitrates[2][3][15] = { { /* MPEG 2 */ {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256}, {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160} }, { /* MPEG 1 */ {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448}, {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384}, {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320} }}; /* *** mpegGetFormat *** *** History: 19980111 Ver 1.00 | Michiel Bronswijk *** 19980112 Ver 1.01 | Michiel Bronswijk *** 19980115 Ver 1.02 | Michiel Bronswijk *** Description: Returns format information for the MPEG bitstream *** that should be present in buf *** Remarks: Fraunhofer MPEG 2.5 causes problems *** Ver 1.02 : calculating frame size is not complete *** Changes: Ver 1.01 : using ISO source for frame header *** Ver 1.02 : now using tables and calculating frame size */ void mpegGetFormat (const void *buf, struct mpegformat_t *returnformat) { struct mpegFrameHeader workheader; /* int temp, temp2; */ int h_version, h_layer, h_bitrate, h_samplerate; memcpy (&workheader, buf, sizeof (struct mpegFrameHeader)); /* determine MPEG version */ h_version = (workheader.synch_v_l_e & 0x08) >> 3; returnformat->version = 2 - h_version; if ((returnformat->version != 1) && (returnformat->version != 2)) returnformat->version = -1; /* determine layer */ h_layer = 3 - ((workheader.synch_v_l_e & 0x06) >> 1); returnformat->layer = 1 + h_layer; if ((returnformat->layer < 1) || (returnformat->layer > 3)) returnformat->version = -1; /* determine channels */ returnformat->channels = (workheader.mo_mx_c_o_em >> 6) & 0x03; /* determine original samplerate */ h_samplerate = (workheader.bri_sf_p_x & 0x0C) >> 2; returnformat->samplerate = samplerates[h_version][h_samplerate]; /* determine kilobits per second */ h_bitrate = (workheader.bri_sf_p_x >> 4) & 0x0f; returnformat->kilobitrate = bitrates[h_version][h_layer][h_bitrate]; /* determine framesize in bytes */ /* !!! NOT COMPLETE !!! */ switch (returnformat->layer) { case 1: returnformat->framesize = bitrates[h_version][h_layer][h_bitrate] * 12000; returnformat->framesize /= samplerates[h_version][h_samplerate]; returnformat->framesize /= (returnformat->version); break; case 3: returnformat->framesize = bitrates[h_version][h_layer][h_bitrate] * 144000; returnformat->framesize /= samplerates[h_version][h_samplerate]; returnformat->framesize /= (returnformat->version); break; default: returnformat->framesize = 0; }; /* finally, check for valid synch (don't force it) */ if (workheader.synch != 255) returnformat->version = -1; };