Mercurial > audlegacy
comparison Plugins/Input/console/Effects_Buffer.cpp @ 90:252843aac42f trunk
[svn] Import the initial sources for console music support.
author | nenolod |
---|---|
date | Tue, 01 Nov 2005 19:57:26 -0800 |
parents | |
children | 84aabc053b6e |
comparison
equal
deleted
inserted
replaced
89:feeda0dda3ce | 90:252843aac42f |
---|---|
1 | |
2 // Game_Music_Emu 0.2.4. http://www.slack.net/~ant/libs/ | |
3 | |
4 #include "Effects_Buffer.h" | |
5 | |
6 #include <string.h> | |
7 | |
8 /* Copyright (C) 2003-2005 Shay Green. This module is free software; you | |
9 can redistribute it and/or modify it under the terms of the GNU Lesser | |
10 General Public License as published by the Free Software Foundation; either | |
11 version 2.1 of the License, or (at your option) any later version. This | |
12 module is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for | |
15 more details. You should have received a copy of the GNU Lesser General | |
16 Public License along with this module; if not, write to the Free Software | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | |
18 | |
19 #include BLARGG_SOURCE_BEGIN | |
20 | |
21 typedef long fixed_t; | |
22 | |
23 #define TO_FIXED( f ) fixed_t ((f) * (1L << 15) + 0.5) | |
24 #define FMUL( x, y ) (((x) * (y)) >> 15) | |
25 | |
26 const unsigned echo_size = 4096; | |
27 const unsigned echo_mask = echo_size - 1; | |
28 BOOST_STATIC_ASSERT( (echo_size & echo_mask) == 0 ); // must be power of 2 | |
29 | |
30 const unsigned reverb_size = 8192 * 2; | |
31 const unsigned reverb_mask = reverb_size - 1; | |
32 BOOST_STATIC_ASSERT( (reverb_size & reverb_mask) == 0 ); // must be power of 2 | |
33 | |
34 Effects_Buffer::config_t::config_t() | |
35 { | |
36 pan_1 = 0.0; | |
37 pan_2 = 0.0; | |
38 reverb_delay = 88; | |
39 reverb_level = 0.10; | |
40 echo_delay = 61; | |
41 echo_level = 0.12; | |
42 delay_variance = 18; | |
43 effects_enabled = false; | |
44 } | |
45 | |
46 Effects_Buffer::Effects_Buffer() | |
47 { | |
48 echo_buf = NULL; | |
49 echo_pos = 0; | |
50 | |
51 reverb_buf = NULL; | |
52 reverb_pos = 0; | |
53 | |
54 stereo_remain = 0; | |
55 effect_remain = 0; | |
56 effects_enabled = false; | |
57 config( config_t() ); | |
58 } | |
59 | |
60 Effects_Buffer::~Effects_Buffer() | |
61 { | |
62 delete [] echo_buf; | |
63 delete [] reverb_buf; | |
64 } | |
65 | |
66 blargg_err_t Effects_Buffer::sample_rate( long rate, int msec ) | |
67 { | |
68 if ( !echo_buf ) | |
69 { | |
70 echo_buf = new blip_sample_t [echo_size]; | |
71 if ( !echo_buf ) | |
72 return "Out of memory"; | |
73 } | |
74 | |
75 if ( !reverb_buf ) | |
76 { | |
77 reverb_buf = new blip_sample_t [reverb_size]; | |
78 if ( !reverb_buf ) | |
79 return "Out of memory"; | |
80 } | |
81 | |
82 for ( int i = 0; i < buf_count; i++ ) | |
83 BLARGG_RETURN_ERR( bufs [i].sample_rate( rate, msec ) ); | |
84 | |
85 length_ = msec; | |
86 sample_rate_ = rate; | |
87 | |
88 config( config_ ); | |
89 | |
90 return blargg_success; | |
91 } | |
92 | |
93 void Effects_Buffer::clock_rate( long rate ) | |
94 { | |
95 for ( int i = 0; i < buf_count; i++ ) | |
96 bufs [i].clock_rate( rate ); | |
97 } | |
98 | |
99 void Effects_Buffer::bass_freq( int freq ) | |
100 { | |
101 for ( int i = 0; i < buf_count; i++ ) | |
102 bufs [i].bass_freq( freq ); | |
103 } | |
104 | |
105 void Effects_Buffer::clear() | |
106 { | |
107 stereo_remain = 0; | |
108 effect_remain = 0; | |
109 memset( echo_buf, 0, echo_size * sizeof (blip_sample_t) ); | |
110 memset( reverb_buf, 0, reverb_size * sizeof (blip_sample_t) ); | |
111 for ( int i = 0; i < buf_count; i++ ) | |
112 bufs [i].clear(); | |
113 } | |
114 | |
115 inline int pin_range( int n, int max, int min = 0 ) | |
116 { | |
117 if ( n < min ) | |
118 return min; | |
119 if ( n > max ) | |
120 return max; | |
121 return n; | |
122 } | |
123 | |
124 void Effects_Buffer::config( const config_t& cfg ) | |
125 { | |
126 // clear echo and reverb buffers | |
127 if ( !config_.effects_enabled && cfg.effects_enabled && echo_buf ) { | |
128 memset( echo_buf, 0, echo_size * sizeof (blip_sample_t) ); | |
129 memset( reverb_buf, 0, reverb_size * sizeof (blip_sample_t) ); | |
130 } | |
131 | |
132 config_ = cfg; | |
133 | |
134 if ( config_.effects_enabled ) | |
135 { | |
136 // convert to internal format | |
137 | |
138 chans.pan_1_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_1 ); | |
139 chans.pan_1_levels [1] = TO_FIXED( 2 ) - chans.pan_1_levels [0]; | |
140 | |
141 chans.pan_2_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_2 ); | |
142 chans.pan_2_levels [1] = TO_FIXED( 2 ) - chans.pan_2_levels [0]; | |
143 | |
144 chans.reverb_level = TO_FIXED( config_.reverb_level ); | |
145 chans.echo_level = TO_FIXED( config_.echo_level ); | |
146 | |
147 const int delay_offset = config_.delay_variance * sample_rate_ / (1000 * 2); | |
148 | |
149 const int reverb_sample_delay = config_.reverb_delay * sample_rate_ / 1000; | |
150 chans.reverb_delay_l = pin_range( reverb_size - | |
151 (reverb_sample_delay - delay_offset) * 2, reverb_size - 2, 0 ); | |
152 chans.reverb_delay_r = pin_range( reverb_size + 1 - | |
153 (reverb_sample_delay + delay_offset) * 2, reverb_size - 1, 1 ); | |
154 | |
155 const int echo_sample_delay = config_.echo_delay * sample_rate_ / 1000; | |
156 chans.echo_delay_l = pin_range( echo_size - 1 - (echo_sample_delay - delay_offset), | |
157 echo_size - 1 ); | |
158 chans.echo_delay_r = pin_range( echo_size - 1 - (echo_sample_delay + delay_offset), | |
159 echo_size - 1 ); | |
160 | |
161 // set up outputs | |
162 for ( unsigned i = 0; i < chan_count; i++ ) { | |
163 channel_t& o = channels [i]; | |
164 if ( i < 2 ) { | |
165 o.center = &bufs [i]; | |
166 o.left = &bufs [3]; | |
167 o.right = &bufs [4]; | |
168 } | |
169 else { | |
170 o.center = &bufs [2]; | |
171 o.left = &bufs [5]; | |
172 o.right = &bufs [6]; | |
173 } | |
174 } | |
175 | |
176 } | |
177 else { | |
178 // set up outputs | |
179 for ( unsigned i = 0; i < chan_count; i++ ) { | |
180 channel_t& o = channels [i]; | |
181 o.center = &bufs [0]; | |
182 o.left = &bufs [1]; | |
183 o.right = &bufs [2]; | |
184 } | |
185 } | |
186 } | |
187 | |
188 void Effects_Buffer::end_frame( blip_time_t clock_count, bool stereo ) | |
189 { | |
190 for ( int i = 0; i < buf_count; i++ ) | |
191 bufs [i].end_frame( clock_count ); | |
192 | |
193 if ( stereo ) | |
194 stereo_remain = bufs [0].samples_avail() + bufs [0].output_latency(); | |
195 | |
196 if ( effects_enabled || config_.effects_enabled ) | |
197 effect_remain = bufs [0].samples_avail() + bufs [0].output_latency(); | |
198 | |
199 effects_enabled = config_.effects_enabled; | |
200 } | |
201 | |
202 #include BLARGG_ENABLE_OPTIMIZER | |
203 | |
204 long Effects_Buffer::read_samples( blip_sample_t* out, long total_samples ) | |
205 { | |
206 require( total_samples % 2 == 0 ); // count must be even | |
207 | |
208 long remain = bufs [0].samples_avail(); | |
209 if ( remain > (unsigned) total_samples / 2 ) | |
210 remain = (unsigned) total_samples / 2; | |
211 total_samples = remain; | |
212 while ( remain ) | |
213 { | |
214 int active_bufs = buf_count; | |
215 long count = remain; | |
216 | |
217 if ( effect_remain ) { | |
218 if ( count > effect_remain ) | |
219 count = effect_remain; | |
220 | |
221 if ( stereo_remain ) { | |
222 mix_enhanced( out, count ); | |
223 } | |
224 else { | |
225 mix_mono_enhanced( out, count ); | |
226 active_bufs = 3; | |
227 } | |
228 } | |
229 else if ( stereo_remain ) { | |
230 mix_stereo( out, count ); | |
231 active_bufs = 3; | |
232 } | |
233 else { | |
234 mix_mono( out, count ); | |
235 active_bufs = 1; | |
236 } | |
237 | |
238 out += count * 2; | |
239 remain -= count; | |
240 | |
241 stereo_remain -= count; | |
242 if ( stereo_remain < 0 ) | |
243 stereo_remain = 0; | |
244 | |
245 effect_remain -= count; | |
246 if ( effect_remain < 0 ) | |
247 effect_remain = 0; | |
248 | |
249 for ( int i = 0; i < buf_count; i++ ) { | |
250 if ( i < active_bufs ) | |
251 bufs [i].remove_samples( count ); | |
252 else | |
253 bufs [i].remove_silence( count ); // keep time synchronized | |
254 } | |
255 } | |
256 | |
257 return total_samples * 2; | |
258 } | |
259 | |
260 void Effects_Buffer::mix_mono( blip_sample_t* out, long count ) | |
261 { | |
262 Blip_Reader c; | |
263 int shift = c.begin( bufs [0] ); | |
264 | |
265 // unrolled loop | |
266 for ( long n = count >> 1; n--; ) | |
267 { | |
268 long cs0 = c.read(); | |
269 c.next( shift ); | |
270 | |
271 long cs1 = c.read(); | |
272 c.next( shift ); | |
273 | |
274 if ( (BOOST::int16_t) cs0 != cs0 ) | |
275 cs0 = 0x7FFF - (cs0 >> 24); | |
276 ((BOOST::uint32_t*) out) [0] = ((BOOST::uint16_t) cs0) | (cs0 << 16); | |
277 | |
278 if ( (BOOST::int16_t) cs1 != cs1 ) | |
279 cs1 = 0x7FFF - (cs1 >> 24); | |
280 ((BOOST::uint32_t*) out) [1] = ((BOOST::uint16_t) cs1) | (cs1 << 16); | |
281 out += 4; | |
282 } | |
283 | |
284 if ( count & 1 ) { | |
285 int s = c.read(); | |
286 c.next( shift ); | |
287 out [0] = s; | |
288 out [1] = s; | |
289 if ( (BOOST::int16_t) s != s ) { | |
290 s = 0x7FFF - (s >> 24); | |
291 out [0] = s; | |
292 out [1] = s; | |
293 } | |
294 } | |
295 | |
296 c.end( bufs [0] ); | |
297 } | |
298 | |
299 void Effects_Buffer::mix_stereo( blip_sample_t* out, long count ) | |
300 { | |
301 Blip_Reader l; l.begin( bufs [1] ); | |
302 Blip_Reader r; r.begin( bufs [2] ); | |
303 Blip_Reader c; | |
304 int shift = c.begin( bufs [0] ); | |
305 | |
306 while ( count-- ) { | |
307 int cs = c.read(); | |
308 c.next( shift ); | |
309 int left = cs + l.read(); | |
310 int right = cs + r.read(); | |
311 l.next( shift ); | |
312 r.next( shift ); | |
313 | |
314 if ( (BOOST::int16_t) left != left ) | |
315 left = 0x7FFF - (left >> 24); | |
316 | |
317 out [0] = left; | |
318 out [1] = right; | |
319 | |
320 out += 2; | |
321 | |
322 if ( (BOOST::int16_t) right != right ) | |
323 out [-1] = 0x7FFF - (right >> 24); | |
324 } | |
325 | |
326 c.end( bufs [0] ); | |
327 r.end( bufs [2] ); | |
328 l.end( bufs [1] ); | |
329 } | |
330 | |
331 void Effects_Buffer::mix_mono_enhanced( blip_sample_t* out, long count ) | |
332 { | |
333 Blip_Reader sq1; sq1.begin( bufs [0] ); | |
334 Blip_Reader sq2; sq2.begin( bufs [1] ); | |
335 Blip_Reader center; | |
336 int shift = center.begin( bufs [2] ); | |
337 | |
338 int echo_pos = this->echo_pos; | |
339 int reverb_pos = this->reverb_pos; | |
340 | |
341 while ( count-- ) | |
342 { | |
343 int sum1_s = sq1.read(); | |
344 int sum2_s = sq2.read(); | |
345 | |
346 sq1.next( shift ); | |
347 sq2.next( shift ); | |
348 | |
349 int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) + | |
350 FMUL( sum2_s, chans.pan_2_levels [0] ) + | |
351 reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask]; | |
352 | |
353 int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) + | |
354 FMUL( sum2_s, chans.pan_2_levels [1] ) + | |
355 reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask]; | |
356 | |
357 fixed_t reverb_level = chans.reverb_level; | |
358 reverb_buf [reverb_pos] = FMUL( new_reverb_l, reverb_level ); | |
359 reverb_buf [reverb_pos + 1] = FMUL( new_reverb_r, reverb_level ); | |
360 reverb_pos = (reverb_pos + 2) & reverb_mask; | |
361 | |
362 int sum3_s = center.read(); | |
363 center.next( shift ); | |
364 | |
365 int left = new_reverb_l + sum3_s + FMUL( chans.echo_level, | |
366 echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] ); | |
367 int right = new_reverb_r + sum3_s + FMUL( chans.echo_level, | |
368 echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] ); | |
369 | |
370 echo_buf [echo_pos] = sum3_s; | |
371 echo_pos = (echo_pos + 1) & echo_mask; | |
372 | |
373 if ( (BOOST::int16_t) left != left ) | |
374 left = 0x7FFF - (left >> 24); | |
375 | |
376 out [0] = left; | |
377 out [1] = right; | |
378 | |
379 out += 2; | |
380 | |
381 if ( (BOOST::int16_t) right != right ) | |
382 out [-1] = 0x7FFF - (right >> 24); | |
383 } | |
384 this->reverb_pos = reverb_pos; | |
385 this->echo_pos = echo_pos; | |
386 | |
387 sq1.end( bufs [0] ); | |
388 sq2.end( bufs [1] ); | |
389 center.end( bufs [2] ); | |
390 } | |
391 | |
392 void Effects_Buffer::mix_enhanced( blip_sample_t* out, long count ) | |
393 { | |
394 Blip_Reader l1; l1.begin( bufs [3] ); | |
395 Blip_Reader r1; r1.begin( bufs [4] ); | |
396 Blip_Reader l2; l2.begin( bufs [5] ); | |
397 Blip_Reader r2; r2.begin( bufs [6] ); | |
398 Blip_Reader sq1; sq1.begin( bufs [0] ); | |
399 Blip_Reader sq2; sq2.begin( bufs [1] ); | |
400 Blip_Reader center; | |
401 int shift = center.begin( bufs [2] ); | |
402 | |
403 int echo_pos = this->echo_pos; | |
404 int reverb_pos = this->reverb_pos; | |
405 | |
406 while ( count-- ) | |
407 { | |
408 int sum1_s = sq1.read(); | |
409 int sum2_s = sq2.read(); | |
410 | |
411 sq1.next( shift ); | |
412 sq2.next( shift ); | |
413 | |
414 int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) + | |
415 FMUL( sum2_s, chans.pan_2_levels [0] ) + l1.read() + | |
416 reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask]; | |
417 | |
418 int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) + | |
419 FMUL( sum2_s, chans.pan_2_levels [1] ) + r1.read() + | |
420 reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask]; | |
421 | |
422 l1.next( shift ); | |
423 r1.next( shift ); | |
424 | |
425 fixed_t reverb_level = chans.reverb_level; | |
426 reverb_buf [reverb_pos] = FMUL( new_reverb_l, reverb_level ); | |
427 reverb_buf [reverb_pos + 1] = FMUL( new_reverb_r, reverb_level ); | |
428 reverb_pos = (reverb_pos + 2) & reverb_mask; | |
429 | |
430 int sum3_s = center.read(); | |
431 center.next( shift ); | |
432 | |
433 int left = new_reverb_l + sum3_s + l2.read() + FMUL( chans.echo_level, | |
434 echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] ); | |
435 int right = new_reverb_r + sum3_s + r2.read() + FMUL( chans.echo_level, | |
436 echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] ); | |
437 | |
438 l2.next( shift ); | |
439 r2.next( shift ); | |
440 | |
441 echo_buf [echo_pos] = sum3_s; | |
442 echo_pos = (echo_pos + 1) & echo_mask; | |
443 | |
444 if ( (BOOST::int16_t) left != left ) | |
445 left = 0x7FFF - (left >> 24); | |
446 | |
447 out [0] = left; | |
448 out [1] = right; | |
449 | |
450 out += 2; | |
451 | |
452 if ( (BOOST::int16_t) right != right ) | |
453 out [-1] = 0x7FFF - (right >> 24); | |
454 } | |
455 this->reverb_pos = reverb_pos; | |
456 this->echo_pos = echo_pos; | |
457 | |
458 sq1.end( bufs [0] ); | |
459 sq2.end( bufs [1] ); | |
460 center.end( bufs [2] ); | |
461 l1.end( bufs [3] ); | |
462 r1.end( bufs [4] ); | |
463 l2.end( bufs [5] ); | |
464 r2.end( bufs [6] ); | |
465 } | |
466 |