Channel routing without inserts.
This commit is contained in:
+101
-148
@@ -338,24 +338,12 @@ namespace pipedal
|
||||
float *discardOutputBuffer = nullptr;
|
||||
std::vector<float *> mainCaptureBuffers;
|
||||
std::vector<float *> mainPlaybackBuffers;
|
||||
std::vector<float *> mainInsertPlaybackBuffers;
|
||||
std::vector<float *> mainVuPlaybackBuffers;
|
||||
|
||||
std::vector<float *> auxCaptureBuffers;
|
||||
std::vector<float *> auxPlaybackBuffers;
|
||||
std::vector<float *> auxVuPlaybackBuffers;
|
||||
|
||||
std::vector<float *> sendCaptureBuffers;
|
||||
std::vector<float *> sendPlaybackBuffers;
|
||||
|
||||
struct OutputBufferMix
|
||||
{
|
||||
size_t outputChannel = 0;
|
||||
std::vector<float *> inputBuffers;
|
||||
float *outputBuffer = nullptr;
|
||||
};
|
||||
|
||||
std::vector<OutputBufferMix> outputBufferMixes;
|
||||
|
||||
std::vector<uint8_t> rawCaptureBuffer;
|
||||
std::vector<uint8_t> rawPlaybackBuffer;
|
||||
@@ -1290,9 +1278,8 @@ namespace pipedal
|
||||
<< ", " << this->bufferSize << "x" << this->numberOfBuffers
|
||||
<< ", " << "device: " << this->DeviceInputBufferCount() << "/" << this->DeviceOutputBufferCount()
|
||||
<< ", main: " << this->MainInputBufferCount() << "/" << this->MainOutputBufferCount()
|
||||
<< ", main ins: " << this->MainOutputBufferCount() << "/" << this->MainOutputBufferCount()
|
||||
<< ", aux: " << this->AuxInputBufferCount() << "/" << this->AuxOutputBufferCount()
|
||||
<< ", send: " << this->SendOutputBufferCount() << "/" << this->SendInputBufferCount());
|
||||
);
|
||||
return result;
|
||||
}
|
||||
void PreparePlaybackFunctions(snd_pcm_format_t playbackFormat)
|
||||
@@ -1833,25 +1820,12 @@ namespace pipedal
|
||||
cpuUse.AddSample(ProfileCategory::Execute);
|
||||
|
||||
// Perform any neccessary mixing of outputs.
|
||||
for (auto &bufferMix : outputBufferMixes)
|
||||
for (auto&mixOp: this->mixOps)
|
||||
{
|
||||
float * PIPEDAL_RESTRICT outputBuffer = bufferMix.outputBuffer;
|
||||
float * PIPEDAL_RESTRICT inputBuffer = bufferMix.inputBuffers[0];
|
||||
for (size_t i = 0; i < framesRead; ++i)
|
||||
{
|
||||
outputBuffer[i] = inputBuffer[i];
|
||||
}
|
||||
for (size_t nInput = 1; nInput < bufferMix.inputBuffers.size(); ++nInput)
|
||||
{
|
||||
float * PIPEDAL_RESTRICT inputBuffer = bufferMix.inputBuffers[nInput];
|
||||
for (size_t i = 0; i < framesRead; ++i)
|
||||
{
|
||||
outputBuffer[i] += inputBuffer[i];
|
||||
}
|
||||
}
|
||||
mixOp(framesRead);
|
||||
}
|
||||
|
||||
// final downmix.
|
||||
// final format conversion.
|
||||
(this->*copyOutputFn)(framesRead);
|
||||
|
||||
if (this->driverHost)
|
||||
@@ -1939,23 +1913,6 @@ namespace pipedal
|
||||
}
|
||||
}
|
||||
}
|
||||
PIPEDAL_NON_INLINE float *AddMixBuffer(int64_t outputChannel, float *mixBuffer)
|
||||
{
|
||||
for (auto &bufferMix : outputBufferMixes)
|
||||
{
|
||||
if (bufferMix.outputChannel == outputChannel)
|
||||
{
|
||||
bufferMix.inputBuffers.push_back(mixBuffer);
|
||||
return bufferMix.outputBuffer;
|
||||
}
|
||||
}
|
||||
OutputBufferMix newMix;
|
||||
newMix.outputChannel = outputChannel;
|
||||
newMix.outputBuffer = devicePlaybackBuffers[outputChannel];
|
||||
newMix.inputBuffers.push_back(mixBuffer);
|
||||
outputBufferMixes.push_back(std::move(newMix));
|
||||
return devicePlaybackBuffers[outputChannel];
|
||||
}
|
||||
PIPEDAL_NON_INLINE void AllocateOutputChannels(
|
||||
const std::vector<int64_t> &channelSelection,
|
||||
std::vector<float *> &channelBuffers)
|
||||
@@ -1983,73 +1940,118 @@ namespace pipedal
|
||||
}
|
||||
}
|
||||
}
|
||||
PIPEDAL_NON_INLINE void AllocateOutputChannels(
|
||||
const std::vector<int64_t> &channelSelection,
|
||||
std::vector<float *> &channelBuffers,
|
||||
std::vector<float *> &vuBuffers,
|
||||
const std::set<int64_t> &summedChannels)
|
||||
{
|
||||
size_t nChannels = channelSelection.size();
|
||||
|
||||
if (nChannels == 0)
|
||||
|
||||
PIPEDAL_NON_INLINE void AllocateAuxChannels()
|
||||
{
|
||||
for (auto ix : channelSelection.auxInputChannels())
|
||||
{
|
||||
channelBuffers.resize(0);
|
||||
vuBuffers.resize(0);
|
||||
return;
|
||||
auxCaptureBuffers.push_back(this->deviceCaptureBuffers[ix]);
|
||||
}
|
||||
channelBuffers.resize(nChannels);
|
||||
vuBuffers.resize(nChannels);
|
||||
for (size_t i = 0; i < nChannels; ++i)
|
||||
for (auto ix : channelSelection.auxOutputChannels())
|
||||
{
|
||||
int64_t deviceChannel = channelSelection[i];
|
||||
if (deviceChannel == -1 || deviceChannel >= playbackChannels)
|
||||
{
|
||||
channelBuffers[i] = GetDiscardOutputBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!summedChannels.contains(deviceChannel))
|
||||
{
|
||||
vuBuffers[i] = channelBuffers[i] = this->devicePlaybackBuffers[deviceChannel];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Used once already. We need to mix down.
|
||||
float *mixBuffer = AllocateAudioBuffer();
|
||||
channelBuffers[i] = mixBuffer;
|
||||
vuBuffers[i] = AddMixBuffer(deviceChannel, mixBuffer);
|
||||
}
|
||||
}
|
||||
auxPlaybackBuffers.push_back(this->devicePlaybackBuffers[ix]);
|
||||
}
|
||||
}
|
||||
|
||||
std::set<int64_t> ComputeSummedChannels()
|
||||
using MixOp = std::function<void(size_t nFrames)>;
|
||||
std::vector<MixOp> mixOps;
|
||||
|
||||
PIPEDAL_NON_INLINE
|
||||
void AddMixCopyOp(float*inputBuffer, float*outputBuffer)
|
||||
{
|
||||
std::set<int64_t> usedOutputChannels;
|
||||
std::set<int64_t> result;
|
||||
for (auto ch : channelSelection.mainOutputChannels())
|
||||
{
|
||||
if (usedOutputChannels.contains(ch))
|
||||
mixOps.push_back([inputBuffer,outputBuffer](size_t nFrames) {
|
||||
float*PIPEDAL_RESTRICT pIn = inputBuffer;
|
||||
float*PIPEDAL_RESTRICT pOut = outputBuffer;
|
||||
for (size_t i = 0; i < nFrames; ++i)
|
||||
{
|
||||
result.insert(ch);
|
||||
pOut[i] = pIn[i];
|
||||
}
|
||||
else
|
||||
});
|
||||
}
|
||||
PIPEDAL_NON_INLINE
|
||||
void AddMixAddOp(float*inputBuffer, float*outputBuffer)
|
||||
{
|
||||
mixOps.push_back([inputBuffer,outputBuffer](size_t nFrames) {
|
||||
float*PIPEDAL_RESTRICT pIn = inputBuffer;
|
||||
float*PIPEDAL_RESTRICT pOut = outputBuffer;
|
||||
for (size_t i = 0; i < nFrames; ++i)
|
||||
{
|
||||
usedOutputChannels.insert(ch);
|
||||
pOut[i] += pIn[i];
|
||||
}
|
||||
});
|
||||
}
|
||||
PIPEDAL_NON_INLINE
|
||||
void AddMixCopyOp(float scale, float*inputBuffer, float*outputBuffer)
|
||||
{
|
||||
mixOps.push_back([scale,inputBuffer,outputBuffer](size_t nFrames) {
|
||||
float*PIPEDAL_RESTRICT pIn = inputBuffer;
|
||||
float*PIPEDAL_RESTRICT pOut = outputBuffer;
|
||||
for (size_t i = 0; i < nFrames; ++i)
|
||||
{
|
||||
pOut[i] = scale*pIn[i];
|
||||
}
|
||||
});
|
||||
}
|
||||
PIPEDAL_NON_INLINE
|
||||
void AddMixAddOp(float scale, float*inputBuffer, float*outputBuffer)
|
||||
{
|
||||
mixOps.push_back([scale,inputBuffer,outputBuffer](size_t nFrames) {
|
||||
float*PIPEDAL_RESTRICT pIn = inputBuffer;
|
||||
float*PIPEDAL_RESTRICT pOut = outputBuffer;
|
||||
for (size_t i = 0; i < nFrames; ++i)
|
||||
{
|
||||
pOut[i] += scale*pIn[i];
|
||||
}
|
||||
});
|
||||
}
|
||||
PIPEDAL_NON_INLINE void AddMixOps()
|
||||
{
|
||||
std::set<size_t> usedOutputChannels;
|
||||
|
||||
for (size_t i = 0; i < this->channelSelection.mainOutputChannels().size(); ++i) {
|
||||
size_t outputChannel = this->channelSelection.mainOutputChannels()[i];
|
||||
AddMixCopyOp(this->mainPlaybackBuffers[i],this->devicePlaybackBuffers[outputChannel]);
|
||||
usedOutputChannels.insert(outputChannel);
|
||||
}
|
||||
for (auto ch : channelSelection.auxOutputChannels())
|
||||
if (channelSelection.auxInputChannels().size() <= channelSelection.auxOutputChannels().size())
|
||||
{
|
||||
if (usedOutputChannels.contains(ch))
|
||||
for (size_t i = 0; i < this->channelSelection.auxOutputChannels().size(); ++i)
|
||||
{
|
||||
result.insert(ch);
|
||||
size_t outputChannel = this->channelSelection.auxOutputChannels()[i];
|
||||
size_t inputChannel;
|
||||
if (this->channelSelection.auxInputChannels().size() == 0) break;
|
||||
if (i >= this->channelSelection.auxInputChannels().size()) {
|
||||
inputChannel = 0;
|
||||
} else {
|
||||
inputChannel = this->channelSelection.auxInputChannels()[i];
|
||||
}
|
||||
if (outputChannel >= this->devicePlaybackBuffers.size())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (usedOutputChannels.contains(outputChannel))
|
||||
{
|
||||
AddMixAddOp(this->deviceCaptureBuffers[inputChannel],this->devicePlaybackBuffers[outputChannel]);
|
||||
} else {
|
||||
AddMixCopyOp(this->deviceCaptureBuffers[inputChannel],this->devicePlaybackBuffers[outputChannel]);
|
||||
}
|
||||
usedOutputChannels.insert(outputChannel);
|
||||
}
|
||||
else
|
||||
} else if (channelSelection.auxInputChannels().size() >= 2 && channelSelection.auxOutputChannels().size() == 1) {
|
||||
float scale = 1.0/channelSelection.auxInputChannels().size();
|
||||
for (size_t i = 0; i < this->channelSelection.auxOutputChannels().size(); ++i)
|
||||
{
|
||||
usedOutputChannels.insert(ch);
|
||||
size_t outputChannel = this->channelSelection.auxOutputChannels()[i];
|
||||
if (usedOutputChannels.contains(outputChannel))
|
||||
{
|
||||
AddMixAddOp(scale,this->auxCaptureBuffers[0],this->devicePlaybackBuffers[outputChannel]);
|
||||
} else {
|
||||
AddMixCopyOp(scale,this->auxCaptureBuffers[0],this->devicePlaybackBuffers[outputChannel]);
|
||||
}
|
||||
usedOutputChannels.insert(outputChannel);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
bool activated = false;
|
||||
@@ -2078,7 +2080,6 @@ namespace pipedal
|
||||
devicePlaybackBuffers[i] = AllocateAudioBuffer();
|
||||
}
|
||||
|
||||
std::set<int64_t> summedOutputChannels = ComputeSummedChannels();
|
||||
|
||||
AllocateInputChannels(
|
||||
channelSelection.mainInputChannels(),
|
||||
@@ -2086,25 +2087,9 @@ namespace pipedal
|
||||
AllocateOutputChannels(
|
||||
channelSelection.mainOutputChannels(),
|
||||
this->mainPlaybackBuffers);
|
||||
AllocateOutputChannels(
|
||||
channelSelection.mainOutputChannels(),
|
||||
this->mainInsertPlaybackBuffers,
|
||||
this->mainVuPlaybackBuffers,
|
||||
summedOutputChannels);
|
||||
AllocateInputChannels(
|
||||
channelSelection.auxInputChannels(),
|
||||
this->auxCaptureBuffers);
|
||||
AllocateOutputChannels(
|
||||
channelSelection.auxOutputChannels(),
|
||||
this->auxPlaybackBuffers,
|
||||
this->auxVuPlaybackBuffers,
|
||||
summedOutputChannels);
|
||||
AllocateInputChannels(
|
||||
channelSelection.sendInputChannels(),
|
||||
this->sendCaptureBuffers);
|
||||
AllocateOutputChannels(
|
||||
channelSelection.sendOutputChannels(),
|
||||
this->sendPlaybackBuffers);
|
||||
|
||||
AllocateAuxChannels();
|
||||
AddMixOps();
|
||||
|
||||
audioThread = std::make_unique<std::jthread>([this]()
|
||||
{ AudioThread(); });
|
||||
@@ -2189,15 +2174,9 @@ namespace pipedal
|
||||
|
||||
virtual std::vector<float *> &MainInputBuffers() override { return this->mainCaptureBuffers; }
|
||||
virtual std::vector<float *> &MainOutputBuffers() override { return this->mainPlaybackBuffers; }
|
||||
virtual std::vector<float *> &MainInsertOutputBuffers() override { return this->mainInsertPlaybackBuffers; }
|
||||
virtual std::vector<float *> &MainVuOutputBuffers() override { return this->mainVuPlaybackBuffers; }
|
||||
|
||||
virtual std::vector<float *> &AuxInputBuffers() override { return this->auxCaptureBuffers; }
|
||||
virtual std::vector<float *> &AuxOutputBuffers() override { return this->auxPlaybackBuffers; }
|
||||
virtual std::vector<float *> &AuxVuOutputBuffers() override { return this->auxVuPlaybackBuffers; }
|
||||
|
||||
virtual const std::vector<float *> &SendInputBuffers() const override { return this->sendCaptureBuffers; }
|
||||
virtual const std::vector<float *> &SendOutputBuffers() const override { return this->sendPlaybackBuffers; }
|
||||
|
||||
virtual size_t MainInputBufferCount() const { return mainCaptureBuffers.size(); }
|
||||
virtual float *GetMainInputBuffer(size_t channel) override
|
||||
@@ -2221,16 +2200,6 @@ namespace pipedal
|
||||
{
|
||||
return auxPlaybackBuffers[channel];
|
||||
}
|
||||
virtual size_t SendInputBufferCount() const { return sendCaptureBuffers.size(); }
|
||||
virtual float *GetSendInputBuffer(size_t channel) override
|
||||
{
|
||||
return sendCaptureBuffers[channel];
|
||||
}
|
||||
virtual size_t SendOutputBufferCount() const { return sendPlaybackBuffers.size(); }
|
||||
virtual float *GetSendOutputBuffer(size_t channel) override
|
||||
{
|
||||
return sendPlaybackBuffers[channel];
|
||||
}
|
||||
|
||||
virtual size_t GetMidiInputEventCount() override
|
||||
{
|
||||
@@ -2246,20 +2215,6 @@ namespace pipedal
|
||||
{
|
||||
return mainPlaybackBuffers[channel];
|
||||
}
|
||||
virtual size_t MainInsertOutputBufferCount() const override
|
||||
{
|
||||
return mainInsertPlaybackBuffers.size();
|
||||
}
|
||||
virtual float *GetMainInsertOutputBuffer(size_t channel) const
|
||||
{
|
||||
if (channel >= (int64_t)mainCaptureBuffers.size())
|
||||
{
|
||||
throw std::runtime_error("GetMainInsertOutputBuffer: Argument out of range.");
|
||||
}
|
||||
|
||||
return mainInsertPlaybackBuffers[channel];
|
||||
}
|
||||
|
||||
float *AllocateAudioBuffer()
|
||||
{
|
||||
std::vector<float> buffer;
|
||||
@@ -2274,8 +2229,6 @@ namespace pipedal
|
||||
mainPlaybackBuffers.clear();
|
||||
auxCaptureBuffers.clear();
|
||||
auxPlaybackBuffers.clear();
|
||||
sendCaptureBuffers.clear();
|
||||
sendPlaybackBuffers.clear();
|
||||
zeroInputBuffer = nullptr;
|
||||
discardOutputBuffer = nullptr;
|
||||
allocatedBuffers.clear();
|
||||
|
||||
+10
-22
@@ -64,42 +64,30 @@ namespace pipedal {
|
||||
|
||||
|
||||
virtual std::vector<float*> &DeviceInputBuffers() = 0;
|
||||
virtual std::vector<float*> &DeviceOutputBuffers() = 0;
|
||||
|
||||
virtual std::vector<float*> &MainInputBuffers() = 0;
|
||||
virtual std::vector<float*> &MainOutputBuffers() = 0;
|
||||
virtual std::vector<float*>&MainInsertOutputBuffers() = 0;
|
||||
virtual std::vector<float*>&MainVuOutputBuffers() = 0;
|
||||
|
||||
virtual std::vector<float*>&AuxInputBuffers() = 0;
|
||||
virtual std::vector<float*>&AuxOutputBuffers() = 0;
|
||||
virtual std::vector<float*>&AuxVuOutputBuffers() = 0;
|
||||
|
||||
virtual size_t DeviceInputBufferCount() const = 0;
|
||||
virtual size_t DeviceOutputBufferCount() const = 0;
|
||||
virtual float* GetDeviceInputBuffer(size_t channel) const = 0;
|
||||
|
||||
virtual std::vector<float*> &DeviceOutputBuffers() = 0;
|
||||
virtual size_t DeviceOutputBufferCount() const = 0;
|
||||
virtual float* GetDeviceOutputBuffer(size_t channel) const = 0;
|
||||
|
||||
virtual std::vector<float*> &MainInputBuffers() = 0;
|
||||
virtual size_t MainInputBufferCount() const = 0;
|
||||
virtual float*GetMainInputBuffer(size_t channel) = 0;
|
||||
|
||||
virtual std::vector<float*> &MainOutputBuffers() = 0;
|
||||
virtual size_t MainOutputBufferCount() const = 0;
|
||||
virtual float*GetMainOutputBuffer(size_t channel) = 0;
|
||||
|
||||
virtual size_t MainInsertOutputBufferCount() const = 0;
|
||||
virtual float*GetMainInsertOutputBuffer(size_t channe) const = 0;
|
||||
|
||||
|
||||
|
||||
virtual std::vector<float*>&AuxInputBuffers() = 0;
|
||||
virtual std::vector<float*>&AuxOutputBuffers() = 0;
|
||||
virtual size_t AuxInputBufferCount() const = 0;
|
||||
|
||||
virtual float*GetAuxInputBuffer(size_t channel) = 0;
|
||||
virtual size_t AuxOutputBufferCount() const = 0;
|
||||
virtual float*GetAuxOutputBuffer(size_t channel) = 0;
|
||||
|
||||
virtual size_t SendInputBufferCount() const = 0;
|
||||
virtual float*GetSendInputBuffer(size_t channel) = 0;
|
||||
virtual const std::vector<float*>&SendInputBuffers() const = 0;
|
||||
virtual size_t SendOutputBufferCount() const = 0;
|
||||
virtual float*GetSendOutputBuffer(size_t channel) = 0;
|
||||
virtual const std::vector<float*>&SendOutputBuffers() const = 0;
|
||||
|
||||
virtual float*GetZeroInputBuffer() = 0;
|
||||
virtual float*GetDiscardOutputBuffer() = 0;
|
||||
|
||||
+125
-404
@@ -532,7 +532,6 @@ private:
|
||||
|
||||
std::vector<std::shared_ptr<Lv2Pedalboard>> activePedalboards; // pedalboards that have been sent to the audio queue.
|
||||
Lv2Pedalboard *realtimeActivePedalboard = nullptr;
|
||||
Lv2RoutingInserts realtimeRoutingInserts;
|
||||
|
||||
uint32_t sampleRate = 0;
|
||||
uint64_t currentSample = 0;
|
||||
@@ -682,7 +681,6 @@ private:
|
||||
}
|
||||
|
||||
void processMonitorPortSubscriptions(
|
||||
PedalboardType pedalboardType,
|
||||
Lv2Pedalboard *pedalboard,
|
||||
uint32_t nframes)
|
||||
{
|
||||
@@ -690,11 +688,6 @@ private:
|
||||
{
|
||||
auto &portSubscription = realtimeMonitorPortSubscriptions->subscriptions[i];
|
||||
|
||||
if (pedalboardType != portSubscription.pedalboardType)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
portSubscription.samplesToNextCallback -= portSubscription.sampleRate;
|
||||
if (portSubscription.samplesToNextCallback < 0)
|
||||
{
|
||||
@@ -906,47 +899,6 @@ private:
|
||||
|
||||
return false; // signal to caller that the effect has been replaced, and processing needs to start again.
|
||||
}
|
||||
case RingBufferCommand::ReplaceRoutingInserts:
|
||||
{
|
||||
Lv2RoutingInserts body;
|
||||
realtimeReader.readComplete(&body);
|
||||
|
||||
auto oldValue = this->realtimeRoutingInserts;
|
||||
this->realtimeRoutingInserts = body;
|
||||
|
||||
realtimeWriter.RoutingInsertsReplaced(oldValue);
|
||||
|
||||
// invalidate the possibly no-good subscriptions. Model will update them shortly.
|
||||
freeRealtimeVuConfiguration();
|
||||
freeRealtimeMonitorPortSubscriptions();
|
||||
cancelParameterRequests();
|
||||
|
||||
Lv2Pedalboard *mainInserts = body.mainInserts;
|
||||
if (mainInserts)
|
||||
{
|
||||
mainInserts->ResetAtomBuffers();
|
||||
// issue patch gets for all writable path properties.
|
||||
for (auto pEffect : mainInserts->GetEffects())
|
||||
{
|
||||
pEffect->RequestAllPathPatchProperties();
|
||||
}
|
||||
mainInserts->UpdateAudioPorts();
|
||||
}
|
||||
Lv2Pedalboard *auxInserts = body.auxInserts;
|
||||
if (auxInserts)
|
||||
{
|
||||
auxInserts->ResetAtomBuffers();
|
||||
// issue patch gets for all writable path properties.
|
||||
for (auto pEffect : auxInserts->GetEffects())
|
||||
{
|
||||
pEffect->RequestAllPathPatchProperties();
|
||||
}
|
||||
auxInserts->UpdateAudioPorts();
|
||||
}
|
||||
reEntered = false;
|
||||
|
||||
return false; // signal to caller that the effect has been replaced, and processing needs to start again.
|
||||
}
|
||||
default:
|
||||
throw PiPedalStateException("Unknown Ringbuffer command.");
|
||||
}
|
||||
@@ -1162,66 +1114,32 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
bool GetAudioDriverBuffers(PedalboardType pedalboardType,
|
||||
float **inputBuffers,
|
||||
float **outputBuffers)
|
||||
bool GetMainDriverBuffers(
|
||||
float **inputBuffers,
|
||||
float **outputBuffers)
|
||||
{
|
||||
bool buffersValid = true;
|
||||
if (!audioDriver)
|
||||
for (int i = 0; i < audioDriver->MainInputBufferCount(); ++i)
|
||||
{
|
||||
inputBuffers[0] = nullptr;
|
||||
outputBuffers[0] = nullptr;
|
||||
return false;
|
||||
float *input = (float *)audioDriver->GetMainInputBuffer(i);
|
||||
if (input == nullptr)
|
||||
{
|
||||
buffersValid = false;
|
||||
}
|
||||
inputBuffers[i] = input;
|
||||
}
|
||||
switch (pedalboardType)
|
||||
inputBuffers[audioDriver->MainInputBufferCount()] = nullptr;
|
||||
|
||||
for (int i = 0; i < audioDriver->MainOutputBufferCount(); ++i)
|
||||
{
|
||||
case PedalboardType::MainPedalboard:
|
||||
for (int i = 0; i < audioDriver->MainInputBufferCount(); ++i)
|
||||
float *output = audioDriver->GetMainOutputBuffer(i);
|
||||
if (output == nullptr)
|
||||
{
|
||||
float *input = (float *)audioDriver->GetMainInputBuffer(i);
|
||||
if (input == nullptr)
|
||||
{
|
||||
buffersValid = false;
|
||||
}
|
||||
inputBuffers[i] = input;
|
||||
buffersValid = false;
|
||||
}
|
||||
inputBuffers[audioDriver->MainInputBufferCount()] = nullptr;
|
||||
|
||||
for (int i = 0; i < audioDriver->MainOutputBufferCount(); ++i)
|
||||
{
|
||||
float *output = audioDriver->GetMainOutputBuffer(i);
|
||||
if (output == nullptr)
|
||||
{
|
||||
buffersValid = false;
|
||||
}
|
||||
outputBuffers[i] = output;
|
||||
}
|
||||
outputBuffers[audioDriver->MainOutputBufferCount()] = nullptr;
|
||||
break;
|
||||
case PedalboardType::MainInserts:
|
||||
for (int i = 0; i < audioDriver->MainInputBufferCount(); ++i)
|
||||
{
|
||||
float *input = (float *)audioDriver->GetMainInputBuffer(i);
|
||||
if (input == nullptr)
|
||||
{
|
||||
buffersValid = false;
|
||||
}
|
||||
inputBuffers[i] = input;
|
||||
}
|
||||
inputBuffers[audioDriver->MainInputBufferCount()] = nullptr;
|
||||
|
||||
for (int i = 0; i < audioDriver->MainOutputBufferCount(); ++i)
|
||||
{
|
||||
float *output = audioDriver->GetMainOutputBuffer(i);
|
||||
if (output == nullptr)
|
||||
{
|
||||
buffersValid = false;
|
||||
}
|
||||
outputBuffers[i] = output;
|
||||
}
|
||||
outputBuffers[audioDriver->MainOutputBufferCount()] = nullptr;
|
||||
break;
|
||||
outputBuffers[i] = output;
|
||||
}
|
||||
outputBuffers[audioDriver->MainOutputBufferCount()] = nullptr;
|
||||
return buffersValid;
|
||||
}
|
||||
void ProcessGlobalMidiInput()
|
||||
@@ -1263,39 +1181,18 @@ private:
|
||||
Lv2Log::info("Audio thread terminated.");
|
||||
}
|
||||
|
||||
PIPEDAL_NON_INLINE void ProcessLv2Pedalboard(PedalboardType pedalboardType, size_t nframes)
|
||||
PIPEDAL_NON_INLINE void ProcessLv2Pedalboard(size_t nframes)
|
||||
{
|
||||
Lv2Pedalboard *pedalboard = nullptr;
|
||||
|
||||
std::vector<float *> *pInputBuffers;
|
||||
std::vector<float *> *pOutputBuffers;
|
||||
switch (pedalboardType)
|
||||
{
|
||||
case PedalboardType::MainPedalboard:
|
||||
pedalboard = this->realtimeActivePedalboard;
|
||||
pInputBuffers = &(audioDriver->MainInputBuffers());
|
||||
if (this->realtimeRoutingInserts.mainInserts != nullptr)
|
||||
{
|
||||
pOutputBuffers = &(audioDriver->MainOutputBuffers());
|
||||
}
|
||||
else
|
||||
{
|
||||
pOutputBuffers = &(audioDriver->MainInsertOutputBuffers());
|
||||
}
|
||||
break;
|
||||
case PedalboardType::MainInserts:
|
||||
pedalboard = this->realtimeActivePedalboard;
|
||||
pInputBuffers = &(audioDriver->MainInputBuffers());
|
||||
|
||||
pOutputBuffers = &(audioDriver->MainOutputBuffers());
|
||||
|
||||
pedalboard = this->realtimeRoutingInserts.mainInserts;
|
||||
pInputBuffers = &(audioDriver->MainOutputBuffers());
|
||||
pOutputBuffers = &(audioDriver->MainInsertOutputBuffers());
|
||||
break;
|
||||
case PedalboardType::AuxInserts:
|
||||
pedalboard = this->realtimeRoutingInserts.auxInserts;
|
||||
pInputBuffers = &(audioDriver->AuxInputBuffers());
|
||||
pOutputBuffers = &(audioDriver->AuxOutputBuffers());
|
||||
break;
|
||||
}
|
||||
if (pInputBuffers->size() == 0 || pOutputBuffers->size() == 0)
|
||||
if (pedalboard == nullptr || pInputBuffers->size() == 0 || pOutputBuffers->size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1320,62 +1217,26 @@ private:
|
||||
|
||||
if (this->realtimeMonitorPortSubscriptions != nullptr)
|
||||
{
|
||||
processMonitorPortSubscriptions(pedalboardType, pedalboard, nframes);
|
||||
processMonitorPortSubscriptions(pedalboard, nframes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (pedalboardType)
|
||||
// zero output buffers.
|
||||
size_t ix = 0;
|
||||
while (outputBuffers[ix])
|
||||
{
|
||||
case PedalboardType::MainPedalboard:
|
||||
{
|
||||
// zero output buffers.
|
||||
size_t ix = 0;
|
||||
while (outputBuffers[ix])
|
||||
float *outputBuffer = outputBuffers[ix];
|
||||
for (size_t i = 0; i < nframes; ++i)
|
||||
{
|
||||
float *outputBuffer = outputBuffers[ix];
|
||||
for (size_t i = 0; i < nframes; ++i)
|
||||
{
|
||||
outputBuffer[i] = 0;
|
||||
}
|
||||
++ix;
|
||||
outputBuffer[i] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PedalboardType::MainInserts:
|
||||
// do nothing. Main pedalboard wrote to Main insert outputs directly in this case.
|
||||
break;
|
||||
case PedalboardType::AuxInserts:
|
||||
// Copy inputs to outputs.
|
||||
{
|
||||
if (outputBuffers[0] != nullptr && inputBuffers[0] != nullptr)
|
||||
{
|
||||
float *PIPEDAL_RESTRICT outputBuffer = outputBuffers[0];
|
||||
float *PIPEDAL_RESTRICT inputBuffer = inputBuffers[0];
|
||||
for (size_t i = 0; i < nframes; ++i)
|
||||
{
|
||||
outputBuffer[i] = inputBuffer[i];
|
||||
}
|
||||
}
|
||||
if (outputBuffers[1] != nullptr && inputBuffers[0] != nullptr)
|
||||
{
|
||||
float *PIPEDAL_RESTRICT outputBuffer = outputBuffers[1];
|
||||
float *PIPEDAL_RESTRICT inputBuffer = inputBuffers[1] != nullptr ? inputBuffers[1] : inputBuffers[0];
|
||||
for (size_t i = 0; i < nframes; ++i)
|
||||
{
|
||||
outputBuffer[i] = inputBuffer[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PedalboardType::Invalid:
|
||||
throw std::runtime_error("Invalid argument.");
|
||||
break;
|
||||
++ix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GetMasterChannels(PedalboardType pedalboardType, float **masterInputBuffers, float **masterOutputBuffers)
|
||||
void GetMasterChannels(float **masterInputBuffers, float **masterOutputBuffers)
|
||||
{
|
||||
size_t inputIx = 0;
|
||||
size_t outputIx = 0;
|
||||
@@ -1385,90 +1246,72 @@ private:
|
||||
masterOutputBuffers[0] = nullptr;
|
||||
masterOutputBuffers[1] = nullptr;
|
||||
|
||||
const ChannelSelection &channelSelection = audioDriver->GetChannelSelection();
|
||||
|
||||
switch (pedalboardType)
|
||||
for (auto nChannel : channelSelection.mainInputChannels())
|
||||
{
|
||||
case PedalboardType::MainPedalboard:
|
||||
for (auto nChannel : channelSelection.mainInputChannels())
|
||||
masterInputBuffers[inputIx++] = audioDriver->GetDeviceInputBuffer(nChannel);
|
||||
}
|
||||
for (auto nChannel : channelSelection.mainOutputChannels())
|
||||
{
|
||||
masterOutputBuffers[outputIx++] = audioDriver->GetDeviceOutputBuffer(nChannel);
|
||||
}
|
||||
}
|
||||
inline void AccumulateVu(float*result, size_t nFrames, float*buffer)
|
||||
{
|
||||
float maxVal = *result;
|
||||
for (size_t i = 0; i < nFrames; ++i)
|
||||
{
|
||||
float v = std::fabs(buffer[i]);
|
||||
if (v > maxVal)
|
||||
{
|
||||
masterInputBuffers[inputIx++] = audioDriver->GetDeviceInputBuffer(nChannel);
|
||||
maxVal = v;
|
||||
}
|
||||
for (auto nChannel : channelSelection.mainOutputChannels())
|
||||
{
|
||||
masterOutputBuffers[outputIx++] = audioDriver->GetDeviceOutputBuffer(nChannel);
|
||||
}
|
||||
break;
|
||||
case PedalboardType::MainInserts:
|
||||
if (this->realtimeActivePedalboard)
|
||||
{
|
||||
for (float *buffer : this->realtimeActivePedalboard->GetoutputBuffers())
|
||||
{
|
||||
masterInputBuffers[inputIx++] = buffer;
|
||||
}
|
||||
for (auto nChannel : channelSelection.mainOutputChannels())
|
||||
{
|
||||
masterOutputBuffers[outputIx++] = audioDriver->GetDeviceOutputBuffer(nChannel);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PedalboardType::AuxInserts:
|
||||
for (auto nChannel : channelSelection.auxInputChannels())
|
||||
{
|
||||
switch (nChannel)
|
||||
{
|
||||
case ChannelRouterSettings::MAIN_OUT_LEFT_CHANNEL:
|
||||
{
|
||||
float *pBuffer = nullptr;
|
||||
if (this->realtimeActivePedalboard)
|
||||
{
|
||||
auto &mainOutputBuffers = realtimeActivePedalboard->GetoutputBuffers();
|
||||
if (mainOutputBuffers.size() >= 1)
|
||||
{
|
||||
pBuffer = mainOutputBuffers[0];
|
||||
}
|
||||
}
|
||||
if (pBuffer == nullptr)
|
||||
{
|
||||
pBuffer = audioDriver->GetZeroInputBuffer();
|
||||
}
|
||||
masterInputBuffers[inputIx++] = pBuffer;
|
||||
}
|
||||
break;
|
||||
case ChannelRouterSettings::MAIN_OUT_RIGHT_CHANNEL:
|
||||
{
|
||||
float *pBuffer = nullptr;
|
||||
if (this->realtimeActivePedalboard)
|
||||
{
|
||||
auto &mainOutputBuffers = realtimeActivePedalboard->GetoutputBuffers();
|
||||
if (mainOutputBuffers.size() == 1)
|
||||
{
|
||||
pBuffer = mainOutputBuffers[0];
|
||||
}
|
||||
else if (mainOutputBuffers.size() == 2)
|
||||
{
|
||||
pBuffer = mainOutputBuffers[0];
|
||||
}
|
||||
}
|
||||
if (pBuffer == nullptr)
|
||||
{
|
||||
pBuffer = audioDriver->GetZeroInputBuffer();
|
||||
}
|
||||
masterInputBuffers[inputIx++] = pBuffer;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
masterInputBuffers[outputIx++] = audioDriver->GetDeviceInputBuffer(nChannel);
|
||||
};
|
||||
}
|
||||
for (auto nChannel : channelSelection.auxOutputChannels())
|
||||
{
|
||||
masterOutputBuffers[outputIx++] = audioDriver->GetDeviceOutputBuffer(nChannel);
|
||||
}
|
||||
break;
|
||||
}
|
||||
*result = maxVal;
|
||||
}
|
||||
void AccumulateVuInputs(size_t nFrames,VuUpdateX&vuUpdate, const std::vector<int64_t>&channels)
|
||||
{
|
||||
if (channels.size() == 0) return;
|
||||
|
||||
default:
|
||||
throw std::runtime_error("GetMasterChannels: Argument out of range.");
|
||||
AccumulateVu(&vuUpdate.inputMaxValueL_,nFrames,this->audioDriver->DeviceInputBuffers()[channels[0]]);
|
||||
|
||||
if (channels.size() == 2) {
|
||||
AccumulateVu(&vuUpdate.inputMaxValueR_,nFrames,this->audioDriver->DeviceInputBuffers()[channels[1]]);
|
||||
}
|
||||
}
|
||||
void AccumulateVuOutputs(size_t nFrames,VuUpdateX&vuUpdate, const std::vector<int64_t>&channels)
|
||||
{
|
||||
if (channels.size() == 0) return;
|
||||
AccumulateVu(&vuUpdate.outputMaxValueL_,nFrames,this->audioDriver->DeviceOutputBuffers()[channels[0]]);
|
||||
if (channels.size() >= 2) {
|
||||
AccumulateVu(&vuUpdate.outputMaxValueR_,nFrames,this->audioDriver->DeviceOutputBuffers()[channels[1]]);
|
||||
}
|
||||
}
|
||||
void ComputeMasterVus(size_t nFrames) {
|
||||
if (this->realtimeVuBuffers)
|
||||
{
|
||||
float** audioBuffers;
|
||||
|
||||
for (auto& vuUpdate: this->realtimeVuBuffers->vuUpdateWorkingData)
|
||||
{
|
||||
if (vuUpdate.instanceId_ < 0)
|
||||
{
|
||||
switch (vuUpdate.instanceId_)
|
||||
{
|
||||
case Pedalboard::START_CONTROL_ID:
|
||||
AccumulateVuInputs(nFrames, vuUpdate, pHost->GetChannelSelection().mainInputChannels());
|
||||
break;
|
||||
case Pedalboard::END_CONTROL_ID:
|
||||
AccumulateVuOutputs(nFrames, vuUpdate, pHost->GetChannelSelection().mainOutputChannels());
|
||||
break;
|
||||
case Pedalboard::AUX_START_CONTROL_ID:
|
||||
AccumulateVuInputs(nFrames, vuUpdate, pHost->GetChannelSelection().auxInputChannels());
|
||||
break;
|
||||
case Pedalboard::AUX_END_CONTROL_ID:
|
||||
AccumulateVuOutputs(nFrames, vuUpdate, pHost->GetChannelSelection().auxOutputChannels());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool OnRealtimeUpdateDeviceVus(size_t nFrames) override
|
||||
@@ -1481,20 +1324,9 @@ private:
|
||||
|
||||
if (this->realtimeActivePedalboard != nullptr)
|
||||
{
|
||||
GetMasterChannels(PedalboardType::MainPedalboard, masterInputBuffers, masterOutputBuffers);
|
||||
realtimeActivePedalboard->ComputeVus(this->realtimeVuBuffers, nFrames, masterInputBuffers, masterOutputBuffers);
|
||||
realtimeActivePedalboard->ComputeVus(this->realtimeVuBuffers, nFrames);
|
||||
}
|
||||
if (this->realtimeRoutingInserts.mainInserts)
|
||||
{
|
||||
GetMasterChannels(PedalboardType::MainInserts, masterInputBuffers, masterOutputBuffers);
|
||||
this->realtimeRoutingInserts.mainInserts->ComputeVus(this->realtimeVuBuffers, nFrames, masterInputBuffers, masterOutputBuffers);
|
||||
}
|
||||
if (this->realtimeRoutingInserts.auxInserts)
|
||||
{
|
||||
GetMasterChannels(PedalboardType::AuxInserts, masterInputBuffers, masterOutputBuffers);
|
||||
this->realtimeRoutingInserts.auxInserts->ComputeVus(this->realtimeVuBuffers, nFrames, masterInputBuffers, masterOutputBuffers);
|
||||
}
|
||||
|
||||
ComputeMasterVus(nFrames);
|
||||
// periodically send updates.
|
||||
realtimeVuSamplesRemaining -= nFrames;
|
||||
if (realtimeVuSamplesRemaining <= 0)
|
||||
@@ -1517,14 +1349,6 @@ private:
|
||||
{
|
||||
pedalboard->ResetAtomBuffers();
|
||||
}
|
||||
if (this->realtimeRoutingInserts.auxInserts)
|
||||
{
|
||||
this->realtimeRoutingInserts.auxInserts->ResetAtomBuffers();
|
||||
}
|
||||
if (this->realtimeRoutingInserts.mainInserts)
|
||||
{
|
||||
this->realtimeRoutingInserts.mainInserts->ResetAtomBuffers();
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
@@ -1542,12 +1366,7 @@ private:
|
||||
{
|
||||
ProcessGlobalMidiInput();
|
||||
}
|
||||
ProcessLv2Pedalboard(PedalboardType::MainPedalboard, nframes);
|
||||
if (this->realtimeRoutingInserts.mainInserts != nullptr) // prevent zero-ing of main outputs if there's no mainInserts
|
||||
{
|
||||
ProcessLv2Pedalboard(PedalboardType::MainInserts, nframes);
|
||||
}
|
||||
ProcessLv2Pedalboard(PedalboardType::AuxInserts, nframes);
|
||||
ProcessLv2Pedalboard(nframes);
|
||||
|
||||
if (pParameterRequests != nullptr)
|
||||
{
|
||||
@@ -1861,19 +1680,6 @@ public:
|
||||
hostReader.read(&body);
|
||||
OnActivePedalboardReleased(body.oldEffect);
|
||||
}
|
||||
else if (command == RingBufferCommand::RoutingInsertsReplaced)
|
||||
{
|
||||
Lv2RoutingInserts body;
|
||||
hostReader.read(&body);
|
||||
if (body.mainInserts)
|
||||
{
|
||||
OnActivePedalboardReleased(body.mainInserts);
|
||||
}
|
||||
if (body.auxInserts)
|
||||
{
|
||||
OnActivePedalboardReleased(body.auxInserts);
|
||||
}
|
||||
}
|
||||
else if (command == RingBufferCommand::FreeSnapshot)
|
||||
{
|
||||
IndexedSnapshot *snapshot;
|
||||
@@ -2099,23 +1905,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void SetChannelRoutingInserts(
|
||||
const std::shared_ptr<Lv2Pedalboard> &mainInserts,
|
||||
const std::shared_ptr<Lv2Pedalboard> &auxInserts) override
|
||||
{
|
||||
if (active && mainInserts)
|
||||
{
|
||||
mainInserts->Activate();
|
||||
this->activePedalboards.push_back(mainInserts);
|
||||
}
|
||||
if (active && auxInserts)
|
||||
{
|
||||
auxInserts->Activate();
|
||||
this->activePedalboards.push_back(auxInserts);
|
||||
}
|
||||
Lv2RoutingInserts routingInserts{mainInserts : mainInserts.get(), auxInserts : auxInserts.get()};
|
||||
hostWriter.ReplaceRoutingInserts(routingInserts);
|
||||
}
|
||||
|
||||
virtual void SetBypass(uint64_t instanceId, bool enabled)
|
||||
{
|
||||
@@ -2233,63 +2022,31 @@ public:
|
||||
|
||||
PIPEDAL_NON_INLINE RealtimePedalboardItemIndex GetRealtimeItemIndex(int64_t instanceId)
|
||||
{
|
||||
PedalboardType instanceType = Pedalboard::GetPedalboardTypeFromInstanceId(instanceId);
|
||||
int64_t index = -1;
|
||||
switch (instanceType)
|
||||
if (this->currentPedalboard)
|
||||
{
|
||||
case PedalboardType::MainPedalboard:
|
||||
if (this->currentPedalboard)
|
||||
if (instanceId == Pedalboard::START_CONTROL_ID)
|
||||
{
|
||||
if (instanceId == Pedalboard::START_CONTROL_ID)
|
||||
{
|
||||
index = Pedalboard::START_CONTROL_ID;
|
||||
}
|
||||
else if (instanceId == Pedalboard::END_CONTROL_ID)
|
||||
{
|
||||
index = Pedalboard::END_CONTROL_ID;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = this->currentPedalboard->GetIndexOfInstanceId(instanceId);
|
||||
}
|
||||
index = Pedalboard::START_CONTROL_ID;
|
||||
}
|
||||
break;
|
||||
case PedalboardType::MainInserts:
|
||||
if (this->currentMainInsertPedalboard)
|
||||
else if (instanceId == Pedalboard::END_CONTROL_ID)
|
||||
{
|
||||
if (instanceId == Pedalboard::MAIN_INSERT_START_CONTROL_ID)
|
||||
{
|
||||
index = Pedalboard::MAIN_INSERT_START_CONTROL_ID;
|
||||
}
|
||||
else if (instanceId == Pedalboard::MAIN_INSERT_END_CONTROL_ID)
|
||||
{
|
||||
index = Pedalboard::END_CONTROL_ID;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = this->currentMainInsertPedalboard->GetIndexOfInstanceId(instanceId);
|
||||
}
|
||||
index = Pedalboard::END_CONTROL_ID;
|
||||
}
|
||||
break;
|
||||
case PedalboardType::AuxInserts:
|
||||
if (this->currentAuxInsertPedalboard)
|
||||
else if (instanceId == Pedalboard::AUX_START_CONTROL_ID)
|
||||
{
|
||||
if (instanceId == Pedalboard::AUX_INSERT_START_CONTROL_ID)
|
||||
{
|
||||
index = Pedalboard::START_CONTROL_ID;
|
||||
}
|
||||
else if (instanceId == Pedalboard::AUX_INSERT_END_CONTROL_ID)
|
||||
{
|
||||
index = Pedalboard::END_CONTROL_ID;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = this->currentAuxInsertPedalboard->GetIndexOfInstanceId(instanceId);
|
||||
}
|
||||
index = Pedalboard::AUX_START_CONTROL_ID;
|
||||
}
|
||||
else if (instanceId == Pedalboard::AUX_END_CONTROL_ID)
|
||||
{
|
||||
index = Pedalboard::AUX_END_CONTROL_ID;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = this->currentPedalboard->GetIndexOfInstanceId(instanceId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
RealtimePedalboardItemIndex result{instanceType, index};
|
||||
RealtimePedalboardItemIndex result{index};
|
||||
return result;
|
||||
}
|
||||
virtual void SetVuSubscriptions(const std::vector<int64_t> &instanceIds)
|
||||
@@ -2310,39 +2067,21 @@ public:
|
||||
for (size_t i = 0; i < instanceIds.size(); ++i)
|
||||
{
|
||||
int64_t instanceId = instanceIds[i];
|
||||
PedalboardType pedalboardType = Pedalboard::GetPedalboardTypeFromInstanceId(instanceId);
|
||||
std::shared_ptr<Lv2Pedalboard> pedalboard;
|
||||
switch (pedalboardType)
|
||||
{
|
||||
case PedalboardType::MainPedalboard:
|
||||
pedalboard = this->currentPedalboard;
|
||||
break;
|
||||
case PedalboardType::MainInserts:
|
||||
pedalboard = this->currentMainInsertPedalboard;
|
||||
break;
|
||||
case PedalboardType::AuxInserts:
|
||||
pedalboard = this->currentAuxInsertPedalboard;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("SetVuSubscriptions: Value out of range.");
|
||||
break;
|
||||
}
|
||||
std::shared_ptr<Lv2Pedalboard>& pedalboard = this->currentPedalboard;
|
||||
int64_t effectIndex = -1;
|
||||
if (pedalboard != nullptr)
|
||||
{
|
||||
effectIndex = pedalboard->GetIndexOfInstanceId(instanceId);
|
||||
}
|
||||
|
||||
|
||||
if (effectIndex != -1)
|
||||
{
|
||||
IEffect *effect = pedalboard->GetEffect(instanceId);
|
||||
RealtimePedalboardItemIndex index = RealtimePedalboardItemIndex(pedalboardType, effectIndex);
|
||||
RealtimePedalboardItemIndex index = RealtimePedalboardItemIndex(effectIndex);
|
||||
vuConfig->enabledIndexes.push_back(index);
|
||||
VuUpdateX v;
|
||||
v.pedalboardType(pedalboardType);
|
||||
v.instanceId_ = instanceId;
|
||||
// Display mono VUs if a stereo device is being fed identical L/R inputs.
|
||||
v.isStereoInput_ = effect->GetNumberOfInputAudioBuffers() >= 2 && effect->GetAudioInputBuffer(0) != effect->GetAudioInputBuffer(1);
|
||||
v.isStereoInput_ = effect->GetNumberOfInputAudioBuffers() >= 2;
|
||||
v.isStereoOutput_ = effect->GetNumberOfOutputAudioBuffers() >= 2;
|
||||
|
||||
vuConfig->vuUpdateWorkingData.push_back(v);
|
||||
@@ -2351,10 +2090,9 @@ public:
|
||||
else if (
|
||||
instanceId == Pedalboard::START_CONTROL_ID ||
|
||||
instanceId == Pedalboard::END_CONTROL_ID ||
|
||||
instanceId == Pedalboard::MAIN_INSERT_START_CONTROL_ID ||
|
||||
instanceId == Pedalboard::MAIN_INSERT_END_CONTROL_ID ||
|
||||
instanceId == Pedalboard::AUX_INSERT_START_CONTROL_ID ||
|
||||
instanceId == Pedalboard::AUX_INSERT_END_CONTROL_ID)
|
||||
instanceId == Pedalboard::AUX_START_CONTROL_ID ||
|
||||
instanceId == Pedalboard::AUX_END_CONTROL_ID
|
||||
)
|
||||
{
|
||||
auto index = GetRealtimeItemIndex(instanceId);
|
||||
VuUpdateX v;
|
||||
@@ -2371,16 +2109,10 @@ public:
|
||||
case Pedalboard::END_CONTROL_ID:
|
||||
nChannels = this->pHost->GetChannelSelection().mainOutputChannels().size();
|
||||
break;
|
||||
case Pedalboard::MAIN_INSERT_START_CONTROL_ID:
|
||||
nChannels = this->pHost->GetChannelSelection().mainOutputChannels().size();
|
||||
break;
|
||||
case Pedalboard::MAIN_INSERT_END_CONTROL_ID:
|
||||
nChannels = this->pHost->GetChannelSelection().mainOutputChannels().size();
|
||||
break;
|
||||
case Pedalboard::AUX_INSERT_START_CONTROL_ID:
|
||||
case Pedalboard::AUX_START_CONTROL_ID:
|
||||
nChannels = this->pHost->GetChannelSelection().auxInputChannels().size();
|
||||
break;
|
||||
case Pedalboard::AUX_INSERT_END_CONTROL_ID:
|
||||
case Pedalboard::AUX_END_CONTROL_ID:
|
||||
nChannels = this->pHost->GetChannelSelection().auxOutputChannels().size();
|
||||
break;
|
||||
}
|
||||
@@ -2395,25 +2127,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
Lv2Pedalboard *GetPedalboard(PedalboardType pedalboardType)
|
||||
Lv2Pedalboard *GetPedalboard()
|
||||
{
|
||||
switch (pedalboardType)
|
||||
{
|
||||
case PedalboardType::MainPedalboard:
|
||||
return this->currentPedalboard.get();
|
||||
case PedalboardType::MainInserts:
|
||||
return this->realtimeRoutingInserts.mainInserts;
|
||||
case PedalboardType::AuxInserts:
|
||||
return this->realtimeRoutingInserts.auxInserts;
|
||||
default:
|
||||
throw std::runtime_error("AudioHostImpl::GetPedalboard: invalid argument.");
|
||||
}
|
||||
return this->currentPedalboard.get();
|
||||
}
|
||||
RealtimeMonitorPortSubscription MakeRealtimeSubscription(const MonitorPortSubscription &subscription)
|
||||
{
|
||||
RealtimeMonitorPortSubscription result;
|
||||
result.subscriptionHandle = subscription.subscriptionHandle;
|
||||
result.pedalboardType = Pedalboard::GetPedalboardTypeFromInstanceId(subscription.subscriptionHandle);
|
||||
result.instanceIndex = this->currentPedalboard->GetIndexOfInstanceId(subscription.instanceid);
|
||||
IEffect *pEffect = this->currentPedalboard->GetEffect(subscription.instanceid);
|
||||
|
||||
|
||||
@@ -148,7 +148,6 @@ namespace pipedal
|
||||
{
|
||||
public:
|
||||
int64_t subscriptionHandle;
|
||||
PedalboardType pedalboardType;
|
||||
int64_t instanceid;
|
||||
std::string key;
|
||||
float updateInterval;
|
||||
@@ -239,10 +238,6 @@ namespace pipedal
|
||||
|
||||
virtual void SetPedalboard(const std::shared_ptr<Lv2Pedalboard> &pedalboard) = 0;
|
||||
|
||||
virtual void SetChannelRoutingInserts(
|
||||
const std::shared_ptr<Lv2Pedalboard> &mainInserts,
|
||||
const std::shared_ptr<Lv2Pedalboard> &auxInserts
|
||||
) = 0;
|
||||
|
||||
|
||||
virtual void SetControlValue(uint64_t instanceId, const std::string &symbol, float value) = 0;
|
||||
|
||||
+1
-1
@@ -240,7 +240,7 @@ namespace pipedal
|
||||
{
|
||||
// zero length? We can never have a zero-length bank.
|
||||
// Add a default preset and make it the selected preset.
|
||||
Pedalboard pedalboard = Pedalboard::MakeDefault(PedalboardType::MainPedalboard);
|
||||
Pedalboard pedalboard = Pedalboard::MakeDefault();
|
||||
this->addPreset(pedalboard);
|
||||
newSelection = presets_[0]->instanceId();
|
||||
}
|
||||
|
||||
@@ -76,8 +76,6 @@ ChannelSelection::ChannelSelection(ChannelRouterSettings&settings)
|
||||
, mainOutputChannels_(settings.mainOutputChannels())
|
||||
, auxInputChannels_(settings.auxInputChannels())
|
||||
, auxOutputChannels_(settings.auxOutputChannels())
|
||||
, sendInputChannels_(settings.sendInputChannels())
|
||||
, sendOutputChannels_(settings.sendOutputChannels())
|
||||
{
|
||||
normalizeChannelSelection();
|
||||
}
|
||||
@@ -104,8 +102,6 @@ void ChannelSelection::normalizeChannelSelection() {
|
||||
normalizeOutputChannels(mainOutputChannels_);
|
||||
normalizeInputChannels(auxInputChannels_);
|
||||
normalizeOutputChannels(auxOutputChannels_);
|
||||
normalizeInputChannels(sendInputChannels_);
|
||||
normalizeOutputChannels(sendOutputChannels_);
|
||||
|
||||
// If either aux inputs or outputs are zero, don't do ANY aux processing.
|
||||
if (auxInputChannels_.size() == 0)
|
||||
@@ -129,8 +125,6 @@ void ChannelSelection::normalizeChannelSelection() {
|
||||
|
||||
|
||||
ChannelRouterSettings::ChannelRouterSettings()
|
||||
: mainInserts_(PedalboardType::MainInserts)
|
||||
, auxInserts_(PedalboardType::AuxInserts)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -152,30 +146,25 @@ JSON_MAP_REFERENCE(ChannelRouterSettings, changed)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, channelRouterPresetId)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, mainInputChannels)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, mainOutputChannels)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, mainInserts)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, auxInputChannels)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, auxOutputChannels)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, auxInserts)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, sendInputChannels)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, sendOutputChannels)
|
||||
JSON_MAP_REFERENCE(ChannelRouterSettings, controlValues)
|
||||
JSON_MAP_END()
|
||||
JSON_MAP_END();
|
||||
|
||||
JSON_MAP_BEGIN(ChannelRouterPresetIndexEntry)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetIndexEntry, id)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetIndexEntry, name)
|
||||
JSON_MAP_END()
|
||||
JSON_MAP_END();
|
||||
|
||||
|
||||
JSON_MAP_BEGIN(ChannelRouterPresetBankEntry)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetBankEntry, id)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetBankEntry, name)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetBankEntry, channelRouterSettings)
|
||||
JSON_MAP_END()
|
||||
JSON_MAP_END();
|
||||
|
||||
JSON_MAP_BEGIN(ChannelRouterPresetBank)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetBank, nextId)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetBank, version)
|
||||
JSON_MAP_REFERENCE(ChannelRouterPresetBank, entries)
|
||||
JSON_MAP_END()
|
||||
JSON_MAP_END();
|
||||
|
||||
|
||||
@@ -30,9 +30,6 @@ namespace pipedal
|
||||
class ChannelRouterSettings
|
||||
{
|
||||
protected:
|
||||
static constexpr int64_t CHANNEL_ROUTER_MAIN_INSERT_ID = -4; // Reserved Instance ID for Router Main Inserts.
|
||||
static constexpr int64_t CHANNEL_ROUTER_AUX_INSERT_ID = -5; // Reserved Instance ID for Router Aux inserts.
|
||||
|
||||
|
||||
bool configured_ = false;
|
||||
int64_t channelRouterPresetId_ = -1;
|
||||
@@ -40,22 +37,12 @@ namespace pipedal
|
||||
|
||||
std::vector<int64_t> mainInputChannels_ = {1, 1};
|
||||
std::vector<int64_t> mainOutputChannels_ = {0, 1};
|
||||
Pedalboard mainInserts_;
|
||||
|
||||
std::vector<int64_t> auxInputChannels_ = {-1, -1};
|
||||
std::vector<int64_t> auxOutputChannels_ = {-1, -1};
|
||||
Pedalboard auxInserts_;
|
||||
|
||||
std::vector<int64_t> sendInputChannels_ = {-1, -1};
|
||||
std::vector<int64_t> sendOutputChannels_ = {-1, -1};
|
||||
|
||||
std::vector<ControlValue> controlValues_;
|
||||
|
||||
public:
|
||||
|
||||
static constexpr int64_t MAIN_OUT_LEFT_CHANNEL = -2;
|
||||
static constexpr int64_t MAIN_OUT_RIGHT_CHANNEL = -3;
|
||||
|
||||
using self = ChannelRouterSettings;
|
||||
using ptr = std::shared_ptr<self>;
|
||||
|
||||
@@ -69,13 +56,8 @@ namespace pipedal
|
||||
JSON_GETTER_SETTER(changed)
|
||||
JSON_GETTER_SETTER_REF(mainInputChannels)
|
||||
JSON_GETTER_SETTER_REF(mainOutputChannels)
|
||||
JSON_GETTER_SETTER_REF(mainInserts)
|
||||
JSON_GETTER_SETTER_REF(auxInputChannels)
|
||||
JSON_GETTER_SETTER_REF(auxOutputChannels)
|
||||
JSON_GETTER_SETTER_REF(auxInserts)
|
||||
JSON_GETTER_SETTER_REF(sendInputChannels)
|
||||
JSON_GETTER_SETTER_REF(sendOutputChannels)
|
||||
JSON_GETTER_SETTER_REF(controlValues)
|
||||
|
||||
DECLARE_JSON_MAP(ChannelRouterSettings);
|
||||
};
|
||||
@@ -96,15 +78,11 @@ namespace pipedal
|
||||
const std::vector<int64_t> &mainOutputChannels() const { return mainOutputChannels_; }
|
||||
const std::vector<int64_t> &auxInputChannels() const { return auxInputChannels_; }
|
||||
const std::vector<int64_t> &auxOutputChannels() const { return auxOutputChannels_; }
|
||||
const std::vector<int64_t> &sendInputChannels() const { return sendInputChannels_; }
|
||||
const std::vector<int64_t> &sendOutputChannels() const { return sendOutputChannels_; }
|
||||
|
||||
std::vector<int64_t> &mainInputChannels() { return mainInputChannels_; }
|
||||
std::vector<int64_t> &mainOutputChannels() { return mainOutputChannels_; }
|
||||
std::vector<int64_t> &auxInputChannels() { return auxInputChannels_; }
|
||||
std::vector<int64_t> &auxOutputChannels() { return auxOutputChannels_; }
|
||||
std::vector<int64_t> &sendInputChannels() { return sendInputChannels_; }
|
||||
std::vector<int64_t> &sendOutputChannels() { return sendOutputChannels_; }
|
||||
|
||||
private:
|
||||
void normalizeChannelSelection();
|
||||
@@ -113,8 +91,6 @@ namespace pipedal
|
||||
std::vector<int64_t> mainOutputChannels_;
|
||||
std::vector<int64_t> auxInputChannels_;
|
||||
std::vector<int64_t> auxOutputChannels_;
|
||||
std::vector<int64_t> sendInputChannels_;
|
||||
std::vector<int64_t> sendOutputChannels_;
|
||||
};
|
||||
|
||||
class ChannelRouterPresetIndexEntry {
|
||||
|
||||
+10
-31
@@ -321,7 +321,6 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
|
||||
void Lv2Pedalboard::Prepare(IHost *pHost, Pedalboard &pedalboard, Lv2PedalboardErrorList &errorList, ExistingEffectMap *existingEffects)
|
||||
{
|
||||
this->pHost = pHost;
|
||||
this->pedalboardType = pedalboard.GetInstanceType();
|
||||
|
||||
inputVolume.SetSampleRate((float)(this->pHost->GetSampleRate()));
|
||||
outputVolume.SetSampleRate((float)(this->pHost->GetSampleRate()));
|
||||
@@ -573,7 +572,7 @@ void Lv2Pedalboard::SetBypass(int effectIndex, bool enabled)
|
||||
}
|
||||
|
||||
|
||||
void Lv2Pedalboard::ComputeVus(RealtimeVuBuffers *realtimeVuBuffers, uint32_t samples, float**masterInputBuffers, float**masterOutputBuffers)
|
||||
void Lv2Pedalboard::ComputeVus(RealtimeVuBuffers *realtimeVuBuffers, uint32_t samples)
|
||||
{
|
||||
if (realtimeVuBuffers == nullptr)
|
||||
{
|
||||
@@ -582,23 +581,25 @@ void Lv2Pedalboard::ComputeVus(RealtimeVuBuffers *realtimeVuBuffers, uint32_t sa
|
||||
for (size_t i = 0; i < realtimeVuBuffers->enabledIndexes.size(); ++i)
|
||||
{
|
||||
auto& rtIndex = realtimeVuBuffers->enabledIndexes[i];
|
||||
if (rtIndex.instanceType != this->pedalboardType)
|
||||
int index = rtIndex.index;
|
||||
if (index == -1) continue;
|
||||
if (index == Pedalboard::AUX_START_CONTROL_ID || index == Pedalboard::AUX_END_CONTROL_ID)
|
||||
{
|
||||
// handled by master VU updates.
|
||||
continue;
|
||||
}
|
||||
int index = rtIndex.index;
|
||||
VuUpdateX *pUpdate = &realtimeVuBuffers->vuUpdateWorkingData[i];
|
||||
if (index == Pedalboard::START_CONTROL_ID)
|
||||
{
|
||||
if (this->pedalboardInputBuffers.size() == 2)
|
||||
{
|
||||
pUpdate->AccumulateInputs(masterInputBuffers[0], masterInputBuffers[1], samples);
|
||||
// input is handled by master VU updates.
|
||||
pUpdate->AccumulateOutputs(&(this->pedalboardInputBuffers[0][0]), &(this->pedalboardInputBuffers[1][0]), samples); // after outputVolume applied.
|
||||
}
|
||||
else if (this->pedalboardInputBuffers.size() == 1)
|
||||
{
|
||||
pUpdate->AccumulateInputs(masterInputBuffers[0], samples);
|
||||
pUpdate->AccumulateOutputs(&(this->pedalboardInputBuffers[0][0]), samples); // after input volume applied.
|
||||
pUpdate->AccumulateOutputs(&(this->pedalboardInputBuffers[0][0]), samples); // before input volume applied.
|
||||
// output is handled by master VU updates.
|
||||
}
|
||||
}
|
||||
else if (index == Pedalboard::END_CONTROL_ID)
|
||||
@@ -606,12 +607,10 @@ void Lv2Pedalboard::ComputeVus(RealtimeVuBuffers *realtimeVuBuffers, uint32_t sa
|
||||
if (this->pedalboardOutputBuffers.size() == 2)
|
||||
{
|
||||
pUpdate->AccumulateInputs(&(this->pedalboardOutputBuffers[0][0]), &(this->pedalboardOutputBuffers[1][0]), samples);
|
||||
pUpdate->AccumulateOutputs(masterOutputBuffers[0], masterOutputBuffers[1], samples);
|
||||
}
|
||||
else if (this->pedalboardOutputBuffers.size() == 1)
|
||||
{
|
||||
pUpdate->AccumulateInputs(&(this->pedalboardOutputBuffers[0][0]), samples);
|
||||
pUpdate->AccumulateOutputs(masterOutputBuffers[0], samples);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1032,29 +1031,9 @@ void Lv2Pedalboard::handleTapTempo(uint8_t value, const MidiTimestamp& timestamp
|
||||
|
||||
|
||||
size_t Lv2Pedalboard::GetNumberOfAudioInputChannels() const {
|
||||
switch (pedalboardType)
|
||||
{
|
||||
case PedalboardType::MainPedalboard:
|
||||
return pHost->GetChannelSelection().mainInputChannels().size();
|
||||
case PedalboardType::MainInserts:
|
||||
return pHost->GetChannelSelection().mainOutputChannels().size();
|
||||
case PedalboardType::AuxInserts:
|
||||
return pHost->GetChannelSelection().auxInputChannels().size();
|
||||
default:
|
||||
throw std::runtime_error("Invalid argument");
|
||||
}
|
||||
return pHost->GetChannelSelection().mainInputChannels().size();
|
||||
}
|
||||
|
||||
size_t Lv2Pedalboard::GetNumberOfAudioOutputChannels() const {
|
||||
switch (pedalboardType)
|
||||
{
|
||||
case PedalboardType::MainPedalboard:
|
||||
return pHost->GetChannelSelection().mainOutputChannels().size();
|
||||
case PedalboardType::MainInserts:
|
||||
return pHost->GetChannelSelection().mainOutputChannels().size();
|
||||
case PedalboardType::AuxInserts:
|
||||
return pHost->GetChannelSelection().auxOutputChannels().size();
|
||||
default:
|
||||
throw std::runtime_error("Invalid argument");
|
||||
}
|
||||
return pHost->GetChannelSelection().mainOutputChannels().size();
|
||||
}
|
||||
@@ -52,7 +52,6 @@ namespace pipedal
|
||||
class Lv2Pedalboard
|
||||
{
|
||||
private:
|
||||
PedalboardType pedalboardType;
|
||||
IHost *pHost = nullptr;
|
||||
size_t currentFrameOffset = 0;
|
||||
DbDezipper inputVolume;
|
||||
@@ -174,7 +173,7 @@ namespace pipedal
|
||||
void SetOutputVolume(float value) { this->outputVolume.SetTarget(value); }
|
||||
void SetBypass(int effectIndex, bool enabled);
|
||||
|
||||
void ComputeVus(RealtimeVuBuffers *vuConfiguration, uint32_t samples, float**masterInputBuffers, float **masterOutputBuffers);
|
||||
void ComputeVus(RealtimeVuBuffers *vuConfiguration, uint32_t samples);
|
||||
|
||||
float GetControlOutputValue(int effectIndex, int portIndex);
|
||||
|
||||
|
||||
+3
-14
@@ -210,7 +210,7 @@ PedalboardItem Pedalboard::MakeSplit()
|
||||
|
||||
|
||||
|
||||
Pedalboard Pedalboard::MakeDefault(PedalboardType instanceType)
|
||||
Pedalboard Pedalboard::MakeDefault()
|
||||
{
|
||||
// copy insanity. but it happens so rarely.
|
||||
Pedalboard result;
|
||||
@@ -510,20 +510,9 @@ Snapshot Pedalboard::MakeSnapshotFromCurrentSettings(const Pedalboard &previousP
|
||||
}
|
||||
|
||||
|
||||
Pedalboard::Pedalboard(PedalboardType instanceType)
|
||||
Pedalboard::Pedalboard()
|
||||
{
|
||||
switch (instanceType)
|
||||
{
|
||||
case PedalboardType::MainPedalboard:
|
||||
nextInstanceId_ = 0;
|
||||
break;
|
||||
case PedalboardType::MainInserts:
|
||||
nextInstanceId_ = MAIN_INSERT_INSTANCE_BASE;;
|
||||
break;
|
||||
case PedalboardType::AuxInserts:
|
||||
nextInstanceId_ = AUX_INSERT_INSTANCE_BASE;;
|
||||
break;
|
||||
}
|
||||
nextInstanceId_ = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-43
@@ -216,13 +216,6 @@ namespace pipedal
|
||||
DECLARE_JSON_MAP(Snapshot);
|
||||
};
|
||||
|
||||
enum class PedalboardType
|
||||
{
|
||||
Invalid = 0,
|
||||
MainPedalboard = 1,
|
||||
MainInserts = 2,
|
||||
AuxInserts = 3
|
||||
};
|
||||
|
||||
class Pedalboard
|
||||
{
|
||||
@@ -239,49 +232,17 @@ namespace pipedal
|
||||
|
||||
int64_t selectedPlugin_ = -1;
|
||||
|
||||
static constexpr int64_t TWO_POWER_52 = 4503599627370496; // Maximum Javascript integer value.
|
||||
static constexpr int64_t TWO_POWER_48 = 281474976710656; // Number of possible instance IDs for Main Pedalboards.
|
||||
static constexpr int64_t MAX_INSTANCE_ID = TWO_POWER_48;
|
||||
|
||||
public:
|
||||
static constexpr int64_t MAIN_INSERT_INSTANCE_BASE = TWO_POWER_52 - 2 * MAX_INSTANCE_ID;
|
||||
static constexpr int64_t AUX_INSERT_INSTANCE_BASE = TWO_POWER_52 - 1 * MAX_INSTANCE_ID;
|
||||
|
||||
static constexpr int64_t CHANNEL_ROUTER_CONTROLS_INSTANCE_ID = -4; // Reserved Instance ID for Router Controls.
|
||||
|
||||
static constexpr int64_t START_CONTROL_ID = -2; // synthetic PedalboardItem for input volume.
|
||||
static constexpr int64_t END_CONTROL_ID = -3; // synthetic PedalboardItem for output volume.
|
||||
static constexpr int64_t MAIN_INSERT_START_CONTROL_ID = MAIN_INSERT_INSTANCE_BASE + MAX_INSTANCE_ID - 2;
|
||||
static constexpr int64_t MAIN_INSERT_END_CONTROL_ID = MAIN_INSERT_INSTANCE_BASE + MAX_INSTANCE_ID - 3;
|
||||
static constexpr int64_t AUX_INSERT_START_CONTROL_ID = AUX_INSERT_INSTANCE_BASE + MAX_INSTANCE_ID - 2;
|
||||
static constexpr int64_t AUX_INSERT_END_CONTROL_ID = AUX_INSERT_INSTANCE_BASE + MAX_INSTANCE_ID - 3;
|
||||
|
||||
static PedalboardType GetPedalboardTypeFromInstanceId(int64_t instanceId)
|
||||
{
|
||||
if (instanceId == START_CONTROL_ID)
|
||||
return PedalboardType::MainPedalboard;
|
||||
if (instanceId == END_CONTROL_ID)
|
||||
return PedalboardType::MainPedalboard;
|
||||
static constexpr int64_t AUX_START_CONTROL_ID = -4; // synthetic PedalboardItem for aux input volume.
|
||||
static constexpr int64_t AUX_END_CONTROL_ID = -5; // synthetic PedalboardItem for aux output volume.
|
||||
|
||||
if (instanceId >= MAIN_INSERT_INSTANCE_BASE)
|
||||
{
|
||||
return PedalboardType::MainInserts;
|
||||
}
|
||||
else if (instanceId >= AUX_INSERT_INSTANCE_BASE)
|
||||
{
|
||||
return PedalboardType::AuxInserts;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PedalboardType::MainPedalboard;
|
||||
}
|
||||
}
|
||||
PedalboardType GetInstanceType() const
|
||||
{
|
||||
return GetPedalboardTypeFromInstanceId(this->nextInstanceId_); // instanceId is irrelevant here.
|
||||
}
|
||||
|
||||
Pedalboard(PedalboardType instanceType = PedalboardType::MainPedalboard);
|
||||
Pedalboard();
|
||||
|
||||
// deep copy, breaking shared pointers.
|
||||
Pedalboard DeepCopy();
|
||||
@@ -315,7 +276,7 @@ namespace pipedal
|
||||
PedalboardItem MakeEmptyItem();
|
||||
PedalboardItem MakeSplit();
|
||||
|
||||
static Pedalboard MakeDefault(PedalboardType instanceType = PedalboardType::MainPedalboard);
|
||||
static Pedalboard MakeDefault();
|
||||
};
|
||||
|
||||
#undef GETTER_SETTER_REF
|
||||
|
||||
@@ -82,7 +82,7 @@ PiPedalModel::PiPedalModel()
|
||||
this->updater = Updater::Create();
|
||||
this->updater->Start();
|
||||
this->currentUpdateStatus = updater->GetCurrentStatus();
|
||||
this->pedalboard = Pedalboard::MakeDefault(PedalboardType::MainPedalboard);
|
||||
this->pedalboard = Pedalboard::MakeDefault();
|
||||
|
||||
this->jackServerSettings = this->storage.GetJackServerSettings();
|
||||
|
||||
@@ -394,7 +394,7 @@ void PiPedalModel::Load()
|
||||
if (CrashGuard::HasCrashed())
|
||||
{
|
||||
// ignore the current preset, and load a blank pedalboard in order to avoid a potential plugin crash.
|
||||
this->pedalboard = Pedalboard::MakeDefault(PedalboardType::MainPedalboard);
|
||||
this->pedalboard = Pedalboard::MakeDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1752,10 +1752,8 @@ static bool isStartOrEndControl(int64_t controlId)
|
||||
{
|
||||
case Pedalboard::START_CONTROL_ID:
|
||||
case Pedalboard::END_CONTROL_ID:
|
||||
case Pedalboard::MAIN_INSERT_START_CONTROL_ID:
|
||||
case Pedalboard::MAIN_INSERT_END_CONTROL_ID:
|
||||
case Pedalboard::AUX_INSERT_START_CONTROL_ID:
|
||||
case Pedalboard::AUX_INSERT_END_CONTROL_ID:
|
||||
case Pedalboard::AUX_START_CONTROL_ID:
|
||||
case Pedalboard::AUX_END_CONTROL_ID:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -1794,11 +1792,9 @@ int64_t PiPedalModel::MonitorPort(int64_t instanceId, const std::string &key, fl
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
int64_t subscriptionId = ++nextSubscriptionId;
|
||||
PedalboardType pedalboardType = Pedalboard::GetPedalboardTypeFromInstanceId(instanceId);
|
||||
activeMonitorPortSubscriptions.push_back(
|
||||
MonitorPortSubscription{
|
||||
subscriptionId,
|
||||
pedalboardType,
|
||||
instanceId,
|
||||
key,
|
||||
updateInterval,
|
||||
|
||||
@@ -45,19 +45,12 @@ namespace pipedal
|
||||
uint8_t cc2_;
|
||||
};
|
||||
|
||||
struct Lv2RoutingInserts {
|
||||
|
||||
Lv2Pedalboard*mainInserts = nullptr;
|
||||
Lv2Pedalboard*auxInserts = nullptr;;
|
||||
};
|
||||
|
||||
enum class RingBufferCommand : int64_t
|
||||
{
|
||||
Invalid = 0,
|
||||
ReplaceEffect,
|
||||
EffectReplaced,
|
||||
ReplaceRoutingInserts,
|
||||
RoutingInsertsReplaced,
|
||||
SetValue,
|
||||
SetBypass,
|
||||
// AudioStopped,
|
||||
@@ -106,19 +99,17 @@ namespace pipedal
|
||||
|
||||
struct RealtimePedalboardItemIndex {
|
||||
RealtimePedalboardItemIndex()
|
||||
: instanceType(PedalboardType::MainPedalboard), index(-1)
|
||||
: index(-1)
|
||||
{
|
||||
}
|
||||
RealtimePedalboardItemIndex(
|
||||
PedalboardType instanceType,
|
||||
int64_t index)
|
||||
: instanceType(instanceType), index(index)
|
||||
: index(index)
|
||||
{
|
||||
}
|
||||
RealtimePedalboardItemIndex(const RealtimePedalboardItemIndex& other) = default;
|
||||
RealtimePedalboardItemIndex& operator=(const RealtimePedalboardItemIndex& other) = default;
|
||||
|
||||
PedalboardType instanceType = PedalboardType::MainPedalboard;
|
||||
int64_t index = -1;
|
||||
};
|
||||
|
||||
@@ -150,7 +141,6 @@ namespace pipedal
|
||||
{
|
||||
public:
|
||||
RealtimeMonitorPortSubscription() { delete callbackPtr; }
|
||||
PedalboardType pedalboardType = PedalboardType::MainPedalboard;
|
||||
int64_t subscriptionHandle;
|
||||
int instanceIndex = 0;
|
||||
int portIndex = 0;
|
||||
@@ -553,15 +543,6 @@ namespace pipedal
|
||||
write(RingBufferCommand::EffectReplaced, pedalboard);
|
||||
}
|
||||
|
||||
void ReplaceRoutingInserts(Lv2RoutingInserts routingInserts)
|
||||
{
|
||||
write(RingBufferCommand::ReplaceRoutingInserts, routingInserts);
|
||||
}
|
||||
|
||||
void RoutingInsertsReplaced(Lv2RoutingInserts routingInserts)
|
||||
{
|
||||
write(RingBufferCommand::ReplaceRoutingInserts, routingInserts);
|
||||
}
|
||||
|
||||
|
||||
void AudioTerminatedAbnormally()
|
||||
|
||||
+1
-1
@@ -472,7 +472,7 @@ void Storage::LoadBankIndex()
|
||||
if (bankIndex.entries().size() == 0)
|
||||
{
|
||||
currentBank.clear();
|
||||
Pedalboard defaultPedalboard = Pedalboard::MakeDefault(PedalboardType::MainPedalboard);
|
||||
Pedalboard defaultPedalboard = Pedalboard::MakeDefault();
|
||||
int64_t instanceId = currentBank.addPreset(defaultPedalboard);
|
||||
currentBank.selectedPreset(instanceId);
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ using namespace pipedal;
|
||||
|
||||
|
||||
JSON_MAP_BEGIN(VuUpdateX)
|
||||
JSON_MAP_REFERENCE(VuUpdateX,pedalboardType)
|
||||
JSON_MAP_REFERENCE(VuUpdateX,instanceId)
|
||||
JSON_MAP_REFERENCE(VuUpdateX,sampleTime)
|
||||
JSON_MAP_REFERENCE(VuUpdateX,isStereoInput)
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace pipedal
|
||||
class VuUpdateX
|
||||
{
|
||||
public:
|
||||
int pedalboardType_ = (int)PedalboardType::Invalid;
|
||||
int64_t instanceId_ = 0;
|
||||
long sampleTime_ = 0;
|
||||
bool isStereoInput_ = false;
|
||||
@@ -38,9 +37,6 @@ namespace pipedal
|
||||
float outputMaxValueR_ = 0;
|
||||
|
||||
public:
|
||||
|
||||
PedalboardType pedalboardType() const { return (PedalboardType)pedalboardType_; }
|
||||
void pedalboardType(PedalboardType value) { pedalboardType_ = (int)value; }
|
||||
void reset() {
|
||||
inputMaxValueL_ = 0;
|
||||
inputMaxValueR_ = 0;
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
|
||||
import { Pedalboard, ControlValue } from "./Pedalboard.tsx";
|
||||
import JackConfiguration from "./Jack.tsx";
|
||||
|
||||
|
||||
export const NONE_CHANNEL: number = -1;
|
||||
// valid for Aux channel input only.
|
||||
export const MAIN_OUT_LEFT_CHANNEL: number = -2;
|
||||
// valid for Aux channel input only.
|
||||
export const MAIN_OUT_RIGHT_CHANNEL: number = -3;
|
||||
|
||||
|
||||
function isActiveChannel(channels: number[]): boolean {
|
||||
@@ -19,12 +15,6 @@ function chName(ch: number, maxChannels: number): string {
|
||||
if (ch === -1) {
|
||||
return "None";
|
||||
}
|
||||
if (ch === MAIN_OUT_LEFT_CHANNEL) {
|
||||
return "Main Out L";
|
||||
}
|
||||
if (ch === MAIN_OUT_RIGHT_CHANNEL) {
|
||||
return "Main Out R";
|
||||
}
|
||||
if (maxChannels <= 2) {
|
||||
if (ch === 0) {
|
||||
return "Left";
|
||||
@@ -83,16 +73,10 @@ export default class ChannelRouterSettings {
|
||||
|
||||
mainInputChannels: number[] = [1, 1];
|
||||
mainOutputChannels: number[] = [0, 1];
|
||||
mainInserts: Pedalboard = new Pedalboard();
|
||||
|
||||
auxInputChannels: number[] = [0, 0];
|
||||
auxOutputChannels: number[] = [-1, -1];
|
||||
auxInserts: Pedalboard = new Pedalboard();
|
||||
|
||||
sendInputChannels: number[] = [-1, -1];
|
||||
sendOutputChannels: number[] = [-1, -1];
|
||||
|
||||
controlValues: ControlValue[] = [];
|
||||
// Inserts...
|
||||
|
||||
deserialize(obj: any): ChannelRouterSettings {
|
||||
@@ -101,42 +85,13 @@ export default class ChannelRouterSettings {
|
||||
this.channelRouterPresetId = obj.channelRouterPresetId ? obj.channelRouterPresetId : -1;
|
||||
this.mainInputChannels = obj.mainInputChannels.slice();
|
||||
this.mainOutputChannels = obj.mainOutputChannels.slice();
|
||||
this.mainInserts = new Pedalboard().deserialize(obj.mainInserts);
|
||||
this.auxInputChannels = obj.auxInputChannels.slice();
|
||||
this.auxOutputChannels = obj.auxOutputChannels.slice();
|
||||
this.auxInserts = new Pedalboard().deserialize(obj.auxInserts);
|
||||
this.sendInputChannels = obj.sendInputChannels.slice();
|
||||
this.sendOutputChannels = obj.sendOutputChannels.slice();
|
||||
this.controlValues = ControlValue.deserializeArray(obj.controlValues);
|
||||
return this;
|
||||
}
|
||||
clone() : ChannelRouterSettings {
|
||||
return new ChannelRouterSettings().deserialize(this);
|
||||
}
|
||||
getControlValue(symbol: string): number | null {
|
||||
for (let control of this.controlValues) {
|
||||
if (control.key === symbol) {
|
||||
return control.value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
setControlValue(symbol: string, value: number): boolean {
|
||||
for (let control of this.controlValues) {
|
||||
if (control.key === symbol) {
|
||||
if (control.value === value) {
|
||||
return false;
|
||||
}
|
||||
control.value = value;
|
||||
this.controlValues = this.controlValues.slice(); // trigger observers.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
let newValue = new ControlValue(symbol, value);
|
||||
this.controlValues.push(newValue);
|
||||
this.controlValues = this.controlValues.slice(); // trigger observers.
|
||||
return true;
|
||||
}
|
||||
|
||||
getDescription(jackConfiguration: JackConfiguration): string {
|
||||
if (!this.configured) {
|
||||
@@ -163,10 +118,6 @@ export default class ChannelRouterSettings {
|
||||
channelPairName(this.auxOutputChannels, nOutputs,false);
|
||||
}
|
||||
}
|
||||
if (isActiveChannel(this.sendInputChannels) && isActiveChannel(this.sendOutputChannels)) {
|
||||
description += " " + ", send: " +channelPairName(this.sendOutputChannels, nOutputs, false)
|
||||
+ " -> " + channelPairName(this.sendInputChannels, nInputs,true);
|
||||
}
|
||||
return description;
|
||||
}
|
||||
canEdit(jackConfiguration: JackConfiguration): boolean {
|
||||
@@ -215,18 +166,10 @@ export default class ChannelRouterSettings {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (let ch of this.sendInputChannels) {
|
||||
if (ch >= maxInputChannels) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
isAuxActive() : boolean {
|
||||
return isActiveChannel(this.auxInputChannels) && isActiveChannel(this.auxOutputChannels);
|
||||
}
|
||||
isSendActive() : boolean{
|
||||
return isActiveChannel(this.sendInputChannels) && isActiveChannel(this.sendOutputChannels);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,22 +22,18 @@ import { useState } from 'react';
|
||||
import VuMeter from './VuMeter';
|
||||
import HelpOutlineIcon from '@mui/icons-material/HelpOutline';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||
import IconButtonEx from './IconButtonEx';
|
||||
import Button from '@mui/material/Button';
|
||||
import useWindowSize from "./UseWindowSize";
|
||||
import Select from '@mui/material/Select';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import ChannelRouterSettingsHelpDialog from './ChannelRouterSettingsHelpDialog';
|
||||
import SpeakerIcon from '@mui/icons-material/Speaker';
|
||||
import MicIcon from '@mui/icons-material/Mic';
|
||||
import SaveIconOutline from '@mui/icons-material/Save';
|
||||
|
||||
import ChannelRouterSettings from './ChannelRouterSettings';
|
||||
import DialogTitle from '@mui/material/DialogTitle';
|
||||
import DialogContent from '@mui/material/DialogContent';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import ChannelRouterSettings, { MAIN_OUT_LEFT_CHANNEL, MAIN_OUT_RIGHT_CHANNEL } from './ChannelRouterSettings';
|
||||
import { Pedalboard } from './Pedalboard';
|
||||
|
||||
import DialogEx from './DialogEx';
|
||||
@@ -58,7 +54,6 @@ export interface ChannelRouterSettingsDialogProps {
|
||||
enum RouteType {
|
||||
Main,
|
||||
Aux,
|
||||
Send
|
||||
}
|
||||
|
||||
interface ChannelRouterSettingsPreset {
|
||||
@@ -79,13 +74,8 @@ let factoryRouterPresets: ChannelRouterSettings[] = [
|
||||
channelRouterPresetId: -2,
|
||||
mainInputChannels: [0, -1],
|
||||
mainOutputChannels: [0, -1],
|
||||
mainInserts: new Pedalboard(),
|
||||
auxInputChannels: [-1, -1],
|
||||
auxOutputChannels: [-1, -1],
|
||||
auxInserts: new Pedalboard(),
|
||||
sendInputChannels: [-1, -1],
|
||||
sendOutputChannels: [-1, -1],
|
||||
controlValues: []
|
||||
})
|
||||
,
|
||||
// Input->Stereo out.
|
||||
@@ -94,70 +84,48 @@ let factoryRouterPresets: ChannelRouterSettings[] = [
|
||||
channelRouterPresetId: -3,
|
||||
mainInputChannels: [0, -1],
|
||||
mainOutputChannels: [0, 1],
|
||||
mainInserts: new Pedalboard(),
|
||||
auxInputChannels: [-1, -1],
|
||||
auxOutputChannels: [-1, -1],
|
||||
auxInserts: new Pedalboard(),
|
||||
sendInputChannels: [-1, -1],
|
||||
sendOutputChannels: [-1, -1],
|
||||
controlValues: []
|
||||
})
|
||||
,
|
||||
// Right->Right
|
||||
new ChannelRouterSettings().deserialize({
|
||||
configured: true,
|
||||
channelRouterPresetId: -4,
|
||||
mainInputChannels: [1,-1],
|
||||
mainOutputChannels: [1, -1],
|
||||
auxInputChannels: [-1, -1],
|
||||
auxOutputChannels: [-1, -1],
|
||||
})
|
||||
,
|
||||
// Right->Stereo out.
|
||||
new ChannelRouterSettings().deserialize({
|
||||
configured: true,
|
||||
channelRouterPresetId: -4,
|
||||
mainInputChannels: [1,-1],
|
||||
mainOutputChannels: [0, 1],
|
||||
mainInserts: new Pedalboard(),
|
||||
auxInputChannels: [-1, -1],
|
||||
auxOutputChannels: [-1, -1],
|
||||
auxInserts: new Pedalboard(),
|
||||
sendInputChannels: [-1, -1],
|
||||
sendOutputChannels: [-1, -1],
|
||||
controlValues: [],
|
||||
})
|
||||
,
|
||||
new ChannelRouterSettings().deserialize({
|
||||
configured: true,
|
||||
channelRouterPresetId: -5,
|
||||
mainInputChannels: [1,-1],
|
||||
mainOutputChannels: [0, -1],
|
||||
mainInserts: new Pedalboard(),
|
||||
auxInputChannels: [1,-1],
|
||||
auxOutputChannels: [1,-1],
|
||||
auxInserts: new Pedalboard(),
|
||||
sendInputChannels: [-1, -1],
|
||||
sendOutputChannels: [-1, -1],
|
||||
controlValues: [],
|
||||
mainOutputChannels: [0, 1],
|
||||
auxInputChannels: [-1, -1],
|
||||
auxOutputChannels: [-1, -1],
|
||||
})
|
||||
,
|
||||
// Right->right, aux: Left->Left .
|
||||
new ChannelRouterSettings().deserialize({
|
||||
configured: true,
|
||||
channelRouterPresetId: -6,
|
||||
mainInputChannels: [1,-1],
|
||||
mainOutputChannels: [1,-1],
|
||||
mainInserts: new Pedalboard(),
|
||||
auxInputChannels: [0, -1],
|
||||
auxOutputChannels: [0, -1],
|
||||
auxInserts: new Pedalboard(),
|
||||
sendInputChannels: [-1, -1],
|
||||
sendOutputChannels: [-1, -1],
|
||||
controlValues: [],
|
||||
mainOutputChannels: [1, -1],
|
||||
auxInputChannels: [0,-1],
|
||||
auxOutputChannels: [0,-1],
|
||||
})
|
||||
,
|
||||
// Right-Left, re-amp->Right.
|
||||
new ChannelRouterSettings().deserialize({
|
||||
configured: true,
|
||||
channelRouterPresetId: -7,
|
||||
mainInputChannels: [1,-1],
|
||||
mainOutputChannels: [0, -1],
|
||||
mainInserts: new Pedalboard(),
|
||||
auxInputChannels: [0, -1],
|
||||
auxInputChannels: [1,-1],
|
||||
auxOutputChannels: [1,-1],
|
||||
auxInserts: new Pedalboard(),
|
||||
sendInputChannels: [-1, -1],
|
||||
sendOutputChannels: [-1, -1],
|
||||
controlValues: []
|
||||
})
|
||||
,
|
||||
new ChannelRouterSettings().deserialize({
|
||||
@@ -165,80 +133,35 @@ let factoryRouterPresets: ChannelRouterSettings[] = [
|
||||
channelRouterPresetId: -8,
|
||||
mainInputChannels: [0, -1],
|
||||
mainOutputChannels: [0, -1],
|
||||
mainInserts: new Pedalboard(),
|
||||
auxInputChannels: [1,-1],
|
||||
auxOutputChannels: [1,-1],
|
||||
auxInserts: new Pedalboard(),
|
||||
sendInputChannels: [-1, -1],
|
||||
sendOutputChannels: [-1, -1],
|
||||
controlValues: []
|
||||
})
|
||||
,
|
||||
new ChannelRouterSettings().deserialize({
|
||||
configured: true,
|
||||
channelRouterPresetId: -9,
|
||||
mainInputChannels: [0, -1],
|
||||
mainOutputChannels: [0, -1],
|
||||
mainInserts: new Pedalboard(),
|
||||
auxInputChannels: [-1, -1],
|
||||
auxOutputChannels: [-1, -1],
|
||||
auxInserts: new Pedalboard(),
|
||||
sendInputChannels: [1,-1],
|
||||
sendOutputChannels: [1,-1],
|
||||
controlValues: []
|
||||
mainInputChannels: [1, -1],
|
||||
mainOutputChannels: [0, 1],
|
||||
auxInputChannels: [2, 3],
|
||||
auxOutputChannels: [0, 1],
|
||||
})
|
||||
,
|
||||
new ChannelRouterSettings().deserialize({
|
||||
configured: true,
|
||||
channelRouterPresetId: -10,
|
||||
mainInputChannels: [1,-1],
|
||||
mainOutputChannels: [1,-1],
|
||||
mainInserts: new Pedalboard(),
|
||||
auxInputChannels: [-1, -1],
|
||||
auxOutputChannels: [-1, -1],
|
||||
auxInserts: new Pedalboard(),
|
||||
sendInputChannels: [0, -1],
|
||||
sendOutputChannels: [0, -1],
|
||||
controlValues: []
|
||||
})
|
||||
,
|
||||
new ChannelRouterSettings().deserialize({
|
||||
configured: true,
|
||||
channelRouterPresetId: -11,
|
||||
mainInputChannels: [0, -1],
|
||||
mainInputChannels: [1, -1],
|
||||
mainOutputChannels: [0, 1],
|
||||
mainInserts: new Pedalboard(),
|
||||
auxInputChannels: [0, -1],
|
||||
auxOutputChannels: [2, -1],
|
||||
auxInserts: new Pedalboard(),
|
||||
sendInputChannels: [-1, -1],
|
||||
sendOutputChannels: [-1, -1],
|
||||
controlValues: []
|
||||
})
|
||||
,
|
||||
new ChannelRouterSettings().deserialize({
|
||||
configured: true,
|
||||
channelRouterPresetId: -12,
|
||||
mainInputChannels: [0, -1],
|
||||
mainOutputChannels: [0, 1],
|
||||
mainInserts: new Pedalboard(),
|
||||
auxInputChannels: [-1, -1],
|
||||
auxOutputChannels: [-1, -1],
|
||||
auxInserts: new Pedalboard(),
|
||||
sendInputChannels: [2, 3],
|
||||
sendOutputChannels: [2, 3],
|
||||
controlValues: []
|
||||
auxInputChannels: [2, 3],
|
||||
auxOutputChannels: [2, 3],
|
||||
})
|
||||
,
|
||||
];
|
||||
|
||||
let cellPortraitInOutDiv: React.CSSProperties = {
|
||||
width: 80, display: "flex", columnGap: 4, flexDirection: "row", alignItems: "center", justifyContent: "right",
|
||||
display: "flex", columnGap: 4, flexDirection: "row", alignItems: "center", justifyContent: "right",
|
||||
};
|
||||
let cellPortraitSectionHead: React.CSSProperties = {
|
||||
border: "0px",
|
||||
paddingTop: 4,
|
||||
paddingBottom: 4,
|
||||
paddingLeft: 0,
|
||||
paddingRight: 12,
|
||||
width: 50,
|
||||
@@ -248,9 +171,8 @@ let cellPortraitSectionHead: React.CSSProperties = {
|
||||
};
|
||||
|
||||
let cellPortraitControlStrip: React.CSSProperties = {
|
||||
border: "0px",
|
||||
paddingTop: 12,
|
||||
paddingBottom: 12,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
paddingLeft: 0,
|
||||
paddingRight: 0,
|
||||
margin: "0px",
|
||||
@@ -268,6 +190,17 @@ let cellLeft: React.CSSProperties = {
|
||||
whiteSpace: "nowrap",
|
||||
verticalAlign: "middle"
|
||||
};
|
||||
let cellPortraitLeft: React.CSSProperties = {
|
||||
border: "0px",
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
paddingLeft: 4,
|
||||
paddingRight: 12,
|
||||
margin: "0px",
|
||||
textAlign: "left",
|
||||
whiteSpace: "nowrap",
|
||||
verticalAlign: "middle"
|
||||
};
|
||||
let cellLandscapeTitle: React.CSSProperties = {
|
||||
border: "0px",
|
||||
paddingTop: 4,
|
||||
@@ -279,13 +212,11 @@ let cellLandscapeTitle: React.CSSProperties = {
|
||||
verticalAlign: "middle"
|
||||
};
|
||||
let cellPortraitInOut: React.CSSProperties = {
|
||||
border: "0px",
|
||||
paddingTop: 4,
|
||||
paddingBottom: 4,
|
||||
paddingLeft: 12,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
paddingLeft: 24,
|
||||
paddingRight: 12,
|
||||
margin: "0px",
|
||||
width: 80,
|
||||
textAlign: "right",
|
||||
verticalAlign: "middle"
|
||||
};
|
||||
@@ -312,8 +243,6 @@ function makeRoutingPresets(audioConfig: JackConfiguration): ChannelRouterSettin
|
||||
normalizeChannelSelection(preset.mainOutputChannels);
|
||||
normalizeChannelSelection(preset.auxInputChannels);
|
||||
normalizeChannelSelection(preset.auxOutputChannels);
|
||||
normalizeChannelSelection(preset.sendInputChannels);
|
||||
normalizeChannelSelection(preset.sendOutputChannels);
|
||||
let newPreset = {
|
||||
id: preset.channelRouterPresetId,
|
||||
name: preset.getDescription(audioConfig),
|
||||
@@ -347,11 +276,6 @@ function MakeChannelMenu(channelCount: number, routeType: RouteType, input: bool
|
||||
items.push((<MenuItem key={i} value={i} disabled={disallowedSelections.includes(i)}>Ch {i + 1}</MenuItem>));
|
||||
}
|
||||
}
|
||||
if (routeType === RouteType.Aux && input) {
|
||||
items.push((<MenuItem key={MAIN_OUT_LEFT_CHANNEL} value={MAIN_OUT_LEFT_CHANNEL} >Main Out L</MenuItem>));
|
||||
items.push((<MenuItem key={MAIN_OUT_RIGHT_CHANNEL} value={MAIN_OUT_RIGHT_CHANNEL} >Main Out R</MenuItem>));
|
||||
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
@@ -435,7 +359,7 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
onClose();
|
||||
};
|
||||
let [windowSize] = useWindowSize();
|
||||
let landscape = windowSize.width > windowSize.height;
|
||||
let landscape = windowSize.height < 600;
|
||||
let fullScreen = windowSize.width < 450 || windowSize.height < 600;
|
||||
|
||||
let ChannelSelect = (routeType: RouteType, channelIndex: number, input: boolean, icon: boolean = true) => {
|
||||
@@ -459,22 +383,12 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
case RouteType.Aux:
|
||||
channelSelection = input ? settings.auxInputChannels : settings.auxOutputChannels;
|
||||
break;
|
||||
case RouteType.Send:
|
||||
channelSelection = input ? settings.sendInputChannels : settings.sendOutputChannels;
|
||||
break;
|
||||
}
|
||||
value = channelSelection[channelIndex];
|
||||
|
||||
if (value >= channelCount) {
|
||||
value = -1;
|
||||
}
|
||||
if (routeType === RouteType.Send) {
|
||||
if (input) {
|
||||
disallowedSelections = settings.mainInputChannels.concat(settings.auxInputChannels);
|
||||
} else {
|
||||
disallowedSelections = settings.mainOutputChannels.concat(settings.auxOutputChannels);
|
||||
}
|
||||
}
|
||||
if (channelIndex === 1) {
|
||||
if (channelSelection[0] !== -1) {
|
||||
disallowedSelections.push(channelSelection[0]);
|
||||
@@ -515,16 +429,6 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
normalizeChannelSelection(newSettings.auxOutputChannels);
|
||||
}
|
||||
break;
|
||||
case RouteType.Send:
|
||||
if (input) {
|
||||
newSettings.sendInputChannels[channelIndex] = newValue;
|
||||
normalizeChannelSelection(newSettings.sendInputChannels);
|
||||
|
||||
} else {
|
||||
newSettings.sendOutputChannels[channelIndex] = newValue;
|
||||
normalizeChannelSelection(newSettings.sendOutputChannels);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (newSettings.channelRouterPresetId >= 0) {
|
||||
newSettings.modified = true; // custom.
|
||||
@@ -544,23 +448,18 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
let instanceId: number;
|
||||
switch (routeType) {
|
||||
case RouteType.Main:
|
||||
instanceId = input ? Pedalboard.START_CONTROL : Pedalboard.MAIN_INSERT_END_CONTROL_ID;
|
||||
instanceId = input ? Pedalboard.START_CONTROL_ID : Pedalboard.END_CONTROL_ID;
|
||||
break;
|
||||
case RouteType.Aux:
|
||||
instanceId = input ? Pedalboard.AUX_INSERT_START_CONTROL_ID : Pedalboard.AUX_INSERT_END_CONTROL_ID;
|
||||
instanceId = input ? Pedalboard.AUX_START_CONTROL_ID : Pedalboard.AUX_END_CONTROL_ID;
|
||||
break;
|
||||
case RouteType.Send:
|
||||
instanceId = input ? Pedalboard.SEND_RETURN_CONTROL : Pedalboard.SEND_OUTPUT_CONTROL;
|
||||
|
||||
}
|
||||
return (
|
||||
<div style={{}} >
|
||||
|
||||
<VuMeter instanceId={instanceId}
|
||||
display={input? "input": "output"}
|
||||
height={48} />
|
||||
</div>
|
||||
);
|
||||
height={64} displayText={true} />
|
||||
);
|
||||
}
|
||||
|
||||
let ApplyPresetId = (presetId: number | string | null | undefined) => {
|
||||
@@ -570,9 +469,6 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
for (let preset of channelRouterPresets) {
|
||||
if (preset.id === presetId) {
|
||||
let newPreset = Object.assign(new ChannelRouterSettings(), preset.settings);
|
||||
// mark the presets as inserts.
|
||||
newPreset.mainInserts.nextInstanceId = Pedalboard.MAIN_INSERT_INSTANCE_BASE;
|
||||
newPreset.auxInserts.nextInstanceId = Pedalboard.AUX_INSERT_INSTANCE_BASE;
|
||||
model.setChannelRouterSettings(newPreset);
|
||||
return;
|
||||
}
|
||||
@@ -586,9 +482,7 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
(preset.settings.mainInputChannels.every((ch) => ch < inputChannels || ch === -1)) &&
|
||||
(preset.settings.mainOutputChannels.every((ch) => ch < outputChannels || ch === -1)) &&
|
||||
(preset.settings.auxInputChannels.every((ch) => ch < inputChannels || ch === -1)) &&
|
||||
(preset.settings.auxOutputChannels.every((ch) => ch < outputChannels || ch === -1)) &&
|
||||
(preset.settings.sendInputChannels.every((ch) => ch < inputChannels || ch === -1)) &&
|
||||
(preset.settings.sendOutputChannels.every((ch) => ch < outputChannels || ch === -1))
|
||||
(preset.settings.auxOutputChannels.every((ch) => ch < outputChannels || ch === -1))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -612,22 +506,10 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
|
||||
return items;
|
||||
}
|
||||
let handleSave = () => {
|
||||
|
||||
};
|
||||
|
||||
let PresetSelect = (width: number | string | undefined) => {
|
||||
return (
|
||||
<div style={{ display: "flex", flexDirection: "row", alignItems: "center", width: width }}>
|
||||
<div style={{ flex: "0 0 auto" }}>
|
||||
<IconButtonEx tooltip="Save current preset"
|
||||
style={{ flex: "0 0 auto", color: "#FFFFFF" }}
|
||||
onClick={(e) => { handleSave(); }}
|
||||
size="large">
|
||||
<SaveIconOutline style={{ opacity: 0.75 }} color="inherit" />
|
||||
</IconButtonEx>
|
||||
</div>
|
||||
|
||||
<div style={{ flex: "1 1", display: "relative" }}>
|
||||
<Select variant="standard" style={{ width: "100%" }} value={settings.channelRouterPresetId}
|
||||
onChange={(event) => {
|
||||
@@ -637,16 +519,12 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
{GeneratePresetMenuItems()}
|
||||
</Select>
|
||||
</div>
|
||||
<IconButtonEx tooltip="Presets" aria-label="more-presets" style={{ marginRight: 8 }}>
|
||||
<MoreVertIcon style={{ opacity: 0.6 }} onClick={() => { }} />
|
||||
</IconButtonEx>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
let LandscapeView = () => {
|
||||
let auxInsertDisabled = !settings.isAuxActive();
|
||||
return (
|
||||
<div style={{
|
||||
display: "flex", flexFlow: "row", alignItems: "center", justifyContent: "center",
|
||||
@@ -673,17 +551,11 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
<td style={cellLeft}>
|
||||
{ChannelSelect(RouteType.Main, 0, true)}
|
||||
</td>
|
||||
<td rowSpan={2} style={cellLeft}>{Vu(RouteType.Main, true)}</td>
|
||||
<td rowSpan={2} style={cellLeft}>
|
||||
<Button variant="outlined" style={{ textTransform: "none", borderRadius: 24 }}>
|
||||
Inserts
|
||||
</Button>
|
||||
</td>
|
||||
|
||||
<td rowSpan={2} style={cellLeft}>{Vu(RouteType.Main, false)}</td>
|
||||
<td rowSpan={3} style={cellLeft}>{Vu(RouteType.Main, true)}</td>
|
||||
<td style={cellLeft}>
|
||||
{ChannelSelect(RouteType.Main, 0, false)}
|
||||
</td>
|
||||
<td rowSpan={3} style={cellLeft}>{Vu(RouteType.Main, false)}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
@@ -706,20 +578,12 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
<td style={cellLeft}>
|
||||
{(ChannelSelect(RouteType.Aux, 0, true))}
|
||||
</td>
|
||||
<td rowSpan={2} style={cellLeft}>{Vu(RouteType.Aux, true)}</td>
|
||||
<td rowSpan={2} style={cellLeft}>
|
||||
<Button variant="outlined" style={{
|
||||
textTransform: "none", borderRadius: 24,
|
||||
}}
|
||||
disabled={auxInsertDisabled}>
|
||||
Inserts
|
||||
</Button>
|
||||
</td>
|
||||
<td rowSpan={3} style={cellLeft}>{Vu(RouteType.Aux, true)}</td>
|
||||
|
||||
<td rowSpan={2} style={cellLeft}>{Vu(RouteType.Aux, false)}</td>
|
||||
<td style={cellLeft}>
|
||||
{(ChannelSelect(RouteType.Aux, 0, false))}
|
||||
</td>
|
||||
<td rowSpan={3} style={cellLeft}>{Vu(RouteType.Aux, false)}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
@@ -730,36 +594,8 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
{(ChannelSelect(RouteType.Aux, 1, false))}
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td colSpan={9} style={{ height: 2 }}></td></tr>
|
||||
|
||||
{/* Spacer ---------------- */}
|
||||
<tr><td colSpan={9} style={{ height: 16 }}></td></tr>
|
||||
|
||||
{/* Send ---------------- */}
|
||||
<tr>
|
||||
<td rowSpan={1} style={cellLandscapeTitle}>
|
||||
<Typography variant="body2" color="textSecondary">Send</Typography>
|
||||
</td>
|
||||
<td style={cellLeft}>
|
||||
{(ChannelSelect(RouteType.Send, 0, false))}
|
||||
</td>
|
||||
<td rowSpan={2} style={cellLeft}>{Vu(RouteType.Send,false)}</td>
|
||||
<td rowSpan={2} style={cellLeft}>
|
||||
{/* No button */}
|
||||
</td>
|
||||
<td rowSpan={2} style={cellLeft}>{Vu(RouteType.Send,true)}</td>
|
||||
<td style={cellLeft}>
|
||||
{(ChannelSelect(RouteType.Send, 0, true))}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td style={cellLeft}>
|
||||
{(ChannelSelect(RouteType.Send, 1, false))}
|
||||
</td>
|
||||
<td style={cellLeft}>
|
||||
{(ChannelSelect(RouteType.Send, 1, true))}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -767,97 +603,83 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
);
|
||||
};
|
||||
let PortraitView = () => {
|
||||
let auxInsertDisabled = !settings.isAuxActive();
|
||||
return (
|
||||
<div style={{
|
||||
display: "flex", flexFlow: "row", alignItems: "center", justifyContent: "center",
|
||||
width: "100%", flexGrow: 0, fontSize: "14px"
|
||||
}} >
|
||||
<table style={{ borderCollapse: "collapse" }}>
|
||||
<table style={{ borderCollapse: "collapse", borderSpacing: 0 }}>
|
||||
<colgroup>
|
||||
<col style={{ width: "auto" }} />
|
||||
<col style={{ width: "auto" }} />
|
||||
<col style={{ width: "auto" }} />
|
||||
<col style={{ width: "auto" }} />
|
||||
<col style={{ width: "auto" }} />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
{/* Main */}
|
||||
<tr>
|
||||
<td colSpan={1} style={cellPortraitSectionHead}>
|
||||
<td colSpan={3} style={cellPortraitSectionHead}>
|
||||
<Typography variant="body2" color="textSecondary" >Main</Typography>
|
||||
</td>
|
||||
<td colSpan={4}>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={cellPortraitInOut}>
|
||||
<td style={cellPortraitInOut} rowSpan={1}>
|
||||
<div style={cellPortraitInOutDiv}>
|
||||
<Typography variant="body2" color="textSecondary" >In</Typography>
|
||||
<MicIcon style={{ verticalAlign: "middle", width: 16, height: 16, opacity: 0.6 }} />
|
||||
</div>
|
||||
</td>
|
||||
<td style={cellLeft}>
|
||||
<td style={cellPortraitLeft}>
|
||||
{ChannelSelect(RouteType.Main, 0, true, false)}
|
||||
</td>
|
||||
<td style={cellPortraitControlStrip} rowSpan={3}>
|
||||
{Vu(RouteType.Main,true)}
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td style={cellLeft}>
|
||||
{ChannelSelect(RouteType.Main, 1, true, false)}
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colSpan={4}>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={cellPortraitControlStrip}>{Vu(RouteType.Main,true)}</td>
|
||||
<td style={cellPortraitControlStrip}>
|
||||
<div style={{ marginLeft: 8, marginRight: 8 }}>
|
||||
<Button variant="outlined" style={{ textTransform: "none", borderRadius: 24 }}>
|
||||
Inserts
|
||||
</Button>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td style={cellPortraitControlStrip}>{Vu(RouteType.Main,false)}</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
{(ChannelSelect(RouteType.Main, 1, true, false))}
|
||||
</td>
|
||||
</tr>
|
||||
{/* Spacer */}
|
||||
<tr>
|
||||
<td style={cellPortraitInOut}>
|
||||
<td colSpan={3} style={{ height: 16 }}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={cellPortraitInOut} rowSpan={1}>
|
||||
<div style={cellPortraitInOutDiv}>
|
||||
<Typography variant="body2" color="textSecondary" >Out</Typography>
|
||||
<SpeakerIcon style={{ verticalAlign: "middle", width: 16, height: 16, opacity: 0.6 }} />
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td style={cellLeft}>
|
||||
|
||||
{ChannelSelect(RouteType.Main, 0, false, false)}
|
||||
</td>
|
||||
<td style={cellPortraitControlStrip} rowSpan={3}>
|
||||
{Vu(RouteType.Main,false)}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={cellLeft}>
|
||||
</td>
|
||||
<td style={cellLeft}>
|
||||
{ChannelSelect(RouteType.Main, 1, false, false)}
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
{/* Spacer ---------------- */}
|
||||
<tr><td colSpan={5} style={{ height: 16 }}></td></tr>
|
||||
<tr><td colSpan={3} style={{ height: 16 }}></td></tr>
|
||||
{/* Aux */}
|
||||
<tr>
|
||||
<td colSpan={1} style={cellPortraitSectionHead}>
|
||||
<td colSpan={3} style={cellPortraitSectionHead}>
|
||||
<Typography variant="body2" color="textSecondary" >Aux</Typography>
|
||||
</td>
|
||||
<td colSpan={4}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={cellPortraitInOut}>
|
||||
<div style={cellPortraitInOutDiv}>
|
||||
<div style={cellPortraitInOutDiv} >
|
||||
<Typography variant="body2" color="textSecondary" >In</Typography>
|
||||
<MicIcon style={{ verticalAlign: "middle", width: 16, height: 16, opacity: 0.6 }} />
|
||||
</div>
|
||||
@@ -865,39 +687,20 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
<td style={cellLeft}>
|
||||
{(ChannelSelect(RouteType.Aux, 0, true, false))}
|
||||
</td>
|
||||
<td style={cellPortraitControlStrip} rowSpan={3}>{Vu(RouteType.Aux, true)}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td style={cellLeft}>
|
||||
{(ChannelSelect(RouteType.Aux, 1, true, false))}
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{/* Spacer */}
|
||||
<tr>
|
||||
<td colSpan={3} style={{ height: 16 }}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colSpan={4}>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={cellPortraitControlStrip}>{Vu(RouteType.Aux, true)}</td>
|
||||
<td style={cellPortraitControlStrip}>
|
||||
<div style={{ marginLeft: 8, marginRight: 8 }}>
|
||||
<Button variant="outlined" style={{
|
||||
textTransform: "none", borderRadius: 24,
|
||||
|
||||
}}
|
||||
disabled={auxInsertDisabled}>
|
||||
Inserts
|
||||
</Button>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td style={cellPortraitControlStrip}>{Vu(RouteType.Aux, false)}</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={cellPortraitInOut}>
|
||||
<td style={cellPortraitInOut} rowSpan={1}>
|
||||
<div style={cellPortraitInOutDiv}>
|
||||
<Typography variant="body2" color="textSecondary" >Out</Typography>
|
||||
<SpeakerIcon style={{ verticalAlign: "middle", width: 16, height: 16, opacity: 0.6 }} />
|
||||
@@ -906,73 +709,13 @@ function ChannelRouterSettingsDialog(props: ChannelRouterSettingsDialogProps) {
|
||||
<td style={cellLeft}>
|
||||
{ChannelSelect(RouteType.Aux, 0, false, false)}
|
||||
</td>
|
||||
<td style={cellPortraitControlStrip} rowSpan={3}>{Vu(RouteType.Aux, false)}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td style={cellLeft}>
|
||||
{ChannelSelect(RouteType.Aux, 1, false, false)}
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
{/* Spacer ---------------- */}
|
||||
<tr><td colSpan={5} style={{ height: 16 }}></td></tr>
|
||||
|
||||
{/* Send */}
|
||||
<tr>
|
||||
<td colSpan={1} style={cellPortraitSectionHead}>
|
||||
<Typography variant="body2" color="textSecondary" >Send</Typography>
|
||||
</td>
|
||||
<td colSpan={4}></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={cellPortraitInOut}>
|
||||
<div style={cellPortraitInOutDiv}>
|
||||
<Typography variant="body2" color="textSecondary" >Send</Typography>
|
||||
<SpeakerIcon style={{ verticalAlign: "middle", width: 16, height: 16, opacity: 0.6 }} />
|
||||
</div>
|
||||
</td>
|
||||
<td style={cellLeft}>
|
||||
{(ChannelSelect(RouteType.Send, 0, false, false))}
|
||||
</td>
|
||||
<td style={cellLeft}>
|
||||
{(ChannelSelect(RouteType.Send, 1, false, false))}
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colSpan={4}>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={cellPortraitControlStrip}>{Vu(RouteType.Send, false)}</td>
|
||||
<td style={cellPortraitControlStrip}>
|
||||
<div style={{ marginLeft: 8, marginRight: 8, visibility: "hidden" }}>
|
||||
<Button variant="outlined" style={{ textTransform: "none", borderRadius: 24 }}>
|
||||
Inserts
|
||||
</Button>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td style={cellPortraitControlStrip}>{Vu(RouteType.Send, true)}</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={cellPortraitInOut}>
|
||||
<div style={cellPortraitInOutDiv}>
|
||||
<Typography variant="body2" color="textSecondary" >Return</Typography>
|
||||
<MicIcon style={{ verticalAlign: "middle", width: 16, height: 16, opacity: 0.6 }} />
|
||||
</div>
|
||||
</td>
|
||||
<td style={cellLeft}>
|
||||
{ChannelSelect(RouteType.Send, 0, true, false)}
|
||||
</td>
|
||||
<td style={cellLeft}>
|
||||
{ChannelSelect(RouteType.Send, 1, true, false)}
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
|
||||
@@ -107,49 +107,23 @@ export default class ChannelRouterSettingsHelpDialog extends ResizeResponsiveCom
|
||||
<div style={{ fontSize: "0.9em", lineHeight: "18pt" }}>
|
||||
<p> The Audio Channel Routing Dialog determines how audio signals are processed and routed between input and output audio channels.
|
||||
</p>
|
||||
<p>By default, guitar effects processing occurs on the <i>Main</i> route only. Plugins in the main PiPedal window are
|
||||
applied before any insert plugins that have been added to the <i>Main</i> route. Main insert plugins are
|
||||
applied globally, regardless of the selected preset or effects in the main PiPedal window. You might
|
||||
want to add an EQ or reverb plugin here, to allow your presets to be globally adjusted to suit the room
|
||||
in which you are currently performing.
|
||||
</p>
|
||||
<p>Plugins in the main PiPedal window are not applied to the <i>Aux</i> route by default. The Aux route is intended to be
|
||||
used for
|
||||
</p>
|
||||
<p>Guitar effects processing occurs on the <i>Main</i> route only.</p>
|
||||
<p>The Aux route can be used for a variety of purposes, such as:</p>
|
||||
<ul>
|
||||
<li>Passing through a dry (unprocessed) guitar signal that can be recorded by a DAW and
|
||||
re-amped later during mixing.
|
||||
</li>
|
||||
<li>Passing through a vocal mic signal from one of the input channels, perhaps with compression, EQ or
|
||||
other processing performed by plugins in Aux inserts.
|
||||
<li>Passing through a vocal mic signal from one of the input channels.
|
||||
</li>
|
||||
<li>
|
||||
Passing through a backing track or other external audio signal from one of the input channels, and then either
|
||||
Passing through a backing track or other external audio signal from one or two input channels, and then either
|
||||
mixing it with the processed guitar signal, or passing it out on a dedicated output channel.
|
||||
</li>
|
||||
</ul>
|
||||
<p>However, if "Main Out L" or "Main Out R" is selected as an Aux input channel, then the Aux route will receive the
|
||||
output of the processed Main route. Main route insrts are not applied
|
||||
to the Aux route input signal, so you can have an independent set of inserts applied to the Main and Aux output signals.
|
||||
An example of how one might use this feature: sending the output of the Main route to
|
||||
a soundboard or PA system without reverb or EQ applied; and then applying reverb and EQ only to the Aux route whose
|
||||
outputs will be used as inputs to a stage monitor or headphones for the performer.
|
||||
</p>
|
||||
<p>If the Main and Aux routes share output channels, then the results of the Main and Output signals are
|
||||
<p>If the Main and Aux routes share output channels, then the results of the Main and Aux signals are
|
||||
summed together on those output channels. For stereo mixing, assign the same left and right output
|
||||
channels to both the Main and Aux routes. If you have a 2x4 or 4x4 audio interface with two guitar input channels
|
||||
you can also pass through stereo dry signals by configuring Main and Aux input and output channels appropriately.
|
||||
</p>
|
||||
<p>The Send route, in conjunction with the TooB Send plugin allows you to send and return audio signals to an external physical device
|
||||
from within a PiPedal preset. This allows you to integrate external hardware effects into your PiPedal presets.
|
||||
Connect a cable from the audio interface output <i>Send</i> channel(s) selected here to the input of your
|
||||
hardware effect, and a cable from the output of your hardware effect to the audio interface's <i>Return</i> channel
|
||||
assigned here. Then insert the TooB Send plugin into your PiPedal preset. The input of the
|
||||
TooB Send plugin will be sent to the external hardware effect, and the output the external hardware
|
||||
effect will be returned to PiPedal at the output of the TooB Send plugin. PiPedal currently supports
|
||||
only one Send plugin instance per preset; and the Send and Return channels may not be shared with the Main
|
||||
or Aux routes. Note that you may only use one instance of the TooB Send plugin per preset. The TooB Send plugin
|
||||
may not be used as a Main or Aux insert effect.
|
||||
you can also pass through stereo dry signals by configuring Main and Aux input and output channels appropriately.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -379,10 +379,10 @@ export const MainPage =
|
||||
let pedalboard = this.model.pedalboard.get();
|
||||
if (!pedalboard) return null;
|
||||
|
||||
if (selectedId === Pedalboard.START_CONTROL) // synthetic input volume item.
|
||||
if (selectedId === Pedalboard.START_CONTROL_ID) // synthetic input volume item.
|
||||
{
|
||||
return pedalboard.makeStartItem();
|
||||
} else if (selectedId === Pedalboard.END_CONTROL) // synthetic output volume.
|
||||
} else if (selectedId === Pedalboard.END_CONTROL_ID) // synthetic output volume.
|
||||
{
|
||||
return pedalboard.makeEndItem();
|
||||
}
|
||||
|
||||
@@ -107,8 +107,8 @@ export class PedalboardItem implements Deserializable<PedalboardItem> {
|
||||
}
|
||||
|
||||
isSyntheticItem(): boolean {
|
||||
return this.instanceId === Pedalboard.START_CONTROL
|
||||
|| this.instanceId === Pedalboard.END_CONTROL;
|
||||
return this.instanceId === Pedalboard.START_CONTROL_ID
|
||||
|| this.instanceId === Pedalboard.END_CONTROL_ID;
|
||||
}
|
||||
getInstanceId() : number {
|
||||
if (this.instanceId === undefined)
|
||||
@@ -357,10 +357,6 @@ export class PedalboardSplitItem extends PedalboardItem {
|
||||
}
|
||||
|
||||
|
||||
let TWO_POWER_52 = 4503599627370496; // Maximum Javascript integer value.
|
||||
let TWO_POWER_48 = 281474976710656; // Number of possible instance IDs for Main Pedalboards.
|
||||
let MAX_INSTANCE_ID = TWO_POWER_48;
|
||||
|
||||
|
||||
|
||||
export enum InstanceType {
|
||||
@@ -372,21 +368,11 @@ export enum InstanceType {
|
||||
|
||||
export class Pedalboard implements Deserializable<Pedalboard> {
|
||||
|
||||
static readonly CHANNEL_ROUTER_CONTROLS_INSTANCE_ID = -4; // Reserved Instance ID for Router Main Inserts.
|
||||
static readonly CHANNEL_ROUTER_MAIN_INSERT_ID = -5; // Reserved Instance ID for Router Main Inserts.
|
||||
static readonly CHANNEL_ROUTER_AUX_INSERT_ID = -6; // Reserved Instance ID for Router Aux inserts.
|
||||
|
||||
static readonly MAIN_INSERT_INSTANCE_BASE = TWO_POWER_52-2*MAX_INSTANCE_ID;
|
||||
static readonly AUX_INSERT_INSTANCE_BASE = TWO_POWER_52-1*MAX_INSTANCE_ID;
|
||||
|
||||
static readonly START_CONTROL = -2; // synthetic PedalboardItem for input volume.
|
||||
static readonly END_CONTROL = -3; // synthetic PedalboardItem for output volume.
|
||||
static readonly SEND_OUTPUT_CONTROL = -4; // synthetic PedalboardItem for send output volume.
|
||||
static readonly SEND_RETURN_CONTROL = -5; // synthetic PedalboardItem for send return volume.
|
||||
static readonly MAIN_INSERT_START_CONTROL_ID = Pedalboard.MAIN_INSERT_INSTANCE_BASE + -2 + MAX_INSTANCE_ID;
|
||||
static readonly MAIN_INSERT_END_CONTROL_ID = Pedalboard.MAIN_INSERT_INSTANCE_BASE + -3 + MAX_INSTANCE_ID;
|
||||
static readonly AUX_INSERT_START_CONTROL_ID = Pedalboard.AUX_INSERT_INSTANCE_BASE + -2 + MAX_INSTANCE_ID
|
||||
static readonly AUX_INSERT_END_CONTROL_ID = Pedalboard.AUX_INSERT_INSTANCE_BASE + -3 + MAX_INSTANCE_ID;
|
||||
static readonly START_CONTROL_ID = -2; // synthetic PedalboardItem for input volume.
|
||||
static readonly END_CONTROL_ID = -3; // synthetic PedalboardItem for output volume.
|
||||
static readonly AUX_START_CONTROL_ID = -4;
|
||||
static readonly AUX_END_CONTROL_ID = -5;
|
||||
|
||||
|
||||
static readonly START_PEDALBOARD_ITEM_URI = "uri://two-play/pipedal/pedalboard#Start";
|
||||
@@ -405,25 +391,6 @@ export class Pedalboard implements Deserializable<Pedalboard> {
|
||||
return this;
|
||||
}
|
||||
|
||||
static getInstanceTypeFromInstanceId(instanceId: number): InstanceType {
|
||||
if (instanceId >= Pedalboard.MAIN_INSERT_INSTANCE_BASE) {
|
||||
return InstanceType.MainInsert;
|
||||
}
|
||||
if (instanceId >= Pedalboard.AUX_INSERT_INSTANCE_BASE) {
|
||||
return InstanceType.AuxInsert;
|
||||
}
|
||||
return InstanceType.MainPedalboard;
|
||||
}
|
||||
getInstanceType(): InstanceType {
|
||||
if (this.nextInstanceId >= Pedalboard.MAIN_INSERT_INSTANCE_BASE) {
|
||||
return InstanceType.MainInsert;
|
||||
}
|
||||
if (this.nextInstanceId >= Pedalboard.AUX_INSERT_INSTANCE_BASE) {
|
||||
return InstanceType.AuxInsert;
|
||||
}
|
||||
return InstanceType.MainPedalboard;
|
||||
}
|
||||
|
||||
clone(): Pedalboard {
|
||||
return new Pedalboard().deserialize(this);
|
||||
}
|
||||
@@ -514,7 +481,7 @@ export class Pedalboard implements Deserializable<Pedalboard> {
|
||||
makeStartItem(): PedalboardItem {
|
||||
let result = new PedalboardItem();
|
||||
result.pluginName = "Input";
|
||||
result.instanceId = Pedalboard.START_CONTROL;
|
||||
result.instanceId = Pedalboard.START_CONTROL_ID;
|
||||
result.uri = Pedalboard.START_PEDALBOARD_ITEM_URI;
|
||||
result.isEnabled = true;
|
||||
result.controlValues = [new ControlValue("volume_db",this.input_volume_db)];
|
||||
@@ -524,7 +491,7 @@ export class Pedalboard implements Deserializable<Pedalboard> {
|
||||
makeEndItem(): PedalboardItem {
|
||||
let result = new PedalboardItem();
|
||||
result.pluginName = "Output";
|
||||
result.instanceId = Pedalboard.END_CONTROL;
|
||||
result.instanceId = Pedalboard.END_CONTROL_ID;
|
||||
result.uri = Pedalboard.END_PEDALBOARD_ITEM_URI;
|
||||
result.isEnabled = true;
|
||||
result.controlValues = [new ControlValue("volume_db",this.output_volume_db)];
|
||||
|
||||
@@ -46,8 +46,8 @@ import {
|
||||
// import { midiChannelBindingControlFeatureEnabled } from './MidiChannelBinding';
|
||||
// import CloseIcon from '@mui/icons-material/Close';
|
||||
|
||||
const START_CONTROL = Pedalboard.START_CONTROL;
|
||||
const END_CONTROL = Pedalboard.END_CONTROL;
|
||||
const START_CONTROL = Pedalboard.START_CONTROL_ID;
|
||||
const END_CONTROL = Pedalboard.END_CONTROL_ID;
|
||||
|
||||
|
||||
const START_PEDALBOARD_ITEM_URI = Pedalboard.START_PEDALBOARD_ITEM_URI;
|
||||
|
||||
@@ -534,7 +534,6 @@ export class PiPedalModel //implements PiPedalModel
|
||||
jackServerSettings: ObservableProperty<JackServerSettings>
|
||||
= new ObservableProperty<JackServerSettings>(new JackServerSettings());
|
||||
|
||||
channelRouterControlValues: ObservableProperty<ControlValue[]> = new ObservableProperty<ControlValue[]>([]);
|
||||
channelRouterSettings: ObservableProperty<ChannelRouterSettings> = new ObservableProperty<ChannelRouterSettings>(new ChannelRouterSettings());
|
||||
|
||||
wifiConfigSettings: ObservableProperty<WifiConfigSettings> = new ObservableProperty<WifiConfigSettings>(new WifiConfigSettings());
|
||||
@@ -1752,7 +1751,7 @@ export class PiPedalModel //implements PiPedalModel
|
||||
|
||||
for (let i = 0; i < this._controlValueChangeItems.length; ++i) {
|
||||
let item = this._controlValueChangeItems[i];
|
||||
if (Pedalboard.START_CONTROL === item.instanceId) {
|
||||
if (Pedalboard.START_CONTROL_ID === item.instanceId) {
|
||||
item.onValueChanged("volume_db", volume_db);
|
||||
}
|
||||
}
|
||||
@@ -1779,7 +1778,7 @@ export class PiPedalModel //implements PiPedalModel
|
||||
}
|
||||
for (let i = 0; i < this._controlValueChangeItems.length; ++i) {
|
||||
let item = this._controlValueChangeItems[i];
|
||||
if (Pedalboard.END_CONTROL === item.instanceId) {
|
||||
if (Pedalboard.END_CONTROL_ID === item.instanceId) {
|
||||
item.onValueChanged("volume_db", volume_db);
|
||||
}
|
||||
}
|
||||
@@ -1788,49 +1787,32 @@ export class PiPedalModel //implements PiPedalModel
|
||||
|
||||
private lastControlMessageWasSentbyMe = false;
|
||||
|
||||
private _setChannelRouterControlValue(key: string, value: number, notifyServer: boolean) : void {
|
||||
let channelRouterSettings = this.channelRouterSettings.get();
|
||||
let changed = channelRouterSettings.setControlValue(key, value);
|
||||
if (changed)
|
||||
{
|
||||
this.channelRouterControlValues.set(this.channelRouterSettings.get().controlValues);
|
||||
if (notifyServer) {
|
||||
this.lastControlMessageWasSentbyMe = true;
|
||||
this._setServerControl("setControl", Pedalboard.CHANNEL_ROUTER_CONTROLS_INSTANCE_ID, key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
private _setPedalboardControlValue(instanceId: number, key: string, value: number, notifyServer: boolean): void {
|
||||
let pedalboard = this.pedalboard.get();
|
||||
if (pedalboard === undefined) throw new PiPedalStateError("Pedalboard not ready.");
|
||||
|
||||
if (instanceId == Pedalboard.CHANNEL_ROUTER_CONTROLS_INSTANCE_ID) {
|
||||
this._setChannelRouterControlValue(key,value,notifyServer);
|
||||
return;
|
||||
} else {
|
||||
let changed: boolean;
|
||||
let newPedalboard = pedalboard.clone();
|
||||
let changed: boolean;
|
||||
let newPedalboard = pedalboard.clone();
|
||||
|
||||
if (instanceId === Pedalboard.START_CONTROL && key === "volume_db") {
|
||||
this._setInputVolume(value, notifyServer);
|
||||
return;
|
||||
} else if (instanceId === Pedalboard.END_CONTROL) {
|
||||
this._setOutputVolume(value, notifyServer);
|
||||
return;
|
||||
if (instanceId === Pedalboard.START_CONTROL_ID && key === "volume_db") {
|
||||
this._setInputVolume(value, notifyServer);
|
||||
return;
|
||||
} else if (instanceId === Pedalboard.END_CONTROL_ID) {
|
||||
this._setOutputVolume(value, notifyServer);
|
||||
return;
|
||||
}
|
||||
let item = newPedalboard.getItem(instanceId);
|
||||
changed = item.setControlValue(key, value);
|
||||
if (changed) {
|
||||
if (notifyServer) {
|
||||
this.lastControlMessageWasSentbyMe = true;
|
||||
this._setServerControl("setControl", instanceId, key, value);
|
||||
}
|
||||
let item = newPedalboard.getItem(instanceId);
|
||||
changed = item.setControlValue(key, value);
|
||||
if (changed) {
|
||||
if (notifyServer) {
|
||||
this.lastControlMessageWasSentbyMe = true;
|
||||
this._setServerControl("setControl", instanceId, key, value);
|
||||
}
|
||||
this.setModelPedalboard(newPedalboard);
|
||||
for (let i = 0; i < this._controlValueChangeItems.length; ++i) {
|
||||
let item = this._controlValueChangeItems[i];
|
||||
if (instanceId === item.instanceId) {
|
||||
item.onValueChanged(key, value);
|
||||
}
|
||||
this.setModelPedalboard(newPedalboard);
|
||||
for (let i = 0; i < this._controlValueChangeItems.length; ++i) {
|
||||
let item = this._controlValueChangeItems[i];
|
||||
if (instanceId === item.instanceId) {
|
||||
item.onValueChanged(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2012,10 +1994,10 @@ export class PiPedalModel //implements PiPedalModel
|
||||
// mouse is down. Don't update EVERYBODY, but we must change
|
||||
// the control on the running audio plugin.
|
||||
// TODO: respect "expensive" port attribute.
|
||||
if (instanceId === Pedalboard.START_CONTROL && key === "volume_db") {
|
||||
if (instanceId === Pedalboard.START_CONTROL_ID && key === "volume_db") {
|
||||
this.previewInputVolume(value);
|
||||
return;
|
||||
} else if (instanceId === Pedalboard.END_CONTROL) {
|
||||
} else if (instanceId === Pedalboard.END_CONTROL_ID) {
|
||||
this.previewOutputVolume(value);
|
||||
return;
|
||||
}
|
||||
@@ -2155,10 +2137,10 @@ export class PiPedalModel //implements PiPedalModel
|
||||
}
|
||||
addPedalboardItem(instanceId: number, append: boolean): number {
|
||||
let pedalboard = this.pedalboard.get();
|
||||
if (instanceId === Pedalboard.START_CONTROL && append) {
|
||||
if (instanceId === Pedalboard.START_CONTROL_ID && append) {
|
||||
instanceId = pedalboard.items[0].instanceId;
|
||||
append = false;
|
||||
} else if (instanceId === Pedalboard.END_CONTROL && !append) {
|
||||
} else if (instanceId === Pedalboard.END_CONTROL_ID && !append) {
|
||||
instanceId = pedalboard.items[pedalboard.items.length - 1].instanceId;
|
||||
append = true;
|
||||
}
|
||||
@@ -2180,10 +2162,10 @@ export class PiPedalModel //implements PiPedalModel
|
||||
addPedalboardSplitItem(instanceId: number, append: boolean): number {
|
||||
let pedalboard = this.pedalboard.get();
|
||||
|
||||
if (instanceId === Pedalboard.START_CONTROL && append) {
|
||||
if (instanceId === Pedalboard.START_CONTROL_ID && append) {
|
||||
instanceId = pedalboard.items[0].instanceId;
|
||||
append = false;
|
||||
} else if (instanceId === Pedalboard.END_CONTROL && !append) {
|
||||
} else if (instanceId === Pedalboard.END_CONTROL_ID && !append) {
|
||||
instanceId = pedalboard.items[pedalboard.items.length - 1].instanceId;
|
||||
append = true;
|
||||
}
|
||||
@@ -3817,7 +3799,6 @@ export class PiPedalModel //implements PiPedalModel
|
||||
|
||||
setChannelRouterSettings(settings: ChannelRouterSettings) {
|
||||
this.channelRouterSettings.set(settings);
|
||||
this.channelRouterControlValues.set(settings.controlValues);
|
||||
if (this.webSocket) {
|
||||
this.webSocket.send("setChannelRouterSettings", settings);
|
||||
}
|
||||
|
||||
@@ -1041,9 +1041,9 @@ const PluginControlView =
|
||||
let pedalboard = this.model.pedalboard.get();
|
||||
|
||||
let pedalboardItem: PedalboardItem;
|
||||
if (this.props.instanceId === Pedalboard.START_CONTROL) {
|
||||
if (this.props.instanceId === Pedalboard.START_CONTROL_ID) {
|
||||
pedalboardItem = pedalboard.makeStartItem();
|
||||
} else if (this.props.instanceId === Pedalboard.END_CONTROL) {
|
||||
} else if (this.props.instanceId === Pedalboard.END_CONTROL_ID) {
|
||||
pedalboardItem = pedalboard.makeEndItem();
|
||||
} else {
|
||||
pedalboardItem = pedalboard.getItem(this.props.instanceId);
|
||||
|
||||
@@ -468,12 +468,16 @@ export const VuMeter =
|
||||
let height = this.props.height;
|
||||
let scale = height / DISPLAY_HEIGHT;
|
||||
return (
|
||||
<div style={{ height: height, transform: `scale(1.0, ${scale})`, transformOrigin: "top left" }}>
|
||||
<div className={this.state.isStereo? classes.stereoTextFrame: classes.monoTextFrame}>
|
||||
{
|
||||
this.renderVus()
|
||||
}
|
||||
<div style={{ display: "flex" , flexFlow: "column nowrap", alignItems: "center" }}>
|
||||
<div style={{ height: height, transform: `scale(1.0, ${scale})`, transformOrigin: "top left" }}>
|
||||
<div className={this.state.isStereo? classes.stereoTextFrame: classes.monoTextFrame}>
|
||||
{
|
||||
this.renderVus()
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div ref={this.textRef} className={classes.vuTextFrame}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user