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 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
<?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"/>
<code><![CDATA[
#include "ladspa-util.h"
#define BASE_BUFFER 8 // Tape length (inches)
]]></code>
</global>
<plugin label="tapeDelay" id="1211" class="DelayPlugin,SimulatorPlugin">
<name>Tape Delay Simulation</name>
<p>Correctly models the tape motion and some of the smear effect, there is no simulation for the head saturation yet, as I don't have a good model of it. When I get one I will add it.</p>
<p>The way the tape accelerates and decelerates gives a nicer delay effect for many purposes.</p>
<callback event="instantiate"><![CDATA[
unsigned int mbs = BASE_BUFFER * s_rate;
sample_rate = s_rate;
for (buffer_size = 4096; buffer_size < mbs;
buffer_size *= 2);
buffer = malloc(buffer_size * sizeof(LADSPA_Data));
buffer_mask = buffer_size - 1;
phase = 0;
last_phase = 0;
last_in = 0.0f;
last2_in = 0.0f;
last3_in = 0.0f;
z0 = 0.0f;
z1 = 0.0f;
z2 = 0.0f;
]]></callback>
<callback event="activate">
int i;
for (i = 0; i < buffer_size; i++) {
buffer[i] = 0;
}
phase = 0;
last_phase = 0;
last_in = 0.0f;
last2_in = 0.0f;
last3_in = 0.0f;
sample_rate = sample_rate;
z0 = 0.0f;
z1 = 0.0f;
z2 = 0.0f;
</callback>
<callback event="cleanup"><![CDATA[
free(plugin_data->buffer);
]]></callback>
<callback event="run"><![CDATA[
unsigned int pos;
float increment = f_clamp(speed, 0.0f, 40.0f);
float lin_int, lin_inc;
unsigned int track;
unsigned int fph;
LADSPA_Data out;
const float da = DB_CO(da_db);
const float t1a = DB_CO(t1a_db);
const float t2a = DB_CO(t2a_db);
const float t3a = DB_CO(t3a_db);
const float t4a = DB_CO(t4a_db);
const unsigned int t1d_s = f_round(t1d * sample_rate);
const unsigned int t2d_s = f_round(t2d * sample_rate);
const unsigned int t3d_s = f_round(t3d * sample_rate);
const unsigned int t4d_s = f_round(t4d * sample_rate);
for (pos = 0; pos < sample_count; pos++) {
fph = f_trunc(phase);
last_phase = fph;
lin_int = phase - (float)fph;
out = buffer[(unsigned int)(fph - t1d_s) & buffer_mask] * t1a;
out += buffer[(unsigned int)(fph - t2d_s) & buffer_mask] * t2a;
out += buffer[(unsigned int)(fph - t3d_s) & buffer_mask] * t3a;
out += buffer[(unsigned int)(fph - t4d_s) & buffer_mask] * t4a;
phase += increment;
lin_inc = 1.0f / (floor(phase) - last_phase + 1);
lin_inc = lin_inc > 1.0f ? 1.0f : lin_inc;
lin_int = 0.0f;
for (track = last_phase; track < phase; track++) {
lin_int += lin_inc;
buffer[track & buffer_mask] =
cube_interp(lin_int, last3_in, last2_in, last_in, input[pos]);
}
last3_in = last2_in;
last2_in = last_in;
last_in = input[pos];
out += input[pos] * da;
buffer_write(output[pos], out);
if (phase >= buffer_size) {
phase -= buffer_size;
}
}
// Store current phase in instance
plugin_data->phase = phase;
plugin_data->last_phase = last_phase;
plugin_data->last_in = last_in;
plugin_data->last2_in = last2_in;
plugin_data->last3_in = last3_in;
plugin_data->z0 = z0;
plugin_data->z1 = z1;
plugin_data->z2 = z2;
]]></callback>
<port label="speed" dir="input" type="control" hint="default_1">
<name>Tape speed (inches/sec, 1=normal)</name>
<range min="0" max="10"/>
</port>
<port label="da_db" dir="input" type="control" hint="default_minimum">
<name>Dry level (dB)</name>
<range min="-90" max="0"/>
</port>
<port label="t1d" dir="input" type="control" hint="default_0">
<name>Tap 1 distance (inches)</name>
<range min="0" max="4"/>
</port>
<port label="t1a_db" dir="input" type="control" hint="default_0">
<name>Tap 1 level (dB)</name>
<range min="-90" max="0"/>
</port>
<port label="t2d" dir="input" type="control" hint="default_low">
<name>Tap 2 distance (inches)</name>
<range min="0" max="4"/>
</port>
<port label="t2a_db" dir="input" type="control" hint="default_minimum">
<name>Tap 2 level (dB)</name>
<range min="-90" max="0"/>
</port>
<port label="t3d" dir="input" type="control" hint="default_middle">
<name>Tap 3 distance (inches)</name>
<range min="0" max="4"/>
</port>
<port label="t3a_db" dir="input" type="control" hint="default_minimum">
<name>Tap 3 level (dB)</name>
<range min="-90" max="0"/>
</port>
<port label="t4d" dir="input" type="control" hint="default_high">
<name>Tap 4 distance (inches)</name>
<range min="0" max="4"/>
</port>
<port label="t4a_db" dir="input" type="control" hint="default_minimum">
<name>Tap 4 level (dB)</name>
<range min="-90" max="0"/>
</port>
<port label="input" dir="input" type="audio">
<name>Input</name>
</port>
<port label="output" dir="output" type="audio">
<name>Output</name>
</port>
<instance-data label="buffer" type="LADSPA_Data *"/>
<instance-data label="buffer_size" type="unsigned int"/>
<instance-data label="buffer_mask" type="unsigned int"/>
<instance-data label="phase" type="float"/>
<instance-data label="last_phase" type="unsigned int"/>
<instance-data label="last_in" type="LADSPA_Data"/>
<instance-data label="last2_in" type="LADSPA_Data"/>
<instance-data label="last3_in" type="LADSPA_Data"/>
<instance-data label="sample_rate" type="int"/>
<instance-data label="z0" type="LADSPA_Data"/>
<instance-data label="z1" type="LADSPA_Data"/>
<instance-data label="z2" type="LADSPA_Data"/>
</plugin>
</ladspa>
|