mirror of
https://github.com/TomHarte/CLK.git
synced 2024-08-21 04:29:34 +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)
|
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)
|
void Speaker::skip_samples(unsigned int number_of_samples)
|
||||||
|
@ -309,6 +309,7 @@
|
|||||||
4BBF99171C8FBA6F0075DAFB /* Shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99101C8FBA6F0075DAFB /* Shader.cpp */; };
|
4BBF99171C8FBA6F0075DAFB /* Shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99101C8FBA6F0075DAFB /* Shader.cpp */; };
|
||||||
4BBF99181C8FBA6F0075DAFB /* TextureTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99121C8FBA6F0075DAFB /* TextureTarget.cpp */; };
|
4BBF99181C8FBA6F0075DAFB /* TextureTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBF99121C8FBA6F0075DAFB /* TextureTarget.cpp */; };
|
||||||
4BC76E691C98E31700E6EF73 /* FIRFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC76E671C98E31700E6EF73 /* FIRFilter.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 */; };
|
4BCB70B41C947DDC005B1712 /* plus1.rom in Resources */ = {isa = PBXBuildFile; fileRef = 4BCB70B31C947DDC005B1712 /* plus1.rom */; };
|
||||||
4BE5F85E1C3E1C2500C43F01 /* basic.rom in Resources */ = {isa = PBXBuildFile; fileRef = 4BE5F85C1C3E1C2500C43F01 /* basic.rom */; };
|
4BE5F85E1C3E1C2500C43F01 /* basic.rom in Resources */ = {isa = PBXBuildFile; fileRef = 4BE5F85C1C3E1C2500C43F01 /* basic.rom */; };
|
||||||
4BE5F85F1C3E1C2500C43F01 /* os.rom in Resources */ = {isa = PBXBuildFile; fileRef = 4BE5F85D1C3E1C2500C43F01 /* os.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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
4BCB70B31C947DDC005B1712 /* plus1.rom */ = {isa = PBXFileReference; lastKnownFileType = file; path = plus1.rom; sourceTree = "<group>"; };
|
||||||
4BE5F85C1C3E1C2500C43F01 /* basic.rom */ = {isa = PBXFileReference; lastKnownFileType = file; path = basic.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>"; };
|
4BE5F85D1C3E1C2500C43F01 /* os.rom */ = {isa = PBXFileReference; lastKnownFileType = file; path = os.rom; sourceTree = "<group>"; };
|
||||||
@ -679,6 +681,7 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
4BC76E6B1C98F43700E6EF73 /* Accelerate.framework in Frameworks */,
|
||||||
4B69FB461C4D950F00B5F0AA /* libz.tbd in Frameworks */,
|
4B69FB461C4D950F00B5F0AA /* libz.tbd in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@ -1115,6 +1118,7 @@
|
|||||||
4BB73E951B587A5100552FC2 = {
|
4BB73E951B587A5100552FC2 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
4BC76E6A1C98F43700E6EF73 /* Accelerate.framework */,
|
||||||
4BB73EA01B587A5100552FC2 /* Clock Signal */,
|
4BB73EA01B587A5100552FC2 /* Clock Signal */,
|
||||||
4BB73EB51B587A5100552FC2 /* Clock SignalTests */,
|
4BB73EB51B587A5100552FC2 /* Clock SignalTests */,
|
||||||
4BB73EC01B587A5100552FC2 /* Clock SignalUITests */,
|
4BB73EC01B587A5100552FC2 /* Clock SignalUITests */,
|
||||||
|
@ -76,12 +76,19 @@ template <class T> class Filter: public Speaker {
|
|||||||
{
|
{
|
||||||
if(_coefficients_are_dirty) update_filter_coefficients();
|
if(_coefficients_are_dirty) update_filter_coefficients();
|
||||||
|
|
||||||
// point sample for now, as a temporary measure
|
// TODO: what if output rate is greater than input rate?
|
||||||
input_cycles += _input_cycles_carry;
|
|
||||||
while(input_cycles > 0)
|
// fill up as much of the input buffer as possible
|
||||||
|
while(input_cycles)
|
||||||
{
|
{
|
||||||
// get a sample for the current location
|
unsigned int cycles_to_read = (unsigned int)std::min(input_cycles, _number_of_taps - _input_buffer_depth);
|
||||||
static_cast<T *>(this)->get_samples(1, &_buffer_in_progress.get()[_buffer_in_progress_pointer]);
|
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++;
|
_buffer_in_progress_pointer++;
|
||||||
|
|
||||||
// announce to delegate if full
|
// 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();
|
uint64_t steps = _stepper->step();
|
||||||
if(steps > 1)
|
int16_t *input_buffer = _input_buffer.get();
|
||||||
static_cast<T *>(this)->skip_samples((unsigned int)(steps-1));
|
memmove(input_buffer, &input_buffer[steps], sizeof(int16_t) * ((size_t)_number_of_taps - (size_t)steps));
|
||||||
input_cycles -= steps;
|
_input_buffer_depth -= steps;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_input_cycles_carry = input_cycles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Filter() {} // _periodic_cycles(0), _periodic_start(0)
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<SignalProcessing::Stepper> _stepper;
|
std::unique_ptr<SignalProcessing::Stepper> _stepper;
|
||||||
std::unique_ptr<SignalProcessing::FIRFilter> _filter;
|
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()
|
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));
|
_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));
|
_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