155 lines
5.4 KiB
C++
155 lines
5.4 KiB
C++
#ifndef OPLABSBANDBUS_HPP
|
||
#define OPLABSBANDBUS_HPP
|
||
|
||
#include <lv2/core/lv2.h>
|
||
#include <lv2/state/state.h>
|
||
#include <lv2/urid/urid.h>
|
||
#include <cstdint>
|
||
#include <cmath>
|
||
#include <cstring>
|
||
|
||
/**
|
||
* OPLabsBandBus — 8-channel stereo bus mixer LV2 plugin.
|
||
*
|
||
* Sums 8 stereo input pairs into a stereo output with per-channel
|
||
* volume, pan, mute controls and peak level metering. Includes master
|
||
* volume and mute. Compatible with PiPedal and any LV2 host.
|
||
*
|
||
* Port layout (62 ports total):
|
||
* Audio inputs: ch1L..ch8R (0–15, 16 ports)
|
||
* Audio outputs: outL, outR (16–17, 2 ports)
|
||
* Controls in: ch1Vol..ch8Vol (18–25, 8 ports)
|
||
* ch1Pan..ch8Pan (26–33, 8 ports)
|
||
* ch1Mute..ch8Mute(34–41, 8 ports)
|
||
* masterVol (42, 1 port)
|
||
* masterMute (43, 1 port)
|
||
* Controls out: ch1LevelL..ch8LevelL (44–51, 8 ports)
|
||
* ch1LevelR..ch8LevelR (52–59, 8 ports)
|
||
* masterLevelL, masterLevelR (60–61, 2 ports)
|
||
*
|
||
* URI: http://ourpad.casa/plugins/oplabs-band-bus#
|
||
*/
|
||
class OPLabsBandBus {
|
||
public:
|
||
static constexpr const char* URI = "http://ourpad.casa/plugins/oplabs-band-bus#";
|
||
static constexpr uint32_t kNumChannels = 8;
|
||
|
||
enum Ports : uint32_t {
|
||
// Audio inputs (16)
|
||
kCh1L = 0, kCh1R = 1,
|
||
kCh2L = 2, kCh2R = 3,
|
||
kCh3L = 4, kCh3R = 5,
|
||
kCh4L = 6, kCh4R = 7,
|
||
kCh5L = 8, kCh5R = 9,
|
||
kCh6L = 10, kCh6R = 11,
|
||
kCh7L = 12, kCh7R = 13,
|
||
kCh8L = 14, kCh8R = 15,
|
||
// Audio outputs (2)
|
||
kOutL = 16,
|
||
kOutR = 17,
|
||
// Per-channel volume (8)
|
||
kCh1Vol = 18, kCh2Vol = 19,
|
||
kCh3Vol = 20, kCh4Vol = 21,
|
||
kCh5Vol = 22, kCh6Vol = 23,
|
||
kCh7Vol = 24, kCh8Vol = 25,
|
||
// Per-channel pan (8)
|
||
kCh1Pan = 26, kCh2Pan = 27,
|
||
kCh3Pan = 28, kCh4Pan = 29,
|
||
kCh5Pan = 30, kCh6Pan = 31,
|
||
kCh7Pan = 32, kCh8Pan = 33,
|
||
// Per-channel mute (8)
|
||
kCh1Mute = 34, kCh2Mute = 35,
|
||
kCh3Mute = 36, kCh4Mute = 37,
|
||
kCh5Mute = 38, kCh6Mute = 39,
|
||
kCh7Mute = 40, kCh8Mute = 41,
|
||
// Master controls (2)
|
||
kMasterVol = 42,
|
||
kMasterMute = 43,
|
||
// Per-channel level L (8)
|
||
kCh1LevelL = 44, kCh2LevelL = 45,
|
||
kCh3LevelL = 46, kCh4LevelL = 47,
|
||
kCh5LevelL = 48, kCh6LevelL = 49,
|
||
kCh7LevelL = 50, kCh8LevelL = 51,
|
||
// Per-channel level R (8)
|
||
kCh1LevelR = 52, kCh2LevelR = 53,
|
||
kCh3LevelR = 54, kCh4LevelR = 55,
|
||
kCh5LevelR = 56, kCh6LevelR = 57,
|
||
kCh7LevelR = 58, kCh8LevelR = 59,
|
||
// Master level (2)
|
||
kMasterLevelL = 60,
|
||
kMasterLevelR = 61,
|
||
kNumPorts = 62
|
||
};
|
||
|
||
// ---- Static LV2 callbacks ----
|
||
static LV2_Handle instantiate(const LV2_Descriptor* descriptor,
|
||
double sampleRate,
|
||
const char* bundlePath,
|
||
const LV2_Feature* const* features);
|
||
static void connectPort(LV2_Handle instance, uint32_t port, void* data);
|
||
static void activate(LV2_Handle instance);
|
||
static void run(LV2_Handle instance, uint32_t nSamples);
|
||
static void deactivate(LV2_Handle instance);
|
||
static void cleanup(LV2_Handle instance);
|
||
static const void* extensionData(const char* uri);
|
||
|
||
// ---- State callbacks ----
|
||
static LV2_State_Status saveState(LV2_Handle instance,
|
||
LV2_State_Store_Function store,
|
||
LV2_State_Handle handle,
|
||
uint32_t flags,
|
||
const LV2_Feature* const* features);
|
||
static LV2_State_Status restoreState(LV2_Handle instance,
|
||
LV2_State_Retrieve_Function retrieve,
|
||
LV2_State_Handle handle,
|
||
uint32_t flags,
|
||
const LV2_Feature* const* features);
|
||
|
||
private:
|
||
OPLabsBandBus(double sampleRate, const LV2_Feature* const* features);
|
||
~OPLabsBandBus() = default;
|
||
OPLabsBandBus(const OPLabsBandBus&) = delete;
|
||
OPLabsBandBus& operator=(const OPLabsBandBus&) = delete;
|
||
|
||
bool initUrids(const LV2_Feature* const* features);
|
||
static inline float dBToGain(float dB) {
|
||
return std::pow(10.0f, dB / 20.0f);
|
||
}
|
||
|
||
// URID map
|
||
LV2_URID_Map* uridMap = nullptr;
|
||
LV2_URID urid__stateDummy = 0;
|
||
|
||
// Audio port pointers [ch][0=L,1=R]
|
||
const float* pAudioIn[8][2] = {};
|
||
float* pAudioOut[2] = {};
|
||
|
||
// Control input port pointers
|
||
const float* pVol[8] = {};
|
||
const float* pPan[8] = {};
|
||
const float* pMute[8] = {};
|
||
const float* pMasterVol = nullptr;
|
||
const float* pMasterMute = nullptr;
|
||
|
||
// Control output port pointers (meters)
|
||
float* pLevelL[8] = {};
|
||
float* pLevelR[8] = {};
|
||
float* pMasterLevelL = nullptr;
|
||
float* pMasterLevelR = nullptr;
|
||
|
||
// Cached parameter values
|
||
float cachedVol[8] = {};
|
||
float cachedPan[8] = {};
|
||
bool cachedMute[8] = {};
|
||
float cachedMasterVol = 0.0f;
|
||
bool cachedMasterMute = false;
|
||
|
||
// Peak meter state
|
||
float peakL[8] = {};
|
||
float peakR[8] = {};
|
||
float peakMasterL = -70.0f;
|
||
float peakMasterR = -70.0f;
|
||
};
|
||
|
||
#endif // OPLABSBANDBUS_HPP
|