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

📄 oggtremor.cpp

📁 OggPlay for Symbian 是symbian上的一个媒体播放程序的源码。它支持ogg,wav等等多媒体格式。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
  iOutStreamByteRate= usedChannels * usedRate * sizeof(short);
  iMaxBytesBetweenFrequencyBins= iOutStreamByteRate / KOggControlFreq;
  return KErrNone;
}


void COggPlayback::SamplingRateSupportedMessage(TBool aConvertRate, TInt aRate, TBool aConvertChannel, TInt /*aNbOfChannels*/)
{
    // Print an error/info msg displaying all supported rates by this HW
    const TInt rates[] = {8000, 11025, 16000, 22050, 32000, 44100, 48000};

#if !defined(MULTI_THREAD_PLAYBACK)
    const TInt ratesMask[] =
	{TMdaAudioDataSettings::ESampleRate8000Hz, TMdaAudioDataSettings::ESampleRate11025Hz,
	TMdaAudioDataSettings::ESampleRate16000Hz, TMdaAudioDataSettings::ESampleRate22050Hz,
	TMdaAudioDataSettings::ESampleRate32000Hz, TMdaAudioDataSettings::ESampleRate44100Hz, TMdaAudioDataSettings::ESampleRate48000Hz };
#endif

    HBufC * hBufMsg = HBufC::NewL(1000);
    CleanupStack::PushL(hBufMsg);

	HBufC * hTmpBuf = HBufC::NewL(500);
    CleanupStack::PushL(hTmpBuf);

    TPtr bufMsg = hBufMsg->Des();
    TPtr tmpBuf = hTmpBuf->Des();
    if (aConvertRate)
    {
        TBuf<128> buf;
        CEikonEnv::Static()->ReadResource(tmpBuf, R_OGG_ERROR_24);
		TBool first = ETrue;
		TInt err;
		for (TInt i=0; i<7; i++)
		{
			#if defined(MULTI_THREAD_PLAYBACK)
			err = SetAudioProperties(rates[i], 1);
			#else
			TRAP(err, iStream->SetAudioPropertiesL(ratesMask[i], TMdaAudioDataSettings::EChannelsMono));
			#endif

			if (err == KErrNone)
			{
				if (!first)
				{ 
					// Append a comma
					buf.Append(_L(", "));
				}
				
				// Append the audio rate
				buf.AppendNum(rates[i]);

				first = EFalse;
			}
		}

		bufMsg.Format(tmpBuf, aRate, &buf);
    }

	if (aConvertChannel)
    {
        CEikonEnv::Static()->ReadResource(tmpBuf, R_OGG_ERROR_25);
        bufMsg.Append(tmpBuf);
    }
    
    CEikonEnv::Static()->ReadResource(tmpBuf, R_OGG_ERROR_26);
    bufMsg.Append(tmpBuf);

    iEnv->OggWarningMsgL(bufMsg);
    CleanupStack::PopAndDestroy(2, hBufMsg);
}

TInt COggPlayback::Volume()
{
#if defined (MULTI_THREAD_PLAYBACK)
  iStreamingThreadCommandHandler->Volume(); 
  return iSharedData.iVolume;
#else
  return iStream->Volume();
#endif
}

void COggPlayback::SetVolume(TInt aVol)
{
#if defined(MULTI_THREAD_PLAYBACK)
  iSharedData.iVolume = aVol;
  iStreamingThreadCommandHandler->SetVolume();
#else
  if (aVol>KMaxVolume) aVol= KMaxVolume;
  else if(aVol<0) aVol= 0;

  TInt volume = (TInt) (((TReal) aVol)/KMaxVolume * iMaxVolume);
  if (volume > iMaxVolume)
      volume = iMaxVolume;

  iStream->SetVolume(volume);
#endif
}

void COggPlayback::SetVolumeGain(TGainType aGain)
{
#if defined(MULTI_THREAD_PLAYBACK)
  FlushBuffers(aGain);
#else
  iOggSampleRateConverter->SetVolumeGain(aGain);
#endif
}

