diff options
author | Robin Gareus <robin@gareus.org> | 2014-10-11 14:47:35 +0200 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2014-10-11 14:47:35 +0200 |
commit | 8525a0b258a02bec0628958a39c8cebeedded9a7 (patch) | |
tree | ee8e66c9f819dda27f6621ec31bf10f0ca736b00 | |
parent | e19e6dc73a8dbc93a93354c1d97c39d0f4fa0f0e (diff) |
add a Dummy Backend Loopback mode:
-rw-r--r-- | libs/backends/dummy/dummy_audiobackend.cc | 61 | ||||
-rw-r--r-- | libs/backends/dummy/dummy_audiobackend.h | 6 |
2 files changed, 63 insertions, 4 deletions
diff --git a/libs/backends/dummy/dummy_audiobackend.cc b/libs/backends/dummy/dummy_audiobackend.cc index a9f5145b1c..f2455702b5 100644 --- a/libs/backends/dummy/dummy_audiobackend.cc +++ b/libs/backends/dummy/dummy_audiobackend.cc @@ -93,6 +93,7 @@ DummyAudioBackend::enumerate_devices () const _device_status.push_back (DeviceStatus (_("Pink Noise (low CPU)"), true)); _device_status.push_back (DeviceStatus (_("Sine Sweep"), true)); _device_status.push_back (DeviceStatus (_("Sine Sweep Swell"), true)); + _device_status.push_back (DeviceStatus (_("Loopback"), true)); } return _device_status; } @@ -179,6 +180,30 @@ DummyAudioBackend::set_buffer_size (uint32_t bs) return -1; } _samples_per_period = bs; + + /* update port latencies + * with 'Loopback' there is exactly once cycle latency, + * divide it between In + Out; + */ + const size_t l_in = _samples_per_period * .25; + const size_t l_out = _samples_per_period - l_in; + LatencyRange lr; + lr.min = lr.max = l_in + _systemic_input_latency; + for (std::vector<DummyAudioPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) { + set_latency_range (*it, false, lr); + } + for (std::vector<DummyMidiPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) { + set_latency_range (*it, false, lr); + } + + lr.min = lr.max = l_out + _systemic_output_latency; + for (std::vector<DummyAudioPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) { + set_latency_range (*it, true, lr); + } + for (std::vector<DummyMidiPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) { + set_latency_range (*it, true, lr); + } + engine.buffer_size_change (bs); return 0; } @@ -335,7 +360,9 @@ DummyAudioBackend::_start (bool /*for_latency_measurement*/) PBD::info << _("DummyAudioBackend: port '") << (*it)->name () << "' exists." << endmsg; } _system_inputs.clear(); + _system_outputs.clear(); _system_midi_in.clear(); + _system_midi_out.clear(); _ports.clear(); } @@ -688,6 +715,8 @@ DummyAudioBackend::register_system_ports() gt = DummyAudioPort::SineSweep; } else if (_device == _("Sine Sweep Swell")) { gt = DummyAudioPort::SineSweepSwell; + } else if (_device == _("Loopback")) { + gt = DummyAudioPort::Loopback; } else { gt = DummyAudioPort::Silence; } @@ -697,8 +726,12 @@ DummyAudioBackend::register_system_ports() const int m_ins = _n_midi_inputs; const int m_out = _n_midi_outputs; + /* with 'Loopback' there is exactly once cycle latency, divide it between In + Out; */ + const size_t l_in = _samples_per_period * .25; + const size_t l_out = _samples_per_period - l_in; + /* audio ports */ - lr.min = lr.max = _samples_per_period + _systemic_input_latency; + lr.min = lr.max = l_in + _systemic_input_latency; for (int i = 1; i <= a_ins; ++i) { char tmp[64]; snprintf(tmp, sizeof(tmp), "system:capture_%d", i); @@ -709,17 +742,18 @@ DummyAudioBackend::register_system_ports() static_cast<DummyAudioPort*>(p)->setup_generator (gt, _samplerate); } - lr.min = lr.max = _samples_per_period + _systemic_output_latency; + lr.min = lr.max = l_out + _systemic_output_latency; for (int i = 1; i <= a_out; ++i) { char tmp[64]; snprintf(tmp, sizeof(tmp), "system:playback_%d", i); PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal)); if (!p) return -1; set_latency_range (p, true, lr); + _system_outputs.push_back (static_cast<DummyAudioPort*>(p)); } /* midi ports */ - lr.min = lr.max = _samples_per_period + _systemic_input_latency; + lr.min = lr.max = l_in + _systemic_input_latency; for (int i = 1; i <= m_ins; ++i) { char tmp[64]; snprintf(tmp, sizeof(tmp), "system:midi_capture_%d", i); @@ -732,13 +766,14 @@ DummyAudioBackend::register_system_ports() } } - lr.min = lr.max = _samples_per_period + _systemic_output_latency; + lr.min = lr.max = l_out + _systemic_output_latency; for (int i = 1; i <= m_out; ++i) { char tmp[64]; snprintf(tmp, sizeof(tmp), "system:midi_playback_%d", i); PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal)); if (!p) return -1; set_latency_range (p, true, lr); + _system_midi_out.push_back (static_cast<DummyMidiPort*>(p)); } return 0; } @@ -748,7 +783,9 @@ DummyAudioBackend::unregister_ports (bool system_only) { size_t i = 0; _system_inputs.clear(); + _system_outputs.clear(); _system_midi_in.clear(); + _system_midi_out.clear(); while (i < _ports.size ()) { DummyPort* port = _ports[i]; if (! system_only || (port->is_physical () && port->is_terminal ())) { @@ -1096,6 +1133,17 @@ DummyAudioBackend::main_process_thread () return 0; } _processed_samples += _samples_per_period; + + if (_device == _("Loopback")) { + int opn = 0; + int opc = _system_outputs.size(); + for (std::vector<DummyAudioPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++opn) { + DummyAudioPort* op = _system_outputs[(opn % opc)]; + (*it)->fill_wavetable ((const float*)op->get_buffer (_samples_per_period), _samples_per_period); + } + + } + if (!_freewheeling) { clock2 = g_get_monotonic_time(); const int64_t elapsed_time = clock2 - clock1; @@ -1446,6 +1494,9 @@ void DummyAudioPort::setup_generator (GeneratorType const g, float const sampler } } break; + case Loopback: + _wavetable = (Sample*) malloc (DummyAudioBackend::max_buffer_size() * sizeof(Sample)); + break; } } @@ -1517,6 +1568,8 @@ void DummyAudioPort::generate (const pframes_t n_samples) } } break; + case Loopback: + _gen_period = n_samples; // XXX DummyBackend::_samples_per_period; case SineWave: case SineSweep: assert(_wavetable && _gen_period > 0); diff --git a/libs/backends/dummy/dummy_audiobackend.h b/libs/backends/dummy/dummy_audiobackend.h index 3d389b7701..392ec7b3c2 100644 --- a/libs/backends/dummy/dummy_audiobackend.h +++ b/libs/backends/dummy/dummy_audiobackend.h @@ -155,8 +155,10 @@ class DummyAudioPort : public DummyPort { KronekerDelta, SineSweep, SineSweepSwell, + Loopback, }; void setup_generator (GeneratorType const, float const); + void fill_wavetable (const float* d, size_t n_samples) { assert(_wavetable != 0); memcpy(_wavetable, d, n_samples * sizeof(float)); } private: Sample _buffer[8192]; @@ -354,6 +356,8 @@ class DummyAudioBackend : public AudioBackend { void* main_process_thread (); + static size_t max_buffer_size() {return _max_buffer_size;} + private: std::string _instance_name; static std::vector<std::string> _midi_options; @@ -402,7 +406,9 @@ class DummyAudioBackend : public AudioBackend { void unregister_ports (bool system_only = false); std::vector<DummyAudioPort *> _system_inputs; + std::vector<DummyAudioPort *> _system_outputs; std::vector<DummyMidiPort *> _system_midi_in; + std::vector<DummyMidiPort *> _system_midi_out; std::vector<DummyPort *> _ports; struct PortConnectData { |