X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fbackends%2Fdummy%2Fdummy_audiobackend.cc;h=692cdc3e08fde2625d81fc490fe90bf6d443a25c;hb=8c61c7f14a8136b877368be7d20fe4eaf8e5bf88;hp=28d73d462ed16f214676a62f8341b110852dc56c;hpb=a76607486c5d37df1207d454483ebd8a81ad7ffd;p=ardour.git diff --git a/libs/backends/dummy/dummy_audiobackend.cc b/libs/backends/dummy/dummy_audiobackend.cc index 28d73d462e..692cdc3e08 100644 --- a/libs/backends/dummy/dummy_audiobackend.cc +++ b/libs/backends/dummy/dummy_audiobackend.cc @@ -33,6 +33,7 @@ #include "dummy_midi_seq.h" #include "pbd/error.h" +#include "pbd/compose.h" #include "ardour/port_manager.h" #include "pbd/i18n.h" @@ -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 @@ -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,13 +1659,19 @@ 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) { @@ -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; @@ -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);