+ const uint32_t g_p2i = rint(g_p2);
+ _wavetable = (Sample*) malloc (_gen_period * sizeof(Sample));
+ for (uint32_t i = 0 ; i < g_p2i; ++i) {
+#ifdef LINEAR_SWEEP
+ const double phase = i * (a + b * i);
+#else
+ const double phase = a * exp (b * i) - a;
+#endif
+ _wavetable[i] = (float)sin (2. * M_PI * (phase - floor (phase)));
+ }
+ for (uint32_t i = g_p2i; i < _gen_period; ++i) {
+ const uint32_t j = _gen_period - i;
+#ifdef LINEAR_SWEEP
+ const double phase = j * (a + b * j);
+#else
+ const double phase = a * exp (b * j) - a;
+#endif
+ _wavetable[i] = -(float)sin (2. * M_PI * (phase - floor (phase)));
+ }
+ if (_gen_type == SquareSweep) {
+ for (uint32_t i = 0 ; i < _gen_period; ++i) {
+ _wavetable[i] = _wavetable[i] < 0 ? -.40709f : .40709f;
+ }
+ }
+ else if (_gen_type == SquareSweepSwell) {
+ for (uint32_t i = 0 ; i < _gen_period; ++i) {
+ _wavetable[i] = _wavetable[i] < 0 ? -1 : 1;
+ }
+ }
+ }
+ 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<Sample> (std::max (DummyAudioBackend::max_buffer_size() * 2.f, samplerate));
+ break;
+ case Loopback:
+ _wavetable = (Sample*) malloc (DummyAudioBackend::max_buffer_size() * sizeof(Sample));
+ break;
+ }
+ return name;
+}
+
+void DummyAudioPort::midi_to_wavetable (DummyMidiBuffer const * const src, size_t n_samples)
+{
+ memset(_wavetable, 0, n_samples * sizeof(float));
+ /* generate an audio spike for every midi message
+ * to verify layency-compensation alignment
+ * (here: midi-out playback-latency + audio-in capture-latency)
+ */
+ for (DummyMidiBuffer::const_iterator it = src->begin (); it != src->end (); ++it) {
+ const pframes_t t = (*it)->timestamp();
+ assert(t < n_samples);
+ // somewhat arbitrary mapping for quick visual feedback
+ float v = -.5f;
+ if ((*it)->size() == 3) {
+ const unsigned char *d = (*it)->const_data();
+ if ((d[0] & 0xf0) == 0x90) { // note on
+ v = .25f + d[2] / 512.f;
+ }
+ else if ((d[0] & 0xf0) == 0x80) { // note off
+ v = .3f - d[2] / 640.f;
+ }
+ else if ((d[0] & 0xf0) == 0xb0) { // CC
+ v = -.1f - d[2] / 256.f;
+ }
+ }
+ _wavetable[t] += v;
+ }