videoeditorengine/audioeditorengine/inc/AudSong.h
author Mikael Laine <mikael.laine@ixonos.com>
Fri, 29 Jan 2010 14:08:33 +0200
changeset 0 951a5db380a0
permissions -rw-r--r--
Committing the Video Editor package under the Eclipse Public License

/*
* 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:  
*
*/




#ifndef __AUDSONG_H__
#define __AUDSONG_H__


#include <e32base.h>
#include <f32file.h>
#include <e32std.h>

#include "AudCommon.h"
#include "AudObservers.h"


// define _WRITE_OUTPUT_TO_FILE_ if you want audio engine to write its output to a file
//#define _WRITE_OUTPUT_TO_FILE_;


/*
*    Forward declarations.
*/


class MAudVisualizationObserver;
class MAudSongProcessingObserver;
class CAudSongProcessOperation;
class CAudSongVisualizationOperation;
class MAudSongObserver;
class CAudClipInfo;
class MAudClipInfoObserver;
class CAudSongAddClipOperation;
class CAudProcessor;

// constants that represent special parameter values

// clip end time (used when setting cutOut-times)
const TInt KClipEndTime = -1;

// KAllTrackIndices represents all tracks in ClipCount()-function
const TInt KAllTrackIndices = -1;

// Let audio engine to decide the bitrate
const TInt KAudBitRateDefault = -1;


