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

📄 xinglmc.cpp

📁 一个简单漂亮的C++编写的mp3播放器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        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;
   }

   // select decoder
   m_audioMethods = audio_table[0][0];       // not integer, non 8 bit mode

   if (m_audioMethods.decode_init(&m_sMpegHead,
                                  m_frameBytes,
                                  0 /* reduction code */ ,
                                  0 /* transform code (ignored) */ ,
                                  0 /* convert code */ ,
                                  24000 /* freq limit */ ))
   {
         DEC_INFO      decinfo;
         int32         iNewSize;
         Error         result;

         m_audioMethods.decode_info(&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;
           }                    

         info->max_buffer_size = m_iMaxWriteSize;

         m_pContext->prefs->GetOutputBufferSize(&iNewSize);
         iNewSize *= 1024;
   
         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;
   IN_OUT         x = {0, 0};

   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");
       ReportError(szCannotDecode);
       return;
   }

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

   if (IsError(Err))
   {
       m_pContext->log->Error("ExtractMediaInfo failed: %d\n", Err);
       ReportError(szCannotDecode);

       return;
   }

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

   if (IsError(Err))
   {
       m_pContext->log->Error("Initializing the decoder failed: %d\n", Err);
       ReportError("Initializing the decoder failed.");

       return;
   }

   m_pContext->prefs->GetDecoderThreadPriority(&iValue);
   m_decoderThread->SetPriority(iValue);

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

      // TODO: This loop needs to be terminated after 64k worth of data..
      for(; !m_bExit; )
		{
          if (m_bPause)
          {
              m_pPauseSem->Wait();
              if (m_bExit)
                  break;
          }

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

              continue;
          }
          if (Err != kError_NoErr)
          {
              ReportError(szFailWrite);
              m_pContext->log->Error("LMC: Cannot write to eventbuffer: %s (%d)\n", 
                        m_szError, Err); 
              return;
          }

          Err = BeginRead(pBuffer, iMaxFrameSize);
          if (Err == kError_Interrupt)
          {
              m_pOutputBuffer->EndWrite(0);
              break;
          }

          if (Err == kError_EndOfStream)
          {
              m_pOutputBuffer->EndWrite(0);
              ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOQuitEvent());
              return;
          }
          if (Err == kError_NoDataAvail)
          {
              m_pOutputBuffer->EndWrite(0);
              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 = m_audioMethods.decode((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());
                 return;
             }

             if (Err != kError_NoErr)
             {
                 m_pContext->log->Error("LMC: Cannot advance to next frame: %d\n", Err);
                 ReportError("Cannot advance to next frame. Possible media corruption?");
                 return;
             }
			 m_audioMethods.decode_init(&m_sMpegHead, m_frameBytes, 0, 0, 0, 24000);
		  }
			 else
          {
			    break;
          }
      }
      if (m_bExit || Err == kError_Interrupt)
      {
          return;
      }
      EndRead(x.in_bytes);
      m_pPmi->Wake();

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

#define _VISUAL_ENABLE_
#ifdef  _VISUAL_ENABLE_
//         if (m_pTarget)
//         {
//             SendVisBufEvent *e = new SendVisBufEvent(x.out_bytes,
//                                    pOutBuffer,x.out_bytes);
//             m_pTarget->AcceptEvent(e);
//             m_pTarget->AcceptEvent(new SendVisBufEvent(x.out_bytes,
//                                    pOutBuffer,x.out_bytes));
//         }
#endif  //_VISUAL_ENABLE_
#undef  _VISUAL_ENABLE_

         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);
             ReportError(szFailWrite);
             return;
         }
      }

      if (iLoop == iMaxDecodeRetries)
      {
         m_pContext->log->Error("LMC: Maximum number of retries reached"
                      " while trying to decode.\n");
         ReportError("Cannot decode this MP3. Is the MP3 corrupted?");
         return;
      }

      m_frameCounter++;
   }

   return;
}

// This function encapsulates all the buffering event management
Error XingLMC::BeginRead(void *&pBuffer, unsigned int iBytesNeeded,
                         bool bBufferUp)
{
   int32  iInPercent, iOutPercent;
   unsigned int iBufferUpBytes;

   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;
   }

   if (m_pPmi && m_pInputBuffer && (!m_pPmi->IsStreaming() || m_iBitRate <= 0))
   {
	   return BlockingBeginRead(pBuffer, iBytesNeeded);
   }

   iInPercent = m_pInputBuffer->GetBufferPercentage();
   iOutPercent = m_pOutputBuffer->GetBufferPercentage();

   // If the input buffer is getting too full, discard some bytes.
   // This could be caused by a soundcard with slow playback or 
   // a host that is sending data too quicky. Clock-drift-a-moo!
   if (iOutPercent > 90 && iInPercent > 90 && m_pPmi->UseBufferReduction())
   {
       m_pInputBuffer->DiscardBytes();
   }

   iBufferUpBytes = (m_iBitRate * m_iBufferUpInterval * 1000) / 8192;
   if (iBufferUpBytes > (unsigned)m_iBufferSize)
       iBufferUpBytes = m_iBufferSize / 2;

   if (bBufferUp && iOutPercent < 1 &&
       m_pInputBuffer->GetNumBytesInBuffer() < iBufferUpBytes / 2)
   {
       assert(m_iBufferSize > 0);
       assert(m_iBufferUpInterval > 0);
       assert(m_iBitRate > 0);

       ReportStatus("Buffering up...");
       m_pTarget->AcceptEvent(new StreamBufferEvent(true, iInPercent, 
                                                    iOutPercent));
       for(; !m_bExit;)
       {
           usleep(1000000);
           iInPercent = m_pInputBuffer->GetBufferPercentage();
           iOutPercent = m_pOutputBuffer->GetBufferPercentage();

           m_pTarget->AcceptEvent(new StreamBufferEvent(true, iInPercent, 
                                                    iOutPercent));

           if (m_pInputBuffer->GetNumBytesInBuffer() >= iBufferUpBytes)
           {
               break;
           }    
           if (m_pInputBuffer->GetBufferPercentage() > 90)
           {
               break;
           }
       }
       m_pTarget->AcceptEvent(new StreamBufferEvent(false, iInPercent, 
                                                    iOutPercent));
       ReportStatus("Playing stream...");
   }

	return BlockingBeginRead(pBuffer, iBytesNeeded);
}

Error XingLMC::BlockingBeginRead(void *&pBuffer, unsigned int iBytesNeeded)
{
   Error eRet;

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

   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);
}

		
#define _EQUALIZER_ENABLE_
#ifdef  _EQUALIZER_ENABLE_

extern "C" {
float equalizer[32] = {
    1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
    1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
};
int enableEQ = false;
	   }

Error XingLMC::SetEQData(float *arrayEQ) {
    Error error = kError_NoErr;
        for(int i=0; i<32; i++)
                equalizer[i] = arrayEQ[i];
        return error;
}

Error XingLMC::SetEQData(bool enable) {
    Error error = kError_NoErr;
        enableEQ = enable;
        return error;
}
#endif  //_EQUALIZER_ENABLE_
#undef  _EQUALIZER_ENABLE_

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

   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 + -