X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fbackends%2Fdummy%2Fdummy_audiobackend.cc;h=94cd5f440aa157c9af92952f3fe041ef8fdc9b30;hb=14fcf86f037b9c66b2d7575e798fe07e4b2614d0;hp=0d3567f3e7130d5a2419d0e2f1d9282d3fcf2c09;hpb=afc1186759225f8ee6ced80578e3dc18224076ee;p=ardour.git diff --git a/libs/backends/dummy/dummy_audiobackend.cc b/libs/backends/dummy/dummy_audiobackend.cc index 0d3567f3e7..94cd5f440a 100644 --- a/libs/backends/dummy/dummy_audiobackend.cc +++ b/libs/backends/dummy/dummy_audiobackend.cc @@ -33,8 +33,9 @@ #include "dummy_midi_seq.h" #include "pbd/error.h" +#include "pbd/compose.h" #include "ardour/port_manager.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace ARDOUR; @@ -127,6 +128,7 @@ DummyAudioBackend::enumerate_devices () const _device_status.push_back (DeviceStatus (_("Sine Sweep Swell"), true)); _device_status.push_back (DeviceStatus (_("Square Sweep"), true)); _device_status.push_back (DeviceStatus (_("Square Sweep Swell"), true)); + _device_status.push_back (DeviceStatus (_("LTC"), true)); _device_status.push_back (DeviceStatus (_("Loopback"), true)); } return _device_status; @@ -182,7 +184,7 @@ DummyAudioBackend::available_output_channel_count (const std::string&) const bool DummyAudioBackend::can_change_sample_rate_when_running () const { - return true; + return false; } bool @@ -455,8 +457,6 @@ DummyAudioBackend::_start (bool /*for_latency_measurement*/) engine.sample_rate_change (_samplerate); engine.buffer_size_change (_samples_per_period); - _dsp_load_calc.set_max_time (_samplerate, _samples_per_period); - if (engine.reestablish_ports ()) { PBD::error << _("DummyAudioBackend: Could not re-establish ports.") << endmsg; stop (); @@ -638,7 +638,7 @@ DummyAudioBackend::my_name () const bool DummyAudioBackend::available () const { - return true; + return _running; } uint32_t @@ -809,7 +809,7 @@ DummyAudioBackend::unregister_port (PortEngine::PortHandle port_handle) return; } DummyPort* port = static_cast(port_handle); - PortIndex::iterator i = _ports.find (static_cast(port_handle)); + PortIndex::iterator i = std::find (_ports.begin(), _ports.end(), static_cast(port_handle)); if (i == _ports.end ()) { PBD::error << _("DummyBackend::unregister_port: Failed to find port") << endmsg; return; @@ -849,6 +849,8 @@ DummyAudioBackend::register_system_ports() gt = DummyAudioPort::SquareSweep; } else if (_device == _("Square Sweep Swell")) { gt = DummyAudioPort::SquareSweepSwell; + } else if (_device == _("LTC")) { + gt = DummyAudioPort::LTC; } else if (_device == _("Loopback")) { gt = DummyAudioPort::Loopback; } else if (_device == _("Demolition")) { @@ -1080,7 +1082,7 @@ DummyAudioBackend::get_connections (PortEngine::PortHandle port, std::vectornext_period(); } - if (engine.process_callback (_samples_per_period)) { + if (engine.process_callback (samples_per_period)) { return 0; } - _processed_samples += _samples_per_period; + _processed_samples += samples_per_period; if (_device == _("Loopback") && _midi_mode != MidiToAudio) { int opn = 0; int opc = _system_outputs.size(); for (std::vector::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); + (*it)->fill_wavetable ((const float*)op->get_buffer (samples_per_period), samples_per_period); } } @@ -1346,11 +1349,12 @@ DummyAudioBackend::main_process_thread () for (std::vector::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++opn) { DummyMidiPort* op = _system_midi_out[(opn % opc)]; op->get_buffer(0); // mix-down - (*it)->midi_to_wavetable (op->const_buffer(), _samples_per_period); + (*it)->midi_to_wavetable (op->const_buffer(), samples_per_period); } } if (!_freewheel) { + _dsp_load_calc.set_max_time (_samplerate, samples_per_period); _dsp_load_calc.set_start_timestamp_us (clock1); _dsp_load_calc.set_stop_timestamp_us (_x_get_monotonic_usec()); _dsp_load = _dsp_load_calc.get_dsp_load_unbound (); @@ -1655,21 +1659,27 @@ DummyAudioPort::DummyAudioPort (DummyAudioBackend &b, const std::string& name, P , _gen_count2 (0) , _pass (false) , _rn1 (0) + , _ltc (0) + , _ltcbuf (0) { memset (_buffer, 0, sizeof (_buffer)); } DummyAudioPort::~DummyAudioPort () { free(_wavetable); + ltc_encoder_free (_ltc); + delete _ltcbuf; _wavetable = 0; + _ltc = 0; + _ltcbuf = 0; } static std::string format_hz (float freq) { std::stringstream ss; if (freq >= 10000) { - ss << std::setprecision (1) << std::fixed << freq / 1000 << "KHz"; + ss << std::setprecision (1) << std::fixed << freq / 1000 << "kHz"; } else if (freq >= 1000) { - ss << std::setprecision (2) << std::fixed << freq / 1000 << "KHz"; + ss << std::setprecision (2) << std::fixed << freq / 1000 << "kHz"; } else { ss << std::setprecision (1) << std::fixed << freq << "Hz"; } @@ -1793,6 +1803,44 @@ DummyAudioPort::setup_generator (GeneratorType const g, float const samplerate, } } break; + case LTC: + switch (c % 4) { + case 0: + _ltc = ltc_encoder_create (samplerate, 25, LTC_TV_625_50, 0); + name = "LTC25"; + break; + case 1: + _ltc = ltc_encoder_create (samplerate, 30, LTC_TV_1125_60, 0); + name = "LTC30"; + break; + case 2: + _ltc = ltc_encoder_create (samplerate, 30001.f / 1001.f, LTC_TV_525_60, 0); + name = "LTC29df"; + break; + case 3: + _ltc = ltc_encoder_create (samplerate, 24, LTC_TV_FILM_24, 0); + name = "LTC24"; + break; + } + _ltc_spd = 1.0; + _ltc_rand = floor((float)c / 4) * .001f; + if (c < 4) { + name += " (locked)"; + } else { + name += " (varspd)"; + } + SMPTETimecode tc; + tc.years = 0; + tc.months = 0; + tc.days = 0; + tc.hours = (3 * (c / 4)) % 24; // XXX + tc.mins = 0; + tc.secs = 0; + tc.frame = 0; + ltc_encoder_set_timecode (_ltc, &tc); + name += string_compose ("@%1h", (int)tc.hours); + _ltcbuf = new RingBuffer (std::max (DummyAudioBackend::max_buffer_size() * 2.f, samplerate)); + break; case Loopback: _wavetable = (Sample*) malloc (DummyAudioBackend::max_buffer_size() * sizeof(Sample)); break; @@ -1854,19 +1902,19 @@ float DummyAudioPort::grandf () /* inspired by jack-demolition by Steve Harris */ static const float _demolition[] = { - 0.0f, /* special case - 0dbFS white noise */ - 0.0f, /* zero, may cause denomrals following a signal */ - 0.73 / 1e45, /* very small - should be denormal when floated */ - 3.7f, /* arbitrary number > 0dBFS */ - -4.3f, /* arbitrary negative number > 0dBFS */ - 4294967395.0f, /* 2^16 + 100 */ + 0.0f, /* special case - 0dbFS white noise */ + 0.0f, /* zero, may cause denomrals following a signal */ + 0.73 / 1e45, /* very small - should be denormal when floated */ + 3.7f, /* arbitrary number > 0dBFS */ + -4.3f, /* arbitrary negative number > 0dBFS */ + 4294967395.0f, /* 2^16 + 100 */ -4294967395.0f, - HUGE, /* Big, non-inf number */ - INFINITY, /* +inf */ - -INFINITY, /* -inf */ - -NAN, /* -nan */ - NAN, /* nan */ - 0.0f, /* some silence to check for recovery */ + 3.402823466e+38F, /* HUGE, HUGEVALF, non-inf number */ + INFINITY, /* +inf */ + -INFINITY, /* -inf */ + -NAN, /* -nan */ + NAN, /* nan */ + 0.0f, /* some silence to check for recovery */ }; void DummyAudioPort::generate (const pframes_t n_samples) @@ -1939,7 +1987,8 @@ void DummyAudioPort::generate (const pframes_t n_samples) } break; case Loopback: - _gen_period = n_samples; // XXX DummyBackend::_samples_per_period; + memcpy((void*)_buffer, (void*)_wavetable, n_samples * sizeof(Sample)); + break; case SineWave: case SineWaveOctaves: case SineSweep: @@ -1996,6 +2045,28 @@ void DummyAudioPort::generate (const pframes_t n_samples) _buffer[i] = _b0 + _b1 + _b2 + white * 0.1848f; } break; + case LTC: + while (_ltcbuf->read_space () < n_samples) { + // we should pre-allocate (or add a zero-copy libltc API), whatever. + ltcsnd_sample_t* enc_buf = (ltcsnd_sample_t*) malloc (ltc_encoder_get_buffersize (_ltc) * sizeof (ltcsnd_sample_t)); + for (int byteCnt = 0; byteCnt < 10; byteCnt++) { + if (_ltc_rand != 0.f) { + _ltc_spd += randf () * _ltc_rand; + _ltc_spd = std::min (1.5f, std::max (0.5f, _ltc_spd)); + } + ltc_encoder_encode_byte (_ltc, byteCnt, _ltc_spd); + const int len = ltc_encoder_get_buffer (_ltc, enc_buf); + for (int i = 0; i < len; ++i) { + const float v1 = enc_buf[i] - 128; + Sample v = v1 * 0.002; + _ltcbuf->write (&v, 1); + } + } + ltc_encoder_inc_timecode (_ltc); + free (enc_buf); + } + _ltcbuf->read (_buffer, n_samples); + break; } _gen_cycle = true; } @@ -2134,7 +2205,7 @@ void* DummyMidiPort::get_buffer (pframes_t n_samples) _buffer.push_back (boost::shared_ptr(new DummyMidiEvent (**it))); } } - std::sort (_buffer.begin (), _buffer.end (), MidiEventSorter()); + std::stable_sort (_buffer.begin (), _buffer.end (), MidiEventSorter()); } else if (is_output () && is_physical () && is_terminal()) { if (!_gen_cycle) { midi_generate(n_samples);