diff options
author | athrxx | 2011-04-30 15:11:13 +0200 |
---|---|---|
committer | Willem Jan Palenstijn | 2011-05-17 20:24:28 +0200 |
commit | 63a78593516dc428f77ac01d90bc228fcf01de5d (patch) | |
tree | 3de4ed88a63a0350a3fb70253995202d97fddecb | |
parent | 5c34e33c2c27b2b5083199b40306370d732f4e53 (diff) | |
download | scummvm-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.cpp | 400 | ||||
-rw-r--r-- | audio/softsynth/fmtowns_pc98/towns_audio.h | 130 | ||||
-rw-r--r-- | audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp | 1 |
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 { |