📄 cpi_player_codec_mpeg.c
字号:
/*
* MPEG 音频解码 (using MAD)
*/
#include "stdafx.h"
#include "globals.h"
#include "CPI_Player_CoDec.h"
#include "libmad/mad.h"
// #include "mmsystem.h"
#include "CPI_Stream.h"
#include "CPI_ID3.h"
#pragma comment(lib, "winmm.lib")
# define SAMPLE_DEPTH 16
# define scale(x, y) dither((x), (y))
struct xing {
long flags;
unsigned long frames;
unsigned long bytes;
unsigned char toc[100];
long scale;
};
enum {
XING_FRAMES = 0x00000001L,
XING_BYTES = 0x00000002L,
XING_TOC = 0x00000004L,
XING_SCALE = 0x00000008L
};
# define XING_MAGIC (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g')
struct dither {
mad_fixed_t error[3];
mad_fixed_t random;
};
typedef struct {
CPs_InStream* m_pInStream;
unsigned long size;
CPs_CoDecOptions options;
struct xing xing;
struct mad_stream stream;
struct mad_frame frame;
struct mad_synth synth;
unsigned int samplecount;
mad_timer_t timer;
mad_timer_t length;
unsigned long rate;
unsigned long frames;
CPs_FileInfo info;
unsigned char buffer[40000];
unsigned int buflen;
} CPs_CoDec_MPEG;
static
int parse_xing(struct xing *xing, struct mad_bitptr ptr, unsigned int bitlen)
{
if (bitlen < 64 || mad_bit_read(&ptr, 32) != XING_MAGIC)
goto fail;
xing->flags = mad_bit_read(&ptr, 32);
bitlen -= 64;
if (xing->flags & XING_FRAMES) {
if (bitlen < 32)
goto fail;
xing->frames = mad_bit_read(&ptr, 32);
bitlen -= 32;
}
if (xing->flags & XING_BYTES) {
if (bitlen < 32)
goto fail;
xing->bytes = mad_bit_read(&ptr, 32);
bitlen -= 32;
}
if (xing->flags & XING_TOC) {
int i;
if (bitlen < 800)
goto fail;
for (i = 0; i < 100; ++i)
xing->toc[i] = (unsigned char) mad_bit_read(&ptr, 8);
bitlen -= 800;
}
if (xing->flags & XING_SCALE) {
if (bitlen < 32)
goto fail;
xing->scale = mad_bit_read(&ptr, 32);
bitlen -= 32;
}
return 0;
fail:
xing->flags = 0;
return -1;
}
static
int scan_header(CPs_InStream* pInStream, struct mad_header *header, struct xing *xing)
{
struct mad_stream stream;
struct mad_frame frame;
unsigned char buffer[8192];
unsigned int buflen = 0;
int count = 0, result = 0;
mad_stream_init(&stream);
mad_frame_init(&frame);
if (xing)
xing->flags = 0;
while (1) {
if (buflen < sizeof(buffer)) {
DWORD bytes;
if(pInStream->Read(pInStream, buffer + buflen, sizeof(buffer) - buflen, &bytes) == FALSE
|| bytes == 0)
{
result = -1;
break;
}
buflen += bytes;
}
mad_stream_buffer(&stream, buffer, buflen);
while (1) {
if (mad_frame_decode(&frame, &stream) == -1) {
if (!MAD_RECOVERABLE(stream.error))
break;
continue;
}
if (count++ ||
(xing && parse_xing(xing, stream.anc_ptr,
stream.anc_bitlen) == 0))
break;
}
if (count || stream.error != MAD_ERROR_BUFLEN)
break;
memmove(buffer, stream.next_frame,
buflen = &buffer[buflen] - stream.next_frame);
}
if (count) {
if (header)
*header = frame.header;
}
else
result = -1;
mad_frame_finish(&frame);
mad_stream_finish(&stream);
return result;
}
static __inline
unsigned long prng(unsigned long state)
{
return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
}
static __inline
signed int dither(mad_fixed_t sample, struct dither *dither)
{
unsigned int scalebits;
mad_fixed_t output, mask, random;
enum {
MIN = -MAD_F_ONE,
MAX = MAD_F_ONE - 1
};
sample += dither->error[0] - dither->error[1] + dither->error[2];
dither->error[2] = dither->error[1];
dither->error[1] = dither->error[0] / 2;
output = sample + (1L << (MAD_F_FRACBITS + 1 - SAMPLE_DEPTH - 1));
scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH;
mask = (1L << scalebits) - 1;
random = prng(dither->random);
output += (random & mask) - (dither->random & mask);
dither->random = random;
if (output > MAX) {
output = MAX;
if (sample > MAX)
sample = MAX;
}
else if (output < MIN) {
output = MIN;
if (sample < MIN)
sample = MIN;
}
output &= ~mask;
dither->error[0] = sample - output;
return output >> scalebits;
}
static
void pack_pcm(unsigned char **pcm, unsigned int nsamples,
mad_fixed_t const *ch1, mad_fixed_t const *ch2)
{
register signed int s0, s1;
static struct dither d0, d1;
if (ch2) { /* stereo */
while (nsamples--) {
s0 = scale(*ch1++, &d0);
s1 = scale(*ch2++, &d1);
# if SAMPLE_DEPTH == 16
(*pcm)[0 + 0] = s0 >> 0;
(*pcm)[0 + 1] = s0 >> 8;
(*pcm)[2 + 0] = s1 >> 0;
(*pcm)[2 + 1] = s1 >> 8;
*pcm += 2 * 2;
# elif SAMPLE_DEPTH == 8
(*pcm)[0] = s0 ^ 0x80;
(*pcm)[1] = s1 ^ 0x80;
*pcm += 2;
# else
# error "bad SAMPLE_DEPTH"
# endif
}
}
else { /* mono */
while (nsamples--) {
s0 = scale(*ch1++, &d0);
# if SAMPLE_DEPTH == 16
(*pcm)[0] = s0 >> 0;
(*pcm)[1] = s0 >> 8;
*pcm += 2;
# elif SAMPLE_DEPTH == 8
*(*pcm)++ = s0 ^ 0x80;
# endif
}
}
}
static void cleanup(CPs_CoDec_MPEG *context)
{
if(context->m_pInStream)
{
context->m_pInStream->Uninitialise(context->m_pInStream);
context->m_pInStream = NULL;
mad_synth_finish(&context->synth);
mad_frame_finish(&context->frame);
mad_stream_finish(&context->stream);
}
}
void CPP_OMMP3_Uninitialise(CPs_CoDecModule* pModule);
BOOL CPP_OMMP3_OpenFile(CPs_CoDecModule* pModule, const char* pcFilename, DWORD dwCookie, HWND hWndOwner);
void CPP_OMMP3_CloseFile(CPs_CoDecModule* pModule);
void CPP_OMMP3_Seek(CPs_CoDecModule* pModule, const int iNumerator, const int iDenominator);
void CPP_OMMP3_GetFileInfo(CPs_CoDecModule* pModule, CPs_FileInfo* pInfo);
//
BOOL CPP_OMMP3_GetPCMBlock(CPs_CoDecModule* pModule, void* pBlock, DWORD* pdwBlockSize);
int CPP_OMMP3_GetCurrentPos_secs(CPs_CoDecModule* pModule);
//
void CP_InitialiseCodec_MPEG(CPs_CoDecModule* pCoDec)
{
CPs_CoDec_MPEG *pContext;
pCoDec->Uninitialise = CPP_OMMP3_Uninitialise;
pCoDec->OpenFile = CPP_OMMP3_OpenFile;
pCoDec->CloseFile = CPP_OMMP3_CloseFile;
pCoDec->Seek = CPP_OMMP3_Seek;
pCoDec->GetFileInfo = CPP_OMMP3_GetFileInfo;
pCoDec->GetPCMBlock = CPP_OMMP3_GetPCMBlock;
pCoDec->GetCurrentPos_secs = CPP_OMMP3_GetCurrentPos_secs;
pCoDec->m_pModuleCookie = malloc(sizeof(CPs_CoDec_MPEG));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -