mirror of
https://github.com/TomHarte/CLK.git
synced 2025-03-25 06:30:38 +00:00
Made a very basic stab at a couple of the tone generators, added straight-through path for the speaker when input rate exactly equals output rate.
This commit is contained in:
parent
40c4544fb7
commit
1e0fcbbee8
@ -802,6 +802,7 @@ void Atari2600::Speaker::set_volume(int channel, uint8_t volume)
|
||||
void Atari2600::Speaker::set_divider(int channel, uint8_t divider)
|
||||
{
|
||||
_divider[channel] = divider & 0x1f;
|
||||
_divider_counter[channel] = 0;
|
||||
}
|
||||
|
||||
void Atari2600::Speaker::set_control(int channel, uint8_t control)
|
||||
@ -816,12 +817,21 @@ void Atari2600::Speaker::get_samples(unsigned int number_of_samples, int16_t *ta
|
||||
target[c] = 0;
|
||||
for(int channel = 0; channel < 2; channel++)
|
||||
{
|
||||
if(!_control[channel])
|
||||
{
|
||||
target[c] += _volume[channel] * 1024;
|
||||
}
|
||||
else
|
||||
switch(_control[channel])
|
||||
{
|
||||
case 0x0: case 0xb:
|
||||
target[c] += _volume[channel] * 1024;
|
||||
break;
|
||||
|
||||
case 0x4: case 0x5:
|
||||
_divider_counter[channel] ++;
|
||||
target[c] += _volume[channel] * 1024 * ((_divider_counter[channel] / (_divider[channel]+1))&1);
|
||||
break;
|
||||
|
||||
case 0xc: case 0xd:
|
||||
_divider_counter[channel] ++;
|
||||
target[c] += _volume[channel] * 1024 * ((_divider_counter[channel] / ((_divider[channel]+1)*3))&1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,9 @@ class Speaker: public ::Outputs::Filter<Speaker> {
|
||||
uint8_t _volume[2];
|
||||
uint8_t _divider[2];
|
||||
uint8_t _control[2];
|
||||
int _shift_counters[2];
|
||||
int _shift_counter[2];
|
||||
int _divider_counter[2];
|
||||
int _output_state[2];
|
||||
};
|
||||
|
||||
class Machine: public CPU6502::Processor<Machine>, public CRTMachine::Machine {
|
||||
|
@ -88,20 +88,16 @@ template <class T> class Filter: public Speaker {
|
||||
{
|
||||
if(_coefficients_are_dirty) update_filter_coefficients();
|
||||
|
||||
// TODO: what if output rate is greater than input rate?
|
||||
|
||||
// fill up as much of the input buffer as possible
|
||||
while(input_cycles)
|
||||
// if input and output rates exactly match, just accumulate results and pass on
|
||||
if(_input_cycles_per_second == _output_cycles_per_second)
|
||||
{
|
||||
unsigned int cycles_to_read = (unsigned int)std::min((int)input_cycles, _number_of_taps - _input_buffer_depth);
|
||||
static_cast<T *>(this)->get_samples(cycles_to_read, &_input_buffer.get()[_input_buffer_depth]);
|
||||
input_cycles -= cycles_to_read;
|
||||
_input_buffer_depth += cycles_to_read;
|
||||
|
||||
if(_input_buffer_depth == _number_of_taps)
|
||||
while(input_cycles)
|
||||
{
|
||||
_buffer_in_progress.get()[_buffer_in_progress_pointer] = _filter->apply(_input_buffer.get());
|
||||
_buffer_in_progress_pointer++;
|
||||
unsigned int cycles_to_read = (unsigned int)(_buffer_size - _buffer_in_progress_pointer);
|
||||
if(cycles_to_read > input_cycles) cycles_to_read = input_cycles;
|
||||
|
||||
static_cast<T *>(this)->get_samples(cycles_to_read, &_buffer_in_progress.get()[_buffer_in_progress_pointer]);
|
||||
_buffer_in_progress_pointer += cycles_to_read;
|
||||
|
||||
// announce to delegate if full
|
||||
if(_buffer_in_progress_pointer == _buffer_size)
|
||||
@ -113,24 +109,60 @@ template <class T> class Filter: public Speaker {
|
||||
}
|
||||
}
|
||||
|
||||
// If the next loop around is going to reuse some of the samples just collected, use a memmove to
|
||||
// preserve them in the correct locations (TODO: use a longer buffer to fix that) and don't skip
|
||||
// anything. Otherwise skip as required to get to the next sample batch and don't expect to reuse.
|
||||
uint64_t steps = _stepper->step();
|
||||
if(steps < _number_of_taps)
|
||||
input_cycles -= cycles_to_read;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if the output rate is less than the input rate, use the filter
|
||||
if(_input_cycles_per_second > _output_cycles_per_second)
|
||||
{
|
||||
while(input_cycles)
|
||||
{
|
||||
unsigned int cycles_to_read = (unsigned int)std::min((int)input_cycles, _number_of_taps - _input_buffer_depth);
|
||||
static_cast<T *>(this)->get_samples(cycles_to_read, &_input_buffer.get()[_input_buffer_depth]);
|
||||
input_cycles -= cycles_to_read;
|
||||
_input_buffer_depth += cycles_to_read;
|
||||
|
||||
if(_input_buffer_depth == _number_of_taps)
|
||||
{
|
||||
int16_t *input_buffer = _input_buffer.get();
|
||||
memmove(input_buffer, &input_buffer[steps], sizeof(int16_t) * ((size_t)_number_of_taps - (size_t)steps));
|
||||
_input_buffer_depth -= steps;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(steps > _number_of_taps)
|
||||
static_cast<T *>(this)->skip_samples((unsigned int)steps - (unsigned int)_number_of_taps);
|
||||
_input_buffer_depth = 0;
|
||||
_buffer_in_progress.get()[_buffer_in_progress_pointer] = _filter->apply(_input_buffer.get());
|
||||
_buffer_in_progress_pointer++;
|
||||
|
||||
// announce to delegate if full
|
||||
if(_buffer_in_progress_pointer == _buffer_size)
|
||||
{
|
||||
_buffer_in_progress_pointer = 0;
|
||||
if(_delegate)
|
||||
{
|
||||
_delegate->speaker_did_complete_samples(this, _buffer_in_progress.get(), _buffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
// If the next loop around is going to reuse some of the samples just collected, use a memmove to
|
||||
// preserve them in the correct locations (TODO: use a longer buffer to fix that) and don't skip
|
||||
// anything. Otherwise skip as required to get to the next sample batch and don't expect to reuse.
|
||||
uint64_t steps = _stepper->step();
|
||||
if(steps < _number_of_taps)
|
||||
{
|
||||
int16_t *input_buffer = _input_buffer.get();
|
||||
memmove(input_buffer, &input_buffer[steps], sizeof(int16_t) * ((size_t)_number_of_taps - (size_t)steps));
|
||||
_input_buffer_depth -= steps;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(steps > _number_of_taps)
|
||||
static_cast<T *>(this)->skip_samples((unsigned int)steps - (unsigned int)_number_of_taps);
|
||||
_input_buffer_depth = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: input rate is less than output rate
|
||||
}
|
||||
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user