1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 23:52:26 +00:00

Completed FIR filter based audio output.

This commit is contained in:
Thomas Harte 2016-03-15 23:37:35 -04:00
parent 726c98446a
commit 4cd0aa3416
3 changed files with 38 additions and 28 deletions

View File

@ -786,15 +786,12 @@ void Machine::set_key_state(Key key, bool isPressed)
void Speaker::get_samples(unsigned int number_of_samples, int16_t *target)
{
if(!_is_enabled)
while(number_of_samples--)
{
*target = 0;
*target = _is_enabled ? _output_level : 0;
target++;
skip_samples(1);
}
else
{
*target = _output_level;
}
skip_samples(number_of_samples);
}
void Speaker::skip_samples(unsigned int number_of_samples)

View File

@ -309,6 +309,7 @@
4BBF99171C8FBA6F0075DAFB /* Shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99101C8FBA6F0075DAFB /* Shader.cpp */; };
4BBF99181C8FBA6F0075DAFB /* TextureTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99121C8FBA6F0075DAFB /* TextureTarget.cpp */; };
4BC76E691C98E31700E6EF73 /* FIRFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC76E671C98E31700E6EF73 /* FIRFilter.cpp */; };
4BC76E6B1C98F43700E6EF73 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BC76E6A1C98F43700E6EF73 /* Accelerate.framework */; };
4BCB70B41C947DDC005B1712 /* plus1.rom in Resources */ = {isa = PBXBuildFile; fileRef = 4BCB70B31C947DDC005B1712 /* plus1.rom */; };
4BE5F85E1C3E1C2500C43F01 /* basic.rom in Resources */ = {isa = PBXBuildFile; fileRef = 4BE5F85C1C3E1C2500C43F01 /* basic.rom */; };
4BE5F85F1C3E1C2500C43F01 /* os.rom in Resources */ = {isa = PBXBuildFile; fileRef = 4BE5F85D1C3E1C2500C43F01 /* os.rom */; };
@ -669,6 +670,7 @@
4BBF99191C8FC2750075DAFB /* CRTTypes.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CRTTypes.hpp; sourceTree = "<group>"; };
4BC76E671C98E31700E6EF73 /* FIRFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FIRFilter.cpp; sourceTree = "<group>"; };
4BC76E681C98E31700E6EF73 /* FIRFilter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FIRFilter.hpp; sourceTree = "<group>"; };
4BC76E6A1C98F43700E6EF73 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
4BCB70B31C947DDC005B1712 /* plus1.rom */ = {isa = PBXFileReference; lastKnownFileType = file; path = plus1.rom; sourceTree = "<group>"; };
4BE5F85C1C3E1C2500C43F01 /* basic.rom */ = {isa = PBXFileReference; lastKnownFileType = file; path = basic.rom; sourceTree = "<group>"; };
4BE5F85D1C3E1C2500C43F01 /* os.rom */ = {isa = PBXFileReference; lastKnownFileType = file; path = os.rom; sourceTree = "<group>"; };
@ -679,6 +681,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4BC76E6B1C98F43700E6EF73 /* Accelerate.framework in Frameworks */,
4B69FB461C4D950F00B5F0AA /* libz.tbd in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -1115,6 +1118,7 @@
4BB73E951B587A5100552FC2 = {
isa = PBXGroup;
children = (
4BC76E6A1C98F43700E6EF73 /* Accelerate.framework */,
4BB73EA01B587A5100552FC2 /* Clock Signal */,
4BB73EB51B587A5100552FC2 /* Clock SignalTests */,
4BB73EC01B587A5100552FC2 /* Clock SignalUITests */,

View File

@ -76,12 +76,19 @@ template <class T> class Filter: public Speaker {
{
if(_coefficients_are_dirty) update_filter_coefficients();
// point sample for now, as a temporary measure
input_cycles += _input_cycles_carry;
while(input_cycles > 0)
// TODO: what if output rate is greater than input rate?
// fill up as much of the input buffer as possible
while(input_cycles)
{
// get a sample for the current location
static_cast<T *>(this)->get_samples(1, &_buffer_in_progress.get()[_buffer_in_progress_pointer]);
unsigned int cycles_to_read = (unsigned int)std::min(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)
{
_buffer_in_progress.get()[_buffer_in_progress_pointer] = _filter->apply(_input_buffer.get());
_buffer_in_progress_pointer++;
// announce to delegate if full
@ -94,21 +101,20 @@ template <class T> class Filter: public Speaker {
}
}
// determine how many source samples to step
uint64_t steps = _stepper->step();
if(steps > 1)
static_cast<T *>(this)->skip_samples((unsigned int)(steps-1));
input_cycles -= steps;
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;
}
}
_input_cycles_carry = input_cycles;
}
Filter() {} // _periodic_cycles(0), _periodic_start(0)
private:
std::unique_ptr<SignalProcessing::Stepper> _stepper;
std::unique_ptr<SignalProcessing::FIRFilter> _filter;
int _input_cycles_carry;
std::unique_ptr<int16_t> _input_buffer;
int _input_buffer_depth;
void update_filter_coefficients()
{
@ -117,6 +123,9 @@ template <class T> class Filter: public Speaker {
_stepper = std::unique_ptr<SignalProcessing::Stepper>(new SignalProcessing::Stepper((uint64_t)_input_cycles_per_second, (uint64_t)_output_cycles_per_second));
_filter = std::unique_ptr<SignalProcessing::FIRFilter>(new SignalProcessing::FIRFilter((unsigned int)_number_of_taps, (unsigned int)_input_cycles_per_second, 0.0, (float)_output_cycles_per_second / 2.0f, SignalProcessing::FIRFilter::DefaultAttenuation));
_input_buffer = std::unique_ptr<int16_t>(new int16_t[_number_of_taps]);
_input_buffer_depth = 0;
}
};