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

📄 vorbislmc.cpp

📁 FreeAMP(MP3播放)程序源代码-用来研究MP3解码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
       else
           ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent());
       return;
   }

   if (!m_bInit)
   {
       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->GetPrefInt32(kDecoderThreadPriorityPref, &iValue);
   m_decoderThread->SetPriority(iValue);

   bytesCopied = 0;
   bytesPerFrame = 1;
   for (m_frameCounter = 0; !m_bExit;)
   {
      if (m_bPause)
      {
          m_pPauseSem->Wait();
          if (m_bExit)
              break;
      }

      if (m_newPos >= 0)
      {   
          ov_time_seek(&m_vf, (double)(m_newPos / iFramesPerSecond));
          m_frameCounter = m_newPos - 1;
          m_newPos = -1;
          bytesCopied = bytesPerFrame;
      }

      if (bytesCopied >= bytesPerFrame)
      {
          m_frameCounter += bytesCopied / bytesPerFrame;
          bytesCopied %= bytesPerFrame;
          ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(
             new PMOTimeInfoEvent(m_frameCounter));

          bitrateLoops++;
          if (bitrateLoops == iBitrateLoopsPerUpdate && m_decodeInfo.sendInfo)
          {
             int b;

             b = ov_bitrate_instant(&m_vf),
             vi = ov_info(&m_vf, -1);
             VorbisInfoEvent *mie = new VorbisInfoEvent(b,
                                           vi->channels, 
                                           vi->rate, 
                                           1. / (float)iFramesPerSecond);
             m_pTarget->AcceptEvent(mie);

             bitrateLoops = 0;
          }
      }

      Err = m_pOutputBuffer->BeginWrite(pOutBuffer, iDecodeBlockSize);
      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);
          break;
      } 

      section = -1;
      ret = ov_read(&m_vf, (char *)pOutBuffer, iDecodeBlockSize, 
                    0, 2, 1, &section);
      if (ret == 0)
      {
         m_pOutputBuffer->EndWrite(0);
         break;
      }

      if (section != m_section)
      { 
          vi = ov_info(&m_vf, -1);

          info = new OutputInfo;
          info->bits_per_sample = 16;
          info->number_of_channels = m_channels = vi->channels;
          info->samples_per_second = m_rate = vi->rate;
          info->samples_per_frame = vi->rate / iFramesPerSecond;
          info->max_buffer_size = 16384;
          m_frameCounter = 0;
          bytesCopied = 0;
          bytesPerFrame = (vi->rate / iFramesPerSecond) * 
                          sizeof(ogg_int16_t) * vi->channels;
          m_section = section;
       
          m_pOutputBuffer->EndWrite(0);
          ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOInitEvent(info));
          ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(
             new PMOTimeInfoEvent(m_frameCounter));

          Err = m_pOutputBuffer->BeginWrite(pOutBuffer, iDecodeBlockSize);
          if (Err != kError_NoErr)
          {
             assert(0);
          }

          vorbis_comment *comment;

          comment = ov_comment(&m_vf, -1);
          if (comment)
          {
              PlaylistItem *plItem = m_pContext->plm->GetCurrentItem();
              if (plItem)
              {
                  MetaData mdata = plItem->GetMetaData();
                  string iso;

                  char *temp;
                  temp = vorbis_comment_query(comment, "title", 0);
                  if (temp)
                  {
                      iso = ConvertToISO(temp);
                      mdata.SetTitle(iso);
                  }
 
                  temp = vorbis_comment_query(comment, "artist", 0);
                  if (temp)
                  {
                      iso = ConvertToISO(temp);
                      mdata.SetArtist(iso);
                  }

                  temp = vorbis_comment_query(comment, "album", 0);
                  if (temp)
                  {
                      iso = ConvertToISO(temp);
                      mdata.SetAlbum(iso);
                  }

                  temp = vorbis_comment_query(comment, "tracknumber", 0);
                  if (temp)
                      mdata.SetTrack(atoi(temp));

                  plItem->SetMetaData(&mdata);
                  m_pContext->target->AcceptEvent(
                             new PlaylistCurrentItemInfoEvent(plItem, 
                                                              m_pContext->plm));

              }
          }
      }
      if(ret <0) 
         ret=0; // hole/error in data - we can safely ignore this
      m_pOutputBuffer->EndWrite(ret);

      bytesCopied += ret;
   }
   ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOQuitEvent());
   ov_clear(&m_vf);

   return;
}

Error VorbisLMC::ChangePosition(int32 position)
{
   m_newPos = position;
   return kError_NoErr;
}

int VorbisLMC::SeekWrapper(void *stream, ogg_int64_t offset, int whence)
{
   return ((VorbisLMC *)stream)->Seek((int32)offset, whence);
}

int VorbisLMC::Seek(long offset, int whence)
{
   int32 ret = -1;

   if (m_pPmi->IsStreaming())
      return -1;

   m_pPmi->Seek(ret, offset, whence);   
   return ret;
}

long VorbisLMC::TellWrapper(void *stream)
{
   return ((VorbisLMC *)stream)->Tell();
}

long VorbisLMC::Tell(void)
{
   int32 ret = -1;

   if (m_pPmi->IsStreaming())
      return -1;

   m_pPmi->Tell(ret);   
   return ret;
}

int VorbisLMC::CloseWrapper(void *stream)
{
   return 0;
}

size_t VorbisLMC::ReadWrapper(void *buf, size_t size, size_t num, void *stream)
{
   return ((VorbisLMC *)stream)->Read(buf, size, num);
}

size_t VorbisLMC::Read(void *buf, size_t size, size_t num)
{
   size_t bytes = size * num;
   void   *ptr;
   Error   Err;

   for(;;)
   {
       Err = m_pInputBuffer->BeginRead(ptr, bytes);
       if (Err == kError_NoDataAvail)
       {
           m_pPmi->Wake();
           usleep(10000);
           continue;
       }
       if (Err == kError_EndOfStream)
       {
           bytes = m_pInputBuffer->GetNumBytesInBuffer();
           if (bytes == 0)
              return (size_t)0;
           continue;
       }
       break;
   }

   if (Err != kError_NoErr)
   {
       return (size_t)-1;
   }

   memcpy(buf, ptr, bytes);
   m_pInputBuffer->EndRead(bytes);

   return bytes / size;   
}

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

const string VorbisLMC::ConvertToISO(const char *utf8)
{
   unsigned char *in, *buf;
   unsigned char *out, *end;
   string               ret;

   in = (unsigned char *)utf8;
   buf = out = new unsigned char[strlen(utf8) + 1];
   end = in + strlen(utf8);
   for(;*in != 0x00 && in <= end; in++, out++)
   {
       if (*in < 0x80)
       {  /* lower 7-bits unchanged */
          *out = *in;
       }
       else
       if (*in > 0xC3)
       { /* discard anything above 0xFF */
          *out = '?';
       }
       else
       if (*in & 0xC0)
       { /* parse upper 7-bits */
          if (in >= end)
            *out = 0;
          else
          {
            *out = (((*in) & 0x1F) << 6) | (0x3F & (*(++in)));
          }
       }
       else
       {
          *out = '?';  /* this should never happen */
       }
   }
   *out = 0x00; /* append null */
   ret = string((char *)buf);
   delete buf;

   return ret;
}

⌨️ 快捷键说明

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