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