1 /* Copyright (C) 2010-2020 The RetroArch team
3 * ---------------------------------------------------------------------------------------
4 * The following license statement only applies to this file (vibrato.c).
5 * ---------------------------------------------------------------------------------------
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:
13 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
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.
27 #include <retro_miscellaneous.h>
28 #include <libretro_dspfilter.h>
29 #include <string/stdstring.h>
31 #define sqr(a) ((a) * (a))
33 #define VIBRATO_BASE_DELAY_SEC 0.002f /* 2 ms */
34 #define VIBRATO_FREQUENCY_DEFAULT_HZ 2.0f
35 #define VIBRATO_FREQUENCY_MAX_HZ 14.0f
36 #define VIBRATO_DEPTH_DEFAULT_PERCENT 50.0f
37 #define VIBRATO_ADD_DELAY 3
39 static float hermite_interp(float x, float *y)
42 float c1 = (1.0f / 2.0f) * (y[2] - y[0]);
43 float c2 = (y[0] - (5.0f / 2.0f) * y[1]) + (2.0f * y[2] - (1.0f / 2.0f) * y[3]);
44 float c3 = (1.0f / 2.0f) * (y[3] - y[0]) + (3.0f / 2.0f) * (y[1] - y[2]);
45 return ((c3 * x + c2) * x + c1) * x + c0;
61 struct vibrato_core left, right;
64 static void vibrato_free(void *data)
66 struct vibrato *vib = (struct vibrato*)data;
67 free(vib->left.buffer);
68 free(vib->right.buffer);
72 static void vibratocore_init(struct vibrato_core *core,float depth,int samplerate,float freq)
74 core->size = VIBRATO_BASE_DELAY_SEC * samplerate * 2;
75 core->buffer = malloc((core->size + VIBRATO_ADD_DELAY) * sizeof(float));
76 memset(core->buffer, 0, (core->size + VIBRATO_ADD_DELAY) * sizeof(float));
77 core->samplerate = samplerate;
84 float vibratocore_core(struct vibrato_core *core,float in)
87 float delay, readindex, fpart, value;
88 float M = core->freq / core->samplerate;
89 int maxphase = core->samplerate / core->freq;
90 float lfo = sin(M * 2. * M_PI * core->phase++);
91 int maxdelay = VIBRATO_BASE_DELAY_SEC * core->samplerate;
92 core->phase = core->phase % maxphase;
93 lfo = (lfo + 1) * 1.; // transform from [-1; 1] to [0; 1]
94 delay = lfo * core->depth * maxdelay;
95 delay += VIBRATO_ADD_DELAY;
96 readindex = core->writeindex - 1 - delay;
98 readindex += core->size;
99 while (readindex >= core->size)
100 readindex -= core->size;
101 ipart = (int)readindex; /* Integer part of the delay */
102 fpart = readindex - ipart; /* fractional part of the delay */
103 value = hermite_interp(fpart, &(core->buffer[ipart]));
104 core->buffer[core->writeindex] = in;
105 if (core->writeindex < VIBRATO_ADD_DELAY)
106 core->buffer[core->size + core->writeindex] = in;
108 if (core->writeindex == core->size)
109 core->writeindex = 0;
113 static void vibrato_process(void *data,
114 struct dspfilter_output *output,
115 const struct dspfilter_input *input)
119 struct vibrato *vib = (struct vibrato*)data;
121 output->samples = input->samples;
122 output->frames = input->frames;
123 out = output->samples;
125 for (i = 0; i < input->frames; i++, out += 2)
127 float in[2] = { out[0], out[1] };
128 out[0] = vibratocore_core(&vib->left, in[0]);
129 out[1] = vibratocore_core(&vib->right, in[1]);
133 static void *vibrato_init(const struct dspfilter_info *info,
134 const struct dspfilter_config *config, void *userdata)
137 struct vibrato *vib = (struct vibrato*)calloc(1, sizeof(*vib));
141 config->get_float(userdata, "freq", &freq,5.0f);
142 config->get_float(userdata, "depth", &depth, 0.5f);
143 vibratocore_init(&vib->left,depth,info->input_rate,freq);
144 vibratocore_init(&vib->right,depth,info->input_rate,freq);
148 static const struct dspfilter_implementation vibrato_plug = {
153 DSPFILTER_API_VERSION,
158 #ifdef HAVE_FILTERS_BUILTIN
159 #define dspfilter_get_implementation vibrato_dspfilter_get_implementation
162 const struct dspfilter_implementation *dspfilter_get_implementation(dspfilter_simd_mask_t mask)
164 return &vibrato_plug;
167 #undef dspfilter_get_implementation