void COggPlayback::SetPosition(TInt64 aPos)
{
  if(iDecoder)
  {
	  // Limit FF to five seconds before the end of the track
	  if (aPos>iTime)
		  aPos = iTime - TInt64(5000);

	  // And don't allow RW past the beginning either
	  if (aPos<0)
		  aPos = 0;

#if defined(MULTI_THREAD_PLAYBACK)
		// Pause/Restart the stream instead of just flushing buffers
	    // This works better with FF/RW because, like next/prev track, key repeats are possible (and very likely on FF/RW)
        TBool streamStopped = FlushBuffers(aPos);

		// Restart streaming
		if (streamStopped)
			iRestartAudioStreamingTimer->Wait(KStreamStartDelay);
#else
	  iDecoder->Setposition(aPos);
#endif
  }
}

TInt64 COggPlayback::Position()
{
#if defined(MULTI_THREAD_PLAYBACK)
  // Approximate position will do here
  const TInt64 KConst500 = TInt64(500);
  TInt64 positionBytes = iSharedData.iTotalBufferBytes - iSharedData.BufferBytes();
  TInt64 positionMillisecs = (KConst500*positionBytes)/TInt64(iSharedData.iSampleRate*iSharedData.iChannels);

  return positionMillisecs;
#else
  // TO DO: Also take into account the buffers (see comments in GetFrequencyBins)
  if(iDecoder) return iDecoder->Position();

  return 0;
#endif
}

TInt64 COggPlayback::Time()
{
  return iTime;
}

#ifdef MDCT_FREQ_ANALYSER
const TInt32 * COggPlayback::GetFrequencyBins()
{
#if defined(MULTI_THREAD_PLAYBACK)
  // Get the precise position from the streaming thread
  iStreamingThreadCommandHandler->Position();
  const TInt64 KConst500000 = TInt64(500000);
  TInt64 streamPositionBytes = (iSharedData.iStreamingPosition.Int64()*TInt64(iSharedData.iSampleRate*iSharedData.iChannels))/KConst500000;
  TInt64 positionBytes = iLastPlayTotalBytes + streamPositionBytes;
#else
  TInt64 positionBytes= iStream->Position().Int64() * iOutStreamByteRate / 1000000; // convert usec to pcm bytes
#endif

  TInt idx = iLastFreqArrayIdx;
  for (TInt i=0; i<KFreqArrayLength; i++)
    {
      if (iFreqArray[idx].iPcmByte <= positionBytes)
          break;
      
        idx--;
        if (idx < 0)
            idx = KFreqArrayLength-1;
    }

  return iFreqArray[idx].iFreqCoefs;
}
#else
const void* COggPlayback::GetDataChunk()
{
  TInt idx= iSentIdx;
  if( iSent[idx] ) 
    return iSent[idx]->Ptr();
  else
    return NULL;
}
#endif

TInt COggPlayback::Info(const TDesC& aFileName, TBool silent)
{
  if (aFileName.Length()==0) return -100;

  RFile* f = new RFile;
  if ((f->Open(iFs, aFileName, EFileShareReadersOnly)) != KErrNone) {
    if (!silent) {
      TBuf<128> buf;
      CEikonEnv::Static()->ReadResource(buf, R_OGG_ERROR_14);
      iEnv->OggErrorMsgL(buf,aFileName);
    }
    return KErrOggFileNotFound;
  }

  MDecoder* decoder = GetDecoderL(aFileName);
  if(decoder->OpenInfo(f, aFileName) < 0) {
    decoder->Close();
	delete decoder;

	f->Close();
	delete f;

	if (!silent) {
       iEnv->OggErrorMsgL(R_OGG_ERROR_20, R_OGG_ERROR_9);
    }
    return -102;
  }
  decoder->ParseTags(iTitle, iArtist, iAlbum, iGenre, iTrackNumber);

  iFileName = aFileName;
  iRate = decoder->Rate();
  iChannels = decoder->Channels();
  iBitRate = decoder->Bitrate();

  decoder->Close(); 
  delete decoder;

  f->Close();
  delete f;

  return KErrNone;
}

