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-09-26 14:19:03 +00:00
|
|
|
// FIXME: One feature still missing is the original's DipMusic() function
|
|
|
|
// which, as far as I can understand, softened the music volume when someone
|
|
|
|
// was speaking, but only if the music was playing loudly at the time.
|
|
|
|
//
|
|
|
|
// I'm not sure if we can implement this in any sensible fashion - I don't
|
|
|
|
// think we have that fine-grained control over the mixer - or if we really
|
|
|
|
// want it anyway.
|
|
|
|
//
|
|
|
|
// Simply adjusting the volume paramters to flow() is not enough. If you
|
|
|
|
// only adjust them a little you won't hear the difference anyway, and if you
|
|
|
|
// adjust them a lot it will sound really bad.
|
|
|
|
//
|
|
|
|
// Does anyone who can run the original interpreter have any
|
|
|
|
// opinions on this?
|
|
|
|
|
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] = {
|
2003-09-26 14:19:03 +00:00
|
|
|
-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-08-31 20:26:21 +00:00
|
|
|
};
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-31 20:26:21 +00:00
|
|
|
int32 musicVolTable[17] = {
|
2003-09-26 14:19:03 +00:00
|
|
|
0, 15, 31, 47, 63, 79, 95, 111, 127,
|
|
|
|
143, 159, 175, 191, 207, 223, 239, 255
|
2003-08-31 20:26:21 +00:00
|
|
|
};
|
2003-09-21 14:26:25 +00:00
|
|
|
|
2003-09-25 06:11:07 +00:00
|
|
|
int16 MusicHandle::read() {
|
|
|
|
uint8 in;
|
Ok, I'm stupid.
The initial sample is, indeed, two bytes, just like the rest of them, but
it really, really helps if you read it from the correct position in the
file.
After fixing that, it turned out that my changing of signedness of the
sample was also wrong. Funny how those two bugs almost cancelled each other
out. Almost.
I've made a few other changes as well, but they're just to clean things up
a bit. The credits music works for me, and I've played the game up to
arriving in Quaramonte, with no obvious music-related problems.
svn-id: r10412
2003-09-26 06:26:18 +00:00
|
|
|
uint16 delta;
|
2003-09-25 06:11:07 +00:00
|
|
|
int16 out;
|
|
|
|
|
|
|
|
if (!_streaming)
|
|
|
|
return 0;
|
|
|
|
|
Ok, I'm stupid.
The initial sample is, indeed, two bytes, just like the rest of them, but
it really, really helps if you read it from the correct position in the
file.
After fixing that, it turned out that my changing of signedness of the
sample was also wrong. Funny how those two bugs almost cancelled each other
out. Almost.
I've made a few other changes as well, but they're just to clean things up
a bit. The credits music works for me, and I've played the game up to
arriving in Quaramonte, with no obvious music-related problems.
svn-id: r10412
2003-09-26 06:26:18 +00:00
|
|
|
if (_firstTime) {
|
|
|
|
_lastSample = fpMus.readUint16LE();
|
|
|
|
_filePos += 2;
|
|
|
|
_firstTime = false;
|
|
|
|
return _lastSample;
|
|
|
|
}
|
|
|
|
|
2003-09-25 06:11:07 +00:00
|
|
|
// Assume the file handle has been correctly positioned already.
|
|
|
|
|
|
|
|
in = fpMus.readByte();
|
|
|
|
delta = GetCompressedAmplitude(in) << GetCompressedShift(in);
|
|
|
|
|
|
|
|
if (GetCompressedSign(in))
|
Ok, I'm stupid.
The initial sample is, indeed, two bytes, just like the rest of them, but
it really, really helps if you read it from the correct position in the
file.
After fixing that, it turned out that my changing of signedness of the
sample was also wrong. Funny how those two bugs almost cancelled each other
out. Almost.
I've made a few other changes as well, but they're just to clean things up
a bit. The credits music works for me, and I've played the game up to
arriving in Quaramonte, with no obvious music-related problems.
svn-id: r10412
2003-09-26 06:26:18 +00:00
|
|
|
out = _lastSample - delta;
|
2003-09-25 06:11:07 +00:00
|
|
|
else
|
Ok, I'm stupid.
The initial sample is, indeed, two bytes, just like the rest of them, but
it really, really helps if you read it from the correct position in the
file.
After fixing that, it turned out that my changing of signedness of the
sample was also wrong. Funny how those two bugs almost cancelled each other
out. Almost.
I've made a few other changes as well, but they're just to clean things up
a bit. The credits music works for me, and I've played the game up to
arriving in Quaramonte, with no obvious music-related problems.
svn-id: r10412
2003-09-26 06:26:18 +00:00
|
|
|
out = _lastSample + delta;
|
2003-09-25 06:11:07 +00:00
|
|
|
|
|
|
|
_filePos++;
|
Ok, I'm stupid.
The initial sample is, indeed, two bytes, just like the rest of them, but
it really, really helps if you read it from the correct position in the
file.
After fixing that, it turned out that my changing of signedness of the
sample was also wrong. Funny how those two bugs almost cancelled each other
out. Almost.
I've made a few other changes as well, but they're just to clean things up
a bit. The credits music works for me, and I've played the game up to
arriving in Quaramonte, with no obvious music-related problems.
svn-id: r10412
2003-09-26 06:26:18 +00:00
|
|
|
_lastSample = out;
|
2003-09-25 06:11:07 +00:00
|
|
|
|
Ok, I'm stupid.
The initial sample is, indeed, two bytes, just like the rest of them, but
it really, really helps if you read it from the correct position in the
file.
After fixing that, it turned out that my changing of signedness of the
sample was also wrong. Funny how those two bugs almost cancelled each other
out. Almost.
I've made a few other changes as well, but they're just to clean things up
a bit. The credits music works for me, and I've played the game up to
arriving in Quaramonte, with no obvious music-related problems.
svn-id: r10412
2003-09-26 06:26:18 +00:00
|
|
|
if (_looping) {
|
|
|
|
if (_filePos >= _fileEnd) {
|
|
|
|
_firstTime = true;
|
|
|
|
_filePos = _fileStart;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Fade out at the end of the music. Is this really desirable
|
|
|
|
// behaviour?
|
|
|
|
|
|
|
|
if (_fileEnd - _filePos <= FADE_SAMPLES)
|
|
|
|
_fading = _fileEnd - _filePos;
|
|
|
|
}
|
2003-09-25 06:11:07 +00:00
|
|
|
|
|
|
|
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;
|
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;
|
|
|
|
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-27 16:10:43 +00:00
|
|
|
// Save/Restore information about current music so that we can restore it
|
|
|
|
// after the credits.
|
|
|
|
|
|
|
|
void Sword2Sound::saveMusicState() {
|
|
|
|
StackLock lock(_mutex);
|
|
|
|
|
|
|
|
int saveStream;
|
|
|
|
|
|
|
|
if (music[0]._streaming && !music[0]._fading) {
|
|
|
|
saveStream = 0;
|
|
|
|
} else if (music[1]._streaming && !music[0]._fading) {
|
|
|
|
saveStream = 1;
|
|
|
|
} else {
|
|
|
|
music[2]._streaming = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
music[2]._streaming = true;
|
|
|
|
music[2]._fading = 0;
|
|
|
|
music[2]._looping = music[saveStream]._looping;
|
|
|
|
music[2]._fileStart = music[saveStream]._fileStart;
|
|
|
|
music[2]._filePos = music[saveStream]._filePos;
|
|
|
|
music[2]._fileEnd = music[saveStream]._fileEnd;
|
|
|
|
music[2]._lastSample = music[saveStream]._lastSample;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sword2Sound::restoreMusicState() {
|
|
|
|
StackLock lock(_mutex);
|
|
|
|
|
|
|
|
int restoreStream;
|
|
|
|
|
|
|
|
if (!music[2]._streaming)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Fade out any music that happens to be playing
|
|
|
|
|
|
|
|
for (int i = 0; i < MAXMUS; i++) {
|
|
|
|
if (music[i]._streaming && !music[i]._fading)
|
|
|
|
music[i]._fading = FADE_SAMPLES;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!music[0]._streaming && !music[0]._fading) {
|
|
|
|
restoreStream = 0;
|
|
|
|
} else {
|
|
|
|
restoreStream = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
music[restoreStream]._streaming = true;
|
|
|
|
music[restoreStream]._fading = 0;
|
|
|
|
music[restoreStream]._looping = music[2]._looping;
|
|
|
|
music[restoreStream]._fileStart = music[2]._fileStart;
|
|
|
|
music[restoreStream]._filePos = music[2]._filePos;
|
|
|
|
music[restoreStream]._fileEnd = music[2]._fileEnd;
|
|
|
|
music[restoreStream]._lastSample = music[2]._lastSample;
|
|
|
|
}
|
|
|
|
|
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-26 14:19:03 +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
|
|
|
// 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) {
|
Ok, I'm stupid.
The initial sample is, indeed, two bytes, just like the rest of them, but
it really, really helps if you read it from the correct position in the
file.
After fixing that, it turned out that my changing of signedness of the
sample was also wrong. Funny how those two bugs almost cancelled each other
out. Almost.
I've made a few other changes as well, but they're just to clean things up
a bit. The credits music works for me, and I've played the game up to
arriving in Quaramonte, with no obvious music-related problems.
svn-id: r10412
2003-09-26 06:26:18 +00:00
|
|
|
uint32 len;
|
2003-08-31 10:38:32 +00:00
|
|
|
int32 primaryStream = -1;
|
|
|
|
int32 secondaryStream = -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-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-09-26 14:19:03 +00:00
|
|
|
// The assumption here is that we are never playing music from two
|
|
|
|
// different files at the same time.
|
|
|
|
|
2003-08-31 10:38:32 +00:00
|
|
|
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);
|
Ok, I'm stupid.
The initial sample is, indeed, two bytes, just like the rest of them, but
it really, really helps if you read it from the correct position in the
file.
After fixing that, it turned out that my changing of signedness of the
sample was also wrong. Funny how those two bugs almost cancelled each other
out. Almost.
I've made a few other changes as well, but they're just to clean things up
a bit. The credits music works for me, and I've played the game up to
arriving in Quaramonte, with no obvious music-related problems.
svn-id: r10412
2003-09-26 06:26:18 +00:00
|
|
|
music[primaryStream]._fileStart = fpMus.readUint32LE();
|
|
|
|
len = fpMus.readUint32LE();
|
2003-08-02 02:31:36 +00:00
|
|
|
|
Ok, I'm stupid.
The initial sample is, indeed, two bytes, just like the rest of them, but
it really, really helps if you read it from the correct position in the
file.
After fixing that, it turned out that my changing of signedness of the
sample was also wrong. Funny how those two bugs almost cancelled each other
out. Almost.
I've made a few other changes as well, but they're just to clean things up
a bit. The credits music works for me, and I've played the game up to
arriving in Quaramonte, with no obvious music-related problems.
svn-id: r10412
2003-09-26 06:26:18 +00:00
|
|
|
if (!music[primaryStream]._fileStart || !len)
|
2003-08-31 10:38:32 +00:00
|
|
|
return RDERR_INVALIDID;
|
2003-08-02 02:31:36 +00:00
|
|
|
|
Ok, I'm stupid.
The initial sample is, indeed, two bytes, just like the rest of them, but
it really, really helps if you read it from the correct position in the
file.
After fixing that, it turned out that my changing of signedness of the
sample was also wrong. Funny how those two bugs almost cancelled each other
out. Almost.
I've made a few other changes as well, but they're just to clean things up
a bit. The credits music works for me, and I've played the game up to
arriving in Quaramonte, with no obvious music-related problems.
svn-id: r10412
2003-09-26 06:26:18 +00:00
|
|
|
music[primaryStream]._fileEnd = music[primaryStream]._fileStart + len;
|
|
|
|
music[primaryStream]._filePos = music[primaryStream]._fileStart;
|
2003-09-21 14:26:25 +00:00
|
|
|
music[primaryStream]._streaming = true;
|
Ok, I'm stupid.
The initial sample is, indeed, two bytes, just like the rest of them, but
it really, really helps if you read it from the correct position in the
file.
After fixing that, it turned out that my changing of signedness of the
sample was also wrong. Funny how those two bugs almost cancelled each other
out. Almost.
I've made a few other changes as well, but they're just to clean things up
a bit. The credits music works for me, and I've played the game up to
arriving in Quaramonte, with no obvious music-related problems.
svn-id: r10412
2003-09-26 06:26:18 +00:00
|
|
|
music[primaryStream]._firstTime = 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) {
|
Ok, I'm stupid.
The initial sample is, indeed, two bytes, just like the rest of them, but
it really, really helps if you read it from the correct position in the
file.
After fixing that, it turned out that my changing of signedness of the
sample was also wrong. Funny how those two bugs almost cancelled each other
out. Almost.
I've made a few other changes as well, but they're just to clean things up
a bit. The credits music works for me, and I've played the game up to
arriving in Quaramonte, with no obvious music-related problems.
svn-id: r10412
2003-09-26 06:26:18 +00:00
|
|
|
for (int i = 0; i < MAXMUS; i++) {
|
2003-09-26 14:19:03 +00:00
|
|
|
if (!music[i]._streaming || music[i]._paused)
|
2003-09-05 11:12:40 +00:00
|
|
|
continue;
|
2003-08-30 18:06:08 +00:00
|
|
|
|
2003-09-26 14:19:03 +00:00
|
|
|
st_sample_t 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-05 16:07:03 +00:00
|
|
|
|
|
|
|
// 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
|
|
|
}
|