Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

#include "FModMusicInterface.h"
#include "SexyAppBase.h"
#include "FModLoader.h"

using namespace Sexy;

FModMusicInfo::FModMusicInfo()
{
        mHSample = NULL;
        mHMusic = NULL;
        mVolume = 0.0;
        mVolumeAdd = 0.0;
        mVolumeCap = 1.0;
        mStopOnFade = false;
        mRepeats = false;
}

FModMusicInterface::FModMusicInterface(HWND theHWnd)
{      
        LoadFModDLL();

        mMasterVolume = 1.0;   
        mMaxMusicVolume = 100;
        mMaxSampleVolume = 100;
}

FModMusicInterface::~FModMusicInterface()
{
        FreeFModDLL();
}

FSOUND_SAMPLE* FModMusicInterface::LoadFMODSample(const std::string& theFileName)
{
        std::string aFilename = theFileName;

        int aLastDotPos = aFilename.rfind('.');
        int aLastSlashPos = max((int) aFilename.rfind('\\'), (int) aFilename.rfind('/'));      
        if (aLastSlashPos < 0)
                aLastSlashPos = 0;

        std::string aCachedName = GetAppDataFolder() + "cached\\" + GetFileName(theFileName, true) + ".wav";
        MkDir(GetFileDir(aCachedName));

        FSOUND_SAMPLE* aSample = gFMod->FSOUND_Sample_Load(FSOUND_FREE, aCachedName.c_str(), 0, 0);

        if (aSample == NULL)                   
        {
                aSample = gFMod->FSOUND_Sample_Load(FSOUND_FREE, (theFileName + ".ogg").c_str(), 0, 0);
       
                if (aSample != NULL)
                {
                        int aMode = gFMod->FSOUND_Sample_GetMode(aSample);     
                        int aFreq = 0;
                        gFMod->FSOUND_Sample_GetDefaults(aSample, &aFreq, NULL, NULL, NULL);
                                                                       
                        ushort aFormatTag = 1;
                        ushort aChannelCount = ((aMode & FSOUND_MONO) != 0) ? 1 : 2;
                        ulong aSampleRate = aFreq;
                        ushort aBitCount = ((aMode & FSOUND_8BITS) != 0) ? 8 : 16;
                        ushort aBlockAlign = aChannelCount*aBitCount/8;
                        ulong aBytesPerSec = aSampleRate * aBlockAlign;

                        int aDataSize = gFMod->FSOUND_Sample_GetLength(aSample) * aBlockAlign;
                        ulong aChunkSize = 4 + 8 + 16 + 8 + aDataSize;                 

                        void* aPtr1;
                        void* aPtr2;
                        uint aLen1;
                        uint aLen2;

                        if (gFMod->FSOUND_Sample_Lock(aSample, 0, aDataSize, &aPtr1, &aPtr2, &aLen1, &aLen2))
                        {
                                FILE* fp = fopen(aCachedName.c_str(), "wb");

                                if (fp != NULL)
                                {
                                        fwrite("RIFF", 1, 4, fp);      
                                        fwrite(&aChunkSize, 4, 1, fp);
                                        fwrite("WAVE", 1, 4, fp);

                                        aChunkSize = 16;
                                        fwrite("fmt ", 1, 4, fp);
                                        fwrite(&aChunkSize, 1, 4, fp);
                                        fwrite(&aFormatTag, 2, 1, fp);
                                        fwrite(&aChannelCount, 2, 1, fp);
                                        fwrite(&aSampleRate, 4, 1, fp);
                                        fwrite(&aBytesPerSec, 4, 1, fp);
                                        fwrite(&aBlockAlign, 2, 1, fp);
                                        fwrite(&aBitCount, 2, 1, fp);                                  

                                        fwrite("data", 1, 4, fp);
                                        fwrite(&aDataSize, 4, 1, fp);
                                        fwrite(aPtr1, 1, aDataSize, fp);
                                        fclose(fp);
                                }

                                gFMod->FSOUND_Sample_Unlock(aSample, aPtr1, aPtr2, aLen1, aLen2);
                        }
                }
        }
       
        return aSample;
}

bool FModMusicInterface::LoadSample(int theSongId, const std::string& theFileName, bool repeat)
{
        FSOUND_SAMPLE* aSample = LoadFMODSample(theFileName.c_str());

        if (aSample == NULL)
                return false;          

        FModMusicInfo aMusicInfo;
        aMusicInfo.mHSample = aSample; 
        aMusicInfo.mRepeats = repeat;
        mMusicMap.insert(FModMusicMap::value_type(theSongId, aMusicInfo));

        return true;   
}

