Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

#include "BassMusicInterface.h"
#include "BassLoader.h"
#include "..\PakLib\PakInterface.h"

using namespace Sexy;

#define BASS2_MUSIC_RAMP                        BASS_MUSIC_RAMP // normal ramping

#define BASS_CONFIG_BUFFER                      0

BassMusicInfo::BassMusicInfo()
{      
        mVolume = 0.0;
        mVolumeAdd = 0.0;
        mVolumeCap = 1.0;
        mStopOnFade = false;
        mHMusic = NULL;
        mHStream = NULL;
}

BassMusicInterface::BassMusicInterface(HWND theHWnd)
{
        LoadBassDLL();

        MIXERCONTROLDETAILS mcd;
        MIXERCONTROLDETAILS_UNSIGNED mxcd_u;
        MIXERLINECONTROLS mxlc;
        MIXERCONTROL mlct;
        MIXERLINE mixerLine;
        HMIXEROBJ phmx;
        MIXERCAPS pmxcaps;     

        mixerOpen((HMIXER*) &phmx, 0, 0, 0, MIXER_OBJECTF_MIXER);
        mixerGetDevCaps(0, &pmxcaps, sizeof(pmxcaps));

        mxlc.cbStruct = sizeof(mxlc);  
        mxlc.cbmxctrl = sizeof(mlct);
        mxlc.pamxctrl = &mlct;
        mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
        mixerLine.cbStruct = sizeof(mixerLine);
        mixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
        mixerGetLineInfo(phmx, &mixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE);
        mxlc.dwLineID = mixerLine.dwLineID;
        mixerGetLineControls(phmx, &mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);   

        mcd.cbStruct = sizeof(mcd);
        mcd.dwControlID = mlct.dwControlID;
        mcd.cChannels = 1;
        mcd.cMultipleItems = 0;
        mcd.cbDetails = sizeof(mxcd_u);
        mcd.paDetails = &mxcd_u;
       
        mixerGetControlDetails(phmx, &mcd, 0L);

        //return mxcd_u.dwValue;       

        BOOL success;

        if (gBass->mVersion2)
        {
                success = gBass->BASS_Init2(1, 44100, 0, theHWnd, NULL);
                gBass->BASS_SetConfig(BASS_CONFIG_BUFFER, 2000);
        }
        else
                success = gBass->BASS_Init(-1, 44100, 0, theHWnd);

        mixerSetControlDetails(phmx, &mcd, 0L);

        gBass->BASS_Start();

        mixerClose((HMIXER) phmx);

        mMaxMusicVolume = 40;

        mMusicLoadFlags = gBass->mVersion2 ? BASS_MUSIC_LOOP | BASS2_MUSIC_RAMP : BASS_MUSIC_LOOP;
}

BassMusicInterface::~BassMusicInterface()
{
        gBass->BASS_Stop();
        gBass->BASS_Free();

        FreeBassDLL();
}

bool BassMusicInterface::LoadMusic(int theSongId, const std::string& theFileName)
{
        HMUSIC aHMusic = NULL;
        HSTREAM aStream = NULL;
       
        std::string anExt;
        int aDotPos = theFileName.find_last_of('.');
        if (aDotPos!=std::string::npos)
                anExt = StringToLower(theFileName.substr(aDotPos+1));

        if (anExt=="wav" || anExt=="ogg" || anExt=="mp3")
                aStream = gBass->BASS_StreamCreateFile(FALSE, (void*) theFileName.c_str(), 0, 0, 0);
        else
        {
                PFILE* aFP = p_fopen(theFileName.c_str(), "rb");
                if (aFP == NULL)
                        return false;

                p_fseek(aFP, 0, SEEK_END);
                int aSize = p_ftell(aFP);
                p_fseek(aFP, 0, SEEK_SET);

                uchar* aData = new uchar[aSize];
                p_fread(aData, 1, aSize, aFP);
                p_fclose(aFP);

                if (gBass->mVersion2)
                        aHMusic = gBass->BASS_MusicLoad2(FALSE, (void*) theFileName.c_str(), 0, 0, BASS_MUSIC_LOOP | BASS2_MUSIC_RAMP, 0);
                else
                        aHMusic = gBass->BASS_MusicLoad(FALSE, (void*) theFileName.c_str(), 0, 0, BASS_MUSIC_LOOP);

                delete aData;
        }

        if (aHMusic==NULL && aStream==NULL)
                return false;
       
        BassMusicInfo aMusicInfo;      
        aMusicInfo.mHMusic = aHMusic;
        aMusicInfo.mHStream = aStream;
        mMusicMap.insert(BassMusicMap::value_type(theSongId, aMusicInfo));

        return true;   
}