void COggPlayback::Play() 
{
    TRACEF(COggLog::VA(_L("PLAY %i "), iState ));
    switch(iState)
	{
    case EPaused:
        break;

    case EStopped:  
        iEof=0;
        break;

    default:
        iEnv->OggErrorMsgL(R_OGG_ERROR_20, R_OGG_ERROR_15);
        RDebug::Print(_L("Oggplay: Tremor - State not Open"));
        return;
  }

  iLastPlayBufferBytes= 0;
#ifdef MDCT_FREQ_ANALYSER
  iLastFreqArrayIdx= 0;
  iBytesSinceLastFrequencyBin= 0;
  // Clear the frequency analyser
  Mem::FillZ(&iFreqArray, sizeof(iFreqArray));
#endif

  // There is something wrong how Nokia audio streaming handles the
  // first buffers. They are somehow swallowed.
  // To avoid that, send few (4) almost empty buffers
  if (iMachineUid != EMachineUid_SendoX) // Sendo X doesn't need this fix. 
      iFirstBuffers = 4; 

#if defined(DELAY_AUDIO_STREAMING_START)
  // Also to avoid the first buffer problem, wait a short time before streaming, 
  // so that Application drawing have been done. Processor should then
  // be fully available for doing audio thingies.

#if !defined(MULTI_THREAD_PLAYBACK)
  // A longer delay is necessary if MULTI_THREAD_PLAYBACK is not defined
  if (iMachineUid == EMachineUid_SendoX) // Latest 1.198.8.2 Sendo X firmware needs a little more time
	iStartAudioStreamingTimer->Wait(KSendoStreamStartDelay);
  else
#endif

	iStartAudioStreamingTimer->Wait(KStreamStartDelay);
#else
  #if defined(MULTI_THREAD_PLAYBACK)
    StartStreaming();
  #else
    for (TInt i=0; i<KBuffers; i++) SendBuffer(*iBuffer[i]);
  #endif
#endif

  iState = EPlaying;
  iObserver->ResumeUpdates();

#if defined(DELAY_AUDIO_STREAMING_START)
  iObserver->NotifyPlayStarted();
#endif
}

void COggPlayback::Pause()
{
  TRACEF(COggLog::VA(_L("PAUSE")));
  if (iState != EPlaying) return;

  iState = EPaused;
  CancelTimers();

#if defined(MULTI_THREAD_PLAYBACK)
  // Flush buffers (and pause the stream)
  FlushBuffers(EPlaybackPaused);
#else
  iStream->Stop();
#endif
}

void COggPlayback::Resume()
{
  //Resume is equivalent of Play() 
  Play();
}

void COggPlayback::Stop()
{
  TRACEF(COggLog::VA(_L("STOP") ));
  if ((iState == EStopped) || (iState == EClosed))
    return;

  iState = EStopped;
  CancelTimers();

#if defined(MULTI_THREAD_PLAYBACK)
  StopStreaming();
#else
  iStream->Stop();
#endif

  if (iFile)
  {
    iDecoder->Close();
    iFile->Close();

	delete iFile;
	iFile = NULL;

	delete iDecoder;
	iDecoder = NULL;
  }

  ClearComments();
  iTime= 0;
  iEof= EFalse;

#if !defined(MULTI_THREAD_PLAYBACK)
  iUnderflowing = EFalse;
#endif

  if (iObserver) iObserver->NotifyUpdate();
}

void COggPlayback::CancelTimers()
{
  iStartAudioStreamingTimer->Cancel();
  iRestartAudioStreamingTimer->Cancel();
  iStopAudioStreamingTimer->Cancel();
}

TInt COggPlayback::GetNewSamples(TDes8 &aBuffer, TBool /*aRequestFrequencyBins*/)
{
    if (iEof)
        return(KErrNotReady);

#ifdef MDCT_FREQ_ANALYSER
	if ((iBytesSinceLastFrequencyBin >= iMaxBytesBetweenFrequencyBins) && !iRequestingFrequencyBins)
	{
		// Make a request for frequency data
		iDecoder->GetFrequencyBins(iFreqArray[iLastFreqArrayIdx].iFreqCoefs, KNumberOfFreqBins);

		// Mark that we have issued the request
		iRequestingFrequencyBins = ETrue;
	}
#endif
    
    TInt len = aBuffer.Length();
    TInt ret = iDecoder->Read(aBuffer,len); 
    if (ret >0)
    {
        aBuffer.SetLength(len + ret);

        iLastPlayBufferBytes+= ret;

#ifdef MDCT_FREQ_ANALYSER
  iBytesSinceLastFrequencyBin+= ret;
	if (iRequestingFrequencyBins)
	{
		// Determine the status of the request
		TInt requestingFrequencyBins = iDecoder->RequestingFrequencyBins();
		if (!requestingFrequencyBins)
		{
			// The frequency request has completed
      iBytesSinceLastFrequencyBin= 0;

      iLastFreqArrayIdx++;
			if (iLastFreqArrayIdx >= KFreqArrayLength)
				iLastFreqArrayIdx = 0;

			#if defined(MULTI_THREAD_PLAYBACK)
			iFreqArray[iLastFreqArrayIdx].iPcmByte= iSharedData.iTotalBufferBytes;
			#else
			iFreqArray[iLastFreqArrayIdx].iPcmByte= iLastPlayBufferBytes;
			#endif

			iRequestingFrequencyBins = EFalse;
		}
	}
#endif
    }

    if (ret == 0)
        iEof= ETrue;

	return ret;
}

