www.pudn.com > Tetris.rar > CMixerThread.cpp
// INCLUDES #include "CMixerThread.h" #include#include "TSample.h" #include "TAudioShared.h" // CONSTANTS const TInt KSampleRate = 16000; // sample rate used const TInt KBufferSize = KSampleRate / 20; // 20 buffers per second TInt CMixerThread::ThreadFunction( TAny* aData ) { TAudioShared& shared = *((TAudioShared*)aData); // tell client we're alive // signaled off when destroying this thread shared.iAliveMutex.Wait(); CMixerThread* mixerThread = CMixerThread::Create( aData ); if( mixerThread == NULL ) { return KErrGeneral; } // if we're still here, activescheduler has been constructed // start wait loop which runs until it's time to end the thread CActiveScheduler::Start(); delete mixerThread; // tell owning thread it's safe to exit shared.iAliveMutex.Signal(); return KErrNone; } CMixerThread* CMixerThread::Create( TAny* aData ) { CMixerThread* self = new CMixerThread( aData ); if( self == NULL ) return self; if( self->Construct() != KErrNone ) { delete self; return NULL; } return self; } TInt CMixerThread::Construct() { // create cleanup stack iCleanupStack = CTrapCleanup::New(); if( iCleanupStack == NULL ) { return KErrNoMemory; } TInt err = KErrNone; TRAP( err, ConstructL() ); return err; } void CMixerThread::ConstructL() { // create active scheduler iActiveScheduler = new( ELeave )CActiveScheduler; CActiveScheduler::Install( iActiveScheduler ); // sound inits iSet.iChannels = TMdaAudioDataSettings::EChannelsMono; iSet.iSampleRate = TMdaAudioDataSettings::ESampleRate16000Hz; iSet.iVolume = 1; iMixBuffer = new( ELeave )TInt[ KBufferSize ]; iBuffer = new( ELeave )TInt16[ KBufferSize ]; iBufferPtr.Set( TPtrC8( (TUint8*)iBuffer, KBufferSize*2 ) ); // store pointer of this class to thread local store // for use in ExcHandler ( static function ) Dll::SetTls( this ); RThread().SetExceptionHandler( ExcHandler, 0xffffffff ); } CMixerThread::CMixerThread( TAny* aData ) : iShared( *((TAudioShared*)aData) ) {} CMixerThread::~CMixerThread() { delete iStream; delete iBuffer; delete iMixBuffer; delete iActiveScheduler; delete iCleanupStack; } void CMixerThread::ExcHandler( TExcType aExc ) { // exception handler entry function CMixerThread* mixerPointer = (CMixerThread*)Dll::Tls(); mixerPointer->HandleException( aExc ); } void CMixerThread::HandleException( TExcType aExc ) { // handle exceptions // exception type EExcUserInterrupt is reserved for inter-thread communication switch( aExc ) { case EExcUserInterrupt: // Command from client { switch( iShared.iCmd ) { case ECmdStartMixer: { StartMixer(); }break; case ECmdStopMixer: { StopMixer(); }break; case ECmdDestroyMixer: { CActiveScheduler::Stop(); // Exit }break; } }break; default: { // if unknown exception, just exit this thread CActiveScheduler::Stop(); // Exit }break; } } void CMixerThread::StartMixer() { iStream = CMdaAudioOutputStream::NewL( *this ); iStream->Open( &iSet ); } void CMixerThread::StopMixer() { iStream->Stop(); delete iStream; iStream = NULL; } void CMixerThread::FillBuffer() { // wait for access to shared data iShared.iMutex.Wait(); TInt volume = iShared.iMainVolume; // // Gather new sample information // TInt i; for( i=0; i > KAudioShift ] * volume ); pos += posAdd; if( pos >= posEnd ) { if( repEnd == 0 ) { iAudioData[ i ] = NULL; break; } else { pos = repStart; posEnd = repEnd; } } *buf++ += sample; } iAudioPos[ i ] = pos; iAudioEnd[ i ] = posEnd; } } // convert 32-bit mixing buffer to 16-bit output buffer TInt* buf = iMixBuffer; TInt* bufEnd = buf + KBufferSize; TInt16* buf2 = iBuffer; while( buf < bufEnd ) { // 32-bit mixer buffer contents are multiplied by main volume // shifts are in two phases to prevent overflow and maintain quality TInt value = ( ( *buf++ >> 8 ) * volume ) >> 8; // Prevent sound from trashing on overboost volume: if( value < -0x7fff ) value = -0x7fff; if( value > 0x7fff ) value = 0x7fff; // and write to buffer *buf2++ = (TInt16)value; } // write 16-bit buffer to CMdaAudioOutputStream iStream->WriteL( iBufferPtr ); } void CMixerThread::MaoscBufferCopied( TInt aError, const TDesC8& /*aBuffer*/ ) { if( aError ) { iError = aError; } else { FillBuffer(); } } void CMixerThread::MaoscOpenComplete( TInt aError ) { if( aError ) { iError = aError; } else { iStream->SetVolume( iStream->MaxVolume() ); FillBuffer(); } } void CMixerThread::MaoscPlayComplete( TInt aError ) { if( aError ) { iError = aError; } else { iStream->SetVolume( iStream->MaxVolume() ); FillBuffer(); } }