diff --git a/Server/Source/AudioWorker.cpp b/Server/Source/AudioWorker.cpp index 16e64d4..ea3396e 100644 --- a/Server/Source/AudioWorker.cpp +++ b/Server/Source/AudioWorker.cpp @@ -48,8 +48,7 @@ void AudioWorker::init(std::unique_ptr s, HandshakeRequest cfg) m_channelMapper.createServerMapping(m_activeChannels); m_channelMapper.print(); m_chain = std::make_shared( - ProcessorChain::createBussesProperties(m_channelsIn, m_channelsOut, m_channelsSC), cfg); - m_chain->setLogTagSource(getLogTagSource()); + getLogTagSource(), ProcessorChain::createBussesProperties(m_channelsIn, m_channelsOut, m_channelsSC), cfg); if (m_doublePrecission && m_chain->supportsDoublePrecisionProcessing()) { m_chain->setProcessingPrecision(AudioProcessor::doublePrecision); } diff --git a/Server/Source/ProcessorChain.cpp b/Server/Source/ProcessorChain.cpp index 5c564be..b66c4c7 100644 --- a/Server/Source/ProcessorChain.cpp +++ b/Server/Source/ProcessorChain.cpp @@ -115,6 +115,7 @@ bool ProcessorChain::setProcessorBusesLayout(Processor* proc) { layout.inputBuses.add(AudioChannelSet::mono()); supported = proc->checkBusesLayoutSupported(layout) && proc->setBusesLayout(layout); } + if (!supported) { logln("trying without sidechain bus"); layout.inputBuses.remove(1); @@ -125,31 +126,81 @@ bool ProcessorChain::setProcessorBusesLayout(Processor* proc) { } } } + if (!supported && layout.getMainOutputChannels() > 2 && layout.getMainInputChannels() == 0) { - logln("trying multi-mono-bus layout for instrument"); - AudioProcessor::BusesLayout layout2; - for (int ch = 0; ch < layout.getMainOutputChannels(); ch++) { - layout2.outputBuses.add(AudioChannelSet::mono()); - } - supported = proc->checkBusesLayoutSupported(layout2) && proc->setBusesLayout(layout2); - if (!supported) { - logln("trying multi-stereo-bus layout for instrument"); - layout2.outputBuses.clear(); - for (int ch = 0; ch + 1 < layout.getMainOutputChannels(); ch += 2) { - layout2.outputBuses.add(AudioChannelSet::stereo()); + auto addInputs = [](AudioProcessor::BusesLayout& l, int channels) { + l.inputBuses.clear(); + + if (channels == 1) { + l.inputBuses.add(AudioChannelSet::mono()); + } else if (channels == 2) { + l.inputBuses.add(AudioChannelSet::stereo()); + } else { + l.inputBuses.add(AudioChannelSet::discreteChannels(channels)); } - supported = proc->checkBusesLayoutSupported(layout2) && proc->setBusesLayout(layout2); - } - if (!supported) { - logln("trying multi-mono-bus layout with stereo main for instrument"); - layout2.outputBuses.clear(); - layout2.outputBuses.add(AudioChannelSet::stereo()); - for (int ch = 2; ch < layout.getMainOutputChannels(); ch++) { - layout2.outputBuses.add(AudioChannelSet::mono()); + }; + + auto addOutputsAndLayout = [](Array& layouts, AudioProcessor::BusesLayout& l, + int channels) { + + // try layouts with different combinations of stereo and mono buses + int numStereo = channels / 2; + + while (numStereo >= 0) { + l.outputBuses.clear(); + + int numMono = channels - numStereo * 2; + + for (int ch = 0; ch < numStereo; ch++) { + l.outputBuses.add(AudioChannelSet::stereo()); + } + + for (int ch = 0; ch < numMono; ch++) { + l.outputBuses.add(AudioChannelSet::mono()); + } + + layouts.add(l); + + numStereo--; } - supported = proc->checkBusesLayoutSupported(layout2) && proc->setBusesLayout(layout2); - } + + // try layouts with one bus with the exact number of channels + for (auto channelSet : AudioChannelSet::channelSetsWithNumberOfChannels(channels)) { + l.outputBuses.clear(); + l.outputBuses.add(channelSet); + layouts.add(l); + } + }; + + auto check = [&](int channels) { + Array layouts; + AudioProcessor::BusesLayout layout2; + + addOutputsAndLayout(layouts, layout2, channels); + + addInputs(layout2, 2); + addOutputsAndLayout(layouts, layout2, channels); + + addInputs(layout2, 1); + addOutputsAndLayout(layouts, layout2, channels); + + for (auto& l : layouts) { + if (proc->checkBusesLayoutSupported(l) && proc->setBusesLayout(l)) { + return true; + } + } + + return false; + }; + + int channelsToTry = Defaults::PLUGIN_CHANNELS_MAX; + + do { + logln("trying instrument-multi-bus layouts with " << channelsToTry << " channels"); + supported = check(channelsToTry--); + } while (!supported && channelsToTry > 0); } + if (!supported) { if (hasSidechain) { logln("disabling sidechain input to use the plugins I/O layout"); @@ -161,42 +212,36 @@ bool ProcessorChain::setProcessorBusesLayout(Processor* proc) { logln("falling back to the plugins default layout"); - // keep the processor's layout and calculate the neede extra channels - auto procLayout = proc->getBusesLayout(); + supported = true; + } + } - // main bus IN - int extraInChannels = procLayout.getMainInputChannels() - layout.getMainInputChannels(); - // check extra busses IN - for (int busIdx = 1; busIdx < procLayout.inputBuses.size(); busIdx++) { - extraInChannels += procLayout.inputBuses[busIdx].size(); - } - // main bus OUT - int extraOutChannels = procLayout.getMainOutputChannels() - layout.getMainOutputChannels(); - // check extra busses OUT - for (int busIdx = 1; busIdx < procLayout.outputBuses.size(); busIdx++) { - extraOutChannels += procLayout.outputBuses[busIdx].size(); - } + auto procLayout = proc->getBusesLayout(); - proc->setExtraChannels(extraInChannels, extraOutChannels); + // main bus IN + int extraInChannels = procLayout.getMainInputChannels() - layout.getMainInputChannels(); + // check extra busses IN + for (int busIdx = 1; busIdx < procLayout.inputBuses.size(); busIdx++) { + extraInChannels += procLayout.inputBuses[busIdx].size(); + } + // main bus OUT + int extraOutChannels = procLayout.getMainOutputChannels() - layout.getMainOutputChannels(); + // check extra busses OUT + for (int busIdx = 1; busIdx < procLayout.outputBuses.size(); busIdx++) { + extraOutChannels += procLayout.outputBuses[busIdx].size(); + } - m_extraChannels = jmax(m_extraChannels, extraInChannels, extraOutChannels); + proc->setExtraChannels(extraInChannels, extraOutChannels); - logln(extraInChannels << " extra input(s), " << extraOutChannels << " extra output(s) -> " - << m_extraChannels << " extra channel(s) in total"); + m_extraChannels = jmax(m_extraChannels, extraInChannels, extraOutChannels); - layout = procLayout; - supported = true; - } - } + logln(extraInChannels << " extra input(s), " << extraOutChannels << " extra output(s) -> " << m_extraChannels + << " extra channel(s) in total"); - if (supported) { - logln("using I/O layout:"); - printBusesLayout(layout); - } else { - logln("no working I/O layout found"); - } + logln("setting processor to I/O layout:"); + printBusesLayout(procLayout); - return supported; + return true; } int ProcessorChain::getExtraChannels() { diff --git a/Tests/Source/Server/ProcessorChainTest.hpp b/Tests/Source/Server/ProcessorChainTest.hpp index 97b5639..1e9acf7 100644 --- a/Tests/Source/Server/ProcessorChainTest.hpp +++ b/Tests/Source/Server/ProcessorChainTest.hpp @@ -31,25 +31,27 @@ class ProcessorChainTest : UnitTest { int chIn = 2, chOut = 2, chSc = 0; - auto pc = std::make_unique(ProcessorChain::createBussesProperties(chIn, chOut, chSc), + LogTag testTag("test"); + + auto pc = std::make_unique(&testTag, ProcessorChain::createBussesProperties(chIn, chOut, chSc), HandshakeRequest()); expect(pc->updateChannels(chIn, chOut, chSc)); pc.reset(); chIn = chOut = 64; - pc = std::make_unique(ProcessorChain::createBussesProperties(chIn, chOut, chSc), + pc = std::make_unique(&testTag, ProcessorChain::createBussesProperties(chIn, chOut, chSc), HandshakeRequest()); expect(pc->updateChannels(chIn, chOut, chSc)); pc.reset(); chSc = 2; - pc = std::make_unique(ProcessorChain::createBussesProperties(chIn, chOut, chSc), + pc = std::make_unique(&testTag, ProcessorChain::createBussesProperties(chIn, chOut, chSc), HandshakeRequest()); expect(pc->updateChannels(chIn, chOut, chSc)); pc.reset(); chIn = chOut = chSc = 2; - pc = std::make_unique(ProcessorChain::createBussesProperties(chIn, chOut, chSc), + pc = std::make_unique(&testTag, ProcessorChain::createBussesProperties(chIn, chOut, chSc), HandshakeRequest()); expect(pc->updateChannels(chIn, chOut, chSc)); } @@ -60,7 +62,9 @@ class ProcessorChainTest : UnitTest { double sampleRate = 48000.0; int blockSize = 512, chIn = 2, chOut = 2, chSc = 2; - auto pc = std::make_unique(ProcessorChain::createBussesProperties(chIn, chOut, chSc), + LogTag testTag("test"); + + auto pc = std::make_unique(&testTag, ProcessorChain::createBussesProperties(chIn, chOut, chSc), HandshakeRequest()); pc->updateChannels(chIn, chOut, chSc); pc->prepareToPlay(sampleRate, blockSize); diff --git a/Tests/Source/Server/SandboxPluginTest.hpp b/Tests/Source/Server/SandboxPluginTest.hpp index d93b2a0..e2a3441 100644 --- a/Tests/Source/Server/SandboxPluginTest.hpp +++ b/Tests/Source/Server/SandboxPluginTest.hpp @@ -42,7 +42,10 @@ class SandboxPluginTest : UnitTest { HandshakeRequest cfg = {AG_PROTOCOL_VERSION, chIn, chOut, chSc, sampleRate, blockSize, false, 0, 0, 0, activeChannels.toInt(), 0}; - auto pc = std::make_unique(ProcessorChain::createBussesProperties(chIn, chOut, chSc), cfg); + LogTag testTag("test"); + + auto pc = + std::make_unique(&testTag, ProcessorChain::createBussesProperties(chIn, chOut, chSc), cfg); pc->setProcessingPrecision(AudioProcessor::singlePrecision); pc->updateChannels(chIn, chOut, chSc); pc->prepareToPlay(sampleRate, blockSize);