FM-TOWNS AUDIO: Change internal interface layout

This commit is contained in:
athrxx 2011-04-30 15:11:13 +02:00 committed by Willem Jan Palenstijn
parent 5c34e33c2c
commit 63a7859351
3 changed files with 322 additions and 209 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -26,6 +26,7 @@
#include "audio/musicplugin.h"
#include "common/translation.h"
#include "common/error.h"
#include "common/system.h"
class TownsEmuMusicPlugin : public MusicPluginObject {