diff --git a/ac3_common.cpp b/ac3_common.cpp new file mode 100644 index 000000000..a946f8970 --- /dev/null +++ b/ac3_common.cpp @@ -0,0 +1,95 @@ +/* + ogmmerge -- utility for splicing together ogg bitstreams + from component media subtypes + + ac3common.c + AC3 common functions + + Written by Moritz Bunkus + Based on Xiph.org's 'oggmerge' found in their CVS repository + See http://www.xiph.org + + Distributed under the GPL + see the file COPYING for details + or visit http://www.gnu.org/copyleft/gpl.html +*/ +#include +#include + +#include "ac3_common.h" + +int find_ac3_header(unsigned char *buf, int size, ac3_header_t *ac3_header) { + static int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, + 192, 224, 256, 320, 384, 448, 512, 576, 640}; + static unsigned char lfeon[8] = {0x10, 0x10, 0x04, 0x04, 0x04, 0x01, + 0x04, 0x01}; + static unsigned char halfrate[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3}; + ac3_header_t header; + int i; + int frmsizecod; + int bitrate; + int half; + int acmod; + + for (i = 0; i < (size - 7); i++) { + if ((buf[i] != 0x0b) || (buf[i + 1] != 0x77)) + continue; + if (buf[i + 5] >= 0x60) + continue; + half = halfrate[buf[i + 5] >> 3]; + acmod = buf[i + 6] >> 5; + header.flags = ((((buf[i + 6] & 0xf8) == 0x50) ? A52_DOLBY : acmod) | + ((buf[i + 6] & lfeon[acmod]) ? A52_LFE : 0)); + frmsizecod = buf[i + 4] & 63; + if (frmsizecod >= 38) + return -1; + bitrate = rate[frmsizecod >> 1]; + header.bit_rate = (bitrate * 1000) >> half; + switch (buf[i + 4] & 0xc0) { + case 0: + header.sample_rate = 48000 >> half; + header.bytes = 4 * bitrate; + break; + case 0x40: + header.sample_rate = 44100 >> half; + header.bytes = 2 * (320 * bitrate / 147 + (frmsizecod & 1)); + break; + case 0x80: + header.sample_rate = 32000 >> half; + header.bytes = 6 * bitrate; + break; + default: + return -1; + } + switch(header.flags & A52_CHANNEL_MASK) { + case A52_MONO: + header.channels=1; + break; + case A52_CHANNEL: + case A52_STEREO: + case A52_CHANNEL1: + case A52_CHANNEL2: + case A52_DOLBY: + header.channels=2; + break; + case A52_2F1R: + case A52_3F: + header.channels=3; + break; + case A52_3F1R: + case A52_2F2R: + header.channels=4; + break; + case A52_3F2R: + header.channels=5; + break; + } + if (header.flags & A52_LFE) + header.channels++; + memcpy(ac3_header, &header, sizeof(ac3_header_t)); + + return i; + } + + return -1; +} diff --git a/ac3_common.h b/ac3_common.h new file mode 100644 index 000000000..8b6c85f32 --- /dev/null +++ b/ac3_common.h @@ -0,0 +1,52 @@ +/* + ogmmerge -- utility for splicing together ogg bitstreams + from component media subtypes + + ac3common.cpp + AC3 header decoding functions + + Written by Moritz Bunkus + Based on Xiph.org's 'oggmerge' found in their CVS repository + See http://www.xiph.org + + Distributed under the GPL + see the file COPYING for details + or visit http://www.gnu.org/copyleft/gpl.html +*/ +#ifndef __AC3COMMON_H +#define __AC3COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define A52_CHANNEL 0 +#define A52_MONO 1 +#define A52_STEREO 2 +#define A52_3F 3 +#define A52_2F1R 4 +#define A52_3F1R 5 +#define A52_2F2R 6 +#define A52_3F2R 7 +#define A52_CHANNEL1 8 +#define A52_CHANNEL2 9 +#define A52_DOLBY 10 +#define A52_CHANNEL_MASK 15 + +#define A52_LFE 16 + +typedef struct { + int sample_rate; + int bit_rate; + int channels; + int flags; + int bytes; +} ac3_header_t; + +int find_ac3_header(unsigned char *buf, int size, ac3_header_t *ac3_header); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mp3_common.cpp b/mp3_common.cpp new file mode 100644 index 000000000..047c41d09 --- /dev/null +++ b/mp3_common.cpp @@ -0,0 +1,97 @@ +/* + ogmmerge -- utility for splicing together ogg bitstreams + from component media subtypes + + mp3_common.cpp + common routines for MP3 handling + + Written by Moritz Bunkus + Based on Xiph.org's 'oggmerge' found in their CVS repository + See http://www.xiph.org + + Distributed under the GPL + see the file COPYING for details + or visit http://www.gnu.org/copyleft/gpl.html +*/ + +#include "mp3_common.h" +#include "common.h" + +#ifdef DMALLOC +#include +#endif + +int mp3_tabsel[2][16] = + {{0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}, + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}}; + +long mp3_freqs[9] = + {44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000}; + +int find_mp3_header(char *buf, int size, unsigned long *_header) { + int i; + unsigned long header; + int pos; + + if (size < 4) + return -1; + + for (pos = 0; pos <= (size - 4); pos++) { + for (i = 0, header = 0; i < 4; i++) { + header <<= 8; + header |= (unsigned char)buf[i + pos]; + } + + if ((header == FOURCC('R', 'I', 'F', 'F')) || + ((header & 0xffffff00) == FOURCC('I', 'D', '3', ' '))) + continue; + + if ((header & 0xffe00000) != 0xffe00000) + continue; + if (!((header >> 17) & 3)) + continue; + if (((header >> 12) & 0xf) == 0xf) + continue; + if (!((header >> 12) & 0xf)) + continue; + if (((header >> 10) & 0x3) == 0x3) + continue; + if ((((header >> 19) & 1) == 1) && (((header >> 17) & 3) == 3) && + (((header >> 16) & 1) == 1)) + continue; + if ((header & 0xffff0000) == 0xfffe0000) + continue; + *_header = header; + return pos; + } + return -1; +} + +void decode_mp3_header(unsigned long header, mp3_header_t *h) { + if (header & (1 << 20)) { + h->lsf = (header & (1 << 19)) ? 0 : 1; + h->mpeg25 = 0; + } else { + h->lsf = 1; + h->mpeg25 = 1; + } + h->mode = (header >> 6) & 3; + h->error_protection = ((header >> 16) & 1) ^ 1; + h->stereo = (h->mode == 3 ? 1 : 2); + if (h->lsf) + h->ssize = (h->stereo == 1 ? 9 : 17); + else + h->ssize = (h->stereo == 1 ? 17: 32); + if (h->error_protection) + h->ssize += 2; + h->bitrate_index = (header >> 12) & 15; + if (h->mpeg25) + h->sampling_frequency = 6 + ((header >> 10) & 3); + else + h->sampling_frequency = ((header >> 10) & 3) + (h->lsf * 3); + h->padding = (header >> 9) & 1; + h->framesize = (long)mp3_tabsel[h->lsf][h->bitrate_index] * 144000; + h->framesize /= (mp3_freqs[h->sampling_frequency] << h->lsf); + h->framesize = h->framesize + h->padding - 4; +} + diff --git a/mp3_common.h b/mp3_common.h new file mode 100644 index 000000000..3f4a34a68 --- /dev/null +++ b/mp3_common.h @@ -0,0 +1,48 @@ +/* + ogmmerge -- utility for splicing together ogg bitstreams + from component media subtypes + + mp3_common.h + common routines for MP3 handling + + Written by Moritz Bunkus + Based on Xiph.org's 'oggmerge' found in their CVS repository + See http://www.xiph.org + + Distributed under the GPL + see the file COPYING for details + or visit http://www.gnu.org/copyleft/gpl.html +*/ + +#ifndef __MP3_COMMON_H +#define __MP3_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern int mp3_tabsel[2][16]; +extern long mp3_freqs[9]; + +typedef struct { + int lsf; + int mpeg25; + int mode; + int error_protection; + int stereo; + int ssize; + int bitrate_index; + int sampling_frequency; + int padding; + int framesize; +} mp3_header_t; + +int find_mp3_header(char *buf, int size, unsigned long *_header); +void decode_mp3_header(unsigned long header, mp3_header_t *h); + +#ifdef __cplusplus +} +#endif + + +#endif