| @@ -8,7 +8,18 @@ | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| // ----------------------------------------------------------------------- | |||||
| /** | |||||
| * FrontLeft, FrontRight, RearLeft, and RearRight speakers: room corners or car doors-like located. | |||||
| * Here is each of L-R, F-R controls attenuates two channels but not one. | |||||
| * | |||||
| * If L-R is +0.1 and F-R is -0.2 then: | |||||
| * FrontLeft channel is *= (0.9 * 1.0), | |||||
| * FrontRight *= (1.0 * 1.0), | |||||
| * RearLeft *= (0.9 * 0.8), | |||||
| * and RearRight *= (1.0 * 0.8). | |||||
| */ | |||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||
| typedef struct { | typedef struct { | ||||
| float a0, b1, z1; | float a0, b1, z1; | ||||
| @@ -24,7 +35,7 @@ void set_filter_sample_rate(Filter* const filter, const float sampleRate) | |||||
| filter->z1 = 0.0f; | filter->z1 = 0.0f; | ||||
| } | } | ||||
| // ----------------------------------------------------------------------- | |||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||
| typedef enum { | typedef enum { | ||||
| PARAM_LEFT_RIGHT = 0, | PARAM_LEFT_RIGHT = 0, | ||||
| @@ -37,7 +48,7 @@ typedef struct { | |||||
| float params[PARAM_COUNT]; | float params[PARAM_COUNT]; | ||||
| } QuadPannerHandle; | } QuadPannerHandle; | ||||
| // ----------------------------------------------------------------------- | |||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||
| static NativePluginHandle quadpanner_instantiate(const NativeHostDescriptor* host) | static NativePluginHandle quadpanner_instantiate(const NativeHostDescriptor* host) | ||||
| { | { | ||||
| @@ -135,35 +146,36 @@ static void quadpanner_process(NativePluginHandle handle, | |||||
| float** inBuffer, float** outBuffer, uint32_t frames, | float** inBuffer, float** outBuffer, uint32_t frames, | ||||
| const NativeMidiEvent* midiEvents, uint32_t midiEventCount) | const NativeMidiEvent* midiEvents, uint32_t midiEventCount) | ||||
| { | { | ||||
| float v1, v2, tmp; | |||||
| float v1, v2, v3, v4, tmp; // FrontLeft, FrontRight, RearLeft, and RearRight | |||||
| // left/right | // left/right | ||||
| if ((tmp = handlePtr->params[PARAM_LEFT_RIGHT]) < 0.f) | if ((tmp = handlePtr->params[PARAM_LEFT_RIGHT]) < 0.f) | ||||
| { | { | ||||
| v1 = 1.f; | |||||
| v2 = 1.f - tmp * -0.01f; | |||||
| v1 = v3 = 1.f; | |||||
| v2 = v4 = 1.f - tmp * -0.01f; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| v1 = 1.f - tmp * 0.01f; | |||||
| v2 = 1.f; | |||||
| v1 = v3 = 1.f - tmp * 0.01f; | |||||
| v2 = v4 = 1.f; | |||||
| } | } | ||||
| handle_audio_buffers(inBuffer[0], outBuffer[0], &handlePtr->lowpass[0], v1, frames); | |||||
| handle_audio_buffers(inBuffer[1], outBuffer[1], &handlePtr->lowpass[1], v2, frames); | |||||
| // front/rear | // front/rear | ||||
| if ((tmp = handlePtr->params[PARAM_FRONT_REAR]) < 0.f) | |||||
| if ((tmp = handlePtr->params[PARAM_FRONT_REAR] * 0.01f) < 0.f) | |||||
| { | { | ||||
| v1 = 1.f; | |||||
| v2 = 1.f - tmp * -0.01f; | |||||
| v3 *= 1.f - -tmp; | |||||
| v4 *= 1.f - -tmp; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| v1 = 1.f - tmp * 0.01f; | |||||
| v2 = 1.f; | |||||
| v1 *= 1.f - tmp; | |||||
| v2 *= 1.f - tmp; | |||||
| } | } | ||||
| handle_audio_buffers(inBuffer[2], outBuffer[2], &handlePtr->lowpass[2], v1, frames); | |||||
| handle_audio_buffers(inBuffer[3], outBuffer[3], &handlePtr->lowpass[3], v2, frames); | |||||
| handle_audio_buffers(inBuffer[0], outBuffer[0], &handlePtr->lowpass[0], v1, frames); | |||||
| handle_audio_buffers(inBuffer[1], outBuffer[1], &handlePtr->lowpass[1], v2, frames); | |||||
| handle_audio_buffers(inBuffer[2], outBuffer[2], &handlePtr->lowpass[2], v3, frames); | |||||
| handle_audio_buffers(inBuffer[3], outBuffer[3], &handlePtr->lowpass[3], v4, frames); | |||||
| return; | return; | ||||
| @@ -176,12 +188,12 @@ static intptr_t quadpanner_dispatcher(NativePluginHandle handle, NativePluginDis | |||||
| { | { | ||||
| switch (opcode) | switch (opcode) | ||||
| { | { | ||||
| case NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED: | |||||
| for (unsigned i = 0; i < PARAM_COUNT * 2; ++i) | |||||
| set_filter_sample_rate(&handlePtr->lowpass[i], opt); | |||||
| break; | |||||
| default: | |||||
| case NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED: | |||||
| for (unsigned i = 0; i < PARAM_COUNT * 2; ++i) | |||||
| set_filter_sample_rate(&handlePtr->lowpass[i], opt); | |||||
| break; | break; | ||||
| default: | |||||
| break; | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| @@ -195,16 +207,16 @@ static intptr_t quadpanner_dispatcher(NativePluginHandle handle, NativePluginDis | |||||
| static const char* quadpanner_get_buffer_port_name(NativePluginHandle handle, uint32_t index, bool isOutput) | static const char* quadpanner_get_buffer_port_name(NativePluginHandle handle, uint32_t index, bool isOutput) | ||||
| { | { | ||||
| static const char* const kInNames[4] = { | static const char* const kInNames[4] = { | ||||
| "In-Left", | |||||
| "In-Right", | |||||
| "In-Front", | |||||
| "In-Rear", | |||||
| "In-FrontLeft", | |||||
| "In-FrontRight", | |||||
| "In-RearLeft", | |||||
| "In-RearRight", | |||||
| }; | }; | ||||
| static const char* const kOutNames[4] = { | static const char* const kOutNames[4] = { | ||||
| "Out-Left", | |||||
| "Out-Right", | |||||
| "Out-Front", | |||||
| "Out-Rear", | |||||
| "Out-FrontLeft", | |||||
| "Out-FrontRight", | |||||
| "Out-RearLeft", | |||||
| "Out-RearRight", | |||||
| }; | }; | ||||
| return isOutput ? kOutNames[index] : kInNames[index]; | return isOutput ? kOutNames[index] : kInNames[index]; | ||||
| @@ -213,7 +225,7 @@ static const char* quadpanner_get_buffer_port_name(NativePluginHandle handle, ui | |||||
| (void)handle; | (void)handle; | ||||
| } | } | ||||
| // ----------------------------------------------------------------------- | |||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||
| static const NativePluginDescriptor quadpannerDesc = { | static const NativePluginDescriptor quadpannerDesc = { | ||||
| .category = NATIVE_PLUGIN_CATEGORY_UTILITY, | .category = NATIVE_PLUGIN_CATEGORY_UTILITY, | ||||
| @@ -268,7 +280,7 @@ static const NativePluginDescriptor quadpannerDesc = { | |||||
| .get_buffer_port_range = NULL, | .get_buffer_port_range = NULL, | ||||
| }; | }; | ||||
| // ----------------------------------------------------------------------- | |||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||
| void carla_register_native_plugin_quadpanner(void); | void carla_register_native_plugin_quadpanner(void); | ||||
| @@ -277,4 +289,4 @@ void carla_register_native_plugin_quadpanner(void) | |||||
| carla_register_native_plugin(&quadpannerDesc); | carla_register_native_plugin(&quadpannerDesc); | ||||
| } | } | ||||
| // ----------------------------------------------------------------------- | |||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||