mirror of https://github.com/stella-emu/stella.git
Improvement to volume sampling in TIA audio (#1038)
volume of audio channels sampled every on every tick. sum of samples is averaged and a new sample output twice per scanline this fixes issues with ROMs that change the volume of the audio multiple times per scanline. for example, the experimental ROM in the following thread now works correctly https://forums.atariage.com/topic/370460-8-bit-digital-audio-from-2600/ (note that the ROM does not initialise the machine cleanly and so running the emulator with developer options (random memory etc.) can cause incorrect audio)
This commit is contained in:
parent
56e6bd69bc
commit
e8a9fe282a
|
@ -47,6 +47,9 @@ void Audio::reset()
|
|||
{
|
||||
myCounter = 0;
|
||||
mySampleIndex = 0;
|
||||
sumChannel0 = 0;
|
||||
sumChannel1 = 0;
|
||||
sumCt = 0;
|
||||
|
||||
myChannel0.reset();
|
||||
myChannel1.reset();
|
||||
|
@ -62,10 +65,15 @@ void Audio::setAudioQueue(const shared_ptr<AudioQueue>& queue)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Audio::phase1()
|
||||
void Audio::createSample()
|
||||
{
|
||||
const uInt8 sample0 = myChannel0.phase1();
|
||||
const uInt8 sample1 = myChannel1.phase1();
|
||||
// calculate average of all recent volume samples. the average for each
|
||||
// channel is mixed to create a single audible value
|
||||
const uInt8 sample0 = (uInt8)(sumChannel0/sumCt);
|
||||
const uInt8 sample1 = (uInt8)(sumChannel1/sumCt);
|
||||
sumChannel0 = 0;
|
||||
sumChannel1 = 0;
|
||||
sumCt = 0;
|
||||
|
||||
addSample(sample0, sample1);
|
||||
#ifdef GUI_SUPPORT
|
||||
|
|
|
@ -57,7 +57,7 @@ class Audio : public Serializable
|
|||
bool load(Serializer& in) override;
|
||||
|
||||
private:
|
||||
void phase1();
|
||||
void createSample();
|
||||
void addSample(uInt8 sample0, uInt8 sample1);
|
||||
|
||||
private:
|
||||
|
@ -68,6 +68,10 @@ class Audio : public Serializable
|
|||
AudioChannel myChannel0;
|
||||
AudioChannel myChannel1;
|
||||
|
||||
uInt32 sumChannel0;
|
||||
uInt32 sumChannel1;
|
||||
uInt32 sumCt;
|
||||
|
||||
std::array<Int16, 0x1e + 1> myMixingTableSum;
|
||||
std::array<Int16, 0x0f + 1> myMixingTableIndividual;
|
||||
|
||||
|
@ -92,6 +96,12 @@ class Audio : public Serializable
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Audio::tick()
|
||||
{
|
||||
// volume for each channel is sampled every color clock. the average of
|
||||
// these samples will be taken twice a scanline in the phase1() function
|
||||
sumChannel0 += (uInt32)myChannel0.actualVolume();
|
||||
sumChannel1 += (uInt32)myChannel1.actualVolume();
|
||||
sumCt++;
|
||||
|
||||
switch (myCounter) {
|
||||
case 9:
|
||||
case 81:
|
||||
|
@ -101,7 +111,9 @@ void Audio::tick()
|
|||
|
||||
case 37:
|
||||
case 149:
|
||||
phase1();
|
||||
myChannel0.phase1();
|
||||
myChannel1.phase1();
|
||||
createSample();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -77,7 +77,7 @@ void AudioChannel::phase0()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 AudioChannel::phase1()
|
||||
void AudioChannel::phase1()
|
||||
{
|
||||
if (myClockEnable) {
|
||||
bool pulseFeedback = false;
|
||||
|
@ -118,7 +118,12 @@ uInt8 AudioChannel::phase1()
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the actual volume of a chaneel is the volume register multiplied by the
|
||||
// lowest of the pulse counter
|
||||
uInt8 AudioChannel::actualVolume()
|
||||
{
|
||||
return (myPulseCounter & 0x01) * myAudv;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,9 @@ class AudioChannel : public Serializable
|
|||
|
||||
void phase0();
|
||||
|
||||
uInt8 phase1();
|
||||
void phase1();
|
||||
|
||||
uInt8 actualVolume();
|
||||
|
||||
void audc(uInt8 value);
|
||||
|
||||
|
|
Loading…
Reference in New Issue