/**
* Audio song, which consists of zero or more audio clips
*
* @see  CAudClip
*/
class CAudSong : public CBase
    {
public:
    /* Constructors. */
    
    /**
    * Constructs a new empty CAudSong object. May leave if no resources are available.
    * 
    * Possible leave codes:
    *    - <code>KErrNoMemory</code> if memory allocation fails
    *
    * @param aFs  file server session to use to lock the audio
    *             clip files of the new song; or NULL to not to lock the files
    * @return  pointer to a new CAudSong instance
    */
    IMPORT_C static CAudSong* NewL(RFs *aFs);
    
    /**
    * Constructs a new empty CAudSong object and leaves the object in the cleanup stack.
    * 
    * Possible leave codes:
    *    - <code>KErrNoMemory</code> if memory allocation fails
    * 
    * @param aFs  file server session to use to lock the audio
    *             clip files of the new song; or NULL to not to lock the files
    * @return  pointer to a new CAudSong instance
    */
    IMPORT_C static CAudSong* NewLC(RFs *aFs);
    
    /**
    * Destroys the object and releases all resources.
    */
    IMPORT_C virtual ~CAudSong();
    
    
    /* Property methods. */
    
    /**
    * Returns an estimate of the total size of this song.
    * 
    * @return  size estimate in bytes
    */
    IMPORT_C TInt GetSizeEstimateL() const;
    
    /**
    * Returns an estimate of the size of this song between the given time interval.
    * 
    * @param aStartTime Beginning of the time interval
    * @param aEndTime End of the time interval
    * @return size estimate in bytes
    */
    IMPORT_C TInt GetFrameSizeEstimateL(TTimeIntervalMicroSeconds aStartTime, 
                                        TTimeIntervalMicroSeconds aEndTime) const;
    
    /**
    * Returns the properties of this song.
    * 
    * @return  output file properties
    */
    IMPORT_C TAudFileProperties OutputFileProperties() const;
    
    /**
    *
    * Generates decoder specific info needed for MP4
    * Caller is responsible for releasing aDecSpecInfo in the case ETrue is returned
    *
    * @param aMaxSize    maximum aDecSpecInfo size allowed    
    *
    */
    IMPORT_C TBool GetMP4DecoderSpecificInfoLC(HBufC8*& aDecSpecInfo, TInt aMaxSize) const;

    /**
    * Get processing time estimate based on trial. Asynchronous version, requires observer.
    *
    */
    IMPORT_C TBool GetTimeEstimateL(MAudTimeEstimateObserver& aObserver,
                                    TAudType aAudType,
                                    TInt aSamplingRate,
                                    TChannelMode aChannelMode,
                                    TInt aBitRate = -1);
                                    
    /**
    * Get processing time estimate based on hardcoded constants. Synchronous version.
    *
    * @return   estimated processing time for the song
    */
    IMPORT_C TTimeIntervalMicroSeconds GetTimeEstimateL();
    
    /**
    * Get the frame duration in microseconds. 
    *
    * @return   frame duration in microseconds
    */
    IMPORT_C TInt GetFrameDurationMicro();


    /* Audio clip management methods. */
    
    /**
    * Returns the number of audio clips in this song on a certain track.
    *
    * @param   aTrackIndex track index
    *
    * @return  number of audio clips on a defined track
    */
    IMPORT_C TInt ClipCount(TInt aTrackIndex = 0) const;
    
    /** 
    * Returns the audio clip at the specified index. 
    * Panics with code <code>EAudioClipIllegalIndex</code> if the clip index is invalid.
    *
    * @param aIndex            index of the clip on the certain track
    * @param aTrackIndex    index of the track
    *
    * @return  clip at the specified index.
    */    
    IMPORT_C CAudClip* Clip(TInt aIndex, TInt aTrackIndex = 0) const;
    
    /** 
    * Adds the specified audio clip to this song. Asynchronous operation
    * CAudSongObserver::NotifyClipAdded or CAudSongObserver::NotifyClipAddingFailed
    * is called once the operation has completed.
    *
    * Possible leave codes:
    *    - <code>KErrNoMemory</code> if memory allocation fails
    *    - <code>KErrNotSupported</code> if audio format is not supported
    *
    * @param aFileName   file name of the clip to add
    * @param aStartTime  start time of the clip in song timebase
    * @param aTrackIndex track index. Used to categorize clips.
    */
    IMPORT_C void AddClipL(const TDesC& aFileName,
        TTimeIntervalMicroSeconds aStartTime, TInt aTrackIndex = 0,
        TTimeIntervalMicroSeconds aCutInTime = TTimeIntervalMicroSeconds(0),
        TTimeIntervalMicroSeconds aCutOutTime = TTimeIntervalMicroSeconds(KClipEndTime));
    
    
    /** 
    * Removes the audio clip at the specified index from this song.
    * Panics with code <code>USER-130</code> if the clip index is invalid.
    *
    * @param aIndex  index of the clip to be removed
    * @param aTrackIndex track index
    */
    IMPORT_C void RemoveClip(TInt aIndex, TInt aTrackIndex = 0);
    
    /** 
    * Removes all audio clips and clears all effects
    *
    * @param aNotify ETrue if observer should be notified
    */
    IMPORT_C void Reset(TBool aNotify);

    /**
    *
    * Sets the duration of the output clip
    * If necessary, silence is generated in the end
    *
    * @param    aDuration    output clip length in microseconds
    * 
    * @return    ETrue if a new duration was set, EFalse otherwise
    *
    */
    IMPORT_C TBool SetDuration(TTimeIntervalMicroSeconds aDuration);

    
    /* Processing methods. */
    
    
    /**
    * Removes a dynamic level mark in a song. 
    * Panics with code <code>EAudioClipIllegalIndex</code> 
    * if the clip index is invalid.
    *
    * @param    aIndex index of the removed mark in this song
    * @return  ETrue if mark was removed, EFalse otherwise
    */
    IMPORT_C TBool RemoveDynamicLevelMark(TInt aIndex);
    
    
    /**
    * Sets an output file format
    *
    * NOTE: only the following combinations are allowed: 
    * AMR: single channel, 8000 Hz, 12000 kbps
    *
    * AAC/16kHz mono/stereo 
    * AAC/48kHz mono/stereo
    *
    * @return   ETrue if format was successfully changed, 
    *             EFalse if format cannot be set
    */
    IMPORT_C TBool SetOutputFileFormat(TAudType aAudType,
                                        TInt aSamplingRate,
                                        TChannelMode aChannelMode,
                                        TInt aBitRate = KAudBitRateDefault);
    
    /**
    * Checks if given properties are supported
    *
    *
    * @param    aProperties audio properties
    * @return   ETrue if properties are supported
    *           EFalse if not
    */
    IMPORT_C TBool AreOutputPropertiesSupported(const TAudFileProperties& aProperties );
    
    
    /*
    * Processing methods
    */

    /**
    * Starts a synchronous audio processing operation. After calling this function
    * the current song can be processed frame by frame by calling ProcessPieceL-function
    * Panics with 
    * <code>TAudPanic::ESongEmpty</code> if there are no clips 
    * in the song.
    *     
    */
    IMPORT_C TBool SyncStartProcessingL();
    
    /**
    * Processes synchronously next audio frame and passes it to the caller. 
    * If a processing operation has not been started, panic 
    * <code>TAudPanic::ESongProcessingNotRunning</code> is raised.
    *
    * Possibly leave codes:
    *    - <code>KErrNoMemory</code> if memory allocation fails
    *
    * NOTE: This function allocates memory and the caller is responsible for
    * releasing it.
    *
    * @param aFrame        pointer to a processed audio frame. Has to be deleted
    *                    when not needed anymore.
    * @param aDuration    Duration of processed audio frame in microseconds 
    *                    after decoding
    * 
    * @return ETrue        Processing operation completed, no more frames to be processed. 
    *                    No memory allocated.
    *          EFalse    Processing operation not completed. Last processed frame stored
    *                    in <code>aFrame</code>. Memory allocated for the processed frame
    *                      
    */
    IMPORT_C TBool SyncProcessFrameL(HBufC8*& aFrame, TInt& aProgress, 
                                TTimeIntervalMicroSeconds& aDuration);


    /**
    * Cancels the processing operation. Used for only synchronous processing 
    * operations. If an operation is not running, 
    * panic <code>TAudPanic::ESongProcessingNotRunning</code> is raised
    */
    IMPORT_C void SyncCancelProcess();


    /* Observer methods. */

    /**
     * Registers a song observer. Panics with panic code 
     * <code>ESongObserverAlreadyRegistered</code> if the song observer is 
     * already registered.
     *
     * @param aObserver  observer that will receive the events
     */
    IMPORT_C void RegisterSongObserverL(MAudSongObserver* aObserver);

    /**
     * Unregisters a song observer. Panics with panic code 
     * <code>ESongObserverNotRegistered</code> if the song observer is not registered.
     *
     * @param aObserver  observer to be unregistered
     */
    IMPORT_C void UnregisterSongObserver(MAudSongObserver* aObserver);
    
    
    /** 
    * Adds the specified audio clip to this song. Asynchronous operation
    * CAudSongObserver::NotifyClipAdded or CAudSongObserver::NotifyClipAddingFailed
    * is called once the operation has completed.
    *
    * Possible leave codes:
    *    - <code>KErrNoMemory</code> if memory allocation fails
    *    - <code>KErrNotSupported</code> if audio format is not supported
    *
    * @param aFileHandle file handle of the clip to add
    * @param aStartTime  start time of the clip in song timebase
    * @param aTrackIndex track index. Used to categorize clips.
    */
    IMPORT_C void AddClipL(RFile* aFileHandle,
        TTimeIntervalMicroSeconds aStartTime, TInt aTrackIndex = 0,
        TTimeIntervalMicroSeconds aCutInTime = TTimeIntervalMicroSeconds(0),
        TTimeIntervalMicroSeconds aCutOutTime = TTimeIntervalMicroSeconds(KClipEndTime));


private:


    // C++ constructor
    CAudSong(RFs *aFs);

    // functions for keeping clip indexes and arrays up to date
    void UpdateClipIndexes();
    void UpdateClipArray();

    /**
    * Returns a track domain clip index
    * of the clip whose song doman index is <code>aIndex</code>
    */
    TInt Index2IndexOnTrack(TInt aIndex);

    /*
    * Returns a song domain clip index
    */
    TInt FindClipIndexOnSong(const CAudClip* aClip) const;
    
    /*
    * ConstructL
    */
    
    void ConstructL();

private:
    
    // Member variables
    
    // File server session.
    RFs* iFs;
    // Audio clip array.
    RPointerArray<CAudClip> iClipArray;
    
    // Marks used for manual level controlling
    RPointerArray<TAudDynamicLevelMark> iDynamicLevelMarkArray;
    
    // Properties of the output file.
    TAudFileProperties* iProperties;
    
    // Duration of the song
    // if iSongDuration is greater than the cut out time of the last output clip,
    // silence is generated in the end
    TTimeIntervalMicroSeconds iSongDuration;
    
    // a flag to indicate whether the user has set the duration manually
    // if not, the duration is the cutOutTime of the last input clip
    TBool iSongDurationManuallySet;

    // Observer array of the song class.
    RPointerArray<MAudSongObserver> iObserverArray;
    
    // Normalizing of this audio clip.
    // If ETrue, the song as a whole is to be normalized
    TBool iNormalize;
    
    // process operation owned by this
    CAudSongProcessOperation* iProcessOperation;
    
    // clip adding operation owned by this
    CAudSongAddClipOperation* iAddOperation;
    
    // song visualization operation owned by this
    CAudSongVisualizationOperation* iVisualizationOperation;
    
    
private:

    // Notifications to fire callbacks to all registered listeners -------->
    
    void FireClipAdded(CAudSong* aSong, CAudClip* aClip, TInt aIndex, TInt aTrackIndex);
    
    void FireClipAddingFailed(CAudSong* aSong, TInt aError, TInt aTrackIndex);

    void FireClipRemoved(CAudSong* aSong, TInt aIndex, TInt aTrackIndex);

    void FireClipIndicesChanged(CAudSong* aSong, TInt aOldIndex, 
                                     TInt aNewIndex, TInt aTrackIndex);

    void FireClipTimingsChanged(CAudSong* aSong, CAudClip* aClip);

    void FireDynamicLevelMarkInserted(CAudSong& aSong, 
        TAudDynamicLevelMark& aMark, 
        TInt aIndex);
    
    void FireDynamicLevelMarkInserted(CAudClip& aClip, 
        TAudDynamicLevelMark& aMark, 
        TInt aIndex);

    void FireDynamicLevelMarkRemoved(CAudSong& aSong, TInt aIndex);
    void FireDynamicLevelMarkRemoved(CAudClip& aClip, TInt aIndex);
    void FireSongReseted(CAudSong& aSong);
    void FireClipReseted(CAudClip& aClip);

    // <------------ Notifications to fire callbacks to all registered listeners

    friend class CAudSongAddClipOperation;
    friend class CAudClip;
    friend class CAudProcessorImpl;
    
    
#ifdef _WRITE_OUTPUT_TO_FILE_

    TBool iFileOpen;
    RFs iDebFs;
    RFile iAudioFile;
    RFile iTextFile;
    
    
#endif
    
    };


