CPI_Player_CoDec_MPEG.c
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:17k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /*
  2.  * MPEG 音频解码 (using MAD)
  3.  */
  4. #include "stdafx.h"
  5. #include "globals.h"
  6. #include "CPI_Player_CoDec.h"
  7. #include "libmad/mad.h"
  8. // #include "mmsystem.h"
  9. #include "CPI_Stream.h"
  10. #include "CPI_ID3.h"
  11. #pragma comment(lib, "winmm.lib")
  12. # define SAMPLE_DEPTH 16
  13. # define scale(x, y) dither((x), (y))
  14. struct xing {
  15.     long flags;
  16.     unsigned long frames;
  17.     unsigned long bytes;
  18.     unsigned char toc[100];
  19.     long scale;
  20. };
  21. enum {
  22.     XING_FRAMES = 0x00000001L,
  23.     XING_BYTES  = 0x00000002L,
  24.     XING_TOC    = 0x00000004L,
  25.     XING_SCALE  = 0x00000008L
  26. };
  27. # define XING_MAGIC (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g')
  28. struct dither {
  29.     mad_fixed_t error[3];
  30.     mad_fixed_t random;
  31. };
  32. typedef struct {
  33.     CPs_InStream* m_pInStream;
  34.     unsigned long size;
  35.     CPs_CoDecOptions options;
  36.     struct xing xing;
  37.     struct mad_stream stream;
  38.     struct mad_frame frame;
  39.     struct mad_synth synth;
  40.     unsigned int samplecount;
  41.     mad_timer_t timer;
  42.     mad_timer_t length;
  43.     unsigned long rate;
  44.     unsigned long frames;
  45.     CPs_FileInfo info;
  46.     unsigned char buffer[40000];
  47.     unsigned int buflen;
  48. } CPs_CoDec_MPEG;
  49. static
  50. int parse_xing(struct xing *xing, struct mad_bitptr ptr, unsigned int bitlen)
  51. {
  52.     if (bitlen < 64 || mad_bit_read(&ptr, 32) != XING_MAGIC)
  53.         goto fail;
  54.     xing->flags = mad_bit_read(&ptr, 32);
  55.     bitlen -= 64;
  56.     if (xing->flags & XING_FRAMES) {
  57.         if (bitlen < 32)
  58.             goto fail;
  59.         xing->frames = mad_bit_read(&ptr, 32);
  60.         bitlen -= 32;
  61.     }
  62.     if (xing->flags & XING_BYTES) {
  63.         if (bitlen < 32)
  64.             goto fail;
  65.         xing->bytes = mad_bit_read(&ptr, 32);
  66.         bitlen -= 32;
  67.     }
  68.     if (xing->flags & XING_TOC) {
  69.         int i;
  70.         if (bitlen < 800)
  71.             goto fail;
  72.         for (i = 0; i < 100; ++i)
  73.             xing->toc[i] = (unsigned char) mad_bit_read(&ptr, 8);
  74.         bitlen -= 800;
  75.     }
  76.     if (xing->flags & XING_SCALE) {
  77.         if (bitlen < 32)
  78.             goto fail;
  79.         xing->scale = mad_bit_read(&ptr, 32);
  80.         bitlen -= 32;
  81.     }
  82.     return 0;
  83. fail:
  84.     xing->flags = 0;
  85.     return -1;
  86. }
  87. static
  88. int scan_header(CPs_InStream* pInStream, struct mad_header *header, struct xing *xing)
  89. {
  90.     struct mad_stream stream;
  91.     struct mad_frame frame;
  92.     unsigned char buffer[8192];
  93.     unsigned int buflen = 0;
  94.     int count = 0, result = 0;
  95.     mad_stream_init(&stream);
  96.     mad_frame_init(&frame);
  97.     if (xing)
  98.         xing->flags = 0;
  99.     while (1) {
  100.         if (buflen < sizeof(buffer)) {
  101.             DWORD bytes;
  102.             if(pInStream->Read(pInStream, buffer + buflen, sizeof(buffer) - buflen, &bytes) == FALSE
  103.                     || bytes == 0)
  104.             {
  105.                 result = -1;
  106.                 break;
  107.             }
  108.             buflen += bytes;
  109.         }
  110.         mad_stream_buffer(&stream, buffer, buflen);
  111.         while (1) {
  112.             if (mad_frame_decode(&frame, &stream) == -1) {
  113.                 if (!MAD_RECOVERABLE(stream.error))
  114.                     break;
  115.                 continue;
  116.             }
  117.             if (count++ ||
  118.                     (xing && parse_xing(xing, stream.anc_ptr,
  119.                                         stream.anc_bitlen) == 0))
  120.                 break;
  121.         }
  122.         if (count || stream.error != MAD_ERROR_BUFLEN)
  123.             break;
  124.         memmove(buffer, stream.next_frame,
  125.                 buflen = &buffer[buflen] - stream.next_frame);
  126.     }
  127.     if (count) {
  128.         if (header)
  129.             *header = frame.header;
  130.     }
  131.     else
  132.         result = -1;
  133.     mad_frame_finish(&frame);
  134.     mad_stream_finish(&stream);
  135.     return result;
  136. }
  137. static __inline
  138. unsigned long prng(unsigned long state)
  139. {
  140.     return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
  141. }
  142. static __inline
  143. signed int dither(mad_fixed_t sample, struct dither *dither)
  144. {
  145.     unsigned int scalebits;
  146.     mad_fixed_t output, mask, random;
  147.     enum {
  148.         MIN = -MAD_F_ONE,
  149.         MAX =  MAD_F_ONE - 1
  150.     };
  151.     sample += dither->error[0] - dither->error[1] + dither->error[2];
  152.     dither->error[2] = dither->error[1];
  153.     dither->error[1] = dither->error[0] / 2;
  154.     output = sample + (1L << (MAD_F_FRACBITS + 1 - SAMPLE_DEPTH - 1));
  155.     scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH;
  156.     mask = (1L << scalebits) - 1;
  157.     random  = prng(dither->random);
  158.     output += (random & mask) - (dither->random & mask);
  159.     dither->random = random;
  160.     if (output > MAX) {
  161.         output = MAX;
  162.         if (sample > MAX)
  163.             sample = MAX;
  164.     }
  165.     else if (output < MIN) {
  166.         output = MIN;
  167.         if (sample < MIN)
  168.             sample = MIN;
  169.     }
  170.     output &= ~mask;
  171.     dither->error[0] = sample - output;
  172.     return output >> scalebits;
  173. }
  174. static
  175. void pack_pcm(unsigned char **pcm, unsigned int nsamples,
  176.               mad_fixed_t const *ch1, mad_fixed_t const *ch2)
  177. {
  178.     register signed int s0, s1;
  179.     static struct dither d0, d1;
  180.     if (ch2) {  /* stereo */
  181.         while (nsamples--) {
  182.             s0 = scale(*ch1++, &d0);
  183.             s1 = scale(*ch2++, &d1);
  184. # if SAMPLE_DEPTH == 16
  185.             (*pcm)[0 + 0] = s0 >> 0;
  186.             (*pcm)[0 + 1] = s0 >> 8;
  187.             (*pcm)[2 + 0] = s1 >> 0;
  188.             (*pcm)[2 + 1] = s1 >> 8;
  189.             *pcm += 2 * 2;
  190. # elif SAMPLE_DEPTH == 8
  191.             (*pcm)[0] = s0 ^ 0x80;
  192.             (*pcm)[1] = s1 ^ 0x80;
  193.             *pcm += 2;
  194. # else
  195. #  error "bad SAMPLE_DEPTH"
  196. # endif
  197.         }
  198.     }
  199.     else {  /* mono */
  200.         while (nsamples--) {
  201.             s0 = scale(*ch1++, &d0);
  202. # if SAMPLE_DEPTH == 16
  203.             (*pcm)[0] = s0 >> 0;
  204.             (*pcm)[1] = s0 >> 8;
  205.             *pcm += 2;
  206. # elif SAMPLE_DEPTH == 8
  207.             *(*pcm)++ = s0 ^ 0x80;
  208. # endif
  209.         }
  210.     }
  211. }
  212. static void cleanup(CPs_CoDec_MPEG *context)
  213. {
  214.     if(context->m_pInStream)
  215.     {
  216.         context->m_pInStream->Uninitialise(context->m_pInStream);
  217.         context->m_pInStream = NULL;
  218.         mad_synth_finish(&context->synth);
  219.         mad_frame_finish(&context->frame);
  220.         mad_stream_finish(&context->stream);
  221.     }
  222. }
  223. void CPP_OMMP3_Uninitialise(CPs_CoDecModule* pModule);
  224. BOOL CPP_OMMP3_OpenFile(CPs_CoDecModule* pModule, const char* pcFilename, DWORD dwCookie, HWND hWndOwner);
  225. void CPP_OMMP3_CloseFile(CPs_CoDecModule* pModule);
  226. void CPP_OMMP3_Seek(CPs_CoDecModule* pModule, const int iNumerator, const int iDenominator);
  227. void CPP_OMMP3_GetFileInfo(CPs_CoDecModule* pModule, CPs_FileInfo* pInfo);
  228. //
  229. BOOL CPP_OMMP3_GetPCMBlock(CPs_CoDecModule* pModule, void* pBlock, DWORD* pdwBlockSize);
  230. int CPP_OMMP3_GetCurrentPos_secs(CPs_CoDecModule* pModule);
  231. //
  232. void CP_InitialiseCodec_MPEG(CPs_CoDecModule* pCoDec)
  233. {
  234.     CPs_CoDec_MPEG *pContext;
  235.     pCoDec->Uninitialise = CPP_OMMP3_Uninitialise;
  236.     pCoDec->OpenFile = CPP_OMMP3_OpenFile;
  237.     pCoDec->CloseFile = CPP_OMMP3_CloseFile;
  238.     pCoDec->Seek = CPP_OMMP3_Seek;
  239.     pCoDec->GetFileInfo = CPP_OMMP3_GetFileInfo;
  240.     pCoDec->GetPCMBlock = CPP_OMMP3_GetPCMBlock;
  241.     pCoDec->GetCurrentPos_secs = CPP_OMMP3_GetCurrentPos_secs;
  242.     pCoDec->m_pModuleCookie = malloc(sizeof(CPs_CoDec_MPEG));
  243.     pContext = (CPs_CoDec_MPEG*)pCoDec->m_pModuleCookie;
  244.     pContext->m_pInStream = NULL;
  245.     pContext->size = 0;
  246.     pContext->options.m_iPretendOption = 42;
  247.     pContext->xing.flags = 0;
  248.     pContext->samplecount = 0;
  249.     pContext->timer  = mad_timer_zero;
  250.     pContext->length = mad_timer_zero;
  251.     pContext->rate   = 0;
  252.     pContext->frames = 0;
  253.     pContext->info.m_iFileLength_Secs = 0;
  254.     pContext->info.m_iBitRate_Kbs     = 0;
  255.     pContext->info.m_iFreq_Hz         = 0;
  256.     pContext->info.m_bStereo          = TRUE;
  257.     pContext->info.m_b16bit           = (SAMPLE_DEPTH == 16);
  258.     pContext->buflen = 0;
  259.     CPFA_InitialiseFileAssociations(pCoDec);
  260.     CPFA_AddFileAssociation(pCoDec, "MP3", 0L);
  261.     CPFA_AddFileAssociation(pCoDec, "MP2", 0L);
  262.     CPFA_AddFileAssociation(pCoDec, "MP1", 0L);
  263. }
  264. void CPP_OMMP3_Uninitialise(CPs_CoDecModule* pModule)
  265. {
  266.     CPs_CoDec_MPEG *context = (CPs_CoDec_MPEG *)pModule->m_pModuleCookie;
  267.     CP_CHECKOBJECT(context);
  268.     cleanup(context);
  269.     free(context);
  270.     CPFA_EmptyFileAssociations(pModule);
  271. }
  272. BOOL CPP_OMMP3_OpenFile(CPs_CoDecModule* pModule, char const *path, DWORD dwCookie, HWND hWndOwner)
  273. {
  274.     CPs_CoDec_MPEG *context = (CPs_CoDec_MPEG *)pModule->m_pModuleCookie;
  275.     int iStreamStart = 0;
  276.     CP_CHECKOBJECT(context);
  277.     cleanup(context);
  278.     CP_TRACE1("CPI_CoDec__OpenFile: "%s"", path);
  279.     context->m_pInStream = CP_CreateInStream(path, hWndOwner);
  280.     if(!context->m_pInStream)
  281.     {
  282.         CP_TRACE0("CPI_CoDec__OpenFile: failed");
  283.         return FALSE;
  284.     }
  285.     if(context->m_pInStream->IsSeekable(context->m_pInStream) == TRUE)
  286.     {
  287.         CIs_ID3v2Tag tag;
  288.         unsigned int iBytesRead;
  289.         memset(&tag, 0, sizeof(tag));
  290.         context->m_pInStream->Read(context->m_pInStream, &tag, sizeof(tag), &iBytesRead);
  291.         if(memcmp(tag.m_cTAG, "ID3", 3) == 0)
  292.         {
  293.             iStreamStart = sizeof(CIs_ID3v2Tag);
  294.             iStreamStart += (tag.m_cSize_Encoded[0] << 21)
  295.                             | (tag.m_cSize_Encoded[1] << 14)
  296.                             | (tag.m_cSize_Encoded[2] << 7)
  297.                             | tag.m_cSize_Encoded[3];
  298.         }
  299.         context->m_pInStream->Seek(context->m_pInStream, iStreamStart);
  300.     }
  301.     mad_stream_init(&context->stream);
  302.     mad_frame_init(&context->frame);
  303.     mad_synth_init(&context->synth);
  304.     if (scan_header(context->m_pInStream,
  305.                     &context->frame.header, &context->xing) == -1) {
  306.         CP_TRACE0("CPI_CoDec__OpenFile: failed to read file header");
  307.         cleanup(context);
  308.         return FALSE;
  309.     }
  310.     context->m_pInStream->Seek(context->m_pInStream, iStreamStart);
  311.     context->size             = context->m_pInStream->GetLength(context->m_pInStream);
  312.     context->synth.pcm.length = 0;
  313.     context->samplecount      = 0;
  314.     context->timer            = mad_timer_zero;
  315.     if (context->xing.flags & XING_FRAMES) {
  316.         context->length = context->frame.header.duration;
  317.         mad_timer_multiply(&context->length, context->xing.frames);
  318.     }
  319.     else {
  320.         mad_timer_set(&context->length, 0,
  321.                       1, context->frame.header.bitrate / 8);
  322.         mad_timer_multiply(&context->length, context->size);
  323.     }
  324.     context->rate   = 0;
  325.     context->frames = 0;
  326.     context->info.m_iFileLength_Secs =
  327.         mad_timer_count(context->length, MAD_UNITS_SECONDS);
  328.     context->info.m_iBitRate_Kbs     = context->frame.header.bitrate / 1000;
  329.     context->info.m_iFreq_Hz         = context->frame.header.samplerate;
  330.     context->info.m_bStereo          =
  331.         context->frame.header.mode == MAD_MODE_SINGLE_CHANNEL ? FALSE : TRUE;
  332.     context->info.m_b16bit           = (SAMPLE_DEPTH == 16);
  333.     context->buflen = 0;
  334.     return TRUE;
  335. }
  336. void CPP_OMMP3_CloseFile(CPs_CoDecModule* pModule)
  337. {
  338.     CPs_CoDec_MPEG *context = (CPs_CoDec_MPEG *)pModule->m_pModuleCookie;
  339.     CP_CHECKOBJECT(context);
  340.     CP_TRACE0("Close MPEG file");
  341.     cleanup(context);
  342. }
  343. void CPP_OMMP3_Seek(CPs_CoDecModule* pModule, int const numer, int const denom)
  344. {
  345.     CPs_CoDec_MPEG *context = (CPs_CoDec_MPEG *)pModule->m_pModuleCookie;
  346.     double fraction;
  347.     unsigned long position;
  348.     CP_CHECKOBJECT(context);
  349.     CP_ASSERT(context->m_pInStream);
  350.     CP_ASSERT(numer >= 0 && denom > 0);
  351.     if(context->m_pInStream->IsSeekable(context->m_pInStream) == FALSE)
  352.         return;
  353.     fraction = (double) numer / denom;
  354.     position = (unsigned long)
  355.                (mad_timer_count(context->length, MAD_UNITS_MILLISECONDS) * fraction);
  356.     mad_timer_set(&context->timer, position / 1000, position % 1000, 1000);
  357.     if (context->xing.flags & XING_TOC) {
  358.         int percent, p1, p2;
  359.         percent = (int) (fraction * 100);
  360.         p1 = (percent < 100) ? context->xing.toc[percent    ] : 0x100;
  361.         p2 = (percent <  99) ? context->xing.toc[percent + 1] : 0x100;
  362.         fraction = (p1 + (p2 - p1) * (fraction * 100 - percent)) / 0x100;
  363.     }
  364.     context->m_pInStream->Seek(context->m_pInStream, (LONG) (context->size * fraction));
  365.     if(context->m_pInStream->Read(context->m_pInStream, context->buffer, sizeof(context->buffer),&context->buflen) == FALSE)
  366.         context->buflen = 0;
  367.     mad_stream_buffer(&context->stream, context->buffer, context->buflen);
  368.     mad_frame_mute(&context->frame);
  369.     mad_synth_mute(&context->synth);
  370.     if (numer) {
  371.         int skip;
  372.         skip = 2;
  373.         do {
  374.             if (mad_frame_decode(&context->frame, &context->stream) == 0) {
  375.                 mad_timer_add(&context->timer, context->frame.header.duration);
  376.                 if (--skip == 0)
  377.                     mad_synth_frame(&context->synth, &context->frame);
  378.             }
  379.             else if (!MAD_RECOVERABLE(context->stream.error))
  380.                 break;
  381.         }
  382.         while (skip);
  383.     }
  384.     context->synth.pcm.length = 0;
  385.     context->samplecount      = 0;
  386. }
  387. BOOL CPP_OMMP3_GetPCMBlock(CPs_CoDecModule* pModule, void *block, DWORD *size)
  388. {
  389.     CPs_CoDec_MPEG *context = (CPs_CoDec_MPEG *)pModule->m_pModuleCookie;
  390.     unsigned char *samples = block;
  391.     unsigned int nsamples;
  392.     CP_CHECKOBJECT(context);
  393.     CP_ASSERT(context->m_pInStream);
  394.     nsamples = (*size / (SAMPLE_DEPTH / 8)) >>
  395.                (context->info.m_bStereo ? 1 : 0);
  396.     *size = 0;
  397.     while (nsamples) {
  398.         unsigned int count, bitrate;
  399.         count = context->synth.pcm.length - context->samplecount;
  400.         if (count > nsamples)
  401.             count = nsamples;
  402.         if (count) {
  403.             mad_fixed_t const *ch1, *ch2;
  404.             ch1 = context->synth.pcm.samples[0] + context->samplecount;
  405.             ch2 = context->synth.pcm.samples[1] + context->samplecount;
  406.             if (context->info.m_bStereo == FALSE)
  407.                 ch2 = 0;
  408.             else if (context->synth.pcm.channels == 1)
  409.                 ch2 = ch1;
  410.             pack_pcm(&samples, count, ch1, ch2);
  411.             context->samplecount += count;
  412.             nsamples             -= count;
  413.             if (nsamples == 0)
  414.                 break;
  415.         }
  416.         while (mad_frame_decode(&context->frame, &context->stream) == -1) {
  417.             DWORD bytes;
  418.             if (MAD_RECOVERABLE(context->stream.error))
  419.                 continue;
  420.             if (context->stream.next_frame) {
  421.                 memmove(context->buffer, context->stream.next_frame,
  422.                         context->buflen = context->buffer +
  423.                                           context->buflen - context->stream.next_frame);
  424.             }
  425.             if(context->m_pInStream->Read(context->m_pInStream,
  426.                                           context->buffer + context->buflen,
  427.                                           sizeof(context->buffer) - context->buflen, &bytes) == FALSE
  428.                     || bytes == 0)
  429.             {
  430.                 return FALSE;
  431.             }
  432.             mad_stream_buffer(&context->stream,
  433.                               context->buffer, context->buflen += bytes);
  434.         }
  435.         bitrate = context->frame.header.bitrate / 1000;
  436.         context->rate += bitrate;
  437.         context->frames++;
  438.         context->info.m_iBitRate_Kbs = bitrate;
  439.         mad_synth_frame(&context->synth, &context->frame);
  440.         context->samplecount = 0;
  441.         mad_timer_add(&context->timer, context->frame.header.duration);
  442.     }
  443.     *size = samples - (unsigned char *) block;
  444.     return TRUE;
  445. }
  446. void CPP_OMMP3_GetFileInfo(CPs_CoDecModule* pModule, CPs_FileInfo *info)
  447. {
  448.     CPs_CoDec_MPEG *context = (CPs_CoDec_MPEG *)pModule->m_pModuleCookie;
  449.     CP_CHECKOBJECT(context);
  450.     if (!(context->xing.flags & XING_FRAMES) && context->frames) {
  451.         mad_timer_set(&context->length, 0,
  452.                       1, (context->rate / context->frames) * (1000 / 8));
  453.         mad_timer_multiply(&context->length, context->size);
  454.         if (mad_timer_compare(context->timer, context->length) > 0)
  455.         {
  456.             context->length = context->timer;
  457.             context->size   = context->m_pInStream->GetLength(context->m_pInStream);
  458.         }
  459.         context->info.m_iFileLength_Secs =
  460.             mad_timer_count(context->length, MAD_UNITS_SECONDS);
  461.     }
  462.     *info = context->info;
  463. }
  464. int CPP_OMMP3_GetCurrentPos_secs(CPs_CoDecModule* pModule)
  465. {
  466.     CPs_CoDec_MPEG *context = (CPs_CoDec_MPEG *)pModule->m_pModuleCookie;
  467.     CP_CHECKOBJECT(context);
  468.     return mad_timer_count(context->timer, MAD_UNITS_SECONDS);
  469. }