summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-11-02 19:38:31 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-11-02 19:38:31 +0000
commit95b52e093ab140717e8ee4ffc74c58b4531a2146 (patch)
treef027bf2299034d892749eed3f5625da2ea59344e
parentad25b455372bb58df9caad6903b462b0905ae4ab (diff)
implement AU host callbacks, to some extent
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@6002 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--libs/ardour/audio_unit.cc150
1 files changed, 143 insertions, 7 deletions
diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc
index 33600f6acd..9befc219d7 100644
--- a/libs/ardour/audio_unit.cc
+++ b/libs/ardour/audio_unit.cc
@@ -20,6 +20,7 @@
#include <sstream>
#include <errno.h>
#include <string.h>
+#include <math.h>
#include <pbd/transmitter.h>
#include <pbd/xml++.h>
@@ -1040,16 +1041,90 @@ OSStatus
AUPlugin::get_beat_and_tempo_callback (Float64* outCurrentBeat,
Float64* outCurrentTempo)
{
- return kAudioUnitErr_CannotDoInCurrentContext;
+ TempoMap& tmap (_session.tempo_map());
+
+ /* 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;
+ }
+
+ BBT_Time bbt;
+ Metric metric;
+
+ tmap.bbt_time_with_metric (_session.transport_frame() + current_offset, bbt, metric);
+
+ if (outCurrentBeat) {
+ float beat;
+ beat = metric.meter().beats_per_bar * bbt.bars;
+ beat += bbt.beats;
+ beat += bbt.ticks / Meter::ticks_per_beat;
+ *outCurrentBeat = *beat;
+ }
+
+ if (outCurrentTempo) {
+ *outCurrentTempo = floor (metric.tempo().beats_per_minute());
+ }
+
+ return noErr;
+
}
OSStatus
-AUPlugin::get_musical_time_location_callback (UInt32* outDeltaSampleOffsetToNextBeat,
- Float32* outTimeSig_Numerator,
- UInt32* outTimeSig_Denominator,
- Float64* outCurrentMeasureDownBeat)
+AUPlugin::get_musical_time_location_callback (UInt32* outDeltaSampleOffsetToNextBeat,
+ Float32* outTimeSig_Numerator,
+ UInt32* outTimeSig_Denominator,
+ Float64* outCurrentMeasureDownBeat)
{
- return kAudioUnitErr_CannotDoInCurrentContext;
+ TempoMap& tmap (_session.tempo_map());
+
+ /* 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;
+ }
+
+ BBT_Time bbt;
+ Metric metric;
+
+ tmap.bbt_time_with_metric (_session.transport_frame() + current_offset, bbt, metric);
+
+ if (*outDeltaSampleOffsetToNextBeat) {
+ if (bbt.ticks == 0) {
+ /* on the beat */
+ *outDeltaSampleOffsetToNextBeat = 0;
+ } else {
+ *outDeltaSampleOffsetToNextBeat = (UInt32) floor (((Meter::ticks_per_beat - bbt.ticks)/Meter::ticks_per_beat) * // fraction of a beat to next beat
+ metric.tempo().frames_per_beat(_session.frame_rate(), metric.meter())); // frames per beat
+ }
+ }
+
+ if (*outTimeSig_Numerator) {
+ *outTimeSig_Numerator = (UInt32) lrintf (metric.meter().beats_per_bar());
+ }
+ if (*outTimeSig_Denominator) {
+ *outTimeSig_Denominator = (UInt32) lrintf (metric.meter().note_divisor());
+ }
+
+ if (*outCurrentMeasureDownBeat) {
+
+ /* beat for the start of the bar.
+ 1|1|0 -> 1
+ 2|1|0 -> 1 + beats_per_bar
+ 3|1|0 -> 1 + (2 * beats_per_bar)
+ etc.
+ */
+
+ *outCurrentMeasureDownBeat = 1 + metric.meter().beats_per_bar * (bbt.bars - 1);
+ }
+
+ return noErr;
}
OSStatus
@@ -1060,7 +1135,68 @@ AUPlugin::get_transport_state_callback (Boolean* outIsPlaying,
Float64* outCycleStartBeat,
Float64* outCycleEndBeat)
{
- return kAudioUnitErr_CannotDoInCurrentContext;
+ if (outIsPlaying) {
+ *outIsPlaying = _session.transport_rolling();
+ }
+
+ if (outTransportStateChanged) {
+ *outTransportStateChanged = false;
+ }
+
+ if (outCurrentSampleInTimeLine) {
+ *outCurrentSampleInTimeLine = _session.transport_frame();
+ }
+
+ if (outIsCycling) {
+ Location* loc = _session.locations()->auto_loop_location();
+
+ *outIsCycling = (loc && _session.transport_rolling() && _session.get_play_loop());
+
+ if (*outIsCycling) {
+
+ if (outCycleStartBeat || outCycleEndBeat) {
+
+ 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;
+ }
+
+ BBT_Time bbt;
+ TempoMap::Metric metric;
+
+ if (outCycleStartBeat) {
+ TempoMap::Metric metric;
+ _session.tempo_map().bbt_time (loc->start(), bbt, metric);
+
+
+ float beat;
+ beat = metric.meter().beats_per_bar * bbt.bars;
+ beat += bbt.beats;
+ beat += bbt.ticks / Meter::ticks_per_beat;
+
+ *outCycleStartBeat = beat;
+ }
+
+ if (outCycleEndBeat) {
+ _session.tempo_map().bbt_time (loc->start(), bbt, metric);
+
+ float beat;
+ beat = metric.meter().beats_per_bar * bbt.bars;
+ beat += bbt.beats;
+ beat += bbt.ticks / Meter::ticks_per_beat;
+
+ *outCycleEndBeat = beat;
+ }
+ }
+ }
+ }
+
+ return noErr;
}
set<uint32_t>