bool FModMusicInterface::LoadSample(int theSongId, const std::string& theIntroFileName, const std::string& theRepeatFileName, bool repeat)
{
        FSOUND_SAMPLE* anIntroSample = LoadFMODSample(theIntroFileName.c_str());
        FSOUND_SAMPLE* aLoopSample = LoadFMODSample(theRepeatFileName.c_str());

        if ((anIntroSample == NULL) || (aLoopSample == NULL))
                return false;
       
        // Get info for intro
        int anIntroFreq;
        gFMod->FSOUND_Sample_GetDefaults(anIntroSample, &anIntroFreq, NULL, NULL, NULL);
        int anIntroMode = gFMod->FSOUND_Sample_GetMode(anIntroSample); 
        int anIntroLen = gFMod->FSOUND_Sample_GetLength(anIntroSample);

        // Get intro for loop
        int aLoopFreq;
        gFMod->FSOUND_Sample_GetDefaults(aLoopSample, &aLoopFreq, NULL, NULL, NULL);
        int aLoopMode = gFMod->FSOUND_Sample_GetMode(aLoopSample);     
        int aLoopLen = gFMod->FSOUND_Sample_GetLength(aLoopSample);
       
        // Formats must be the same
        if ((anIntroFreq != aLoopFreq) || (anIntroMode != aLoopMode))
                return false;

        // Create new sound to combine these two into
        FSOUND_SAMPLE* aSample = gFMod->FSOUND_Sample_Alloc(FSOUND_FREE, anIntroLen + aLoopLen, anIntroMode | FSOUND_LOOP_NORMAL, anIntroFreq, 255, 128, 0);
       
        void* aSamplePtr1;
        void* aSamplePtr2;
        uint aSampleLen1;
        uint aSampleLen2;

        int aSampleBytes = (((anIntroMode & FSOUND_MONO) != 0) ? 1 : 2) * (((anIntroMode & FSOUND_8BITS) != 0) ? 1 : 2);

        if (gFMod->FSOUND_Sample_Lock(aSample, 0, (anIntroLen + aLoopLen) * aSampleBytes, &aSamplePtr1, &aSamplePtr2, &aSampleLen1, &aSampleLen2))
        {                      
                void* aSrcPtr1;
                void* aSrcPtr2;
                uint aSrcLen1;
                uint aSrcLen2;

                if (gFMod->FSOUND_Sample_Lock(anIntroSample, 0, anIntroLen * aSampleBytes, &aSrcPtr1, &aSrcPtr2, &aSrcLen1, &aSrcLen2))
                {
                        memcpy(aSamplePtr1, aSrcPtr1, aSrcLen1);
                        gFMod->FSOUND_Sample_Unlock(anIntroSample, aSrcPtr1, aSrcPtr2, aSrcLen1, aSrcLen2);
                }

                if (gFMod->FSOUND_Sample_Lock(aLoopSample, anIntroLen * aSampleBytes, aLoopLen * aSampleBytes, &aSrcPtr1, &aSrcPtr2, &aSrcLen1, &aSrcLen2))
                {
                        memcpy((char*) aSamplePtr1 + (anIntroLen * aSampleBytes), aSrcPtr1, aSrcLen1);
                        gFMod->FSOUND_Sample_Unlock(aLoopSample, aSrcPtr1, aSrcPtr2, aSrcLen1, aSrcLen2);
                }
               
                gFMod->FSOUND_Sample_Unlock(aSample, aSamplePtr1, aSamplePtr2, aSampleLen1, aSampleLen2);
        }

        gFMod->FSOUND_Sample_Free(anIntroSample);
        gFMod->FSOUND_Sample_Free(aLoopSample);

        gFMod->FSOUND_Sample_SetLoopPoints(aSample, anIntroLen, aLoopLen);

        FModMusicInfo aMusicInfo;
        aMusicInfo.mHSample = aSample;
        aMusicInfo.mRepeats = repeat;
        mMusicMap.insert(FModMusicMap::value_type(theSongId, aMusicInfo));

        return true;   
}

bool FModMusicInterface::LoadMusic(int theSongId, const std::string& theFileName)
{
        FMUSIC_MODULE* aHMusic = gFMod->FMUSIC_LoadSong(theFileName.c_str());

        if (aHMusic == NULL)
                return false;  
       
        FModMusicInfo aMusicInfo;
        aMusicInfo.mHMusic = aHMusic;  
        mMusicMap.insert(FModMusicMap::value_type(theSongId, aMusicInfo));

        return true;   
}