// Abstract interface class to get events from audio processor

class MProcProcessObserver 
    {

public:
    /**
     * Called to notify that a new audio processing operation has been started. 
     *
     */
    virtual void NotifyAudioProcessingStartedL() = 0;

    /**
     * Called to inform about the current progress of the audio processing operation.
     *
     * @param aPercentage  percentage of the operation completed, must be 
       *                     in range 0..100
     */
    virtual void NotifyAudioProcessingProgressed(TInt aPercentage) = 0;

    /**
    * Called to notify that the song processing operation has been completed. 
    * 
    * @param aError  error code why the operation was completed. 
    *                <code>KErrNone</code> if the operation was completed 
    *                successfully.
    */
    virtual void NotifyAudioProcessingCompleted(TInt aError) = 0;

    };



/**
* Internal class for processing a song.
*/
class CAudSongProcessOperation : public CBase, public MProcProcessObserver, public MAudTimeEstimateObserver
    {
    
    
    
public:

    
    static CAudSongProcessOperation* NewL(CAudSong* aSong);

    // From MProcProcessObserver

    void NotifyAudioProcessingStartedL();
    void NotifyAudioProcessingProgressed(TInt aPercentage);
    void NotifyAudioProcessingCompleted(TInt aError);
    
    // From // MAudTimeEstimateObserver
    void NotifyTimeEstimateReady(TInt64 aTimeEstimate);

    /**
    * Starts asyncronous processing a song
    * 
    * Can leave with one of the system wide error codes
    *
    * Possible panic code
    * <code>ESongProcessingOperationAlreadyRunning</code>
    *
    * @param    aFileName    output file name
    * @param    aObserver    an observer to be notified of progress
    * @param    aPriority    priority of audio processing operation
    */
    void StartASyncProcL(const TDesC& aFileName, 
        MAudSongProcessingObserver& aObserver, TInt aPriority);


    /**
    * Starts syncronous song processing
    * 
    * Can leave with one of the system wide error codes
    *
    * Possible panic code
    * <code>ESongProcessingOperationAlreadyRunning</code>
    *
    */
    TBool StartSyncProcL();
    
    
    /**
    * Processes synchronously next audio frame and passes it to the caller. 
    * If a processing operation has not been started, panic 
    * <code>TAudPanic::ESongProcessingNotRunning</code> is raised.
    *
    * Possibly leave codes:
    *    - <code>KErrNoMemory</code> if memory allocation fails
    *
    * NOTE: This function allocates memory and the caller is responsible for
    * releasing it.
    *
    * @param aFrame        pointer to a processed audio frame. Has to be deleted
    *                    when not needed anymore.
    * @param aDuration    Duration of processed audio frame in microseconds 
    *                    after decoding
    * 
    * @return ETrue        Processing operation completed, no more frames to be processed. 
    *                    No memory allocated.
    *          EFalse    Processing operation not completed. Last processed frame stored
    *                    in <code>aFrame</code>. Memory allocated for the processed frame
    *                      
    */
    TBool ProcessSyncPieceL(HBufC8*& aFrame, TInt& aProgress,
                                       TTimeIntervalMicroSeconds& aDuration);

    /**
    * Cancels both syncronous and and asyncronous song processing operation and deletes the output file
    *
    * Possible panic code
    * <code>ESongProcessingOperationNotRunning</code>
    *
    */
    void Cancel();
    
    TBool GetTimeEstimateL(MAudTimeEstimateObserver& aTEObserver);


private:

    CAudSongProcessOperation(CAudSong* aSong);
    void ConstructL();
    virtual ~CAudSongProcessOperation();
    
private:
    
   /* 
    * Member Variables
    */
    
    // song
    CAudSong *iSong;
    
    // song processing observer
    MAudSongProcessingObserver* iObserver;
    
    // time estimate observer
    MAudTimeEstimateObserver* iTEObserver;
    
    // A flag that indicates whether this song has changed since
    // the last processing
    TBool iChanged;
    
    // processor owned by this
    CAudProcessor* iProcessor;
    
    friend class CAudSong;
    
    
    };


/**
* Internal class for adding clips.
*/
class CAudSongAddClipOperation : public CBase, public MAudClipInfoObserver 
    {

public:

    /*
    * Constuctor & destructor
    */

    static CAudSongAddClipOperation* NewL(CAudSong* aSong);

    virtual ~CAudSongAddClipOperation();
        
    /*
    * From base class MAudClipInfoObserver
    */
    virtual void NotifyClipInfoReady(CAudClipInfo& aInfo, 
        TInt aError);
    
    
private:
    
    /*
    * ConstructL
    */
    void ConstructL();
    
    /*
    * C++ constructor
    */
    CAudSongAddClipOperation(CAudSong* aSong);
    
    /*
    * Completes add clip operation
    */
    void CompleteAddClipOperation();
 
    
private:

    // song
    CAudSong* iSong;
    
    // clip that we are trying to add
    CAudClip* iClip;
    
    // error possible caught by callback function NotifyClipInfoReady
    TInt iError;
    
    friend class CAudSong;
    };



#endif