2003-07-28 01:47:41 +00:00
|
|
|
/* Copyright (C) 1994-2003 Revolution Software Ltd
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* $Header$
|
|
|
|
*/
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
//
|
|
|
|
// Filename : d_sound.c
|
|
|
|
// Created : 3rd December 1996
|
|
|
|
// By : P.R.Porter
|
|
|
|
//
|
|
|
|
// Summary : This module holds the driver interface to direct sound.
|
|
|
|
//
|
|
|
|
// Functions
|
|
|
|
// ---------
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 PlayCompSpeech(const char *filename, uint32 id, uint8 vol, int8 pan)
|
|
|
|
//
|
|
|
|
// This function loads, decompresses and plays the wav 'id' from the cluster
|
|
|
|
// 'filename'. An error occurs if speech is already playing, or directSound
|
|
|
|
// comes accross problems. 'volume' can be from 0 to 16. 'pan' can be from
|
|
|
|
// -16 (full left) to 16 (full right).
|
|
|
|
// id is the text line id used to reference the speech within the speech
|
|
|
|
// cluster.
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
2003-07-30 19:25:31 +00:00
|
|
|
// int32 StopSpeechSword2(void)
|
2003-07-28 01:47:41 +00:00
|
|
|
//
|
|
|
|
// Stops the speech from playing.
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 GetSpeechStatus(void)
|
|
|
|
//
|
|
|
|
// Returns either RDSE_SAMPLEPLAYING or RDSE_SAMPLEFINISHED
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 AmISpeaking(void)
|
|
|
|
//
|
|
|
|
// Returns either RDSE_QUIET or RDSE_SPEAKING
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 PauseSpeech(void)
|
|
|
|
//
|
|
|
|
// Stops the speech dead in it's tracks.
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 UnpauseSpeech(void)
|
|
|
|
//
|
|
|
|
// Re-starts the speech from where it was stopped.
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 OpenFx(int32 id, uint8 *data)
|
|
|
|
//
|
|
|
|
// This function opens a sound effect ready for playing. A unique id should
|
|
|
|
// be passed in so that each effect can be referenced individually.
|
|
|
|
//
|
|
|
|
// WARNING: Zero is not a valid ID.
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 PlayFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type)
|
|
|
|
//
|
|
|
|
// This function plays a sound effect. If the effect has already been opened
|
|
|
|
// then *data should be NULL, and the sound effect will simply be obtained
|
|
|
|
// from the id passed in. If the effect has not been opened, then the wav
|
|
|
|
// data should be passed in data. The sound effect will be closed when it
|
|
|
|
// has finished playing.
|
|
|
|
//
|
|
|
|
// The volume can be between 0 (minimum) and 16 (maximum). The pan defines
|
|
|
|
// the left/right balance of the sample. -16 is full left, and 16 is full
|
|
|
|
// right with 0 in the middle. The sample type can be either RDSE_FXSPOT, or
|
|
|
|
// RDSE_FXLOOP.
|
|
|
|
//
|
|
|
|
// WARNING: Zero is not a valid ID
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 CloseFx(int32 id)
|
|
|
|
//
|
|
|
|
// This function closes a sound effect which has been previously opened for
|
|
|
|
// playing. Sound effects must be closed when they are finished with,
|
|
|
|
// otherwise you will run out of sound effect buffers.
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 ClearAllFx(void)
|
|
|
|
//
|
|
|
|
// This function clears all of the sound effects which are currently open or
|
|
|
|
// playing, irrespective of type.
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 StreamCompMusic(uint8 *filename, uint32 id, int32 loopFlag)
|
|
|
|
//
|
|
|
|
// Streams music 'id' from the cluster file 'filename'. The loopFlag should
|
|
|
|
// be set to RDSE_FXLOOP if the music is to loop back to the start.
|
|
|
|
// Otherwise, it should be RDSE_FXSPOT.
|
|
|
|
// The return value must be checked for any problems.
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// void StopMusic(void)
|
|
|
|
//
|
|
|
|
// Fades out and stops the music.
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 PauseMusic(void)
|
|
|
|
//
|
|
|
|
// Stops the music dead in it's tracks.
|
|
|
|
//
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 UnpauseMusic(void)
|
|
|
|
//
|
|
|
|
// Re-starts the music from where it was stopped.
|
|
|
|
//
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 MusicTimeRemaining(void)
|
|
|
|
//
|
|
|
|
// Returns the time left for the current tune.
|
|
|
|
//
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// int32 ReverseStereo(void)
|
|
|
|
//
|
|
|
|
// This function reverse the pan table, thus reversing the stereo.
|
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
|
2003-07-28 03:12:49 +00:00
|
|
|
#include "stdafx.h"
|
2003-07-28 01:47:41 +00:00
|
|
|
#include "driver96.h"
|
2003-07-29 12:34:46 +00:00
|
|
|
#include "d_sound.h"
|
2003-08-27 06:32:42 +00:00
|
|
|
#include "../sword2.h"
|
2003-09-25 06:11:07 +00:00
|
|
|
#include "sound/audiostream.h"
|
2003-08-30 18:06:08 +00:00
|
|
|
#include "sound/mixer.h"
|
2003-09-25 06:11:07 +00:00
|
|
|
#include "sound/rate.h"
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-25 06:11:07 +00:00
|
|
|
// Fade-out takes half a second. This may need some tuning.
|
|
|
|
#define FADE_SAMPLES 11025
|
|
|
|
|
|
|
|
static File fpMus;
|
2003-09-21 14:26:25 +00:00
|
|
|
|
2003-07-28 01:47:41 +00:00
|
|
|
// Decompression macros
|
2003-09-25 10:02:52 +00:00
|
|
|
#define GetCompressedShift(n) ((n) >> 4)
|
|
|
|
#define GetCompressedSign(n) (((n) >> 3) & 1)
|
|
|
|
#define GetCompressedAmplitude(n) ((n) & 7)
|
2003-07-29 12:34:46 +00:00
|
|
|
|
2003-08-31 20:26:21 +00:00
|
|
|
int32 panTable[33] = {
|
|
|
|
-127, -119, -111, -103, -95, -87, -79, -71, -63, -55, -47, -39, -31, -23, -15, -7,
|
|
|
|
0,
|
|
|
|
7, 15, 23, 31, 39, 47, 55, 63, 71, 79, 87, 95, 103, 111, 119, 127
|
|
|
|
};
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-31 20:26:21 +00:00
|
|
|
int32 musicVolTable[17] = {
|
|
|
|
0, 15, 31, 47, 63, 79, 95, 111, 127, 143, 159, 175, 191, 207, 223, 239, 255
|
|
|
|
};
|
2003-09-21 14:26:25 +00:00
|
|
|
|
2003-09-25 06:11:07 +00:00
|
|
|
int16 MusicHandle::read() {
|
|
|
|
uint8 in;
|
|
|
|
uint16 delta, value;
|
|
|
|
int16 out;
|
|
|
|
|
|
|
|
if (!_streaming)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Assume the file handle has been correctly positioned already.
|
|
|
|
|
|
|
|
in = fpMus.readByte();
|
|
|
|
delta = GetCompressedAmplitude(in) << GetCompressedShift(in);
|
|
|
|
|
|
|
|
if (GetCompressedSign(in))
|
|
|
|
value = _lastSample - delta;
|
|
|
|
else
|
|
|
|
value = _lastSample + delta;
|
|
|
|
|
|
|
|
_filePos++;
|
|
|
|
_lastSample = value;
|
|
|
|
|
|
|
|
out = (int16) (value ^ 0x8000);
|
|
|
|
|
|
|
|
if (_fading > 0) {
|
|
|
|
if (--_fading == 0) {
|
|
|
|
_streaming = false;
|
|
|
|
_looping = false;
|
|
|
|
}
|
|
|
|
out = (out * _fading) / FADE_SAMPLES;
|
|
|
|
}
|
2003-09-16 07:11:29 +00:00
|
|
|
|
2003-09-25 06:11:07 +00:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MusicHandle::eos() const {
|
|
|
|
if (!_streaming || _filePos >= _fileEnd)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void premix_proc(void *param, int16 *data, uint len) {
|
|
|
|
((Sword2Sound *) param)->FxServer(data, len);
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-02 02:31:36 +00:00
|
|
|
Sword2Sound::Sword2Sound(SoundMixer *mixer) {
|
2003-09-04 10:58:55 +00:00
|
|
|
_mutex = g_system->create_mutex();
|
|
|
|
|
2003-07-29 12:34:46 +00:00
|
|
|
soundOn = 0;
|
|
|
|
speechStatus = 0;
|
|
|
|
fxPaused = 0;
|
|
|
|
speechPaused = 0;
|
|
|
|
speechVol = 14;
|
|
|
|
fxVol = 14;
|
|
|
|
speechMuted = 0;
|
|
|
|
fxMuted = 0;
|
|
|
|
compressedMusic = 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
musicVol = 16;
|
|
|
|
|
2003-07-29 12:34:46 +00:00
|
|
|
musicMuted = 0;
|
2003-08-02 02:31:36 +00:00
|
|
|
_mixer = mixer;
|
2003-09-21 14:26:25 +00:00
|
|
|
|
|
|
|
memset(fx, 0, sizeof(fx));
|
|
|
|
|
2003-09-03 03:57:23 +00:00
|
|
|
soundHandleSpeech = 0;
|
2003-09-02 15:55:55 +00:00
|
|
|
|
2003-09-03 03:57:23 +00:00
|
|
|
soundOn = 1;
|
2003-09-25 06:11:07 +00:00
|
|
|
|
|
|
|
_converter = makeRateConverter(music[0].getRate(), _mixer->getOutputRate(), music[0].isStereo(), false);
|
|
|
|
|
|
|
|
_mixer->setupPremix(premix_proc, this);
|
2003-07-29 12:34:46 +00:00
|
|
|
}
|
|
|
|
|
2003-09-04 10:58:55 +00:00
|
|
|
Sword2Sound::~Sword2Sound() {
|
|
|
|
if (_mutex)
|
|
|
|
g_system->delete_mutex(_mutex);
|
|
|
|
}
|
|
|
|
|
2003-08-31 10:38:32 +00:00
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// This function reverse the pan table, thus reversing the stereo.
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
// FIXME: We could probably use the FLAG_REVERSE_STEREO mixer flag here.
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::ReverseStereo(void) {
|
2003-09-16 07:11:29 +00:00
|
|
|
int i, j;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
for (i = 0; i < 16; i++) {
|
2003-07-28 01:47:41 +00:00
|
|
|
j = panTable[i];
|
2003-08-30 18:06:08 +00:00
|
|
|
panTable[i] = panTable[32 - i];
|
|
|
|
panTable[32 - i] = j;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// This function returns the index of the sound effect with the ID passed in.
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::GetFxIndex(int32 id) {
|
2003-09-21 14:26:25 +00:00
|
|
|
int32 i;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
for (i = 0; i < MAXFX; i++) {
|
|
|
|
if (fx[i]._id == id)
|
2003-07-28 01:47:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
return i;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::IsFxOpen(int32 id) {
|
2003-09-21 14:26:25 +00:00
|
|
|
// FIXME: This seems backwards to me, but changing it breaks sound.
|
|
|
|
return GetFxIndex(id) == MAXFX;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// This function checks the status of all current sound effects, and clears
|
|
|
|
// out the ones which are no longer required in a buffer. It is called by
|
|
|
|
// a separate thread.
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
2003-09-25 06:11:07 +00:00
|
|
|
void Sword2Sound::FxServer(int16 *data, uint len) {
|
2003-09-05 15:56:43 +00:00
|
|
|
StackLock lock(_mutex);
|
2003-09-03 18:59:02 +00:00
|
|
|
|
2003-07-28 01:47:41 +00:00
|
|
|
if (!soundOn)
|
|
|
|
return;
|
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
if (!music[0]._paused && !music[1]._paused) {
|
2003-07-28 01:47:41 +00:00
|
|
|
if (compressedMusic == 1)
|
2003-09-25 06:11:07 +00:00
|
|
|
UpdateCompSampleStreaming(data, len);
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
if (!music[0]._streaming && !music[1]._streaming && fpMus.isOpen())
|
2003-09-05 15:56:43 +00:00
|
|
|
fpMus.close();
|
|
|
|
|
2003-09-04 10:58:55 +00:00
|
|
|
// FIXME: Doing this sort of things from a separate thread seems like
|
2003-09-05 15:56:43 +00:00
|
|
|
// just asking for trouble. But removing it outright causes regressions
|
|
|
|
// which need to be investigated.
|
|
|
|
//
|
|
|
|
// I've fixed one such regression, and as far as I can tell it's
|
|
|
|
// working now.
|
2003-09-04 10:58:55 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
int i;
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
if (fxPaused) {
|
|
|
|
for (i = 0; i < MAXFX; i++) {
|
2003-09-21 14:26:25 +00:00
|
|
|
if ((fx[i]._id == (int32) 0xfffffffe) || (fx[i]._id == (int32) 0xffffffff)) {
|
|
|
|
if (!fx[i]._handle) {
|
|
|
|
fx[i]._id = 0;
|
|
|
|
if (fx[i]._buf != NULL) {
|
|
|
|
free(fx[i]._buf);
|
|
|
|
fx[i]._buf = NULL;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._bufSize = 0;
|
|
|
|
fx[i]._flags = 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
for (i = 0; i < MAXFX; i++) {
|
2003-09-21 14:26:25 +00:00
|
|
|
if (fx[i]._id) {
|
|
|
|
if (!fx[i]._handle) {
|
|
|
|
fx[i]._id = 0;
|
|
|
|
if (fx[i]._buf != NULL) {
|
|
|
|
free(fx[i]._buf);
|
|
|
|
fx[i]._buf = NULL;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._bufSize = 0;
|
|
|
|
fx[i]._flags = 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-09-04 10:58:55 +00:00
|
|
|
#endif
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::AmISpeaking() {
|
2003-09-16 07:11:29 +00:00
|
|
|
if (!speechMuted && !speechPaused && soundHandleSpeech != 0)
|
|
|
|
return RDSE_SPEAKING;
|
|
|
|
|
|
|
|
return RDSE_QUIET;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
uint32 Sword2Sound::PreFetchCompSpeech(const char *filename, uint32 speechid, uint16 **buf) {
|
|
|
|
uint32 i;
|
|
|
|
uint8 *data8;
|
2003-09-16 07:11:29 +00:00
|
|
|
uint32 speechIndex[2];
|
|
|
|
File fp;
|
2003-09-22 06:36:38 +00:00
|
|
|
uint32 bufferSize;
|
|
|
|
|
|
|
|
*buf = NULL;
|
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
// Open the speech cluster and find the data offset & size
|
2003-09-17 21:06:16 +00:00
|
|
|
fp.open(filename);
|
2003-09-22 06:36:38 +00:00
|
|
|
if (!fp.isOpen())
|
2003-09-16 07:11:29 +00:00
|
|
|
return 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
fp.seek((speechid + 1) * 8, SEEK_SET);
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
if (fp.read(speechIndex, sizeof(uint32) * 2) != (sizeof(uint32) * 2)) {
|
|
|
|
fp.close();
|
2003-09-16 07:11:29 +00:00
|
|
|
return 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
2003-09-16 07:11:29 +00:00
|
|
|
|
2003-09-13 14:32:40 +00:00
|
|
|
#ifdef SCUMM_BIG_ENDIAN
|
|
|
|
speechIndex[0] = SWAP_BYTES_32(speechIndex[0]);
|
|
|
|
speechIndex[1] = SWAP_BYTES_32(speechIndex[1]);
|
|
|
|
#endif
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
if (!speechIndex[0] || !speechIndex[1]) {
|
|
|
|
fp.close();
|
2003-09-16 07:11:29 +00:00
|
|
|
return 0;
|
2003-09-22 06:36:38 +00:00
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
// Create a temporary buffer for compressed speech
|
|
|
|
if ((data8 = (uint8 *) malloc(speechIndex[1])) == NULL) {
|
2003-08-30 18:06:08 +00:00
|
|
|
fp.close();
|
2003-09-22 06:36:38 +00:00
|
|
|
return 0;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-09-16 07:11:29 +00:00
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
fp.seek(speechIndex[0], SEEK_SET);
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
if (fp.read(data8, speechIndex[1]) != speechIndex[1]) {
|
2003-08-30 18:06:08 +00:00
|
|
|
fp.close();
|
2003-09-22 06:36:38 +00:00
|
|
|
free(data8);
|
|
|
|
return 0;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
fp.close();
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
// Decompress data into speech buffer.
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
bufferSize = (speechIndex[1] - 1) * 2;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
*buf = (uint16 *) malloc(bufferSize);
|
|
|
|
if (!*buf) {
|
|
|
|
free(data8);
|
|
|
|
return 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
uint16 *data16 = *buf;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
// Starting Value
|
|
|
|
data16[0] = READ_LE_UINT16(data8);
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
for (i = 1; i < speechIndex[1] - 1; i++) {
|
2003-08-30 18:06:08 +00:00
|
|
|
if (GetCompressedSign(data8[i + 1]))
|
|
|
|
data16[i] = data16[i - 1] - (GetCompressedAmplitude(data8[i + 1]) << GetCompressedShift(data8[i + 1]));
|
2003-07-28 01:47:41 +00:00
|
|
|
else
|
2003-08-31 20:26:21 +00:00
|
|
|
data16[i] = data16[i - 1] + (GetCompressedAmplitude(data8[i + 1]) << GetCompressedShift(data8[i + 1]));
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
free(data8);
|
|
|
|
|
|
|
|
#ifndef SCUMM_BIG_ENDIAN
|
|
|
|
// Until the mixer supports LE samples natively, we need to convert
|
|
|
|
// our LE ones to BE
|
|
|
|
for (uint j = 0; j < bufferSize / 2; j++)
|
|
|
|
data16[j] = SWAP_BYTES_16(data16[j]);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return bufferSize;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::PlayCompSpeech(const char *filename, uint32 speechid, uint8 vol, int8 pan) {
|
2003-09-16 07:11:29 +00:00
|
|
|
uint16 *data16;
|
|
|
|
uint32 bufferSize;
|
2003-08-27 00:36:01 +00:00
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
if (!speechMuted) {
|
2003-07-28 01:47:41 +00:00
|
|
|
if (GetSpeechStatus() == RDERR_SPEECHPLAYING)
|
|
|
|
return RDERR_SPEECHPLAYING;
|
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
bufferSize = PreFetchCompSpeech(filename, speechid, &data16);
|
2003-09-16 07:11:29 +00:00
|
|
|
|
2003-09-22 06:36:38 +00:00
|
|
|
// We don't know exactly what went wrong here.
|
|
|
|
if (bufferSize == 0)
|
|
|
|
return RDERR_OUTOFMEMORY;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-12 23:22:45 +00:00
|
|
|
// Modify the volume according to the master volume
|
2003-09-21 14:26:25 +00:00
|
|
|
|
|
|
|
byte volume = speechMuted ? 0 : vol * speechVol;
|
|
|
|
int8 p = panTable[pan + 16];
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-12 23:22:45 +00:00
|
|
|
// Start the speech playing
|
2003-09-21 14:26:25 +00:00
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
speechPaused = 1;
|
2003-08-27 00:36:01 +00:00
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
uint32 flags = SoundMixer::FLAG_16BITS | SoundMixer::FLAG_AUTOFREE;
|
2003-08-27 00:36:01 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
_mixer->playRaw(&soundHandleSpeech, data16, bufferSize, 22050, flags, -1, volume, p);
|
2003-08-31 20:26:21 +00:00
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
speechStatus = 1;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
// FIXME: See comment in UpdateCompSampleStreaming()
|
|
|
|
// DipMusic();
|
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::StopSpeechSword2(void) {
|
2003-07-28 01:47:41 +00:00
|
|
|
if (!soundOn)
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
if (speechStatus) {
|
|
|
|
g_engine->_mixer->stopHandle(soundHandleSpeech);
|
2003-07-28 01:47:41 +00:00
|
|
|
speechStatus = 0;
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
2003-09-16 07:11:29 +00:00
|
|
|
return RDERR_SPEECHNOTPLAYING;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::GetSpeechStatus(void) {
|
2003-09-16 07:11:29 +00:00
|
|
|
if (!soundOn || !speechStatus)
|
|
|
|
return RDSE_SAMPLEFINISHED;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
|
|
|
if (speechPaused)
|
2003-09-16 07:11:29 +00:00
|
|
|
return RDSE_SAMPLEPLAYING;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-01 13:43:22 +00:00
|
|
|
if (!soundHandleSpeech) {
|
2003-07-28 01:47:41 +00:00
|
|
|
speechStatus = 0;
|
2003-09-16 07:11:29 +00:00
|
|
|
return RDSE_SAMPLEFINISHED;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
2003-09-16 07:11:29 +00:00
|
|
|
return RDSE_SAMPLEPLAYING;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
void Sword2Sound::SetSpeechVolume(uint8 volume) {
|
2003-07-28 01:47:41 +00:00
|
|
|
speechVol = volume;
|
2003-09-16 07:11:29 +00:00
|
|
|
if (soundHandleSpeech != 0 && !speechMuted && GetSpeechStatus() == RDSE_SAMPLEPLAYING) {
|
2003-08-31 20:26:21 +00:00
|
|
|
g_engine->_mixer->setChannelVolume(soundHandleSpeech, 16 * speechVol);
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
uint8 Sword2Sound::GetSpeechVolume() {
|
2003-07-28 01:47:41 +00:00
|
|
|
return speechVol;
|
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
void Sword2Sound::MuteSpeech(uint8 mute) {
|
2003-07-28 01:47:41 +00:00
|
|
|
speechMuted = mute;
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
if (GetSpeechStatus() == RDSE_SAMPLEPLAYING) {
|
2003-09-21 14:26:25 +00:00
|
|
|
byte volume = mute ? 0 : 16 * speechVol;
|
|
|
|
|
|
|
|
g_engine->_mixer->setChannelVolume(soundHandleSpeech, volume);
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
uint8 Sword2Sound::IsSpeechMute(void) {
|
2003-09-02 13:50:45 +00:00
|
|
|
return speechMuted;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::PauseSpeech(void) {
|
|
|
|
if (GetSpeechStatus() == RDSE_SAMPLEPLAYING) {
|
2003-07-28 01:47:41 +00:00
|
|
|
speechPaused = 1;
|
2003-09-02 13:50:45 +00:00
|
|
|
g_engine->_mixer->pauseHandle(soundHandleSpeech, true);
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::UnpauseSpeech(void) {
|
|
|
|
if (speechPaused) {
|
2003-07-28 01:47:41 +00:00
|
|
|
speechPaused = 0;
|
2003-09-02 13:50:45 +00:00
|
|
|
g_engine->_mixer->pauseHandle(soundHandleSpeech, false);
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::OpenFx(int32 id, uint8 *data) {
|
2003-09-16 07:11:29 +00:00
|
|
|
int32 i, fxi;
|
|
|
|
uint32 *data32 = NULL;
|
|
|
|
_wavHeader *wav;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
|
|
|
wav = (_wavHeader *) data;
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
if (soundOn) {
|
2003-07-28 01:47:41 +00:00
|
|
|
// Check for a valid id.
|
|
|
|
if (id == 0)
|
2003-09-16 07:11:29 +00:00
|
|
|
return RDERR_INVALIDID;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
|
|
|
// Check that the fx is not already open
|
2003-08-30 18:06:08 +00:00
|
|
|
for (i = 0; i < MAXFX; i++) {
|
2003-09-21 14:26:25 +00:00
|
|
|
if (fx[i]._id == id)
|
2003-09-16 07:11:29 +00:00
|
|
|
return RDERR_FXALREADYOPEN;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
|
|
|
|
// Now choose a free slot for the fx
|
2003-09-21 14:26:25 +00:00
|
|
|
for (fxi = 0; fxi < MAXFX; fxi++) {
|
|
|
|
if (fx[fxi]._id == 0)
|
2003-07-28 01:47:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-09-04 10:58:55 +00:00
|
|
|
if (fxi == MAXFX) {
|
|
|
|
// Expire the first sound effect that isn't currently
|
|
|
|
// playing.
|
|
|
|
|
|
|
|
// FIXME. This may need a bit of work. I still haven't
|
|
|
|
// grasped all the intricacies of the sound effects
|
|
|
|
// handling.
|
|
|
|
//
|
|
|
|
// Anyway, it'd be nicer - in theory - to expire the
|
|
|
|
// least recently used slot.
|
2003-09-21 14:26:25 +00:00
|
|
|
//
|
|
|
|
// This used to be done by the "garbage collector" in
|
|
|
|
// FxServer().
|
2003-09-04 10:58:55 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
for (fxi = 0; fxi < MAXFX; fxi++) {
|
|
|
|
if (!fx[fxi]._handle)
|
2003-09-04 10:58:55 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Still no dice? I give up!
|
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
if (fxi == MAXFX) {
|
|
|
|
warning("OpenFx: No free sound slots");
|
2003-09-16 07:11:29 +00:00
|
|
|
return RDERR_NOFREEBUFFERS;
|
2003-09-21 14:26:25 +00:00
|
|
|
}
|
2003-09-04 10:58:55 +00:00
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
// Set the sample size - search for the size of the data.
|
2003-07-28 01:47:41 +00:00
|
|
|
i = 0;
|
2003-08-30 18:06:08 +00:00
|
|
|
while (i < 100) {
|
|
|
|
if (*data == 'd') {
|
2003-09-21 14:26:25 +00:00
|
|
|
data32 = (uint32 *) data;
|
2003-09-13 11:39:25 +00:00
|
|
|
if (READ_UINT32(data32) == MKID('data'))
|
2003-08-30 18:06:08 +00:00
|
|
|
break;
|
|
|
|
}
|
2003-09-21 14:26:25 +00:00
|
|
|
i++;
|
2003-08-30 18:06:08 +00:00
|
|
|
data++;
|
|
|
|
}
|
2003-09-22 06:36:38 +00:00
|
|
|
|
2003-08-31 10:38:32 +00:00
|
|
|
if (!data32)
|
2003-09-16 07:11:29 +00:00
|
|
|
return RDERR_INVALIDWAV;
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[fxi]._bufSize = READ_LE_UINT32(data32 + 1);
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
// Fill the speech buffer with data
|
2003-09-21 14:26:25 +00:00
|
|
|
if (fx[fxi]._buf != NULL)
|
|
|
|
free(fx[fxi]._buf);
|
|
|
|
fx[fxi]._buf = (uint16 *) malloc(fx[fxi]._bufSize);
|
|
|
|
memcpy(fx[fxi]._buf, (uint8 *) (data32 + 2), fx[fxi]._bufSize);
|
|
|
|
fx[fxi]._flags = SoundMixer::FLAG_16BITS;
|
2003-09-13 01:59:11 +00:00
|
|
|
if (FROM_LE_16(wav->channels) == 2)
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[fxi]._flags |= SoundMixer::FLAG_STEREO;
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[fxi]._rate = FROM_LE_16(wav->samplesPerSec);
|
2003-08-31 10:45:14 +00:00
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
// Until the mixer supports LE samples natively, we need to
|
|
|
|
// convert our LE ones to BE
|
2003-09-21 14:26:25 +00:00
|
|
|
for (int32 j = 0; j < fx[fxi]._bufSize / 2; j++)
|
|
|
|
fx[fxi]._buf[j] = SWAP_BYTES_16(fx[fxi]._buf[j]);
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[fxi]._id = id;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::PlayFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type) {
|
|
|
|
int32 i, loop;
|
2003-08-31 00:00:09 +00:00
|
|
|
uint32 hr;
|
2003-08-30 20:27:48 +00:00
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
if (type == RDSE_FXLOOP)
|
|
|
|
loop = 1;
|
|
|
|
else
|
|
|
|
loop = 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
if (soundOn) {
|
|
|
|
if (data == NULL) {
|
|
|
|
if (type == RDSE_FXLEADOUT) {
|
2003-09-03 06:27:25 +00:00
|
|
|
id = (int32) 0xffffffff;
|
2003-08-30 18:06:08 +00:00
|
|
|
i = GetFxIndex(id);
|
|
|
|
if (i == MAXFX) {
|
2003-09-04 10:58:55 +00:00
|
|
|
warning("PlayFx(%d, %d, %d, %d) - Not open", id, vol, pan, type);
|
2003-09-16 07:11:29 +00:00
|
|
|
return RDERR_FXNOTOPEN;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._flags &= ~SoundMixer::FLAG_LOOP;
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
// Start the sound effect playing
|
2003-09-21 14:26:25 +00:00
|
|
|
|
|
|
|
byte volume = musicMuted ? 0 : musicVolTable[musicVol];
|
|
|
|
|
|
|
|
g_engine->_mixer->playRaw(&fx[i]._handle, fx[i]._buf, fx[i]._bufSize, fx[i]._rate, fx[i]._flags, -1, volume, 0);
|
2003-08-30 18:06:08 +00:00
|
|
|
} else {
|
|
|
|
i = GetFxIndex(id);
|
|
|
|
if (i == MAXFX) {
|
2003-09-04 10:58:55 +00:00
|
|
|
warning("PlayFx(%d, %d, %d, %d) - Not open", id, vol, pan, type);
|
2003-09-16 07:11:29 +00:00
|
|
|
return RDERR_FXNOTOPEN;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
|
|
|
if (loop == 1)
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._flags |= SoundMixer::FLAG_LOOP;
|
2003-08-30 18:06:08 +00:00
|
|
|
else
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._flags &= ~SoundMixer::FLAG_LOOP;
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._volume = vol;
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
// Start the sound effect playing
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
byte volume = fxMuted ? 0 : vol * fxVol;
|
|
|
|
int8 p = panTable[pan + 16];
|
|
|
|
|
|
|
|
g_engine->_mixer->playRaw(&fx[i]._handle, fx[i]._buf, fx[i]._bufSize, fx[i]._rate, fx[i]._flags, -1, volume, p);
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (type == RDSE_FXLEADIN) {
|
2003-08-31 00:00:09 +00:00
|
|
|
id = (int32) 0xfffffffe;
|
2003-08-30 18:06:08 +00:00
|
|
|
hr = OpenFx(id, data);
|
|
|
|
if (hr != RD_OK) {
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
i = GetFxIndex(id);
|
|
|
|
if (i == MAXFX) {
|
2003-09-04 10:58:55 +00:00
|
|
|
warning("PlayFx(%d, %d, %d, %d) - Not found", id, vol, pan, type);
|
2003-08-30 18:06:08 +00:00
|
|
|
return RDERR_FXFUCKED;
|
|
|
|
}
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._flags &= ~SoundMixer::FLAG_LOOP;
|
2003-08-31 20:26:21 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
byte volume = musicMuted ? 0 : musicVolTable[musicVol];
|
|
|
|
|
|
|
|
g_engine->_mixer->playRaw(&fx[i]._handle, fx[i]._buf, fx[i]._bufSize, fx[i]._rate, fx[i]._flags, -1, volume, 0);
|
2003-08-30 18:06:08 +00:00
|
|
|
} else {
|
|
|
|
hr = OpenFx(id, data);
|
|
|
|
if (hr != RD_OK) {
|
2003-09-16 07:11:29 +00:00
|
|
|
return hr;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
i = GetFxIndex(id);
|
|
|
|
if (i == MAXFX) {
|
2003-09-04 10:58:55 +00:00
|
|
|
warning("PlayFx(%d, %d, %d, %d) - Not found", id, vol, pan, type);
|
2003-09-16 07:11:29 +00:00
|
|
|
return RDERR_FXFUCKED;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
|
|
|
if (loop == 1)
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._flags |= SoundMixer::FLAG_LOOP;
|
2003-08-30 18:06:08 +00:00
|
|
|
else
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._flags &= ~SoundMixer::FLAG_LOOP;
|
|
|
|
fx[i]._volume = vol;
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
// Start the sound effect playing
|
2003-09-21 14:26:25 +00:00
|
|
|
|
|
|
|
byte volume = fxMuted ? 0 : vol * fxVol;
|
|
|
|
int8 p = panTable[pan + 16];
|
|
|
|
|
|
|
|
g_engine->_mixer->playRaw(&fx[i]._handle, fx[i]._buf, fx[i]._bufSize, fx[i]._rate, fx[i]._flags, -1, volume, p);
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::SetFxVolumePan(int32 id, uint8 vol, int8 pan) {
|
2003-07-28 01:47:41 +00:00
|
|
|
int32 i = GetFxIndex(id);
|
|
|
|
if (i == MAXFX)
|
|
|
|
return RDERR_FXNOTOPEN;
|
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._volume = vol;
|
2003-08-30 18:06:08 +00:00
|
|
|
if (!fxMuted) {
|
2003-09-21 14:26:25 +00:00
|
|
|
g_engine->_mixer->setChannelVolume(fx[i]._handle, vol * fxVol);
|
|
|
|
g_engine->_mixer->setChannelPan(fx[i]._handle, panTable[pan + 16]);
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
return RD_OK;
|
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::SetFxIdVolume(int32 id, uint8 vol) {
|
2003-07-28 01:47:41 +00:00
|
|
|
int32 i = GetFxIndex(id);
|
2003-09-21 14:26:25 +00:00
|
|
|
|
2003-07-28 01:47:41 +00:00
|
|
|
if (i == MAXFX)
|
|
|
|
return RDERR_FXNOTOPEN;
|
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._volume = vol;
|
|
|
|
if (!fxMuted)
|
|
|
|
g_engine->_mixer->setChannelVolume(fx[i]._handle, vol * fxVol);
|
|
|
|
|
2003-07-28 01:47:41 +00:00
|
|
|
return RD_OK;
|
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::ClearAllFx(void) {
|
2003-07-28 01:47:41 +00:00
|
|
|
if (!soundOn)
|
|
|
|
return(RD_OK);
|
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
for (int i = 0; i < MAXFX; i++) {
|
|
|
|
if (fx[i]._id && fx[i]._id != (int32) 0xfffffffe && fx[i]._id != (int32) 0xffffffff) {
|
|
|
|
g_engine->_mixer->stopHandle(fx[i]._handle);
|
|
|
|
fx[i]._id = 0;
|
|
|
|
fx[i]._paused = false;
|
|
|
|
if (fx[i]._buf != NULL) {
|
|
|
|
free(fx[i]._buf);
|
|
|
|
fx[i]._buf = NULL;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._bufSize = 0;
|
|
|
|
fx[i]._flags = 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
}
|
2003-09-21 14:26:25 +00:00
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::CloseFx(int32 id) {
|
|
|
|
int i;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
|
|
|
if (!soundOn)
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
|
|
|
i = GetFxIndex(id);
|
2003-08-30 18:06:08 +00:00
|
|
|
if (i < MAXFX) {
|
2003-09-21 14:26:25 +00:00
|
|
|
g_engine->_mixer->stopHandle(fx[i]._handle);
|
|
|
|
fx[i]._id = 0;
|
|
|
|
fx[i]._paused = false;
|
|
|
|
if (fx[i]._buf != NULL) {
|
|
|
|
free(fx[i]._buf);
|
|
|
|
fx[i]._buf = NULL;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._bufSize = 0;
|
|
|
|
fx[i]._flags = 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
2003-09-21 14:26:25 +00:00
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::PauseFx(void) {
|
|
|
|
if (!fxPaused) {
|
2003-09-21 14:26:25 +00:00
|
|
|
for (int i = 0; i < MAXFX; i++) {
|
|
|
|
if (fx[i]._id) {
|
|
|
|
g_engine->_mixer->pauseHandle(fx[i]._handle, true);
|
|
|
|
fx[i]._paused = true;
|
|
|
|
} else
|
|
|
|
fx[i]._paused = false;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
fxPaused = 1;
|
|
|
|
}
|
2003-09-21 14:26:25 +00:00
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::PauseFxForSequence(void) {
|
|
|
|
if (!fxPaused) {
|
2003-09-21 14:26:25 +00:00
|
|
|
for (int i = 0; i < MAXFX; i++) {
|
|
|
|
if (fx[i]._id && fx[i]._id != (int32) 0xfffffffe) {
|
|
|
|
g_engine->_mixer->pauseHandle(fx[i]._handle, true);
|
|
|
|
fx[i]._paused = true;
|
2003-08-30 18:06:08 +00:00
|
|
|
} else {
|
2003-09-21 14:26:25 +00:00
|
|
|
fx[i]._paused = false;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fxPaused = 1;
|
|
|
|
}
|
2003-09-21 14:26:25 +00:00
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::UnpauseFx(void) {
|
|
|
|
if (fxPaused) {
|
2003-09-21 14:26:25 +00:00
|
|
|
for (int i = 0; i < MAXFX; i++) {
|
|
|
|
if (fx[i]._paused && fx[i]._id) {
|
|
|
|
g_engine->_mixer->pauseHandle(fx[i]._handle, false);
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fxPaused = 0;
|
|
|
|
}
|
2003-09-21 14:26:25 +00:00
|
|
|
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
uint8 Sword2Sound::GetFxVolume() {
|
2003-07-28 01:47:41 +00:00
|
|
|
return fxVol;
|
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
void Sword2Sound::SetFxVolume(uint8 volume) {
|
2003-07-28 01:47:41 +00:00
|
|
|
fxVol = volume;
|
|
|
|
|
|
|
|
// Now update the volume of any fxs playing
|
2003-09-21 14:26:25 +00:00
|
|
|
for (int i = 0; i < MAXFX; i++) {
|
|
|
|
if (fx[i]._id && !fxMuted)
|
|
|
|
g_engine->_mixer->setChannelVolume(fx[i]._handle, fx[i]._volume * fxVol);
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
void Sword2Sound::MuteFx(uint8 mute) {
|
2003-07-28 01:47:41 +00:00
|
|
|
fxMuted = mute;
|
|
|
|
|
|
|
|
// Now update the volume of any fxs playing
|
2003-09-21 14:26:25 +00:00
|
|
|
for (int i = 0; i < MAXFX; i++) {
|
|
|
|
if (fx[i]._id) {
|
|
|
|
byte volume = mute ? 0 : fx[i]._volume * fxVol;
|
|
|
|
|
|
|
|
g_engine->_mixer->setChannelVolume(fx[i]._handle, volume);
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
uint8 Sword2Sound::IsFxMute(void) {
|
2003-09-16 07:11:29 +00:00
|
|
|
return fxMuted;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
int32 Sword2Sound::StreamCompMusic(const char *filename, uint32 musicId, bool looping) {
|
2003-09-04 10:58:55 +00:00
|
|
|
StackLock lock(_mutex);
|
|
|
|
return StreamCompMusicFromLock(filename, musicId, looping);
|
|
|
|
}
|
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
int32 Sword2Sound::StreamCompMusicFromLock(const char *filename, uint32 musicId, bool looping) {
|
2003-08-31 10:38:32 +00:00
|
|
|
int32 primaryStream = -1;
|
|
|
|
int32 secondaryStream = -1;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
compressedMusic = 1;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-31 10:38:32 +00:00
|
|
|
// If both music streams are playing, that should mean one of them is
|
|
|
|
// fading out. Pick that one.
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
if (music[0]._streaming && music[1]._streaming) {
|
|
|
|
if (music[0]._fading)
|
2003-08-31 10:38:32 +00:00
|
|
|
primaryStream = 0;
|
|
|
|
else
|
|
|
|
primaryStream = 1;
|
2003-08-02 02:31:36 +00:00
|
|
|
|
2003-09-25 06:11:07 +00:00
|
|
|
music[primaryStream]._fading = 0;
|
2003-09-21 14:26:25 +00:00
|
|
|
music[primaryStream]._streaming = false;
|
2003-08-31 10:38:32 +00:00
|
|
|
}
|
2003-08-02 02:31:36 +00:00
|
|
|
|
2003-08-31 10:38:32 +00:00
|
|
|
// Pick the available music stream. If no music is playing it doesn't
|
|
|
|
// matter which we use, so pick the first one.
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
if (music[0]._streaming || music[1]._streaming) {
|
|
|
|
if (music[0]._streaming) {
|
2003-08-31 10:38:32 +00:00
|
|
|
primaryStream = 1;
|
|
|
|
secondaryStream = 0;
|
2003-08-30 18:06:08 +00:00
|
|
|
} else {
|
2003-08-31 10:38:32 +00:00
|
|
|
primaryStream = 0;
|
|
|
|
secondaryStream = 1;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-08-31 10:38:32 +00:00
|
|
|
} else
|
|
|
|
primaryStream = 0;
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
strcpy(music[primaryStream]._fileName, filename);
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-08-31 10:38:32 +00:00
|
|
|
// Save looping info and tune id
|
2003-09-21 14:26:25 +00:00
|
|
|
music[primaryStream]._looping = looping;
|
|
|
|
music[primaryStream]._id = musicId;
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-08-31 10:38:32 +00:00
|
|
|
// Don't start streaming if the volume is off.
|
|
|
|
if (IsMusicMute())
|
|
|
|
return RD_OK;
|
2003-08-02 02:31:36 +00:00
|
|
|
|
2003-08-31 10:38:32 +00:00
|
|
|
// Always use fpMus[0] (all music in one cluster)
|
|
|
|
// musFilePos[primaryStream] for different pieces of music.
|
|
|
|
if (!fpMus.isOpen())
|
2003-09-17 21:06:16 +00:00
|
|
|
fpMus.open(filename);
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-08-31 10:38:32 +00:00
|
|
|
if (!fpMus.isOpen())
|
|
|
|
return RDERR_INVALIDFILENAME;
|
2003-08-02 02:31:36 +00:00
|
|
|
|
2003-08-31 10:38:32 +00:00
|
|
|
// Start other music stream fading out
|
2003-09-21 14:26:25 +00:00
|
|
|
if (secondaryStream != -1 && !music[secondaryStream]._fading)
|
2003-09-25 06:11:07 +00:00
|
|
|
music[secondaryStream]._fading = FADE_SAMPLES;
|
2003-08-02 02:31:36 +00:00
|
|
|
|
2003-08-31 10:38:32 +00:00
|
|
|
fpMus.seek((musicId + 1) * 8, SEEK_SET);
|
2003-09-21 14:26:25 +00:00
|
|
|
music[primaryStream]._filePos = fpMus.readUint32LE();
|
|
|
|
music[primaryStream]._fileEnd = fpMus.readUint32LE();
|
2003-08-02 02:31:36 +00:00
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
if (!music[primaryStream]._filePos || !music[primaryStream]._fileEnd)
|
2003-08-31 10:38:32 +00:00
|
|
|
return RDERR_INVALIDID;
|
2003-08-02 02:31:36 +00:00
|
|
|
|
2003-08-31 10:38:32 +00:00
|
|
|
// Calculate the file position of the end of the music
|
2003-09-21 14:26:25 +00:00
|
|
|
music[primaryStream]._fileEnd += music[primaryStream]._filePos;
|
2003-08-02 02:31:36 +00:00
|
|
|
|
2003-09-25 11:35:54 +00:00
|
|
|
// We used to read two bytes for _lastSample, but doing that breaks
|
|
|
|
// some of the music, so I guess that was a bug. Maybe.
|
|
|
|
|
|
|
|
music[primaryStream]._lastSample = fpMus.readByte();
|
|
|
|
music[primaryStream]._filePos++;
|
2003-09-21 14:26:25 +00:00
|
|
|
music[primaryStream]._streaming = true;
|
2003-09-25 06:11:07 +00:00
|
|
|
|
2003-08-31 10:38:32 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-25 06:11:07 +00:00
|
|
|
void Sword2Sound::UpdateCompSampleStreaming(int16 *data, uint len) {
|
|
|
|
uint32 i;
|
2003-08-30 18:06:08 +00:00
|
|
|
|
|
|
|
for (i = 0; i < MAXMUS; i++) {
|
2003-09-21 14:26:25 +00:00
|
|
|
if (!music[i]._streaming)
|
2003-09-05 11:12:40 +00:00
|
|
|
continue;
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-25 06:11:07 +00:00
|
|
|
// Modify the volume according to the master volume and music
|
|
|
|
// mute state
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-25 06:11:07 +00:00
|
|
|
byte volume = musicMuted ? 0 : musicVolTable[musicVol];
|
2003-09-05 11:12:40 +00:00
|
|
|
|
2003-09-25 06:11:07 +00:00
|
|
|
fpMus.seek(music[i]._filePos, SEEK_SET);
|
|
|
|
_converter->flow(music[i], data, len, volume, volume);
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-25 06:11:07 +00:00
|
|
|
if (music[i].eos()) {
|
|
|
|
// End of the music so we need to start fading and
|
|
|
|
// start the music again
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-05 11:12:40 +00:00
|
|
|
// FIXME: The original code faded the music here, but
|
|
|
|
// to do that we need to start before we reach the end
|
|
|
|
// of the file.
|
2003-09-21 14:26:25 +00:00
|
|
|
//
|
|
|
|
// On the other hand, do we want to fade out the end
|
|
|
|
// of the music?
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-05 11:12:40 +00:00
|
|
|
// Fade the old music
|
|
|
|
// musFading[i] = -16;
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-05 11:12:40 +00:00
|
|
|
// Loop if neccassary
|
2003-09-25 06:11:07 +00:00
|
|
|
if (music[i]._looping) {
|
|
|
|
music[i]._streaming = false;
|
2003-09-21 14:26:25 +00:00
|
|
|
StreamCompMusicFromLock(music[i]._fileName, music[i]._id, music[i]._looping);
|
2003-09-25 06:11:07 +00:00
|
|
|
}
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
|
|
|
}
|
2003-09-05 16:07:03 +00:00
|
|
|
|
|
|
|
// FIXME: We need to implement DipMusic()'s functionality, but since
|
|
|
|
// our sound buffer is much shorter than the original's it should be
|
|
|
|
// enough to simply modify the channel volume in this function instead
|
|
|
|
// of using a separate function to modify part of the sound buffer.
|
|
|
|
|
|
|
|
// DipMusic();
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::DipMusic() {
|
|
|
|
// disable this func for now
|
|
|
|
return RD_OK;
|
|
|
|
|
2003-07-28 01:47:41 +00:00
|
|
|
/*
|
|
|
|
int32 len;
|
|
|
|
int32 readCursor, writeCursor;
|
|
|
|
int32 dwBytes1, dwBytes2;
|
|
|
|
int16 *sample;
|
|
|
|
int32 total = 0;
|
|
|
|
int32 i;
|
|
|
|
int32 status;
|
|
|
|
LPVOID lpv1, lpv2;
|
|
|
|
HRESULT hr = DS_OK;
|
|
|
|
LPDIRECTSOUNDBUFFER dsbMusic = NULL;
|
|
|
|
|
|
|
|
int32 currentMusicVol = musicVolTable[volMusic[0]];
|
|
|
|
int32 minMusicVol;
|
|
|
|
|
|
|
|
// Find which music buffer is currently playing
|
|
|
|
for (i = 0; i<MAXMUS && !dsbMusic; i++)
|
|
|
|
{
|
|
|
|
if (musStreaming[i] && musFading[i] == 0)
|
|
|
|
dsbMusic = lpDsbMus[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((!musicMuted) && dsbMusic && (!speechMuted) && (volMusic[0]>2))
|
|
|
|
{
|
|
|
|
minMusicVol = musicVolTable[volMusic[0] - 3];
|
|
|
|
|
|
|
|
if (speechStatus)
|
|
|
|
{
|
|
|
|
IDirectSoundBuffer_GetStatus(dsbSpeech, &status);
|
|
|
|
if ((hr = IDirectSoundBuffer_GetCurrentPosition(dsbMusic, &readCursor, &writeCursor)) != DS_OK)
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
len = 44100 / 12 ;// 12th of a second
|
|
|
|
|
|
|
|
if ((hr = IDirectSoundBuffer_Lock(dsbMusic, readCursor, len, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0)) != DS_OK)
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
for (i = 0, sample = (int16*)lpv1; sample<(int16*)((int8*)lpv1+dwBytes1); sample+= 30, i++) // 60 samples
|
|
|
|
{
|
|
|
|
if (*sample>0)
|
|
|
|
total += *sample;
|
|
|
|
else
|
|
|
|
total -= *sample;
|
|
|
|
}
|
|
|
|
|
|
|
|
total /= i;
|
|
|
|
|
|
|
|
total = minMusicVol + ( ( (currentMusicVol - minMusicVol) * total ) / 8000);
|
|
|
|
|
|
|
|
if (total > currentMusicVol)
|
|
|
|
total = currentMusicVol;
|
|
|
|
|
|
|
|
IDirectSoundBuffer_SetVolume(dsbMusic, total);
|
|
|
|
|
|
|
|
IDirectSoundBuffer_Unlock(dsbMusic,lpv1,dwBytes1,lpv2,dwBytes2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IDirectSoundBuffer_GetVolume(dsbMusic, &total);
|
|
|
|
total += 50;
|
|
|
|
if (total > currentMusicVol)
|
|
|
|
total = currentMusicVol;
|
|
|
|
|
|
|
|
IDirectSoundBuffer_SetVolume(dsbMusic, total);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (hr);
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::MusicTimeRemaining() {
|
2003-09-04 10:58:55 +00:00
|
|
|
StackLock lock(_mutex);
|
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
for (int i = 0; i < MAXMUS; i++) {
|
|
|
|
if (music[i]._streaming && !music[i]._fading)
|
|
|
|
return (music[i]._fileEnd - music[i]._filePos) / 22050;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
return 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
void Sword2Sound::StopMusic(void) {
|
2003-09-04 10:58:55 +00:00
|
|
|
StackLock lock(_mutex);
|
|
|
|
|
2003-09-21 14:26:25 +00:00
|
|
|
for (int i = 0; i < MAXMUS; i++) {
|
|
|
|
if (music[i]._streaming)
|
2003-09-25 06:11:07 +00:00
|
|
|
music[i]._fading = FADE_SAMPLES;
|
2003-08-30 18:06:08 +00:00
|
|
|
else
|
2003-09-21 14:26:25 +00:00
|
|
|
music[i]._looping = false;
|
2003-08-30 18:06:08 +00:00
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::PauseMusic(void) {
|
2003-09-04 10:58:55 +00:00
|
|
|
StackLock lock(_mutex);
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
if (soundOn) {
|
2003-09-21 14:26:25 +00:00
|
|
|
for (int i = 0; i < MAXMUS; i++) {
|
|
|
|
if (music[i]._streaming) {
|
|
|
|
music[i]._paused = true;
|
2003-08-30 18:06:08 +00:00
|
|
|
} else {
|
2003-09-21 14:26:25 +00:00
|
|
|
music[i]._paused = false;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
int32 Sword2Sound::UnpauseMusic(void) {
|
2003-09-04 10:58:55 +00:00
|
|
|
StackLock lock(_mutex);
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
if (soundOn) {
|
2003-09-25 06:11:07 +00:00
|
|
|
for (int i = 0; i < MAXMUS; i++)
|
|
|
|
music[i]._paused = false;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
2003-09-16 07:11:29 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
void Sword2Sound::SetMusicVolume(uint8 volume) {
|
2003-09-21 14:26:25 +00:00
|
|
|
musicVol = volume;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
uint8 Sword2Sound::GetMusicVolume() {
|
2003-09-21 14:26:25 +00:00
|
|
|
return musicVol;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
void Sword2Sound::MuteMusic(uint8 mute) {
|
2003-07-28 01:47:41 +00:00
|
|
|
musicMuted = mute;
|
|
|
|
}
|
|
|
|
|
2003-08-30 18:06:08 +00:00
|
|
|
uint8 Sword2Sound::IsMusicMute(void) {
|
2003-09-16 07:11:29 +00:00
|
|
|
return musicMuted;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|