📄 neostreamplayer.cpp
字号:
/*
============================================================================
Name : NeoStreamPlayer.cpp
Author :
Version :
Copyright : Your copyright notice
Description : CNeoStreamPlayer implementation
============================================================================
*/
#include "NeoStreamPlayer.h"
#include <aknnotewrappers.h>
#include <f32file.h>
#include <coemain.h>
#include <mmf/common/mmffourcc.h>
// Bit rates in bits/sec supported by MPEG2, MPEG1 and MPEG2.5 respectively
const TInt16 KMp3BitRateTable[3][16] =
{
{-1,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0},
{-1,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0},
{-1,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0},
};
// Sampling frequencies supported by MPEG2, MPEG1 and MPEG2.5 respectively
const TUint16 KMp3SamplingFrequencyTable[3][4] =
{
{22050,24000,16000,0},
{44100,48000,32000,0},
{11025,12000,8000,0},
};
// Maximum MP3 frame size
const TInt KMp3MaxFrameSize = 1440; // 320kbit/s @ 32kHz
// The size of MP3 header, header must include bits for determining frame length
const TInt KMp3FrameHeaderSize = 5;
CNeoStreamPlayer::CNeoStreamPlayer()
{
// No implementation required
}
CNeoStreamPlayer::~CNeoStreamPlayer()
{
if (iAudioOutputStream)
{
iAudioOutputStream->Stop();
delete iAudioOutputStream;
iAudioOutputStream = NULL;
}
iBuffersArray.Reset();
iBuffersArray.Close();
if (iBufferLump)
{
User::Free(iBufferLump);
iBufferLump = NULL;
}
if (iSrcBuf)
{
delete iSrcBuf;
iSrcBuf = NULL;
}
if (iDstBuf)
{
delete iDstBuf;
iDstBuf = NULL;
}
if (iMMFCodec)
{
delete iMMFCodec;
iMMFCodec = NULL;
}
}
CNeoStreamPlayer* CNeoStreamPlayer::NewLC()
{
CNeoStreamPlayer* self = new (ELeave)CNeoStreamPlayer();
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
CNeoStreamPlayer* CNeoStreamPlayer::NewL()
{
CNeoStreamPlayer* self=CNeoStreamPlayer::NewLC();
CleanupStack::Pop(); // self;
return self;
}
void CNeoStreamPlayer::ConstructL()
{
iAudioOutputStream = CMdaAudioOutputStream::NewL(*this);
iBufferLump = NULL;
iMMFCodec = CMMFCodec::NewL(KMMFFourCCCodeMP3, KMMFFourCCCodePCM16);
iSrcBuf = CMMFDescriptorBuffer::NewL(SRC_SIZE);
iDstBuf = CMMFDescriptorBuffer::NewL(FRAME_SIZE * MAX_PCM_BUFFER_COUNT * 2);
iOpened = EFalse;
iVolume = 5;
}
void CNeoStreamPlayer::MaoscOpenComplete(TInt aError)
{
if (aError == KErrNone)
{
//CAknInformationNote* informationNote = new ( ELeave ) CAknInformationNote;
//informationNote->ExecuteLD( _L("Open Completed!") );
iOpened = ETrue;
// iAudioOutputStream->SetDataTypeL(KMMFFourCCCodeMP3);
// iAudioOutputStream->SetAudioPropertiesL(iStreamSettings.iSampleRate, iStreamSettings.iChannels);
iAudioOutputStream->SetVolume(iAudioOutputStream->MaxVolume() * iVolume / 10);
} else {
//CAknInformationNote* informationNote = new ( ELeave ) CAknInformationNote;
//informationNote->ExecuteLD( _L("Open Failed!") );
}
}
void CNeoStreamPlayer::MaoscBufferCopied(TInt /*aError*/, const TDesC8& aBuffer)
{
for (TInt i = 0; i < MAX_PCM_BUFFER_COUNT ; i++)
if (aBuffer.Ptr() == iBuffersArray[i].Ptr())
{
iBufferValid[i] = EFalse;
break;
}
}
void CNeoStreamPlayer::MaoscPlayComplete(TInt aError)
{
if (aError == KErrUnderflow)
{
} else if (aError == KErrCancel)
{
}
}
void CNeoStreamPlayer::InitStreamPlayer(TInt32 aChannels, TInt32 aSampleRate, TInt /*aFrameSize*/)
{
switch (aChannels)
{
case 1:
iStreamSettings.iChannels = TMdaAudioDataSettings::EChannelsMono;
break;
case 2:
iStreamSettings.iChannels = TMdaAudioDataSettings::EChannelsStereo;
break;
default:
iStreamSettings.iChannels = TMdaAudioDataSettings::EChannelsMono;
break;
}
switch (aSampleRate)
{
case 8000:
iStreamSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate8000Hz;
break;
case 11025:
iStreamSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate11025Hz;
break;
case 12000:
iStreamSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate12000Hz;
break;
case 16000:
iStreamSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate16000Hz;
break;
case 22050:
iStreamSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate22050Hz;
break;
case 24000:
iStreamSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate24000Hz;
break;
case 32000:
iStreamSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate32000Hz;
break;
case 44100:
iStreamSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate44100Hz;
break;
case 48000:
iStreamSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate48000Hz;
break;
case 96000:
iStreamSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate96000Hz;
break;
case 64000:
iStreamSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate64000Hz;
break;
default:
iStreamSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate8000Hz;
break;
}
RArray<TInt> configParams;
// Configure codec for 44.1kHz stereo output
if (aChannels == 2)
configParams.Append(0); // stereo to mono switch (TRUE(1) or default FALSE(0))
else
configParams.Append(1); // stereo to mono switch (TRUE(1) or default FALSE(0))
configParams.Append(0); // decode left or right channel (1 left, 2 right, 0 default all)
configParams.Append(1); // decimation factor (2, 4 or default 1)
configParams.Append(1); // error concealment level (0 none, default 1)
configParams.Append(16); // resolution of PCM samples (default 16 bits)
configParams.Append(aSampleRate); //Output sampling frequency
TUid codecId = TUid::Uid(KUidMmfCodecAudioSettings);
TDesC8& codecData = REINTERPRET_CAST(TDesC8&, configParams);
iMMFCodec->ConfigureL(codecId, codecData);
configParams.Close();
// iAudioOutputStream->SetPriority(80 , EMdaPriorityPreferenceTimeAndQuality);
iOpened = EFalse;
iAudioOutputStream->Open(&iStreamSettings);
iBufferLumpSize = FRAME_SIZE * MAX_PCM_BUFFER_COUNT * 2 * aChannels;
iBufferLump = (unsigned char*)(User::AllocL(iBufferLumpSize));
iBufferSize = iBufferLumpSize / MAX_PCM_BUFFER_COUNT;
for (TInt i = 0; i < MAX_PCM_BUFFER_COUNT; i++)
{
TUint8* bufPtr = iBufferLump + (iBufferSize * i);
User::LeaveIfError(iBuffersArray.Append(TPtr8(bufPtr, 0, iBufferSize)));
iBufferValid[i] = EFalse;
}
}
void CNeoStreamPlayer::WriteBuffer(const signed short* aBuffer, TInt aLength)
{
if (aLength < 0)
return;
TInt foundBuffer = -1;
for (TInt i = 0; i < MAX_PCM_BUFFER_COUNT ; i++)
if (!iBufferValid[i])
{
foundBuffer = i;
break;
}
if (foundBuffer == -1)
return;
iBufferValid[foundBuffer] = ETrue;
TPtr8& dest = iBuffersArray[foundBuffer];
dest.Copy((const TUint8*)aBuffer, aLength);
iAudioOutputStream->WriteL(dest);
}
void CNeoStreamPlayer::WriteBufferMP3(const unsigned char* aBuffer, TInt aLength)
{
// if (!iOpened)
// return;
if (aLength < 0)
return;
TInt foundBuffer = -1;
for (TInt i = 0; i < MAX_PCM_BUFFER_COUNT ; i++)
if (!iBufferValid[i])
{
foundBuffer = i;
break;
}
if (foundBuffer == -1)
{
//CEikonEnv::Static()->InfoMsg(_L("Damn"));
return;
}
iSrcBuf->Data().Copy(aBuffer, aLength);
TCodecProcessResult result = iMMFCodec->ProcessL(*iSrcBuf, *iDstBuf);
iBufferValid[foundBuffer] = ETrue;
TPtr8& dest = iBuffersArray[foundBuffer];
dest.Copy(iDstBuf->Data());
// dest.Copy(aBuffer, aLength);
iAudioOutputStream->WriteL(dest);
}
void CNeoStreamPlayer::RefreshVolume()
{
if (iAudioOutputStream)
iAudioOutputStream->SetVolume(iAudioOutputStream->MaxVolume() * iVolume / 10);
}
void CNeoStreamPlayer::IncreaseVolume()
{
if (iVolume < 10)
iVolume++;
if (iAudioOutputStream)
iAudioOutputStream->SetVolume(iAudioOutputStream->MaxVolume() * iVolume / 10);
}
void CNeoStreamPlayer::DecreaseVolume()
{
if (iVolume > 0)
iVolume--;
if (iAudioOutputStream)
iAudioOutputStream->SetVolume(iAudioOutputStream->MaxVolume() * iVolume / 10);
}
void CNeoStreamPlayer::Stop()
{
if (iAudioOutputStream)
iAudioOutputStream->Stop();
}
TInt CNeoStreamPlayer::GetBytes()
{
if (iAudioOutputStream)
return iAudioOutputStream->GetBytes();
return 0;
}
TInt CNeoStreamPlayer::GetMp3FrameInfo(const TUint8* aBuf, TInt aBufLen, TAudioFrameInfo& aInfo )
{
TInt length = 0;
TUint temp;
TUint lTempVal;
// Extract header fields to aInfo and check their bit syntax
// (including the sync word!). If the syntax is not OK the length
// is set to zero.
if ( aBufLen >= KMp3FrameHeaderSize )
{
temp = 0;
temp = aBuf[0] << 24;
temp |= (aBuf[1] << 16);
temp |= (aBuf[2] << 8);
temp |= aBuf[3];
if ( ((temp >> 21) & 0x7FF) != 0x7FF )
{
return length;
}
lTempVal = (temp >> 19) & 0x03;
switch ( lTempVal )
{
case 0:
aInfo.iId = 2; // MPEG2.5
aInfo.iFrameSamples = 576;
break;
case 1:
return length;
case 2:
aInfo.iId = 0; // MPEG 2
aInfo.iFrameSamples = 576;
break;
case 3:
aInfo.iId = 1; // MPEG 1
aInfo.iFrameSamples = 1152;
break;
}
lTempVal = (temp >> 17) & 0x03;
if ( lTempVal != 1 )
{
return length;
}
lTempVal = (temp >> 12) & 0x0F;
aInfo.iBitRate = KMp3BitRateTable[aInfo.iId][lTempVal] * 1000;
if ( aInfo.iBitRate == 0 )
{
return length;
}
lTempVal = (temp >> 10) & 0x03;
if ( lTempVal == 3 )
{
return length;
}
else
{
aInfo.iSamplingRate = KMp3SamplingFrequencyTable[aInfo.iId][lTempVal];
}
aInfo.iPadding = (temp >> 9) & 0x01;
lTempVal = (temp >> 6) & 0x03;
aInfo.iMode = lTempVal;
if ( lTempVal == 3 )
{
aInfo.iChannels = 1;
}
else
{
aInfo.iChannels = 2;
}
aInfo.iSamplingRateOut = aInfo.iSamplingRate;
aInfo.iChannelsOut = 2; /* always set to stereo output */
aInfo.iFrameSamplesOut = aInfo.iFrameSamples;
if ( aInfo.iBitRate == -1 )
{
// For free mode operation
length = KMp3MaxFrameSize;
}
if ( aInfo.iSamplingRate > 0 && aInfo.iBitRate > 0 )
{
length = (144 * aInfo.iBitRate) / aInfo.iSamplingRate;
if ( aInfo.iId != 1 )
{
length >>= 1; /*for MPEG2 and MPEG2.5 */
}
if ( aInfo.iPadding )
{
length++;
}
}
aInfo.iFrameSize = length;
}
return length;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -