, comp (_comp)
, unit (new CAAudioUnit)
, initialized (false)
- , _current_block_size (0)
+ , _last_nframes (0)
+ , _current_latency (UINT_MAX)
, _requires_fixed_size_buffers (false)
, buffers (0)
, variable_inputs (false)
, audio_input_cnt (0)
, _parameter_listener (0)
, _parameter_listener_arg (0)
- , transport_frame (false)
- , transport_speed (false)
+ , transport_frame (0)
+ , transport_speed (0)
, last_transport_speed (0.0)
{
if (!preset_search_path_initialized) {
, comp (other.get_comp())
, unit (new CAAudioUnit)
, initialized (false)
- , _current_block_size (0)
, _last_nframes (0)
+ , _current_latency (UINT_MAX)
, _requires_fixed_size_buffers (false)
, buffers (0)
, variable_inputs (false)
, bus_outputs (0)
, input_maxbuf (0)
, input_offset (0)
+ , cb_offsets (0)
, input_buffers (0)
, input_map (0)
, frames_processed (0)
, _parameter_listener (0)
, _parameter_listener_arg (0)
+ , transport_frame (0)
+ , transport_speed (0)
+ , last_transport_speed (0.0)
{
init ();
framecnt_t
AUPlugin::signal_latency () const
{
- return unit->Latency() * _session.frame_rate();
+ guint lat = g_atomic_int_get (&_current_latency);;
+ if (lat == UINT_MAX) {
+ lat = unit->Latency() * _session.frame_rate();
+ g_atomic_int_set (&_current_latency, lat);
+ }
+ return lat;
}
void
activate ();
}
- _current_block_size = nframes;
-
return 0;
}
bool inplace = true; // TODO check plugin-insert in-place ?
ChanMapping::Mappings inmap (in_map.mappings ());
ChanMapping::Mappings outmap (out_map.mappings ());
- assert (outmap[DataType::AUDIO].size () > 0);
+ if (outmap[DataType::AUDIO].size () == 0) {
+ inplace = false;
+ }
if (inmap[DataType::AUDIO].size() > 0 && inmap != outmap) {
inplace = false;
}
DEBUG_TRACE (DEBUG::AudioUnits, "AU calls ardour beat&tempo callback\n");
- /* more than 1 meter or more than 1 tempo means that a simplistic computation
- (and interpretation) of a beat position will be incorrect. So refuse to
- offer the value.
- */
-
- if (tmap.n_tempos() > 1 || tmap.n_meters() > 1) {
- return kAudioUnitErr_CannotDoInCurrentContext;
- }
-
- TempoMetric metric = tmap.metric_at (transport_frame + input_offset);
- Timecode::BBT_Time bbt = _session.tempo_map().bbt_at_frame (transport_frame + input_offset);
-
if (outCurrentBeat) {
- const double ppq_scaling = metric.meter().note_divisor() / 4.0;
- float beat;
- beat = metric.meter().divisions_per_bar() * (bbt.bars - 1);
- beat += (bbt.beats - 1);
- beat += bbt.ticks / Timecode::BBT_Time::ticks_per_beat;
- *outCurrentBeat = beat * ppq_scaling;
+ *outCurrentBeat = tmap.quarter_note_at_frame (transport_frame + input_offset);
}
if (outCurrentTempo) {
- *outCurrentTempo = floor (metric.tempo().beats_per_minute());
+ *outCurrentTempo = tmap.tempo_at_frame (transport_frame + input_offset).beats_per_minute();
}
return noErr;
DEBUG_TRACE (DEBUG::AudioUnits, "AU calls ardour music time location callback\n");
- /* more than 1 meter or more than 1 tempo means that a simplistic computation
- (and interpretation) of a beat position will be incorrect. So refuse to
- offer the value.
- */
-
- if (tmap.n_tempos() > 1 || tmap.n_meters() > 1) {
- return kAudioUnitErr_CannotDoInCurrentContext;
- }
-
TempoMetric metric = tmap.metric_at (transport_frame + input_offset);
Timecode::BBT_Time bbt = _session.tempo_map().bbt_at_frame (transport_frame + input_offset);
/* on the beat */
*outDeltaSampleOffsetToNextBeat = 0;
} else {
- double const beat_frac_to_next = (Timecode::BBT_Time::ticks_per_beat - bbt.ticks) / Timecode::BBT_Time::ticks_per_beat;
- *outDeltaSampleOffsetToNextBeat = tmap.frame_at_beat (tmap.beat_at_frame (transport_frame + input_offset) + beat_frac_to_next);
+ double const next_beat = ceil (tmap.quarter_note_at_frame (transport_frame + input_offset));
+ framepos_t const next_beat_frame = tmap.frame_at_quarter_note (next_beat);
+
+ *outDeltaSampleOffsetToNextBeat = next_beat_frame - (transport_frame + input_offset);
}
}
3|1|0 -> 1 + (2 * divisions_per_bar)
etc.
*/
+ bbt.beats = 1;
+ bbt.ticks = 0;
- *outCurrentMeasureDownBeat = 1 + metric.meter().divisions_per_bar() * (bbt.bars - 1);
+ *outCurrentMeasureDownBeat = tmap.pulse_at_bbt (bbt) * 4.0;
}
return noErr;
TempoMap& tmap (_session.tempo_map());
- /* more than 1 meter means that a simplistic computation (and interpretation) of
- a beat position will be incorrect. so refuse to offer the value.
- */
-
- if (tmap.n_meters() > 1) {
- return kAudioUnitErr_CannotDoInCurrentContext;
- }
-
Timecode::BBT_Time bbt;
if (outCycleStartBeat) {
- TempoMetric metric = tmap.metric_at (loc->start() + input_offset);
- bbt = _session.tempo_map().bbt_at_frame (loc->start() + input_offset);
-
- float beat;
- beat = metric.meter().divisions_per_bar() * bbt.bars;
- beat += bbt.beats;
- beat += bbt.ticks / Timecode::BBT_Time::ticks_per_beat;
-
- *outCycleStartBeat = beat;
+ *outCycleStartBeat = tmap.quarter_note_at_frame (loc->start() + input_offset);
}
if (outCycleEndBeat) {
- TempoMetric metric = tmap.metric_at (loc->end() + input_offset);
- bbt = _session.tempo_map().bbt_at_frame (loc->end() + input_offset);
-
- float beat;
- beat = metric.meter().divisions_per_bar() * bbt.bars;
- beat += bbt.beats;
- beat += bbt.ticks / Timecode::BBT_Time::ticks_per_beat;
-
- *outCycleEndBeat = beat;
+ *outCycleEndBeat = tmap.quarter_note_at_frame (loc->end() + input_offset);
}
}
}
_parameter_listener_arg = arg;
+ // listen for latency changes
+ AudioUnitEvent event;
+ event.mEventType = kAudioUnitEvent_PropertyChange;
+ event.mArgument.mProperty.mAudioUnit = unit->AU();
+ event.mArgument.mProperty.mPropertyID = kAudioUnitProperty_Latency;
+ event.mArgument.mProperty.mScope = kAudioUnitScope_Global;
+ event.mArgument.mProperty.mElement = 0;
+
+ if (AUEventListenerAddEventType (_parameter_listener, _parameter_listener_arg, &event) != noErr) {
+ PBD::error << "Failed to create latency event listener\n";
+ // TODO don't cache _current_latency
+ }
+
return 0;
}
void
AUPlugin::parameter_change_listener (void* /*arg*/, void* src, const AudioUnitEvent* event, UInt64 /*host_time*/, Float32 new_value)
{
+ if (event->mEventType == kAudioUnitEvent_PropertyChange) {
+ if (event->mArgument.mProperty.mPropertyID == kAudioUnitProperty_Latency) {
+ DEBUG_TRACE (DEBUG::AudioUnits, string_compose("AU Latency Change Event %1 <> %2\n", new_value, unit->Latency()));
+ guint lat = unit->Latency() * _session.frame_rate();
+ g_atomic_int_set (&_current_latency, lat);
+ }
+ return;
+ }
+
ParameterMap::iterator i;
if ((i = parameter_map.find (event->mArgument.mParameter.mParameterID)) == parameter_map.end()) {