videoeditorengine/audioeditorengine/src/AudSong.cpp
changeset 0 951a5db380a0
--- /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 <e32base.h>
+
+// Debug print macro
+#if defined _DEBUG 
+#include <e32svr.h>
+#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<CAudClip> 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")));
+
+    }
+
+
+