2012-04-30 09:27:12 +10:00
|
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
|
*
|
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
|
*
|
|
|
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
*
|
|
|
|
|
*/
|
2012-05-14 07:43:50 +02:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This code is based on original Tony Tough source code
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 1997-2003 Nayma Software
|
|
|
|
|
*/
|
2012-04-30 09:27:12 +10:00
|
|
|
|
|
2012-06-10 21:23:28 -04:00
|
|
|
|
#include "audio/audiostream.h"
|
|
|
|
|
#include "audio/decoders/adpcm.h"
|
|
|
|
|
#include "audio/decoders/raw.h"
|
|
|
|
|
#include "audio/decoders/wave.h"
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#include "common/textconsole.h"
|
2012-04-30 09:27:12 +10:00
|
|
|
|
#include "tony/game.h"
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#include "tony/tony.h"
|
2012-04-30 09:27:12 +10:00
|
|
|
|
|
|
|
|
|
namespace Tony {
|
|
|
|
|
|
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
/****************************************************************************\
|
|
|
|
|
* Defines
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
#define RELEASE(x) {if ((x) != NULL) { (x)->release(); x = NULL; }}
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Metodi per FPSound
|
2012-05-03 21:43:00 +10:00
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Function: FPSound::FPSound();
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
* Description: Costruttore di default. Inizializza gli attributi.
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
FPSound::FPSound() {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_bSoundSupported = false;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Function: bool FPSound::Init();
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
* Description: Inizializza l'oggetto, e prepara tutto il necessario per
|
|
|
|
|
* creare stream e effetti sonori.
|
|
|
|
|
*
|
|
|
|
|
* Return: True se tutto OK, false in caso di errore.
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPSound::init() {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_bSoundSupported = g_system->getMixer()->isReady();
|
|
|
|
|
return _bSoundSupported;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Function: FPSound::~FPSound();
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
* Description: Deinizializza l'oggetto, disallocando la memoria.
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
FPSound::~FPSound() {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Function: bool CreateStream(FPStream** lplpStream);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Description: Alloca un oggetti di tipo FPStream, e ritorna il suo
|
2012-05-03 21:43:00 +10:00
|
|
|
|
* puntatore dopo averlo inizializzato.
|
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Input: FPStream** lplpStream Conterra' il pointer all'oggetto
|
2012-05-03 21:43:00 +10:00
|
|
|
|
* appena creato.
|
|
|
|
|
*
|
|
|
|
|
* Return: true se tutto OK, false in caso di errore
|
|
|
|
|
*
|
|
|
|
|
* Note: L'utilizzo di funzioni del tipo CreateStream(), CreateSfx(),
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* sono dovute al fatto che i costruttori delle classi FPStream
|
|
|
|
|
* e FPSfx richiedono che DirectSound sia gia' stato
|
2012-05-03 21:43:00 +10:00
|
|
|
|
* inzializzato. In questo modo quindi si evitano dei bugs
|
|
|
|
|
* che si verrebbero a creare se venisse dichiarata un oggetto
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* di tipo FPStream o FPSfx globale (o cmq prima della
|
2012-05-03 21:43:00 +10:00
|
|
|
|
* inizializzazione di DirectSound).
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPSound::createStream(FPStream **lplpStream) {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
(*lplpStream) = new FPStream(_bSoundSupported);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
|
|
|
|
return (*lplpStream != NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Function: bool CreateSfx(FPSfx** lplpSfx);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Description: Alloca un oggetti di tipo FPSfx e ritorna il suo
|
2012-05-03 21:43:00 +10:00
|
|
|
|
* puntatore dopo averlo inizializzato.
|
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Input: FPSfx** lplpSfx Conterra' il pointer all'oggetto
|
2012-05-03 21:43:00 +10:00
|
|
|
|
* appena creato.
|
|
|
|
|
*
|
|
|
|
|
* Return: true se tutto OK, false in caso di errore
|
|
|
|
|
*
|
2012-05-21 23:53:13 +02:00
|
|
|
|
* Note: Vedi le note di CreateStream()
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPSound::createSfx(FPSfx **lplpSfx) {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
(*lplpSfx) = new FPSfx(_bSoundSupported);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
|
|
|
|
return (*lplpSfx != NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: void SetMasterVolume(int dwVolume);
|
|
|
|
|
*
|
|
|
|
|
* Description: Setta il volume generale
|
|
|
|
|
*
|
|
|
|
|
* Input: int dwVolume Volume da settare (0-63)
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPSound::setMasterVolume(int dwVolume) {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
if (!_bSoundSupported)
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return;
|
|
|
|
|
|
2012-06-09 18:35:08 -04:00
|
|
|
|
g_system->getMixer()->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, CLIP<int>(dwVolume, 0, 63) * Audio::Mixer::kMaxChannelVolume / 63);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: void GetMasterVolume(int *lpdwVolume);
|
|
|
|
|
*
|
|
|
|
|
* Description: Richiede il volume generale
|
|
|
|
|
*
|
|
|
|
|
* Input: int *lpdwVolume Variabile che conterra' il volume (0-63)
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPSound::getMasterVolume(int *lpdwVolume) {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
if (!_bSoundSupported)
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-06-09 18:35:08 -04:00
|
|
|
|
*lpdwVolume = g_system->getMixer()->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) * 63 / Audio::Mixer::kMaxChannelVolume;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Metodi di FPSfx
|
2012-05-03 21:43:00 +10:00
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Function: FPSfx(bool bSoundOn);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
* Description: Costruttore di default. *NON* bisogna dichiarare direttamente
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* un oggetto, ma crearlo piuttosto tramite FPSound::CreateSfx()
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
FPSfx::FPSfx(bool bSoundOn) {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_bSoundSupported = bSoundOn;
|
|
|
|
|
_bFileLoaded = false;
|
|
|
|
|
_lastVolume = 63;
|
|
|
|
|
_hEndOfBuffer = CORO_INVALID_PID_VALUE;
|
|
|
|
|
_bIsVoice = false;
|
2012-06-12 11:35:27 -04:00
|
|
|
|
_loopStream = 0;
|
2012-06-10 22:03:52 -04:00
|
|
|
|
_rewindableStream = 0;
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_bPaused = false;
|
2012-06-11 12:20:12 +10:00
|
|
|
|
|
|
|
|
|
_vm->_activeSfx.push_back(this);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Function: ~FPSfx();
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
* Description: Distruttore di default. Si preoccupa anche di fermare il sound
|
2012-05-21 23:53:13 +02:00
|
|
|
|
* effect eventualmente in esecuzione, e disallocare la memoria
|
|
|
|
|
* da esso occupata.
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
FPSfx::~FPSfx() {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
if (!_bSoundSupported)
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return;
|
|
|
|
|
|
2012-06-10 21:23:28 -04:00
|
|
|
|
g_system->getMixer()->stopHandle(_handle);
|
2012-06-11 12:20:12 +10:00
|
|
|
|
_vm->_activeSfx.remove(this);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-06-12 11:35:27 -04:00
|
|
|
|
if (_loopStream)
|
|
|
|
|
delete _loopStream; // _rewindableStream is deleted by deleting _loopStream
|
|
|
|
|
else
|
|
|
|
|
delete _rewindableStream;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-06-10 21:23:28 -04:00
|
|
|
|
// FIXME
|
|
|
|
|
//if (hEndOfBuffer != CORO_INVALID_PID_VALUE)
|
|
|
|
|
// CloseHandle(hEndOfBuffer);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: Release();
|
|
|
|
|
*
|
|
|
|
|
* Description: Rilascia la memoria dell'oggetto. Deve essere richiamata quando
|
|
|
|
|
* l'oggetto non serve piu' e **SOLO SE** l'oggetto e' stato
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* creato con la FPSound::CreateStream().
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
* Note: Eventuali puntatori all'oggetto non sono piu' validi dopo
|
|
|
|
|
* questa chiamata.
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPSfx::release() {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
delete this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
2012-06-09 18:09:54 -04:00
|
|
|
|
* Function: bool loadWave(Common::SeekableReadStream *stream);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
* Description: Apre un file di effetto sonoro e lo carica.
|
|
|
|
|
*
|
2012-05-21 23:53:13 +02:00
|
|
|
|
* Input: byte *lpBuf Buffer dove si trova l'sfx
|
2012-05-03 21:43:00 +10:00
|
|
|
|
* uint32 dwCoded CODEC da utilizzare per decomprimere
|
|
|
|
|
* i campioni sonori
|
|
|
|
|
*
|
|
|
|
|
* Return: true se tutto OK, false in caso di errore
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPSfx::loadWave(Common::SeekableReadStream *stream) {
|
2012-06-10 21:23:28 -04:00
|
|
|
|
if (!stream)
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return false;
|
|
|
|
|
|
2012-06-10 22:03:52 -04:00
|
|
|
|
_rewindableStream = Audio::makeWAVStream(stream, DisposeAfterUse::YES);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-06-10 22:03:52 -04:00
|
|
|
|
if (!_rewindableStream)
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return false;
|
|
|
|
|
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_bFileLoaded = true;
|
|
|
|
|
setVolume(_lastVolume);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: bool LoadFile(LPSTR lpszFileName, uint32 dwCodec=FPCODEC_RAW);
|
|
|
|
|
*
|
|
|
|
|
* Description: Apre un file di effetto sonoro e lo carica.
|
|
|
|
|
*
|
|
|
|
|
* Input: LPSTR lpszFile Nome del file di sfx da aprire
|
|
|
|
|
* uint32 dwCodec CODEC da utilizzare per decomprimere
|
|
|
|
|
* i campioni sonori
|
|
|
|
|
*
|
|
|
|
|
* Return: true se tutto OK, false in caso di errore
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPSfx::loadVoiceFromVDB(Common::File &vdbFP) {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
if (!_bSoundSupported)
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return true;
|
|
|
|
|
|
2012-06-10 21:23:28 -04:00
|
|
|
|
uint32 size = vdbFP.readUint32LE();
|
|
|
|
|
uint32 rate = vdbFP.readUint32LE();
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_bIsVoice = true;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-06-10 22:03:52 -04:00
|
|
|
|
_rewindableStream = Audio::makeADPCMStream(vdbFP.readStream(size), DisposeAfterUse::YES, 0, Audio::kADPCMDVI, rate, 1);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_bFileLoaded = true;
|
2012-06-16 11:32:50 +02:00
|
|
|
|
setVolume(62);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPSfx::loadFile(const char *lpszFileName, uint32 dwCodec) {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
if (!_bSoundSupported)
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return true;
|
|
|
|
|
|
2012-06-10 21:23:28 -04:00
|
|
|
|
Common::File file;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
if (!file.open(lpszFileName)) {
|
2012-06-16 11:32:50 +02:00
|
|
|
|
warning("FPSfx::LoadFile(): Cannot open sfx file!");
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-10 21:23:28 -04:00
|
|
|
|
if (file.readUint32BE() != MKTAG('A', 'D', 'P', 0x10)) {
|
2012-06-16 11:32:50 +02:00
|
|
|
|
warning("FPSfx::LoadFile(): Invalid ADP header!");
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-10 21:23:28 -04:00
|
|
|
|
uint32 rate = file.readUint32LE();
|
|
|
|
|
uint32 channels = file.readUint32LE();
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-06-10 21:23:28 -04:00
|
|
|
|
Common::SeekableReadStream *buffer = file.readStream(file.size() - file.pos());
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-06-10 21:23:28 -04:00
|
|
|
|
if (dwCodec == FPCODEC_ADPCM) {
|
2012-06-10 22:03:52 -04:00
|
|
|
|
_rewindableStream = Audio::makeADPCMStream(buffer, DisposeAfterUse::YES, 0, Audio::kADPCMDVI, rate, channels);
|
2012-06-10 21:23:28 -04:00
|
|
|
|
} else {
|
|
|
|
|
byte flags = Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-06-10 21:23:28 -04:00
|
|
|
|
if (channels == 2)
|
|
|
|
|
flags |= Audio::FLAG_STEREO;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-06-10 22:03:52 -04:00
|
|
|
|
_rewindableStream = Audio::makeRawStream(buffer, rate, flags, DisposeAfterUse::YES);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_bFileLoaded = true;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: bool Play();
|
|
|
|
|
*
|
|
|
|
|
* Description: Suona lo sfx caricato.
|
|
|
|
|
*
|
|
|
|
|
* Return: true se tutto OK, false in caso di errore.
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPSfx::play() {
|
|
|
|
|
stop(); // sanity check
|
2012-06-10 21:23:28 -04:00
|
|
|
|
|
2012-06-16 19:04:19 +02:00
|
|
|
|
if (_bFileLoaded) {
|
2012-06-10 21:23:28 -04:00
|
|
|
|
// FIXME
|
|
|
|
|
//if (hEndOfBuffer != CORO_INVALID_PID_VALUE)
|
|
|
|
|
// ResetEvent(hEndOfBuffer);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-06-10 22:03:52 -04:00
|
|
|
|
_rewindableStream->rewind();
|
|
|
|
|
|
2012-06-12 11:35:27 -04:00
|
|
|
|
Audio::AudioStream *stream = _rewindableStream;
|
|
|
|
|
|
2012-06-16 19:04:19 +02:00
|
|
|
|
if (_bLoop) {
|
2012-06-12 11:35:27 -04:00
|
|
|
|
if (!_loopStream)
|
|
|
|
|
_loopStream = Audio::makeLoopingAudioStream(_rewindableStream, 0);
|
|
|
|
|
|
|
|
|
|
stream = _loopStream;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_handle, stream, -1,
|
2012-06-10 21:23:28 -04:00
|
|
|
|
Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-06-16 19:04:19 +02:00
|
|
|
|
setVolume(_lastVolume);
|
2012-06-10 21:23:28 -04:00
|
|
|
|
|
2012-06-16 19:04:19 +02:00
|
|
|
|
if (_bPaused)
|
2012-06-10 21:23:28 -04:00
|
|
|
|
g_system->getMixer()->pauseHandle(_handle, true);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
2012-06-10 21:23:28 -04:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: bool Stop(void);
|
|
|
|
|
*
|
|
|
|
|
* Description: Ferma il play dello sfx.
|
|
|
|
|
*
|
|
|
|
|
* Return: true se tutto OK, false in caso di errore.
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPSfx::stop() {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
if (_bFileLoaded) {
|
2012-06-10 21:23:28 -04:00
|
|
|
|
g_system->getMixer()->stopHandle(_handle);
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_bPaused = false;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
2012-06-10 21:23:28 -04:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: bool SetLoop(bool bLoop);
|
|
|
|
|
*
|
|
|
|
|
* Description: Attiva o disattiva il loop dello sfx.
|
|
|
|
|
*
|
|
|
|
|
* Input: bool bLoop true per attivare il loop, false per
|
|
|
|
|
* disattivarlo
|
|
|
|
|
*
|
|
|
|
|
* Note: Il loop deve essere attivato PRIMA di eseguire il play
|
|
|
|
|
* dello sfx. Qualsiasi modifica effettuata durante il play
|
|
|
|
|
* non avra' effetto fino a che lo sfx non viene fermato,
|
|
|
|
|
* e poi rimesso in play.
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPSfx::setLoop(bool bLop) {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_bLoop = bLop;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPSfx::pause(bool bPause) {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
if (_bFileLoaded) {
|
|
|
|
|
if (g_system->getMixer()->isSoundHandleActive(_handle) && (bPause ^ _bPaused))
|
2012-06-10 21:23:28 -04:00
|
|
|
|
g_system->getMixer()->pauseHandle(_handle, bPause);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_bPaused = bPause;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: void SetVolume(int dwVolume);
|
|
|
|
|
*
|
|
|
|
|
* Description: Cambia il volume dello sfx
|
|
|
|
|
*
|
|
|
|
|
* Input: int dwVolume Volume da settare (0-63)
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPSfx::setVolume(int dwVolume) {
|
|
|
|
|
if (dwVolume > 63)
|
|
|
|
|
dwVolume = 63;
|
|
|
|
|
if (dwVolume < 0)
|
|
|
|
|
dwVolume = 0;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_lastVolume = dwVolume;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-06-16 19:04:19 +02:00
|
|
|
|
if (_bIsVoice) {
|
2012-06-16 11:32:50 +02:00
|
|
|
|
if (!GLOBALS._bCfgDubbing)
|
|
|
|
|
dwVolume = 0;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
else {
|
2012-06-09 00:52:38 +02:00
|
|
|
|
dwVolume -= (10 - GLOBALS._nCfgDubbingVolume) * 2;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
if (dwVolume < 0) dwVolume = 0;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2012-06-16 11:32:50 +02:00
|
|
|
|
if (!GLOBALS._bCfgSFX)
|
|
|
|
|
dwVolume = 0;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
else {
|
2012-06-09 00:52:38 +02:00
|
|
|
|
dwVolume -= (10 - GLOBALS._nCfgSFXVolume) * 2;
|
2012-06-16 11:32:50 +02:00
|
|
|
|
if (dwVolume < 0)
|
|
|
|
|
dwVolume = 0;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-06-10 21:23:28 -04:00
|
|
|
|
|
|
|
|
|
if (g_system->getMixer()->isSoundHandleActive(_handle))
|
|
|
|
|
g_system->getMixer()->setChannelVolume(_handle, dwVolume * Audio::Mixer::kMaxChannelVolume / 63);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: void GetVolume(int *lpdwVolume);
|
|
|
|
|
*
|
|
|
|
|
* Description: Chiede il volume dello sfx
|
|
|
|
|
*
|
|
|
|
|
* Input: int *lpdwVolume Variabile in cui verra' inserito
|
|
|
|
|
* il volume corrente
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPSfx::getVolume(int *lpdwVolume) {
|
2012-06-10 21:23:28 -04:00
|
|
|
|
if (g_system->getMixer()->isSoundHandleActive(_handle))
|
|
|
|
|
*lpdwVolume = g_system->getMixer()->getChannelVolume(_handle) * 63 / Audio::Mixer::kMaxChannelVolume;
|
|
|
|
|
else
|
|
|
|
|
*lpdwVolume = 0;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
2012-06-11 12:20:12 +10:00
|
|
|
|
/**
|
|
|
|
|
* Returns true if the underlying sound has ended
|
|
|
|
|
*/
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPSfx::endOfBuffer() const {
|
2012-06-12 11:35:27 -04:00
|
|
|
|
return !g_system->getMixer()->isSoundHandleActive(_handle) && (!_rewindableStream || _rewindableStream->endOfData());
|
2012-06-11 12:20:12 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Continually checks to see if active sounds have finished playing
|
|
|
|
|
* Sets the event signalling the sound has ended
|
|
|
|
|
*/
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPSfx::soundCheckProcess(CORO_PARAM, const void *param) {
|
2012-06-11 12:20:12 +10:00
|
|
|
|
CORO_BEGIN_CONTEXT;
|
2012-06-16 11:32:50 +02:00
|
|
|
|
Common::List<FPSfx *>::iterator i;
|
2012-06-11 12:20:12 +10:00
|
|
|
|
CORO_END_CONTEXT(_ctx);
|
|
|
|
|
|
|
|
|
|
CORO_BEGIN_CODE(_ctx);
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
// Check each active sound
|
|
|
|
|
for (_ctx->i = _vm->_activeSfx.begin(); _ctx->i != _vm->_activeSfx.end(); ++_ctx->i) {
|
2012-06-16 11:32:50 +02:00
|
|
|
|
FPSfx *sfx = *_ctx->i;
|
2012-06-11 12:20:12 +10:00
|
|
|
|
if (sfx->endOfBuffer())
|
2012-06-16 19:04:19 +02:00
|
|
|
|
CoroScheduler.setEvent(sfx->_hEndOfBuffer);
|
2012-06-11 12:20:12 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Delay until the next check is done
|
|
|
|
|
CORO_INVOKE_1(CoroScheduler.sleep, 50);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CORO_END_CODE;
|
|
|
|
|
}
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Metodi di FPStream
|
2012-05-03 21:43:00 +10:00
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Function: FPStream(LPDIRECTSOUND lpDS, bool bSoundOn);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
* Description: Costruttore di default. *NON* bisogna dichiarare direttamente
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* un oggetto, ma crearlo piuttosto tramite FPSound::CreateStream()
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
FPStream::FPStream(bool bSoundOn) {
|
2012-05-03 22:49:30 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
2012-05-03 21:43:00 +10:00
|
|
|
|
//hwnd=hWnd;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
lpDS = LPDS;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
bSoundSupported = bSoundOn;
|
|
|
|
|
bFileLoaded = false;
|
|
|
|
|
bIsPlaying = false;
|
|
|
|
|
bPaused = false;
|
|
|
|
|
bSyncExit = false;
|
|
|
|
|
lpDSBuffer = NULL;
|
|
|
|
|
lpDSNotify = NULL;
|
|
|
|
|
hHot1 = hHot2 = hHot3 = hPlayThread_PlayFast = hPlayThread_PlayNormal = NULL;
|
2012-05-03 22:49:30 +10:00
|
|
|
|
#endif
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPStream::createBuffer(int nBufSize) {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
|
|
|
|
static PCMWAVEFORMAT pcmwf;
|
|
|
|
|
static DSBUFFERDESC dsbdesc;
|
|
|
|
|
static HRESULT err;
|
|
|
|
|
static char errbuf[128];
|
|
|
|
|
|
|
|
|
|
if (bSoundSupported == false)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
/* Setta le strutture necessarie per la creazione di un secondary buffer
|
2012-05-21 23:53:13 +02:00
|
|
|
|
per lo stream lungo esattamente 1 secondo di musica. Attiviamo inoltre
|
|
|
|
|
il controllo del volume, in modo da poter abbassare e alzare il volume
|
|
|
|
|
della musica indipendentemente da quello generale. Ovviamente si tratta
|
|
|
|
|
di un buffer in RAM */
|
2012-05-03 21:43:00 +10:00
|
|
|
|
pcmwf.wBitsPerSample = 16;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
pcmwf.wf.nChannels = 2;
|
|
|
|
|
pcmwf.wf.nSamplesPerSec = 44100;
|
|
|
|
|
pcmwf.wf.nBlockAlign = (pcmwf.wBitsPerSample / 8) * pcmwf.wf.nChannels;
|
|
|
|
|
pcmwf.wf.nAvgBytesPerSec = (uint32)pcmwf.wf.nBlockAlign * (uint32)pcmwf.wf.nSamplesPerSec;
|
|
|
|
|
|
|
|
|
|
dsbdesc.dwSize = sizeof(dsbdesc);
|
|
|
|
|
dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
dwBufferSize = dsbdesc.dwBufferBytes = (((uint32)(pcmwf.wf.nAvgBytesPerSec * nBufSize) / 1000 + 31) / 32) * 32;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
dsbdesc.lpwfxFormat = (LPWAVEFORMATEX) & pcmwf;
|
|
|
|
|
|
|
|
|
|
if ((err = lpDS->CreateSoundBuffer(&dsbdesc, &lpDSBuffer, NULL)) != DS_OK) {
|
2012-05-21 23:53:13 +02:00
|
|
|
|
wsprintf(errbuf, "Error creating the secondary buffer (%lx)", err);
|
2012-06-16 11:32:50 +02:00
|
|
|
|
MessageBox(hwnd, errbuf, "FPStream::FPStream()", MB_OK);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
bSoundSupported = false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
SetVolume(63);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Crea il notify per avvertire quando vengono raggiunte le posizioni chiave
|
2012-05-21 23:53:13 +02:00
|
|
|
|
all'interno dello stream. Le posizioni chiave si trovano rispettivamente
|
|
|
|
|
subito dopo l'inizio e subito dopo la meta' del buffer */
|
|
|
|
|
err = lpDSBuffer->QueryInterface(IID_IDirectSoundNotify, (void **)&lpDSNotify);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
|
|
|
|
if (FAILED(err)) {
|
2012-05-21 23:53:13 +02:00
|
|
|
|
wsprintf(errbuf, "Error creating notify object! (%lx)", err);
|
2012-06-16 11:32:50 +02:00
|
|
|
|
MessageBox(hwnd, errbuf, "FPStream::FPStream()", MB_OK);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
bSoundSupported = false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-21 23:53:13 +02:00
|
|
|
|
hHot1 = CreateEvent(NULL, false, false, NULL);
|
|
|
|
|
hHot2 = CreateEvent(NULL, false, false, NULL);
|
|
|
|
|
hHot3 = CreateEvent(NULL, false, false, NULL);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
hPlayThread_PlayFast = CreateEvent(NULL, false, false, NULL);
|
|
|
|
|
|
|
|
|
|
dspnHot[0].dwOffset = 32;
|
|
|
|
|
dspnHot[0].hEventNotify = hHot1;
|
|
|
|
|
|
|
|
|
|
dspnHot[1].dwOffset = dwBufferSize / 2 + 32;
|
|
|
|
|
dspnHot[1].hEventNotify = hHot2;
|
|
|
|
|
|
|
|
|
|
dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP;
|
|
|
|
|
dspnHot[2].hEventNotify = hHot3;
|
|
|
|
|
|
2012-05-21 23:53:13 +02:00
|
|
|
|
lpDSNotify->SetNotificationPositions(3, dspnHot);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#endif
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Function: ~FPStream();
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
* Description: Distruttore di default. Richiama anche la CloseFile() se ce
|
|
|
|
|
* ne e' bisogno.
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
FPStream::~FPStream() {
|
2012-05-03 22:49:30 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
if (!bSoundSupported)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (bIsPlaying)
|
|
|
|
|
Stop();
|
|
|
|
|
|
|
|
|
|
if (bFileLoaded)
|
|
|
|
|
UnloadFile();
|
|
|
|
|
|
|
|
|
|
if (hHot1) {
|
|
|
|
|
CloseHandle(hHot1);
|
|
|
|
|
hHot1 = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (hHot2) {
|
|
|
|
|
CloseHandle(hHot2);
|
|
|
|
|
hHot2 = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (hHot3) {
|
|
|
|
|
CloseHandle(hHot3);
|
|
|
|
|
hHot3 = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (hPlayThread_PlayFast) {
|
|
|
|
|
CloseHandle(hPlayThread_PlayFast);
|
|
|
|
|
hPlayThread_PlayFast = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (hPlayThread_PlayNormal) {
|
|
|
|
|
CloseHandle(hPlayThread_PlayNormal);
|
|
|
|
|
hPlayThread_PlayNormal = NULL;
|
|
|
|
|
}
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
SyncToPlay = NULL;
|
|
|
|
|
|
|
|
|
|
RELEASE(lpDSNotify);
|
|
|
|
|
RELEASE(lpDSBuffer);
|
2012-05-03 22:49:30 +10:00
|
|
|
|
#endif
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: Release();
|
|
|
|
|
*
|
|
|
|
|
* Description: Rilascia la memoria dell'oggetto. Deve essere richiamata quando
|
|
|
|
|
* l'oggetto non serve piu' e **SOLO SE** l'oggetto e' stato
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* creato con la FPSound::CreateStream().
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
* Note: Eventuali puntatori all'oggetto non sono piu' validi dopo
|
|
|
|
|
* questa chiamata.
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPStream::release() {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
delete this;
|
2012-05-03 22:49:30 +10:00
|
|
|
|
// return NULL;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: bool LoadFile(LPSTREAM lpszFileName, uint32 dwCodec=FPCODEC_RAW);
|
|
|
|
|
*
|
|
|
|
|
* Description: Apre un file di stream.
|
|
|
|
|
*
|
|
|
|
|
* Input: LPSTR lpszFile Nome del file di stream da aprire
|
|
|
|
|
* uint32 dwCodec CODEC da utilizzare per decomprimere
|
|
|
|
|
* i campioni sonori
|
|
|
|
|
*
|
|
|
|
|
* Return: true se tutto OK, false in caso di errore
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPStream::loadFile(const char *lpszFileName, uint32 dwCodType, int nBufSize) {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
|
|
|
|
HRESULT err;
|
|
|
|
|
void *lpBuf;
|
|
|
|
|
uint32 dwHi;
|
|
|
|
|
|
|
|
|
|
if (!bSoundSupported)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
/* Si salva il tipo di codec */
|
|
|
|
|
dwCodec = dwCodType;
|
|
|
|
|
|
|
|
|
|
/* Crea il buffer */
|
|
|
|
|
if (!CreateBuffer(nBufSize))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
/* Apre il file di stream in lettura */
|
|
|
|
|
if (!_file.open(lpszFileName))
|
2012-06-16 11:32:50 +02:00
|
|
|
|
//MessageBox(hwnd,"Cannot open stream file!","FPStream::LoadFile()", MB_OK);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return false;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
}
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-05-21 23:53:13 +02:00
|
|
|
|
/* Si salva la lunghezza dello stream */
|
|
|
|
|
dwSize = _file.size();
|
|
|
|
|
_file.seek(0);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-05-21 23:53:13 +02:00
|
|
|
|
/* Tutto a posto, possiamo uscire */
|
|
|
|
|
bFileLoaded = true;
|
|
|
|
|
bIsPlaying = false;
|
|
|
|
|
bPaused = false;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#endif
|
2012-05-21 23:53:13 +02:00
|
|
|
|
return true;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: UnloadFile();
|
|
|
|
|
*
|
|
|
|
|
* Description: Chiude un file di stream eventualmente aperto. E' necessario
|
|
|
|
|
* richiamare questa funzione per disallocare la memoria
|
|
|
|
|
* occupata dallo stream.
|
|
|
|
|
*
|
|
|
|
|
* Return: Il distruttore della classe per sicurezza richiama la
|
|
|
|
|
* UnloadFile() se non e' stata richiamata esplicitamente.
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPStream::unloadFile() {
|
2012-05-03 22:49:30 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
if (!bSoundSupported || !bFileLoaded)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
/* Chiude gli handle del file di stream */
|
|
|
|
|
_file.close();
|
|
|
|
|
|
|
|
|
|
RELEASE(lpDSNotify);
|
|
|
|
|
RELEASE(lpDSBuffer);
|
|
|
|
|
|
|
|
|
|
/* Si ricorda che non c'e' piu' nessun file in memoria */
|
|
|
|
|
bFileLoaded = false;
|
2012-05-03 22:49:30 +10:00
|
|
|
|
#endif
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: bool Play();
|
|
|
|
|
*
|
|
|
|
|
* Description: Suona lo stream caricato.
|
|
|
|
|
*
|
|
|
|
|
* Return: true se tutto OK, false in caso di errore.
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPStream::prefetch(void) {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
|
|
|
|
uint32 dwId;
|
|
|
|
|
void *lpBuf;
|
|
|
|
|
uint32 dwHi;
|
|
|
|
|
HRESULT err;
|
|
|
|
|
|
|
|
|
|
if (!bSoundSupported || !bFileLoaded)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Alloca un buffer temporaneo */
|
|
|
|
|
lpTempBuffer = (byte *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, dwBufferSize / 2);
|
|
|
|
|
if (lpTempBuffer == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
switch (dwCodec) {
|
|
|
|
|
case FPCODEC_RAW:
|
|
|
|
|
lpCodec = new CODECRAW(bLoop);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case FPCODEC_ADPCM:
|
|
|
|
|
lpCodec = new CODECADPCMSTEREO(bLoop);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Posiziona lo stream file all'inizio */
|
|
|
|
|
_file.seek(0);
|
|
|
|
|
|
|
|
|
|
/* Riempie il buffer per avere i dati gia' pronti */
|
|
|
|
|
if ((err = lpDSBuffer->Lock(0, dwBufferSize / 2, &lpBuf, (uint32 *)&dwHi, NULL, NULL, 0)) != DS_OK) {
|
2012-05-21 23:53:13 +02:00
|
|
|
|
MessageBox(hwnd, "Cannot lock stream buffer!", "soundLoadStream()", MB_OK);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return;
|
|
|
|
|
}
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
/* Decomprime i dati dello stream direttamente dentro il buffer lockato */
|
|
|
|
|
lpCodec->Decompress(hFile, lpBuf, dwBufferSize / 2);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
/* Unlocka il buffer */
|
|
|
|
|
lpDSBuffer->Unlock(lpBuf, dwBufferSize / 2, NULL, NULL);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
/* Crea il thread che fa il play dello stream */
|
|
|
|
|
hThreadEnd = CreateEvent(NULL, false, false, NULL);
|
|
|
|
|
hPlayThread = CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)PlayThread, (void *)this, 0, &dwId);
|
|
|
|
|
SetThreadPriority(hPlayThread, THREAD_PRIORITY_HIGHEST);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
/* Start il play del buffer DirectSound */
|
|
|
|
|
lpDSBuffer->SetCurrentPosition(0);
|
|
|
|
|
bIsPlaying = true;
|
|
|
|
|
|
|
|
|
|
dspnHot[0].dwOffset = 32;
|
|
|
|
|
dspnHot[0].hEventNotify = hHot1;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
dspnHot[1].dwOffset = dwBufferSize / 2 + 32;
|
|
|
|
|
dspnHot[1].hEventNotify = hHot2;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP;
|
|
|
|
|
dspnHot[2].hEventNotify = hHot3;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
|
|
|
|
if (FAILED(lpDSNotify->SetNotificationPositions(3, dspnHot))) {
|
|
|
|
|
int a = 1;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPStream::playFast(void) {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
|
|
|
|
dspnHot[0].dwOffset = 32;
|
|
|
|
|
dspnHot[0].hEventNotify = hHot1;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
dspnHot[1].dwOffset = dwBufferSize / 2 + 32;
|
|
|
|
|
dspnHot[1].hEventNotify = hHot2;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
|
|
|
|
dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
dspnHot[2].hEventNotify = hHot3;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
lpDSBuffer->Stop();
|
|
|
|
|
|
2012-05-21 23:53:13 +02:00
|
|
|
|
if (FAILED(lpDSNotify->SetNotificationPositions(3, dspnHot))) {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
warning("PlayFast SNP failed!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (FAILED(lpDSBuffer->Play(0, 0, DSBPLAY_LOOPING))) {
|
|
|
|
|
warning("PlayFast failed!\n");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPStream::play() {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
|
|
|
|
uint32 dwId;
|
|
|
|
|
void *lpBuf;
|
|
|
|
|
uint32 dwHi;
|
|
|
|
|
HRESULT err;
|
|
|
|
|
|
|
|
|
|
if (!bSoundSupported || !bFileLoaded)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
/* Alloca un buffer temporaneo */
|
|
|
|
|
lpTempBuffer = (byte *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, dwBufferSize / 2);
|
|
|
|
|
if (lpTempBuffer == NULL)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
switch (dwCodec) {
|
|
|
|
|
case FPCODEC_RAW:
|
|
|
|
|
lpCodec = new CODECRAW(bLoop);
|
|
|
|
|
break;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
case FPCODEC_ADPCM:
|
|
|
|
|
lpCodec = new CODECADPCMSTEREO(bLoop);
|
|
|
|
|
break;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
/* Posiziona lo stream file all'inizio */
|
|
|
|
|
_file.seek(0);
|
|
|
|
|
lpDSBuffer->Stop();
|
|
|
|
|
lpDSBuffer->SetCurrentPosition(0);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
/* Riempie il buffer per avere i dati gia' pronti */
|
2012-05-21 23:53:13 +02:00
|
|
|
|
if ((err = lpDSBuffer->Lock(0, dwBufferSize / 2, &lpBuf, (uint32 *)&dwHi, NULL, NULL, 0)) != DS_OK) {
|
|
|
|
|
error("Cannot lock stream buffer!", "soundLoadStream()");
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
/* Decomprime i dati dello stream direttamente dentro il buffer lockato */
|
|
|
|
|
lpCodec->Decompress(hFile, lpBuf, dwBufferSize / 2);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
/* Unlocka il buffer */
|
|
|
|
|
lpDSBuffer->Unlock(lpBuf, dwBufferSize / 2, NULL, NULL);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
/* Crea il thread che fa il play dello stream */
|
|
|
|
|
hThreadEnd = CreateEvent(NULL, false, false, NULL);
|
|
|
|
|
hPlayThread = CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)PlayThread, (void *)this, 0, &dwId);
|
|
|
|
|
SetThreadPriority(hPlayThread, THREAD_PRIORITY_HIGHEST);
|
|
|
|
|
|
|
|
|
|
SetEvent(hPlayThread_PlayFast);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#if 0
|
2012-05-21 23:53:13 +02:00
|
|
|
|
/* Start il play del buffer DirectSound */
|
|
|
|
|
lpDSBuffer->SetCurrentPosition(0);
|
|
|
|
|
|
|
|
|
|
dspnHot[0].dwOffset = 32;
|
|
|
|
|
dspnHot[0].hEventNotify = hHot1;
|
|
|
|
|
|
|
|
|
|
dspnHot[1].dwOffset = dwBufferSize / 2 + 32;
|
|
|
|
|
dspnHot[1].hEventNotify = hHot2;
|
|
|
|
|
|
|
|
|
|
dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP;
|
|
|
|
|
dspnHot[2].hEventNotify = hHot3;
|
|
|
|
|
|
|
|
|
|
if (FAILED(lpDSNotify->SetNotificationPositions(3, dspnHot))) {
|
|
|
|
|
int a = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lpDSBuffer->Play(0, 0, DSBPLAY_LOOPING);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
bIsPlaying = true;
|
|
|
|
|
#endif
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: bool Stop(bool bSync);
|
|
|
|
|
*
|
|
|
|
|
* Description: Ferma il play dello stream.
|
|
|
|
|
*
|
|
|
|
|
* Return: true se tutto OK, false in caso di errore.
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
bool FPStream::stop(bool bSync) {
|
2012-05-03 22:49:30 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
if (!bSoundSupported)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (!bFileLoaded)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (!bIsPlaying)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (bSync) {
|
|
|
|
|
// bSyncExit = true;
|
|
|
|
|
// lpDSBuffer->Stop();
|
|
|
|
|
// lpDSBuffer->Play(0, 0, 0);
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
2012-05-21 23:53:13 +02:00
|
|
|
|
/* Ferma il buffer DirectSound */
|
2012-05-03 21:43:00 +10:00
|
|
|
|
lpDSBuffer->Stop();
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
/* Avverte il thread che deve uscire e aspetta che si chiuda */
|
|
|
|
|
SetEvent(hThreadEnd);
|
2012-05-11 23:15:59 +10:00
|
|
|
|
WaitForSingleObject(hPlayThread, CORO_INFINITE);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
|
|
|
|
/* Chiude l'handle del thread e disalloca la memoria temporanea */
|
|
|
|
|
CloseHandle(hPlayThread);
|
|
|
|
|
CloseHandle(hThreadEnd);
|
|
|
|
|
GlobalFree(lpTempBuffer);
|
|
|
|
|
|
|
|
|
|
/* Disalloca e chiude il CODEC */
|
|
|
|
|
delete lpCodec;
|
|
|
|
|
|
|
|
|
|
bIsPlaying = false;
|
|
|
|
|
bPaused = false;
|
|
|
|
|
}
|
2012-05-03 22:49:30 +10:00
|
|
|
|
#endif
|
2012-05-03 21:43:00 +10:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPStream::waitForSync(FPStream *toplay) {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
|
|
|
|
if (!bSoundSupported)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!bFileLoaded)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!bIsPlaying)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
SyncToPlay = toplay;
|
|
|
|
|
bSyncExit = true;
|
|
|
|
|
|
|
|
|
|
char buf[1024];
|
2012-05-21 23:53:13 +02:00
|
|
|
|
sprintf(buf, "Wait for sync: %x (SyncToPlay: [%x]=%x, SyncExit: [%x]=%d) MyThread: 0x%x\n",
|
|
|
|
|
this->lpDSBuffer, &this->SyncToPlay, SyncToPlay, &bSyncExit, bSyncExit, GetCurrentThreadId());
|
2012-05-03 21:43:00 +10:00
|
|
|
|
warning(buf);
|
|
|
|
|
|
2012-05-11 23:15:59 +10:00
|
|
|
|
WaitForSingleObject(hPlayThread, CORO_INFINITE);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
|
|
|
|
/* Chiude l'handle del thread e disalloca la memoria temporanea */
|
|
|
|
|
CloseHandle(hPlayThread);
|
|
|
|
|
CloseHandle(hThreadEnd);
|
|
|
|
|
GlobalFree(lpTempBuffer);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
/* Disalloca e chiude il CODEC */
|
|
|
|
|
delete lpCodec;
|
|
|
|
|
#endif
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_bIsPlaying = false;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
2012-06-16 11:32:50 +02:00
|
|
|
|
* Function: void FPStream::PlayThread();
|
2012-05-03 21:43:00 +10:00
|
|
|
|
*
|
|
|
|
|
* Description: Thread che si occupa del play dello stream
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPStream::playThread(FPStream *This) {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
|
|
|
|
byte *lpLockBuf;
|
|
|
|
|
uint32 dwResult;
|
|
|
|
|
byte *lpLockBuf2;
|
|
|
|
|
uint32 dwResult2;
|
|
|
|
|
bool cicla = true;
|
|
|
|
|
uint32 countEnd;
|
|
|
|
|
bool bPrecache;
|
|
|
|
|
char buf[1024];
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
/* Eventi che segnalano quando bisogna eseguire qualcosa */
|
|
|
|
|
HANDLE hList[5] = { This->hThreadEnd, This->hHot1, This->hHot2, This->hHot3, This->hPlayThread_PlayFast };
|
|
|
|
|
|
|
|
|
|
bPrecache = true;
|
|
|
|
|
countEnd = 0;
|
|
|
|
|
while (cicla) {
|
|
|
|
|
if (This->lpCodec->EndOfStream() && This->lpCodec->bLoop == false) {
|
|
|
|
|
countEnd++;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
if (countEnd == 3)
|
2012-05-03 21:43:00 +10:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Decomprime i dati che stanno per essere scritti dentro il buffer temporaneo */
|
|
|
|
|
if (This->lastVolume == 0)
|
|
|
|
|
ZeroMemory(This->lpTempBuffer, This->dwBufferSize / 2);
|
|
|
|
|
else if (bPrecache)
|
|
|
|
|
This->lpCodec->Decompress(This->_file, This->lpTempBuffer, This->dwBufferSize / 2);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
bPrecache = false;
|
|
|
|
|
|
|
|
|
|
/* Attende il set di un evento. Dato che sono tutti in automatic reset,
|
|
|
|
|
non c'e' bisogno di resettarlo dopo */
|
|
|
|
|
|
|
|
|
|
// uint32 dwBufStatus;
|
|
|
|
|
// This->lpDSBuffer->GetStatus(&dwBufStatus);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// sprintf(buf, "WFMO: %x (buf status: %x) MyThread: 0x%x\n", This->lpDSBuffer, dwBufStatus, GetCurrentThreadId());
|
|
|
|
|
// warning(buf);
|
2012-05-11 23:15:59 +10:00
|
|
|
|
dwResult = WaitForMultipleObjects(5, hList, false, CORO_INFINITE);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-05-21 23:53:13 +02:00
|
|
|
|
/* uint32 dwPlay, dwWrite;
|
|
|
|
|
This->lpDSBuffer->GetCurrentPosition(&dwPlay, &dwWrite);
|
|
|
|
|
sprintf(buf, "CP Play: %u, Write: %u\n", dwPlay, dwWrite);
|
|
|
|
|
warning(buf); */
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-05-21 23:53:13 +02:00
|
|
|
|
/* Fa uno switch per stabilire quale evento e' stato settato */
|
2012-05-03 21:43:00 +10:00
|
|
|
|
switch (dwResult - WAIT_OBJECT_0) {
|
|
|
|
|
case 0:
|
|
|
|
|
/* Bisogna uscire dal thread */
|
|
|
|
|
cicla = false;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 1:
|
2012-05-21 23:53:13 +02:00
|
|
|
|
/* Bisogna riempire la seconda meta' del buffer */
|
2012-05-03 21:43:00 +10:00
|
|
|
|
// if (dwPlay >= This->dspnHot[0].dwOffset && dwPlay <= This->dspnHot[0].dwOffset+1024 )
|
|
|
|
|
{
|
|
|
|
|
// sprintf(buf, "Prima met<65> buffer: %x\n", This->lpDSBuffer);
|
|
|
|
|
// warning(buf);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
This->lpDSBuffer->Lock(This->dwBufferSize / 2, This->dwBufferSize / 2, (void **)&lpLockBuf, &dwResult, (void **)&lpLockBuf2, &dwResult2, 0);
|
|
|
|
|
// sprintf(buf, "LockedBuf: dwResult=%x, dwBufferSize/2=%x, lpLockBuf2=%x, dwResult2=%x\n", dwResult, This->dwBufferSize/2, lpLockBuf2, dwResult2);
|
|
|
|
|
// warning(buf);
|
2012-06-07 21:14:59 +02:00
|
|
|
|
copyMemory(lpLockBuf, This->lpTempBuffer, This->dwBufferSize / 2);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
This->lpDSBuffer->Unlock(lpLockBuf, This->dwBufferSize / 2, lpLockBuf2, 0);
|
2012-05-03 21:43:00 +10:00
|
|
|
|
bPrecache = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
/* Bisogna riempire la prima meta' del buffer */
|
|
|
|
|
// if (dwPlay >= This->dspnHot[1].dwOffset && dwPlay <= This->dspnHot[1].dwOffset+1024 )
|
2012-05-21 23:53:13 +02:00
|
|
|
|
{
|
2012-05-03 21:43:00 +10:00
|
|
|
|
// sprintf(buf, "Seconda met<65> buffer: %x\n", This->lpDSBuffer);
|
|
|
|
|
// warning(buf);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
This->lpDSBuffer->Lock(0, This->dwBufferSize / 2, (void **)&lpLockBuf, &dwResult, NULL, NULL, 0);
|
2012-06-07 21:14:59 +02:00
|
|
|
|
copyMemory(lpLockBuf, This->lpTempBuffer, This->dwBufferSize / 2);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
This->lpDSBuffer->Unlock(lpLockBuf, This->dwBufferSize / 2, NULL, NULL);
|
|
|
|
|
bPrecache = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
2012-05-21 23:53:13 +02:00
|
|
|
|
case 3: {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
// sprintf(buf, "End of buffer %x (SyncToPlay [%x]=%x, SyncExit: [%x]=%d)\n", This->lpDSBuffer, &This->SyncToPlay, This->SyncToPlay, &This->bSyncExit, This->bSyncExit);
|
|
|
|
|
// warning(buf);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
if (This->bSyncExit) {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
// sprintf(buf, "Go with sync (Buffer: %x) MyThread: %x!\n", This->SyncToPlay->lpDSBuffer, GetCurrentThreadId());
|
|
|
|
|
// warning(buf);
|
2012-05-21 23:53:13 +02:00
|
|
|
|
//This->SyncToPlay->PlayFast();
|
|
|
|
|
SetEvent(This->SyncToPlay->hPlayThread_PlayFast);
|
|
|
|
|
// Transfer immediatly control to the other threads
|
|
|
|
|
Sleep(0);
|
|
|
|
|
This->bSyncExit = false;
|
|
|
|
|
cicla = false;
|
|
|
|
|
break;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
2012-05-21 23:53:13 +02:00
|
|
|
|
}
|
|
|
|
|
break;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
|
This->PlayFast();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-21 23:53:13 +02:00
|
|
|
|
/* Ferma il buffer DirectSound */
|
2012-05-03 21:43:00 +10:00
|
|
|
|
// sprintf(buf, "Exiting thread. Buffer = %x, MyThread = 0x%x\n", This->lpDSBuffer, GetCurrentThreadId());
|
|
|
|
|
// warning(buf);
|
|
|
|
|
This->lpDSBuffer->Stop();
|
2012-05-09 00:42:27 +10:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
ExitThread(0);
|
2012-05-09 00:42:27 +10:00
|
|
|
|
#endif
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: bool SetLoop(bool bLoop);
|
|
|
|
|
*
|
|
|
|
|
* Description: Attiva o disattiva il loop dello stream.
|
|
|
|
|
*
|
|
|
|
|
* Input: bool bLoop true per attivare il loop, false per
|
|
|
|
|
* disattivarlo
|
|
|
|
|
*
|
|
|
|
|
* Note: Il loop deve essere attivato PRIMA di eseguire il play
|
|
|
|
|
* dello stream. Qualsiasi modifica effettuata durante il play
|
|
|
|
|
* non avra' effetto fino a che lo stream non viene fermato,
|
|
|
|
|
* e poi rimesso in play.
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPStream::setLoop(bool loop) {
|
2012-06-16 19:04:19 +02:00
|
|
|
|
_bLoop = loop;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPStream::pause(bool bPause) {
|
2012-05-03 22:49:30 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
if (bFileLoaded) {
|
|
|
|
|
if (bPause && bIsPlaying) {
|
|
|
|
|
lpDSBuffer->Stop();
|
|
|
|
|
bIsPlaying = false;
|
|
|
|
|
bPaused = true;
|
|
|
|
|
} else if (!bPause && bPaused) {
|
|
|
|
|
dspnHot[0].dwOffset = 32;
|
|
|
|
|
dspnHot[0].hEventNotify = hHot1;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
dspnHot[1].dwOffset = dwBufferSize / 2 + 32;
|
|
|
|
|
dspnHot[1].hEventNotify = hHot2;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
|
|
|
|
dspnHot[2].dwOffset = dwBufferSize - 32; //DSBPN_OFFSETSTOP;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
dspnHot[2].hEventNotify = hHot3;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
|
|
|
|
if (FAILED(lpDSNotify->SetNotificationPositions(3, dspnHot))) {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
int a = 1;
|
|
|
|
|
}
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
lpDSBuffer->Play(0, 0, bLoop);
|
|
|
|
|
bIsPlaying = true;
|
|
|
|
|
bPaused = false;
|
|
|
|
|
|
|
|
|
|
// Trucchetto per risettare il volume secondo le
|
|
|
|
|
// possibili nuove configurazioni sonore
|
|
|
|
|
SetVolume(lastVolume);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-03 22:49:30 +10:00
|
|
|
|
#endif
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: void SetVolume(int dwVolume);
|
|
|
|
|
*
|
|
|
|
|
* Description: Cambia il volume dello stream
|
|
|
|
|
*
|
|
|
|
|
* Input: int dwVolume Volume da settare (0-63)
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPStream::setVolume(int dwVolume) {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
|
|
|
|
if (dwVolume > 63) dwVolume = 63;
|
|
|
|
|
if (dwVolume < 0) dwVolume = 0;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
|
2012-05-03 21:43:00 +10:00
|
|
|
|
lastVolume = dwVolume;
|
|
|
|
|
|
2012-05-13 22:34:40 +10:00
|
|
|
|
if (!GLOBALS.bCfgMusic) dwVolume = 0;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
else {
|
2012-05-13 22:34:40 +10:00
|
|
|
|
dwVolume -= (10 - GLOBALS.nCfgMusicVolume) * 2;
|
2012-05-21 23:53:13 +02:00
|
|
|
|
if (dwVolume < 0) dwVolume = 0;
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lpDSBuffer)
|
|
|
|
|
lpDSBuffer->SetVolume(dwVolume * (DSBVOLUME_MAX - DSBVOLUME_MIN) / 64 + DSBVOLUME_MIN);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
|
*
|
|
|
|
|
* Function: void GetVolume(int *lpdwVolume);
|
|
|
|
|
*
|
|
|
|
|
* Description: Chiede il volume dello stream
|
|
|
|
|
*
|
|
|
|
|
* Input: int *lpdwVolume Variabile in cui verra' inserito
|
|
|
|
|
* il volume corrente
|
|
|
|
|
*
|
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
2012-06-16 11:32:50 +02:00
|
|
|
|
void FPStream::getVolume(int *lpdwVolume) {
|
2012-05-03 21:43:00 +10:00
|
|
|
|
#ifdef REFACTOR_ME
|
|
|
|
|
if (lpDSBuffer)
|
|
|
|
|
lpDSBuffer->GetVolume((uint32 *)lpdwVolume);
|
|
|
|
|
*lpdwVolume -= (DSBVOLUME_MIN);
|
|
|
|
|
*lpdwVolume *= 64;
|
|
|
|
|
*lpdwVolume /= (DSBVOLUME_MAX - DSBVOLUME_MIN);
|
2012-05-03 22:49:30 +10:00
|
|
|
|
#endif
|
2012-05-03 21:43:00 +10:00
|
|
|
|
}
|
|
|
|
|
|
2012-04-30 09:27:12 +10:00
|
|
|
|
} // End of namespace Tony
|