void FModMusicInterface::PlayMusic(int theSongId, int theOffset, bool noLoop)
{
        FModMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {
                FModMusicInfo* aMusicInfo = &anItr->second;
                aMusicInfo->mVolume = aMusicInfo->mVolumeCap;
                aMusicInfo->mVolumeAdd = 0.0;

                if (aMusicInfo->mHMusic != NULL)
                {
                        gFMod->FMUSIC_SetMasterVolume(aMusicInfo->mHMusic, (int) (mMasterVolume * aMusicInfo->mVolume * mMaxMusicVolume));
                        gFMod->FMUSIC_SetLooping(aMusicInfo->mHMusic, noLoop ? FSOUND_LOOP_OFF : FSOUND_LOOP_NORMAL);
                        gFMod->FMUSIC_PlaySong(aMusicInfo->mHMusic);
                        gFMod->FMUSIC_SetOrder(aMusicInfo->mHMusic, theOffset);        
                }
                else
                {                      
                        gFMod->FSOUND_PlaySound(anItr->first, aMusicInfo->mHSample);
                        gFMod->FSOUND_SetLoopMode(anItr->first, aMusicInfo->mRepeats ? FSOUND_LOOP_NORMAL : FSOUND_LOOP_OFF);
                        gFMod->FSOUND_SetVolume(anItr->first, (int) (mMasterVolume * aMusicInfo->mVolume * mMaxSampleVolume));
                }
        }
}

void FModMusicInterface::PauseMusic(int theSongId)
{
        FModMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {
                FModMusicInfo* aMusicInfo = &anItr->second;
               
                if (aMusicInfo->mHMusic != NULL)
                {
                        gFMod->FMUSIC_SetPaused(aMusicInfo->mHMusic, TRUE);
                }
                else
                {
                        gFMod->FSOUND_SetPaused(theSongId, TRUE);
                }
        }
}

void FModMusicInterface::ResumeMusic(int theSongId)
{
        FModMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {
                FModMusicInfo* aMusicInfo = &anItr->second;
               
                if (aMusicInfo->mHMusic != NULL)
                {
                        gFMod->FMUSIC_SetPaused(aMusicInfo->mHMusic, FALSE);
                }
                else
                {
                        gFMod->FSOUND_SetPaused(theSongId, FALSE);
                }
        }
}

void FModMusicInterface::StopMusic(int theSongId)
{
        FModMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {
                FModMusicInfo* aMusicInfo = &anItr->second;
                aMusicInfo->mVolume = 0.0;

                if (aMusicInfo->mHMusic != NULL)
                {
                        gFMod->FMUSIC_StopSong(aMusicInfo->mHMusic);
                }
                else
                {
                        gFMod->FSOUND_StopSound(theSongId);
                }
        }
}

void FModMusicInterface::StopAllMusic()
{
        FModMusicMap::iterator anItr = mMusicMap.begin();
        while (anItr != mMusicMap.end())
        {
                FModMusicInfo* aMusicInfo = &anItr->second;
                aMusicInfo->mVolume = 0.0;
               
                if (aMusicInfo->mHMusic != NULL)
                {
                        gFMod->FMUSIC_StopSong(aMusicInfo->mHMusic);
                }
                else
                {
                        gFMod->FSOUND_StopSound(anItr->first);
                }

                ++anItr;
        }
}

void FModMusicInterface::FadeIn(int theSongId, int theOffset, double theSpeed, bool noLoop)
{
        FModMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {
                FModMusicInfo* aMusicInfo = &anItr->second;
               
                aMusicInfo->mVolumeAdd = theSpeed;
                               
                if (aMusicInfo->mHMusic != NULL)
                {      
                        gFMod->FMUSIC_SetMasterVolume(aMusicInfo->mHMusic, (int) (mMasterVolume * aMusicInfo->mVolume * mMaxMusicVolume));

                        gFMod->FMUSIC_SetLooping(aMusicInfo->mHMusic, noLoop ? FSOUND_LOOP_OFF : FSOUND_LOOP_NORMAL);

                        if (!gFMod->FMUSIC_IsPlaying(aMusicInfo->mHMusic))
                                gFMod->FMUSIC_PlaySong(aMusicInfo->mHMusic);

                        if (theOffset != -1)
                                gFMod->FMUSIC_SetOrder(aMusicInfo->mHMusic, theOffset);
                }
                else
                {                      
                        if (!gFMod->FSOUND_IsPlaying(theSongId))
                        {
                                gFMod->FSOUND_PlaySound(theSongId, aMusicInfo->mHSample);
                                gFMod->FSOUND_SetLoopMode(anItr->first, aMusicInfo->mRepeats ? FSOUND_LOOP_NORMAL : FSOUND_LOOP_OFF);
                        }

                        gFMod->FSOUND_SetVolume(anItr->first, (int) (mMasterVolume * aMusicInfo->mVolume * mMaxSampleVolume));
                }
        }
}

