mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-23 03:32:32 +00:00
Merge pull request #118 from TomHarte/HighResolutionAtariAudio
Introduces a higher source sampling rate for Atari audio
This commit is contained in:
commit
4127350abe
@ -38,7 +38,7 @@ Machine::Machine() :
|
|||||||
void Machine::setup_output(float aspect_ratio) {
|
void Machine::setup_output(float aspect_ratio) {
|
||||||
bus_->tia_.reset(new TIA);
|
bus_->tia_.reset(new TIA);
|
||||||
bus_->speaker_.reset(new Speaker);
|
bus_->speaker_.reset(new Speaker);
|
||||||
bus_->speaker_->set_input_rate((float)(get_clock_rate() / 38.0));
|
bus_->speaker_->set_input_rate((float)(get_clock_rate() / (double)CPUTicksPerAudioTick));
|
||||||
bus_->tia_->get_crt()->set_delegate(this);
|
bus_->tia_->get_crt()->set_delegate(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,8 +149,8 @@ void Machine::crt_did_end_batch_of_frames(Outputs::CRT::CRT *crt, unsigned int n
|
|||||||
bus_->tia_->set_output_mode(TIA::OutputMode::PAL);
|
bus_->tia_->set_output_mode(TIA::OutputMode::PAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bus_->speaker_->set_input_rate((float)(clock_rate / 38.0));
|
bus_->speaker_->set_input_rate((float)(clock_rate / (double)CPUTicksPerAudioTick));
|
||||||
bus_->speaker_->set_high_frequency_cut_off((float)(clock_rate / (38.0 * 2.0)));
|
bus_->speaker_->set_high_frequency_cut_off((float)(clock_rate / ((double)CPUTicksPerAudioTick * 2.0)));
|
||||||
set_clock_rate(clock_rate);
|
set_clock_rate(clock_rate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,6 @@
|
|||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
|
||||||
const unsigned int number_of_upcoming_events = 6;
|
|
||||||
const unsigned int number_of_recorded_counters = 7;
|
|
||||||
|
|
||||||
class Machine:
|
class Machine:
|
||||||
public CRTMachine::Machine,
|
public CRTMachine::Machine,
|
||||||
public ConfigurationTarget::Machine,
|
public ConfigurationTarget::Machine,
|
||||||
|
@ -9,9 +9,10 @@
|
|||||||
#ifndef Atari2600_Bus_hpp
|
#ifndef Atari2600_Bus_hpp
|
||||||
#define Atari2600_Bus_hpp
|
#define Atari2600_Bus_hpp
|
||||||
|
|
||||||
|
#include "Atari2600.hpp"
|
||||||
#include "PIA.hpp"
|
#include "PIA.hpp"
|
||||||
#include "TIA.hpp"
|
|
||||||
#include "Speaker.hpp"
|
#include "Speaker.hpp"
|
||||||
|
#include "TIA.hpp"
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
|
||||||
@ -38,8 +39,8 @@ class Bus {
|
|||||||
// speaker backlog accumlation counter
|
// speaker backlog accumlation counter
|
||||||
unsigned int cycles_since_speaker_update_;
|
unsigned int cycles_since_speaker_update_;
|
||||||
inline void update_audio() {
|
inline void update_audio() {
|
||||||
unsigned int audio_cycles = cycles_since_speaker_update_ / 114;
|
unsigned int audio_cycles = cycles_since_speaker_update_ / (CPUTicksPerAudioTick * 3);
|
||||||
cycles_since_speaker_update_ %= 114;
|
cycles_since_speaker_update_ %= (CPUTicksPerAudioTick * 3);
|
||||||
speaker_->run_for_cycles(audio_cycles);
|
speaker_->run_for_cycles(audio_cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ void Atari2600::Speaker::get_samples(unsigned int number_of_samples, int16_t *ta
|
|||||||
target[c] = 0;
|
target[c] = 0;
|
||||||
for(int channel = 0; channel < 2; channel++) {
|
for(int channel = 0; channel < 2; channel++) {
|
||||||
divider_counter_[channel] ++;
|
divider_counter_[channel] ++;
|
||||||
|
int divider_value = divider_counter_[channel] / (38 / CPUTicksPerAudioTick);
|
||||||
int level = 0;
|
int level = 0;
|
||||||
switch(control_[channel]) {
|
switch(control_[channel]) {
|
||||||
case 0x0: case 0xb: // constant 1
|
case 0x0: case 0xb: // constant 1
|
||||||
@ -51,24 +52,24 @@ void Atari2600::Speaker::get_samples(unsigned int number_of_samples, int16_t *ta
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x4: case 0x5: // div2 tone
|
case 0x4: case 0x5: // div2 tone
|
||||||
level = (divider_counter_[channel] / (divider_[channel]+1))&1;
|
level = (divider_value / (divider_[channel]+1))&1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc: case 0xd: // div6 tone
|
case 0xc: case 0xd: // div6 tone
|
||||||
level = (divider_counter_[channel] / ((divider_[channel]+1)*3))&1;
|
level = (divider_value / ((divider_[channel]+1)*3))&1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x6: case 0xa: // div31 tone
|
case 0x6: case 0xa: // div31 tone
|
||||||
level = (divider_counter_[channel] / (divider_[channel]+1))%30 <= 18;
|
level = (divider_value / (divider_[channel]+1))%30 <= 18;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xe: // div93 tone
|
case 0xe: // div93 tone
|
||||||
level = (divider_counter_[channel] / ((divider_[channel]+1)*3))%30 <= 18;
|
level = (divider_value / ((divider_[channel]+1)*3))%30 <= 18;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1: // 4-bit poly
|
case 0x1: // 4-bit poly
|
||||||
level = poly4_counter_[channel]&1;
|
level = poly4_counter_[channel]&1;
|
||||||
if(divider_counter_[channel] == divider_[channel]+1) {
|
if(divider_value == divider_[channel]+1) {
|
||||||
divider_counter_[channel] = 0;
|
divider_counter_[channel] = 0;
|
||||||
advance_poly4(channel);
|
advance_poly4(channel);
|
||||||
}
|
}
|
||||||
@ -76,14 +77,14 @@ void Atari2600::Speaker::get_samples(unsigned int number_of_samples, int16_t *ta
|
|||||||
|
|
||||||
case 0x2: // 4-bit poly div31
|
case 0x2: // 4-bit poly div31
|
||||||
level = poly4_counter_[channel]&1;
|
level = poly4_counter_[channel]&1;
|
||||||
if(divider_counter_[channel]%(30*(divider_[channel]+1)) == 18) {
|
if(divider_value%(30*(divider_[channel]+1)) == 18) {
|
||||||
advance_poly4(channel);
|
advance_poly4(channel);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x3: // 5/4-bit poly
|
case 0x3: // 5/4-bit poly
|
||||||
level = output_state_[channel];
|
level = output_state_[channel];
|
||||||
if(divider_counter_[channel] == divider_[channel]+1) {
|
if(divider_value == divider_[channel]+1) {
|
||||||
if(poly5_counter_[channel]&1) {
|
if(poly5_counter_[channel]&1) {
|
||||||
output_state_[channel] = poly4_counter_[channel]&1;
|
output_state_[channel] = poly4_counter_[channel]&1;
|
||||||
advance_poly4(channel);
|
advance_poly4(channel);
|
||||||
@ -94,7 +95,7 @@ void Atari2600::Speaker::get_samples(unsigned int number_of_samples, int16_t *ta
|
|||||||
|
|
||||||
case 0x7: case 0x9: // 5-bit poly
|
case 0x7: case 0x9: // 5-bit poly
|
||||||
level = poly5_counter_[channel]&1;
|
level = poly5_counter_[channel]&1;
|
||||||
if(divider_counter_[channel] == divider_[channel]+1) {
|
if(divider_value == divider_[channel]+1) {
|
||||||
divider_counter_[channel] = 0;
|
divider_counter_[channel] = 0;
|
||||||
advance_poly5(channel);
|
advance_poly5(channel);
|
||||||
}
|
}
|
||||||
@ -102,7 +103,7 @@ void Atari2600::Speaker::get_samples(unsigned int number_of_samples, int16_t *ta
|
|||||||
|
|
||||||
case 0xf: // 5-bit poly div6
|
case 0xf: // 5-bit poly div6
|
||||||
level = poly5_counter_[channel]&1;
|
level = poly5_counter_[channel]&1;
|
||||||
if(divider_counter_[channel] == (divider_[channel]+1)*3) {
|
if(divider_value == (divider_[channel]+1)*3) {
|
||||||
divider_counter_[channel] = 0;
|
divider_counter_[channel] = 0;
|
||||||
advance_poly5(channel);
|
advance_poly5(channel);
|
||||||
}
|
}
|
||||||
@ -110,7 +111,7 @@ void Atari2600::Speaker::get_samples(unsigned int number_of_samples, int16_t *ta
|
|||||||
|
|
||||||
case 0x8: // 9-bit poly
|
case 0x8: // 9-bit poly
|
||||||
level = poly9_counter_[channel]&1;
|
level = poly9_counter_[channel]&1;
|
||||||
if(divider_counter_[channel] == divider_[channel]+1) {
|
if(divider_value == divider_[channel]+1) {
|
||||||
divider_counter_[channel] = 0;
|
divider_counter_[channel] = 0;
|
||||||
advance_poly9(channel);
|
advance_poly9(channel);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,10 @@
|
|||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
|
||||||
|
// This should be a divisor of 38; audio counters are updated every 38 cycles — though lesser dividers
|
||||||
|
// will give greater resolution to changes in audio state. 1, 2 and 19 are the only divisors of 38.
|
||||||
|
const int CPUTicksPerAudioTick = 2;
|
||||||
|
|
||||||
class Speaker: public ::Outputs::Filter<Speaker> {
|
class Speaker: public ::Outputs::Filter<Speaker> {
|
||||||
public:
|
public:
|
||||||
Speaker();
|
Speaker();
|
||||||
|
Loading…
Reference in New Issue
Block a user