diff -r 000000000000 -r 951a5db380a0 videoeditorengine/audioeditorengine/src/AudSong.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videoeditorengine/audioeditorengine/src/AudSong.cpp Fri Jan 29 14:08:33 2010 +0200 @@ -0,0 +1,1438 @@ +/* +* Copyright (c) 2010 Ixonos Plc. +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - Initial contribution +* +* Contributors: +* Ixonos Plc +* +* Description: +* +*/ + + + + +#include "AudSong.h" +#include "AudClip.h" +#include "AudPanic.h" +#include "ProcInFileHandler.h" +#include "ProcADTSInFileHandler.h" +#include "ProcAMRInFileHandler.h" +#include "ProcMP4InFileHandler.h" +#include "ProcAWBInFileHandler.h" +#include "AACConstants.h" +#include "audconstants.h" + +#include "AudProcessor.h" +#include "AACApi.h" +#include "aedproctimeestimate.h" + +#include + +// Debug print macro +#if defined _DEBUG +#include +#define PRINT(x) RDebug::Print x; +#else +#define PRINT(x) +#endif + +EXPORT_C CAudSong* CAudSong::NewL(RFs *aFs) + { + CAudSong* self = NewLC(aFs); + CleanupStack::Pop(self); + return self; + } + + +EXPORT_C CAudSong* CAudSong::NewLC(RFs *aFs) + { + CAudSong* self = new (ELeave) CAudSong(aFs); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +CAudSong::CAudSong(RFs *aFs) : iFs(aFs), iClipArray(32), iSongDuration(0), + iSongDurationManuallySet(EFalse), iObserverArray(16), iNormalize(EFalse) + { + } + + +void CAudSong::ConstructL() + { + iProperties = new (ELeave) TAudFileProperties(); + + iProperties->iAudioType = EAudNoAudio; + iProperties->iFileFormat = EAudFormatUnrecognized; + iProperties->iDuration = 0; + iProperties->iFrameCount = 0; + iProperties->iFrameLen = 0; + iProperties->iFrameDuration = 0; + + + iProcessOperation = CAudSongProcessOperation::NewL(this); + iAddOperation = CAudSongAddClipOperation::NewL(this); + + +#ifdef _WRITE_OUTPUT_TO_FILE_ + + + TBuf<32> fileName; + _LIT(KFn, "C:\\audioEngineOut."); + _LIT(KTextFileName, "C:\\audioEngineOut.txt"); + + fileName.Append(KFn); + + if (iProperties->iAudioType == EAudAMR) + { + fileName.Append(_L("amr")); + } + else + { + fileName.Append(_L("aac")); + } + + + User::LeaveIfError(iDebFs.Connect()); + iDebFs.Delete(fileName); + iDebFs.Delete(KTextFileName); + + iFileOpen = EFalse; + TInt err1 = iAudioFile.Create(iDebFs, fileName, EFileWrite); + + TInt err2 = iTextFile.Create(iDebFs, KTextFileName, EFileWrite); + + if (err1 == KErrNone && err2 == KErrNone) + { + iFileOpen = ETrue; + } + + if (iFileOpen && iProperties->iAudioType == EAudAMR) + { + iAudioFile.Write(_L8("#!AMR")); + } + +#endif + + + } + + +EXPORT_C CAudSong::~CAudSong() + { + + Reset(EFalse); + delete iProperties; + iProperties = 0; + delete iProcessOperation; + iProcessOperation = 0; + delete iAddOperation; + iAddOperation = 0; + + + iObserverArray.Reset(); + + +#ifdef _WRITE_OUTPUT_TO_FILE_ + iAudioFile.Close(); + iTextFile.Close(); + iDebFs.Close(); + +#endif + + } + +EXPORT_C TInt CAudSong::GetSizeEstimateL() const + { + + + // if there are no clips added yet + if (iClipArray.Count() == 0) + { + return 0; + } + + TInt durationMilli = ProcTools::MilliSeconds(iClipArray[iClipArray.Count()-1]->EndTime()); + TInt silenceDuration = ProcTools::MilliSeconds(iSongDuration) - durationMilli; + + if (silenceDuration < 0) + { + silenceDuration = 0; + } + + TInt sizeInBytes = 0; + + const TInt KBitrate = iProperties->iBitrate; + const TInt KBitsInByte = 8; + TInt KByterate = KBitrate/KBitsInByte; + + // make sure we round up + sizeInBytes = (durationMilli/1000+1)*KByterate; + + TInt frameDurationMilli = 20; // AMR + TInt silentFrameLen = 13; // AMR + + if (iProperties->iAudioType == EAudAAC_MPEG4) + { + + frameDurationMilli = ((1024*1000)/(iProperties->iSamplingRate)); + + if (iProperties->iChannelMode == EAudSingleChannel) + { + silentFrameLen = KSilentMonoAACFrameLenght; + } + else + { + silentFrameLen = KSilentStereoAACFrameLenght; + } + + } + + if (frameDurationMilli > 0) + { + TInt silentFrames = silenceDuration/frameDurationMilli; + TInt silenceSize = silentFrames*silentFrameLen; + sizeInBytes += silenceSize; + + } + + return sizeInBytes; + + } + +EXPORT_C TInt CAudSong::GetFrameSizeEstimateL(TTimeIntervalMicroSeconds aStartTime, + TTimeIntervalMicroSeconds aEndTime) const + { + // if there are no clips added yet + if (iClipArray.Count() == 0) + { + return 0; + } + + TInt frameDurationMicro = 20000; // AMR + + if (iProperties->iAudioType == EAudAAC_MPEG4) + { + + frameDurationMicro = ((1024*1000)/(iProperties->iSamplingRate))*1000; + } + + // just in case to prevent infinite loop + if (frameDurationMicro <= 0) + { + return 0; + } + + TInt size = 0; + + // Calculate the time of the first frame included in the time interval + TInt64 firstFrameIndex = aStartTime.Int64() / frameDurationMicro; + TInt64 currentTime = firstFrameIndex * frameDurationMicro; + + while (currentTime + frameDurationMicro <= aEndTime.Int64()) // Make sure the whole frame fits inside the time interval + { + + TBool silence = ETrue; + TInt clipIndex = 0; + TInt overLappingClips = 0; + + for (TInt a = 0 ; a < iClipArray.Count() ; a++) + { + if (!iClipArray[a]->Muting()) + { + + if ((currentTime >= iClipArray[a]->iStartTime.Int64() + iClipArray[a]->iCutInTime.Int64()) && + (currentTime < iClipArray[a]->iStartTime.Int64() + iClipArray[a]->iCutOutTime.Int64())) + + { + silence = EFalse; + clipIndex = a; + overLappingClips++; + + } + } + } + + TInt frameSize = 0; + if (silence) + { + + // if there is no audio around "aTime", just return a silent frame length + + if (iProperties->iAudioType == EAudAAC_MPEG4) + { + + if (iProperties->iChannelMode == EAudSingleChannel) + { + frameSize = KSilentMonoAACFrameLenght; + } + else + { + frameSize = KSilentStereoAACFrameLenght; + } + } + else if (iProperties->iAudioType == EAudAMR) + { + + TInt KSilentFrameLen = 13; // AMR + frameSize = KSilentFrameLen; + + } + + size +=frameSize; + currentTime += frameDurationMicro; + continue; + + } + + + + // if not silent, estimate according to bitrate if transcoding + // if no transcoding is necessary, return the frame length of the original + // input clip + + // input clip is not transcoded if the original clip has the same + // audio properties as the output clip and no mixing is needed + + TAudFileProperties clipProp = iClipArray[clipIndex]->Info()->Properties(); + + TBool clipTranscoded = EFalse; + + if (clipProp.iAudioType != + iProperties->iAudioType || + clipProp.iSamplingRate != + iProperties->iSamplingRate || + clipProp.iChannelMode != + iProperties->iChannelMode) + { + clipTranscoded = ETrue; + } + + if (overLappingClips > 1) + { + clipTranscoded = ETrue; + } + + + if (clipTranscoded) + { + const TInt KBitrate = iProperties->iBitrate; + const TInt KBitsInByte = 8; + + TInt KByterate = KBitrate/KBitsInByte; + + TInt frameDurationMilli = 20; // AMR + + if (iProperties->iAudioType == EAudAAC_MPEG4) + { + + frameDurationMilli = ((1024*1000)/(iProperties->iSamplingRate)); + + } + + frameSize = (KByterate/(1000/frameDurationMilli)+1); + + } + else + { + + frameSize = clipProp.iFrameLen; + + } + + size +=frameSize; + currentTime += frameDurationMicro; + continue; + + } + + return size; + + } + +EXPORT_C TAudFileProperties CAudSong::OutputFileProperties() const + { + + return *iProperties; + } + + +EXPORT_C TBool CAudSong::GetMP4DecoderSpecificInfoLC(HBufC8*& aDecSpecInfo, TInt aMaxSize) const + { + + if (iClipArray.Count() == 0) + { + return EFalse; + } + + if (iProperties->iAudioType == EAudAAC_MPEG4) + + { + + int16 frameLen = 1024; + int32 sampleRate = iProperties->iSamplingRate; + uint8 profile = LC_OBJECT; + uint8 nChannels = 1; + uint8 decSpecInfo[16]; + int16 nConfigBytes; + + if (iProperties->iChannelMode == EAudStereo) + { + nChannels = 2; + } + + + //nConfigBytes = AACGetMP4ConfigInfo(&aacInfo, decSpecInfo, 16); + nConfigBytes = AACGetMP4ConfigInfo(sampleRate, profile, + nChannels, frameLen, decSpecInfo, aMaxSize); + + + if (nConfigBytes > 0) + { + + aDecSpecInfo = HBufC8::NewLC(nConfigBytes); + aDecSpecInfo->Des().Append(decSpecInfo, nConfigBytes); + + } + + return ETrue; + + } + else if (iProperties->iAudioType == EAudAMR) + { + aDecSpecInfo = HBufC8::NewLC(aMaxSize); + + const TUint8 frameDecSpecInfo[] = {0x14,0x08}; //the decoder specific + const TInt frameSize = 2; //constant as maximum size of decoderspecific info is 2 + + for (TInt a = 0 ; a < frameSize ; a++) + { + aDecSpecInfo->Des().Append(frameDecSpecInfo[a]); + } + + + return ETrue; + } + + else + { + return EFalse; + } + + + } + +EXPORT_C TBool CAudSong::GetTimeEstimateL(MAudTimeEstimateObserver& aObserver, + TAudType aAudType, + TInt aSamplingRate, + TChannelMode aChannelMode, + TInt aBitRate) + { + + + if (iClipArray.Count() == 0) + { + return EFalse; + } + + if (SetOutputFileFormat(aAudType, aSamplingRate, aChannelMode, aBitRate)) + { + return iProcessOperation->GetTimeEstimateL(aObserver); + + } + else + { + return EFalse; + } + + + } + +EXPORT_C TTimeIntervalMicroSeconds CAudSong::GetTimeEstimateL() + { + TAudFileProperties prop; + TInt64 estimatedTime = TInt64(0); + TReal complexityFactor = 0.0; + TInt a; + + for (a = 0; a < iClipArray.Count() ; a++) + { + complexityFactor = 0.0; + + prop = iClipArray[a]->Info()->Properties(); + if ( iClipArray[a]->Muting() ) + { + // the clip is muted + complexityFactor = KAEDMutingComplFactor; + } + else if ( (prop.iAudioType != iProperties->iAudioType ) + || (prop.iChannelMode != iProperties->iChannelMode ) + || (prop.iSamplingRate != iProperties->iSamplingRate ) ) + { + // need transcoding + + // decoding + switch (prop.iAudioType) + { + case EAudAMR : + { + // AMR decoding + complexityFactor = KAEDAMRDecComplFactor; + } + break; + case EAudAAC_MPEG4 : + { + // AAC decoding + complexityFactor = KAEDAACDecComplFactor; + } + break; + case EAudAMRWB : + { + // AMR-WB decoding + complexityFactor = KAEDAMRWBDecComplFactor; + } + break; + case EAudMP3 : + { + // MP3 decoding + complexityFactor = KAEDMP3DecComplFactor; + } + break; + default: + { + //EAudWAV + complexityFactor = KAEDWavDecComplFactor; + } + } + if ( prop.iChannelMode == EAudStereo ) + { + complexityFactor += KAEDAACStereoDecAddComplFactor; + } + if ( prop.iSamplingRate > 8000 ) + { + complexityFactor *= prop.iSamplingRate/16000; + } + + + // encoding + if (iProperties->iAudioType == EAudAMR) + { + // AMR encoding + complexityFactor += KAEDAMREncComplFactor; + } + else + { + // AAC encoding + complexityFactor += KAEDAACEncComplFactor; + if ( iProperties->iChannelMode == EAudStereo ) + { + complexityFactor += KAEDAACStereoEncAddComplFactor; + } + complexityFactor *= iProperties->iSamplingRate/16000; + } + + + } + else if (iClipArray[a]->DynamicLevelMarkCount() > 0) + { + // need bitstream processing (level control etc) + complexityFactor = KAEDBitstreamProcComplFactor; + } + else + { + // just passing through + complexityFactor = KAEDPassThroughComplFactor; + } + + + + estimatedTime = estimatedTime + TInt64(complexityFactor * I64INT(iClipArray[a]->EditedDuration().Int64())); + } + + return estimatedTime; + } + +EXPORT_C TInt CAudSong::GetFrameDurationMicro() + { + TInt frameDurationMicro = 20000; // AMR + + if (iProperties->iAudioType == EAudAAC_MPEG4) + { + frameDurationMicro = ((1024 * 1000) / iProperties->iSamplingRate) * 1000; + } + + return frameDurationMicro; + } + + +EXPORT_C TInt CAudSong::ClipCount(TInt aTrackIndex) const + { + + + if (aTrackIndex == KAllTrackIndices) + { + return iClipArray.Count(); + + } + + TInt amount = 0; + for (TInt a = 0; a < iClipArray.Count() ; a++) + { + if (iClipArray[a]->TrackIndex() == aTrackIndex) amount++; + + } + + return amount; + + } + + +EXPORT_C CAudClip* CAudSong::Clip(TInt aIndex, TInt aTrackIndex) const + { + + if (aTrackIndex == KAllTrackIndices) + { + return iClipArray[aIndex]; + } + + + TInt index = 0; + TInt a = 0; + TBool found = EFalse; + + if (aTrackIndex == KAllTrackIndices) + { + return iClipArray[aIndex]; + } + + for (a = 0; a < iClipArray.Count() ; a++) + { + + if (iClipArray[a]->TrackIndex() == aTrackIndex) index++; + + if (index == aIndex+1) + { + found = ETrue; + break; + } + + + } + + if (found) + { + return iClipArray[a]; + } + else + { + TAudPanic::Panic(TAudPanic::EAudioClipIllegalIndex); + } + return NULL; + } + + + +EXPORT_C void CAudSong::AddClipL(const TDesC& aFileName, + TTimeIntervalMicroSeconds aStartTime, TInt aTrackIndex, + TTimeIntervalMicroSeconds aCutInTime, + TTimeIntervalMicroSeconds aCutOutTime) + { + + PRINT((_L("CAudSong::AddClipL in"))); + if (iAddOperation->iClip != 0) + { + TAudPanic::Panic(TAudPanic::ESongAddOperationAlreadyRunning); + } + if (iProcessOperation->iProcessor != 0 ) + { + TAudPanic::Panic(TAudPanic::ESongProcessingOperationAlreadyRunning); + } + + + iAddOperation->iClip = CAudClip::NewL(this, aFileName, aStartTime, *iAddOperation, aTrackIndex); + iAddOperation->iClip->iCutInTime = aCutInTime; + iAddOperation->iClip->iCutOutTime = aCutOutTime; + + PRINT((_L("CAudSong::AddClipL out"))); + + } + + +EXPORT_C void CAudSong::RemoveClip(TInt aIndex, TInt aTrackIndex) + { + PRINT((_L("CAudSong::RemoveClip in"))); + + TInt index = -1; + TInt a = 0; + TBool found = EFalse; + + for (a = 0; a < iClipArray.Count() ; a++) + { + + + if (iClipArray[a]->TrackIndex() == aTrackIndex) index++; + + if (index == aIndex) + { + found = ETrue; + break; + } + + } + + + if (found) + { + + CAudClip* clip = iClipArray[a]; + iClipArray.Remove(a); + delete clip; + UpdateClipIndexes(); + FireClipRemoved(this, aIndex, aTrackIndex); + } + else + { + TAudPanic::Panic(TAudPanic::EAudioClipIllegalIndex); + } + + PRINT((_L("CAudSong::RemoveClip out"))); + + } + + +EXPORT_C TBool CAudSong::SetOutputFileFormat(TAudType aAudType, + TInt aSamplingRate, + TChannelMode aChannelMode, + TInt aBitRate) + { + PRINT((_L("CAudSong::SetOutputFileFormat in"))); + + // allow both EAudAAC_MPEG2 and EAudAAC_MPEG4 + // as inpyt type, but consider all AAC_ MPEG as mpeg4 + + if (aAudType == EAudAAC_MPEG2) + { + aAudType = EAudAAC_MPEG4; + } + + // make sure the given parameters are correct + + if (aBitRate == KAudBitRateDefault) + { + // the defaut bitrates: + PRINT((_L("CAudSong::SetOutputFileFormat use default bitrate"))); + if (aAudType == EAudAMR) + { + aBitRate = KAedBitRateAMR; + } + else if (aAudType == EAudAAC_MPEG4) + { + if (aSamplingRate == KAedSampleRate16kHz) + { + aBitRate = KAedBitRateAAC16kHz; + } + else + { + aBitRate = KAedBitRateAAC48kHz; + } + } + } + + if (aAudType == EAudAAC_MPEG4) + { + + iProperties->iAudioType = EAudAAC_MPEG4; + iProperties->iAACObjectType = EAudAACObjectTypeLC; + + TInt channels = (aChannelMode == EAudSingleChannel) ? 1 : 2; + + // legal sampling rates are 16000 and 48000 Hz + if (aSamplingRate == KAedSampleRate16kHz) + { + if (aBitRate < KAedAACMinBitRateMultiplier * KAedSampleRate16kHz * channels || + aBitRate > KAedAACMaxBitRateMultiplier * KAedSampleRate16kHz * channels) + { + // illegal bitrate + PRINT((_L("CAudSong::SetOutputFileFormat out, unsupported bitrate given"))); + return EFalse; + } + else + { + iProperties->iSamplingRate = aSamplingRate; + iProperties->iBitrate = aBitRate; + iProperties->iChannelMode = aChannelMode; + } + } + else if (aSamplingRate == KAedSampleRate48kHz) + { + if (aBitRate < KAedAACMinBitRateMultiplier * KAedSampleRate48kHz * channels || + aBitRate > KAedAACMaxBitRateMultiplier * KAedSampleRate48kHz * channels) + { + // illegal bitrate + PRINT((_L("CAudSong::SetOutputFileFormat out, unsupported bitrate given"))); + return EFalse; + } + else + { + iProperties->iSamplingRate = aSamplingRate; + iProperties->iBitrate = aBitRate; + iProperties->iChannelMode = aChannelMode; + } + } + else + { + PRINT((_L("CAudSong::SetOutputFileFormat out, unsupported sampling rate given"))); + return EFalse; + } + + } + + + else if (aAudType == EAudAMR) + { + + iProperties->iAudioType = EAudAMR; + // for AMR the bitrate is always set to 12200 and sampling rate to 8000 + iProperties->iSamplingRate = KAedSampleRate8kHz; + iProperties->iBitrate = KAedBitRateAMR; + iProperties->iChannelMode = EAudSingleChannel; + + } + + else + { + PRINT((_L("CAudSong::SetOutputFileFormat out, unsupported output format given"))); + return EFalse; + } + + + PRINT((_L("CAudSong::SetOutputFileFormat out"))); + return ETrue; + } + +EXPORT_C TBool CAudSong::AreOutputPropertiesSupported(const TAudFileProperties& aProperties ) + { + if ( ( aProperties.iAudioType == EAudAAC_MPEG4 ) + && ((aProperties.iSamplingRate == KAedSampleRate16kHz) + || (aProperties.iSamplingRate == KAedSampleRate48kHz))) + { + return ETrue; + } + else if ( (aProperties.iAudioType == EAudAMR) + && (aProperties.iSamplingRate == KAedSampleRate8kHz)) + { + return ETrue; + } + else + { + return EFalse; + } + } + + +EXPORT_C TBool CAudSong::SyncStartProcessingL() + { + PRINT((_L("CAudSong::SyncStartProcessingL"))); + return iProcessOperation->StartSyncProcL(); + } + +EXPORT_C TBool CAudSong::SyncProcessFrameL(HBufC8*& aFrame, TInt& aProgress, + TTimeIntervalMicroSeconds& aDuration) + { + PRINT((_L("CAudSong::SyncProcessFrameL in"))); + + aFrame = 0; + TBool ret = iProcessOperation->ProcessSyncPieceL(aFrame, aProgress, aDuration); + +#ifdef _WRITE_OUTPUT_TO_FILE_ + + + if (!ret) + { + + if (iFileOpen) + { + + + + TBuf8<32> mes; + mes.Append(_L8("aProgress: ")); + mes.AppendNum(aProgress); + mes.Append(_L8("aDuration: ")); + mes.AppendNum(I64INT(aDuration.Int64()/1000)); + mes.Append(_L8("\n")); + + + iTextFile.Write(mes); + + + if (iProperties->iAudioType == EAudAMR) + { + iAudioFile.Write(aFrame->Des()); + + } + else + { + TBuf8<7> adtsHeader; + + ProcTools::GenerateADTSHeaderL(adtsHeader, aFrame->Size(), *iProperties); + iAudioFile.Write(adtsHeader); + iAudioFile.Write(aFrame->Des()); + + } + + } + + } + +#endif + + PRINT((_L("CAudSong::SyncProcessFrameL out"))); + return ret; + + } + +EXPORT_C void CAudSong::SyncCancelProcess() + { + + iProcessOperation->Cancel(); + + } + + +EXPORT_C void CAudSong::Reset(TBool aNotify) + { + iSongDurationManuallySet = EFalse; + + iDynamicLevelMarkArray.ResetAndDestroy(); + iClipArray.ResetAndDestroy(); + + if (aNotify) + { + FireSongReseted(*this); + } + } + +EXPORT_C TBool CAudSong::SetDuration(TTimeIntervalMicroSeconds aDuration) + { + + if (aDuration.Int64() > 0) + { + iSongDuration = aDuration; + iSongDurationManuallySet = ETrue; + return ETrue; + } + + return EFalse; + } + + +EXPORT_C void CAudSong::RegisterSongObserverL(MAudSongObserver* aObserver) + { + for (TInt i = 0; i < iObserverArray.Count(); i++) + { + if (iObserverArray[i] == aObserver) + { + TAudPanic::Panic(TAudPanic::ESongObserverAlreadyRegistered); + } + } + + User::LeaveIfError(iObserverArray.Append(aObserver)); + } + + +EXPORT_C void CAudSong::UnregisterSongObserver(MAudSongObserver* aObserver) + { + for (TInt i = 0; i < iObserverArray.Count(); i++) + { + if (iObserverArray[i] == aObserver) + { + iObserverArray.Remove(i); + return; + } + } + + TAudPanic::Panic(TAudPanic::ESongObserverNotRegistered); + } + + +void CAudSong::UpdateClipIndexes() + { + + for (TInt i = 0; i < iClipArray.Count() ; i++) + { + + iClipArray[i]->iIndex = Index2IndexOnTrack(i); + + } + + } + +void CAudSong::UpdateClipArray() + { + + TLinearOrder order(CAudClip::Compare); + iClipArray.Sort(order); + + + } + +TInt CAudSong::Index2IndexOnTrack(TInt aIndex) + { + + if (aIndex > iClipArray.Count()) + { + TAudPanic::Panic(TAudPanic::EInternal); + } + TInt indexOnTrack = 0; + TInt trackIndex = iClipArray[aIndex]->TrackIndex(); + + for (TInt a = 0; a < aIndex ; a++) + { + + if (iClipArray[a]->TrackIndex() == trackIndex) + { + indexOnTrack++; + } + + } + return indexOnTrack; + } + +TInt CAudSong::FindClipIndexOnSong(const CAudClip* aClip) const + { + + for (TInt index = 0 ; index < iClipArray.Count() ; index++) + { + if (iClipArray[index] == aClip) + { + return index; + } + } + + // if the clip is not in the array... + TAudPanic::Panic(TAudPanic::EInternal); + return 0; + + } + +void CAudSong::FireClipAdded(CAudSong* aSong, CAudClip* aClip, TInt aIndex, TInt aTrackIndex) + { + + for (TInt i = 0; i < iObserverArray.Count(); i++) + { + iObserverArray[i]->NotifyClipAdded(*aSong, *aClip, aIndex, aTrackIndex); + } + } + +void CAudSong::FireClipAddingFailed(CAudSong* aSong, TInt aError, TInt aTrackIndex) + { + + for (TInt i = 0; i < iObserverArray.Count(); i++) + { + iObserverArray[i]->NotifyClipAddingFailed(*aSong, aError, aTrackIndex); + } + } + +void CAudSong::FireClipRemoved(CAudSong* aSong, TInt aIndex, TInt aTrackIndex) + { + + for (TInt i = 0; i < iObserverArray.Count(); i++) + { + iObserverArray[i]->NotifyClipRemoved(*aSong, aIndex, aTrackIndex); + } + + } + +void CAudSong::FireClipIndicesChanged(CAudSong* aSong, TInt aOldIndex, + TInt aNewIndex, TInt aTrackIndex) + { + + for (TInt i = 0; i < iObserverArray.Count(); i++) + { + iObserverArray[i]->NotifyClipIndicesChanged(*aSong, aOldIndex, aNewIndex, aTrackIndex); + } + } + +void CAudSong::FireClipTimingsChanged(CAudSong* aSong, CAudClip* aClip) + { + + + for (TInt i = 0; i < iObserverArray.Count(); i++) + { + iObserverArray[i]->NotifyClipTimingsChanged(*aSong, *aClip); + } + + } + + +void CAudSong::FireDynamicLevelMarkInserted(CAudClip& aClip, + TAudDynamicLevelMark& aMark, + TInt aIndex) + { + + for (TInt i = 0; i < iObserverArray.Count(); i++) + { + iObserverArray[i]->NotifyDynamicLevelMarkInserted(aClip, aMark, aIndex); + } + + + } + +void CAudSong::FireDynamicLevelMarkRemoved(CAudClip& aClip, TInt aIndex) + { + + for (TInt i = 0; i < iObserverArray.Count(); i++) + { + iObserverArray[i]->NotifyDynamicLevelMarkRemoved(aClip, aIndex); + } + + } + +void CAudSong::FireSongReseted(CAudSong& aSong) + { + + for (TInt i = 0; i < iObserverArray.Count(); i++) + { + iObserverArray[i]->NotifySongReseted(aSong); + } + } + +void CAudSong::FireClipReseted(CAudClip& aClip) + { + + for (TInt i = 0; i < iObserverArray.Count(); i++) + { + iObserverArray[i]->NotifyClipReseted(aClip); + } + } + + + +CAudSongProcessOperation* CAudSongProcessOperation::NewL(CAudSong* aSong) + { + CAudSongProcessOperation* self = + new (ELeave) CAudSongProcessOperation(aSong); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + + +CAudSongProcessOperation::CAudSongProcessOperation(CAudSong* aSong) +: iSong(aSong), iObserver(0), iProcessor(0) + { + + } + + +void CAudSongProcessOperation::ConstructL() + { + } + +CAudSongProcessOperation::~CAudSongProcessOperation() + { + + if (iProcessor != 0) + { + delete iProcessor; + iProcessor = 0; + + } + + } + + + +void CAudSongProcessOperation::NotifyAudioProcessingStartedL() + { + if (iObserver != 0) + iObserver->NotifyAudioProcessingStartedL(*iSong); + + } +void CAudSongProcessOperation::NotifyAudioProcessingProgressed(TInt aPercentage) + { + if (iObserver != 0) + iObserver->NotifyAudioProcessingProgressed(*iSong, aPercentage); + + } +void CAudSongProcessOperation::NotifyAudioProcessingCompleted(TInt aError) + { + + delete iProcessor; + iProcessor = 0; + + MAudSongProcessingObserver* observer = iObserver; + iObserver = 0; + if (observer != 0) + { + observer->NotifyAudioProcessingProgressed(*iSong, 100); + observer->NotifyAudioProcessingCompleted(*iSong, aError); + } + } + +void CAudSongProcessOperation::NotifyTimeEstimateReady(TInt64 aTimeEstimate) + { + + delete iProcessor; + iProcessor = 0; + + MAudTimeEstimateObserver* observer = iTEObserver; + iTEObserver = 0; + + if (observer != 0) + { + observer->NotifyTimeEstimateReady(aTimeEstimate); + } + } + + +TBool CAudSongProcessOperation::StartSyncProcL() + { + + if (iProcessor != 0) + { + User::Leave(KErrNotReady); + } + + CAudProcessor* processor = CAudProcessor::NewLC(); + TBool ret = processor->StartSyncProcessingL(iSong); + CleanupStack::Pop(processor); + iProcessor = processor; + + return ret; + + } + +TBool CAudSongProcessOperation::ProcessSyncPieceL(HBufC8*& aFrame, TInt& aProgress, + TTimeIntervalMicroSeconds& aDuration) + { + TBool ret = iProcessor->ProcessSyncPieceL(aFrame, aProgress, aDuration); + if (!ret) return EFalse; + else + { + delete iProcessor; + iProcessor = 0; + return ETrue; + + } + + } + + +void CAudSongProcessOperation::Cancel() + { + + if (iProcessor == 0) + { + TAudPanic::Panic(TAudPanic::ESongProcessingOperationNotRunning); + } + else + { + iProcessor->CancelProcessing(*this); + } + } + +TBool CAudSongProcessOperation::GetTimeEstimateL(MAudTimeEstimateObserver& aTEObserver) + { + + + + if (iProcessor != 0) + { + User::Leave(KErrNotReady); + } + iTEObserver = &aTEObserver; + + CAudProcessor* processor = CAudProcessor::NewLC(); + + + TBool ret = processor->StartTimeEstimateL(iSong, *this); + CleanupStack::Pop(processor); + iProcessor = processor; + + return ret; + + } + + +CAudSongAddClipOperation* CAudSongAddClipOperation::NewL(CAudSong* aSong) + { + CAudSongAddClipOperation* self = + new (ELeave) CAudSongAddClipOperation(aSong); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + + +CAudSongAddClipOperation::CAudSongAddClipOperation(CAudSong* aSong) + : iSong(aSong), iClip(0) + { + } + + +void CAudSongAddClipOperation::ConstructL() + { + } + + +CAudSongAddClipOperation::~CAudSongAddClipOperation() + { + if (iClip) + { + delete iClip; + iClip = 0; + } + + } + + +void CAudSongAddClipOperation::NotifyClipInfoReady(CAudClipInfo& /*aInfo*/, + TInt aError) + { + + + iError = aError; + CompleteAddClipOperation(); + + } + + +void CAudSongAddClipOperation::CompleteAddClipOperation() + { + PRINT((_L("CAudSongAddClipOperation::CompleteAddClipOperation in"))); + + + if (iError != KErrNone) + { + TInt trackIndex = iClip->TrackIndex(); + delete iClip; + iClip = 0; + iSong->FireClipAddingFailed(iSong, iError, trackIndex); + PRINT((_L("CAudSong::CompleteAddClipOperation failed, out"))); + return; + } + else + { + + TAudFileProperties info = iClip->iInfo->Properties(); + + if (iSong->iClipArray.Count() > 0) + { + if (!(info.isCompatible(iSong->iClipArray[0]->Info()->Properties()))) + { + TInt trackIndex = iClip->TrackIndex(); + + delete iClip; + iClip = 0; + iSong->FireClipAddingFailed(iSong, KErrNotSupported, trackIndex); + PRINT((_L("CAudSong::CompleteAddClipOperation failed, out"))); + return; + } + } + + if (iClip->CutOutTime() == TTimeIntervalMicroSeconds(KClipEndTime)) + { + + iClip->iCutOutTime = info.iDuration; + } + + + TInt err = KErrNone; + + TBool added = EFalse; + + // insert clips so that they are always sorted by start time + TInt index = 0; + for (index = 0 ; index < iSong->iClipArray.Count() ; index++) + { + if (iSong->iClipArray[index]->StartTime() > iClip->StartTime()) + { + err = iSong->iClipArray.Insert(iClip, index); + added = ETrue; + break; + } + } + if (!added) + { + index = iSong->iClipArray.Count(); + err = iSong->iClipArray.Insert(iClip, index); + if (err != KErrNone) + { + TInt trackIndex = iClip->TrackIndex(); + delete iClip; + iClip = 0; + iSong->FireClipAddingFailed(iSong, KErrGeneral, trackIndex); + PRINT((_L("CAudSong::CompleteAddClipOperation failed, out"))); + return; + } + + } + iClip->iIndex = iSong->Index2IndexOnTrack(index); + + if (err != KErrNone) + { + TInt trackIndex = iClip->TrackIndex(); + + delete iClip; + iClip = 0; + iSong->FireClipAddingFailed(iSong, err, trackIndex); + } + else + { + iSong->UpdateClipIndexes(); + CAudClip* clip = iClip; + iClip = 0; + + + if (clip->EndTime() > iSong->iSongDuration) + { + iSong->iSongDuration = clip->EndTime(); + } + + + iSong->FireClipAdded(iSong, clip, clip->iIndex, clip->iTrackIndex); + + + } + } + PRINT((_L("CAudSongAddClipOperation::CompleteAddClipOperation out"))); + } + +EXPORT_C void CAudSong::AddClipL(RFile* aFileHandle, + TTimeIntervalMicroSeconds aStartTime, TInt aTrackIndex, + TTimeIntervalMicroSeconds aCutInTime, + TTimeIntervalMicroSeconds aCutOutTime) + { + + PRINT((_L("CAudSong::AddClipL in"))); + if (iAddOperation->iClip != 0) + { + TAudPanic::Panic(TAudPanic::ESongAddOperationAlreadyRunning); + } + if (iProcessOperation->iProcessor != 0 ) + { + TAudPanic::Panic(TAudPanic::ESongProcessingOperationAlreadyRunning); + } + + iAddOperation->iClip = CAudClip::NewL(this, aFileHandle, aStartTime, *iAddOperation, aTrackIndex); + iAddOperation->iClip->iCutInTime = aCutInTime; + iAddOperation->iClip->iCutOutTime = aCutOutTime; + + PRINT((_L("CAudSong::AddClipL out"))); + + } + + +