⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xinglmc.cpp

📁 FreeAMP(MP3播放)程序源代码-用来研究MP3解码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    h_mode     = (buf[3] >> 6) & 3;
    
    
    // determine offset of header
    if( h_id ) {        // mpeg1
        if( h_mode != 3 ) buf+=(32+4);
        else              buf+=(17+4);
    }
    else {      // mpeg2
        if( h_mode != 3 ) buf+=(17+4);
        else              buf+=(9+4);
    }
    
    if( buf[0] != 'X' ) return 0;    // fail
    if( buf[1] != 'i' ) return 0;    // header not found
    if( buf[2] != 'n' ) return 0;
    if( buf[3] != 'g' ) return 0;
    buf+=4;
    
    X->h_id = h_id;
    X->samprate = sr_table[h_sr_index];
    if( h_id == 0 ) X->samprate >>= 1;
    
    head_flags = X->flags = ExtractI4(buf); buf+=4;      // get flags
    
    if( head_flags & FRAMES_FLAG ) {X->frames   = ExtractI4(buf); buf+=4;}
    if( head_flags & BYTES_FLAG )  {X->bytes = ExtractI4(buf); buf+=4;}
    
    if( head_flags & TOC_FLAG ) {
        if( X->toc != NULL ) {
            for(i=0;i<100;i++) X->toc[i] = buf[i];
        }
        buf+=100;
    }
    
    X->vbr_scale = -1;
    if( head_flags & VBR_SCALE_FLAG )  {X->vbr_scale = ExtractI4(buf); buf+=4;}
    
    return 1;       // success
}

int XingLMC::SeekPoint(unsigned char TOC[100], int file_bytes, float percent)
{
    // interpolate in TOC to get file seek point in bytes
    int a, seekpoint;
    float fa, fb, fx;
    
    if( percent < 0.0f )   percent = 0.0f;
    if( percent > 100.0f ) percent = 100.0f;
    
    a = (int)percent;
    if( a > 99 ) a = 99;
    fa = TOC[a];
    if( a < 99 ) {
        fb = TOC[a+1];
    }
    else {
        fb = 256.0f;
    }
    
    fx = fa + (fb-fa)*(percent-a);
    
    seekpoint = (int)((1.0f/256.0f)*fx*file_bytes); 
    
    return seekpoint;
}

Error XingLMC::InitDecoder()
{
   Error          Err;

   if (!m_pTarget || !m_pPmi || !m_pPmo || !m_pInputBuffer || !m_pOutputBuffer)
   {
      return kError_NullValueInvalid;
   }

   if (m_frameBytes < 0)
   {
       Err = GetHeadInfo();
		 if (Err != kError_NoErr)
		    return Err;
   }

   uint32 iRedCode = 0;
//   if (m_decodeInfo.downsample == 1)
//       iRedCode = 1;
//   else if (m_decodeInfo.downsample == 2)
//       iRedCode = 2;

   uint32 iConvCode = 0;
//   if (m_decodeInfo.mono)
//       iConvCode = 1;
//   if (m_decodeInfo.eightbit)
//       iConvCode += 8;

   if (audio_decode_init(&m_sMPEG, &m_sMpegHead, m_frameBytes,
                   iRedCode /* reduction code */, 
                   0 /* transform code (ignored) */ ,
                   iConvCode /* convert code */ ,
                   24000 /* freq limit */ ))
   {
         DEC_INFO      decinfo;
         int32         iNewSize;
         Error         result;

         audio_decode_info(&m_sMPEG, &decinfo);

#if __BYTE_ORDER != __LITTLE_ENDIAN
         cvt_to_wave_init(decinfo.bits);
#endif

         OutputInfo *info;

         info = new OutputInfo;

         info->bits_per_sample = decinfo.bits;
         info->number_of_channels = decinfo.channels;
         info->samples_per_second = decinfo.samprate;

	   if (m_sMpegHead.id)
           {
             m_iMaxWriteSize = (info->number_of_channels * 
	    		               (decinfo.bits / 8) * 1152);
             info->samples_per_frame = 1152;
           }                    
	   else
           {
             m_iMaxWriteSize = (info->number_of_channels * 
	    		               (decinfo.bits / 8) * 576);
             info->samples_per_frame = 576;
           }                    

//         if (m_decodeInfo.downsample == 1)
//             m_iMaxWriteSize *= 2;
//         else if (m_decodeInfo.downsample == 2)
//             m_iMaxWriteSize *= 4;

         info->max_buffer_size = m_iMaxWriteSize;

         m_pContext->prefs->GetPrefInt32(kOutputBufferSizePref, &iNewSize);
         iNewSize = max(iNewSize, iMinimumOutputBufferSize);
         iNewSize *= 1024;
   
         //iNewSize -= iNewSize % (m_iMaxWriteSize * 16);
         iNewSize -= iNewSize % m_iMaxWriteSize;
         result = m_pOutputBuffer->Resize(iNewSize, 0);
         if (IsError(result))
         {
            ReportError("Internal buffer sizing error occurred.");
            m_pContext->log->Error("Resize output buffer failed.");
            return result;
         } 

         ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOInitEvent(info));
   }
   else
   {
      m_pContext->log->Log(LogDecode, "Audio decode init failed.\n");
      return (Error) lmcError_AudioDecodeInitFailed;
   }

   return (Error) kError_NoErr;
}


#if MP3_PROF
extern "C"
{
   etext();
   monstartup();
   _mcleanup();
}
#endif

void XingLMC::DecodeWorkerThreadFunc(void *pxlmc)
{
   if (pxlmc)
   {
      XingLMC  *xlmc = (XingLMC *) pxlmc;

#if MP3_PROF
      monstartup(0x08040000, etext);
#endif

      xlmc->DecodeWork();

#if MP3_PROF
      _mcleanup();
#endif
   }
}

void XingLMC::DecodeWork()
{
   void          *pBuffer, *pOutBuffer;
   Error          Err;
   int32          iLoop = 0, iValue, iReadSize;
   IN_OUT         x = {0, 0};
   bool           bRestart = false;

   assert(m_pPmi);
   assert(m_pPmo);

   m_pSleepSem->Wait();

   m_pPmi->Wake();

   Err = CanDecode();
   if (Err == kError_Interrupt)
      return;
   if (Err != kError_NoErr)
   {
       m_pContext->log->Error("CanDecode returned false.\n");
       if (m_decodeInfo.sendInfo)
       {
           ReportStatus(szCannotDecode);
           m_pTarget->AcceptEvent(new Event(INFO_DoneOutputtingDueToError));
       }
       else
           ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent());
       return;
   }

   Err = ExtractMediaInfo();
   if (Err == kError_Interrupt)
      return;

   if (IsError(Err))
   {
       m_pContext->log->Error("ExtractMediaInfo failed: %d\n", Err);
       if (m_decodeInfo.sendInfo)
       {
           ReportStatus(szCannotDecode);
           m_pTarget->AcceptEvent(new Event(INFO_DoneOutputtingDueToError));
       }
       else
           ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent());
       return;
   }

   Err = InitDecoder();
   if (Err == kError_Interrupt)
      return;

   if (IsError(Err))
   {
       m_pContext->log->Error("Initializing the decoder failed: %d\n", Err);
       if (m_decodeInfo.sendInfo)
           ReportError("Initializing the decoder failed.");
       else
           ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent());
       return;
   }

   m_pContext->prefs->GetPrefInt32(kDecoderThreadPriorityPref, &iValue);
   m_decoderThread->SetPriority(iValue);

   for (m_frameCounter = 0; !m_bExit;)
   {
      bRestart = false;
      ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(
             new PMOTimeInfoEvent(m_frameCounter));

      for(; !m_bExit; )
	  {
          if (m_bPause)
          {
              m_pPauseSem->Wait();
              if (m_bExit)
                  break;
          }

          if (iMaxFrameSize > (int)m_pInputBuffer->GetNumBytesInBuffer() &&
              m_pInputBuffer->GetNumBytesInBuffer() > 0 &&
              m_pInputBuffer->IsEndOfStream())
              iReadSize = m_pInputBuffer->GetNumBytesInBuffer();
          else
              iReadSize = iMaxFrameSize;    

          Err = BeginRead(pBuffer, iReadSize);
          if (Err == kError_Interrupt)
          {
              break;
          }

          if (Err == kError_EndOfStream)
          {
              ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOQuitEvent());

              // Hang around until we're told to leave in case
              // the user seeks and wants to restart the decoder.
              while(!m_bExit && m_pInputBuffer->IsEndOfStream())
              {
                  Sleep();
              }   
              if (!m_pInputBuffer->IsEndOfStream())
              {
                 bRestart = true;
                 break;
              }   
              
              return;
          }
          if (Err == kError_NoDataAvail)
          {
              if (Sleep())
                  break;

              continue;
          }

          if (Err != kError_NoErr)
          {
              ReportError(szFailRead);
              m_pContext->log->Error("LMC: Cannot read from pullbuffer: %s\n", m_szError); 
              return;
          }

          x.in_bytes = 0;
          Err = m_pOutputBuffer->BeginWrite(pOutBuffer, m_iMaxWriteSize);
          if (Err == kError_Interrupt)
          {
              m_pInputBuffer->EndRead(0);
              break;
          }
          if (Err == kError_BufferTooSmall)
          {
              m_pInputBuffer->EndRead(0);
              if (Sleep())
                 break;

              continue;
          }
          if (Err != kError_NoErr)
          {
              m_pInputBuffer->EndRead(0);
              if (m_decodeInfo.sendInfo)
                  ReportError(szFailWrite);
              else
                  ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent());
              m_pContext->log->Error("LMC: Cannot write to eventbuffer: %s (%d)\n", 
                        m_szError, Err); 
              return;
          }

          x = audio_decode(&m_sMPEG, (unsigned char *)pBuffer, 
                                     (short *)pOutBuffer);
          if (x.in_bytes == 0)
		  {
             EndRead(x.in_bytes);
             m_pOutputBuffer->EndWrite(x.in_bytes);
             //m_pContext->log->Log(LogDecode, "Audio decode failed. "
             //                                "Resetting the decoder.\n");

             Err = AdvanceBufferToNextFrame();
             if (Err == kError_Interrupt)
             {
                 break;
             }    

             if (Err == kError_EndOfStream)
             {
                 ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOQuitEvent());
                 break;
             }

             if (Err != kError_NoErr)
             {
                 m_pContext->log->Error("LMC: Cannot advance to next frame: %d\n", Err);
                 if (m_decodeInfo.sendInfo)
                 {
                     ReportStatus("Skipping corrupt track.");
                     m_pTarget->AcceptEvent(new Event(INFO_DoneOutputtingDueToError));
                 }
                 else
                     ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent());
                 return;
             }
          mpeg_init(&m_sMPEG, 0);
			 audio_decode_init(&m_sMPEG, &m_sMpegHead, m_frameBytes, 0, 0, 0, 24000);
		  }
		  else
          {
			    break;
          }
      }
      if (bRestart)
         continue;
         
      if (m_bExit || Err == kError_Interrupt || Err == kError_EndOfStream)
      {
          return;
      }
      EndRead(min((int32)x.in_bytes, iReadSize));
      m_pPmi->Wake();

      if (m_pOutputBuffer)
      {
#if __BYTE_ORDER != __LITTLE_ENDIAN
         x.out_bytes = cvt_to_wave((unsigned char *)pOutBuffer, x.out_bytes);
#endif

         Err = m_pOutputBuffer->EndWrite(x.out_bytes);
         if (Err == kError_Interrupt)
            break;

         if (IsError(Err))
         {
             m_pContext->log->Error("lmc: EndWrite returned %d\n", Err);
             if (m_decodeInfo.sendInfo)
                 ReportError(szFailWrite);
             else
                 ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent());
             return;
         }
      }

      if (iLoop == iMaxDecodeRetries)
      {
         m_pContext->log->Error("LMC: Maximum number of retries reached"
                      " while trying to decode.\n");
         if (m_decodeInfo.sendInfo) 
             ReportStatus(szCannotDecode);

         ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent());
         return;
      }

      m_frameCounter++;
   }

   return;
}

