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:
parent
726c98446a
commit
4cd0aa3416
@ -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)
|
||||
|
@ -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 */,
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user