summaryrefslogtreecommitdiff
path: root/Core/Src/Effects/ringmod.c
blob: be58c11eec7219d9a32245f37b10c8552376060d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/*
 * ringmod.c
 *
 *  Created on: Aug 19, 2026
 *      Author: ozpv
 */

#include "cs4272.h"
#include "ringmod.h"
#include "arm_math.h"

/* MF-102S ring modulator */
void ringmod(
    const struct RingModParams *params,
    const int32_t *samples_in,
    int32_t *samples_out,
    const size_t range_min,
    const size_t range_max,
    const enum Channel channel
) {
    static float lfo_phase = 0.0f;
    static float carrier_phase = 0.0f;

    const float sample_rate = (float)SAMPLE_RATE;
    const float inverse_sample_rate = 1.0f / sample_rate;

    /* samples are interleaved */
    for (size_t i = range_min + channel; i < range_max; i += 2) {
        float sample = int24_t_to_f32(samples_in[i]);

        float frequency_lfo = 0.0f;

        if (params->square_lfo) {
            frequency_lfo = (lfo_phase < 0.5f) ? params->lfo_amount : -params->lfo_amount;
        } else {
            frequency_lfo = params->lfo_amount * arm_sin_f32(M_TWOPI * lfo_phase);
        }

        float carrier = arm_sin_f32(M_TWOPI * carrier_phase);

        float output_sample = (sample * (1.0f - params->mix)) + (sample * carrier * params->mix);
        samples_out[i] = f32_to_int24_t(output_sample);

        lfo_phase += params->lfo_rate * inverse_sample_rate;
        while (lfo_phase >= 1.0f) {
            lfo_phase -= 1.0f;
        }

        carrier_phase += (params->frequency + frequency_lfo) * inverse_sample_rate;
        while (carrier_phase >= 1.0f) {
            carrier_phase -= 1.0f;
        }
    }
}