
/*
 * Copyright  2011 Nokia Corporation.
 *
 * GE::GA AudioBuffer functionality
 * tuomo.hirvonen@digia.com
 *
 */

#ifndef __GE_IGA_AUDIOBUFFER__
#define __GE_IGA_AUDIOBUFFER__

#include "GEInterfaces.h"


namespace GE {

    class CAudioBufferPlayInstance;
    class CAudioBuffer;
// Prototype function for audio sampling
    typedef AUDIO_SAMPLE_TYPE(*SAMPLE_FUNCTION_TYPE)(CAudioBuffer *abuffer,
                                                     int pos,
                                                     int channel);

/*
 * Class to hold audio information (a buffer).
 *
 */
    class CAudioBuffer : public QObject {
    public:
        CAudioBuffer();
        virtual ~CAudioBuffer();

        static CAudioBuffer* loadWav( QString fileName );
	static CAudioBuffer* loadWav( FILE *wavFile );
        void reallocate( int length );

        inline void* getRawData() { return m_data; }
        inline int getDataLength() { return m_dataLength; }

        inline int getBytesPerSample() { return (m_bitsPerSample >> 3); }
        inline int getBitsPerSample() { return m_bitsPerSample; }
        inline int getSamplesPerSec() { return m_samplesPerSec; }
        inline short getNofChannels() { return m_nofChannels; }
        inline SAMPLE_FUNCTION_TYPE getSampleFunction() {
            return m_sampleFunction;
        }

        // Static implementations of sample functions
        static AUDIO_SAMPLE_TYPE sampleFunction8bitMono(
            CAudioBuffer *abuffer, int pos, int channel);
        static AUDIO_SAMPLE_TYPE sampleFunction16bitMono(
            CAudioBuffer *abuffer, int pos, int channel);
        static AUDIO_SAMPLE_TYPE sampleFunction32bitMono(
            CAudioBuffer *abuffer, int pos, int channel);
        static AUDIO_SAMPLE_TYPE sampleFunction8bitStereo(
            CAudioBuffer *abuffer, int pos, int channel);
        static AUDIO_SAMPLE_TYPE sampleFunction16bitStereo(
            CAudioBuffer *abuffer, int pos, int channel);
        static AUDIO_SAMPLE_TYPE sampleFunction32bitStereo(
            CAudioBuffer *abuffer, int pos, int channel);

        CAudioBufferPlayInstance *playWithMixer(GE::CAudioMixer &mixer);

    protected:
        SAMPLE_FUNCTION_TYPE m_sampleFunction;
        short m_nofChannels;
        void *m_data;
        int m_dataLength;				// in bytes
        short m_bitsPerSample;
        bool m_signedData;
        int m_samplesPerSec;
    };


    class CAudioBufferPlayInstance : public IAudioSource {
    public:
        CAudioBufferPlayInstance();
        CAudioBufferPlayInstance(CAudioBuffer *start_playing);
        virtual ~CAudioBufferPlayInstance();
        // Looptimes -1 = loop forever
        void playBuffer(CAudioBuffer *startPlaying, float volume,
                        float fixedSpeed, int loopTimes = 0);

        void setSpeed(float speed);
        void setLeftVolume(float lvol);
        void setRightVolume(float rvol);

        inline void setLoopTimes(int ltimes) { m_loopTimes = ltimes; }
        void stop();

        int pullAudio(AUDIO_SAMPLE_TYPE *target, int bufferLength);
        bool canBeDestroyed();

        bool isPlaying() {
            if (m_buffer)
                return true;
            else
                return false;
        }
        inline bool isFinished() { return m_finished; }
        inline bool destroyWhenFinished() { return m_destroyWhenFinished; }
        inline void setDestroyWhenFinished( bool set ) {
            m_destroyWhenFinished = set;
        }

    protected:
        int mixBlock( AUDIO_SAMPLE_TYPE *target, int bufferLength );
        bool m_finished;
        bool m_destroyWhenFinished;
        int m_fixedPos;
        int m_fixedInc;

        int m_fixedLeftVolume;
        int m_fixedRightVolume;
        int m_fixedCenter;
        int m_loopTimes;
        CAudioBuffer *m_buffer;
    };
};





#endif
