mirror of
https://github.com/KolibriOS/kolibrios.git
synced 2024-12-18 04:43:06 +03:00
3eda462807
Programs: fasm updated to 1.67.14, small fixes in desktop, stackcfg, calc, board, pipes, freecell, big cleanup of unused programs, added some applications from 0.6.3.0 distr... git-svn-id: svn://kolibrios.org@205 a494cfbc-eb01-0410-851d-a64ba20cac60
514 lines
13 KiB
C
514 lines
13 KiB
C
#include "mp3dec.h"
|
||
#include <string.h>
|
||
#include <math.h>
|
||
|
||
typedef unsigned char byte;
|
||
typedef unsigned int uint;
|
||
typedef unsigned short ushort;
|
||
|
||
static const int br_tbl[3][3][16] = {
|
||
{// MPEG-1
|
||
// Layer1
|
||
{ 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 },
|
||
// Layer2
|
||
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0 },
|
||
// Layer3
|
||
{ 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 },
|
||
},
|
||
{// MPEG-2
|
||
// Layer1
|
||
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0 },
|
||
// Layer2
|
||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 },
|
||
// Layer3
|
||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 },
|
||
},
|
||
{// MPEG-2.5
|
||
// Layer1 (not available)
|
||
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0 },
|
||
// Layer2 (not available)
|
||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 },
|
||
// Layer3
|
||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 },
|
||
},
|
||
};
|
||
|
||
static const int fr_tbl[3][4] = {
|
||
// MPEG-1
|
||
{ 44100, 48000, 32000, 0/*reserved*/ },
|
||
// MPEG-2
|
||
{ 22050, 24000, 16000, 0/*reserved*/ },
|
||
// MPEG-2.5
|
||
{ 11025, 12000, 8000, 0/*reserved*/ },
|
||
};
|
||
/* 1999/11/01<30>í<EFBFBD>œ
|
||
static const double ms_p_f_table[3][3] =
|
||
{
|
||
// Layer1
|
||
{8.707483f, 8.0f, 12.0f},
|
||
// Layer2
|
||
{26.12245f, 24.0f, 36.0f},
|
||
// Layer3
|
||
{26.12245f, 24.0f, 36.0f},
|
||
};
|
||
*/
|
||
typedef void (*FRAME_PROC) (MPEG_HEADER* h, byte* mpeg, byte* pcm);
|
||
|
||
MPEG_DECODE_OPTION m_option;
|
||
FRAME_PROC m_frame_proc;
|
||
int m_last_error;
|
||
int m_frequency;
|
||
int m_frame_size, m_pcm_size;
|
||
int m_enableEQ;
|
||
float m_equalizer[32];
|
||
//float m_band_tbl[2][32];
|
||
|
||
void L1table_init();
|
||
void L2table_init();
|
||
void L3table_init();
|
||
void L1decode_start(MPEG_HEADER* h);
|
||
void L2decode_start(MPEG_HEADER* h);
|
||
void L3decode_start(MPEG_HEADER* h);
|
||
void L1decode_frame(MPEG_HEADER* h, byte* mpeg, byte* pcm);
|
||
void L2decode_frame(MPEG_HEADER* h, byte* mpeg, byte* pcm);
|
||
void L3decode_frame(MPEG_HEADER* h, byte* mpeg, byte* pcm);
|
||
|
||
void _stdcall debug_out_hex(unsigned int val);
|
||
void debug_out_str(char* str);
|
||
|
||
|
||
void mp3DecodeInit()
|
||
{
|
||
// _set_SSE2_enable(0);
|
||
|
||
m_option.reduction = 0;
|
||
m_option.convert = 0;
|
||
m_option.freqLimit = 24000;
|
||
|
||
L1table_init();
|
||
L2table_init();
|
||
L3table_init();
|
||
}
|
||
|
||
int mp3GetHeader(byte* buf, MPEG_HEADER* h)
|
||
{
|
||
h->version = (buf[1] & 0x08) >> 3;
|
||
h->layer = (buf[1] & 0x06) >> 1;
|
||
h->error_prot = (buf[1] & 0x01);
|
||
h->br_index = (buf[2] & 0xf0) >> 4;
|
||
h->fr_index = (buf[2] & 0x0c) >> 2;
|
||
h->padding = (buf[2] & 0x02) >> 1;
|
||
h->extension = (buf[2] & 0x01);
|
||
h->mode = (buf[3] & 0xc0) >> 6;
|
||
h->mode_ext = (buf[3] & 0x30) >> 4;
|
||
h->copyright = (buf[3] & 0x08) >> 3;
|
||
h->original = (buf[3] & 0x04) >> 2;
|
||
h->emphasis = (buf[3] & 0x03);
|
||
|
||
if (buf[0] != 0xFF) {//sync error
|
||
m_last_error = MP3_ERROR_INVALID_SYNC;
|
||
return 0;
|
||
}
|
||
if ((buf[1] & 0xF0) == 0xF0) //MPEG-1, MPEG-2
|
||
h->version = (h->version) ? 1 : 2;
|
||
else if ((buf[1] & 0xF0) == 0xE0) //MPEG-2.5
|
||
h->version = 3;
|
||
else {
|
||
m_last_error = MP3_ERROR_INVALID_SYNC;
|
||
return 0;
|
||
}
|
||
if (h->fr_index >= 3 ||
|
||
h->br_index == 0 || h->br_index >= 15 ||
|
||
h->layer == 0 || h->layer >= 4) {
|
||
m_last_error = MP3_ERROR_INVALID_HEADER;
|
||
return 0;
|
||
}
|
||
h->layer = 4 - h->layer;
|
||
h->error_prot = (h->error_prot) ? 0 : 1;
|
||
|
||
return 1;
|
||
}
|
||
|
||
int mp3GetLastError()
|
||
{
|
||
return m_last_error;
|
||
}
|
||
|
||
int mp3FindSync(byte* buf, int size, int* sync)
|
||
{
|
||
int i;
|
||
|
||
*sync = 0;
|
||
size -= 3;
|
||
if (size <= 0) {
|
||
m_last_error = MP3_ERROR_OUT_OF_BUFFER;
|
||
return 0;
|
||
}
|
||
for (i = 0; i < size; i ++) {
|
||
if (buf[i] == 0xFF) {
|
||
if ((buf[i + 1] & 0xF0) == 0xF0) {
|
||
break;
|
||
}
|
||
else if ((buf[i + 1] & 0xF0) == 0xE0) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (i == size) {
|
||
m_last_error = MP3_ERROR_OUT_OF_BUFFER;
|
||
return 0;
|
||
}
|
||
*sync = i;
|
||
return 1;
|
||
}
|
||
|
||
void mp3GetDecodeOption(MPEG_DECODE_OPTION* option)
|
||
{
|
||
*option = m_option;
|
||
}
|
||
|
||
int mp3SetDecodeOption(MPEG_DECODE_OPTION* option)
|
||
{
|
||
m_option = *option;
|
||
return 1;
|
||
}
|
||
|
||
int mp3SetEqualizer(int* value)
|
||
{
|
||
int i;
|
||
if (value == (void*)0) {
|
||
m_enableEQ = 0;
|
||
return 1;
|
||
}
|
||
m_enableEQ = 1;
|
||
//60, 170, 310, 600, 1K, 3K
|
||
for (i = 0; i < 6; i ++) {
|
||
m_equalizer[i] = (float)pow_test(10,(double)value[i]/200);
|
||
}
|
||
//6K
|
||
m_equalizer[6] = (float)pow_test(10,(double)value[6]/200);
|
||
m_equalizer[7] = m_equalizer[6];
|
||
//12K
|
||
m_equalizer[8] = (float)pow_test(10,(double)value[7]/200);
|
||
m_equalizer[9] = m_equalizer[8];
|
||
m_equalizer[10] = m_equalizer[8];
|
||
m_equalizer[11] = m_equalizer[8];
|
||
//14K
|
||
m_equalizer[12] = (float)pow_test(10,(double)value[8]/200);
|
||
m_equalizer[13] = m_equalizer[12];
|
||
m_equalizer[14] = m_equalizer[12];
|
||
m_equalizer[15] = m_equalizer[12];
|
||
m_equalizer[16] = m_equalizer[12];
|
||
m_equalizer[17] = m_equalizer[12];
|
||
m_equalizer[18] = m_equalizer[12];
|
||
m_equalizer[19] = m_equalizer[12];
|
||
//16K
|
||
m_equalizer[20] = (float)pow_test(10,(double)value[9]/200);
|
||
m_equalizer[21] = m_equalizer[20];
|
||
m_equalizer[22] = m_equalizer[20];
|
||
m_equalizer[23] = m_equalizer[20];
|
||
m_equalizer[24] = m_equalizer[20];
|
||
m_equalizer[25] = m_equalizer[20];
|
||
m_equalizer[26] = m_equalizer[20];
|
||
m_equalizer[27] = m_equalizer[20];
|
||
m_equalizer[28] = m_equalizer[20];
|
||
m_equalizer[29] = m_equalizer[20];
|
||
m_equalizer[30] = m_equalizer[20];
|
||
m_equalizer[31] = m_equalizer[20];
|
||
return 1;
|
||
}
|
||
|
||
#define VBR_FRAMES_FLAG 0x0001
|
||
#define VBR_BYTES_FLAG 0x0002
|
||
#define VBR_TOC_FLAG 0x0004
|
||
#define VBR_SCALE_FLAG 0x0008
|
||
|
||
static int extractInt4(byte* buf)
|
||
{// big endian extract
|
||
return buf[3] | (buf[2] << 8) |
|
||
(buf[1] << 16) | (buf[0] << 24);
|
||
}
|
||
|
||
int mp3GetDecodeInfo(byte* mpeg, int size, MPEG_DECODE_INFO* info, int decFlag)
|
||
{
|
||
MPEG_HEADER* h = &info->header;
|
||
byte* p = mpeg;
|
||
int vbr;
|
||
uint minBitRate, maxBitRate;
|
||
uint i, j, flags;
|
||
|
||
|
||
//int bitRate;
|
||
//int frame_size;
|
||
|
||
if (size < 156) {//max vbr header size
|
||
m_last_error = MP3_ERROR_OUT_OF_BUFFER;
|
||
return 0;
|
||
}
|
||
if (!mp3GetHeader(p, h)) {
|
||
return 0;
|
||
}
|
||
//check VBR Header
|
||
p += 4;//skip mpeg header
|
||
if (h->error_prot) p += 2;//skip crc
|
||
if (h->layer == 3) {//skip side info
|
||
if (h->version == 1) {//MPEG-1
|
||
if (h->mode != 3) p += 32;
|
||
else p += 17;
|
||
}
|
||
else {//MPEG-2, MPEG-2.5
|
||
if (h->mode != 3) p += 17;
|
||
else p += 9;
|
||
}
|
||
}
|
||
|
||
info->bitRate = br_tbl[h->version-1][h->layer-1][h->br_index] * 1000;
|
||
info->frequency = fr_tbl[h->version-1][h->fr_index];
|
||
if (memcmp(p, "Xing", 4) == 0) {//VBR
|
||
p += 4;
|
||
flags = extractInt4(p);
|
||
p += 4;
|
||
if (!(flags & (VBR_FRAMES_FLAG | VBR_BYTES_FLAG))) {
|
||
m_last_error = MP3_ERROR_INVALID_HEADER;
|
||
return 0;
|
||
}
|
||
info->frames = extractInt4(p);
|
||
p += 4;
|
||
info->dataSize = extractInt4(p);
|
||
p += 4;
|
||
if (flags & VBR_TOC_FLAG) p += 100;
|
||
if (flags & VBR_SCALE_FLAG) p += 4;
|
||
|
||
/*/////////////////////////////////
|
||
//•W<E280A2>€VBR‘Ήž
|
||
if ( p[0] == mpeg[0] && p[1] == mpeg[1] ) {
|
||
info->skipSize = (int)(p - mpeg);
|
||
} else {
|
||
info->bitRate = br_tbl[h->version-1][h->layer-1][h->br_index] * 1000;
|
||
switch (h->layer) {
|
||
case 1://layer1
|
||
m_frame_size = (12 * info->bitRate / fr_tbl[h->version-1][h->fr_index]) * 4;//one slot is 4 bytes long
|
||
if (h->padding) m_frame_size += 4;
|
||
break;
|
||
case 2://layer2
|
||
m_frame_size = 144 * info->bitRate / fr_tbl[h->version-1][h->fr_index];
|
||
if (h->padding) m_frame_size ++;
|
||
break;
|
||
case 3://layer3
|
||
m_frame_size = 144 * info->bitRate / fr_tbl[h->version-1][h->fr_index];
|
||
if (h->version != 1) //MPEG-2, MPEG-2.5
|
||
m_frame_size /= 2;
|
||
if (h->padding) m_frame_size;
|
||
break;
|
||
}
|
||
info->skipSize = (int)(m_frame_size);
|
||
}
|
||
info->bitRate = 0;
|
||
/////////////////////////////////*/
|
||
|
||
vbr = 1;
|
||
minBitRate = 0xffffffff;
|
||
maxBitRate = 0;
|
||
for (i = 1; i < 15; i ++) {
|
||
j = br_tbl[h->version-1][h->layer-1][i] * 1000;
|
||
if (j < minBitRate) minBitRate = j;
|
||
if (j > maxBitRate) maxBitRate = j;
|
||
}
|
||
}
|
||
else if (memcmp(p, "VBRI", 4) == 0) {//VBRI
|
||
p += 10;
|
||
info->dataSize = extractInt4(p);
|
||
p += 4;
|
||
info->frames = extractInt4(p);
|
||
p += 4;
|
||
vbr = 1;
|
||
minBitRate = 0xffffffff;
|
||
maxBitRate = 0;
|
||
for (i = 1; i < 15; i ++) {
|
||
j = br_tbl[h->version-1][h->layer-1][i] * 1000;
|
||
if (j < minBitRate) minBitRate = j;
|
||
if (j > maxBitRate) maxBitRate = j;
|
||
}
|
||
}
|
||
else {//not VBR
|
||
vbr = 0;
|
||
info->frames = 0;
|
||
//info->skipSize = 0;
|
||
info->dataSize = 0;
|
||
//info->bitRate = br_tbl[h->version-1][h->layer-1][h->br_index] * 1000;
|
||
}
|
||
|
||
// info->frequency = fr_tbl[h->version-1][h->fr_index];
|
||
// info->msPerFrame = ms_p_f_table[h->layer-1][h->fr_index];
|
||
// if (h->version == 3) info->msPerFrame *= 2;
|
||
switch (h->layer) {
|
||
case 1://layer1
|
||
info->outputSize = 384 >> m_option.reduction;
|
||
//if (info->bitRate) {
|
||
if (!vbr) {
|
||
info->skipSize = 0;
|
||
info->minInputSize = (12 * info->bitRate / info->frequency) * 4;//one slot is 4 bytes long
|
||
info->maxInputSize = info->minInputSize + 4;
|
||
}
|
||
else {
|
||
info->skipSize = (12 * info->bitRate / info->frequency + h->padding) * 4;
|
||
info->minInputSize = (12 * minBitRate / info->frequency) * 4;
|
||
info->maxInputSize = (12 * maxBitRate / info->frequency) * 4 + 4;
|
||
}
|
||
break;
|
||
case 2://layer2
|
||
info->outputSize = 1152 >> m_option.reduction;
|
||
//if (info->bitRate) {
|
||
if (!vbr) {
|
||
info->skipSize = 0;
|
||
info->minInputSize = 144 * info->bitRate / info->frequency;
|
||
info->maxInputSize = info->minInputSize + 1;
|
||
}
|
||
else {
|
||
info->skipSize = 144 * info->bitRate / info->frequency + h->padding;
|
||
info->minInputSize = 144 * minBitRate / info->frequency;
|
||
info->maxInputSize = 144 * maxBitRate / info->frequency + 1;
|
||
}
|
||
break;
|
||
case 3://layer3
|
||
i = (h->version == 1) ? 1 : 2;
|
||
//info->outputSize = 1152 >> m_option.reduction;
|
||
info->outputSize = (1152 >> m_option.reduction) / i;
|
||
//if (info->bitRate) {
|
||
if (!vbr) {
|
||
info->skipSize = 0;
|
||
info->minInputSize = 144 * info->bitRate / info->frequency / i;
|
||
info->maxInputSize = info->minInputSize + 1;
|
||
}
|
||
else {
|
||
info->skipSize = 144 * info->bitRate / info->frequency / i + h->padding;
|
||
info->minInputSize = 144 * minBitRate / info->frequency / i;
|
||
info->maxInputSize = 144 * maxBitRate / info->frequency / i + 1;
|
||
}
|
||
break;
|
||
|
||
/*
|
||
if (h->version != 1) {
|
||
//MPEG-2, MPEG-2.5
|
||
info->outputSize /= 2;
|
||
info->minInputSize /= 2;
|
||
info->maxInputSize /= 2;
|
||
}
|
||
info->maxInputSize ++;
|
||
break; */
|
||
|
||
}
|
||
|
||
if ((h->mode == 3) || (m_option.convert & 3))
|
||
info->channels = 1;
|
||
else
|
||
info->channels = 2;
|
||
if (m_option.convert & 8) {
|
||
//not available
|
||
info->bitsPerSample = 8;
|
||
info->outputSize *= info->channels;
|
||
}
|
||
else {
|
||
info->bitsPerSample = 16;
|
||
info->outputSize *= info->channels * 2;
|
||
}
|
||
if ( decFlag == 1 ) {
|
||
m_frequency = info->frequency;
|
||
m_pcm_size = info->outputSize;
|
||
}
|
||
info->frequency >>= m_option.reduction;
|
||
if (vbr) info->bitRate = 0;
|
||
|
||
return 1;
|
||
}
|
||
|
||
void sbt_init();
|
||
|
||
int mp3DecodeStart(byte* mpeg, int size)
|
||
{
|
||
MPEG_DECODE_INFO info;
|
||
MPEG_HEADER* h = &info.header;
|
||
|
||
if (!mp3GetDecodeInfo(mpeg, size, &info, 1)) {
|
||
return 0;
|
||
}
|
||
sbt_init();
|
||
switch (h->layer) {
|
||
case 1:
|
||
L1decode_start(h);
|
||
m_frame_proc = L1decode_frame;
|
||
break;
|
||
case 2:
|
||
L2decode_start(h);
|
||
m_frame_proc = L2decode_frame;
|
||
break;
|
||
case 3:
|
||
L3decode_start(h);
|
||
m_frame_proc = L3decode_frame;
|
||
break;
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
int mp3DecodeFrame(MPEG_DECODE_PARAM* param)
|
||
{
|
||
MPEG_HEADER* h = ¶m->header;
|
||
|
||
if (param->inputSize <= 4) {
|
||
m_last_error = MP3_ERROR_OUT_OF_BUFFER;
|
||
return 0;
|
||
}
|
||
if (!mp3GetHeader(param->inputBuf, h)) {
|
||
return 0;
|
||
}
|
||
|
||
param->bitRate = br_tbl[h->version-1][h->layer-1][h->br_index] * 1000;
|
||
switch (h->layer) {
|
||
case 1://layer1
|
||
m_frame_size = (12 * param->bitRate / m_frequency + h->padding) * 4;
|
||
break;
|
||
case 2://layer2
|
||
m_frame_size = 144 * param->bitRate / m_frequency + h->padding;
|
||
break;
|
||
case 3://layer3
|
||
if (h->version == 1) m_frame_size = 144 * param->bitRate / m_frequency + h->padding;
|
||
else m_frame_size = (144 * param->bitRate / m_frequency) / 2 + h->padding;
|
||
break;
|
||
}
|
||
if (param->inputSize < m_frame_size) {
|
||
m_last_error = MP3_ERROR_OUT_OF_BUFFER;
|
||
return 0;
|
||
}
|
||
|
||
m_frame_proc(h, param->inputBuf, param->outputBuf);
|
||
param->inputSize = m_frame_size;
|
||
param->outputSize = m_pcm_size;
|
||
return 1;
|
||
}
|
||
|
||
void null_frame_proc(MPEG_HEADER* h, byte* mpeg, byte* pcm) {}
|
||
void L3decode_reset();
|
||
|
||
void mp3MuteStart(MPEG_DECODE_PARAM* param)
|
||
{
|
||
m_frame_proc = null_frame_proc;
|
||
}
|
||
|
||
void mp3MuteEnd(MPEG_DECODE_PARAM* param)
|
||
{
|
||
MPEG_HEADER* h = ¶m->header;
|
||
|
||
switch (h->layer) {
|
||
case 1:
|
||
m_frame_proc = L1decode_frame;
|
||
break;
|
||
case 2:
|
||
m_frame_proc = L2decode_frame;
|
||
break;
|
||
case 3:
|
||
L3decode_reset();
|
||
m_frame_proc = L3decode_frame;
|
||
break;
|
||
}
|
||
}
|