aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorathrxx2011-04-30 15:11:13 +0200
committerWillem Jan Palenstijn2011-05-17 20:24:28 +0200
commit63a78593516dc428f77ac01d90bc228fcf01de5d (patch)
tree3de4ed88a63a0350a3fb70253995202d97fddecb
parent5c34e33c2c27b2b5083199b40306370d732f4e53 (diff)
downloadscummvm-rg350-63a78593516dc428f77ac01d90bc228fcf01de5d.tar.gz
scummvm-rg350-63a78593516dc428f77ac01d90bc228fcf01de5d.tar.bz2
scummvm-rg350-63a78593516dc428f77ac01d90bc228fcf01de5d.zip
FM-TOWNS AUDIO: Change internal interface layout
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_audio.cpp400
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_audio.h130
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp1
3 files changed, 322 insertions, 209 deletions
diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
index ee8327fba7..065532f526 100644
--- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
@@ -21,13 +21,16 @@
*/
#include "audio/softsynth/fmtowns_pc98/towns_audio.h"
+#include "audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
+
#include "common/endian.h"
#include "common/util.h"
+#include "common/textconsole.h"
#include "backends/audiocd/audiocd.h"
class TownsAudio_PcmChannel {
-friend class TownsAudioInterface;
+friend class TownsAudioInterfaceIntern;
public:
TownsAudio_PcmChannel();
~TownsAudio_PcmChannel();
@@ -77,7 +80,7 @@ private:
};
class TownsAudio_WaveTable {
-friend class TownsAudioInterface;
+friend class TownsAudioInterfaceIntern;
public:
TownsAudio_WaveTable();
~TownsAudio_WaveTable();
@@ -98,14 +101,160 @@ private:
int8 *data;
};
-TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns),
+class TownsAudioInterfaceIntern : public TownsPC98_FmSynth {
+public:
+ TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver);
+ ~TownsAudioInterfaceIntern();
+
+ static TownsAudioInterfaceIntern *addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver);
+ static void releaseRef();
+ bool checkPluginDriver(TownsAudioInterfacePluginDriver *driver);
+
+ bool init();
+
+ int callback(int command, ...);
+ int processCommand(int command, va_list &args);
+
+ void setMusicVolume(int volume);
+ void setSoundEffectVolume(int volume);
+ // Defines the channels used as sound effect channels for the purpose of ScummVM GUI volume control.
+ // The first 6 bits are the 6 fm channels. The next 8 bits are pcm channels.
+ void setSoundEffectChanMask(int mask);
+
+private:
+ void nextTickEx(int32 *buffer, uint32 bufferSize);
+
+ void timerCallbackA();
+ void timerCallbackB();
+
+ typedef int (TownsAudioInterfaceIntern::*TownsAudioIntfCallback)(va_list &);
+ const TownsAudioIntfCallback *_intfOpcodes;
+
+ int intf_reset(va_list &args);
+ int intf_keyOn(va_list &args);
+ int intf_keyOff(va_list &args);
+ int intf_setPanPos(va_list &args);
+ int intf_setInstrument(va_list &args);
+ int intf_loadInstrument(va_list &args);
+ int intf_setPitch(va_list &args);
+ int intf_setLevel(va_list &args);
+ int intf_chanOff(va_list &args);
+ int intf_writeReg(va_list &args);
+ int intf_writeRegBuffer(va_list &args);
+ int intf_readRegBuffer(va_list &args);
+ int intf_setTimerA(va_list &args);
+ int intf_setTimerB(va_list &args);
+ int intf_enableTimerA(va_list &args);
+ int intf_enableTimerB(va_list &args);
+ int intf_loadSamples(va_list &args);
+ int intf_reserveEffectChannels(va_list &args);
+ int intf_loadWaveTable(va_list &args);
+ int intf_unloadWaveTable(va_list &args);
+ int intf_pcmPlayEffect(va_list &args);
+ int intf_pcmChanOff(va_list &args);
+ int intf_pcmEffectPlaying(va_list &args);
+ int intf_fmKeyOn(va_list &args);
+ int intf_fmKeyOff(va_list &args);
+ int intf_fmSetPanPos(va_list &args);
+ int intf_fmSetInstrument(va_list &args);
+ int intf_fmLoadInstrument(va_list &args);
+ int intf_fmSetPitch(va_list &args);
+ int intf_fmSetLevel(va_list &args);
+ int intf_fmReset(va_list &args);
+ int intf_setOutputVolume(va_list &args);
+ int intf_resetOutputVolume(va_list &args);
+ int intf_updateOutputVolume(va_list &args);
+ int intf_cdaToggle(va_list &args);
+ int intf_pcmUpdateEnvelopeGenerator(va_list &args);
+
+ int intf_notImpl(va_list &args);
+
+ void fmReset();
+ int fmKeyOn(int chan, int note, int velo);
+ int fmKeyOff(int chan);
+ int fmChanOff(int chan);
+ int fmSetPanPos(int chan, int mode);
+ int fmSetInstrument(int chan, int instrId);
+ int fmLoadInstrument(int instrId, const uint8 *data);
+ int fmSetPitch(int chan, int pitch);
+ int fmSetLevel(int chan, int lvl);
+
+ void bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value);
+
+ uint8 _fmChanPlaying;
+ uint8 _fmChanNote[6];
+ int16 _fmChanPitch[6];
+
+ uint8 *_fmSaveReg[2];
+ uint8 *_fmInstruments;
+
+ void pcmReset();
+ int pcmKeyOn(int chan, int note, int velo);
+ int pcmKeyOff(int chan);
+ int pcmChanOff(int chan);
+ int pcmSetPanPos(int chan, int mode);
+ int pcmSetInstrument(int chan, int instrId);
+ int pcmLoadInstrument(int instrId, const uint8 *data);
+ int pcmSetPitch(int chan, int pitch);
+ int pcmSetLevel(int chan, int lvl);
+ void pcmUpdateEnvelopeGenerator(int chan);
+
+ TownsAudio_PcmChannel *_pcmChan;
+ uint8 _pcmChanOut;
+ uint8 _pcmChanReserved;
+ uint8 _pcmChanKeyPressed;
+ uint8 _pcmChanEffectPlaying;
+ uint8 _pcmChanKeyPlaying;
+
+ uint8 _pcmChanNote[8];
+ uint8 _pcmChanVelo[8];
+ uint8 _pcmChanLevel[8];
+
+ uint8 _numReservedChannels;
+ uint8 *_pcmInstruments;
+
+ TownsAudio_WaveTable *_waveTables;
+ uint8 _numWaveTables;
+ uint32 _waveTablesTotalDataSize;
+
+ void pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w);
+
+ void updateOutputVolume();
+ uint8 _outputVolumeFlags;
+ uint8 _outputLevel[16];
+ uint8 _outputMuteFlags;
+
+ const float _baserate;
+ uint32 _timerBase;
+ uint32 _tickLength;
+ uint32 _timer;
+
+ uint16 _musicVolume;
+ uint16 _sfxVolume;
+ int _pcmSfxChanMask;
+
+ TownsAudioInterfacePluginDriver *_drv;
+ bool _ready;
+
+ static TownsAudioInterfaceIntern *_refInstance;
+ static int _refCount;
+
+ static const uint8 _chanFlags[];
+ static const uint16 _frequency[];
+ static const uint8 _carrier[];
+ static const uint8 _fmDefaultInstrument[];
+ static const uint16 _pcmPhase1[];
+ static const uint16 _pcmPhase2[];
+};
+
+TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns),
_fmInstruments(0), _pcmInstruments(0), _pcmChan(0), _waveTables(0), _waveTablesTotalDataSize(0),
_baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver),
_pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume),
_outputVolumeFlags(0), _outputMuteFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0),
_pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _ready(false) {
-#define INTCB(x) &TownsAudioInterface::intf_##x
+#define INTCB(x) &TownsAudioInterfaceIntern::intf_##x
static const TownsAudioIntfCallback intfCb[] = {
// 0
INTCB(reset),
@@ -222,7 +371,7 @@ TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfac
_tickLength = 2 * _timerBase;
}
-TownsAudioInterface::~TownsAudioInterface() {
+TownsAudioInterfaceIntern::~TownsAudioInterfaceIntern() {
_ready = false;
deinit();
@@ -234,7 +383,47 @@ TownsAudioInterface::~TownsAudioInterface() {
delete[] _pcmChan;
}
-bool TownsAudioInterface::init() {
+TownsAudioInterfaceIntern *TownsAudioInterfaceIntern::addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) {
+ _refCount++;
+ if (_refCount == 1 && _refInstance == 0)
+ _refInstance = new TownsAudioInterfaceIntern(mixer, driver);
+ else if (_refCount < 2 || _refInstance == 0)
+ error("TownsAudioInterfaceIntern::addNewRef(): Internal reference management failure");
+ else if (!_refInstance->checkPluginDriver(driver))
+ error("TownsAudioInterfaceIntern::addNewRef(): Plugin driver conflict");
+
+ return _refInstance;
+}
+
+void TownsAudioInterfaceIntern::releaseRef() {
+ if (!_refCount)
+ return;
+
+ _refCount--;
+
+ if (!_refCount) {
+ delete _refInstance;
+ _refInstance = 0;
+ }
+}
+
+bool TownsAudioInterfaceIntern::checkPluginDriver(TownsAudioInterfacePluginDriver *driver) {
+ if (_refCount <= 1)
+ return true;
+
+ Common::StackLock lock(_mutex);
+
+ if (_drv) {
+ if (driver && driver != _drv)
+ return false;
+ } else {
+ _drv = driver;
+ }
+
+ return true;
+}
+
+bool TownsAudioInterfaceIntern::init() {
if (_ready)
return true;
@@ -258,41 +447,46 @@ bool TownsAudioInterface::init() {
return true;
}
-int TownsAudioInterface::callback(int command, ...) {
+int TownsAudioInterfaceIntern::callback(int command, ...) {
if (!_ready)
return 1;
va_list args;
va_start(args, command);
- if (command > 81) {
- va_end(args);
- return 4;
- }
-
- int res = (this->*_intfOpcodes[command])(args);
+ int res = processCommand(command, args);
va_end(args);
return res;
}
-void TownsAudioInterface::setMusicVolume(int volume) {
+int TownsAudioInterfaceIntern::processCommand(int command, va_list &args) {
+ if (!_ready)
+ return 1;
+
+ if (command < 0 || command > 81)
+ return 4;
+
+ return (this->*_intfOpcodes[command])(args);
+}
+
+void TownsAudioInterfaceIntern::setMusicVolume(int volume) {
_musicVolume = CLIP<uint16>(volume, 0, Audio::Mixer::kMaxMixerVolume);
setVolumeIntern(_musicVolume, _sfxVolume);
}
-void TownsAudioInterface::setSoundEffectVolume(int volume) {
+void TownsAudioInterfaceIntern::setSoundEffectVolume(int volume) {
_sfxVolume = CLIP<uint16>(volume, 0, Audio::Mixer::kMaxMixerVolume);
setVolumeIntern(_musicVolume, _sfxVolume);
}
-void TownsAudioInterface::setSoundEffectChanMask(int mask) {
+void TownsAudioInterfaceIntern::setSoundEffectChanMask(int mask) {
_pcmSfxChanMask = mask >> 6;
mask &= 0x3f;
setVolumeChannelMasks(~mask, mask);
}
-void TownsAudioInterface::nextTickEx(int32 *buffer, uint32 bufferSize) {
+void TownsAudioInterfaceIntern::nextTickEx(int32 *buffer, uint32 bufferSize) {
if (!_ready)
return;
@@ -343,13 +537,13 @@ void TownsAudioInterface::nextTickEx(int32 *buffer, uint32 bufferSize) {
}
}
-void TownsAudioInterface::timerCallbackA() {
+void TownsAudioInterfaceIntern::timerCallbackA() {
Common::StackLock lock(_mutex);
if (_drv && _ready)
_drv->timerCallback(0);
}
-void TownsAudioInterface::timerCallbackB() {
+void TownsAudioInterfaceIntern::timerCallbackB() {
Common::StackLock lock(_mutex);
if (_ready) {
if (_drv)
@@ -358,62 +552,62 @@ void TownsAudioInterface::timerCallbackB() {
}
}
-int TownsAudioInterface::intf_reset(va_list &args) {
+int TownsAudioInterfaceIntern::intf_reset(va_list &args) {
fmReset();
pcmReset();
callback(68);
return 0;
}
-int TownsAudioInterface::intf_keyOn(va_list &args) {
+int TownsAudioInterfaceIntern::intf_keyOn(va_list &args) {
int chan = va_arg(args, int);
int note = va_arg(args, int);
int velo = va_arg(args, int);
return (chan & 0x40) ? pcmKeyOn(chan, note, velo) : fmKeyOn(chan, note, velo);
}
-int TownsAudioInterface::intf_keyOff(va_list &args) {
+int TownsAudioInterfaceIntern::intf_keyOff(va_list &args) {
int chan = va_arg(args, int);
return (chan & 0x40) ? pcmKeyOff(chan) : fmKeyOff(chan);
}
-int TownsAudioInterface::intf_setPanPos(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setPanPos(va_list &args) {
int chan = va_arg(args, int);
int mode = va_arg(args, int);
return (chan & 0x40) ? pcmSetPanPos(chan, mode) : fmSetPanPos(chan, mode);
}
-int TownsAudioInterface::intf_setInstrument(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setInstrument(va_list &args) {
int chan = va_arg(args, int);
int instrId = va_arg(args, int);
return (chan & 0x40) ? pcmSetInstrument(chan, instrId) : fmSetInstrument(chan, instrId);
}
-int TownsAudioInterface::intf_loadInstrument(va_list &args) {
+int TownsAudioInterfaceIntern::intf_loadInstrument(va_list &args) {
int chanType = va_arg(args, int);
int instrId = va_arg(args, int);
uint8 *instrData = va_arg(args, uint8 *);
return (chanType & 0x40) ? pcmLoadInstrument(instrId, instrData) : fmLoadInstrument(instrId, instrData);
}
-int TownsAudioInterface::intf_setPitch(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setPitch(va_list &args) {
int chan = va_arg(args, int);
int16 pitch = (int16)(va_arg(args, int) & 0xffff);
return (chan & 0x40) ? pcmSetPitch(chan, pitch) : fmSetPitch(chan, pitch);
}
-int TownsAudioInterface::intf_setLevel(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setLevel(va_list &args) {
int chan = va_arg(args, int);
int lvl = va_arg(args, int);
return (chan & 0x40) ? pcmSetLevel(chan, lvl) : fmSetLevel(chan, lvl);
}
-int TownsAudioInterface::intf_chanOff(va_list &args) {
+int TownsAudioInterfaceIntern::intf_chanOff(va_list &args) {
int chan = va_arg(args, int);
return (chan & 0x40) ? pcmChanOff(chan) : fmChanOff(chan);
}
-int TownsAudioInterface::intf_writeReg(va_list &args) {
+int TownsAudioInterfaceIntern::intf_writeReg(va_list &args) {
int part = va_arg(args, int) ? 1 : 0;
int reg = va_arg(args, int);
int val = va_arg(args, int);
@@ -424,7 +618,7 @@ int TownsAudioInterface::intf_writeReg(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_writeRegBuffer(va_list &args) {
+int TownsAudioInterfaceIntern::intf_writeRegBuffer(va_list &args) {
int part = va_arg(args, int) ? 1 : 0;
int reg = va_arg(args, int);
int val = va_arg(args, int);
@@ -436,7 +630,7 @@ int TownsAudioInterface::intf_writeRegBuffer(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_readRegBuffer(va_list &args) {
+int TownsAudioInterfaceIntern::intf_readRegBuffer(va_list &args) {
int part = va_arg(args, int) ? 1 : 0;
int reg = va_arg(args, int);
uint8 *dst = va_arg(args, uint8 *);
@@ -449,7 +643,7 @@ int TownsAudioInterface::intf_readRegBuffer(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_setTimerA(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setTimerA(va_list &args) {
int enable = va_arg(args, int);
int tempo = va_arg(args, int);
@@ -464,7 +658,7 @@ int TownsAudioInterface::intf_setTimerA(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_setTimerB(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setTimerB(va_list &args) {
int enable = va_arg(args, int);
int tempo = va_arg(args, int);
@@ -478,17 +672,17 @@ int TownsAudioInterface::intf_setTimerB(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_enableTimerA(va_list &args) {
+int TownsAudioInterfaceIntern::intf_enableTimerA(va_list &args) {
bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x15);
return 0;
}
-int TownsAudioInterface::intf_enableTimerB(va_list &args) {
+int TownsAudioInterfaceIntern::intf_enableTimerB(va_list &args) {
bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x2a);
return 0;
}
-int TownsAudioInterface::intf_loadSamples(va_list &args) {
+int TownsAudioInterfaceIntern::intf_loadSamples(va_list &args) {
uint32 dest = va_arg(args, uint32);
int size = va_arg(args, int);
uint8 *src = va_arg(args, uint8*);
@@ -511,7 +705,7 @@ int TownsAudioInterface::intf_loadSamples(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_reserveEffectChannels(va_list &args) {
+int TownsAudioInterfaceIntern::intf_reserveEffectChannels(va_list &args) {
int numChan = va_arg(args, int);
if (numChan > 8)
return 3;
@@ -543,7 +737,7 @@ int TownsAudioInterface::intf_reserveEffectChannels(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_loadWaveTable(va_list &args) {
+int TownsAudioInterfaceIntern::intf_loadWaveTable(va_list &args) {
uint8 *data = va_arg(args, uint8 *);
if (_numWaveTables > 127)
return 3;
@@ -570,7 +764,7 @@ int TownsAudioInterface::intf_loadWaveTable(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_unloadWaveTable(va_list &args) {
+int TownsAudioInterfaceIntern::intf_unloadWaveTable(va_list &args) {
int id = va_arg(args, int);
if (id == -1) {
@@ -597,7 +791,7 @@ int TownsAudioInterface::intf_unloadWaveTable(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_pcmPlayEffect(va_list &args) {
+int TownsAudioInterfaceIntern::intf_pcmPlayEffect(va_list &args) {
int chan = va_arg(args, int);
int note = va_arg(args, int);
int velo = va_arg(args, int);
@@ -647,13 +841,13 @@ int TownsAudioInterface::intf_pcmPlayEffect(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_pcmChanOff(va_list &args) {
+int TownsAudioInterfaceIntern::intf_pcmChanOff(va_list &args) {
int chan = va_arg(args, int);
pcmChanOff(chan);
return 0;
}
-int TownsAudioInterface::intf_pcmEffectPlaying(va_list &args) {
+int TownsAudioInterfaceIntern::intf_pcmEffectPlaying(va_list &args) {
int chan = va_arg(args, int);
if (chan < 0x40 || chan > 0x47)
return 1;
@@ -661,54 +855,54 @@ int TownsAudioInterface::intf_pcmEffectPlaying(va_list &args) {
return (_pcmChanEffectPlaying & _chanFlags[chan]) ? 1 : 0;
}
-int TownsAudioInterface::intf_fmKeyOn(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmKeyOn(va_list &args) {
int chan = va_arg(args, int);
int note = va_arg(args, int);
int velo = va_arg(args, int);
return fmKeyOn(chan, note, velo);
}
-int TownsAudioInterface::intf_fmKeyOff(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmKeyOff(va_list &args) {
int chan = va_arg(args, int);
return fmKeyOff(chan);
}
-int TownsAudioInterface::intf_fmSetPanPos(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmSetPanPos(va_list &args) {
int chan = va_arg(args, int);
int mode = va_arg(args, int);
return fmSetPanPos(chan, mode);
}
-int TownsAudioInterface::intf_fmSetInstrument(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmSetInstrument(va_list &args) {
int chan = va_arg(args, int);
int instrId = va_arg(args, int);
return fmSetInstrument(chan, instrId);
}
-int TownsAudioInterface::intf_fmLoadInstrument(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmLoadInstrument(va_list &args) {
int instrId = va_arg(args, int);
uint8 *instrData = va_arg(args, uint8 *);
return fmLoadInstrument(instrId, instrData);
}
-int TownsAudioInterface::intf_fmSetPitch(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmSetPitch(va_list &args) {
int chan = va_arg(args, int);
uint16 freq = va_arg(args, int) & 0xffff;
return fmSetPitch(chan, freq);
}
-int TownsAudioInterface::intf_fmSetLevel(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmSetLevel(va_list &args) {
int chan = va_arg(args, int);
int lvl = va_arg(args, int);
return fmSetLevel(chan, lvl);
}
-int TownsAudioInterface::intf_fmReset(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmReset(va_list &args) {
fmReset();
return 0;
}
-int TownsAudioInterface::intf_setOutputVolume(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setOutputVolume(va_list &args) {
int chanType = va_arg(args, int);
int left = va_arg(args, int);
int right = va_arg(args, int);
@@ -743,7 +937,7 @@ int TownsAudioInterface::intf_setOutputVolume(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_resetOutputVolume(va_list &args) {
+int TownsAudioInterfaceIntern::intf_resetOutputVolume(va_list &args) {
memset(_outputLevel, 0, sizeof(_outputLevel));
_outputMuteFlags = 0;
_outputVolumeFlags = 0;
@@ -751,30 +945,30 @@ int TownsAudioInterface::intf_resetOutputVolume(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_updateOutputVolume(va_list &args) {
+int TownsAudioInterfaceIntern::intf_updateOutputVolume(va_list &args) {
int flags = va_arg(args, int);
_outputMuteFlags = flags & 3;
updateOutputVolume();
return 0;
}
-int TownsAudioInterface::intf_cdaToggle(va_list &args) {
+int TownsAudioInterfaceIntern::intf_cdaToggle(va_list &args) {
//int mode = va_arg(args, int);
//_unkMask = mode ? 0x7f : 0x3f;
return 0;
}
-int TownsAudioInterface::intf_pcmUpdateEnvelopeGenerator(va_list &args) {
+int TownsAudioInterfaceIntern::intf_pcmUpdateEnvelopeGenerator(va_list &args) {
for (int i = 0; i < 8; i++)
pcmUpdateEnvelopeGenerator(i);
return 0;
}
-int TownsAudioInterface::intf_notImpl(va_list &args) {
+int TownsAudioInterfaceIntern::intf_notImpl(va_list &args) {
return 4;
}
-void TownsAudioInterface::fmReset() {
+void TownsAudioInterfaceIntern::fmReset() {
TownsPC98_FmSynth::reset();
_fmChanPlaying = 0;
@@ -802,7 +996,7 @@ void TownsAudioInterface::fmReset() {
}
}
-int TownsAudioInterface::fmKeyOn(int chan, int note, int velo) {
+int TownsAudioInterfaceIntern::fmKeyOn(int chan, int note, int velo) {
if (chan > 5)
return 1;
if (note < 12 || note > 107 || (velo & 0x80))
@@ -882,7 +1076,7 @@ int TownsAudioInterface::fmKeyOn(int chan, int note, int velo) {
return 0;
}
-int TownsAudioInterface::fmKeyOff(int chan) {
+int TownsAudioInterfaceIntern::fmKeyOff(int chan) {
if (chan > 5)
return 1;
_fmChanPlaying &= ~_chanFlags[chan];
@@ -892,7 +1086,7 @@ int TownsAudioInterface::fmKeyOff(int chan) {
return 0;
}
-int TownsAudioInterface::fmChanOff(int chan) {
+int TownsAudioInterfaceIntern::fmChanOff(int chan) {
if (chan > 5)
return 1;
_fmChanPlaying &= ~_chanFlags[chan];
@@ -910,7 +1104,7 @@ int TownsAudioInterface::fmChanOff(int chan) {
return 0;
}
-int TownsAudioInterface::fmSetPanPos(int chan, int value) {
+int TownsAudioInterfaceIntern::fmSetPanPos(int chan, int value) {
if (chan > 5)
return 1;
@@ -929,7 +1123,7 @@ int TownsAudioInterface::fmSetPanPos(int chan, int value) {
return 0;
}
-int TownsAudioInterface::fmSetInstrument(int chan, int instrId) {
+int TownsAudioInterfaceIntern::fmSetInstrument(int chan, int instrId) {
if (chan > 5)
return 1;
if (instrId > 127)
@@ -973,7 +1167,7 @@ int TownsAudioInterface::fmSetInstrument(int chan, int instrId) {
return 0;
}
-int TownsAudioInterface::fmLoadInstrument(int instrId, const uint8 *data) {
+int TownsAudioInterfaceIntern::fmLoadInstrument(int instrId, const uint8 *data) {
if (instrId > 127)
return 3;
assert(data);
@@ -981,7 +1175,7 @@ int TownsAudioInterface::fmLoadInstrument(int instrId, const uint8 *data) {
return 0;
}
-int TownsAudioInterface::fmSetPitch(int chan, int pitch) {
+int TownsAudioInterfaceIntern::fmSetPitch(int chan, int pitch) {
if (chan > 5)
return 1;
@@ -1068,7 +1262,7 @@ int TownsAudioInterface::fmSetPitch(int chan, int pitch) {
return 0;
}
-int TownsAudioInterface::fmSetLevel(int chan, int lvl) {
+int TownsAudioInterfaceIntern::fmSetLevel(int chan, int lvl) {
if (chan > 5)
return 1;
if (lvl > 127)
@@ -1091,12 +1285,12 @@ int TownsAudioInterface::fmSetLevel(int chan, int lvl) {
return 0;
}
-void TownsAudioInterface::bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value) {
+void TownsAudioInterfaceIntern::bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value) {
_fmSaveReg[part][regAddress] = value;
writeReg(part, regAddress, value);
}
-void TownsAudioInterface::pcmReset() {
+void TownsAudioInterfaceIntern::pcmReset() {
_pcmChanOut = 0;
_pcmChanReserved = _pcmChanKeyPressed = _pcmChanEffectPlaying = _pcmChanKeyPlaying = 0;
_numReservedChannels = 0;
@@ -1124,7 +1318,7 @@ void TownsAudioInterface::pcmReset() {
}
}
-int TownsAudioInterface::pcmKeyOn(int chan, int note, int velo) {
+int TownsAudioInterfaceIntern::pcmKeyOn(int chan, int note, int velo) {
if (chan < 0x40 || chan > 0x47)
return 1;
@@ -1195,7 +1389,7 @@ int TownsAudioInterface::pcmKeyOn(int chan, int note, int velo) {
return 0;
}
-int TownsAudioInterface::pcmKeyOff(int chan) {
+int TownsAudioInterfaceIntern::pcmKeyOff(int chan) {
if (chan < 0x40 || chan > 0x47)
return 1;
@@ -1205,7 +1399,7 @@ int TownsAudioInterface::pcmKeyOff(int chan) {
return 0;
}
-int TownsAudioInterface::pcmChanOff(int chan) {
+int TownsAudioInterfaceIntern::pcmChanOff(int chan) {
if (chan < 0x40 || chan > 0x47)
return 1;
@@ -1219,7 +1413,7 @@ int TownsAudioInterface::pcmChanOff(int chan) {
return 0;
}
-int TownsAudioInterface::pcmSetPanPos(int chan, int mode) {
+int TownsAudioInterfaceIntern::pcmSetPanPos(int chan, int mode) {
if (chan > 0x47)
return 1;
if (mode & 0x80)
@@ -1242,7 +1436,7 @@ int TownsAudioInterface::pcmSetPanPos(int chan, int mode) {
return 0;
}
-int TownsAudioInterface::pcmSetInstrument(int chan, int instrId) {
+int TownsAudioInterfaceIntern::pcmSetInstrument(int chan, int instrId) {
if (chan > 0x47)
return 1;
if (instrId > 31)
@@ -1252,7 +1446,7 @@ int TownsAudioInterface::pcmSetInstrument(int chan, int instrId) {
return 0;
}
-int TownsAudioInterface::pcmLoadInstrument(int instrId, const uint8 *data) {
+int TownsAudioInterfaceIntern::pcmLoadInstrument(int instrId, const uint8 *data) {
if (instrId > 31)
return 3;
assert(data);
@@ -1260,7 +1454,7 @@ int TownsAudioInterface::pcmLoadInstrument(int instrId, const uint8 *data) {
return 0;
}
-int TownsAudioInterface::pcmSetPitch(int chan, int pitch) {
+int TownsAudioInterfaceIntern::pcmSetPitch(int chan, int pitch) {
if (chan > 0x47)
return 1;
@@ -1290,7 +1484,7 @@ int TownsAudioInterface::pcmSetPitch(int chan, int pitch) {
return 0;
}
-int TownsAudioInterface::pcmSetLevel(int chan, int lvl) {
+int TownsAudioInterfaceIntern::pcmSetLevel(int chan, int lvl) {
if (chan > 0x47)
return 1;
@@ -1319,7 +1513,7 @@ int TownsAudioInterface::pcmSetLevel(int chan, int lvl) {
return 0;
}
-void TownsAudioInterface::pcmUpdateEnvelopeGenerator(int chan) {
+void TownsAudioInterfaceIntern::pcmUpdateEnvelopeGenerator(int chan) {
TownsAudio_PcmChannel *p = &_pcmChan[chan];
if (!p->envCurrentLevel) {
_pcmChanKeyPlaying &= ~_chanFlags[chan];
@@ -1361,7 +1555,7 @@ void TownsAudioInterface::pcmUpdateEnvelopeGenerator(int chan) {
p->velo = (p->envCurrentLevel >> 8) << 1;
}
-void TownsAudioInterface::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w) {
+void TownsAudioInterfaceIntern::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w) {
int8 diff = p->note - w->baseNote;
uint16 r = w->rate + w->rateOffs;
uint16 bl = 0;
@@ -1390,7 +1584,7 @@ void TownsAudioInterface::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_
p->step = (s * p->stepPitch) >> 14;
}
-void TownsAudioInterface::updateOutputVolume() {
+void TownsAudioInterfaceIntern::updateOutputVolume() {
// FM Towns seems to support volumes of 0 - 63 for each channel.
// We recalculate sane values for our 0 to 255 volume range and
// balance values for our -128 to 127 volume range
@@ -1405,30 +1599,34 @@ void TownsAudioInterface::updateOutputVolume() {
g_system->getAudioCDManager()->setBalance(balance);
}
-const uint8 TownsAudioInterface::_chanFlags[] = {
+TownsAudioInterfaceIntern *TownsAudioInterfaceIntern::_refInstance = 0;
+
+int TownsAudioInterfaceIntern::_refCount = 0;
+
+const uint8 TownsAudioInterfaceIntern::_chanFlags[] = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
};
-const uint16 TownsAudioInterface::_frequency[] = {
+const uint16 TownsAudioInterfaceIntern::_frequency[] = {
0x028C, 0x02B4, 0x02DC, 0x030A, 0x0338, 0x0368, 0x039C, 0x03D4, 0x040E, 0x044A, 0x048C, 0x04D0
};
-const uint8 TownsAudioInterface::_carrier[] = {
+const uint8 TownsAudioInterfaceIntern::_carrier[] = {
0x10, 0x10, 0x10, 0x10, 0x30, 0x70, 0x70, 0xF0
};
-const uint8 TownsAudioInterface::_fmDefaultInstrument[] = {
+const uint8 TownsAudioInterfaceIntern::_fmDefaultInstrument[] = {
0x45, 0x4C, 0x45, 0x50, 0x49, 0x41, 0x4E, 0x4F, 0x01, 0x0A, 0x02, 0x01,
0x1E, 0x32, 0x05, 0x00, 0x9C, 0xDC, 0x9C, 0xDC, 0x07, 0x03, 0x14, 0x08,
0x00, 0x03, 0x05, 0x05, 0x55, 0x45, 0x27, 0xA7, 0x04, 0xC0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-const uint16 TownsAudioInterface::_pcmPhase1[] = {
+const uint16 TownsAudioInterfaceIntern::_pcmPhase1[] = {
0x879B, 0x0F37, 0x1F58, 0x306E, 0x4288, 0x55B6, 0x6A08, 0x7F8F, 0x965E, 0xAE88, 0xC882, 0xE341
};
-const uint16 TownsAudioInterface::_pcmPhase2[] = {
+const uint16 TownsAudioInterfaceIntern::_pcmPhase2[] = {
0xFEFE, 0xF1A0, 0xE411, 0xD744, 0xCB2F, 0xBFC7, 0xB504, 0xAAE2, 0xA144, 0x9827, 0x8FAC
};
@@ -1579,3 +1777,37 @@ void TownsAudio_WaveTable::clear() {
data = 0;
}
+TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) {
+ _intf = TownsAudioInterfaceIntern::addNewRef(mixer, driver);
+}
+
+TownsAudioInterface::~TownsAudioInterface() {
+ TownsAudioInterfaceIntern::releaseRef();
+ _intf = 0;
+}
+
+bool TownsAudioInterface::init() {
+ return _intf->init();
+}
+
+int TownsAudioInterface::callback(int command, ...) {
+ va_list args;
+ va_start(args, command);
+
+ int res = _intf->processCommand(command, args);
+
+ va_end(args);
+ return res;
+}
+
+void TownsAudioInterface::setMusicVolume(int volume) {
+ _intf->setMusicVolume(volume);
+}
+
+void TownsAudioInterface::setSoundEffectVolume(int volume) {
+ _intf->setSoundEffectVolume(volume);
+}
+
+void TownsAudioInterface::setSoundEffectChanMask(int mask) {
+ _intf->setSoundEffectChanMask(mask);
+} \ No newline at end of file
diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.h b/audio/softsynth/fmtowns_pc98/towns_audio.h
index f3d863b949..2c58d46d06 100644
--- a/audio/softsynth/fmtowns_pc98/towns_audio.h
+++ b/audio/softsynth/fmtowns_pc98/towns_audio.h
@@ -23,7 +23,9 @@
#ifndef TOWNS_AUDIO_H
#define TOWNS_AUDIO_H
-#include "audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
+#include "audio/mixer.h"
+
+class TownsAudioInterfaceIntern;
class TownsAudioInterfacePluginDriver {
public:
@@ -31,10 +33,7 @@ public:
virtual void timerCallback(int timerId) = 0;
};
-class TownsAudio_PcmChannel;
-class TownsAudio_WaveTable;
-
-class TownsAudioInterface : public TownsPC98_FmSynth {
+class TownsAudioInterface {
public:
TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver);
~TownsAudioInterface();
@@ -50,126 +49,7 @@ public:
void setSoundEffectChanMask(int mask);
private:
- void nextTickEx(int32 *buffer, uint32 bufferSize);
-
- void timerCallbackA();
- void timerCallbackB();
-
- typedef int (TownsAudioInterface::*TownsAudioIntfCallback)(va_list &);
- const TownsAudioIntfCallback *_intfOpcodes;
-
- int intf_reset(va_list &args);
- int intf_keyOn(va_list &args);
- int intf_keyOff(va_list &args);
- int intf_setPanPos(va_list &args);
- int intf_setInstrument(va_list &args);
- int intf_loadInstrument(va_list &args);
- int intf_setPitch(va_list &args);
- int intf_setLevel(va_list &args);
- int intf_chanOff(va_list &args);
- int intf_writeReg(va_list &args);
- int intf_writeRegBuffer(va_list &args);
- int intf_readRegBuffer(va_list &args);
- int intf_setTimerA(va_list &args);
- int intf_setTimerB(va_list &args);
- int intf_enableTimerA(va_list &args);
- int intf_enableTimerB(va_list &args);
- int intf_loadSamples(va_list &args);
- int intf_reserveEffectChannels(va_list &args);
- int intf_loadWaveTable(va_list &args);
- int intf_unloadWaveTable(va_list &args);
- int intf_pcmPlayEffect(va_list &args);
- int intf_pcmChanOff(va_list &args);
- int intf_pcmEffectPlaying(va_list &args);
- int intf_fmKeyOn(va_list &args);
- int intf_fmKeyOff(va_list &args);
- int intf_fmSetPanPos(va_list &args);
- int intf_fmSetInstrument(va_list &args);
- int intf_fmLoadInstrument(va_list &args);
- int intf_fmSetPitch(va_list &args);
- int intf_fmSetLevel(va_list &args);
- int intf_fmReset(va_list &args);
- int intf_setOutputVolume(va_list &args);
- int intf_resetOutputVolume(va_list &args);
- int intf_updateOutputVolume(va_list &args);
- int intf_cdaToggle(va_list &args);
- int intf_pcmUpdateEnvelopeGenerator(va_list &args);
-
- int intf_notImpl(va_list &args);
-
- void fmReset();
- int fmKeyOn(int chan, int note, int velo);
- int fmKeyOff(int chan);
- int fmChanOff(int chan);
- int fmSetPanPos(int chan, int mode);
- int fmSetInstrument(int chan, int instrId);
- int fmLoadInstrument(int instrId, const uint8 *data);
- int fmSetPitch(int chan, int pitch);
- int fmSetLevel(int chan, int lvl);
-
- void bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value);
-
- uint8 _fmChanPlaying;
- uint8 _fmChanNote[6];
- int16 _fmChanPitch[6];
-
- uint8 *_fmSaveReg[2];
- uint8 *_fmInstruments;
-
- void pcmReset();
- int pcmKeyOn(int chan, int note, int velo);
- int pcmKeyOff(int chan);
- int pcmChanOff(int chan);
- int pcmSetPanPos(int chan, int mode);
- int pcmSetInstrument(int chan, int instrId);
- int pcmLoadInstrument(int instrId, const uint8 *data);
- int pcmSetPitch(int chan, int pitch);
- int pcmSetLevel(int chan, int lvl);
- void pcmUpdateEnvelopeGenerator(int chan);
-
- TownsAudio_PcmChannel *_pcmChan;
- uint8 _pcmChanOut;
- uint8 _pcmChanReserved;
- uint8 _pcmChanKeyPressed;
- uint8 _pcmChanEffectPlaying;
- uint8 _pcmChanKeyPlaying;
-
- uint8 _pcmChanNote[8];
- uint8 _pcmChanVelo[8];
- uint8 _pcmChanLevel[8];
-
- uint8 _numReservedChannels;
- uint8 *_pcmInstruments;
-
- TownsAudio_WaveTable *_waveTables;
- uint8 _numWaveTables;
- uint32 _waveTablesTotalDataSize;
-
- void pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w);
-
- void updateOutputVolume();
- uint8 _outputVolumeFlags;
- uint8 _outputLevel[16];
- uint8 _outputMuteFlags;
-
- const float _baserate;
- uint32 _timerBase;
- uint32 _tickLength;
- uint32 _timer;
-
- uint16 _musicVolume;
- uint16 _sfxVolume;
- int _pcmSfxChanMask;
-
- TownsAudioInterfacePluginDriver *_drv;
- bool _ready;
-
- static const uint8 _chanFlags[];
- static const uint16 _frequency[];
- static const uint8 _carrier[];
- static const uint8 _fmDefaultInstrument[];
- static const uint16 _pcmPhase1[];
- static const uint16 _pcmPhase2[];
+ TownsAudioInterfaceIntern *_intf;
};
#endif
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
index bbde75eb66..3b46aca14d 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
@@ -26,6 +26,7 @@
#include "audio/musicplugin.h"
#include "common/translation.h"
#include "common/error.h"
+#include "common/system.h"
class TownsEmuMusicPlugin : public MusicPluginObject {