Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/quicknes/nes_emu/Effects_Buffer.cpp
2 views
1
2
// Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
3
4
#include "Effects_Buffer.h"
5
6
#include <string.h>
7
8
/* Copyright (C) 2003-2006 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.h"
20
21
#ifdef BLARGG_ENABLE_OPTIMIZER
22
#include BLARGG_ENABLE_OPTIMIZER
23
#endif
24
25
typedef long fixed_t;
26
27
#define TO_FIXED( f ) fixed_t ((f) * (1L << 15) + 0.5)
28
#define FMUL( x, y ) (((x) * (y)) >> 15)
29
30
const unsigned echo_size = 4096;
31
const unsigned echo_mask = echo_size - 1;
32
BOOST_STATIC_ASSERT( (echo_size & echo_mask) == 0 ); // must be power of 2
33
34
const unsigned reverb_size = 8192 * 2;
35
const unsigned reverb_mask = reverb_size - 1;
36
BOOST_STATIC_ASSERT( (reverb_size & reverb_mask) == 0 ); // must be power of 2
37
38
Effects_Buffer::config_t::config_t()
39
{
40
pan_1 = -0.15f;
41
pan_2 = 0.15f;
42
reverb_delay = 88.0f;
43
reverb_level = 0.12f;
44
echo_delay = 61.0f;
45
echo_level = 0.10f;
46
delay_variance = 18.0f;
47
effects_enabled = false;
48
}
49
50
void Effects_Buffer::set_depth( double d )
51
{
52
float f = (float) d;
53
config_t c;
54
c.pan_1 = -0.6f * f;
55
c.pan_2 = 0.6f * f;
56
c.reverb_delay = 880 * 0.1f;
57
c.echo_delay = 610 * 0.1f;
58
if ( f > 0.5 )
59
f = 0.5; // TODO: more linear reduction of extreme reverb/echo
60
c.reverb_level = 0.5f * f;
61
c.echo_level = 0.30f * f;
62
c.delay_variance = 180 * 0.1f;
63
c.effects_enabled = (d > 0.0f);
64
config( c );
65
}
66
67
Effects_Buffer::Effects_Buffer( bool center_only ) : Multi_Buffer( 2 )
68
{
69
buf_count = center_only ? max_buf_count - 4 : max_buf_count;
70
71
echo_buf = NULL;
72
echo_pos = 0;
73
74
reverb_buf = NULL;
75
reverb_pos = 0;
76
77
stereo_remain = 0;
78
effect_remain = 0;
79
effects_enabled = false;
80
set_depth( 0 );
81
}
82
83
Effects_Buffer::~Effects_Buffer()
84
{
85
delete [] echo_buf;
86
delete [] reverb_buf;
87
}
88
89
blargg_err_t Effects_Buffer::set_sample_rate( long rate, int msec )
90
{
91
if ( !echo_buf )
92
{
93
echo_buf = BLARGG_NEW blip_sample_t [echo_size];
94
CHECK_ALLOC( echo_buf );
95
}
96
97
if ( !reverb_buf )
98
{
99
reverb_buf = BLARGG_NEW blip_sample_t [reverb_size];
100
CHECK_ALLOC( reverb_buf );
101
}
102
103
for ( int i = 0; i < buf_count; i++ )
104
RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
105
106
config( config_ );
107
clear();
108
109
return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
110
}
111
112
void Effects_Buffer::clock_rate( long rate )
113
{
114
for ( int i = 0; i < buf_count; i++ )
115
bufs [i].clock_rate( rate );
116
}
117
118
void Effects_Buffer::bass_freq( int freq )
119
{
120
for ( int i = 0; i < buf_count; i++ )
121
bufs [i].bass_freq( freq );
122
}
123
124
void Effects_Buffer::clear()
125
{
126
stereo_remain = 0;
127
effect_remain = 0;
128
if ( echo_buf )
129
memset( echo_buf, 0, echo_size * sizeof *echo_buf );
130
if ( reverb_buf )
131
memset( reverb_buf, 0, reverb_size * sizeof *reverb_buf );
132
for ( int i = 0; i < buf_count; i++ )
133
bufs [i].clear();
134
}
135
136
inline int pin_range( int n, int max, int min = 0 )
137
{
138
if ( n < min )
139
return min;
140
if ( n > max )
141
return max;
142
return n;
143
}
144
145
void Effects_Buffer::config( const config_t& cfg )
146
{
147
channels_changed();
148
149
// clear echo and reverb buffers
150
if ( !config_.effects_enabled && cfg.effects_enabled && echo_buf )
151
{
152
memset( echo_buf, 0, echo_size * sizeof (blip_sample_t) );
153
memset( reverb_buf, 0, reverb_size * sizeof (blip_sample_t) );
154
}
155
156
config_ = cfg;
157
158
if ( config_.effects_enabled )
159
{
160
// convert to internal format
161
162
chans.pan_1_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_1 );
163
chans.pan_1_levels [1] = TO_FIXED( 2 ) - chans.pan_1_levels [0];
164
165
chans.pan_2_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_2 );
166
chans.pan_2_levels [1] = TO_FIXED( 2 ) - chans.pan_2_levels [0];
167
168
chans.reverb_level = TO_FIXED( config_.reverb_level );
169
chans.echo_level = TO_FIXED( config_.echo_level );
170
171
int delay_offset = int (1.0 / 2000 * config_.delay_variance * sample_rate());
172
173
int reverb_sample_delay = int (1.0 / 1000 * config_.reverb_delay * sample_rate());
174
chans.reverb_delay_l = pin_range( reverb_size -
175
(reverb_sample_delay - delay_offset) * 2, reverb_size - 2, 0 );
176
chans.reverb_delay_r = pin_range( reverb_size + 1 -
177
(reverb_sample_delay + delay_offset) * 2, reverb_size - 1, 1 );
178
179
int echo_sample_delay = int (1.0 / 1000 * config_.echo_delay * sample_rate());
180
chans.echo_delay_l = pin_range( echo_size - 1 - (echo_sample_delay - delay_offset),
181
echo_size - 1 );
182
chans.echo_delay_r = pin_range( echo_size - 1 - (echo_sample_delay + delay_offset),
183
echo_size - 1 );
184
185
// set up outputs
186
for ( unsigned i = 0; i < chan_count; i++ )
187
{
188
channel_t& o = channels [i];
189
if ( i < 2 )
190
{
191
o.center = &bufs [i];
192
o.left = &bufs [3];
193
o.right = &bufs [4];
194
}
195
else
196
{
197
o.center = &bufs [2];
198
o.left = &bufs [5];
199
o.right = &bufs [6];
200
}
201
}
202
203
}
204
else
205
{
206
// set up outputs
207
for ( unsigned i = 0; i < chan_count; i++ )
208
{
209
channel_t& o = channels [i];
210
o.center = &bufs [0];
211
o.left = &bufs [1];
212
o.right = &bufs [2];
213
}
214
}
215
216
if ( buf_count < max_buf_count )
217
{
218
for ( unsigned i = 0; i < chan_count; i++ )
219
{
220
channel_t& o = channels [i];
221
o.left = o.center;
222
o.right = o.center;
223
}
224
}
225
}
226
227
void Effects_Buffer::end_frame( blip_time_t clock_count, bool stereo )
228
{
229
for ( int i = 0; i < buf_count; i++ )
230
bufs [i].end_frame( clock_count );
231
232
if ( stereo && buf_count == max_buf_count )
233
stereo_remain = bufs [0].samples_avail() + bufs [0].output_latency();
234
235
if ( effects_enabled || config_.effects_enabled )
236
effect_remain = bufs [0].samples_avail() + bufs [0].output_latency();
237
238
effects_enabled = config_.effects_enabled;
239
}
240
241
long Effects_Buffer::samples_avail() const
242
{
243
return bufs [0].samples_avail() * 2;
244
}
245
246
long Effects_Buffer::read_samples( blip_sample_t* out, long total_samples )
247
{
248
require( total_samples % 2 == 0 ); // count must be even
249
250
long remain = bufs [0].samples_avail();
251
if ( remain > (total_samples >> 1) )
252
remain = (total_samples >> 1);
253
total_samples = remain;
254
while ( remain )
255
{
256
int active_bufs = buf_count;
257
long count = remain;
258
259
// optimizing mixing to skip any channels which had nothing added
260
if ( effect_remain )
261
{
262
if ( count > effect_remain )
263
count = effect_remain;
264
265
if ( stereo_remain )
266
{
267
mix_enhanced( out, count );
268
}
269
else
270
{
271
mix_mono_enhanced( out, count );
272
active_bufs = 3;
273
}
274
}
275
else if ( stereo_remain )
276
{
277
mix_stereo( out, count );
278
active_bufs = 3;
279
}
280
else
281
{
282
mix_mono( out, count );
283
active_bufs = 1;
284
}
285
286
out += count * 2;
287
remain -= count;
288
289
stereo_remain -= count;
290
if ( stereo_remain < 0 )
291
stereo_remain = 0;
292
293
effect_remain -= count;
294
if ( effect_remain < 0 )
295
effect_remain = 0;
296
297
for ( int i = 0; i < buf_count; i++ )
298
{
299
if ( i < active_bufs )
300
bufs [i].remove_samples( count );
301
else
302
bufs [i].remove_silence( count ); // keep time synchronized
303
}
304
}
305
306
return total_samples * 2;
307
}
308
309
void Effects_Buffer::mix_mono( blip_sample_t* out, long count )
310
{
311
Blip_Reader c;
312
int shift = c.begin( bufs [0] );
313
314
// unrolled loop
315
for ( long n = count >> 1; n--; )
316
{
317
long cs0 = c.read();
318
c.next( shift );
319
320
long cs1 = c.read();
321
c.next( shift );
322
323
if ( (BOOST::int16_t) cs0 != cs0 )
324
cs0 = 0x7FFF - (cs0 >> 24);
325
((BOOST::uint32_t*) out) [0] = ((BOOST::uint16_t) cs0) | (cs0 << 16);
326
327
if ( (BOOST::int16_t) cs1 != cs1 )
328
cs1 = 0x7FFF - (cs1 >> 24);
329
((BOOST::uint32_t*) out) [1] = ((BOOST::uint16_t) cs1) | (cs1 << 16);
330
out += 4;
331
}
332
333
if ( count & 1 )
334
{
335
int s = c.read();
336
c.next( shift );
337
out [0] = s;
338
out [1] = s;
339
if ( (BOOST::int16_t) s != s )
340
{
341
s = 0x7FFF - (s >> 24);
342
out [0] = s;
343
out [1] = s;
344
}
345
}
346
347
c.end( bufs [0] );
348
}
349
350
void Effects_Buffer::mix_stereo( blip_sample_t* out, long count )
351
{
352
Blip_Reader l; l.begin( bufs [1] );
353
Blip_Reader r; r.begin( bufs [2] );
354
Blip_Reader c;
355
int shift = c.begin( bufs [0] );
356
357
while ( count-- )
358
{
359
int cs = c.read();
360
c.next( shift );
361
int left = cs + l.read();
362
int right = cs + r.read();
363
l.next( shift );
364
r.next( shift );
365
366
if ( (BOOST::int16_t) left != left )
367
left = 0x7FFF - (left >> 24);
368
369
out [0] = left;
370
out [1] = right;
371
372
out += 2;
373
374
if ( (BOOST::int16_t) right != right )
375
out [-1] = 0x7FFF - (right >> 24);
376
}
377
378
c.end( bufs [0] );
379
r.end( bufs [2] );
380
l.end( bufs [1] );
381
}
382
383
void Effects_Buffer::mix_mono_enhanced( blip_sample_t* out, long count )
384
{
385
Blip_Reader sq1; sq1.begin( bufs [0] );
386
Blip_Reader sq2; sq2.begin( bufs [1] );
387
Blip_Reader center;
388
int shift = center.begin( bufs [2] );
389
390
int echo_pos = this->echo_pos;
391
int reverb_pos = this->reverb_pos;
392
393
while ( count-- )
394
{
395
int sum1_s = sq1.read();
396
int sum2_s = sq2.read();
397
398
sq1.next( shift );
399
sq2.next( shift );
400
401
int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) +
402
FMUL( sum2_s, chans.pan_2_levels [0] ) +
403
reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask];
404
405
int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) +
406
FMUL( sum2_s, chans.pan_2_levels [1] ) +
407
reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask];
408
409
fixed_t reverb_level = chans.reverb_level;
410
reverb_buf [reverb_pos] = FMUL( new_reverb_l, reverb_level );
411
reverb_buf [reverb_pos + 1] = FMUL( new_reverb_r, reverb_level );
412
reverb_pos = (reverb_pos + 2) & reverb_mask;
413
414
int sum3_s = center.read();
415
center.next( shift );
416
417
int left = new_reverb_l + sum3_s + FMUL( chans.echo_level,
418
echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] );
419
int right = new_reverb_r + sum3_s + FMUL( chans.echo_level,
420
echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] );
421
422
echo_buf [echo_pos] = sum3_s;
423
echo_pos = (echo_pos + 1) & echo_mask;
424
425
if ( (BOOST::int16_t) left != left )
426
left = 0x7FFF - (left >> 24);
427
428
out [0] = left;
429
out [1] = right;
430
431
out += 2;
432
433
if ( (BOOST::int16_t) right != right )
434
out [-1] = 0x7FFF - (right >> 24);
435
}
436
this->reverb_pos = reverb_pos;
437
this->echo_pos = echo_pos;
438
439
sq1.end( bufs [0] );
440
sq2.end( bufs [1] );
441
center.end( bufs [2] );
442
}
443
444
void Effects_Buffer::mix_enhanced( blip_sample_t* out, long count )
445
{
446
Blip_Reader l1; l1.begin( bufs [3] );
447
Blip_Reader r1; r1.begin( bufs [4] );
448
Blip_Reader l2; l2.begin( bufs [5] );
449
Blip_Reader r2; r2.begin( bufs [6] );
450
Blip_Reader sq1; sq1.begin( bufs [0] );
451
Blip_Reader sq2; sq2.begin( bufs [1] );
452
Blip_Reader center;
453
int shift = center.begin( bufs [2] );
454
455
int echo_pos = this->echo_pos;
456
int reverb_pos = this->reverb_pos;
457
458
while ( count-- )
459
{
460
int sum1_s = sq1.read();
461
int sum2_s = sq2.read();
462
463
sq1.next( shift );
464
sq2.next( shift );
465
466
int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) +
467
FMUL( sum2_s, chans.pan_2_levels [0] ) + l1.read() +
468
reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask];
469
470
int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) +
471
FMUL( sum2_s, chans.pan_2_levels [1] ) + r1.read() +
472
reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask];
473
474
l1.next( shift );
475
r1.next( shift );
476
477
fixed_t reverb_level = chans.reverb_level;
478
reverb_buf [reverb_pos] = FMUL( new_reverb_l, reverb_level );
479
reverb_buf [reverb_pos + 1] = FMUL( new_reverb_r, reverb_level );
480
reverb_pos = (reverb_pos + 2) & reverb_mask;
481
482
int sum3_s = center.read();
483
center.next( shift );
484
485
int left = new_reverb_l + sum3_s + l2.read() + FMUL( chans.echo_level,
486
echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] );
487
int right = new_reverb_r + sum3_s + r2.read() + FMUL( chans.echo_level,
488
echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] );
489
490
l2.next( shift );
491
r2.next( shift );
492
493
echo_buf [echo_pos] = sum3_s;
494
echo_pos = (echo_pos + 1) & echo_mask;
495
496
if ( (BOOST::int16_t) left != left )
497
left = 0x7FFF - (left >> 24);
498
499
out [0] = left;
500
out [1] = right;
501
502
out += 2;
503
504
if ( (BOOST::int16_t) right != right )
505
out [-1] = 0x7FFF - (right >> 24);
506
}
507
this->reverb_pos = reverb_pos;
508
this->echo_pos = echo_pos;
509
510
sq1.end( bufs [0] );
511
sq2.end( bufs [1] );
512
center.end( bufs [2] );
513
l1.end( bufs [3] );
514
r1.end( bufs [4] );
515
l2.end( bufs [5] );
516
r2.end( bufs [6] );
517
}
518
519
520