void BassMusicInterface::PlayMusic(int theSongId, int theOffset, bool noLoop)
{
        BassMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {
                BassMusicInfo* aMusicInfo = &anItr->second;
                aMusicInfo->mVolume = aMusicInfo->mVolumeCap;
                aMusicInfo->mVolumeAdd = 0.0;
                aMusicInfo->mStopOnFade = noLoop;
                gBass->BASS_ChannelSetAttributes(aMusicInfo->GetHandle(), -1, (int) (aMusicInfo->mVolume*100), -101);                      

                gBass->BASS_ChannelStop(aMusicInfo->GetHandle());
                if (aMusicInfo->mHMusic)
                {
                        if (gBass->mVersion2)
                                gBass->BASS_MusicPlayEx(aMusicInfo->mHMusic, theOffset, BASS_MUSIC_POSRESET | BASS2_MUSIC_RAMP | (noLoop ? 0 : BASS_MUSIC_LOOP), TRUE);
                        else
                                gBass->BASS_MusicPlayEx(aMusicInfo->mHMusic, theOffset, noLoop ? 0 : BASS_MUSIC_LOOP, TRUE);
                }
                else
                {
                        BOOL flush = theOffset == -1 ? FALSE : TRUE;
                        gBass->BASS_StreamPlay(aMusicInfo->mHStream, flush, noLoop ? 0 : BASS_MUSIC_LOOP);
                        if (theOffset > 0)
                                gBass->BASS_ChannelSetPosition(aMusicInfo->mHStream, theOffset);
                }
        }
}

void BassMusicInterface::StopMusic(int theSongId)
{
        BassMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {
                BassMusicInfo* aMusicInfo = &anItr->second;
                aMusicInfo->mVolume = 0.0;
                gBass->BASS_ChannelStop(aMusicInfo->GetHandle());
        }
}

void BassMusicInterface::StopAllMusic()
{
        BassMusicMap::iterator anItr = mMusicMap.begin();
        while (anItr != mMusicMap.end())
        {
                BassMusicInfo* aMusicInfo = &anItr->second;
                aMusicInfo->mVolume = 0.0;
                gBass->BASS_ChannelStop(aMusicInfo->GetHandle());
                ++anItr;
        }
}

void BassMusicInterface::UnloadMusic(int theSongId)
{
        StopMusic(theSongId);
       
        BassMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {
                BassMusicInfo* aMusicInfo = &anItr->second;
                if (aMusicInfo->mHStream)
                        gBass->BASS_StreamFree(aMusicInfo->mHStream);
                else if (aMusicInfo->mHMusic)
                        gBass->BASS_MusicFree(aMusicInfo->mHMusic);

                mMusicMap.erase(anItr);
        }
}

void BassMusicInterface::UnloadAllMusic()
{
        StopAllMusic();
        for (BassMusicMap::iterator anItr = mMusicMap.begin(); anItr != mMusicMap.end(); ++anItr)
        {
                BassMusicInfo* aMusicInfo = &anItr->second;
                if (aMusicInfo->mHStream)
                        gBass->BASS_StreamFree(aMusicInfo->mHStream);
                else if (aMusicInfo->mHMusic)
                        gBass->BASS_MusicFree(aMusicInfo->mHMusic);
        }
        mMusicMap.clear();
}

void BassMusicInterface::PauseMusic(int theSongId)
{
        BassMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {
                BassMusicInfo* aMusicInfo = &anItr->second;
                gBass->BASS_ChannelPause(aMusicInfo->GetHandle());
        }
}

void BassMusicInterface::PauseAllMusic()
{
        for (BassMusicMap::iterator anItr = mMusicMap.begin(); anItr != mMusicMap.end(); ++anItr)
        {
                BassMusicInfo* aMusicInfo = &anItr->second;
                if (gBass->BASS_ChannelIsActive(aMusicInfo->GetHandle()) == BASS_ACTIVE_PLAYING)
                        gBass->BASS_ChannelPause(aMusicInfo->GetHandle());
        }
}

void BassMusicInterface::ResumeAllMusic()
{
        for (BassMusicMap::iterator anItr = mMusicMap.begin(); anItr != mMusicMap.end(); ++anItr)
        {
                BassMusicInfo* aMusicInfo = &anItr->second;

                if (gBass->BASS_ChannelIsActive(aMusicInfo->GetHandle()) == BASS_ACTIVE_PAUSED)
                        gBass->BASS_ChannelResume(aMusicInfo->GetHandle());
        }
}

void BassMusicInterface::ResumeMusic(int theSongId)
{
        BassMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {
                BassMusicInfo* aMusicInfo = &anItr->second;
                gBass->BASS_ChannelResume(aMusicInfo->GetHandle());
        }
}

