diff options
Diffstat (limited to 'apps/codecs/dumb/src/helpers/clickrem.c')
-rw-r--r-- | apps/codecs/dumb/src/helpers/clickrem.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/apps/codecs/dumb/src/helpers/clickrem.c b/apps/codecs/dumb/src/helpers/clickrem.c new file mode 100644 index 0000000000..ddc861d931 --- /dev/null +++ b/apps/codecs/dumb/src/helpers/clickrem.c | |||
@@ -0,0 +1,270 @@ | |||
1 | /* _______ ____ __ ___ ___ | ||
2 | * \ _ \ \ / \ / \ \ / / ' ' ' | ||
3 | * | | \ \ | | || | \/ | . . | ||
4 | * | | | | | | || ||\ /| | | ||
5 | * | | | | | | || || \/ | | ' ' ' | ||
6 | * | | | | | | || || | | . . | ||
7 | * | |_/ / \ \__// || | | | ||
8 | * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque | ||
9 | * / \ | ||
10 | * / . \ | ||
11 | * clickrem.c - Click removal helpers. / / \ \ | ||
12 | * | < / \_ | ||
13 | * By entheh. | \/ /\ / | ||
14 | * \_ / > / | ||
15 | * | \ / / | ||
16 | * | ' / | ||
17 | * \__/ | ||
18 | */ | ||
19 | |||
20 | #include <stdlib.h> | ||
21 | #include <math.h> | ||
22 | #include "dumb.h" | ||
23 | |||
24 | |||
25 | |||
26 | typedef struct DUMB_CLICK DUMB_CLICK; | ||
27 | |||
28 | |||
29 | struct DUMB_CLICK_REMOVER | ||
30 | { | ||
31 | DUMB_CLICK *click; | ||
32 | int n_clicks; | ||
33 | |||
34 | int offset; | ||
35 | }; | ||
36 | |||
37 | |||
38 | struct DUMB_CLICK | ||
39 | { | ||
40 | DUMB_CLICK *next; | ||
41 | long pos; | ||
42 | sample_t step; | ||
43 | }; | ||
44 | |||
45 | |||
46 | |||
47 | DUMB_CLICK_REMOVER *dumb_create_click_remover(void) | ||
48 | { | ||
49 | DUMB_CLICK_REMOVER *cr = malloc(sizeof(*cr)); | ||
50 | if (!cr) return NULL; | ||
51 | |||
52 | cr->click = NULL; | ||
53 | cr->n_clicks = 0; | ||
54 | |||
55 | cr->offset = 0; | ||
56 | |||
57 | return cr; | ||
58 | } | ||
59 | |||
60 | |||
61 | |||
62 | void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step) | ||
63 | { | ||
64 | DUMB_CLICK *click; | ||
65 | |||
66 | ASSERT(pos >= 0); | ||
67 | |||
68 | if (!cr || !step) return; | ||
69 | |||
70 | if (pos == 0) { | ||
71 | cr->offset -= step; | ||
72 | return; | ||
73 | } | ||
74 | |||
75 | click = malloc(sizeof(*click)); | ||
76 | if (!click) return; | ||
77 | |||
78 | click->pos = pos; | ||
79 | click->step = step; | ||
80 | |||
81 | click->next = cr->click; | ||
82 | cr->click = click; | ||
83 | cr->n_clicks++; | ||
84 | } | ||
85 | |||
86 | |||
87 | |||
88 | static DUMB_CLICK *dumb_click_mergesort(DUMB_CLICK *click, int n_clicks) | ||
89 | { | ||
90 | int i; | ||
91 | DUMB_CLICK *c1, *c2, **cp; | ||
92 | |||
93 | if (n_clicks <= 1) return click; | ||
94 | |||
95 | /* Split the list into two */ | ||
96 | c1 = click; | ||
97 | cp = &c1; | ||
98 | for (i = 0; i < n_clicks; i += 2) cp = &(*cp)->next; | ||
99 | c2 = *cp; | ||
100 | *cp = NULL; | ||
101 | |||
102 | /* Sort the sublists */ | ||
103 | c1 = dumb_click_mergesort(c1, (n_clicks + 1) >> 1); | ||
104 | c2 = dumb_click_mergesort(c2, n_clicks >> 1); | ||
105 | |||
106 | /* Merge them */ | ||
107 | cp = &click; | ||
108 | while (c1 && c2) { | ||
109 | if (c1->pos > c2->pos) { | ||
110 | *cp = c2; | ||
111 | c2 = c2->next; | ||
112 | } else { | ||
113 | *cp = c1; | ||
114 | c1 = c1->next; | ||
115 | } | ||
116 | cp = &(*cp)->next; | ||
117 | } | ||
118 | if (c2) | ||
119 | *cp = c2; | ||
120 | else | ||
121 | *cp = c1; | ||
122 | |||
123 | return click; | ||
124 | } | ||
125 | |||
126 | |||
127 | |||
128 | void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, float halflife) | ||
129 | { | ||
130 | DUMB_CLICK *click; | ||
131 | long pos = 0; | ||
132 | int offset; | ||
133 | int factor; | ||
134 | |||
135 | if (!cr) return; | ||
136 | |||
137 | factor = (int)floor(pow(0.5, 1.0/halflife) * (1U << 31)); | ||
138 | |||
139 | click = dumb_click_mergesort(cr->click, cr->n_clicks); | ||
140 | cr->click = NULL; | ||
141 | cr->n_clicks = 0; | ||
142 | |||
143 | while (click) { | ||
144 | DUMB_CLICK *next = click->next; | ||
145 | ASSERT(click->pos <= length); | ||
146 | offset = cr->offset; | ||
147 | if (offset < 0) { | ||
148 | offset = -offset; | ||
149 | while (pos < click->pos) { | ||
150 | samples[pos++] -= offset; | ||
151 | offset = (int)((LONG_LONG)(offset << 1) * factor >> 32); | ||
152 | } | ||
153 | offset = -offset; | ||
154 | } else { | ||
155 | while (pos < click->pos) { | ||
156 | samples[pos++] += offset; | ||
157 | offset = (int)((LONG_LONG)(offset << 1) * factor >> 32); | ||
158 | } | ||
159 | } | ||
160 | cr->offset = offset - click->step; | ||
161 | free(click); | ||
162 | click = next; | ||
163 | } | ||
164 | |||
165 | offset = cr->offset; | ||
166 | if (offset < 0) { | ||
167 | offset = -offset; | ||
168 | while (pos < length) { | ||
169 | samples[pos++] -= offset; | ||
170 | offset = (int)((LONG_LONG)(offset << 1) * factor >> 32); | ||
171 | } | ||
172 | offset = -offset; | ||
173 | } else { | ||
174 | while (pos < length) { | ||
175 | samples[pos++] += offset; | ||
176 | offset = (int)((LONG_LONG)(offset << 1) * factor >> 32); | ||
177 | } | ||
178 | } | ||
179 | cr->offset = offset; | ||
180 | } | ||
181 | |||
182 | |||
183 | |||
184 | sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr) | ||
185 | { | ||
186 | return cr ? cr->offset : 0; | ||
187 | } | ||
188 | |||
189 | |||
190 | |||
191 | void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr) | ||
192 | { | ||
193 | if (cr) { | ||
194 | DUMB_CLICK *click = cr->click; | ||
195 | while (click) { | ||
196 | DUMB_CLICK *next = click->next; | ||
197 | free(click); | ||
198 | click = next; | ||
199 | } | ||
200 | free(cr); | ||
201 | } | ||
202 | } | ||
203 | |||
204 | |||
205 | |||
206 | DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n) | ||
207 | { | ||
208 | int i; | ||
209 | DUMB_CLICK_REMOVER **cr; | ||
210 | if (n <= 0) return NULL; | ||
211 | cr = malloc(n * sizeof(*cr)); | ||
212 | if (!cr) return NULL; | ||
213 | for (i = 0; i < n; i++) cr[i] = dumb_create_click_remover(); | ||
214 | return cr; | ||
215 | } | ||
216 | |||
217 | |||
218 | |||
219 | void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step) | ||
220 | { | ||
221 | if (cr) { | ||
222 | int i; | ||
223 | for (i = 0; i < n; i++) | ||
224 | dumb_record_click(cr[i], pos, step[i]); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | |||
229 | |||
230 | void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step) | ||
231 | { | ||
232 | if (cr) { | ||
233 | int i; | ||
234 | for (i = 0; i < n; i++) | ||
235 | dumb_record_click(cr[i], pos, -step[i]); | ||
236 | } | ||
237 | } | ||
238 | |||
239 | |||
240 | |||
241 | void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr, sample_t **samples, long length, float halflife) | ||
242 | { | ||
243 | if (cr) { | ||
244 | int i; | ||
245 | for (i = 0; i < n; i++) | ||
246 | dumb_remove_clicks(cr[i], samples[i], length, halflife); | ||
247 | } | ||
248 | } | ||
249 | |||
250 | |||
251 | |||
252 | void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr, sample_t *offset) | ||
253 | { | ||
254 | if (cr) { | ||
255 | int i; | ||
256 | for (i = 0; i < n; i++) | ||
257 | if (cr[i]) offset[i] += cr[i]->offset; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | |||
262 | |||
263 | void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr) | ||
264 | { | ||
265 | if (cr) { | ||
266 | int i; | ||
267 | for (i = 0; i < n; i++) dumb_destroy_click_remover(cr[i]); | ||
268 | free(cr); | ||
269 | } | ||
270 | } | ||