Vapor: expose Apple Spatial Mixer contols (via Lua)

This commit is contained in:
Robin Gareus 2024-02-24 19:46:54 +01:00
parent 572a8b9cf8
commit 22094c6caa
3 changed files with 122 additions and 0 deletions

View File

@ -71,6 +71,9 @@ public:
return _have_au_renderer;
}
bool load_au_preset (size_t);
bool set_au_param (size_t, float);
std::shared_ptr<PBD::Controllable> binaural_render_controllable () const {
return _binaural_render_control;
}
@ -144,6 +147,17 @@ private:
samplecnt_t _au_samples_processed;
float* _au_data[12];
struct LIBARDOUR_API AUParameter {
AudioUnitParameterID id;
AudioUnitScope scope;
AudioUnitElement element;
std::string label;
float lower, upper, normal;
};
std::vector<AUParameter> _au_params;
std::vector<AUPreset> _au_presets;
static OSStatus _render_callback(void*, AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32, UInt32, AudioBufferList*);
OSStatus render_callback(AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32, UInt32, AudioBufferList*);
#endif

View File

@ -1917,6 +1917,14 @@ LuaBindings::common (lua_State* L)
.deriveWSPtrClass <SurroundReturn, Processor> ("SurroundReturn")
.addFunction ("set_bed_mix", &SurroundReturn::set_bed_mix)
.addFunction ("have_au_renderer", &SurroundReturn::have_au_renderer)
.addFunction ("load_au_preset", &SurroundReturn::load_au_preset)
.addFunction ("set_au_param", &SurroundReturn::set_au_param)
.addFunction ("integrated_loudness", &SurroundReturn::integrated_loudness)
.addFunction ("max_momentary", &SurroundReturn::max_momentary)
.addFunction ("momentary", &SurroundReturn::momentary)
.addFunction ("max_dbtp", &SurroundReturn::max_dbtp)
.addFunction ("output_format_controllable", &SurroundReturn::output_format_controllable)
.endClass ()
.deriveWSPtrClass <Return, IOProcessor> ("Return")

View File

@ -29,6 +29,13 @@
#include "ardour/surround_return.h"
#include "ardour/surround_send.h"
#include "ardour/uri_map.h"
#ifdef __APPLE__
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioUnitUtilities.h>
#include "AUParamInfo.h"
#endif
#include "pbd/i18n.h"
using namespace ARDOUR;
@ -227,6 +234,67 @@ SurroundReturn::SurroundReturn (Session& s, Route* r)
return;
}
{
UInt32 dataSize;
Boolean isWritable;
if (noErr == AudioUnitGetPropertyInfo (_au, kAudioUnitProperty_FactoryPresets, kAudioUnitScope_Global, 0, &dataSize, &isWritable)) {
CFArrayRef presets;
assert (dataSize == sizeof (presets));
if (noErr == AudioUnitGetProperty (_au, kAudioUnitProperty_FactoryPresets, kAudioUnitScope_Global, 0, (void*) &presets, &dataSize) && presets) {
CFIndex cnt = CFArrayGetCount (presets);
for (CFIndex i = 0; i < cnt; ++i) {
AUPreset const* preset = (AUPreset const*) CFArrayGetValueAtIndex (presets, i);
_au_presets.push_back (*preset);
std::string name = CFStringRefToStdString (preset->presetName);
std::cout << "FOUND PRESET "<< preset->presetNumber << " - " << name << "\n";
}
CFRelease (presets);
}
}
}
AudioUnitScope scopes[] = {
kAudioUnitScope_Global,
kAudioUnitScope_Output,
kAudioUnitScope_Input
};
for (uint32_t i = 0; i < sizeof (scopes) / sizeof (scopes[0]); ++i) {
AUParamInfo param_info (_au, false, /* include read only */ false, scopes[i]);
for (uint32_t i = 0; i < param_info.NumParams(); ++i) {
const CAAUParameter* param = param_info.GetParamInfo ( param_info.ParamID (i));
const AudioUnitParameterInfo& info (param->ParamInfo());
if (!(info.flags & kAudioUnitParameterFlag_NonRealTime) && (info.flags & kAudioUnitParameterFlag_IsWritable)) {
AUParameter d;
d.id = param_info.ParamID (i);
d.scope = param_info.GetScope ();
d.element = param_info.GetElement ();
d.lower = info.minValue;
d.upper = info.maxValue;
d.normal = info.defaultValue;
const int len = CFStringGetLength (param->GetName());
char local_buffer[len * 2];
if (CFStringGetCString (param->GetName(), local_buffer,len * 2, kCFStringEncodingUTF8)) {
d.label = local_buffer;
}
_au_params.push_back(d);
}
}
}
#if 1 // RAMP up reverb
load_au_preset (1);
set_au_param (0, 0.6); // +8dB global reverb
#endif
_have_au_renderer = true;
}
#endif
@ -734,6 +802,38 @@ SurroundReturn::state () const
return node;
}
bool
SurroundReturn::load_au_preset (size_t id)
{
#ifdef __APPLE__
if (_au && _have_au_renderer && id < _au_presets.size ()) {
AUPreset* preset = &_au_presets[id];
if (noErr == AudioUnitSetProperty (_au, kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0, preset, sizeof (AUPreset))) {
AudioUnitParameter changedUnit;
changedUnit.mAudioUnit = _au;
changedUnit.mParameterID = kAUParameterListener_AnyParameter;
AUParameterListenerNotify (NULL, NULL, &changedUnit);
return true;
}
}
#endif
return false;
}
bool
SurroundReturn::set_au_param (size_t id, float val)
{
#ifdef __APPLE__
if (_au && _have_au_renderer && id < _au_params.size ()) {
const AUParameter& d (_au_params[id]);
val = std::max (0.f, std::min (1.f, val));
float v = d.lower + val * (d.upper - d.lower);
return noErr == AudioUnitSetParameter (_au, d.id, d.scope, d.element, v, 0);
}
#endif
return false;
}
#ifdef __APPLE__
OSStatus
SurroundReturn::_render_callback (void* userData,