void FModMusicInterface::FadeOut(int theSongId, bool stopSong, double theSpeed)
{
        FModMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {
                FModMusicInfo* aMusicInfo = &anItr->second;
                               
                aMusicInfo->mVolumeAdd = -theSpeed;
                aMusicInfo->mStopOnFade = stopSong;
        }
}

void FModMusicInterface::FadeOutAll(bool stopSong, double theSpeed)
{
        FModMusicMap::iterator anItr = mMusicMap.begin();
        if (anItr != mMusicMap.end())
        {
                FModMusicInfo* aMusicInfo = &anItr->second;
                               
                aMusicInfo->mVolumeAdd = -theSpeed;
                aMusicInfo->mStopOnFade = stopSong;

                ++anItr;
        }
}

void FModMusicInterface::SetVolume(double theVolume)
{
        mMasterVolume = theVolume;

        FModMusicMap::iterator anItr = mMusicMap.begin();
        while (anItr != mMusicMap.end())
        {
                FModMusicInfo* aMusicInfo = &anItr->second;                                            

                if (aMusicInfo->mHMusic != NULL)
                {
                        gFMod->FMUSIC_SetMasterVolume(aMusicInfo->mHMusic, (int) (mMasterVolume * aMusicInfo->mVolume * mMaxMusicVolume));
                }
                else
                {
                        gFMod->FSOUND_SetVolume(anItr->first, (int) (mMasterVolume * aMusicInfo->mVolume * mMaxSampleVolume));
                }              

                ++anItr;
        }      
}

void FModMusicInterface::SetSongVolume(int theSongId, double theVolume)
{
        FModMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {              
                FModMusicInfo* aMusicInfo = &anItr->second;

                aMusicInfo->mVolume = theVolume;
               
                if (aMusicInfo->mHMusic != NULL)
                {
                        gFMod->FMUSIC_SetMasterVolume(aMusicInfo->mHMusic, (int) (mMasterVolume * aMusicInfo->mVolume * mMaxMusicVolume));
                }
                else
                {
                        gFMod->FSOUND_SetVolume(anItr->first, (int) (mMasterVolume * aMusicInfo->mVolume * mMaxSampleVolume));
                }              
        }
}

bool FModMusicInterface::IsPlaying(int theSongId)
{
        FModMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {              
                FModMusicInfo* aMusicInfo = &anItr->second;

                return (gFMod->FMUSIC_IsPlaying(aMusicInfo->mHMusic) != 0);
        }
        else
                return false;  
}

void FModMusicInterface::Update()
{
        FModMusicMap::iterator anItr = mMusicMap.begin();
        while (anItr != mMusicMap.end())
        {
                FModMusicInfo* aMusicInfo = &anItr->second;

                if (aMusicInfo->mVolumeAdd != 0.0)
                {
                        aMusicInfo->mVolume += aMusicInfo->mVolumeAdd;
                       
                        if (aMusicInfo->mVolume > aMusicInfo->mVolumeCap)
                        {
                                aMusicInfo->mVolume = aMusicInfo->mVolumeCap;
                                aMusicInfo->mVolumeAdd = 0.0;
                        }
                        else if (aMusicInfo->mVolume < 0.0)
                        {
                                aMusicInfo->mVolume = 0.0;
                                aMusicInfo->mVolumeAdd = 0.0;

                                if (aMusicInfo->mStopOnFade)
                                {
                                        if (aMusicInfo->mHMusic != NULL)
                                        {
                                                gFMod->FMUSIC_StopSong(aMusicInfo->mHMusic);
                                        }
                                        else
                                        {
                                                gFMod->FSOUND_StopSound(anItr->first);
                                        }
                                }
                        }

                        if (aMusicInfo->mHMusic != NULL)
                        {
                                gFMod->FMUSIC_SetMasterVolume(aMusicInfo->mHMusic, (int) (mMasterVolume * aMusicInfo->mVolume * mMaxMusicVolume));
                        }
                        else
                        {                              
                                gFMod->FSOUND_SetVolume(anItr->first, (int) (mMasterVolume * aMusicInfo->mVolume * mMaxSampleVolume));
                        }
                }

                ++anItr;
        }
}