1
0
mirror of https://github.com/blupi-games/planetblupi synced 2024-12-30 10:15:36 +01:00
planetblupi/sound.cpp

459 lines
8.0 KiB
C++
Raw Normal View History

2017-01-21 17:27:46 +01:00
// sound.cpp
//
#include <SDL.h>
2017-01-21 17:27:46 +01:00
#include <dsound.h>
#include <stdio.h>
#include "sound.h"
#include "misc.h"
#include "def.h"
#include "resource.h"
// Stops all sounds.
bool CSound::StopAllSounds()
2017-01-21 17:27:46 +01:00
{
for (int i = 0; i < MAXSOUND; i ++)
{
if (!m_lpSDL[i])
continue;
2017-01-21 17:27:46 +01:00
if (Mix_Playing (i + 1) == SDL_TRUE)
Mix_FadeOutChannel (i + 1, 500);
}
2017-01-21 17:27:46 +01:00
return true;
2017-01-21 17:27:46 +01:00
}
/////////////////////////////////////////////////////////////////////////////
// Modifie le volume midi.
// Le volume est compris entre 0 et 20 !
void InitMidiVolume(int volume)
{
int nb, i, n;
MMRESULT result;
HMIDIOUT hmo = 0;
2017-01-21 23:31:49 +01:00
static unsigned int table[21] =
2017-01-21 17:27:46 +01:00
{
0x00000000,
0x11111111,
0x22222222,
0x33333333,
0x44444444,
0x55555555,
0x66666666,
0x77777777,
0x88888888,
0x99999999,
0xAAAAAAAA,
0xBBBBBBBB,
0xCCCCCCCC,
0xDDDDDDDD,
0xEEEEEEEE,
0xF222F222,
0xF555F555,
0xF777F777,
0xFAAAFAAA,
0xFDDDFDDD,
0xFFFFFFFF,
};
if ( volume < 0 ) volume = 0;
if ( volume > MAXVOLUME ) volume = MAXVOLUME;
nb = midiOutGetNumDevs();
for ( i=0 ; i<nb ; i++ )
{
result = midiOutOpen((LPHMIDIOUT)&hmo, i, 0L, 0L, 0L);
if ( result != MMSYSERR_NOERROR )
{
continue;
}
result = midiOutSetVolume(hmo, table[volume]);
if ( result != MMSYSERR_NOERROR )
{
n = 1;
}
midiOutClose(hmo);
hmo = 0;
}
}
/////////////////////////////////////////////////////////////////////////////
// Constructeur.
CSound::CSound()
{
int i;
m_bEnable = false;
m_bState = false;
2017-01-21 17:27:46 +01:00
m_MidiDeviceID = 0;
m_MIDIFilename[0] = 0;
m_audioVolume = 20;
m_midiVolume = 15;
m_lastMidiVolume = 0;
m_nbSuspendSkip = 0;
for ( i=0 ; i<MAXBLUPI ; i++ )
{
m_channelBlupi[i] = -1;
}
}
// Destructeur.
CSound::~CSound()
{
int i;
if ( m_bEnable )
{
InitMidiVolume(15); // remet un volume moyen !
}
for ( i=0 ; i<MAXSOUND ; i++ )
{
if (!m_lpSDL[i])
continue;
2017-01-21 17:27:46 +01:00
Mix_FreeChunk (m_lpSDL[i]);
m_lpSDL[i] = nullptr;
2017-01-21 17:27:46 +01:00
}
}
// Initialisation de DirectSound.
bool CSound::Create()
2017-01-21 17:27:46 +01:00
{
m_bEnable = true;
if (Mix_OpenAudio (44100, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 4096) == -1)
return false;
2017-01-21 17:27:46 +01:00
Mix_AllocateChannels (MAXSOUND);
return true;
2017-01-21 17:27:46 +01:00
}
// Retourne l'<27>tat de DirectSound.
bool CSound::GetEnable()
2017-01-21 17:27:46 +01:00
{
return m_bEnable;
}
// Enclenche ou d<>clenche le son.
void CSound::SetState(bool bState)
2017-01-21 17:27:46 +01:00
{
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)
2017-01-21 17:27:46 +01:00
{
if ( !m_bEnable ) return false;
if ( channel < 0 || channel >= MAXSOUND ) return false;
2017-01-21 17:27:46 +01:00
if (m_lpSDL[channel])
2017-01-21 17:27:46 +01:00
Flush(channel);
m_lpSDL[channel] = Mix_LoadWAV (pFilename);
if (!m_lpSDL[channel])
{
SDL_Log ("Mix_LoadWAV: %s\n", Mix_GetError ());
return false;
}
return true;
2017-01-21 17:27:46 +01:00
}
// 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;
}
2017-01-21 17:27:46 +01:00
}
// 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).
2017-01-21 17:27:46 +01:00
bool CSound::Play(int channel, int volume, Uint8 panLeft, Uint8 panRight)
2017-01-21 17:27:46 +01:00
{
if (!m_bEnable)
return true;
2017-01-21 17:27:46 +01:00
if (!m_bState || !m_audioVolume)
return true;
2017-01-21 17:27:46 +01:00
if (channel < 0 || channel >= MAXSOUND)
return false;
2017-01-21 17:27:46 +01:00
Mix_SetPanning (channel + 1, panLeft, panRight);
volume = volume * 100 * m_audioVolume / 20 / 100;
Mix_Volume (channel + 1, volume);
2017-01-21 17:27:46 +01:00
if (Mix_Playing (channel + 1) == SDL_FALSE)
Mix_PlayChannel (channel + 1, m_lpSDL[channel], 0);
2017-01-21 17:27:46 +01:00
return true;
2017-01-21 17:27:46 +01:00
}
// 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)
2017-01-21 17:27:46 +01:00
{
int stopCh, volumex, volumey, volume;
2017-01-21 17:27:46 +01:00
if ( rank >= 0 && rank < MAXBLUPI )
{
stopCh = m_channelBlupi[rank];
if ( stopCh >= 0 && m_lpSDL[stopCh] != NULL )
Mix_FadeOutChannel (stopCh + 1, 500);
2017-01-21 17:27:46 +01:00
m_channelBlupi[rank] = channel;
}
Uint8 panRight, panLeft;
volumex = MIX_MAX_VOLUME;
volumey = MIX_MAX_VOLUME;
2017-01-21 17:27:46 +01:00
if (pos.x < 0)
2017-01-21 17:27:46 +01:00
{
panRight = 0;
panLeft = 255;
volumex += pos.x;
if (volumex < 0)
volumex = 0;
2017-01-21 17:27:46 +01:00
}
else if (pos.x > LXIMAGE)
{
panRight = 255;
panLeft = 0;
volumex -= pos.x - LXIMAGE;
if (volumex < 0)
volumex = 0;
}
else
2017-01-21 17:27:46 +01:00
{
panRight = 255 * static_cast<Uint16> (pos.x) / LXIMAGE;
panLeft = 255 - panRight;
2017-01-21 17:27:46 +01:00
}
if (pos.y < 0)
2017-01-21 17:27:46 +01:00
{
volumey += pos.y;
if (volumey < 0)
volumey = 0;
2017-01-21 17:27:46 +01:00
}
else if (pos.y > LYIMAGE)
2017-01-21 17:27:46 +01:00
{
volumey -= pos.y - LYIMAGE;
if (volumey < 0)
volumey = 0;
2017-01-21 17:27:46 +01:00
}
volume = volumex < volumey ? volumex : volumey;
2017-01-21 17:27:46 +01:00
return Play(channel, volume, panLeft, panRight);
2017-01-21 17:27:46 +01:00
}
// Uses MCI to play a MIDI file. The window procedure
// is notified when playback is complete.
bool CSound::PlayMusic(HWND hWnd, LPSTR lpszMIDIFilename)
2017-01-21 17:27:46 +01:00
{
MCI_OPEN_PARMS mciOpenParms;
MCI_PLAY_PARMS mciPlayParms;
DWORD dwReturn;
char string[MAX_PATH];
if ( !m_bEnable ) return true;
if ( m_midiVolume == 0 ) return true;
2017-01-21 17:27:46 +01:00
InitMidiVolume(m_midiVolume);
m_lastMidiVolume = m_midiVolume;
if ( lpszMIDIFilename[1] == ':' ) // nom complet "D:\REP..." ?
{
strcpy(string, lpszMIDIFilename);
}
else
{
GetCurrentDir(string, MAX_PATH-30);
strcat(string, lpszMIDIFilename);
}
// Open the device by specifying the device and filename.
// MCI will attempt to choose the MIDI mapper as the output port.
mciOpenParms.lpstrDeviceType = "sequencer";
mciOpenParms.lpstrElementName = string;
dwReturn = mciSendCommand(NULL,
MCI_OPEN,
MCI_OPEN_TYPE|MCI_OPEN_ELEMENT,
(DWORD_PTR)(LPVOID)&mciOpenParms);
2017-01-21 17:27:46 +01:00
if ( dwReturn != 0 )
{
OutputDebug("PlayMusic-1\n");
mciGetErrorString(dwReturn, string, 128);
OutputDebug(string);
// Failed to open device. Don't close it; just return error.
return false;
2017-01-21 17:27:46 +01:00
}
// The device opened successfully; get the device ID.
m_MidiDeviceID = mciOpenParms.wDeviceID;
// Begin playback.
mciPlayParms.dwCallback = (DWORD_PTR)hWnd;
2017-01-21 17:27:46 +01:00
dwReturn = mciSendCommand(m_MidiDeviceID,
MCI_PLAY,
MCI_NOTIFY,
(DWORD_PTR)(LPVOID)&mciPlayParms);
2017-01-21 17:27:46 +01:00
if ( dwReturn != 0 )
{
OutputDebug("PlayMusic-2\n");
mciGetErrorString(dwReturn, string, 128);
OutputDebug(string);
StopMusic();
return false;
2017-01-21 17:27:46 +01:00
}
strcpy(m_MIDIFilename, lpszMIDIFilename);
return true;
2017-01-21 17:27:46 +01:00
}
// Restart the MIDI player.
bool CSound::RestartMusic()
2017-01-21 17:27:46 +01:00
{
OutputDebug("RestartMusic\n");
if ( !m_bEnable ) return true;
if ( m_midiVolume == 0 ) return true;
if ( m_MIDIFilename[0] == 0 ) return false;
2017-01-21 17:27:46 +01:00
return PlayMusic(m_hWnd, m_MIDIFilename);
}
// Shuts down the MIDI player.
void CSound::SuspendMusic()
{
if ( !m_bEnable ) return;
if ( m_nbSuspendSkip != 0 )
{
m_nbSuspendSkip --;
return;
}
if ( m_MidiDeviceID && m_midiVolume != 0 )
{
mciSendCommand(m_MidiDeviceID, MCI_CLOSE, 0, NULL);
}
m_MidiDeviceID = 0;
}
// Shuts down the MIDI player.
void CSound::StopMusic()
{
SuspendMusic();
m_MIDIFilename[0] = 0;
}
// Retourne true si une musique est en cours.
2017-01-21 17:27:46 +01:00
bool CSound::IsPlayingMusic()
2017-01-21 17:27:46 +01:00
{
return (m_MIDIFilename[0] != 0);
}
// Adapte le volume de la musique en cours, si n<>cessaire.
void CSound::AdaptVolumeMusic()
{
if ( m_midiVolume != m_lastMidiVolume )
{
InitMidiVolume(m_midiVolume);
m_lastMidiVolume = m_midiVolume;
RestartMusic();
}
}
// Indique le nombre de suspend <20> sauter.
void CSound::SetSuspendSkip(int nb)
{
m_nbSuspendSkip = nb;
}