// These two functions are here just to support the CalculcateSongLength()
// function which opens a local file and then reads from it, rather than
// reading from the pipeline.
Error XingLMC::BeginRead(void *&pBuffer, unsigned int iBytesNeeded)
{
   Error eRet;

   if (m_fpFile)
   {
       int iRead;
       
       pBuffer = new char[iBytesNeeded];
       m_pLocalReadBuffer = (char*)pBuffer;
       
       iRead = fread(pBuffer, sizeof(char), iBytesNeeded, m_fpFile);
       if (iRead != (int)iBytesNeeded)
          return kError_EndOfStream;
          
       return kError_NoErr;
   }

   for(; !m_bExit;)
   {
       eRet = m_pInputBuffer->BeginRead(pBuffer, iBytesNeeded);
       if (eRet == kError_NoDataAvail)
       {
           m_pPmi->Wake();
           if (Sleep()) 
              return kError_Interrupt; 
           continue;
       }
       break;
   }
   if (m_bExit)
      return kError_Interrupt;

   return eRet;
}

Error XingLMC::EndRead(size_t iBytesUsed)
{
   if (m_fpFile)
   {
      delete m_pLocalReadBuffer;
      m_pLocalReadBuffer = NULL;
      return kError_NoErr;
   }
       
   return m_pInputBuffer->EndRead(iBytesUsed);
}

Error XingLMC::SetEQData(float *arrayEQ, float preamp) 
{
    Error error = kError_NoErr;
    for(int i=0; i<32; i++)
       m_sMPEG.eq->equalizer[i] = arrayEQ[i];
    m_sMPEG.eq->EQ_gain_adjust = preamp;
    return error;
}

Error XingLMC::SetEQData(bool enable) {
    Error error = kError_NoErr;
    m_sMPEG.eq->enableEQ = enable;
    return error;
}

Error XingLMC::SetDecodeInfo(DecodeInfo &info) 
{
    m_decodeInfo = info;
    return kError_NoErr;
}

Error XingLMC::ChangePosition(int32 position)
{
   int32   dummy;
   uint32  lSeekTo;

   assert(position >= 0 && position < m_iTotalFrames);

   m_frameCounter = position;
   if (m_pXingHeader)
      lSeekTo = XingLMC::SeekPoint(m_pXingHeader->toc, m_lFileSize, 
                                   (float)position * 100/
                                   (float)m_pXingHeader->frames);
   else
      lSeekTo = position * m_frameBytes;
      
   m_pPmi->Seek(dummy, lSeekTo, SEEK_FROM_START);

   return kError_NoErr;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -