From d1e443c1a73c82703a2afe6fd1bb8624fe924668 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 12 Feb 2010 22:17:33 +0000 Subject: [PATCH] provide Redirect::requires_fixed_sized_buffers() as a way to handle UAD plugins on OS X; reset AU plugins that have requires_fixed_sized_buffers() == true; if a redirect requires fixed sized buffers, quantize all automation to the start of the process block, and ignore actual automation event placement; TRACE_API macros for AU plugins git-svn-id: http://subversion.ardour.org/svn/ardour2/ardour2/branches/2.0-ongoing@6680 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/audio_unit.h | 3 ++ libs/ardour/ardour/redirect.h | 1 + libs/ardour/audio_unit.cc | 63 ++++++++++++++++++++++++++++++++++------- libs/ardour/audioengine.cc | 2 ++ libs/ardour/insert.cc | 18 ++++++------ 5 files changed, 68 insertions(+), 19 deletions(-) diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h index 35b4630f9..8ce6e0f09 100644 --- a/libs/ardour/ardour/audio_unit.h +++ b/libs/ardour/ardour/audio_unit.h @@ -107,6 +107,7 @@ class AUPlugin : public ARDOUR::Plugin uint32_t output_streams() const; uint32_t input_streams() const; int32_t configure_io (int32_t in, int32_t out); + bool requires_fixed_size_buffers() const; boost::shared_ptr get_au () { return unit; } boost::shared_ptr get_comp () const { return comp; } @@ -144,6 +145,8 @@ class AUPlugin : public ARDOUR::Plugin int32_t input_channels; int32_t output_channels; std::vector > io_configs; + nframes_t _current_block_size; + bool _requires_fixed_size_buffers; AudioBufferList* buffers; /* despite all the cool work that apple did on their AU preset diff --git a/libs/ardour/ardour/redirect.h b/libs/ardour/ardour/redirect.h index e4e6ccc14..ca8d1d486 100644 --- a/libs/ardour/ardour/redirect.h +++ b/libs/ardour/ardour/redirect.h @@ -77,6 +77,7 @@ class Redirect : public IO virtual nframes_t latency() { return 0; } virtual void set_block_size (nframes_t nframes) {} + virtual bool requires_fixed_size_buffers () const { return false; } sigc::signal active_changed; sigc::signal placement_changed; diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc index 5808e2e51..83ae9ffd3 100644 --- a/libs/ardour/audio_unit.cc +++ b/libs/ardour/audio_unit.cc @@ -56,6 +56,13 @@ using namespace std; using namespace PBD; using namespace ARDOUR; +#define TRACE_AU_API +#ifdef TRACE_AU_API +#define TRACE_API(fmt,...) fprintf (stderr, fmt, ## __VA_ARGS__) +#else +#define TRACE_API(fmt,...) +#endif + #ifndef AU_STATE_SUPPORT static bool seen_get_state_message = false; static bool seen_set_state_message = false; @@ -341,6 +348,8 @@ AUPlugin::AUPlugin (AudioEngine& engine, Session& session, boost::shared_ptrUninitialize (); } @@ -393,6 +405,7 @@ AUPlugin::discover_factory_presets () UInt32 dataSize = sizeof (presets); OSStatus err; + TRACE_API ("get property FactoryPresets in global scope\n"); if ((err = unit->GetProperty (kAudioUnitProperty_FactoryPresets, kAudioUnitScope_Global, 0, (void*) &presets, &dataSize)) != 0) { cerr << "cannot get factory preset info: " << err << endl; return; @@ -420,6 +433,7 @@ AUPlugin::init () OSErr err; try { + TRACE_API ("opening AudioUnit\n"); err = CAAudioUnit::Open (*(comp.get()), *unit); } catch (...) { error << _("Exception thrown during AudioUnit plugin loading - plugin ignored") << endmsg; @@ -436,6 +450,7 @@ AUPlugin::init () renderCallbackInfo.inputProc = _render_callback; renderCallbackInfo.inputProcRefCon = this; + TRACE_API ("set render callback in input scope\n"); if ((err = unit->SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, (void*) &renderCallbackInfo, sizeof(renderCallbackInfo))) != 0) { cerr << "cannot install render callback (err = " << err << ')' << endl; @@ -452,14 +467,18 @@ AUPlugin::init () info.transportStateProc = _get_transport_state_callback; //ignore result of this - don't care if the property isn't supported + TRACE_API ("set host callbacks in global scope\n"); unit->SetProperty (kAudioUnitProperty_HostCallbacks, kAudioUnitScope_Global, 0, //elementID &info, sizeof (HostCallbackInfo)); + TRACE_API ("count global elements\n"); unit->GetElementCount (kAudioUnitScope_Global, global_elements); + TRACE_API ("count input elements\n"); unit->GetElementCount (kAudioUnitScope_Input, input_elements); + TRACE_API ("count output elements\n"); unit->GetElementCount (kAudioUnitScope_Output, output_elements); /* these keep track of *configured* channel set up, @@ -739,6 +758,7 @@ AUPlugin::set_parameter (uint32_t which, float val) { if (which < descriptors.size()) { const AUParameterDescriptor& d (descriptors[which]); + TRACE_API ("set parameter %d in scope %d element %d to %f\n", d.id, d.scope, d.element, val); unit->SetParameter (d.id, d.scope, d.element, val); /* tell the world what we did */ @@ -750,7 +770,8 @@ AUPlugin::set_parameter (uint32_t which, float val) theEvent.mArgument.mParameter.mParameterID = d.id; theEvent.mArgument.mParameter.mScope = d.scope; theEvent.mArgument.mParameter.mElement = d.element; - + + TRACE_API ("notify about parameter change\n"); AUEventListenerNotify (NULL, NULL, &theEvent); } } @@ -761,6 +782,7 @@ AUPlugin::get_parameter (uint32_t which) const float val = 0.0; if (which < descriptors.size()) { const AUParameterDescriptor& d (descriptors[which]); + TRACE_API ("get value of parameter %d in scope %d element %d\n", d.id, d.scope, d.element); unit->GetParameter(d.id, d.scope, d.element, val); } return val; @@ -792,6 +814,7 @@ AUPlugin::activate () { if (!initialized) { OSErr err; + TRACE_API ("call Initialize in activate()\n"); if ((err = unit->Initialize()) != noErr) { error << string_compose (_("AUPlugin: %1 cannot initialize plugin (err = %2)"), name(), err) << endmsg; } else { @@ -804,6 +827,7 @@ AUPlugin::activate () void AUPlugin::deactivate () { + TRACE_API ("call Uninitialize in deactivate()\n"); unit->Uninitialize (); initialized = false; } @@ -811,18 +835,13 @@ AUPlugin::deactivate () void AUPlugin::flush () { + TRACE_API ("call Reset in flush()\n"); unit->GlobalReset (); } void AUPlugin::set_block_size (nframes_t nframes) { - _set_block_size (nframes); -} - -int -AUPlugin::_set_block_size (nframes_t nframes) -{ bool was_initialized = initialized; UInt32 numFrames = nframes; OSErr err; @@ -831,6 +850,7 @@ AUPlugin::_set_block_size (nframes_t nframes) deactivate (); } + TRACE_API ("set MaximumFramesPerSlice in global scope to %u\n", numFrames); if ((err = unit->SetProperty (kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &numFrames, sizeof (numFrames))) != noErr) { cerr << "cannot set max frames (err = " << err << ')' << endl; @@ -841,6 +861,8 @@ AUPlugin::_set_block_size (nframes_t nframes) activate (); } + _current_block_size = nframes; + return 0; } @@ -1116,6 +1138,9 @@ AUPlugin::set_stream_format (int scope, uint32_t cnt, AudioStreamBasicDescriptio OSErr result; for (uint32_t i = 0; i < cnt; ++i) { + TRACE_API ("set stream format for %s, scope = %d element %d\n", + (scope == kAudioUnitScope_Input ? "input" : "output"), + scope, cnt); if ((result = unit->SetFormat (scope, i, fmt)) != 0) { error << string_compose (_("AUPlugin: could not set stream format for %1/%2 (err = %3)"), (scope == kAudioUnitScope_Input ? "input" : "output"), i, result) << endmsg; @@ -1186,6 +1211,10 @@ AUPlugin::connect_and_run (vector& bufs, uint32_t maxbuf, int32_t& in, AudioTimeStamp ts; OSErr err; + if (requires_fixed_size_buffers() && (nframes != _current_block_size) { + unit->GlobalReset(); + } + current_buffers = &bufs; current_maxbuf = maxbuf; current_offset = offset; @@ -1239,6 +1268,8 @@ AUPlugin::get_beat_and_tempo_callback (Float64* outCurrentBeat, { TempoMap& tmap (_session.tempo_map()); + TRACE_API ("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. @@ -1276,6 +1307,8 @@ AUPlugin::get_musical_time_location_callback (UInt32* outDeltaSampleOffsetToNe { TempoMap& tmap (_session.tempo_map()); + TRACE_API ("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. @@ -1332,6 +1365,8 @@ AUPlugin::get_transport_state_callback (Boolean* outIsPlaying, bool rolling; float speed; + TRACE_API ("AU calls ardour transport state callback\n"); + rolling = _session.transport_rolling(); speed = _session.transport_speed (); @@ -1470,6 +1505,7 @@ AUPlugin::get_state() CFDataRef xmlData; CFPropertyListRef propertyList; + TRACE_API ("get preset state\n"); if (unit->GetAUPreset (propertyList) != noErr) { return *root; } @@ -1543,6 +1579,7 @@ AUPlugin::set_state(const XMLNode& node) CFRelease (xmlData); if (propertyList) { + TRACE_API ("set preset\n"); if (unit->SetAUPreset (propertyList) == noErr) { ret = 0; @@ -1581,6 +1618,7 @@ AUPlugin::load_preset (const string preset_label) if ((ux = user_preset_map.find (preset_label)) != user_preset_map.end()) { if ((propertyList = load_property_list (ux->second)) != 0) { + TRACE_API ("set preset from user presets\n"); if (unit->SetAUPreset (propertyList) == noErr) { ret = true; @@ -1601,7 +1639,7 @@ AUPlugin::load_preset (const string preset_label) preset.presetNumber = fx->second; preset.presetName = CFStringCreateWithCString (kCFAllocatorDefault, fx->first.c_str(), kCFStringEncodingUTF8); - cerr << "Setting factory preset " << fx->second << endl; + TRACE_API ("set preset from factory presets\n"); if (unit->SetPresentPreset (preset) == 0) { ret = true; @@ -1655,6 +1693,7 @@ AUPlugin::save_preset (string preset_name) return false; } + TRACE_API ("get current preset\n"); if (unit->GetAUPreset (propertyList) != noErr) { return false; } @@ -1854,6 +1893,7 @@ AUPlugin::current_preset() const #ifdef AU_STATE_SUPPORT CFPropertyListRef propertyList; + TRACE_API ("get current preset for current_preset()\n"); if (unit->GetAUPreset (propertyList) == noErr) { preset_name = get_preset_name_in_plist (propertyList); CFRelease(propertyList); @@ -1945,6 +1985,7 @@ AUPluginInfo::load (Session& session) try { PluginPtr plugin; + TRACE_API ("load AU as a component\n"); boost::shared_ptr comp (new CAComponent(*descriptor)); if (!comp->IsValid()) { @@ -1953,8 +1994,9 @@ AUPluginInfo::load (Session& session) plugin.reset (new AUPlugin (session.engine(), session, comp)); } - plugin->set_info (PluginInfoPtr (new AUPluginInfo (*this))); - return plugin; + AUPluginInfo *aup = new AUPluginInfo (*this); + plugin->set_info (PluginInfoPtr (aup)); + plugin->set_fixed_size_buffers (aup->creator() == "!UAD"); } catch (failed_constructor &err) { @@ -2245,6 +2287,7 @@ AUPluginInfo::cached_io_configuration (const std::string& unique_id, } + TRACE_API ("get AU channel info\n"); if ((ret = unit.GetChannelInfo (&channel_info, cnt)) < 0) { return false; } diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index d1776ccb7..b8cf0cf12 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -201,6 +201,8 @@ AudioEngine::stop (bool forever) } } + stop_metering_thread (); + return _running ? -1 : 0; } diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc index e70293d98..8d7ae52b5 100644 --- a/libs/ardour/insert.cc +++ b/libs/ardour/insert.cc @@ -441,26 +441,26 @@ PluginInsert::automation_run (vector& bufs, uint32_t nbufs, nframes_t return; } - if (!find_next_event (now, end, next_event)) { + if (!find_next_event (now, end, next_event) || requires_fixed_size_buffers()) { /* no events have a time within the relevant range */ connect_and_run (bufs, nbufs, nframes, 0, true, now); return; } - - while (nframes) { + + while (nframes) { nframes_t cnt = min (((nframes_t) ceil (next_event.when) - now), nframes); - - connect_and_run (bufs, nbufs, cnt, offset, true, now); - - nframes -= cnt; + + connect_and_run (bufs, nbufs, cnt, offset, true, now); + + nframes -= cnt; now += cnt; offset += cnt; - + if (!find_next_event (now, end, next_event)) { break; } } - + /* cleanup anything that is left to do */ if (nframes) { -- 2.11.4.GIT