git subrepo clone https://github.com/libretro/libretro-common.git deps/libretro-common
[pcsx_rearmed.git] / deps / libretro-common / audio / dsp_filters / tremolo.c
1 /* Copyright  (C) 2010-2020 The RetroArch team
2  *
3  * ---------------------------------------------------------------------------------------
4  * The following license statement only applies to this file (tremolo.c).
5  * ---------------------------------------------------------------------------------------
6  *
7  * Permission is hereby granted, free of charge,
8  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #include <math.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <retro_miscellaneous.h>
28 #include <libretro_dspfilter.h>
29 #include <string/stdstring.h>
30
31 #define sqr(a) ((a) * (a))
32
33 struct tremolo_core
34 {
35    float *wavetable;
36    float freq;
37    float depth;
38    int index;
39    int maxindex;
40 };
41
42 struct tremolo
43 {
44    struct tremolo_core left, right;
45 };
46
47 static void tremolo_free(void *data)
48 {
49    struct tremolo *tre = (struct tremolo*)data;
50    free(tre->left.wavetable);
51    free(tre->right.wavetable);
52    free(data);
53 }
54
55 static void tremolocore_init(struct tremolo_core *core,float depth,int samplerate,float freq)
56 {
57    double env;
58    unsigned i;
59    const double offset = 1. - depth / 2.;
60    core->index     = 0;
61    core->maxindex  = samplerate / freq;
62    core->wavetable = malloc(core->maxindex   * sizeof(float));
63    memset(core->wavetable, 0, core->maxindex * sizeof(float));
64    for (i = 0; i < core->maxindex; i++)
65    {
66       env                = freq * i / samplerate;
67       env                = sin((M_PI*2) * fmod(env + 0.25, 1.0));
68       core->wavetable[i] = env * (1 - fabs(offset)) + offset;
69    }
70 }
71
72 float tremolocore_core(struct tremolo_core *core,float in)
73 {
74    core->index = core->index % core->maxindex;
75    return in * core->wavetable[core->index++];
76 }
77
78 static void tremolo_process(void *data, struct dspfilter_output *output,
79       const struct dspfilter_input *input)
80 {
81    unsigned i;
82    float *out;
83    struct tremolo *tre = (struct tremolo*)data;
84
85    output->samples     = input->samples;
86    output->frames      = input->frames;
87    out                 = output->samples;
88
89    for (i = 0; i < input->frames; i++, out += 2)
90    {
91       float in[2]      = { out[0], out[1] };
92       out[0]           = tremolocore_core(&tre->left, in[0]);
93       out[1]           = tremolocore_core(&tre->right, in[1]);
94    }
95 }
96
97 static void *tremolo_init(const struct dspfilter_info *info,
98       const struct dspfilter_config *config, void *userdata)
99 {
100    float freq, depth;
101    struct tremolo *tre = (struct tremolo*)calloc(1, sizeof(*tre));
102    if (!tre)
103       return NULL;
104
105    config->get_float(userdata, "freq", &freq,4.0f);
106    config->get_float(userdata, "depth", &depth, 0.9f);
107    tremolocore_init(&tre->left,depth,info->input_rate,freq);
108    tremolocore_init(&tre->right,depth,info->input_rate,freq);
109    return tre;
110 }
111
112 static const struct dspfilter_implementation tremolo_plug = {
113    tremolo_init,
114    tremolo_process,
115    tremolo_free,
116
117    DSPFILTER_API_VERSION,
118    "Tremolo",
119    "tremolo",
120 };
121
122 #ifdef HAVE_FILTERS_BUILTIN
123 #define dspfilter_get_implementation tremolo_dspfilter_get_implementation
124 #endif
125
126 const struct dspfilter_implementation *dspfilter_get_implementation(dspfilter_simd_mask_t mask)
127 {
128    return &tremolo_plug;
129 }
130
131 #undef dspfilter_get_implementation