void COggPlayback::StartAudioStreamingCallBack()
{
  #if defined(MULTI_THREAD_PLAYBACK)
  StartStreaming();
  #else
  for (TInt i=0; i<KBuffers; i++) 
	SendBuffer(*(iBuffer[i]));
  #endif
}

#if defined(MULTI_THREAD_PLAYBACK)
void COggPlayback::RestartAudioStreamingCallBack()
{
  StartStreaming();
}
#endif

void COggPlayback::StopAudioStreamingCallBack()
{
  Stop();
  iObserver->NotifyPlayComplete();
}

TInt COggPlayback::StartAudioStreamingCallBack(TAny* aPtr)
{
  COggPlayback* self= (COggPlayback*) aPtr;
  self->StartAudioStreamingCallBack();

  return 0;
}

TInt COggPlayback::RestartAudioStreamingCallBack(TAny* aPtr)
{
  COggPlayback* self= (COggPlayback*) aPtr;
  self->RestartAudioStreamingCallBack();

  return 0;
}

TInt COggPlayback::StopAudioStreamingCallBack(TAny* aPtr)
{
  COggPlayback* self= (COggPlayback*) aPtr;
  self->StopAudioStreamingCallBack();

  return 0;
}


#if defined(MULTI_THREAD_PLAYBACK)
TInt COggPlayback::AttachToFs()
{
#if defined(SERIES60V3)
  return KErrNone;
#else
  return iFs.Attach();
#endif
}

TInt COggPlayback::SetAudioProperties(TInt aSampleRate, TInt aChannels)
{
  iSharedData.iSampleRate = aSampleRate;
  iSharedData.iChannels = aChannels;
  return iStreamingThreadCommandHandler->SetAudioProperties();
}

void COggPlayback::StartStreaming()
{
#ifdef MDCT_FREQ_ANALYSER
  // Reset the frequency analyser
  iLastFreqArrayIdx = 0;
  Mem::FillZ(&iFreqArray, sizeof(iFreqArray));

  iLastPlayTotalBytes = iSharedData.iTotalBufferBytes;
#endif

  // Start the buffering listener
  if (iSharedData.iBufferingMode == EBufferThread)
	iBufferingThreadAO->StartListening();

  // The NGage has a poor memory and always forgets the audio settings
  if ((iMachineUid == EMachineUid_NGage) || (iMachineUid == EMachineUid_NGageQD))
	iStreamingThreadCommandHandler->SetAudioProperties();

  // Start the streaming
  iStreamingThreadCommandHandler->StartStreaming();
}

void COggPlayback::StopStreaming()
{
  // Stop the streaming
  iStreamingThreadCommandHandler->StopStreaming();

  // Cancel the buffering AO
  iBufferingThreadAO->Cancel();
}

TInt COggPlayback::SetBufferingMode(TBufferingMode aNewBufferingMode)
{
  if (aNewBufferingMode == iSharedData.iBufferingMode)
	  return KErrNone;

  // Flush the buffers (and stop the stream)
  TBool streamStopped = FlushBuffers(EBufferingModeChanged);

  // Set the new buffering mode
  TBufferingMode oldMode = iSharedData.iBufferingMode;
  iSharedData.iBufferingMode = aNewBufferingMode;

⌨️ 快捷键说明

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