aboutsummaryrefslogtreecommitdiff
path: root/audio/softsynth
diff options
context:
space:
mode:
authorathrxx2011-05-02 23:41:55 +0200
committerWillem Jan Palenstijn2011-05-17 20:36:26 +0200
commit9fa1b9aa361d204ca98e60917c4c7e2e3b3c4f64 (patch)
tree361a43035fab47de780b2ba930ef458f64d214a3 /audio/softsynth
parentd9772ff88f29e37fa7b91b7b6e43d846bcfad008 (diff)
downloadscummvm-rg350-9fa1b9aa361d204ca98e60917c4c7e2e3b3c4f64.tar.gz
scummvm-rg350-9fa1b9aa361d204ca98e60917c4c7e2e3b3c4f64.tar.bz2
scummvm-rg350-9fa1b9aa361d204ca98e60917c4c7e2e3b3c4f64.zip
FM-TOWNS AUDIO: More midi driver code
Diffstat (limited to 'audio/softsynth')
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_midi.cpp154
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_midi.h7
2 files changed, 123 insertions, 38 deletions
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index c492a97122..0cf8a0d581 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -49,28 +49,25 @@ public:
private:
struct StateA {
- uint8 active;
- uint8 fld_1;
- uint8 fld_2;
- uint8 fld_3;
- uint8 fld_4;
- uint8 fld_5;
- uint8 fld_6;
- uint8 fld_7;
- uint8 fld_8;
- uint32 fld_9;
- uint32 effectState;
+ uint8 numLoop;
+ int32 fld_1;
+ uint32 fld_5;
+ int32 fld_9;
+ int32 effectState;
uint8 fld_11;
- uint8 fld_12;
- uint8 fld_13;
- uint8 fld_14;
- uint8 fld_15;
- uint8 fld_16;
- uint8 fld_17;
- uint8 fld_18;
- uint8 fld_19;
+ uint8 ar1[4];
+ uint8 ar2[4];
uint8 fld_1a;
uint8 modWheelImpact;
+ uint8 fld_1c;
+ uint32 fld_1d;
+ uint32 fld_21;
+ uint32 fld_25;
+ int8 dir;
+ uint32 fld_2a;
+ uint8 fld_2b;
+ uint8 fld_2c;
+ uint8 fld_2d;
uint8 modWheel;
} *_stateA;
@@ -83,7 +80,9 @@ private:
} *_stateB;
uint32 getEffectState(uint8 type);
- void processEffect(StateA *a, const uint8 *effectData);
+ void initEffect(StateA *a, const uint8 *effectData);
+ void updateEffect(StateA *a);
+ int lookupVolume(int a, int b);
void keyOn();
void keyOff();
@@ -101,7 +100,7 @@ private:
uint8 _sustainNoteOff;
uint32 _duration;
uint8 _fld_13;
- uint8 _prg;
+ uint8 _prg;
uint16 _freq;
int16 _freqAdjust;
@@ -111,6 +110,7 @@ private:
static const uint8 _chanMap[];
static const uint8 _chanMap2[];
static const uint8 _effectDefs[];
+ static const uint16 _effectData[];
static const uint8 _freqMSB[];
static const uint16 _freqLSB[];
};
@@ -327,14 +327,14 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effec
break;
}
- processEffect(a, effectData);
+ initEffect(a, effectData);
}
void TownsMidiOutputChannel::setModWheel(uint8 value) {
- if (_stateA[0].active && _stateB[0].type)
+ if (_stateA[0].numLoop && _stateB[0].type)
_stateA[0].modWheel = value >> 2;
- if (_stateA[1].active && _stateB[1].type)
+ if (_stateA[1].numLoop && _stateB[1].type)
_stateA[1].modWheel = value >> 2;
}
@@ -393,8 +393,81 @@ uint32 TownsMidiOutputChannel::getEffectState(uint8 type) {
return res;
}
-void TownsMidiOutputChannel::processEffect(StateA *a, const uint8 *effectData) {
+void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) {
+ a->numLoop = 1;
+ a->fld_1 = 0;
+ a->fld_1c = 0x1f;
+ a->fld_5 = effectData[0];
+ a->ar1[0] = effectData[1];
+ a->ar1[1] = effectData[3];
+ a->ar1[2] = effectData[5];
+ a->ar1[3] = effectData[6];
+ a->ar2[0] = effectData[2];
+ a->ar2[1] = effectData[3];
+ a->ar2[2] = 0;
+ a->ar2[3] = effectData[7];
+ updateEffect(a);
+}
+
+void TownsMidiOutputChannel::updateEffect(StateA *a) {
+ uint8 c = --a->numLoop;
+ uint16 v = a->ar1[c];
+ int e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->fld_1a]];
+
+ if (v & 0x80)
+ e = _driver->randomValue(e);
+
+ if (!e)
+ e = 1;
+
+ a->fld_1d = a->fld_21 = e;
+ int32 d = 0;
+ if (c + 1 != 3) {
+ v = a->ar2[c];
+ e = lookupVolume(a->fld_9, (v & 0x7f) - 31);
+
+ if (v & 0x80)
+ e = _driver->randomValue(e);
+
+ if (e + a->effectState > a->fld_9) {
+ e = a->fld_9 - a->effectState;
+ } else {
+ if (e + a->effectState + 1 <= 0)
+ e = -e;
+ }
+
+ d = e - a->fld_1;
+ }
+
+ a->fld_25 = d / a->fld_1d;
+ a->dir = d < 0 ? -1 : 1;
+ a->fld_2a = d % a->fld_1d;
+
+ a->fld_2b = a->fld_2c = a->fld_2d = a->modWheel = 0;
+}
+
+int TownsMidiOutputChannel::lookupVolume(int a, int b) {
+ if (b == 0)
+ return 0;
+
+ if (b == 31)
+ return a;
+
+ if (a > 63)
+ return ((a + 1) * b) >> 5;
+
+ if (b < 0) {
+ if (a < 0)
+ return _driver->_chanOutputLevel[(-a << 5) - b];
+ else
+ return -_driver->_chanOutputLevel[(a << 5) - b];
+ } else {
+ if (a < 0)
+ return -_driver->_chanOutputLevel[(-a << 5) + b];
+ else
+ return _driver->_chanOutputLevel[(-a << 5) + b];
+ }
}
void TownsMidiOutputChannel::keyOn() {
@@ -452,6 +525,13 @@ const uint8 TownsMidiOutputChannel::_effectDefs[] = {
0x20, 0x04, 0x10, 0x00, 0xC0, 0x00, 0x01, 0x00, 0xC0, 0x01, 0x0E, 0x00
};
+const uint16 TownsMidiOutputChannel::_effectData[] = {
+ 0x0001, 0x0002, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000A, 0x000C, 0x000E, 0x0010, 0x0012, 0x0015, 0x0018, 0x001E,
+ 0x0024, 0x0032, 0x0040, 0x0052, 0x0064, 0x0088, 0x00A0, 0x00C0,
+ 0x00F0, 0x0114, 0x0154, 0x01CC, 0x0258, 0x035C, 0x04B0, 0x0640
+};
+
const uint8 TownsMidiOutputChannel::_freqMSB[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -556,12 +636,12 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
if (_instrument[11] & 0x80)
oc->setupEffects(0, _instrument[11], &_instrument[12]);
else
- oc->_stateA[0].active = 0;
+ oc->_stateA[0].numLoop = 0;
if (_instrument[20] & 0x80)
oc->setupEffects(1, _instrument[20], &_instrument[21]);
else
- oc->_stateA[1].active = 0;
+ oc->_stateA[1].numLoop = 0;
}
void TownsMidiInputChannel::programChange(byte program) {
@@ -661,7 +741,7 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = {
0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F
};
-MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timerBpara(0), _open(false) {
+MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _tickCounter(0), _curChan(0), _rand(1), _open(false) {
_intf = new TownsAudioInterface(mixer, this);
_channels = new TownsMidiInputChannel*[32];
@@ -681,9 +761,6 @@ MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timer
}
for (int i = 0; i < 64; i++)
_chanOutputLevel[i << 5] = 0;
-
- _tickCounter = 0;
- _curChan = 0;
}
MidiDriver_TOWNS::~MidiDriver_TOWNS() {
@@ -764,8 +841,8 @@ void MidiDriver_TOWNS::send(uint32 b) {
}
void MidiDriver_TOWNS::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
- _timerBproc = timer_proc;
- _timerBpara = timer_param;
+ _timerProc = timer_proc;
+ _timerProcPara = timer_param;
}
uint32 MidiDriver_TOWNS::getBaseTempo() {
@@ -792,12 +869,12 @@ void MidiDriver_TOWNS::timerCallback(int timerId) {
switch (timerId) {
case 1:
- if (_timerBproc) {
- _timerBproc(_timerBpara);
+ if (_timerProc) {
+ _timerProc(_timerProcPara);
_tickCounter += 10000;
while (_tickCounter >= 4167) {
_tickCounter -= 4167;
- _timerBproc(_timerBpara);
+ _timerProc(_timerProcPara);
}
}
break;
@@ -828,3 +905,8 @@ TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) {
return res;
}
+
+int MidiDriver_TOWNS::randomValue(int para) {
+ _rand = (_rand & 1) ? (_rand >> 1) ^ 0xb8 : (_rand >> 1);
+ return (_rand * para) >> 8;
+}
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
index 005c77cedf..1a4a8613ca 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.h
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.h
@@ -59,18 +59,21 @@ public:
private:
TownsMidiOutputChannel *allocateOutputChannel(int pri);
+
+ int randomValue(int para);
TownsMidiInputChannel **_channels;
TownsMidiOutputChannel **_out;
TownsMidiChanState *_chanState;
- Common::TimerManager::TimerProc _timerBproc;
- void *_timerBpara;
+ Common::TimerManager::TimerProc _timerProc;
+ void *_timerProcPara;
TownsAudioInterface *_intf;
uint32 _tickCounter;
uint8 _curChan;
+ uint8 _rand;
bool _open;