diff --git a/examples/synth_poly/src/bw_example_synth_poly.c b/examples/synth_poly/src/bw_example_synth_poly.c index 522a971..4bf36ab 100644 --- a/examples/synth_poly/src/bw_example_synth_poly.c +++ b/examples/synth_poly/src/bw_example_synth_poly.c @@ -237,8 +237,7 @@ void bw_example_synth_poly_process(bw_example_synth_poly *instance, const float* else for (int j = 0; j < N_VOICES; j++) bw_pink_filt_reset_state(&instance->pink_filt_coeffs, pink_filt_states[j]); // FIXME: calling this here is sloppy coding - for (int j = 0; j < N_VOICES; j++) - bw_buf_scale(b1[j], b1[j], 5.f, n); + bw_buf_scale_multi(b1, (const float **)b1, 5.f, N_VOICES, n); float vcf_mod[N_VOICES]; for (int j = 0; j < N_VOICES; j++) { @@ -283,20 +282,16 @@ void bw_example_synth_poly_process(bw_example_synth_poly *instance, const float* bw_gain_process_multi(&instance->vco2_gain_coeffs, (const float **)b2, b2, N_VOICES, n); bw_gain_process_multi(&instance->vco3_gain_coeffs, (const float **)b0, b0, N_VOICES, n); bw_gain_process_multi(&instance->noise_gain_coeffs, (const float **)b1, b1, N_VOICES, n); - for (int j = 0; j < N_VOICES; j++) { - bw_buf_mix(b0[j], b0[j], b2[j], n); - bw_buf_mix(b0[j], b0[j], b3[j], n); - } + bw_buf_mix_multi(b0, (const float **)b0, (const float **)b2, N_VOICES, n); + bw_buf_mix_multi(b0, (const float **)b0, (const float **)b3, N_VOICES, n); bw_osc_filt_process_multi(osc_filt_states, (const float **)b0, b0, N_VOICES, n); const float k = instance->params[p_noise_color] >= 0.5f ? 6.f * bw_noise_gen_get_scaling_k(&instance->noise_gen_coeffs) * bw_pink_filt_get_scaling_k(&instance->pink_filt_coeffs) : 0.1f * bw_noise_gen_get_scaling_k(&instance->noise_gen_coeffs); - for (int j = 0; j < N_VOICES; j++) { - bw_buf_scale(b1[j], b1[j], k, n); - bw_buf_mix(b0[j], b0[j], b1[j], n); - } + bw_buf_scale_multi(b1, (const float **)b1, k, N_VOICES, n); + bw_buf_mix_multi(b0, (const float **)b0, (const float **)b1, N_VOICES, n); bw_env_gen_process_multi(&instance->vcf_env_gen_coeffs, vcf_env_gen_states, gates, NULL, N_VOICES, n); for (int j = 0; j < N_VOICES; j++) { @@ -314,8 +309,7 @@ void bw_example_synth_poly_process(bw_example_synth_poly *instance, const float* } bw_env_gen_process_multi(&instance->vca_env_gen_coeffs, vca_env_gen_states, gates, b1, N_VOICES, n); - for (int j = 0; j < N_VOICES; j++) - bw_buf_mul(b0[j], b0[j], b1[j], n); + bw_buf_mul_multi(b0, (const float **)b0, (const float **)b1, N_VOICES, n); bw_buf_fill(out, 0.f, n); for (int j = 0; j < N_VOICES; j++) diff --git a/examples/synthpp_poly/src/bw_example_synthpp_poly.cpp b/examples/synthpp_poly/src/bw_example_synthpp_poly.cpp index ae289e1..d50ade6 100644 --- a/examples/synthpp_poly/src/bw_example_synthpp_poly.cpp +++ b/examples/synthpp_poly/src/bw_example_synthpp_poly.cpp @@ -21,7 +21,7 @@ #include "bw_example_synthpp_poly.h" #include -#include +#include #include void bw_example_synthpp_poly_init(bw_example_synthpp_poly *instance) { @@ -209,8 +209,7 @@ void bw_example_synthpp_poly_process(bw_example_synthpp_poly *instance, const fl instance->pinkFilt.process(cb1, b1, n); else instance->pinkFilt.reset(); // FIXME: calling this here is sloppy coding - for (int j = 0; j < N_VOICES; j++) - bw_buf_scale(b1.data()[j], b1.data()[j], 5.f, n); + bufScale(b1, cb1, 5.f, n); float vcf_mod[N_VOICES]; for (int j = 0; j < N_VOICES; j++) { @@ -220,7 +219,7 @@ void bw_example_synthpp_poly_process(bw_example_synthpp_poly *instance, const fl } for (int j = 0; j < N_VOICES; j++) { - bw_buf_scale(b3.data()[j], b2.data()[j], instance->params[p_vco1_mod], n); + bufScale<1>({b3.data()[j]}, {b2.data()[j]}, instance->params[p_vco1_mod], n); instance->voices[j].vco1PhaseGen.process({b3.data()[j]}, {b3.data()[j]}, {b4.data()[j]}, n); } if (instance->params[p_vco1_waveform] >= (1.f / 4.f + 1.f / 2.f)) { @@ -236,7 +235,7 @@ void bw_example_synthpp_poly_process(bw_example_synthpp_poly *instance, const fl } for (int j = 0; j < N_VOICES; j++) { - bw_buf_scale(b2.data()[j], b2.data()[j], instance->params[p_vco2_mod], n); + bufScale<1>({b2.data()[j]}, {b2.data()[j]}, instance->params[p_vco2_mod], n); instance->voices[j].vco2PhaseGen.process({b2.data()[j]}, {b2.data()[j]}, {b4.data()[j]}, n); } if (instance->params[p_vco2_waveform] >= (1.f / 4.f + 1.f / 2.f)) { @@ -255,20 +254,16 @@ void bw_example_synthpp_poly_process(bw_example_synthpp_poly *instance, const fl instance->vco2Gain.process(cb2, b2, n); instance->vco3Gain.process(cb0, b0, n); instance->noiseGain.process(cb1, b1, n); - for (int j = 0; j < N_VOICES; j++) { - bw_buf_mix(b0.data()[j], b0.data()[j], b2.data()[j], n); - bw_buf_mix(b0.data()[j], b0.data()[j], b3.data()[j], n); - } + bufMix(b0, cb0, cb2, n); + bufMix(b0, cb0, cb3, n); instance->oscFilt.process(cb0, b0, n); const float k = instance->params[p_noise_color] >= 0.5f ? 6.f * instance->noiseGen.getScalingK() * instance->pinkFilt.getScalingK() : 0.1f * instance->noiseGen.getScalingK(); - for (int j = 0; j < N_VOICES; j++) { - bw_buf_scale(b1.data()[j], b1.data()[j], k, n); - bw_buf_mix(b0.data()[j], b0.data()[j], b1.data()[j], n); - } + bufScale(b1, cb1, k, n); + bufMix(b0, cb0, cb1, n); instance->vcfEnvGen.process(gates, na, n); for (int j = 0; j < N_VOICES; j++) { @@ -286,17 +281,16 @@ void bw_example_synthpp_poly_process(bw_example_synthpp_poly *instance, const fl } instance->vcaEnvGen.process(gates, b1, n); - for (int j = 0; j < N_VOICES; j++) - bw_buf_mul(b0.data()[j], b0.data()[j], b1.data()[j], n); + bufMul(b0, cb0, cb1, n); - bw_buf_fill(out, 0.f, n); + bufFill<1>({out}, 0.f, n); for (int j = 0; j < N_VOICES; j++) - bw_buf_mix(out, out, b0.data()[j], n); + bufMix<1>({out}, {out}, {b0.data()[j]}, n); instance->a440PhaseGen.process({nullptr}, {instance->buf}, {nullptr}, n); oscSinProcess<1>({instance->buf}, {instance->buf}, n); if (instance->params[p_a440] >= 0.5f) - bw_buf_mix(out, out, instance->buf, n); + bufMix<1>({out}, {out}, {instance->buf}, n); instance->gain.process({out}, {out}, n); instance->ppm.process({out}, {nullptr}, n); diff --git a/include/bw_buf.h b/include/bw_buf.h index 7ad2312..2bf170a 100644 --- a/include/bw_buf.h +++ b/include/bw_buf.h @@ -29,6 +29,7 @@ *
    *
  • Version 0.5.0: *
      + *
    • Added bw_buf_*_multi().
    • *
    • Added bw_buf_neg().
    • *
    *
  • @@ -97,6 +98,53 @@ static inline void bw_buf_mul(float *dest, const float *src1, const float *src2, /*! <<<``` * Multiplies the first `n_elems` of `src1` and `src2` and stores the results * in the first `n_elems` of `dest`. + * + * #### bw_buf_fill_multi() + * ```>>> */ +static inline void bw_buf_fill_multi(float **dest, float k, int n_channels, int n_elems); +/*! <<<``` + * Sets the first `n_elems` in each of the `n_channels` buffers `dest` to + * `k`. + * + * #### bw_buf_neg_multi() + * ```>>> */ +static inline void bw_buf_neg_multi(float **dest, const float **src, int n_channels, int n_elems); +/*! <<<``` + * Inverts the sign of the first `n_elems` in each of the `n_channels` + * buffers `src` and stores the results in the first `n_elems` in each of the + * `n_channels` buffers `dest`. + * + * #### bw_buf_add_multi() + * ```>>> */ +static inline void bw_buf_add_multi(float **dest, const float **src, float k, int n_channels, int n_elems); +/*! <<<``` + * Adds `k` to the first `n_elems` in each of the `n_channels` buffers `src` + * and stores the results in the first `n_elems` in each of the `n_channels` + * buffers `dest`. + * + * #### bw_buf_scale_multi() + * ```>>> */ +static inline void bw_buf_scale_multi(float **dest, const float **src, float k, int n_channels, int n_elems); +/*! <<<``` + * Multiplies the first `n_elems` in each of the `n_channels` buffers `src` + * by `k` and stores the results in the first `n_elems` in each of the + * `n_channels` buffers `dest`. + * + * #### bw_buf_mix_multi() + * ```>>> */ +static inline void bw_buf_mix_multi(float **dest, const float **src1, const float **src2, int n_channels, int n_elems); +/*! <<<``` + * Adds the first `n_elems` in each of the `n_channels` buffers `src1` and + * `src2` and stores the results in the first `n_elems` in each of the + * `n_channels` buffers `dest`. + * + * #### bw_buf_mul_multi() + * ```>>> */ +static inline void bw_buf_mul_multi(float **dest, const float **src1, const float **src2, int n_channels, int n_elems); +/*! <<<``` + * Multiplies the first `n_elems` in each of the `n_channels` buffers `src1` + * and `src2` and stores the results in the first `n_elems` in each of the + * `n_channels` buffers `dest`. * }}} */ /*** Implementation ***/ @@ -134,6 +182,36 @@ static inline void bw_buf_mul(float *dest, const float *src1, const float *src2, dest[i] = src1[i] * src2[i]; } +static inline void bw_buf_fill_multi(float **dest, float k, int n_channels, int n_elems) { + for (int i = 0; i < n_channels; i++) + bw_buf_fill(dest[i], k, n_elems); +} + +static inline void bw_buf_neg_multi(float **dest, const float **src, int n_channels, int n_elems) { + for (int i = 0; i < n_channels; i++) + bw_buf_neg(dest[i], src[i], n_elems); +} + +static inline void bw_buf_add_multi(float **dest, const float **src, float k, int n_channels, int n_elems) { + for (int i = 0; i < n_channels; i++) + bw_buf_add(dest[i], src[i], k, n_elems); +} + +static inline void bw_buf_scale_multi(float **dest, const float **src, float k, int n_channels, int n_elems) { + for (int i = 0; i < n_channels; i++) + bw_buf_scale(dest[i], src[i], k, n_elems); +} + +static inline void bw_buf_mix_multi(float **dest, const float **src1, const float **src2, int n_channels, int n_elems) { + for (int i = 0; i < n_channels; i++) + bw_buf_mix(dest[i], src1[i], src2[i], n_elems); +} + +static inline void bw_buf_mul_multi(float **dest, const float **src1, const float **src2, int n_channels, int n_elems) { + for (int i = 0; i < n_channels; i++) + bw_buf_mul(dest[i], src1[i], src2[i], n_elems); +} + #ifdef __cplusplus } #endif diff --git a/include/bwpp_buf.h b/include/bwpp_buf.h new file mode 100644 index 0000000..2899fc7 --- /dev/null +++ b/include/bwpp_buf.h @@ -0,0 +1,121 @@ +/* + * Brickworks + * + * Copyright (C) 2023 Orastron Srl unipersonale + * + * Brickworks is free software: you can reosc_sinribute 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 osc_sinributed 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 . + * + * File author: Stefano D'Angelo + */ + +#ifndef BWPP_BUF_H +#define BWPP_BUF_H + +#include +#include + +namespace Brickworks { + template + void bufFill( + std::array dest, + float k, + int nSamples); + + template + void bufNeg( + std::array dest, + std::array src, + int nSamples); + + template + void bufAdd( + std::array dest, + std::array src, + float k, + int nSamples); + + template + void bufScale( + std::array dest, + std::array src, + float k, + int nSamples); + + template + void bufMix( + std::array dest, + std::array src1, + std::array src2, + int nSamples); + + template + void bufMul( + std::array dest, + std::array src1, + std::array src2, + int nSamples); + + template + inline void bufFill( + std::array dest, + float k, + int nSamples) { + bw_buf_fill_multi(dest.data(), k, N_CHANNELS, nSamples); + } + + template + inline void bufNeg( + std::array dest, + std::array src, + int nSamples) { + bw_buf_neg_multi(dest.data(), src.data(), N_CHANNELS, nSamples); + } + + template + inline void bufAdd( + std::array dest, + std::array src, + float k, + int nSamples) { + bw_buf_add_multi(dest.data(), src.data(), k, N_CHANNELS, nSamples); + } + + template + inline void bufScale( + std::array dest, + std::array src, + float k, + int nSamples) { + bw_buf_scale_multi(dest.data(), src.data(), k, N_CHANNELS, nSamples); + } + + template + inline void bufMix( + std::array dest, + std::array src1, + std::array src2, + int nSamples) { + bw_buf_mix_multi(dest.data(), src1.data(), src2.data(), N_CHANNELS, nSamples); + } + + template + inline void bufMul( + std::array dest, + std::array src1, + std::array src2, + int nSamples) { + bw_buf_mul_multi(dest.data(), src1.data(), src2.data(), N_CHANNELS, nSamples); + } +} + +#endif