forked from swh/ladspa
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgsm_1215.xml
160 lines (133 loc) · 5.05 KB
/
gsm_1215.xml
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
<?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 <[email protected]>"/>
<meta name="copyright" value="GPL"/>
<code><![CDATA[
#include <stdlib.h>
#include "ladspa-util.h"
#include "gsm/gsm.h"
#include "util/biquad.h"
#define SCALE 32768.0f
#define SCALE_R 0.0000305175f
int bits[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
]]></code>
</global>
<plugin label="gsm" id="1215" class="DistortionPlugin">
<name>GSM simulator</name>
<p>Encodes and decodes a signal using the GSM voice compression system. Has the effect of making the signal sound like it is being sent over a European mobile phone network.</p>
<callback event="instantiate"><![CDATA[
count = 0;
resamp = s_rate / 8000;
fs = s_rate;
rsf = SCALE / (float)resamp;
src = malloc(sizeof(gsm_signal) * 160);
dst = malloc(sizeof(gsm_signal) * 163);
dry = malloc(sizeof(LADSPA_Data) * 160 * resamp);
handle = NULL;
blf = malloc(sizeof(biquad));
biquad_init(blf);
]]></callback>
<callback event="activate"><![CDATA[
count = 0;
memset(src, 0, sizeof(gsm_signal) * 160);
memset(dst, 0, sizeof(gsm_signal) * 163);
memset(dry, 0, sizeof(LADSPA_Data) * 160 * resamp);
handle = gsm_create();
biquad_init(blf);
hs_set_params(blf, 3500.0f, -50.0f, 0.7f, fs);
]]></callback>
<callback event="cleanup"><![CDATA[
free(plugin_data->src);
free(plugin_data->dst);
free(plugin_data->dry);
free(plugin_data->blf);
if (plugin_data->handle) {
gsm_destroy(plugin_data->handle);
}
]]></callback>
<callback event="run"><![CDATA[
unsigned long pos;
gsm_frame frame;
int samp;
float part;
int error_rate = f_round(error);
int num_passes = f_round(passes);
fs = fs; // So gcc doesn't think it's unused
for (pos = 0; pos < sample_count; pos++) {
// oversample into buffer down to aprox 8kHz, 13bit
src[count / resamp] += f_round(biquad_run(blf, input[pos]) * rsf);
// interpolate output, so it doesn't sound totaly awful
samp = count / resamp;
part = (float)count / (float)resamp - (float)samp;
buffer_write(output[pos], cube_interp(part, dst[samp], dst[samp+1], dst[samp+2], dst[samp+3]) * SCALE_R * drywet + dry[count] * (1.0f - drywet));
// Maintain delayed, dry buffer.
dry[count] = input[pos];
count++;
// If we have a full, downsampled buffer then run the encode +
// decode process.
if (count >= 160 * resamp) {
int i, j;
gsm_signal *in;
count = 0;
dst[0] = dst[160];
dst[1] = dst[161];
dst[2] = dst[162];
in = src;
for (j=0; j<num_passes; j++) {
gsm_encode(handle, in, frame);
for (i=0; i < error_rate; i++) {
frame[1 + (rand() % 32)] ^= bits[rand() % 8];
}
gsm_decode(handle, frame, dst+3);
in = dst+3;
}
if (num_passes == 0) {
for (j=0; j < 160; j++) {
dst[j + 3] = src[j];
}
}
memset(src, 0, sizeof(gsm_signal) * 160);
}
}
plugin_data->count = count;
*(plugin_data->latency) = 160 * resamp;
]]></callback>
<port label="drywet" dir="input" type="control" hint="default_1">
<name>Dry/wet mix</name>
<range min="0" max="1"/>
<p>Controls the dry/wet mix, 0 will give you the dry signal (but with the appropriate amount of delay), 1 will give you a totally wet signal.</p>
</port>
<port label="passes" dir="input" type="control" hint="integer,default_1">
<name>Number of passes</name>
<range min="0" max="10"/>
<p>The number of times the signal is sent through the encode/decode process. Increases the CPU consumption almost linearly, and it will become more peaky so less friendly to realtime processing.</p>
</port>
<port label="error" dir="input" type="control" hint="default_0">
<name>Error rate (bits/block)</name>
<range min="0" max="30"/>
<p>The number of simulated bits that get changed during the transmission process.</p>
<p>I really wanted to reduce the bandwidth to get that {}"shouting down a drainpipe{}" effect, but I'm not sure how the reduced bandwidth is dealt with by real phones. I suspect it's heavily patented technology.</p>
</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="count" type="int" />
<instance-data label="fs" type="float" />
<instance-data label="rsf" type="float" />
<instance-data label="resamp" type="int" />
<instance-data label="handle" type="gsm" />
<instance-data label="dry" type="LADSPA_Data *" />
<instance-data label="src" type="gsm_signal *" />
<instance-data label="dst" type="gsm_signal *" />
<instance-data label="blf" type="biquad *" />
</plugin>
</ladspa>