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