aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pitkanen2011-06-10 19:35:00 +0300
committerEugene Sandulenko2011-08-13 23:26:36 +0100
commit24bb5da2288b782cfe0e9546ca811e7dd28d0359 (patch)
tree722bfde7aab7049f3dbbc406a9d8c49e8d2fbba0
parent8183103777fbf3528d184aa87201aed76923d8a1 (diff)
downloadscummvm-rg350-24bb5da2288b782cfe0e9546ca811e7dd28d0359.tar.gz
scummvm-rg350-24bb5da2288b782cfe0e9546ca811e7dd28d0359.tar.bz2
scummvm-rg350-24bb5da2288b782cfe0e9546ca811e7dd28d0359.zip
AGI: Add a layer of abstraction between the sound chip and the two players
-rw-r--r--engines/agi/sound_pcjr.cpp178
-rw-r--r--engines/agi/sound_pcjr.h14
2 files changed, 72 insertions, 120 deletions
diff --git a/engines/agi/sound_pcjr.cpp b/engines/agi/sound_pcjr.cpp
index d5c6935139..2ca71557ba 100644
--- a/engines/agi/sound_pcjr.cpp
+++ b/engines/agi/sound_pcjr.cpp
@@ -220,12 +220,12 @@ int SoundGenPCJr::volumeCalc(SndGenChan *chan) {
return attenuation;
}
-int SoundGenPCJr::getNextNote(int ch, Tone *tone)
+int SoundGenPCJr::getNextNote(int ch)
{
if (_vm->getVersion() > 0x2001)
- return getNextNote_v2(ch, tone);
+ return getNextNote_v2(ch);
else
- return getNextNote_v1(ch, tone);
+ return getNextNote_v1(ch);
return -1;
}
@@ -234,13 +234,11 @@ int SoundGenPCJr::getNextNote(int ch, Tone *tone)
// if tone isn't touched.. it should be inited so it just plays silence
// return 0 if it's passing more data
// return -1 if it's passing nothing (end of data)
-
-int SoundGenPCJr::getNextNote_v2(int ch, Tone *tone) {
+int SoundGenPCJr::getNextNote_v2(int ch) {
ToneChan *tpcm;
SndGenChan *chan;
const byte *data;
- assert(tone);
assert(ch < CHAN_MAX);
if (!_vm->getflag(fSoundOn))
@@ -251,7 +249,7 @@ int SoundGenPCJr::getNextNote_v2(int ch, Tone *tone) {
if (!chan->avail)
return -1;
- while ((chan->duration == 0) && (chan->duration != 0xFFFF)) {
+ while (chan->duration <= 0) {
data = chan->data;
// read the duration of the note
@@ -259,58 +257,32 @@ int SoundGenPCJr::getNextNote_v2(int ch, Tone *tone) {
// if it's 0 then it's not going to be played
// if it's 0xFFFF then the channel data has finished.
- if ((chan->duration != 0) && (chan->duration != 0xFFFF)) {
+ if ((chan->duration == 0) || (chan->duration == 0xFFFF)) {
tpcm->genTypePrev = -1;
tpcm->freqCountPrev = -1;
- // only tone channels dissolve
- if ((ch != 3) && (_dissolveMethod != 0)) // != noise??
- chan->dissolveCount = 0;
+ break;
+ }
- // attenuation (volume)
- chan->attenuation = data[4] & 0xF;
+ _tchannel[ch].genTypePrev = -1;
+ _tchannel[ch].freqCountPrev = -1;
- // frequency
- if (ch < (CHAN_MAX - 1)) {
- chan->freqCount = (uint16)data[2] & 0x3F;
- chan->freqCount <<= 4;
- chan->freqCount |= data[3] & 0x0F;
+ // only tone channels dissolve
+ if ((ch != 3) && (_dissolveMethod != 0)) // != noise??
+ chan->dissolveCount = 0;
+
+ // attenuation (volume)
+ writeData(data[4]);
+
+ // frequency
+ writeData(data[3]);
+ writeData(data[2]);
- chan->genType = kGenTone;
- } else {
- int noiseFreq;
-
- // check for white noise (1) or periodic (0)
- chan->genType = (data[3] & 0x04) ? kGenWhite : kGenPeriod;
-
- noiseFreq = data[3] & 0x03;
-
- switch (noiseFreq) {
- case 0:
- chan->freqCount = 32;
- break;
- case 1:
- chan->freqCount = 64;
- break;
- case 2:
- chan->freqCount = 128;
- break;
- case 3:
- chan->freqCount = _channel[2].freqCount * 2;
- break;
- }
- }
- }
// data now points to the next data seg-a-ment
chan->data += 5;
}
- if (chan->duration != 0xFFFF) {
- tone->freqCount = chan->freqCount;
- tone->atten = volumeCalc(chan); // calc volume, sent vol is different from saved vol
- tone->type = chan->genType;
- chan->duration--;
- } else {
+ if (chan->duration == 0xFFFF) {
// kill channel
chan->avail = 0;
chan->attenuation = 0x0F; // silent
@@ -319,17 +291,17 @@ int SoundGenPCJr::getNextNote_v2(int ch, Tone *tone) {
return -1;
}
+ chan->duration--;
+
return 0;
}
-int SoundGenPCJr::getNextNote_v1(int ch, Tone *tone)
-{
- static bool fetched[4] = { false, false, false, false };
+int SoundGenPCJr::getNextNote_v1(int ch) {
+ static int channels = 4;
static int duration = 0;
byte *data = _v1data;
uint32 len = _v1size;
- int reg = 0;
if (len <= 0 || data == NULL) {
_channel[ch].avail = 0;
@@ -339,60 +311,22 @@ int SoundGenPCJr::getNextNote_v1(int ch, Tone *tone)
}
// Get previously fetched data if possible
- if (fetched[ch]) {
- fetched[ch] = false;
-
- tone->freqCount = _channel[ch].freqCount;
- tone->atten = _channel[ch].attenuation;
- tone->type = _channel[ch].genType;
-
+ if (channels > 0) {
+ channels--;
return 0;
}
+ channels = 4;
// In the V1 player the default duration for a row is 2 ticks
if (duration > 0) {
duration--;
-
- tone->freqCount = _channel[ch].freqCount;
- tone->atten = _channel[ch].attenuation;
- tone->type = _channel[ch].genType;
-
return 0;
}
duration = 2 * CHAN_MAX;
// Otherwise fetch a row of data for all channels
- fetched[0] = fetched[1] = fetched[2] = fetched[3] = true;
-
while (*data) {
- if ((*data & 0x90) == 0x90) {
- reg = (*data >> 5) & 0x3;
- _channel[reg].attenuation = *data & 0xF;
- } else if ((*data & 0xF0) == 0xE0) {
- _channel[3].genType = (data[3] & 0x4) ? kGenWhite : kGenPeriod;
- int noiseFreq = data[3] & 0x03;
- switch (noiseFreq) {
- case 0:
- _channel[3].freqCount = 32;
- break;
- case 1:
- _channel[3].freqCount = 64;
- break;
- case 2:
- _channel[3].freqCount = 128;
- break;
- case 3:
- _channel[3].freqCount = _channel[2].freqCount * 2;
- break;
- }
- } else if (*data & 0x80) {
- reg = (*data >> 5) & 0x3;
- _channel[reg].freqCount = *data & 0xF;
- _channel[reg].genType = kGenTone;
- } else {
- _channel[reg].freqCount |= (*data & 0x3F) << 4;
- }
-
+ writeData(*data);
data++;
len--;
}
@@ -402,13 +336,43 @@ int SoundGenPCJr::getNextNote_v1(int ch, Tone *tone)
_v1data = data;
_v1size = len;
- tone->freqCount = _channel[ch].freqCount;
- tone->atten = _channel[ch].attenuation;
- tone->type = _channel[ch].genType;
-
return 0;
}
+void SoundGenPCJr::writeData(uint8 val) {
+ static int reg = 0;
+
+ debugC(5, kDebugLevelSound, "writeData(%.2X)", val);
+
+ if ((val & 0x90) == 0x90) {
+ reg = (val >> 5) & 0x3;
+ _channel[reg].attenuation = val & 0xF;
+ } else if ((val & 0xF0) == 0xE0) {
+ _channel[3].genType = (val & 0x4) ? kGenWhite : kGenPeriod;
+ int noiseFreq = val & 0x03;
+ switch (noiseFreq) {
+ case 0:
+ _channel[3].freqCount = 32;
+ break;
+ case 1:
+ _channel[3].freqCount = 64;
+ break;
+ case 2:
+ _channel[3].freqCount = 128;
+ break;
+ case 3:
+ _channel[3].freqCount = _channel[2].freqCount * 2;
+ break;
+ }
+ } else if (val & 0x80) {
+ reg = (val >> 5) & 0x3;
+ _channel[reg].freqCount = val & 0xF;
+ _channel[reg].genType = kGenTone;
+ } else {
+ _channel[reg].freqCount |= (val & 0x3F) << 4;
+ }
+}
+
// Formulas for noise generator
// bit0 = output
@@ -444,7 +408,6 @@ const int16 volTable[16] = {
// fill buff
int SoundGenPCJr::chanGen(int chan, int16 *stream, int len) {
ToneChan *tpcm;
- Tone toneNew;
int fillSize;
int retVal;
@@ -452,20 +415,13 @@ int SoundGenPCJr::chanGen(int chan, int16 *stream, int len) {
retVal = -1;
- debugC(5, kDebugLevelSound, "chanGen()");
-
while (len > 0) {
if (tpcm->noteCount <= 0) {
// get new tone data
- tpcm->avail=1;
- debugC(5, kDebugLevelSound, "new note data (avail=%d)", tpcm->avail);
- toneNew.freqCount = 0;
- toneNew.atten = 0xF;
- toneNew.type = kGenTone;
- if ((tpcm->avail) && (getNextNote(chan, &toneNew) == 0)) {
- tpcm->atten = toneNew.atten;
- tpcm->freqCount = toneNew.freqCount;
- tpcm->genType = toneNew.type;
+ if ((tpcm->avail) && (getNextNote(chan) == 0)) {
+ tpcm->atten = _channel[chan].attenuation;
+ tpcm->freqCount = _channel[chan].freqCount;
+ tpcm->genType = _channel[chan].genType;
// setup counters 'n stuff
// SAMPLE_RATE samples per sec.. tone changes 60 times per sec
diff --git a/engines/agi/sound_pcjr.h b/engines/agi/sound_pcjr.h
index d9ced4ac80..ec3fdff972 100644
--- a/engines/agi/sound_pcjr.h
+++ b/engines/agi/sound_pcjr.h
@@ -71,12 +71,6 @@ struct ToneChan {
int feedback; /* noise feedback mask */
};
-struct Tone {
- int freqCount;
- int atten;
- GenType type;
-};
-
class SoundGenPCJr : public SoundGen, public Audio::AudioStream {
public:
SoundGenPCJr(AgiEngine *vm, Audio::Mixer *pMixer);
@@ -102,11 +96,13 @@ public:
}
private:
- int getNextNote(int ch, Tone *tone);
- int getNextNote_v2(int ch, Tone *tone);
- int getNextNote_v1(int ch, Tone *tone);
+ int getNextNote(int ch);
+ int getNextNote_v2(int ch);
+ int getNextNote_v1(int ch);
int volumeCalc(SndGenChan *chan);
+ void writeData(uint8 val);
+
int chanGen(int chan, int16 *stream, int len);
int fillNoise(ToneChan *t, int16 *buf, int len);