mirror of
https://github.com/blupi-games/planetblupi
synced 2024-12-30 10:15:36 +01:00
365 lines
6.1 KiB
C++
365 lines
6.1 KiB
C++
// sound.cpp
|
||
//
|
||
|
||
#include <stdio.h>
|
||
#include "sound.h"
|
||
#include "event.h"
|
||
#include "misc.h"
|
||
#include "def.h"
|
||
#include "resource.h"
|
||
|
||
|
||
// Stops all sounds.
|
||
|
||
bool CSound::StopAllSounds()
|
||
{
|
||
for (int i = 0; i < MAXSOUND; i ++)
|
||
{
|
||
if (!m_lpSDL[i])
|
||
continue;
|
||
|
||
if (Mix_Playing (i + 1) == SDL_TRUE)
|
||
Mix_FadeOutChannel (i + 1, 500);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
CSound::CSound()
|
||
{
|
||
int i;
|
||
|
||
m_bEnable = false;
|
||
m_bState = false;
|
||
m_MIDIFilename[0] = 0;
|
||
m_audioVolume = 20;
|
||
m_midiVolume = 15;
|
||
m_lastMidiVolume = 0;
|
||
m_nbSuspendSkip = 0;
|
||
m_pMusic = nullptr;
|
||
m_bStopped = false;
|
||
|
||
for ( i=0 ; i<MAXBLUPI ; i++ )
|
||
{
|
||
m_channelBlupi[i] = -1;
|
||
}
|
||
|
||
memset (m_lpSDL, 0, sizeof (m_lpSDL));
|
||
}
|
||
|
||
// Destructeur.
|
||
|
||
CSound::~CSound()
|
||
{
|
||
int i;
|
||
|
||
for ( i=0 ; i<MAXSOUND ; i++ )
|
||
{
|
||
if (!m_lpSDL[i])
|
||
continue;
|
||
|
||
Mix_FreeChunk (m_lpSDL[i]);
|
||
m_lpSDL[i] = nullptr;
|
||
}
|
||
}
|
||
|
||
|
||
// Initialisation de DirectSound.
|
||
|
||
bool CSound::Create()
|
||
{
|
||
m_bEnable = true;
|
||
|
||
if (Mix_OpenAudio (44100, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 4096) == -1)
|
||
return false;
|
||
|
||
Mix_AllocateChannels (MAXSOUND);
|
||
|
||
Mix_HookMusicFinished ([] ()
|
||
{
|
||
CEvent::PushUserEvent (WM_MUSIC_STOP);
|
||
});
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
// Retourne l'<27>tat de DirectSound.
|
||
|
||
bool CSound::GetEnable()
|
||
{
|
||
return m_bEnable;
|
||
}
|
||
|
||
|
||
// Enclenche ou d<>clenche le son.
|
||
|
||
void CSound::SetState(bool bState)
|
||
{
|
||
m_bState = bState;
|
||
}
|
||
|
||
|
||
// Gestion des volumes audio (.wav) et midi (.mid).
|
||
|
||
void CSound::SetAudioVolume(int volume)
|
||
{
|
||
m_audioVolume = volume;
|
||
}
|
||
|
||
int CSound::GetAudioVolume()
|
||
{
|
||
if ( !m_bEnable ) return 0;
|
||
return m_audioVolume;
|
||
}
|
||
|
||
void CSound::SetMidiVolume(int volume)
|
||
{
|
||
m_midiVolume = volume;
|
||
}
|
||
|
||
int CSound::GetMidiVolume()
|
||
{
|
||
if ( !m_bEnable ) return 0;
|
||
return m_midiVolume;
|
||
}
|
||
|
||
|
||
// Cache tous les ficheirs son (.wav).
|
||
|
||
void CSound::CacheAll()
|
||
{
|
||
int i;
|
||
char name[50];
|
||
|
||
if ( !m_bEnable ) return;
|
||
|
||
for ( i=0 ; i<MAXSOUND ; i++ )
|
||
{
|
||
sprintf(name, "sound\\sound%.3d.blp", i);
|
||
if ( !Cache(i, name) ) break;
|
||
}
|
||
}
|
||
|
||
// Charge un fichier son (.wav).
|
||
|
||
bool CSound::Cache(int channel, char *pFilename)
|
||
{
|
||
if ( !m_bEnable ) return false;
|
||
if ( channel < 0 || channel >= MAXSOUND ) return false;
|
||
|
||
if (m_lpSDL[channel])
|
||
Flush(channel);
|
||
|
||
m_lpSDL[channel] = Mix_LoadWAV (pFilename);
|
||
if (!m_lpSDL[channel])
|
||
{
|
||
SDL_Log ("Mix_LoadWAV: %s\n", Mix_GetError ());
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
// D<>charge un son.
|
||
|
||
void CSound::Flush(int channel)
|
||
{
|
||
if ( !m_bEnable ) return;
|
||
if ( channel < 0 || channel >= MAXSOUND ) return;
|
||
|
||
if (m_lpSDL[channel])
|
||
{
|
||
Mix_FreeChunk (m_lpSDL[channel]);
|
||
m_lpSDL[channel] = nullptr;
|
||
}
|
||
}
|
||
|
||
// Fait entendre un son.
|
||
// Le volume est compris entre 128 (max) et 0 (silence).
|
||
// Le panoramique est compris entre 255,0 (gauche), 127,128 (centre)
|
||
// et 0,255 (droite).
|
||
|
||
bool CSound::Play(int channel, int volume, Uint8 panLeft, Uint8 panRight)
|
||
{
|
||
if (!m_bEnable)
|
||
return true;
|
||
|
||
if (!m_bState || !m_audioVolume)
|
||
return true;
|
||
|
||
if (channel < 0 || channel >= MAXSOUND)
|
||
return false;
|
||
|
||
Mix_SetPanning (channel + 1, panLeft, panRight);
|
||
|
||
volume = volume * 100 * m_audioVolume / 20 / 100;
|
||
Mix_Volume (channel + 1, volume);
|
||
|
||
if (Mix_Playing (channel + 1) == SDL_FALSE)
|
||
Mix_PlayChannel (channel + 1, m_lpSDL[channel], 0);
|
||
|
||
return true;
|
||
}
|
||
|
||
// Fait entendre un son dans une image.
|
||
// Si rank != -1, il indique le rang du blupi dont il faudra
|
||
// <20>ventuellement stopper le dernier son en cours !
|
||
|
||
bool CSound::PlayImage(int channel, POINT pos, int rank)
|
||
{
|
||
int stopCh, volumex, volumey, volume;
|
||
|
||
if ( rank >= 0 && rank < MAXBLUPI )
|
||
{
|
||
stopCh = m_channelBlupi[rank];
|
||
if ( stopCh >= 0 && m_lpSDL[stopCh] != nullptr )
|
||
Mix_FadeOutChannel (stopCh + 1, 500);
|
||
|
||
m_channelBlupi[rank] = channel;
|
||
}
|
||
|
||
Uint8 panRight, panLeft;
|
||
volumex = MIX_MAX_VOLUME;
|
||
volumey = MIX_MAX_VOLUME;
|
||
|
||
if (pos.x < 0)
|
||
{
|
||
panRight = 0;
|
||
panLeft = 255;
|
||
volumex += pos.x;
|
||
if (volumex < 0)
|
||
volumex = 0;
|
||
}
|
||
else if (pos.x > LXIMAGE)
|
||
{
|
||
panRight = 255;
|
||
panLeft = 0;
|
||
volumex -= pos.x - LXIMAGE;
|
||
if (volumex < 0)
|
||
volumex = 0;
|
||
}
|
||
else
|
||
{
|
||
panRight = 255 * static_cast<Uint16> (pos.x) / LXIMAGE;
|
||
panLeft = 255 - panRight;
|
||
}
|
||
|
||
if (pos.y < 0)
|
||
{
|
||
volumey += pos.y;
|
||
if (volumey < 0)
|
||
volumey = 0;
|
||
}
|
||
else if (pos.y > LYIMAGE)
|
||
{
|
||
volumey -= pos.y - LYIMAGE;
|
||
if (volumey < 0)
|
||
volumey = 0;
|
||
}
|
||
|
||
volume = volumex < volumey ? volumex : volumey;
|
||
|
||
return Play(channel, volume, panLeft, panRight);
|
||
}
|
||
|
||
|
||
// Uses MCI to play a MIDI file. The window procedure
|
||
// is notified when playback is complete.
|
||
|
||
bool CSound::PlayMusic(const char *lpszMIDIFilename)
|
||
{
|
||
std::string path = GetBaseDir ();
|
||
|
||
if ( !m_bEnable ) return true;
|
||
if ( m_midiVolume == 0 ) return true;
|
||
|
||
Mix_VolumeMusic (MIX_MAX_VOLUME * 100 * m_midiVolume / 20 / 100);
|
||
m_lastMidiVolume = m_midiVolume;
|
||
|
||
path += lpszMIDIFilename;
|
||
|
||
m_pMusic = Mix_LoadMUS (path.c_str ());
|
||
if (!m_pMusic)
|
||
{
|
||
printf ("%s\n", Mix_GetError ());
|
||
return false;
|
||
}
|
||
|
||
if (Mix_PlayMusic (m_pMusic, 0) == -1)
|
||
{
|
||
printf ("%s\n", Mix_GetError ());
|
||
return false;
|
||
}
|
||
|
||
m_bStopped = false;
|
||
strcpy(m_MIDIFilename, lpszMIDIFilename);
|
||
return true;
|
||
}
|
||
|
||
// Restart the MIDI player.
|
||
|
||
bool CSound::RestartMusic()
|
||
{
|
||
OutputDebug("RestartMusic\n");
|
||
if ( !m_bEnable ) return true;
|
||
if ( m_midiVolume == 0 ) return true;
|
||
if ( m_MIDIFilename[0] == 0 ) return false;
|
||
|
||
return PlayMusic(m_MIDIFilename);
|
||
}
|
||
|
||
// Shuts down the MIDI player.
|
||
|
||
void CSound::SuspendMusic()
|
||
{
|
||
if ( !m_bEnable ) return;
|
||
|
||
if ( m_nbSuspendSkip != 0 )
|
||
{
|
||
m_nbSuspendSkip --;
|
||
return;
|
||
}
|
||
|
||
m_bStopped = true;
|
||
Mix_HaltMusic ();
|
||
}
|
||
|
||
// Shuts down the MIDI player.
|
||
|
||
void CSound::StopMusic()
|
||
{
|
||
SuspendMusic();
|
||
m_MIDIFilename[0] = 0;
|
||
}
|
||
|
||
// Retourne true si une musique est en cours.
|
||
|
||
bool CSound::IsPlayingMusic()
|
||
{
|
||
return (m_MIDIFilename[0] != 0);
|
||
}
|
||
|
||
bool CSound::IsStoppedOnDemand ()
|
||
{
|
||
return m_bStopped;
|
||
}
|
||
|
||
// Adapte le volume de la musique en cours, si n<>cessaire.
|
||
|
||
void CSound::AdaptVolumeMusic()
|
||
{
|
||
if (m_midiVolume != m_lastMidiVolume)
|
||
{
|
||
Mix_VolumeMusic (MIX_MAX_VOLUME * 100 * m_midiVolume / 20 / 100);
|
||
m_lastMidiVolume = m_midiVolume;
|
||
}
|
||
}
|
||
|
||
// Indique le nombre de suspend <20> sauter.
|
||
|
||
void CSound::SetSuspendSkip(int nb)
|
||
{
|
||
m_nbSuspendSkip = nb;
|
||
}
|