void BassMusicInterface::FadeIn(int theSongId, int theOffset, double theSpeed, bool noLoop)
{
        BassMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {
                BassMusicInfo* aMusicInfo = &anItr->second;
                               
                aMusicInfo->mVolumeAdd = theSpeed;
                aMusicInfo->mStopOnFade = noLoop;

                gBass->BASS_ChannelStop(aMusicInfo->GetHandle());
                gBass->BASS_ChannelSetAttributes(aMusicInfo->GetHandle(), -1, (int) (aMusicInfo->mVolume*100), -101);
                if (aMusicInfo->mHMusic)
                {
                        if (theOffset == -1)
                                gBass->BASS_MusicPlay(aMusicInfo->mHMusic);
                        else
                        {
                                if (gBass->mVersion2)
                                        gBass->BASS_MusicPlayEx(aMusicInfo->mHMusic, theOffset, BASS2_MUSIC_RAMP | (noLoop ? 0 : BASS_MUSIC_LOOP), TRUE);
                                else
                                        gBass->BASS_MusicPlayEx(aMusicInfo->mHMusic, theOffset, noLoop ? 0 : BASS_MUSIC_LOOP, TRUE);
                        }
                }
                else
                {
                        BOOL flush = theOffset == -1 ? FALSE : TRUE;
                        gBass->BASS_StreamPlay(aMusicInfo->mHStream, flush, noLoop ? 0 : BASS_MUSIC_LOOP);
                        if (theOffset > 0)
                                gBass->BASS_ChannelSetPosition(aMusicInfo->mHStream, theOffset);
                }

        }
}

void BassMusicInterface::FadeOut(int theSongId, bool stopSong, double theSpeed)
{
        BassMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {              
                BassMusicInfo* aMusicInfo = &anItr->second;
               
                if (aMusicInfo->mVolume != 0.0)
                {
                        aMusicInfo->mVolumeAdd = -theSpeed;                    
                }

                aMusicInfo->mStopOnFade = stopSong;
        }
}

void BassMusicInterface::FadeOutAll(bool stopSong, double theSpeed)
{
        BassMusicMap::iterator anItr = mMusicMap.begin();
        while (anItr != mMusicMap.end())
        {
                BassMusicInfo* aMusicInfo = &anItr->second;
                               
                aMusicInfo->mVolumeAdd = -theSpeed;
                aMusicInfo->mStopOnFade = stopSong;

                ++anItr;
        }
}

void BassMusicInterface::SetVolume(double theVolume)
{
        int aVolume = (int) (theVolume * mMaxMusicVolume);
       
        if (gBass->mVersion2)
        {
                gBass->BASS_SetConfig(/*BASS_CONFIG_GVOL_MUSIC*/6, (int) (theVolume * 100));
                gBass->BASS_SetConfig(/*BASS_CONFIG_GVOL_STREAM*/5, (int) (theVolume * 100));
        }
        else
                gBass->BASS_SetGlobalVolumes(aVolume, aVolume, aVolume);               
}

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

                aMusicInfo->mVolume = theVolume;
                gBass->BASS_ChannelSetAttributes(aMusicInfo->GetHandle(), -1, (int) (aMusicInfo->mVolume*100), -101);
        }
}

void BassMusicInterface::SetSongMaxVolume(int theSongId, double theMaxVolume)
{
        BassMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {              
                BassMusicInfo* aMusicInfo = &anItr->second;

                aMusicInfo->mVolumeCap = theMaxVolume;
                aMusicInfo->mVolume = min(aMusicInfo->mVolume, theMaxVolume);
                gBass->BASS_ChannelSetAttributes(aMusicInfo->GetHandle(), -1, (int) (aMusicInfo->mVolume*100), -101);
        }
}

bool BassMusicInterface::IsPlaying(int theSongId)
{
        BassMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {              
                BassMusicInfo* aMusicInfo = &anItr->second;
                return gBass->BASS_ChannelIsActive(aMusicInfo->GetHandle()) == BASS_ACTIVE_PLAYING;
        }

        return false;
}

void BassMusicInterface::SetMusicAmplify(int theSongId, double theAmp)
{
        BassMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {              
                BassMusicInfo* aMusicInfo = &anItr->second;            
                gBass->BASS_MusicSetAmplify(aMusicInfo->GetHandle(), (int) (theAmp * 100));
        }
}

void BassMusicInterface::Update()
{
        BassMusicMap::iterator anItr = mMusicMap.begin();
        while (anItr != mMusicMap.end())
        {
                BassMusicInfo* 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)
                                        gBass->BASS_ChannelStop(aMusicInfo->GetHandle());
                        }

                        gBass->BASS_ChannelSetAttributes(aMusicInfo->GetHandle(), -1, (int) (aMusicInfo->mVolume*100), -101);
                }

                ++anItr;
        }      
}

////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// MODs are broken up into several orders or patterns. This returns the current order a song is on.
int BassMusicInterface::GetMusicOrder(int theSongId)
{
        BassMusicMap::iterator anItr = mMusicMap.find(theSongId);
        if (anItr != mMusicMap.end())
        {              
                BassMusicInfo* aMusicInfo = &anItr->second;
                int aPosition = gBass->BASS_MusicGetOrderPosition(aMusicInfo->GetHandle());
                return aPosition;
        }
        return -1;
}