From 806fe2cba63529b70c1ac919ccdbe0a642c79a28 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Wed, 30 Mar 2016 22:41:13 +0200 Subject: [PATCH] add i/o map support for Audio Unit untested - not even compile-tested. --- libs/ardour/ardour/audio_unit.h | 1 + libs/ardour/audio_unit.cc | 104 ++++++++++++++++++++------------ 2 files changed, 67 insertions(+), 38 deletions(-) diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h index 42e74b37da..057ff4f4a0 100644 --- a/libs/ardour/ardour/audio_unit.h +++ b/libs/ardour/ardour/audio_unit.h @@ -202,6 +202,7 @@ class LIBARDOUR_API AUPlugin : public ARDOUR::Plugin framecnt_t input_offset; framecnt_t cb_offset; BufferSet* input_buffers; + ChanMapping * input_map; framecnt_t frames_processed; uint32_t audio_input_cnt; diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc index 25c243ccdb..0ece03aa46 100644 --- a/libs/ardour/audio_unit.cc +++ b/libs/ardour/audio_unit.cc @@ -436,6 +436,7 @@ AUPlugin::AUPlugin (AudioEngine& engine, Session& session, boost::shared_ptrmNumberBuffers, input_maxbuf); + ChanCount bufs_count (DataType::AUDIO, 1); + BufferSet& silent_bufs = _session.get_silent_buffers(bufs_count); + for (uint32_t i = 0; i < limit; ++i) { ioData->mBuffers[i].mNumberChannels = 1; ioData->mBuffers[i].mDataByteSize = sizeof (Sample) * inNumberFrames; - /* we don't use the channel mapping because audiounits are - * never replicated. one plugin instance uses all channels/buffers - * passed to PluginInsert::connect_and_run() - */ - - ioData->mBuffers[i].mData = input_buffers->get_audio (i).data (cb_offset + input_offset); + bool valid = false; + uint32_t idx = in_map->get (DataType::AUDIO, i, &valid); + if (valid) { + ioData->mBuffers[i].mData = input_buffers->get_audio (idx).data (cb_offset + input_offset); + } else { + ioData->mBuffers[i].mData = silent_bufs.get_audio(0).data (cb_offset + input_offset); + } } cb_offset += inNumberFrames; @@ -1497,11 +1503,16 @@ AUPlugin::connect_and_run (BufferSet& bufs, ChanMapping in_map, ChanMapping out_ assert (bufs.available() >= ChanCount (DataType::AUDIO, output_channels)); input_buffers = &bufs; + input_map = &in_map; input_maxbuf = bufs.count().n_audio(); // number of input audio buffers input_offset = offset; cb_offset = 0; buffers->mNumberBuffers = output_channels; + bool inplace = in_map == out_map; + + ChanCount bufs_count (DataType::AUDIO, 1); + BufferSet& scratch_bufs = _session.get_scratch_buffers(bufs_count); for (int32_t i = 0; i < output_channels; ++i) { buffers->mBuffers[i].mNumberChannels = 1; @@ -1513,7 +1524,17 @@ AUPlugin::connect_and_run (BufferSet& bufs, ChanMapping in_map, ChanMapping out_ * a non-null values tells the plugin to render into the buffer pointed * at by the value. */ - buffers->mBuffers[i].mData = 0; + if (inplace) { + buffers->mBuffers[i].mData = 0; + } else { + bool valid = false; + uint32_t idx = out_map.get (DataType::AUDIO, i, &valid); + if (valid) { + buffers->mBuffers[i].mData = bufs.et_audio (idx).data (offset); + } else { + buffers->mBuffers[i].mData = scratch_bufs.get_audio(0).data(offset); + } + } } if (_has_midi_input) { @@ -1524,57 +1545,64 @@ AUPlugin::connect_and_run (BufferSet& bufs, ChanMapping in_map, ChanMapping out_ /* one MIDI port/buffer only */ - MidiBuffer& m = bufs.get_midi (i); + MidiBuffer& m = bufs.get_midi (i); - for (MidiBuffer::iterator i = m.begin(); i != m.end(); ++i) { - Evoral::MIDIEvent ev (*i); + for (MidiBuffer::iterator i = m.begin(); i != m.end(); ++i) { + Evoral::MIDIEvent ev (*i); - if (ev.is_channel_event()) { - const uint8_t* b = ev.buffer(); - DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1: MIDI event %2\n", name(), ev)); - unit->MIDIEvent (b[0], b[1], b[2], ev.time()); + if (ev.is_channel_event()) { + const uint8_t* b = ev.buffer(); + DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1: MIDI event %2\n", name(), ev)); + unit->MIDIEvent (b[0], b[1], b[2], ev.time()); + } + + /* XXX need to handle sysex and other message types */ } - - /* XXX need to handle sysex and other message types */ } } - } - /* does this really mean anything ? - */ + /* does this really mean anything ? + */ - ts.mSampleTime = frames_processed; - ts.mFlags = kAudioTimeStampSampleTimeValid; + ts.mSampleTime = frames_processed; + ts.mFlags = kAudioTimeStampSampleTimeValid; - DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1 render flags=%2 time=%3 nframes=%4 buffers=%5\n", - name(), flags, frames_processed, nframes, buffers->mNumberBuffers)); + DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1 render flags=%2 time=%3 nframes=%4 buffers=%5\n", + name(), flags, frames_processed, nframes, buffers->mNumberBuffers)); - if ((err = unit->Render (&flags, &ts, 0, nframes, buffers)) == noErr) { + if ((err = unit->Render (&flags, &ts, 0, nframes, buffers)) == noErr) { - input_maxbuf = 0; - frames_processed += nframes; + input_maxbuf = 0; + frames_processed += nframes; - DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1 rendered %2 buffers of %3\n", - name(), buffers->mNumberBuffers, output_channels)); + DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1 rendered %2 buffers of %3\n", + name(), buffers->mNumberBuffers, output_channels)); - int32_t limit = min ((int32_t) buffers->mNumberBuffers, output_channels); - int32_t i; + int32_t limit = min ((int32_t) buffers->mNumberBuffers, output_channels); + int32_t i; - for (i = 0; i < limit; ++i) { - Sample* expected_buffer_address= bufs.get_audio (i).data (offset); - if (expected_buffer_address != buffers->mBuffers[i].mData) { - /* plugin provided its own buffer for output so copy it back to where we want it - */ - memcpy (expected_buffer_address, buffers->mBuffers[i].mData, nframes * sizeof (Sample)); + for (i = 0; i < limit && inplace; ++i) { + // we know in_map == out_map + bool valid = false; + uint32_t idx = out_map.get (DataType::AUDIO, i, &valid); + if (!valid) continue; + Sample* expected_buffer_address = bufs.get_audio (idx).data (offset); + if (expected_buffer_address != buffers->mBuffers[i].mData) { + /* plugin provided its own buffer for output so copy it back to where we want it + */ + memcpy (expected_buffer_address, buffers->mBuffers[i].mData, nframes * sizeof (Sample)); + } } - } /* now silence any buffers that were passed in but the that the plugin * did not fill/touch/use. */ for (;i < output_channels; ++i) { - memset (bufs.get_audio (i).data (offset), 0, nframes * sizeof (Sample)); + bool valid = false; + uint32_t idx = out_map.get (DataType::AUDIO, i, &valid); + if (!valid) continue; + memset (bufs.get_audio (idx).data (offset), 0, nframes * sizeof (Sample)); } return 0;