2
Copyright (C) 2004 Tom Szilagyi
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or
7
(at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
$Id: tap_pitch.c,v 1.2 2004/02/21 17:33:36 tszilagyi Exp $
28
#include "tap_utils.h"
31
/* The Unique ID of the plugin: */
35
/* The port numbers for the plugin: */
45
/* Total number of ports */
48
#define PORTCOUNT_MONO 7
51
/* depth of phase mod (yes, this is a magic number) */
52
#define PM_DEPTH 3681.0f
55
/* another magic number, derived from the above one */
56
#define PM_BUFLEN 16027
59
/* frequency of the modulation signal (Hz) */
63
#define COS_TABLE_SIZE 1024
64
LADSPA_Data cos_table[COS_TABLE_SIZE];
67
/* \sqrt{12}{2} used for key frequency computing */
68
#define ROOT_12_2 1.059463094f
71
/* The structure used to hold port connection information and state */
75
LADSPA_Data * semitone;
76
LADSPA_Data * drylevel;
77
LADSPA_Data * wetlevel;
78
LADSPA_Data * latency;
82
LADSPA_Data * ringbuffer;
87
unsigned long sample_rate;
88
LADSPA_Data run_adding_gain;
93
/* Construct a new plugin instance. */
95
instantiate_Pitch(const LADSPA_Descriptor * Descriptor,
96
unsigned long sample_rate) {
100
if ((ptr = malloc(sizeof(Pitch))) != NULL) {
101
((Pitch *)ptr)->sample_rate = sample_rate;
102
((Pitch *)ptr)->run_adding_gain = 1.0f;
104
if ((((Pitch *)ptr)->ringbuffer =
105
calloc(2 * PM_BUFLEN, sizeof(LADSPA_Data))) == NULL)
107
((Pitch *)ptr)->buflen = 2 * PM_BUFLEN * sample_rate / 192000;
108
((Pitch *)ptr)->pos = 0;
117
activate_Pitch(LADSPA_Handle Instance) {
119
Pitch * ptr = (Pitch *)Instance;
122
for (i = 0; i < ptr->buflen; i++)
123
ptr->ringbuffer[i] = 0.0f;
132
/* Connect a port to a data location. */
134
connect_port_Pitch(LADSPA_Handle Instance,
136
LADSPA_Data * DataLocation) {
138
Pitch * ptr = (Pitch *)Instance;
142
ptr->rate = DataLocation;
145
ptr->semitone = DataLocation;
148
ptr->drylevel = DataLocation;
151
ptr->wetlevel = DataLocation;
154
ptr->latency = DataLocation;
155
*(ptr->latency) = ptr->buflen / 2; /* IS THIS LEGAL? */
158
ptr->input = DataLocation;
161
ptr->output = DataLocation;
169
run_Pitch(LADSPA_Handle Instance,
170
unsigned long SampleCount) {
172
Pitch * ptr = (Pitch *)Instance;
173
LADSPA_Data * input = ptr->input;
174
LADSPA_Data * output = ptr->output;
175
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
176
LADSPA_Data wetlevel = 0.333333f * db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
177
LADSPA_Data buflen = ptr->buflen / 2.0f;
178
LADSPA_Data semitone = LIMIT(*(ptr->semitone),-12.0f,12.0f);
183
unsigned long sample_index;
184
unsigned long sample_count = SampleCount;
186
LADSPA_Data in = 0.0f;
187
LADSPA_Data sign = 1.0f;
188
LADSPA_Data phase_0 = 0.0f;
189
LADSPA_Data phase_am_0 = 0.0f;
190
LADSPA_Data phase_1 = 0.0f;
191
LADSPA_Data phase_am_1 = 0.0f;
192
LADSPA_Data phase_2 = 0.0f;
193
LADSPA_Data phase_am_2 = 0.0f;
194
LADSPA_Data fpos_0 = 0.0f, fpos_1 = 0.0f, fpos_2 = 0.0f;
195
LADSPA_Data n_0 = 0.0f, n_1 = 0.0f, n_2 = 0.0f;
196
LADSPA_Data rem_0 = 0.0f, rem_1 = 0.0f, rem_2 = 0.0f;
197
LADSPA_Data sa_0, sb_0, sa_1, sb_1, sa_2, sb_2;
200
if (semitone == 0.0f)
201
rate = LIMIT(*(ptr->rate),-50.0f,100.0f);
203
rate = 100.0f * (powf(ROOT_12_2,semitone) - 1.0f);
205
r = -1.0f * ABS(rate);
206
depth = buflen * LIMIT(ABS(r) / 100.0f, 0.0f, 1.0f);
212
for (sample_index = 0; sample_index < sample_count; sample_index++) {
216
phase_0 = COS_TABLE_SIZE * PM_FREQ * sample_index / ptr->sample_rate + ptr->phase;
217
while (phase_0 >= COS_TABLE_SIZE)
218
phase_0 -= COS_TABLE_SIZE;
219
phase_am_0 = phase_0 + COS_TABLE_SIZE/2;
220
while (phase_am_0 >= COS_TABLE_SIZE)
221
phase_am_0 -= COS_TABLE_SIZE;
223
phase_1 = phase_0 + COS_TABLE_SIZE/3.0f;
224
while (phase_1 >= COS_TABLE_SIZE)
225
phase_1 -= COS_TABLE_SIZE;
226
phase_am_1 = phase_1 + COS_TABLE_SIZE/2;
227
while (phase_am_1 >= COS_TABLE_SIZE)
228
phase_am_1 -= COS_TABLE_SIZE;
230
phase_2 = phase_0 + 2.0f*COS_TABLE_SIZE/3.0f;
231
while (phase_2 >= COS_TABLE_SIZE)
232
phase_2 -= COS_TABLE_SIZE;
233
phase_am_2 = phase_2 + COS_TABLE_SIZE/2;
234
while (phase_am_2 >= COS_TABLE_SIZE)
235
phase_am_2 -= COS_TABLE_SIZE;
237
push_buffer(in, ptr->ringbuffer, ptr->buflen, &(ptr->pos));
239
fpos_0 = depth * (1.0f - sign * (2.0f * phase_0 / COS_TABLE_SIZE - 1.0f));
240
n_0 = floorf(fpos_0);
241
rem_0 = fpos_0 - n_0;
243
fpos_1 = depth * (1.0f - sign * (2.0f * phase_1 / COS_TABLE_SIZE - 1.0f));
244
n_1 = floorf(fpos_1);
245
rem_1 = fpos_1 - n_1;
247
fpos_2 = depth * (1.0f - sign * (2.0f * phase_2 / COS_TABLE_SIZE - 1.0f));
248
n_2 = floorf(fpos_2);
249
rem_2 = fpos_2 - n_2;
251
sa_0 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_0);
252
sb_0 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_0 + 1);
254
sa_1 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_1);
255
sb_1 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_1 + 1);
257
sa_2 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_2);
258
sb_2 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_2 + 1);
262
((1.0f + cos_table[(unsigned long) phase_am_0]) *
263
((1 - rem_0) * sa_0 + rem_0 * sb_0) +
264
(1.0f + cos_table[(unsigned long) phase_am_1]) *
265
((1 - rem_1) * sa_1 + rem_1 * sb_1) +
266
(1.0f + cos_table[(unsigned long) phase_am_2]) *
267
((1 - rem_2) * sa_2 + rem_2 * sb_2)) +
269
read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) depth);
273
ptr->phase += COS_TABLE_SIZE * PM_FREQ * sample_index / ptr->sample_rate;
274
while (ptr->phase >= COS_TABLE_SIZE)
275
ptr->phase -= COS_TABLE_SIZE;
277
*(ptr->latency) = buflen - (unsigned long) depth;
283
set_run_adding_gain_Pitch(LADSPA_Handle Instance, LADSPA_Data gain) {
285
Pitch * ptr = (Pitch *)Instance;
287
ptr->run_adding_gain = gain;
293
run_adding_Pitch(LADSPA_Handle Instance,
294
unsigned long SampleCount) {
296
Pitch * ptr = (Pitch *)Instance;
297
LADSPA_Data * input = ptr->input;
298
LADSPA_Data * output = ptr->output;
299
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
300
LADSPA_Data wetlevel = 0.333333f * db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
301
LADSPA_Data buflen = ptr->buflen / 2.0f;
302
LADSPA_Data semitone = LIMIT(*(ptr->semitone),-12.0f,12.0f);
307
unsigned long sample_index;
308
unsigned long sample_count = SampleCount;
310
LADSPA_Data in = 0.0f;
311
LADSPA_Data sign = 1.0f;
312
LADSPA_Data phase_0 = 0.0f;
313
LADSPA_Data phase_am_0 = 0.0f;
314
LADSPA_Data phase_1 = 0.0f;
315
LADSPA_Data phase_am_1 = 0.0f;
316
LADSPA_Data phase_2 = 0.0f;
317
LADSPA_Data phase_am_2 = 0.0f;
318
LADSPA_Data fpos_0 = 0.0f, fpos_1 = 0.0f, fpos_2 = 0.0f;
319
LADSPA_Data n_0 = 0.0f, n_1 = 0.0f, n_2 = 0.0f;
320
LADSPA_Data rem_0 = 0.0f, rem_1 = 0.0f, rem_2 = 0.0f;
321
LADSPA_Data sa_0, sb_0, sa_1, sb_1, sa_2, sb_2;
324
if (semitone == 0.0f)
325
rate = LIMIT(*(ptr->rate),-50.0f,100.0f);
327
rate = 100.0f * (powf(ROOT_12_2,semitone) - 1.0f);
329
r = -1.0f * ABS(rate);
330
depth = buflen * LIMIT(ABS(r) / 100.0f, 0.0f, 1.0f);
336
for (sample_index = 0; sample_index < sample_count; sample_index++) {
340
phase_0 = COS_TABLE_SIZE * PM_FREQ * sample_index / ptr->sample_rate + ptr->phase;
341
while (phase_0 >= COS_TABLE_SIZE)
342
phase_0 -= COS_TABLE_SIZE;
343
phase_am_0 = phase_0 + COS_TABLE_SIZE/2;
344
while (phase_am_0 >= COS_TABLE_SIZE)
345
phase_am_0 -= COS_TABLE_SIZE;
347
phase_1 = phase_0 + COS_TABLE_SIZE/3.0f;
348
while (phase_1 >= COS_TABLE_SIZE)
349
phase_1 -= COS_TABLE_SIZE;
350
phase_am_1 = phase_1 + COS_TABLE_SIZE/2;
351
while (phase_am_1 >= COS_TABLE_SIZE)
352
phase_am_1 -= COS_TABLE_SIZE;
354
phase_2 = phase_0 + 2.0f*COS_TABLE_SIZE/3.0f;
355
while (phase_2 >= COS_TABLE_SIZE)
356
phase_2 -= COS_TABLE_SIZE;
357
phase_am_2 = phase_2 + COS_TABLE_SIZE/2;
358
while (phase_am_2 >= COS_TABLE_SIZE)
359
phase_am_2 -= COS_TABLE_SIZE;
361
push_buffer(in, ptr->ringbuffer, ptr->buflen, &(ptr->pos));
363
fpos_0 = depth * (1.0f - sign * (2.0f * phase_0 / COS_TABLE_SIZE - 1.0f));
364
n_0 = floorf(fpos_0);
365
rem_0 = fpos_0 - n_0;
367
fpos_1 = depth * (1.0f - sign * (2.0f * phase_1 / COS_TABLE_SIZE - 1.0f));
368
n_1 = floorf(fpos_1);
369
rem_1 = fpos_1 - n_1;
371
fpos_2 = depth * (1.0f - sign * (2.0f * phase_2 / COS_TABLE_SIZE - 1.0f));
372
n_2 = floorf(fpos_2);
373
rem_2 = fpos_2 - n_2;
375
sa_0 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_0);
376
sb_0 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_0 + 1);
378
sa_1 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_1);
379
sb_1 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_1 + 1);
381
sa_2 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_2);
382
sb_2 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_2 + 1);
384
*(output++) += ptr->run_adding_gain *
386
((1.0f + cos_table[(unsigned long) phase_am_0]) *
387
((1 - rem_0) * sa_0 + rem_0 * sb_0) +
388
(1.0f + cos_table[(unsigned long) phase_am_1]) *
389
((1 - rem_1) * sa_1 + rem_1 * sb_1) +
390
(1.0f + cos_table[(unsigned long) phase_am_2]) *
391
((1 - rem_2) * sa_2 + rem_2 * sb_2)) +
393
read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) depth);
397
ptr->phase += COS_TABLE_SIZE * PM_FREQ * sample_index / ptr->sample_rate;
398
while (ptr->phase >= COS_TABLE_SIZE)
399
ptr->phase -= COS_TABLE_SIZE;
401
*(ptr->latency) = buflen - (unsigned long) depth;
406
/* Throw away a Pitch effect instance. */
408
cleanup_Pitch(LADSPA_Handle Instance) {
410
Pitch * ptr = (Pitch *)Instance;
411
free(ptr->ringbuffer);
417
LADSPA_Descriptor * mono_descriptor = NULL;
421
/* __attribute__((constructor)) _init() is called automatically when the plugin library is first
424
__attribute__((constructor)) _init() {
428
LADSPA_PortDescriptor * port_descriptors;
429
LADSPA_PortRangeHint * port_range_hints;
431
if ((mono_descriptor =
432
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
435
for (i = 0; i < COS_TABLE_SIZE; i++)
436
cos_table[i] = cosf(i * 2.0f * M_PI / COS_TABLE_SIZE);
439
mono_descriptor->UniqueID = ID_MONO;
440
mono_descriptor->Label = strdup("tap_pitch");
441
mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
442
mono_descriptor->Name = strdup("TAP Pitch Shifter");
443
mono_descriptor->Maker = strdup("Tom Szilagyi");
444
mono_descriptor->Copyright = strdup("GPL");
445
mono_descriptor->PortCount = PORTCOUNT_MONO;
447
if ((port_descriptors =
448
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
451
mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
452
port_descriptors[RATE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
453
port_descriptors[SEMITONE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
454
port_descriptors[DRYLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
455
port_descriptors[WETLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
456
port_descriptors[LATENCY] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
457
port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
458
port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
461
(char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
464
mono_descriptor->PortNames = (const char **)port_names;
465
port_names[SEMITONE] = strdup("Semitone Shift");
466
port_names[RATE] = strdup("Rate Shift [%]");
467
port_names[DRYLEVEL] = strdup("Dry Level [dB]");
468
port_names[WETLEVEL] = strdup("Wet Level [dB]");
469
port_names[LATENCY] = strdup("latency");
470
port_names[INPUT] = strdup("Input");
471
port_names[OUTPUT] = strdup("Output");
473
if ((port_range_hints =
474
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
477
mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
478
port_range_hints[RATE].HintDescriptor =
479
(LADSPA_HINT_BOUNDED_BELOW |
480
LADSPA_HINT_BOUNDED_ABOVE |
481
LADSPA_HINT_DEFAULT_0);
482
port_range_hints[SEMITONE].HintDescriptor =
483
(LADSPA_HINT_BOUNDED_BELOW |
484
LADSPA_HINT_BOUNDED_ABOVE |
485
LADSPA_HINT_DEFAULT_0);
486
port_range_hints[DRYLEVEL].HintDescriptor =
487
(LADSPA_HINT_BOUNDED_BELOW |
488
LADSPA_HINT_BOUNDED_ABOVE |
489
LADSPA_HINT_DEFAULT_MINIMUM);
490
port_range_hints[WETLEVEL].HintDescriptor =
491
(LADSPA_HINT_BOUNDED_BELOW |
492
LADSPA_HINT_BOUNDED_ABOVE |
493
LADSPA_HINT_DEFAULT_0);
494
port_range_hints[LATENCY].HintDescriptor =
495
(LADSPA_HINT_BOUNDED_BELOW |
496
LADSPA_HINT_BOUNDED_ABOVE |
497
LADSPA_HINT_DEFAULT_MAXIMUM);
498
port_range_hints[RATE].LowerBound = -50.0f;
499
port_range_hints[RATE].UpperBound = 100.0f;
500
port_range_hints[SEMITONE].LowerBound = -12.0f;
501
port_range_hints[SEMITONE].UpperBound = 12.0f;
502
port_range_hints[DRYLEVEL].LowerBound = -90.0f;
503
port_range_hints[DRYLEVEL].UpperBound = 20.0f;
504
port_range_hints[WETLEVEL].LowerBound = -90.0f;
505
port_range_hints[WETLEVEL].UpperBound = 20.0f;
506
port_range_hints[LATENCY].LowerBound = 0;
507
port_range_hints[LATENCY].UpperBound = PM_BUFLEN;
508
port_range_hints[INPUT].HintDescriptor = 0;
509
port_range_hints[OUTPUT].HintDescriptor = 0;
510
mono_descriptor->instantiate = instantiate_Pitch;
511
mono_descriptor->connect_port = connect_port_Pitch;
512
mono_descriptor->activate = activate_Pitch;
513
mono_descriptor->run = run_Pitch;
514
mono_descriptor->run_adding = run_adding_Pitch;
515
mono_descriptor->set_run_adding_gain = set_run_adding_gain_Pitch;
516
mono_descriptor->deactivate = NULL;
517
mono_descriptor->cleanup = cleanup_Pitch;
522
delete_descriptor(LADSPA_Descriptor * descriptor) {
525
free((char *)descriptor->Label);
526
free((char *)descriptor->Name);
527
free((char *)descriptor->Maker);
528
free((char *)descriptor->Copyright);
529
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
530
for (index = 0; index < descriptor->PortCount; index++)
531
free((char *)(descriptor->PortNames[index]));
532
free((char **)descriptor->PortNames);
533
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
539
/* __attribute__((destructor)) _fini() is called automatically when the library is unloaded. */
541
__attribute__((destructor)) _fini() {
542
delete_descriptor(mono_descriptor);
546
/* Return a descriptor of the requested plugin type. */
547
const LADSPA_Descriptor *
548
ladspa_descriptor(unsigned long Index) {
552
return mono_descriptor;