finalized bw_{ring_mod,osc_sin}, bw_dry_wet (untested) + new fx(pp)_ring_mod + cosmetics
This commit is contained in:
parent
baf440a171
commit
dc93bd675b
6
examples/fx_ring_mod/android/Makefile
Normal file
6
examples/fx_ring_mod/android/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
|
||||
NAME := bw_example_fx_ring_mod
|
||||
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_ring_mod.c
|
||||
|
||||
include ${ROOT_DIR}/../../common/android/android.mk
|
7
examples/fx_ring_mod/daisy-seed/Makefile
Normal file
7
examples/fx_ring_mod/daisy-seed/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
|
||||
TARGET = bw_example_fx_ring_mod
|
||||
|
||||
C_SOURCES += ${ROOT_DIR}/../src/bw_example_fx_ring_mod.c
|
||||
|
||||
include ${ROOT_DIR}/../../common/daisy-seed/daisy-seed.mk
|
36
examples/fx_ring_mod/daisy-seed/config_daisy_seed.h
Normal file
36
examples/fx_ring_mod/daisy-seed/config_daisy_seed.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2023 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Brickworks is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* File authors: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_DAISY_SEED_H
|
||||
#define _CONFIG_DAISY_SEED_H
|
||||
|
||||
struct config_pin {
|
||||
int param_index;
|
||||
int pin;
|
||||
};
|
||||
|
||||
#define NUM_PINS 2
|
||||
|
||||
static struct config_pin config_pins[NUM_PINS] = {
|
||||
{ 0, 15 },
|
||||
{ 1, 16 }
|
||||
};
|
||||
|
||||
#endif
|
6
examples/fx_ring_mod/ios/Makefile
Normal file
6
examples/fx_ring_mod/ios/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
|
||||
NAME := bw_example_fx_ring_mod
|
||||
SOURCE := ${NAME}.c
|
||||
|
||||
include ${ROOT_DIR}/../../common/ios/ios.mk
|
62
examples/fx_ring_mod/src/bw_example_fx_ring_mod.c
Normal file
62
examples/fx_ring_mod/src/bw_example_fx_ring_mod.c
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2022, 2023 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Brickworks is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#include "bw_example_fx_ring_mod.h"
|
||||
|
||||
#include <bw_osc_sin.h>
|
||||
|
||||
void bw_example_fx_ring_mod_init(bw_example_fx_ring_mod *instance) {
|
||||
bw_phase_gen_init(&instance->phase_gen_coeffs);
|
||||
bw_ring_mod_init(&instance->ring_mod_coeffs);
|
||||
}
|
||||
|
||||
void bw_example_fx_ring_mod_set_sample_rate(bw_example_fx_ring_mod *instance, float sample_rate) {
|
||||
bw_phase_gen_set_sample_rate(&instance->phase_gen_coeffs, sample_rate);
|
||||
bw_ring_mod_set_sample_rate(&instance->ring_mod_coeffs, sample_rate);
|
||||
}
|
||||
|
||||
void bw_example_fx_ring_mod_reset(bw_example_fx_ring_mod *instance) {
|
||||
bw_phase_gen_reset_coeffs(&instance->phase_gen_coeffs);
|
||||
float v, v_inc;
|
||||
bw_phase_gen_reset_state(&instance->phase_gen_coeffs, &instance->phase_gen_state, 0.f, &v, &v_inc);
|
||||
bw_ring_mod_reset_coeffs(&instance->ring_mod_coeffs);
|
||||
}
|
||||
|
||||
void bw_example_fx_ring_mod_process(bw_example_fx_ring_mod *instance, const float** x, float** y, int n_samples) {
|
||||
bw_phase_gen_process(&instance->phase_gen_coeffs, &instance->phase_gen_state, NULL, y[0], NULL, n_samples);
|
||||
bw_osc_sin_process(y[0], y[0], n_samples);
|
||||
bw_ring_mod_process(&instance->ring_mod_coeffs, x[0], y[0], y[0], n_samples);
|
||||
}
|
||||
|
||||
void bw_example_fx_ring_mod_set_parameter(bw_example_fx_ring_mod *instance, int index, float value) {
|
||||
instance->params[index] = value;
|
||||
switch (index) {
|
||||
case p_freq:
|
||||
bw_phase_gen_set_frequency(&instance->phase_gen_coeffs, 100.f + (1000.f - 100.f) * value * value * value);
|
||||
break;
|
||||
case p_amount:
|
||||
bw_ring_mod_set_amount(&instance->ring_mod_coeffs, -1.f + 2.f * value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float bw_example_fx_ring_mod_get_parameter(bw_example_fx_ring_mod *instance, int index) {
|
||||
return instance->params[index];
|
||||
}
|
61
examples/fx_ring_mod/src/bw_example_fx_ring_mod.h
Normal file
61
examples/fx_ring_mod/src/bw_example_fx_ring_mod.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2023 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Brickworks is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#ifndef _BW_EXAMPLE_FX_RING_MOD_H
|
||||
#define _BW_EXAMPLE_FX_RING_MOD_H
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include <bw_ring_mod.h>
|
||||
#include <bw_phase_gen.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum {
|
||||
p_freq,
|
||||
p_amount,
|
||||
p_n
|
||||
};
|
||||
|
||||
struct _bw_example_fx_ring_mod {
|
||||
// Sub-components
|
||||
bw_phase_gen_coeffs phase_gen_coeffs;
|
||||
bw_phase_gen_state phase_gen_state;
|
||||
bw_ring_mod_coeffs ring_mod_coeffs;
|
||||
|
||||
// Parameters
|
||||
float params[p_n];
|
||||
};
|
||||
typedef struct _bw_example_fx_ring_mod bw_example_fx_ring_mod;
|
||||
|
||||
void bw_example_fx_ring_mod_init(bw_example_fx_ring_mod *instance);
|
||||
void bw_example_fx_ring_mod_set_sample_rate(bw_example_fx_ring_mod *instance, float sample_rate);
|
||||
void bw_example_fx_ring_mod_reset(bw_example_fx_ring_mod *instance);
|
||||
void bw_example_fx_ring_mod_process(bw_example_fx_ring_mod *instance, const float** x, float** y, int n_samples);
|
||||
void bw_example_fx_ring_mod_set_parameter(bw_example_fx_ring_mod *instance, int index, float value);
|
||||
float bw_example_fx_ring_mod_get_parameter(bw_example_fx_ring_mod *instance, int index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
88
examples/fx_ring_mod/src/config.h
Normal file
88
examples/fx_ring_mod/src/config.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2022, 2023 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Brickworks is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* File authors: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
// Definitions
|
||||
|
||||
#define IO_MONO 1
|
||||
#define IO_STEREO (1<<1)
|
||||
|
||||
struct config_io_bus {
|
||||
const char *name;
|
||||
char out;
|
||||
char aux;
|
||||
char cv;
|
||||
char configs;
|
||||
};
|
||||
|
||||
struct config_parameter {
|
||||
const char *name;
|
||||
const char *shortName;
|
||||
const char *units;
|
||||
char out;
|
||||
char bypass;
|
||||
int steps;
|
||||
float defaultValueUnmapped;
|
||||
};
|
||||
|
||||
// Data
|
||||
|
||||
#define COMPANY_NAME "Orastron"
|
||||
#define COMPANY_WEBSITE "https://www.orastron.com/"
|
||||
#define COMPANY_MAILTO "mailto:info@orastron.com"
|
||||
|
||||
#define PLUGIN_NAME "bw_example_fx_ring_mod"
|
||||
#define PLUGIN_VERSION "1.0.0"
|
||||
|
||||
#define NUM_BUSES_IN 1
|
||||
#define NUM_BUSES_OUT 1
|
||||
#define NUM_CHANNELS_IN 1
|
||||
#define NUM_CHANNELS_OUT 1
|
||||
|
||||
static struct config_io_bus config_buses_in[NUM_BUSES_IN] = {
|
||||
{ "Audio in", 0, 0, 0, IO_MONO }
|
||||
};
|
||||
|
||||
static struct config_io_bus config_buses_out[NUM_BUSES_OUT] = {
|
||||
{ "Audio out", 1, 0, 0, IO_MONO }
|
||||
};
|
||||
|
||||
#define NUM_PARAMETERS 2
|
||||
|
||||
static struct config_parameter config_parameters[NUM_PARAMETERS] = {
|
||||
{ "Frequency", "Freq", "Hz", 0, 0, 0, 0.5f },
|
||||
{ "Amount", "Amount", "", 0, 0, 0, 1.0f },
|
||||
};
|
||||
|
||||
// Internal API
|
||||
|
||||
#include "bw_example_fx_ring_mod.h"
|
||||
|
||||
#define P_TYPE bw_example_fx_ring_mod
|
||||
#define P_INIT bw_example_fx_ring_mod_init
|
||||
#define P_SET_SAMPLE_RATE bw_example_fx_ring_mod_set_sample_rate
|
||||
#define P_RESET bw_example_fx_ring_mod_reset
|
||||
#define P_PROCESS bw_example_fx_ring_mod_process
|
||||
#define P_SET_PARAMETER bw_example_fx_ring_mod_set_parameter
|
||||
#define P_GET_PARAMETER bw_example_fx_ring_mod_get_parameter
|
||||
|
||||
#endif
|
43
examples/fx_ring_mod/src/config.js
Normal file
43
examples/fx_ring_mod/src/config.js
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2023 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Brickworks is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
var buses = [
|
||||
{
|
||||
stereo: false,
|
||||
output: false
|
||||
},
|
||||
{
|
||||
stereo: false,
|
||||
output: true
|
||||
}
|
||||
];
|
||||
|
||||
var parameters = [
|
||||
{
|
||||
name: "Frequency",
|
||||
output: false,
|
||||
defaultValue: 0.5
|
||||
},
|
||||
{
|
||||
name: "Amount",
|
||||
output: false,
|
||||
defaultValue: 1.0
|
||||
}
|
||||
];
|
9
examples/fx_ring_mod/vst3/Makefile
Normal file
9
examples/fx_ring_mod/vst3/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
|
||||
NAME := bw_example_fx_ring_mod
|
||||
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_ring_mod.c
|
||||
|
||||
include ${ROOT_DIR}/../../common/vst3/vst3.mk
|
||||
|
||||
CXXFLAGS += -DRELEASE=1 -DNDEBUG -DBW_NO_DEBUG
|
||||
#CXXFLAGS += -DDEVELOPMENT=1 -DBW_DEBUG_DEEP
|
36
examples/fx_ring_mod/vst3/config_vst3.h
Normal file
36
examples/fx_ring_mod/vst3/config_vst3.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2022 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Brickworks is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* File authors: Stefano D'Angelo, Paolo Marrone
|
||||
*/
|
||||
|
||||
#ifndef _VST3_CONFIG_H
|
||||
#define _VST3_CONFIG_H
|
||||
|
||||
#define PLUGIN_SUBCATEGORY "Fx"
|
||||
|
||||
#define PLUGIN_GUID_1 0x2680121d
|
||||
#define PLUGIN_GUID_2 0x4e0b47fa
|
||||
#define PLUGIN_GUID_3 0xb213e6e7
|
||||
#define PLUGIN_GUID_4 0xd13cde60
|
||||
|
||||
#define CTRL_GUID_1 0xc747bf7a
|
||||
#define CTRL_GUID_2 0x90ac41d0
|
||||
#define CTRL_GUID_3 0xb53d3df9
|
||||
#define CTRL_GUID_4 0x2c81a74d
|
||||
|
||||
#endif
|
4
examples/fx_ring_mod/web/Makefile
Normal file
4
examples/fx_ring_mod/web/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_ring_mod.c
|
||||
|
||||
include ${ROOT_DIR}/../../common/web/web.mk
|
6
examples/fxpp_ring_mod/android/Makefile
Normal file
6
examples/fxpp_ring_mod/android/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
|
||||
NAME := bw_example_fxpp_ring_mod
|
||||
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fxpp_ring_mod.cpp
|
||||
|
||||
include ${ROOT_DIR}/../../common/android/android.mk
|
7
examples/fxpp_ring_mod/daisy-seed/Makefile
Normal file
7
examples/fxpp_ring_mod/daisy-seed/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
|
||||
TARGET = bw_example_fxpp_ring_mod
|
||||
|
||||
CPP_SOURCES_EXTRA = ${ROOT_DIR}/../src/bw_example_fxpp_ring_mod.cpp
|
||||
|
||||
include ${ROOT_DIR}/../../common/daisy-seed/daisy-seed.mk
|
36
examples/fxpp_ring_mod/daisy-seed/config_daisy_seed.h
Normal file
36
examples/fxpp_ring_mod/daisy-seed/config_daisy_seed.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2023 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Brickworks is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* File authors: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_DAISY_SEED_H
|
||||
#define _CONFIG_DAISY_SEED_H
|
||||
|
||||
struct config_pin {
|
||||
int param_index;
|
||||
int pin;
|
||||
};
|
||||
|
||||
#define NUM_PINS 2
|
||||
|
||||
static struct config_pin config_pins[NUM_PINS] = {
|
||||
{ 0, 15 },
|
||||
{ 1, 16 }
|
||||
};
|
||||
|
||||
#endif
|
6
examples/fxpp_ring_mod/ios/Makefile
Normal file
6
examples/fxpp_ring_mod/ios/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
|
||||
NAME := bw_example_fxpp_ring_mod
|
||||
SOURCE := ${NAME}.cpp
|
||||
|
||||
include ${ROOT_DIR}/../../common/ios/ios.mk
|
59
examples/fxpp_ring_mod/src/bw_example_fxpp_ring_mod.cpp
Normal file
59
examples/fxpp_ring_mod/src/bw_example_fxpp_ring_mod.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2023 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Brickworks is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#include "bw_example_fxpp_ring_mod.h"
|
||||
|
||||
#include <bw_osc_sin.h>
|
||||
|
||||
void bw_example_fxpp_ring_mod_init(bw_example_fxpp_ring_mod *instance) {
|
||||
(void)instance;
|
||||
}
|
||||
|
||||
void bw_example_fxpp_ring_mod_set_sample_rate(bw_example_fxpp_ring_mod *instance, float sample_rate) {
|
||||
instance->phaseGen.setSampleRate(sample_rate);
|
||||
instance->ringMod.setSampleRate(sample_rate);
|
||||
}
|
||||
|
||||
void bw_example_fxpp_ring_mod_reset(bw_example_fxpp_ring_mod *instance) {
|
||||
instance->phaseGen.reset();
|
||||
instance->ringMod.reset();
|
||||
}
|
||||
|
||||
void bw_example_fxpp_ring_mod_process(bw_example_fxpp_ring_mod *instance, const float** x, float** y, int n_samples) {
|
||||
instance->phaseGen.process({}, {y[0]}, {}, n_samples);
|
||||
oscSinProcess<1>({y[0]}, {y[0]}, n_samples);
|
||||
instance->ringMod.process({x[0]}, {y[0]}, {y[0]}, n_samples);
|
||||
}
|
||||
|
||||
void bw_example_fxpp_ring_mod_set_parameter(bw_example_fxpp_ring_mod *instance, int index, float value) {
|
||||
instance->params[index] = value;
|
||||
switch (index) {
|
||||
case p_freq:
|
||||
instance->phaseGen.setFrequency(100.f + (1000.f - 100.f) * value * value * value);
|
||||
break;
|
||||
case p_amount:
|
||||
instance->ringMod.setAmount(-1.f + 2.f * value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float bw_example_fxpp_ring_mod_get_parameter(bw_example_fxpp_ring_mod *instance, int index) {
|
||||
return instance->params[index];
|
||||
}
|
58
examples/fxpp_ring_mod/src/bw_example_fxpp_ring_mod.h
Normal file
58
examples/fxpp_ring_mod/src/bw_example_fxpp_ring_mod.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2023 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Brickworks is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#ifndef _BW_EXAMPLE_FXPP_WAH_H
|
||||
#define _BW_EXAMPLE_FXPP_WAH_H
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include <bw_ring_mod.h>
|
||||
#include <bw_phase_gen.h>
|
||||
|
||||
using namespace Brickworks;
|
||||
|
||||
extern "C" {
|
||||
|
||||
enum {
|
||||
p_freq,
|
||||
p_amount,
|
||||
p_n
|
||||
};
|
||||
|
||||
struct _bw_example_fxpp_ring_mod {
|
||||
// Sub-components
|
||||
PhaseGen<1> phaseGen;
|
||||
RingMod<1> ringMod;
|
||||
|
||||
// Parameters
|
||||
float params[p_n];
|
||||
};
|
||||
typedef struct _bw_example_fxpp_ring_mod bw_example_fxpp_ring_mod;
|
||||
|
||||
void bw_example_fxpp_ring_mod_init(bw_example_fxpp_ring_mod *instance);
|
||||
void bw_example_fxpp_ring_mod_set_sample_rate(bw_example_fxpp_ring_mod *instance, float sample_rate);
|
||||
void bw_example_fxpp_ring_mod_reset(bw_example_fxpp_ring_mod *instance);
|
||||
void bw_example_fxpp_ring_mod_process(bw_example_fxpp_ring_mod *instance, const float** x, float** y, int n_samples);
|
||||
void bw_example_fxpp_ring_mod_set_parameter(bw_example_fxpp_ring_mod *instance, int index, float value);
|
||||
float bw_example_fxpp_ring_mod_get_parameter(bw_example_fxpp_ring_mod *instance, int index);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
88
examples/fxpp_ring_mod/src/config.h
Normal file
88
examples/fxpp_ring_mod/src/config.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2023 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Brickworks is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* File authors: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
// Definitions
|
||||
|
||||
#define IO_MONO 1
|
||||
#define IO_STEREO (1<<1)
|
||||
|
||||
struct config_io_bus {
|
||||
const char *name;
|
||||
char out;
|
||||
char aux;
|
||||
char cv;
|
||||
char configs;
|
||||
};
|
||||
|
||||
struct config_parameter {
|
||||
const char *name;
|
||||
const char *shortName;
|
||||
const char *units;
|
||||
char out;
|
||||
char bypass;
|
||||
int steps;
|
||||
float defaultValueUnmapped;
|
||||
};
|
||||
|
||||
// Data
|
||||
|
||||
#define COMPANY_NAME "Orastron"
|
||||
#define COMPANY_WEBSITE "https://www.orastron.com/"
|
||||
#define COMPANY_MAILTO "mailto:info@orastron.com"
|
||||
|
||||
#define PLUGIN_NAME "bw_example_fxpp_ring_mod"
|
||||
#define PLUGIN_VERSION "1.0.0"
|
||||
|
||||
#define NUM_BUSES_IN 1
|
||||
#define NUM_BUSES_OUT 1
|
||||
#define NUM_CHANNELS_IN 1
|
||||
#define NUM_CHANNELS_OUT 1
|
||||
|
||||
static struct config_io_bus config_buses_in[NUM_BUSES_IN] = {
|
||||
{ "Audio in", 0, 0, 0, IO_MONO }
|
||||
};
|
||||
|
||||
static struct config_io_bus config_buses_out[NUM_BUSES_OUT] = {
|
||||
{ "Audio out", 1, 0, 0, IO_MONO }
|
||||
};
|
||||
|
||||
#define NUM_PARAMETERS 2
|
||||
|
||||
static struct config_parameter config_parameters[NUM_PARAMETERS] = {
|
||||
{ "Frequency", "Freq", "Hz", 0, 0, 0, 0.5f },
|
||||
{ "Amount", "Amount", "", 0, 0, 0, 1.0f },
|
||||
};
|
||||
|
||||
// Internal API
|
||||
|
||||
#include "bw_example_fxpp_ring_mod.h"
|
||||
|
||||
#define P_TYPE bw_example_fxpp_ring_mod
|
||||
#define P_INIT bw_example_fxpp_ring_mod_init
|
||||
#define P_SET_SAMPLE_RATE bw_example_fxpp_ring_mod_set_sample_rate
|
||||
#define P_RESET bw_example_fxpp_ring_mod_reset
|
||||
#define P_PROCESS bw_example_fxpp_ring_mod_process
|
||||
#define P_SET_PARAMETER bw_example_fxpp_ring_mod_set_parameter
|
||||
#define P_GET_PARAMETER bw_example_fxpp_ring_mod_get_parameter
|
||||
|
||||
#endif
|
43
examples/fxpp_ring_mod/src/config.js
Normal file
43
examples/fxpp_ring_mod/src/config.js
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2023 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Brickworks is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
var buses = [
|
||||
{
|
||||
stereo: false,
|
||||
output: false
|
||||
},
|
||||
{
|
||||
stereo: false,
|
||||
output: true
|
||||
}
|
||||
];
|
||||
|
||||
var parameters = [
|
||||
{
|
||||
name: "Frequency",
|
||||
output: false,
|
||||
defaultValue: 0.5
|
||||
},
|
||||
{
|
||||
name: "Amount",
|
||||
output: false,
|
||||
defaultValue: 1.0
|
||||
}
|
||||
];
|
9
examples/fxpp_ring_mod/vst3/Makefile
Normal file
9
examples/fxpp_ring_mod/vst3/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
|
||||
NAME := bw_example_fxpp_ring_mod
|
||||
SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fxpp_ring_mod.cpp
|
||||
|
||||
include ${ROOT_DIR}/../../common/vst3/vst3.mk
|
||||
|
||||
CXXFLAGS += -DRELEASE=1 -DNDEBUG -DBW_NO_DEBUG
|
||||
#CXXFLAGS += -DDEVELOPMENT=1 -DBW_DEBUG_DEEP
|
36
examples/fxpp_ring_mod/vst3/config_vst3.h
Normal file
36
examples/fxpp_ring_mod/vst3/config_vst3.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2023 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Brickworks is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* File authors: Stefano D'Angelo, Paolo Marrone
|
||||
*/
|
||||
|
||||
#ifndef _VST3_CONFIG_H
|
||||
#define _VST3_CONFIG_H
|
||||
|
||||
#define PLUGIN_SUBCATEGORY "Fx"
|
||||
|
||||
#define PLUGIN_GUID_1 0xf4737471
|
||||
#define PLUGIN_GUID_2 0xb94c4c95
|
||||
#define PLUGIN_GUID_3 0x8f4091ce
|
||||
#define PLUGIN_GUID_4 0x5da09fa8
|
||||
|
||||
#define CTRL_GUID_1 0x1e8f7e86
|
||||
#define CTRL_GUID_2 0xc29447c1
|
||||
#define CTRL_GUID_3 0x91f175ce
|
||||
#define CTRL_GUID_4 0x220b5635
|
||||
|
||||
#endif
|
@ -39,6 +39,8 @@
|
||||
* <li>Added overloaded C++ <code>process()</code> function taking
|
||||
* C-style arrays as arguments.</li>
|
||||
* <li>Removed usage of reserved identifiers.</li>
|
||||
* <li>Clearly specified parameter validity ranges.</li>
|
||||
* <li>Added debugging code.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>Version <strong>0.6.0</strong>:
|
||||
@ -73,44 +75,58 @@ typedef struct bw_dry_wet_coeffs bw_dry_wet_coeffs;
|
||||
*
|
||||
* #### bw_dry_wet_init()
|
||||
* ```>>> */
|
||||
static inline void bw_dry_wet_init(bw_dry_wet_coeffs *BW_RESTRICT coeffs);
|
||||
static inline void bw_dry_wet_init(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs);
|
||||
/*! <<<```
|
||||
* Initializes input parameter values in `coeffs`.
|
||||
*
|
||||
* #### bw_dry_wet_set_sample_rate()
|
||||
* ```>>> */
|
||||
static inline void bw_dry_wet_set_sample_rate(bw_dry_wet_coeffs *BW_RESTRICT coeffs, float sample_rate);
|
||||
static inline void bw_dry_wet_set_sample_rate(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs,
|
||||
float sample_rate);
|
||||
/*! <<<```
|
||||
* Sets the `sample_rate` (Hz) value in `coeffs`.
|
||||
*
|
||||
* #### bw_dry_wet_reset_coeffs()
|
||||
* ```>>> */
|
||||
static inline void bw_dry_wet_reset_coeffs(bw_dry_wet_coeffs *BW_RESTRICT coeffs);
|
||||
static inline void bw_dry_wet_reset_coeffs(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs);
|
||||
/*! <<<```
|
||||
* Resets coefficients in `coeffs` to assume their target values.
|
||||
*
|
||||
* #### bw_dry_wet_update_coeffs_ctrl()
|
||||
* ```>>> */
|
||||
static inline void bw_dry_wet_update_coeffs_ctrl(bw_dry_wet_coeffs *BW_RESTRICT coeffs);
|
||||
static inline void bw_dry_wet_update_coeffs_ctrl(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs);
|
||||
/*! <<<```
|
||||
* Triggers control-rate update of coefficients in `coeffs`.
|
||||
*
|
||||
* #### bw_dry_wet_update_coeffs_audio()
|
||||
* ```>>> */
|
||||
static inline void bw_dry_wet_update_coeffs_audio(bw_dry_wet_coeffs *BW_RESTRICT coeffs);
|
||||
static inline void bw_dry_wet_update_coeffs_audio(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs);
|
||||
/*! <<<```
|
||||
* Triggers audio-rate update of coefficients in `coeffs`.
|
||||
*
|
||||
* #### bw_dry_wet_process1()
|
||||
* ```>>> */
|
||||
static inline float bw_dry_wet_process1(const bw_dry_wet_coeffs *BW_RESTRICT coeffs, float x_dry, float x_wet);
|
||||
static inline float bw_dry_wet_process1(
|
||||
const bw_dry_wet_coeffs * BW_RESTRICT coeffs,
|
||||
float x_dry,
|
||||
float x_wet);
|
||||
/*! <<<```
|
||||
* Processes one dry input sample `x_dry` and one wet input sample `x_wet`
|
||||
* using `coeffs` and returns the corresponding output sample.
|
||||
*
|
||||
* #### bw_dry_wet_process()
|
||||
* ```>>> */
|
||||
static inline void bw_dry_wet_process(bw_dry_wet_coeffs *BW_RESTRICT coeffs, const float *x_dry, const float *x_wet, float *y, size_t n_samples);
|
||||
static inline void bw_dry_wet_process(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs,
|
||||
const float * x_dry,
|
||||
const float * x_wet,
|
||||
float * y,
|
||||
size_t n_samples);
|
||||
/*! <<<```
|
||||
* Processes the first `n_samples` of the dry input buffer `x_dry` and of the
|
||||
* wet input buffer `x_wet` and fills the first `n_samples` of the output
|
||||
@ -118,7 +134,13 @@ static inline void bw_dry_wet_process(bw_dry_wet_coeffs *BW_RESTRICT coeffs, con
|
||||
*
|
||||
* #### bw_dry_wet_process_multi()
|
||||
* ```>>> */
|
||||
static inline void bw_dry_wet_process_multi(bw_dry_wet_coeffs *BW_RESTRICT coeffs, const float * const *x_dry, const float * const *x_wet, float * const *y, size_t n_channels, size_t n_samples);
|
||||
static inline void bw_dry_wet_process_multi(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs,
|
||||
const float * const * x_dry,
|
||||
const float * const * x_wet,
|
||||
float * const * y,
|
||||
size_t n_channels,
|
||||
size_t n_samples);
|
||||
/*! <<<```
|
||||
* Processes the first `n_samples` of the `n_channels` dry input buffers
|
||||
* `x_dry` and of the `n_channels` wet input buffers `x_wet`, and fills the
|
||||
@ -127,19 +149,39 @@ static inline void bw_dry_wet_process_multi(bw_dry_wet_coeffs *BW_RESTRICT coeff
|
||||
*
|
||||
* #### bw_dry_wet_set_wet()
|
||||
* ```>>> */
|
||||
static inline void bw_dry_wet_set_wet(bw_dry_wet_coeffs *BW_RESTRICT coeffs, float value);
|
||||
static inline void bw_dry_wet_set_wet(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs,
|
||||
float value);
|
||||
/*! <<<```
|
||||
* Sets the wet gain parameter to the given `value` (linear gain) in `coeffs`.
|
||||
*
|
||||
* Valid range: [`0.f`, `1.f`].
|
||||
*
|
||||
* Default value: `1.f`.
|
||||
*
|
||||
* #### bw_dry_wet_set_smooth_tau()
|
||||
* ```>>> */
|
||||
static inline void bw_dry_wet_set_smooth_tau(bw_dry_wet_coeffs *BW_RESTRICT coeffs, float value);
|
||||
static inline void bw_dry_wet_set_smooth_tau(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs,
|
||||
float value);
|
||||
/*! <<<```
|
||||
* Sets the smoothing time constant `value` (s) in `coeffs`.
|
||||
*
|
||||
* `value` must be non-negative.
|
||||
*
|
||||
* Default value: `0.05f`.
|
||||
*
|
||||
* #### bw_dry_wet_coeffs_is_valid()
|
||||
* ```>>> */
|
||||
static inline char bw_dry_wet_coeffs_is_valid(
|
||||
const bw_dry_wet_coeffs * BW_RESTRICT coeffs);
|
||||
/*! <<<```
|
||||
* Tries to determine whether `coeffs` is valid and returns non-`0` if it
|
||||
* seems to be the case and `0` if it is certainly not. False positives are
|
||||
* possible, false negatives are not.
|
||||
*
|
||||
* `coeffs` must at least point to a readable memory block of size greater
|
||||
* than or equal to that of `bw_dry_wet_coeffs`.
|
||||
* }}} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -157,58 +199,207 @@ static inline void bw_dry_wet_set_smooth_tau(bw_dry_wet_coeffs *BW_RESTRICT coef
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef BW_DEBUG_DEEP
|
||||
enum bw_dry_wet_coeffs_state {
|
||||
bw_dry_wet_coeffs_state_invalid,
|
||||
bw_dry_wet_coeffs_state_init,
|
||||
bw_dry_wet_coeffs_state_set_sample_rate,
|
||||
bw_dry_wet_coeffs_state_reset_coeffs
|
||||
};
|
||||
#endif
|
||||
|
||||
struct bw_dry_wet_coeffs {
|
||||
#ifdef BW_DEBUG_DEEP
|
||||
uint32_t hash;
|
||||
enum bw_dry_wet_coeffs_state state;
|
||||
#endif
|
||||
|
||||
// Sub-components
|
||||
bw_gain_coeffs gain_coeffs;
|
||||
};
|
||||
|
||||
static inline void bw_dry_wet_init(bw_dry_wet_coeffs *BW_RESTRICT coeffs) {
|
||||
static inline void bw_dry_wet_init(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
|
||||
bw_gain_init(&coeffs->gain_coeffs);
|
||||
|
||||
#ifdef BW_DEBUG_DEEP
|
||||
coeffs->hash = bw_hash_sdbm("bw_dry_wet_coeffs");
|
||||
coeffs->state = bw_dry_wet_coeffs_state_init;
|
||||
#endif
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state == bw_dry_wet_coeffs_state_init);
|
||||
}
|
||||
|
||||
static inline void bw_dry_wet_set_sample_rate(bw_dry_wet_coeffs *BW_RESTRICT coeffs, float sample_rate) {
|
||||
static inline void bw_dry_wet_set_sample_rate(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs,
|
||||
float sample_rate) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_init);
|
||||
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
|
||||
|
||||
bw_gain_set_sample_rate(&coeffs->gain_coeffs, sample_rate);
|
||||
|
||||
#ifdef BW_DEBUG_DEEP
|
||||
coeffs->state = bw_dry_wet_coeffs_state_set_sample_rate;
|
||||
#endif
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state == bw_dry_wet_coeffs_state_set_sample_rate);
|
||||
}
|
||||
|
||||
static inline void bw_dry_wet_reset_coeffs(bw_dry_wet_coeffs *BW_RESTRICT coeffs) {
|
||||
static inline void bw_dry_wet_reset_coeffs(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_set_sample_rate);
|
||||
|
||||
bw_gain_reset_coeffs(&coeffs->gain_coeffs);
|
||||
|
||||
#ifdef BW_DEBUG_DEEP
|
||||
coeffs->state = bw_dry_wet_coeffs_state_reset_coeffs;
|
||||
#endif
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state == bw_dry_wet_coeffs_state_reset_coeffs);
|
||||
}
|
||||
|
||||
static inline void bw_dry_wet_update_coeffs_ctrl(bw_dry_wet_coeffs *BW_RESTRICT coeffs) {
|
||||
static inline void bw_dry_wet_update_coeffs_ctrl(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
|
||||
|
||||
bw_gain_update_coeffs_ctrl(&coeffs->gain_coeffs);
|
||||
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
|
||||
}
|
||||
|
||||
static inline void bw_dry_wet_update_coeffs_audio(bw_dry_wet_coeffs *BW_RESTRICT coeffs) {
|
||||
static inline void bw_dry_wet_update_coeffs_audio(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
|
||||
|
||||
bw_gain_update_coeffs_audio(&coeffs->gain_coeffs);
|
||||
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
|
||||
}
|
||||
|
||||
static inline float bw_dry_wet_process1(const bw_dry_wet_coeffs *BW_RESTRICT coeffs, float x_dry, float x_wet) {
|
||||
return bw_gain_process1(&coeffs->gain_coeffs, x_wet - x_dry) + x_dry;
|
||||
static inline float bw_dry_wet_process1(
|
||||
const bw_dry_wet_coeffs * BW_RESTRICT coeffs,
|
||||
float x_dry,
|
||||
float x_wet) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
|
||||
BW_ASSERT(bw_is_finite(x_dry));
|
||||
BW_ASSERT(bw_is_finite(x_wet));
|
||||
|
||||
const float y = bw_gain_process1(&coeffs->gain_coeffs, x_wet - x_dry) + x_dry;
|
||||
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
|
||||
BW_ASSERT(bw_is_finite(*y));
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
static inline void bw_dry_wet_process(bw_dry_wet_coeffs *BW_RESTRICT coeffs, const float *x_dry, const float *x_wet, float *y, size_t n_samples) {
|
||||
static inline void bw_dry_wet_process(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs,
|
||||
const float * x_dry,
|
||||
const float * x_wet,
|
||||
float * y,
|
||||
size_t n_samples) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
|
||||
BW_ASSERT(x_dry != NULL);
|
||||
BW_ASSERT_DEEP(bw_has_only_finite(x_dry, n_samples));
|
||||
BW_ASSERT(x_wet != NULL);
|
||||
BW_ASSERT_DEEP(bw_has_only_finite(x_wet, n_samples));
|
||||
BW_ASSERT(y != NULL);
|
||||
|
||||
bw_dry_wet_update_coeffs_ctrl(coeffs);
|
||||
for (size_t i = 0; i < n_samples; i++) {
|
||||
bw_dry_wet_update_coeffs_audio(coeffs);
|
||||
y[i] = bw_dry_wet_process1(coeffs, x_dry[i], x_wet[i]);
|
||||
}
|
||||
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
|
||||
BW_ASSERT_DEEP(bw_has_only_finite(y, n_samples));
|
||||
}
|
||||
|
||||
static inline void bw_dry_wet_process_multi(bw_dry_wet_coeffs *BW_RESTRICT coeffs, const float * const *x_dry, const float * const *x_wet, float * const *y, size_t n_channels, size_t n_samples) {
|
||||
static inline void bw_dry_wet_process_multi(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs,
|
||||
const float * const * x_dry,
|
||||
const float * const * x_wet,
|
||||
float * const * y,
|
||||
size_t n_channels,
|
||||
size_t n_samples) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
|
||||
BW_ASSERT(x_dry != NULL);
|
||||
BW_ASSERT(x_wet != NULL);
|
||||
BW_ASSERT(y != NULL);
|
||||
|
||||
bw_dry_wet_update_coeffs_ctrl(coeffs);
|
||||
for (size_t i = 0; i < n_samples; i++) {
|
||||
bw_dry_wet_update_coeffs_audio(coeffs);
|
||||
for (size_t j = 0; j < n_channels; j++)
|
||||
y[j][i] = bw_dry_wet_process1(coeffs, x_dry[j][i], x_wet[j][i]);
|
||||
}
|
||||
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
|
||||
}
|
||||
|
||||
static inline void bw_dry_wet_set_wet(bw_dry_wet_coeffs *BW_RESTRICT coeffs, float value) {
|
||||
static inline void bw_dry_wet_set_wet(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs,
|
||||
float value) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_init);
|
||||
BW_ASSERT(bw_is_finite(value));
|
||||
BW_ASSERT(value >= 0.f && value <= 1.f);
|
||||
|
||||
bw_gain_set_gain_lin(&coeffs->gain_coeffs, value);
|
||||
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_init);
|
||||
}
|
||||
|
||||
static inline void bw_dry_wet_set_smooth_tau(bw_dry_wet_coeffs *BW_RESTRICT coeffs, float value) {
|
||||
static inline void bw_dry_wet_set_smooth_tau(
|
||||
bw_dry_wet_coeffs * BW_RESTRICT coeffs,
|
||||
float value) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_init);
|
||||
BW_ASSERT(bw_is_finite(value));
|
||||
BW_ASSERT(value >= 0.f);
|
||||
|
||||
bw_gain_set_smooth_tau(&coeffs->gain_coeffs, value);
|
||||
|
||||
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_init);
|
||||
}
|
||||
|
||||
static inline char bw_dry_wet_coeffs_is_valid(
|
||||
const bw_dry_wet_coeffs * BW_RESTRICT coeffs) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
|
||||
#ifdef BW_DEBUG_DEEP
|
||||
if (coeffs->hash != bw_hash_sdbm("bw_dry_wet_coeffs"))
|
||||
return 0;
|
||||
if (coeffs->state < bw_dry_wet_coeffs_state_init || coeffs->state > bw_dry_wet_coeffs_state_reset_coeffs)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return bw_gain_coeffs_is_valid(&coeffs->gain_coeffs);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -241,8 +432,28 @@ public:
|
||||
std::array<float *, N_CHANNELS> y,
|
||||
size_t nSamples);
|
||||
|
||||
void setWet(float value);
|
||||
void setSmoothTau(float value);
|
||||
void setSampleRate(
|
||||
float sampleRate);
|
||||
|
||||
void reset();
|
||||
|
||||
void process(
|
||||
const float * const * xDry,
|
||||
const float * const * xWet,
|
||||
float * const * y,
|
||||
size_t nSamples);
|
||||
|
||||
void process(
|
||||
std::array<const float *, N_CHANNELS> xDry,
|
||||
std::array<const float *, N_CHANNELS> xWet,
|
||||
std::array<float *, N_CHANNELS> y,
|
||||
size_t nSamples);
|
||||
|
||||
void setWet(
|
||||
float value);
|
||||
|
||||
void setSmoothTau(
|
||||
float value);
|
||||
/*! <<<...
|
||||
* }
|
||||
* ```
|
||||
@ -263,7 +474,8 @@ inline DryWet<N_CHANNELS>::DryWet() {
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void DryWet<N_CHANNELS>::setSampleRate(float sampleRate) {
|
||||
inline void DryWet<N_CHANNELS>::setSampleRate(
|
||||
float sampleRate) {
|
||||
bw_dry_wet_set_sample_rate(&coeffs, sampleRate);
|
||||
}
|
||||
|
||||
@ -274,29 +486,31 @@ inline void DryWet<N_CHANNELS>::reset() {
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void DryWet<N_CHANNELS>::process(
|
||||
const float * const *x_dry,
|
||||
const float * const *x_wet,
|
||||
const float * const * xDry,
|
||||
const float * const * xWet,
|
||||
float * const * y,
|
||||
size_t nSamples) {
|
||||
bw_dry_wet_process_multi(&coeffs, x_dry, x_wet, y, N_CHANNELS, nSamples);
|
||||
bw_dry_wet_process_multi(&coeffs, xDry, xWet, y, N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void DryWet<N_CHANNELS>::process(
|
||||
std::array<const float *, N_CHANNELS> x_dry,
|
||||
std::array<const float *, N_CHANNELS> x_wet,
|
||||
std::array<const float *, N_CHANNELS> xDry,
|
||||
std::array<const float *, N_CHANNELS> xWet,
|
||||
std::array<float *, N_CHANNELS> y,
|
||||
size_t nSamples) {
|
||||
process(x_dry.data(), x_wet.data(), y.data(), nSamples);
|
||||
process(xDry.data(), xWet.data(), y.data(), nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void DryWet<N_CHANNELS>::setWet(float value) {
|
||||
inline void DryWet<N_CHANNELS>::setWet(
|
||||
float value) {
|
||||
bw_dry_wet_set_wet(&coeffs, value);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void DryWet<N_CHANNELS>::setSmoothTau(float value) {
|
||||
inline void DryWet<N_CHANNELS>::setSmoothTau(
|
||||
float value) {
|
||||
bw_dry_wet_set_smooth_tau(&coeffs, value);
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ static inline void bw_osc_pulse_update_coeffs_audio(bw_osc_pulse_coeffs *BW_REST
|
||||
static inline float bw_osc_pulse_process1(const bw_osc_pulse_coeffs *BW_RESTRICT coeffs, float x);
|
||||
static inline float bw_osc_pulse_process1_antialias(const bw_osc_pulse_coeffs *BW_RESTRICT coeffs, float x, float x_phase_inc);
|
||||
/*! <<<```
|
||||
* These function process one input sample `x`, indicating the normalized
|
||||
* These function process one input sample `x`, representing the normalized
|
||||
* phase, using `coeffs`. They return the corresponding output sample.
|
||||
*
|
||||
* In particular:
|
||||
|
@ -106,7 +106,7 @@ static inline void bw_osc_saw_init(bw_osc_saw_coeffs *BW_RESTRICT coeffs);
|
||||
static inline float bw_osc_saw_process1(const bw_osc_saw_coeffs *BW_RESTRICT coeffs, float x);
|
||||
static inline float bw_osc_saw_process1_antialias(const bw_osc_saw_coeffs *BW_RESTRICT coeffs, float x, float x_phase_inc);
|
||||
/*! <<<```
|
||||
* These function process one input sample `x`, indicating the normalized
|
||||
* These function process one input sample `x`, representing the normalized
|
||||
* phase, using `coeffs`. They return the corresponding output sample.
|
||||
*
|
||||
* In particular:
|
||||
|
@ -41,6 +41,7 @@
|
||||
* <li>Added overloaded C++ <code>oscSinProcess()</code> function taking
|
||||
* C-style arrays as arguments.</li>
|
||||
* <li>Removed usage of reserved identifiers.</li>
|
||||
* <li>Added debugging code.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>Version <strong>0.6.0</strong>:
|
||||
@ -80,15 +81,18 @@ extern "C" {
|
||||
/*! api {{{
|
||||
* #### bw_osc_sin_process1()
|
||||
* ```>>> */
|
||||
static inline float bw_osc_sin_process1(float x);
|
||||
static inline float bw_osc_sin_process1(
|
||||
float x);
|
||||
/*! <<<```
|
||||
* Processes one input sample `x`, indicating the normalized phase, and
|
||||
* returns the corresponding output
|
||||
* sample.
|
||||
* Processes one input sample `x`, representing the normalized phase, and
|
||||
* returns the corresponding output sample.
|
||||
*
|
||||
* #### bw_osc_sin_process()
|
||||
* ```>>> */
|
||||
static inline void bw_osc_sin_process(const float *x, float *y, size_t n_samples);
|
||||
static inline void bw_osc_sin_process(
|
||||
const float * x,
|
||||
float * y,
|
||||
size_t n_samples);
|
||||
/*! <<<```
|
||||
* Processes the first `n_samples` of the input buffer `x`, containing the
|
||||
* normalized phase signal, and fills the first `n_samples` of the output
|
||||
@ -96,7 +100,11 @@ static inline void bw_osc_sin_process(const float *x, float *y, size_t n_samples
|
||||
*
|
||||
* #### bw_osc_sin_process_multi()
|
||||
* ```>>> */
|
||||
static inline void bw_osc_sin_process_multi(const float * const *x, float * const *y, size_t n_channels, size_t n_samples);
|
||||
static inline void bw_osc_sin_process_multi(
|
||||
const float * const * x,
|
||||
float * const * y,
|
||||
size_t n_channels,
|
||||
size_t n_samples);
|
||||
/*! <<<```
|
||||
* Processes the first `n_samples` of the `n_channels` input buffers `x`,
|
||||
* containing the normalized phase signals, and fills the first `n_samples`
|
||||
@ -118,16 +126,39 @@ static inline void bw_osc_sin_process_multi(const float * const *x, float * cons
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline float bw_osc_sin_process1(float x) {
|
||||
return bw_sin2pif(x);
|
||||
static inline float bw_osc_sin_process1(
|
||||
float x) {
|
||||
BW_ASSERT(bw_is_finite(x));
|
||||
|
||||
const float y = bw_sin2pif(x);
|
||||
|
||||
BW_ASSERT(bw_is_finite(y));
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
static inline void bw_osc_sin_process(const float *x, float *y, size_t n_samples) {
|
||||
static inline void bw_osc_sin_process(
|
||||
const float * x,
|
||||
float * y,
|
||||
size_t n_samples) {
|
||||
BW_ASSERT(x != NULL);
|
||||
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
|
||||
BW_ASSERT(y != NULL);
|
||||
|
||||
for (size_t i = 0; i < n_samples; i++)
|
||||
y[i] = bw_osc_sin_process1(x[i]);
|
||||
|
||||
BW_ASSERT_DEEP(bw_has_only_finite(y, n_samples));
|
||||
}
|
||||
|
||||
static inline void bw_osc_sin_process_multi(const float * const *x, float * const *y, size_t n_channels, size_t n_samples) {
|
||||
static inline void bw_osc_sin_process_multi(
|
||||
const float * const * x,
|
||||
float * const * y,
|
||||
size_t n_channels,
|
||||
size_t n_samples) {
|
||||
BW_ASSERT(x != NULL);
|
||||
BW_ASSERT(y != NULL);
|
||||
|
||||
for (size_t i = 0; i < n_channels; i++)
|
||||
bw_osc_sin_process(x[i], y[i], n_samples);
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ static inline void bw_osc_tri_update_coeffs_audio(bw_osc_tri_coeffs *BW_RESTRICT
|
||||
static inline float bw_osc_tri_process1(const bw_osc_tri_coeffs *BW_RESTRICT coeffs, float x);
|
||||
static inline float bw_osc_tri_process1_antialias(const bw_osc_tri_coeffs *BW_RESTRICT coeffs, float x, float x_phase_inc);
|
||||
/*! <<<```
|
||||
* These function process one input sample `x`, indicating the normalized
|
||||
* These function process one input sample `x`, representing the normalized
|
||||
* phase, using `coeffs`. They return the corresponding output sample.
|
||||
*
|
||||
* In particular:
|
||||
|
@ -39,6 +39,9 @@
|
||||
* <li>Added overloaded C++ <code>process()</code> function taking
|
||||
* C-style arrays as arguments.</li>
|
||||
* <li>Removed usage of reserved identifiers.</li>
|
||||
* <li>Fixed inverted-polarity modulation (for real this time).</li>
|
||||
* <li>Clearly specified parameter validity ranges.</li>
|
||||
* <li>Added debugging code.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>Version <strong>0.6.0</strong>:
|
||||
@ -81,44 +84,58 @@ typedef struct bw_ring_mod_coeffs bw_ring_mod_coeffs;
|
||||
*
|
||||
* #### bw_ring_mod_init()
|
||||
* ```>>> */
|
||||
static inline void bw_ring_mod_init(bw_ring_mod_coeffs *BW_RESTRICT coeffs);
|
||||
static inline void bw_ring_mod_init(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs);
|
||||
/*! <<<```
|
||||
* Initializes input parameter values in `coeffs`.
|
||||
*
|
||||
* #### bw_ring_mod_set_sample_rate()
|
||||
* ```>>> */
|
||||
static inline void bw_ring_mod_set_sample_rate(bw_ring_mod_coeffs *BW_RESTRICT coeffs, float sample_rate);
|
||||
static inline void bw_ring_mod_set_sample_rate(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs,
|
||||
float sample_rate);
|
||||
/*! <<<```
|
||||
* Sets the `sample_rate` (Hz) value in `coeffs`.
|
||||
*
|
||||
* #### bw_ring_mod_reset_coeffs()
|
||||
* ```>>> */
|
||||
static inline void bw_ring_mod_reset_coeffs(bw_ring_mod_coeffs *BW_RESTRICT coeffs);
|
||||
static inline void bw_ring_mod_reset_coeffs(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs);
|
||||
/*! <<<```
|
||||
* Resets coefficients in `coeffs` to assume their target values.
|
||||
*
|
||||
* #### bw_ring_mod_update_coeffs_ctrl()
|
||||
* ```>>> */
|
||||
static inline void bw_ring_mod_update_coeffs_ctrl(bw_ring_mod_coeffs *BW_RESTRICT coeffs);
|
||||
static inline void bw_ring_mod_update_coeffs_ctrl(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs);
|
||||
/*! <<<```
|
||||
* Triggers control-rate update of coefficients in `coeffs`.
|
||||
*
|
||||
* #### bw_ring_mod_update_coeffs_audio()
|
||||
* ```>>> */
|
||||
static inline void bw_ring_mod_update_coeffs_audio(bw_ring_mod_coeffs *BW_RESTRICT coeffs);
|
||||
static inline void bw_ring_mod_update_coeffs_audio(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs);
|
||||
/*! <<<```
|
||||
* Triggers audio-rate update of coefficients in `coeffs`.
|
||||
*
|
||||
* #### bw_ring_mod_process1()
|
||||
* ```>>> */
|
||||
static inline float bw_ring_mod_process1(const bw_ring_mod_coeffs *BW_RESTRICT coeffs, float x_mod, float x_car);
|
||||
static inline float bw_ring_mod_process1(
|
||||
const bw_ring_mod_coeffs * BW_RESTRICT coeffs,
|
||||
float x_mod,
|
||||
float x_car);
|
||||
/*! <<<```
|
||||
* Processes one modulation input sample `x_mod` and one carrier input sample
|
||||
* `x_car` using `coeffs` and returns the corresponding output sample.
|
||||
*
|
||||
* #### bw_ring_mod_process()
|
||||
* ```>>> */
|
||||
static inline void bw_ring_mod_process(bw_ring_mod_coeffs *BW_RESTRICT coeffs, const float *x_mod, const float *x_car, float *y, size_t n_samples);
|
||||
static inline void bw_ring_mod_process(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs,
|
||||
const float * x_mod,
|
||||
const float * x_car,
|
||||
float * y,
|
||||
size_t n_samples);
|
||||
/*! <<<```
|
||||
* Processes the first `n_samples` of the modulation input buffer `x_mod` and
|
||||
* of the carrier input buffer `x_car` and fills the first `n_samples` of the
|
||||
@ -127,7 +144,13 @@ static inline void bw_ring_mod_process(bw_ring_mod_coeffs *BW_RESTRICT coeffs, c
|
||||
*
|
||||
* #### bw_ring_mod_process_multi()
|
||||
* ```>>> */
|
||||
static inline void bw_ring_mod_process_multi(bw_ring_mod_coeffs *BW_RESTRICT coeffs, const float * const *x_mod, const float * const *x_car, float * const *y, size_t n_channels, size_t n_samples);
|
||||
static inline void bw_ring_mod_process_multi(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs,
|
||||
const float * const * x_mod,
|
||||
const float * const * x_car,
|
||||
float * const * y,
|
||||
size_t n_channels,
|
||||
size_t n_samples);
|
||||
/*! <<<```
|
||||
* Processes the first `n_samples` of the `n_channels` modulation input
|
||||
* buffers `x_mod` and of the `n_channels` carrier input buffers `x_car`, and
|
||||
@ -136,13 +159,30 @@ static inline void bw_ring_mod_process_multi(bw_ring_mod_coeffs *BW_RESTRICT coe
|
||||
*
|
||||
* #### bw_ring_mod_set_amount()
|
||||
* ```>>> */
|
||||
static inline void bw_ring_mod_set_amount(bw_ring_mod_coeffs *BW_RESTRICT coeffs, float value);
|
||||
static inline void bw_ring_mod_set_amount(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs,
|
||||
float value);
|
||||
/*! <<<```
|
||||
* Sets the modulation amount parameter to the given `value` (`0.f` = no
|
||||
* modulation, `1.f` = full modulation, `-1.f` = full modulation with
|
||||
* inverted polarity) in `coeffs`.
|
||||
*
|
||||
* Valid range: [`-1.f` (full modulation with inverted polarity),
|
||||
* `1.f` (full modulation)].
|
||||
*
|
||||
* Default value: `1.f`.
|
||||
*
|
||||
* #### bw_ring_mod_coeffs_is_valid()
|
||||
* ```>>> */
|
||||
static inline char bw_ring_mod_coeffs_is_valid(
|
||||
const bw_ring_mod_coeffs * BW_RESTRICT coeffs);
|
||||
/*! <<<```
|
||||
* Tries to determine whether `coeffs` is valid and returns non-`0` if it
|
||||
* seems to be the case and `0` if it is certainly not. False positives are
|
||||
* possible, false negatives are not.
|
||||
*
|
||||
* `coeffs` must at least point to a readable memory block of size greater
|
||||
* than or equal to that of `bw_ring_mod_coeffs`.
|
||||
* }}} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -161,7 +201,21 @@ static inline void bw_ring_mod_set_amount(bw_ring_mod_coeffs *BW_RESTRICT coeffs
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef BW_DEBUG_DEEP
|
||||
enum bw_ring_mod_coeffs_state {
|
||||
bw_ring_mod_coeffs_state_invalid,
|
||||
bw_ring_mod_coeffs_state_init,
|
||||
bw_ring_mod_coeffs_state_set_sample_rate,
|
||||
bw_ring_mod_coeffs_state_reset_coeffs
|
||||
};
|
||||
#endif
|
||||
|
||||
struct bw_ring_mod_coeffs {
|
||||
#ifdef BW_DEBUG_DEEP
|
||||
uint32_t hash;
|
||||
enum bw_ring_mod_coeffs_state state;
|
||||
#endif
|
||||
|
||||
// Sub-components
|
||||
bw_one_pole_coeffs smooth_coeffs;
|
||||
bw_one_pole_state smooth_state;
|
||||
@ -170,51 +224,183 @@ struct bw_ring_mod_coeffs {
|
||||
float mod_amount;
|
||||
};
|
||||
|
||||
static inline void bw_ring_mod_init(bw_ring_mod_coeffs *BW_RESTRICT coeffs) {
|
||||
static inline void bw_ring_mod_init(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
|
||||
bw_one_pole_init(&coeffs->smooth_coeffs);
|
||||
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.05f);
|
||||
coeffs->mod_amount = 1.f;
|
||||
|
||||
#ifdef BW_DEBUG_DEEP
|
||||
coeffs->hash = bw_hash_sdbm("bw_ring_mod_coeffs");
|
||||
coeffs->state = bw_ring_mod_coeffs_state_init;
|
||||
#endif
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state == bw_ring_mod_coeffs_state_init);
|
||||
}
|
||||
|
||||
static inline void bw_ring_mod_set_sample_rate(bw_ring_mod_coeffs *BW_RESTRICT coeffs, float sample_rate) {
|
||||
static inline void bw_ring_mod_set_sample_rate(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs,
|
||||
float sample_rate) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_init);
|
||||
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
|
||||
|
||||
bw_one_pole_set_sample_rate(&coeffs->smooth_coeffs, sample_rate);
|
||||
bw_one_pole_reset_coeffs(&coeffs->smooth_coeffs);
|
||||
|
||||
#ifdef BW_DEBUG_DEEP
|
||||
coeffs->state = bw_ring_mod_coeffs_state_set_sample_rate;
|
||||
#endif
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state == bw_ring_mod_coeffs_state_set_sample_rate);
|
||||
}
|
||||
|
||||
static inline void bw_ring_mod_reset_coeffs(bw_ring_mod_coeffs *BW_RESTRICT coeffs) {
|
||||
static inline void bw_ring_mod_reset_coeffs(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_set_sample_rate);
|
||||
|
||||
bw_one_pole_reset_state(&coeffs->smooth_coeffs, &coeffs->smooth_state, coeffs->mod_amount);
|
||||
|
||||
#ifdef BW_DEBUG_DEEP
|
||||
coeffs->state = bw_ring_mod_coeffs_state_reset_coeffs;
|
||||
#endif
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state == bw_ring_mod_coeffs_state_reset_coeffs);
|
||||
}
|
||||
|
||||
static inline void bw_ring_mod_update_coeffs_ctrl(bw_ring_mod_coeffs *BW_RESTRICT coeffs) {
|
||||
static inline void bw_ring_mod_update_coeffs_ctrl(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
|
||||
|
||||
(void)coeffs;
|
||||
}
|
||||
|
||||
static inline void bw_ring_mod_update_coeffs_audio(bw_ring_mod_coeffs *BW_RESTRICT coeffs) {
|
||||
static inline void bw_ring_mod_update_coeffs_audio(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
|
||||
|
||||
bw_one_pole_process1(&coeffs->smooth_coeffs, &coeffs->smooth_state, coeffs->mod_amount);
|
||||
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
|
||||
}
|
||||
|
||||
static inline float bw_ring_mod_process1(const bw_ring_mod_coeffs *BW_RESTRICT coeffs, float x_mod, float x_car) {
|
||||
static inline float bw_ring_mod_process1(
|
||||
const bw_ring_mod_coeffs * BW_RESTRICT coeffs,
|
||||
float x_mod,
|
||||
float x_car) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
|
||||
BW_ASSERT(bw_is_finite(x_mod));
|
||||
BW_ASSERT(bw_is_finite(x_car));
|
||||
|
||||
const float k = bw_one_pole_get_y_z1(&coeffs->smooth_state);
|
||||
return k * x_car * x_mod + bw_absf(1.f - k) * x_mod;
|
||||
const float y = (k * x_car - bw_absf(k)) * x_mod + x_mod;
|
||||
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
|
||||
BW_ASSERT(bw_is_finite(y));
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
static inline void bw_ring_mod_process(bw_ring_mod_coeffs *BW_RESTRICT coeffs, const float *x_mod, const float *x_car, float *y, size_t n_samples) {
|
||||
static inline void bw_ring_mod_process(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs,
|
||||
const float * x_mod,
|
||||
const float * x_car,
|
||||
float * y,
|
||||
size_t n_samples) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
|
||||
BW_ASSERT(x_mod != NULL);
|
||||
BW_ASSERT_DEEP(bw_has_only_finite(x_mod, n_samples));
|
||||
BW_ASSERT(x_car != NULL);
|
||||
BW_ASSERT_DEEP(bw_has_only_finite(x_car, n_samples));
|
||||
BW_ASSERT(y != NULL);
|
||||
|
||||
for (size_t i = 0; i < n_samples; i++) {
|
||||
bw_ring_mod_update_coeffs_audio(coeffs);
|
||||
y[i] = bw_ring_mod_process1(coeffs, x_mod[i], x_car[i]);
|
||||
}
|
||||
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
|
||||
BW_ASSERT_DEEP(bw_has_only_finite(y, n_samples));
|
||||
}
|
||||
|
||||
static inline void bw_ring_mod_process_multi(bw_ring_mod_coeffs *BW_RESTRICT coeffs, const float * const *x_mod, const float * const *x_car, float * const *y, size_t n_channels, size_t n_samples) {
|
||||
static inline void bw_ring_mod_process_multi(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs,
|
||||
const float * const * x_mod,
|
||||
const float * const * x_car,
|
||||
float * const * y,
|
||||
size_t n_channels,
|
||||
size_t n_samples) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
|
||||
BW_ASSERT(x_mod != NULL);
|
||||
BW_ASSERT(x_car != NULL);
|
||||
BW_ASSERT(y != NULL);
|
||||
|
||||
for (size_t i = 0; i < n_samples; i++) {
|
||||
bw_ring_mod_update_coeffs_audio(coeffs);
|
||||
for (size_t j = 0; j < n_channels; j++)
|
||||
y[j][i] = bw_ring_mod_process1(coeffs, x_mod[j][i], x_car[j][i]);
|
||||
}
|
||||
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
|
||||
}
|
||||
|
||||
static inline void bw_ring_mod_set_amount(bw_ring_mod_coeffs *BW_RESTRICT coeffs, float value) {
|
||||
static inline void bw_ring_mod_set_amount(
|
||||
bw_ring_mod_coeffs * BW_RESTRICT coeffs,
|
||||
float value) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_init);
|
||||
BW_ASSERT(bw_is_finite(value));
|
||||
BW_ASSERT(value >= -1.f && value <= 1.f);
|
||||
|
||||
coeffs->mod_amount = value;
|
||||
|
||||
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
|
||||
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_init);
|
||||
}
|
||||
|
||||
static inline char bw_ring_mod_coeffs_is_valid(
|
||||
const bw_ring_mod_coeffs * BW_RESTRICT coeffs) {
|
||||
BW_ASSERT(coeffs != NULL);
|
||||
|
||||
#ifdef BW_DEBUG_DEEP
|
||||
if (coeffs->hash != bw_hash_sdbm("bw_ring_mod_coeffs"))
|
||||
return 0;
|
||||
if (coeffs->state < bw_ring_mod_coeffs_state_init || coeffs->state > bw_ring_mod_coeffs_state_reset_coeffs)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (!bw_is_finite(coeffs->mod_amount) || coeffs->mod_amount < -1.f || coeffs->mod_amount > 1.f)
|
||||
return 0;
|
||||
|
||||
if (!bw_one_pole_coeffs_is_valid(&coeffs->smooth_coeffs))
|
||||
return 0;
|
||||
|
||||
#ifdef BW_DEBUG_DEEP
|
||||
if (coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs && !bw_one_pole_state_is_valid(&coeffs->smooth_coeffs, &coeffs->smooth_state))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -234,16 +420,20 @@ class RingMod {
|
||||
public:
|
||||
RingMod();
|
||||
|
||||
void setSampleRate(float sampleRate);
|
||||
void setSampleRate(
|
||||
float sampleRate);
|
||||
|
||||
void reset();
|
||||
|
||||
void process(
|
||||
const float * const *x_mod,
|
||||
const float * const *x_car,
|
||||
const float * const * xMod,
|
||||
const float * const * xCar,
|
||||
float * const * y,
|
||||
size_t nSamples);
|
||||
|
||||
void process(
|
||||
std::array<const float *, N_CHANNELS> x_mod,
|
||||
std::array<const float *, N_CHANNELS> x_car,
|
||||
std::array<const float *, N_CHANNELS> xMod,
|
||||
std::array<const float *, N_CHANNELS> xCar,
|
||||
std::array<float *, N_CHANNELS> y,
|
||||
size_t nSamples);
|
||||
|
||||
@ -268,7 +458,8 @@ inline RingMod<N_CHANNELS>::RingMod() {
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void RingMod<N_CHANNELS>::setSampleRate(float sampleRate) {
|
||||
inline void RingMod<N_CHANNELS>::setSampleRate(
|
||||
float sampleRate) {
|
||||
bw_ring_mod_set_sample_rate(&coeffs, sampleRate);
|
||||
}
|
||||
|
||||
@ -279,24 +470,25 @@ inline void RingMod<N_CHANNELS>::reset() {
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void RingMod<N_CHANNELS>::process(
|
||||
const float * const *x_mod,
|
||||
const float * const *x_car,
|
||||
const float * const * xMod,
|
||||
const float * const * xCar,
|
||||
float * const * y,
|
||||
size_t nSamples) {
|
||||
bw_ring_mod_process_multi(&coeffs, x_mod, x_car, y, N_CHANNELS, nSamples);
|
||||
bw_ring_mod_process_multi(&coeffs, xMod, xCar, y, N_CHANNELS, nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void RingMod<N_CHANNELS>::process(
|
||||
std::array<const float *, N_CHANNELS> x_mod,
|
||||
std::array<const float *, N_CHANNELS> x_car,
|
||||
std::array<const float *, N_CHANNELS> xMod,
|
||||
std::array<const float *, N_CHANNELS> xCar,
|
||||
std::array<float *, N_CHANNELS> y,
|
||||
size_t nSamples) {
|
||||
process(x_mod.data(), x_car.data(), y.data(), nSamples);
|
||||
process(xMod.data(), xCar.data(), y.data(), nSamples);
|
||||
}
|
||||
|
||||
template<size_t N_CHANNELS>
|
||||
inline void RingMod<N_CHANNELS>::setAmount(float value) {
|
||||
inline void RingMod<N_CHANNELS>::setAmount(
|
||||
float value) {
|
||||
bw_ring_mod_set_amount(&coeffs, value);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user