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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
<?xml version="1.0"?>
<!DOCTYPE ladspa SYSTEM "ladspa-swh.dtd">
<?xml-stylesheet href="ladspa.css" type="text/css"?>
<ladspa>
<global>
<meta name="maker" value="Steve Harris <steve@plugin.org.uk>"/>
<meta name="copyright" value="GPL"/>
<meta name="properties" value="HARD_RT_CAPABLE"/>
<code><![CDATA[
#include <stdlib.h>
#include <math.h>
#include "ladspa-util.h"
/* Beware of dependcies if you change this */
#define DELAY_SIZE 8192
]]></code>
</global>
<plugin label="amPitchshift" id="1433" class="PitchPlugin">
<name>AM pitchshifter</name>
<p>This plugin works by running a single write pointer (monotonic) and two read pointers (pitchscaled) over a ringbuffer.</p>
<p>The output is faded between the two readpointers according to the sine of the distance from the write pointer. The design is based on the mechanism of a mechanical pitchshifter I saw in the Gemeentemuseum in Den Haag, though I'm sure it is a common enough algorithm.</p>
<callback event="instantiate"><![CDATA[
delay = calloc(DELAY_SIZE, sizeof(LADSPA_Data));
rptr.all = 0;
wptr = 0;
last_size = -1;
delay_mask = 0xFF;
delay_ofs = 0x80;
last_gain = 0.5f;
count = 0;
last_inc = 0.0f;
]]></callback>
<callback event="cleanup"><![CDATA[
free(plugin_data->delay);
]]></callback>
<callback event="run"><![CDATA[
unsigned long pos;
fixp16 om;
float gain = last_gain, gain_inc = last_inc;
unsigned int i;
om.all = f_round(pitch * 65536.0f);
if (size != last_size) {
int size_tmp = f_round(size);
if (size_tmp > 7) {
size_tmp = 5;
} else if (size_tmp < 1) {
size_tmp = 1;
}
plugin_data->last_size = size;
/* Calculate the ringbuf parameters, the magick constants will need
* to be changed if you change DELAY_SIZE */
delay_mask = (1 << (size_tmp + 6)) - 1;
delay_ofs = 1 << (size_tmp + 5);
}
for (pos = 0; pos < sample_count; pos++) {
float out = 0.0f;
if (count++ > 14) {
float tmp;
count = 0;
tmp = 0.5f * (float)((rptr.part.in - wptr + delay_ofs/2) &
delay_mask) / (float)delay_ofs;
tmp = sinf(M_PI * 2.0f * tmp) * 0.5f + 0.5f;
gain_inc = (tmp - gain) / 15.0f;
}
gain += gain_inc;
delay[wptr] = input[pos];
/* Add contributions from the two readpointers, scaled by thier
* distance from the write pointer */
i = rptr.part.in;
out += cube_interp((float)rptr.part.fr * 0.0000152587f,
delay[(i - 1) & delay_mask], delay[i],
delay[(i + 1) & delay_mask],
delay[(i + 2) & delay_mask]) * (1.0f - gain);
i += delay_ofs;
out += cube_interp((float)rptr.part.fr * 0.0000152587f,
delay[(i - 1) & delay_mask], delay[i & delay_mask],
delay[(i + 1) & delay_mask],
delay[(i + 2) & delay_mask]) * gain;
buffer_write(output[pos], out);
/* Increment ringbuffer pointers */
wptr = (wptr + 1) & delay_mask;
rptr.all += om.all;
rptr.part.in &= delay_mask;
}
plugin_data->rptr.all = rptr.all;
plugin_data->wptr = wptr;
plugin_data->delay_mask = delay_mask;
plugin_data->delay_ofs = delay_ofs;
plugin_data->last_gain = gain;
plugin_data->count = count;
plugin_data->last_inc = gain_inc;
*(plugin_data->latency) = delay_ofs/2;
]]></callback>
<port label="pitch" dir="input" type="control" hint="logarithmic,default_1">
<name>Pitch shift</name>
<p>The multiple of the output pitch, eg. 2.0 will increase the pitch by one octave.</p>
<range min="0.25" max="4.0"/>
</port>
<port label="size" dir="input" type="control" hint="integer,default_middle">
<name>Buffer size</name>
<p>The order of magnitude of the buffer size. Small buffers will sound fluttery, large buffers will have flangy sounding echos.</p>
<p>I recommend a buffer size of 3 for a reasonable compromise, with wideband material at around 48KHz. For drums you might have to lower it, and for voiced background noises it can go higher.</p>
<range min="1" max="7"/>
</port>
<port label="input" dir="input" type="audio">
<name>Input</name>
</port>
<port label="output" dir="output" type="audio">
<name>Output</name>
</port>
<port label="latency" dir="output" type="control">
<name>latency</name>
</port>
<instance-data label="delay" type="LADSPA_Data *" />
<instance-data label="rptr" type="fixp16" />
<instance-data label="wptr" type="unsigned int" />
<instance-data label="last_size" type="int" />
<instance-data label="delay_mask" type="unsigned int" />
<instance-data label="delay_ofs" type="unsigned int" />
<instance-data label="last_gain" type="float" />
<instance-data label="last_inc" type="float" />
<instance-data label="count" type="unsigned int" />
</plugin>
</ladspa>
|