Channel routing without inserts.

This commit is contained in:
Robin E.R. Davies
2026-04-04 14:51:41 -04:00
parent 1f60e02ce0
commit b21c9d636a
25 changed files with 418 additions and 1284 deletions
+101 -148
View File
@@ -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
View File
@@ -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
View File
@@ -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);
-5
View File
@@ -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
View File
@@ -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();
}
+4 -15
View File
@@ -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();
-24
View File
@@ -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
View File
@@ -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();
}
+1 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
+4 -8
View File
@@ -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,
+2 -21
View File
@@ -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
View File
@@ -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);
-1
View File
@@ -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)
-4
View File
@@ -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);
}
}
+95 -352
View File
@@ -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>
+2 -2
View File
@@ -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();
}
+8 -41
View File
@@ -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)];
+2 -2
View File
@@ -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;
+28 -47
View File
@@ -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);
}
+2 -2
View File
@@ -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);
+9 -5
View File
@@ -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>
);
}