#include "mp3-header.h" #include #include #include // layer-1, layer-2, layer-3 static int s_bitrate_mpeg1[3][16] = { { 0/*free*/, 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000, -1 }, { 0/*free*/, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000, -1 }, { 0/*free*/, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, -1 }, }; // layer-1, layer-2, layer-3 static int s_bitrate_mpeg2[3][16] = { { 0/*free*/, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000, -1 }, { 0/*free*/, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, -1 }, { 0/*free*/, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, -1 }, }; // layer-1, layer-2, layer-3 static int s_frequency_mpeg1[4] = { 44100, 48000, 32000, -1 }; static int s_frequency_mpeg2[4] = { 22050, 24000, 16000, -1 }; static int s_frequency_mpeg25[4] = { 11025, 12000, 8000, -1 }; // layer-1, layer-2, layer-3 //static int s_frames_mpeg1[3] = { 384, 1152, 1152 }; //static int s_frames_mpeg2[3] = { 384, 1152, 576 }; //static int s_frames_mpeg25[3] = { 384, 1152, 576 }; // layer-1 bytes = ((frames / 8 * bitrate) / frequency + padding * 4 // layer-2/3 bytes = ((frames / 8 * bitrate) / frequency + padding int mp3_header_load(struct mp3_header_t* mp3, const void* data, int bytes) { const uint8_t* p; if (bytes < 4) return 0; p = data; if (0 == memcmp("TAG", p, 3)) { if (bytes < 128/*ID3v1*/ + 4) return 0; p += 128; } else if (0 == memcmp("ID3", p, 3)) { uint32_t n; if (3 != p[3]/*version*/ || bytes < 10) return 0; n = (((uint32_t)p[6] & 0x7F) << 21) | (((uint32_t)p[7] & 0x7F) << 14) | (((uint32_t)p[8] & 0x7F) << 7) | (p[9] & 0x7F); if (bytes < (int)n + 10) return 0; p += n + 10; } //sync: 1111 1111 111 if (0xFF != p[0] || 0xE0 != (p[1] & 0xE0)) { assert(0); return 0; } mp3->version = (p[1] >> 3) & 0x03; mp3->layer = (p[1] >> 1) & 0x03; mp3->protection = p[1] & 0x01; mp3->bitrate_index = (p[2] >> 4) & 0x0F; mp3->sampling_frequency = (p[2] >> 2) & 0x03; mp3->priviate = p[2] & 0x01; mp3->mode = (p[3] >> 6) & 0x03; mp3->mode_extension = (p[3] >> 4) & 0x03; mp3->copyright = (p[3] >> 3) & 0x01; mp3->original = (p[3] >> 2) & 0x01; mp3->emphasis = p[3] & 0x03; return (int)(p - (uint8_t*)data) + 4; } int mp3_header_save(const struct mp3_header_t* mp3, void* data, int bytes) { uint8_t* p; if (bytes < 4) return 0; p = data; p[0] = 0xFF; p[1] = (uint8_t)(0xE0 | (mp3->version << 3) | (mp3->layer << 1) | mp3->protection); p[2] = (uint8_t)((mp3->bitrate_index << 4) | (mp3->sampling_frequency << 2) | 0x00 /*padding*/ | mp3->priviate); p[3] = (uint8_t)((mp3->mode << 6) | (mp3->mode_extension << 4) | (mp3->copyright << 3) | (mp3->original << 2) | mp3->emphasis); return 4; } int mp3_get_channel(const struct mp3_header_t* mp3) { return 0x03 == mp3->mode ? 1 : 2; } int mp3_get_bitrate(const struct mp3_header_t* mp3) { if (mp3->layer < 1 || mp3->layer > 3) { assert(0); return -1; } switch (mp3->version) { case MP3_MPEG1: return s_bitrate_mpeg1[3 - mp3->layer][mp3->bitrate_index]; case MP3_MPEG2: case MP3_MPEG2_5: return s_bitrate_mpeg2[3 - mp3->layer][mp3->bitrate_index]; default: assert(0); return -1; } } static int mp3_find_bitrate(const int* arr, int bitrate) { int i; for (i = 0; i < 16; i++) { if (bitrate == arr[i]) return i; } return -1; } int mp3_set_bitrate(struct mp3_header_t* mp3, int bitrate) { int r; if (mp3->layer < 1 || mp3->layer > 3) { assert(0); return -1; } switch (mp3->version) { case MP3_MPEG1: r = mp3_find_bitrate(s_bitrate_mpeg1[3 - mp3->layer], bitrate); break; case MP3_MPEG2: case MP3_MPEG2_5: r = mp3_find_bitrate(s_bitrate_mpeg2[3 - mp3->layer], bitrate); break; default: assert(0); r = -1; } if (-1 == r) return -1; mp3->bitrate_index = (unsigned int)r; return 0; } int mp3_get_frequency(const struct mp3_header_t* mp3) { if (mp3->sampling_frequency < 0 || mp3->sampling_frequency > 3) return -1; switch (mp3->version) { case MP3_MPEG1: return s_frequency_mpeg1[mp3->sampling_frequency]; case MP3_MPEG2: return s_frequency_mpeg2[mp3->sampling_frequency]; case MP3_MPEG2_5: return s_frequency_mpeg25[mp3->sampling_frequency]; default: assert(0); return -1; } } static int mp3_find_frequency(const int* arr, int frequency) { int i; for (i = 0; i < 4; i++) { if (frequency == arr[i]) return i; } return -1; } int mp3_set_frequency(struct mp3_header_t* mp3, int frequency) { int r; switch (mp3->version) { case MP3_MPEG1: r = mp3_find_frequency(s_frequency_mpeg1, frequency); break; case MP3_MPEG2: r = mp3_find_frequency(s_frequency_mpeg2, frequency); break; case MP3_MPEG2_5: r = mp3_find_frequency(s_frequency_mpeg25, frequency); break; default: assert(0); r = -1; } if (-1 == r) return -1; mp3->sampling_frequency = (unsigned int)r; return 0; } #if defined(DEBUG) || defined(_DEBUG) void mp3_header_test(void) { uint8_t v[4] = { 0xff, 0xfb, 0xe0, 0x64 }; uint8_t v2[4]; struct mp3_header_t mp3; assert(4 == mp3_header_load(&mp3, v, 4)); assert(MP3_MPEG1 == mp3.version && MP3_LAYER3 == mp3.layer); assert(14 == mp3.bitrate_index && 320000 == mp3_get_bitrate(&mp3)); assert(0 == mp3.sampling_frequency && 44100 == mp3_get_frequency(&mp3)); assert(1 == mp3.mode && 1 == mp3.protection); assert(4 == mp3_header_save(&mp3, v2, 4)); assert(0 == memcmp(v, v2, 4)); } #endif