Browse code

[GSF] Some more code cleanup, also removed a few files that were unneeded.

Naram Qashat authored on 2013/05/16 01:25:34
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,609 +0,0 @@
1
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
2
-
3
-#include "Effects_Buffer.h"
4
-
5
-#include <cmath>
6
-#include <cstring>
7
-
8
-/* Copyright (C) 2006-2007 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 more
15
-details. You should have received a copy of the GNU Lesser General Public
16
-License along with this module; if not, write to the Free Software Foundation,
17
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18
-
19
-#include "blargg_source.h"
20
-
21
-static const int fixed_shift = 12;
22
-template<typename T> static inline Effects_Buffer::fixed_t TO_FIXED(const T &f) { return static_cast<Effects_Buffer::fixed_t>(f * (static_cast<Effects_Buffer::fixed_t>(1) << fixed_shift)); }
23
-static inline Effects_Buffer::fixed_t FROM_FIXED(Effects_Buffer::fixed_t f) { return f >> fixed_shift; }
24
-
25
-static const int max_read = 2560; // determines minimum delay
26
-
27
-Effects_Buffer::Effects_Buffer(int max_bufs, long echo_size_) : Multi_Buffer(stereo)
28
-{
29
-	this->echo_size = std::max<long>(max_read * stereo, echo_size_ & ~1);
30
-	this->clock_rate_ = 0;
31
-	this->bass_freq_ = 90;
32
-	this->bufs.clear();
33
-	this->bufs_size = 0;
34
-	this->bufs_max = std::max<int>(max_bufs, extra_chans);
35
-	this->no_echo = this->no_effects  = true;
36
-
37
-	// defaults
38
-	this->config_.enabled = false;
39
-	this->config_.delay[0] = 120;
40
-	this->config_.delay[1] = 122;
41
-	this->config_.feedback = 0.2f;
42
-	this->config_.treble = 0.4f;
43
-
44
-	static const float sep = 0.8f;
45
-	this->config_.side_chans[0].pan = -sep;
46
-	this->config_.side_chans[1].pan = sep;
47
-	this->config_.side_chans[0].vol = this->config_.side_chans[1].vol = 1.0f;
48
-
49
-	memset(&this->s, 0, sizeof(this->s));
50
-	this->clear();
51
-}
52
-
53
-Effects_Buffer::~Effects_Buffer()
54
-{
55
-	this->delete_bufs();
56
-}
57
-
58
-// avoid using new []
59
-blargg_err_t Effects_Buffer::new_bufs(int size)
60
-{
61
-	this->delete_bufs();
62
-	this->bufs.resize(size);
63
-	for (int i = 0; i < size; ++i)
64
-		this->bufs[i].reset(new buf_t);
65
-	this->bufs_size = size;
66
-	return 0;
67
-}
68
-
69
-void Effects_Buffer::delete_bufs()
70
-{
71
-	this->bufs.clear();
72
-	this->bufs_size = 0;
73
-}
74
-
75
-blargg_err_t Effects_Buffer::set_sample_rate(long rate, int msec)
76
-{
77
-	// extra to allow farther past-the-end pointers
78
-	this->mixer.samples_read = 0;
79
-	this->echo.resize(echo_size + stereo);
80
-	return Multi_Buffer::set_sample_rate(rate, msec);
81
-}
82
-
83
-void Effects_Buffer::clock_rate(long rate)
84
-{
85
-	this->clock_rate_ = rate;
86
-	for (int i = this->bufs_size; --i >= 0; )
87
-		this->bufs[i]->clock_rate(this->clock_rate_);
88
-}
89
-
90
-void Effects_Buffer::bass_freq(int freq)
91
-{
92
-	this->bass_freq_ = freq;
93
-	for (int i = this->bufs_size; --i >= 0; )
94
-		this->bufs[i]->bass_freq(this->bass_freq_);
95
-}
96
-
97
-blargg_err_t Effects_Buffer::set_channel_count(int count, const int *types)
98
-{
99
-	Multi_Buffer::set_channel_count(count, types);
100
-
101
-	this->delete_bufs();
102
-
103
-	this->mixer.samples_read = 0;
104
-
105
-	this->chans.resize(count + extra_chans);
106
-
107
-	this->new_bufs(std::min(this->bufs_max, count + extra_chans));
108
-
109
-	for (int i = this->bufs_size; --i >= 0; )
110
-		RETURN_ERR(this->bufs[i]->set_sample_rate(this->sample_rate(), this->length()));
111
-
112
-	for (int i = this->chans.size(); --i >= 0; )
113
-	{
114
-		auto &ch = this->chans[i];
115
-		ch.cfg.vol = 1.0f;
116
-		ch.cfg.pan = 0.0f;
117
-		ch.cfg.surround = ch.cfg.echo = false;
118
-	}
119
-	// side channels with echo
120
-	this->chans[2].cfg.echo = this->chans[3].cfg.echo = true;
121
-
122
-	this->clock_rate(this->clock_rate_);
123
-	this->bass_freq(this->bass_freq_);
124
-	this->apply_config();
125
-	this->clear();
126
-
127
-	return 0;
128
-}
129
-
130
-void Effects_Buffer::clear_echo()
131
-{
132
-	if (!this->echo.empty())
133
-		memset(&this->echo[0], 0, this->echo.size() * sizeof(echo[0]));
134
-}
135
-
136
-void Effects_Buffer::clear()
137
-{
138
-	this->echo_pos = 0;
139
-	this->s.low_pass[0] = this->s.low_pass[1] = 0;
140
-	this->mixer.samples_read = 0;
141
-
142
-	for (int i = this->bufs_size; --i >= 0; )
143
-		this->bufs[i]->clear();
144
-	this->clear_echo();
145
-}
146
-
147
-auto Effects_Buffer::channel(int i) -> channel_t
148
-{
149
-	i += extra_chans;
150
-	assert(extra_chans <= i && i < static_cast<int>(this->chans.size()));
151
-	return this->chans[i].channel;
152
-}
153
-
154
-// Configuration
155
-
156
-// 3 wave positions with/without surround, 2 multi (one with same config as wave)
157
-static const int simple_bufs = 3 * 2 + 2 - 1;
158
-
159
-Simple_Effects_Buffer::Simple_Effects_Buffer() : Effects_Buffer(extra_chans + simple_bufs, 18 * 1024L)
160
-{
161
-	this->config_.echo = 0.20f;
162
-	this->config_.stereo = 0.20f;
163
-	this->config_.surround = true;
164
-	this->config_.enabled = false;
165
-}
166
-
167
-void Simple_Effects_Buffer::apply_config()
168
-{
169
-	auto &c = Effects_Buffer::config();
170
-
171
-	c.enabled = this->config_.enabled;
172
-	if (c.enabled)
173
-	{
174
-		c.delay[0] = 120;
175
-		c.delay[1] = 122;
176
-		c.feedback = this->config_.echo * 0.7f;
177
-		c.treble = 0.6f - 0.3f * this->config_.echo;
178
-
179
-		float sep = this->config_.stereo + 0.80f;
180
-		if (sep > 1.0f)
181
-			sep = 1.0f;
182
-
183
-		c.side_chans[0].pan = -sep;
184
-		c.side_chans[1].pan = sep;
185
-
186
-		for (int i = this->channel_count(); --i >= 0; )
187
-		{
188
-			auto &ch = Effects_Buffer::chan_config(i);
189
-
190
-			ch.pan = 0.0f;
191
-			ch.surround = this->config_.surround;
192
-			ch.echo = false;
193
-
194
-			int type = this->channel_types() ? this->channel_types()[i] : 0;
195
-			if (!(type & noise_type))
196
-			{
197
-				int index = (type & type_index_mask) % 6 - 3;
198
-				if (index < 0)
199
-				{
200
-					index += 3;
201
-					ch.surround = false;
202
-					ch.echo = true;
203
-				}
204
-				if (index >= 1)
205
-				{
206
-					ch.pan = this->config_.stereo;
207
-					if (index == 1)
208
-						ch.pan = -ch.pan;
209
-				}
210
-			}
211
-			else if (type & 1)
212
-				ch.surround = false;
213
-		}
214
-	}
215
-
216
-	Effects_Buffer::apply_config();
217
-}
218
-
219
-int Effects_Buffer::min_delay() const
220
-{
221
-	assert(this->sample_rate());
222
-	return max_read * 1000L / this->sample_rate();
223
-}
224
-
225
-int Effects_Buffer::max_delay() const
226
-{
227
-	assert(this->sample_rate());
228
-	return (this->echo_size / stereo - max_read) * 1000L / this->sample_rate();
229
-}
230
-
231
-void Effects_Buffer::apply_config()
232
-{
233
-	if (!this->bufs_size)
234
-		return;
235
-
236
-	this->s.treble = TO_FIXED(this->config_.treble);
237
-
238
-	bool echo_dirty = false;
239
-
240
-	fixed_t old_feedback = this->s.feedback;
241
-	this->s.feedback = TO_FIXED(this->config_.feedback);
242
-	if (!old_feedback && this->s.feedback)
243
-		echo_dirty = true;
244
-
245
-	// delays
246
-	int i;
247
-	for (i = stereo; --i >= 0;)
248
-	{
249
-		long delay = this->config_.delay[i] * this->sample_rate() / 1000 * stereo;
250
-		delay = std::max<long>(delay, max_read * stereo);
251
-		delay = std::min<long>(delay, this->echo_size - max_read * stereo);
252
-		if (this->s.delay[i] != delay)
253
-		{
254
-			this->s.delay[i] = delay;
255
-			echo_dirty = true;
256
-		}
257
-	}
258
-
259
-	// side channels
260
-	for (i = 2; --i >= 0; )
261
-	{
262
-		this->chans[i + 2].cfg.vol = this->chans[i].cfg.vol = this->config_.side_chans[i].vol * 0.5f;
263
-		this->chans[i + 2].cfg.pan = this->chans[i].cfg.pan = this->config_.side_chans[i].pan;
264
-	}
265
-
266
-	// convert volumes
267
-	for (i = this->chans.size(); --i >= 0; )
268
-	{
269
-		auto &ch = this->chans[i];
270
-		ch.vol[0] = TO_FIXED(ch.cfg.vol - ch.cfg.vol * ch.cfg.pan);
271
-		ch.vol[1] = TO_FIXED(ch.cfg.vol + ch.cfg.vol * ch.cfg.pan);
272
-		if (ch.cfg.surround)
273
-			ch.vol[0] = -ch.vol [0];
274
-	}
275
-
276
-	this->assign_buffers();
277
-
278
-	// set side channels
279
-	for (i = this->chans.size(); --i >= 0; )
280
-	{
281
-		auto &ch = chans[i];
282
-		ch.channel.left = this->chans[ch.cfg.echo * 2].channel.center;
283
-		ch.channel.right = this->chans[ch.cfg.echo * 2 + 1].channel.center;
284
-	}
285
-
286
-	bool old_echo = !this->no_echo && !this->no_effects;
287
-
288
-	// determine whether effects and echo are needed at all
289
-	this->no_effects = this->no_echo = true;
290
-	for (i = this->chans.size(); --i >= extra_chans; )
291
-	{
292
-		auto &ch = this->chans[i];
293
-		if (ch.cfg.echo && this->s.feedback)
294
-			this->no_echo = false;
295
-
296
-		if (ch.vol[0] != TO_FIXED(1) || ch.vol[1] != TO_FIXED(1))
297
-			this->no_effects = false;
298
-	}
299
-	if (!this->no_echo)
300
-		this->no_effects = false;
301
-
302
-	if (this->chans[0].vol[0] != TO_FIXED(1) || this->chans[0].vol[1] != TO_FIXED(0) || this->chans[1].vol[0] != TO_FIXED(0) || this->chans[1].vol[1] != TO_FIXED(1))
303
-		this->no_effects = false;
304
-
305
-	if (!this->config_.enabled)
306
-		this->no_effects = true;
307
-
308
-	if (this->no_effects)
309
-	{
310
-		for (i = this->chans.size(); --i >= 0; )
311
-		{
312
-			auto &ch = this->chans[i];
313
-			ch.channel.center = this->bufs[2].get();
314
-			ch.channel.left = this->bufs[0].get();
315
-			ch.channel.right = this->bufs[1].get();
316
-		}
317
-	}
318
-
319
-	this->mixer.bufs[0] = this->bufs[0].get();
320
-	this->mixer.bufs[1] = this->bufs[1].get();
321
-	this->mixer.bufs[2] = this->bufs[2].get();
322
-
323
-	if (echo_dirty || (!old_echo && (!this->no_echo && !this->no_effects)))
324
-		this->clear_echo();
325
-
326
-	this->channels_changed();
327
-}
328
-
329
-void Effects_Buffer::assign_buffers()
330
-{
331
-	// assign channels to buffers
332
-	int buf_count = 0;
333
-	for (int i = 0; i < static_cast<int>(this->chans.size()); ++i)
334
-	{
335
-		// put second two side channels at end to give priority to main channels
336
-		// in case closest matching is necessary
337
-		int x = i;
338
-		if (i > 1)
339
-			x += 2;
340
-		if (x >= static_cast<int>(this->chans.size()))
341
-			x -= this->chans.size() - 2;
342
-		auto &ch = this->chans[x];
343
-
344
-		int b = 0;
345
-		for (; b < buf_count; ++b)
346
-		{
347
-			if (ch.vol[0] == this->bufs[b]->vol[0] && ch.vol[1] == this->bufs[b]->vol[1] && (ch.cfg.echo == this->bufs[b]->echo || !this->s.feedback))
348
-				break;
349
-		}
350
-
351
-		if (b >= buf_count)
352
-		{
353
-			if (buf_count < this->bufs_max)
354
-			{
355
-				this->bufs[b]->vol[0] = ch.vol[0];
356
-				this->bufs[b]->vol[1] = ch.vol[1];
357
-				this->bufs[b]->echo = ch.cfg.echo;
358
-				++buf_count;
359
-			}
360
-			else
361
-			{
362
-				// TODO: this is a mess, needs refinement
363
-				b = 0;
364
-				fixed_t best_dist = TO_FIXED(8);
365
-				for (int h = buf_count; --h >= 0; )
366
-				{
367
-					auto CALC_LEVELS = [&](fixed_t vols[], fixed_t &sum, fixed_t &diff, bool &surround)
368
-					{
369
-						fixed_t vol_0 = vols[0];
370
-						if (vol_0 < 0)
371
-						{
372
-							vol_0 = -vol_0;
373
-							surround = true;
374
-						}
375
-						fixed_t vol_1 = vols[1];
376
-						if (vol_1 < 0)
377
-						{
378
-							vol_1 = -vol_1;
379
-							surround = true;
380
-						}
381
-						sum = vol_0 + vol_1;
382
-						diff = vol_0 - vol_1;
383
-					};
384
-					fixed_t ch_sum, ch_diff, buf_sum, buf_diff;
385
-					bool ch_surround, buf_surround;
386
-					CALC_LEVELS(ch.vol, ch_sum, ch_diff, ch_surround);
387
-					CALC_LEVELS(this->bufs[h]->vol, buf_sum, buf_diff, buf_surround);
388
-
389
-					fixed_t dist = std::abs(ch_sum - buf_sum) + std::abs(ch_diff - buf_diff);
390
-
391
-					if (ch_surround != buf_surround)
392
-						dist += TO_FIXED(1) / 2;
393
-
394
-					if (this->s.feedback && ch.cfg.echo != this->bufs[h]->echo)
395
-						dist += TO_FIXED(1) / 2;
396
-
397
-					if (best_dist > dist)
398
-					{
399
-						best_dist = dist;
400
-						b = h;
401
-					}
402
-				}
403
-			}
404
-		}
405
-
406
-		ch.channel.center = this->bufs[b].get();
407
-	}
408
-}
409
-
410
-// Mixing
411
-
412
-void Effects_Buffer::end_frame(blip_time_t time)
413
-{
414
-	for (int i = bufs_size; --i >= 0; )
415
-		this->bufs[i]->end_frame(time);
416
-}
417
-
418
-long Effects_Buffer::read_samples(blip_sample_t *out, long out_size)
419
-{
420
-	out_size = std::min(out_size, this->samples_avail());
421
-
422
-	int pair_count = static_cast<int>(out_size >> 1);
423
-	assert(pair_count * stereo == out_size); // must read an even number of samples
424
-	if (pair_count)
425
-	{
426
-		if (this->no_effects)
427
-			this->mixer.read_pairs(out, pair_count);
428
-		else
429
-		{
430
-			int pairs_remain = pair_count;
431
-			do
432
-			{
433
-				// mix at most max_read pairs at a time
434
-				int count = max_read;
435
-				if (count > pairs_remain)
436
-					count = pairs_remain;
437
-
438
-				if (this->no_echo)
439
-				{
440
-					// optimization: clear echo here to keep mix_effects() a leaf function
441
-					this->echo_pos = 0;
442
-					memset(&this->echo[0], 0, count * stereo * sizeof(this->echo[0]));
443
-				}
444
-				this->mix_effects(out, count);
445
-
446
-				int32_t new_echo_pos = this->echo_pos + count * stereo;
447
-				if (new_echo_pos >= this->echo_size)
448
-					new_echo_pos -= this->echo_size;
449
-				this->echo_pos = new_echo_pos;
450
-				assert(this->echo_pos < this->echo_size);
451
-
452
-				out += count * stereo;
453
-				this->mixer.samples_read += count;
454
-				pairs_remain -= count;
455
-			} while (pairs_remain);
456
-		}
457
-
458
-		if (this->samples_avail() <= 0 || this->immediate_removal())
459
-		{
460
-			for (int i = this->bufs_size; --i >= 0; )
461
-			{
462
-				auto &b = this->bufs[i];
463
-				// TODO: might miss non-silence settling since it checks END of last read
464
-				if (b->non_silent())
465
-					b->remove_samples(this->mixer.samples_read);
466
-				else
467
-					b->remove_silence(this->mixer.samples_read);
468
-			}
469
-			this->mixer.samples_read = 0;
470
-		}
471
-	}
472
-	return out_size;
473
-}
474
-
475
-void Effects_Buffer::mix_effects(blip_sample_t *out_, int pair_count)
476
-{
477
-	typedef fixed_t stereo_fixed_t[stereo];
478
-
479
-	// add channels with echo, do echo, add channels without echo, then convert to 16-bit and output
480
-	int echo_phase = 1;
481
-	do
482
-	{
483
-		// mix any modified buffers
484
-		{
485
-			size_t bufNum = 0;
486
-			int bufs_remain = this->bufs_size;
487
-			do
488
-			{
489
-				auto &buf = this->bufs[bufNum++];
490
-				if (buf->non_silent() && (buf->echo == !!echo_phase))
491
-				{
492
-					auto out = reinterpret_cast<stereo_fixed_t *>(&this->echo[this->echo_pos]);
493
-					int bass = BLIP_READER_BASS(*buf);
494
-					BLIP_READER_BEGIN(in, *buf);
495
-					BLIP_READER_ADJ_(in, this->mixer.samples_read);
496
-					fixed_t vol_0 = buf->vol[0];
497
-					fixed_t vol_1 = buf->vol[1];
498
-
499
-					int count = static_cast<unsigned>(echo_size - echo_pos) / stereo;
500
-					int remain = pair_count;
501
-					if (count > remain)
502
-						count = remain;
503
-					do
504
-					{
505
-						remain -= count;
506
-						BLIP_READER_ADJ_(in, count);
507
-
508
-						out += count;
509
-						int offset = -count;
510
-						do
511
-						{
512
-							fixed_t s = BLIP_READER_READ(in);
513
-							BLIP_READER_NEXT_IDX_(in, bass, offset);
514
-
515
-							out[offset][0] += s * vol_0;
516
-							out[offset][1] += s * vol_1;
517
-						} while ( ++offset );
518
-
519
-						out = reinterpret_cast<stereo_fixed_t *>(&this->echo[0]);
520
-						count = remain;
521
-					} while (remain);
522
-
523
-					BLIP_READER_END(in, *buf);
524
-				}
525
-			} while (--bufs_remain);
526
-		}
527
-
528
-		// add echo
529
-		if (echo_phase && !this->no_echo)
530
-		{
531
-			fixed_t feedback = this->s.feedback;
532
-			fixed_t treble = this->s.treble;
533
-
534
-			int i = 1;
535
-			do
536
-			{
537
-				fixed_t low_pass = this->s.low_pass[i];
538
-
539
-				auto echo_end = &this->echo[this->echo_size + i];
540
-				auto in_pos = &this->echo[this->echo_pos + i];
541
-				int32_t out_offset = this->echo_pos + i + this->s.delay[i];
542
-				if (out_offset >= this->echo_size)
543
-					out_offset -= this->echo_size;
544
-				assert(out_offset < this->echo_size);
545
-				auto out_pos = &this->echo[out_offset];
546
-
547
-				// break into up to three chunks to avoid having to handle wrap-around
548
-				// in middle of core loop
549
-				int remain = pair_count;
550
-				do
551
-				{
552
-					auto pos = in_pos;
553
-					if (pos < out_pos)
554
-						pos = out_pos;
555
-					int count = static_cast<uint32_t>(reinterpret_cast<char *>(echo_end) - reinterpret_cast<const char *>(pos)) / (stereo * sizeof(fixed_t));
556
-					if (count > remain)
557
-						count = remain;
558
-					remain -= count;
559
-
560
-					in_pos += count * stereo;
561
-					out_pos += count * stereo;
562
-					int offset = -count;
563
-					do
564
-					{
565
-						low_pass += FROM_FIXED(in_pos[offset * stereo] - low_pass) * treble;
566
-						out_pos[offset * stereo] = FROM_FIXED(low_pass) * feedback;
567
-					} while (++offset);
568
-
569
-					if (in_pos >= echo_end)
570
-						in_pos -= echo_size;
571
-					if (out_pos >= echo_end)
572
-						out_pos -= echo_size;
573
-				} while (remain);
574
-
575
-				this->s.low_pass [i] = low_pass;
576
-			} while (--i >= 0);
577
-		}
578
-	} while (--echo_phase >= 0);
579
-
580
-	// clamp to 16 bits
581
-	auto in = reinterpret_cast<stereo_fixed_t *>(&this->echo[this->echo_pos]);
582
-	typedef blip_sample_t stereo_blip_sample_t[stereo];
583
-	auto out = reinterpret_cast<stereo_blip_sample_t *>(out_);
584
-	int count = static_cast<unsigned>(this->echo_size - this->echo_pos) / stereo;
585
-	int remain = pair_count;
586
-	if (count > remain)
587
-		count = remain;
588
-	do
589
-	{
590
-		remain -= count;
591
-		in  += count;
592
-		out += count;
593
-		int offset = -count;
594
-		do
595
-		{
596
-			fixed_t in_0 = FROM_FIXED(in[offset][0]);
597
-			fixed_t in_1 = FROM_FIXED(in[offset][1]);
598
-
599
-			BLIP_CLAMP(in_0, in_0);
600
-			out[offset][0] = static_cast<blip_sample_t>(in_0);
601
-
602
-			BLIP_CLAMP(in_1, in_1);
603
-			out[offset][1] = static_cast<blip_sample_t>(in_1);
604
-		} while (++offset);
605
-
606
-		in = reinterpret_cast<stereo_fixed_t *>(&this->echo[0]);
607
-		count = remain;
608
-	} while (remain);
609
-}
Browse code

[GSF] Massive code cleanup.

(As an aside, blargg's code style makes me go blarg myself.)

Naram Qashat authored on 2013/05/14 01:07:18
Showing 1 changed files
... ...
@@ -2,7 +2,8 @@
2 2
 
3 3
 #include "Effects_Buffer.h"
4 4
 
5
-#include <string.h>
5
+#include <cmath>
6
+#include <cstring>
6 7
 
7 8
 /* Copyright (C) 2006-2007 Shay Green. This module is free software; you
8 9
 can redistribute it and/or modify it under the terms of the GNU Lesser
... ...
@@ -17,213 +18,198 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
17 18
 
18 19
 #include "blargg_source.h"
19 20
 
20
-int const fixed_shift = 12;
21
-#define TO_FIXED( f )   fixed_t ((f) * ((fixed_t) 1 << fixed_shift))
22
-#define FROM_FIXED( f ) ((f) >> fixed_shift)
21
+static const int fixed_shift = 12;
22
+template<typename T> static inline Effects_Buffer::fixed_t TO_FIXED(const T &f) { return static_cast<Effects_Buffer::fixed_t>(f * (static_cast<Effects_Buffer::fixed_t>(1) << fixed_shift)); }
23
+static inline Effects_Buffer::fixed_t FROM_FIXED(Effects_Buffer::fixed_t f) { return f >> fixed_shift; }
23 24
 
24
-int const max_read = 2560; // determines minimum delay
25
+static const int max_read = 2560; // determines minimum delay
25 26
 
26
-Effects_Buffer::Effects_Buffer( int max_bufs, long echo_size_ ) : Multi_Buffer( stereo )
27
+Effects_Buffer::Effects_Buffer(int max_bufs, long echo_size_) : Multi_Buffer(stereo)
27 28
 {
28
-	echo_size   = max( max_read * (long) stereo, echo_size_ & ~1 );
29
-	clock_rate_ = 0;
30
-	bass_freq_  = 90;
31
-	bufs        = 0;
32
-	bufs_size   = 0;
33
-	bufs_max    = max( max_bufs, (int) extra_chans );
34
-	no_echo     = true;
35
-	no_effects  = true;
29
+	this->echo_size = std::max<long>(max_read * stereo, echo_size_ & ~1);
30
+	this->clock_rate_ = 0;
31
+	this->bass_freq_ = 90;
32
+	this->bufs.clear();
33
+	this->bufs_size = 0;
34
+	this->bufs_max = std::max<int>(max_bufs, extra_chans);
35
+	this->no_echo = this->no_effects  = true;
36 36
 
37 37
 	// defaults
38
-	config_.enabled   = false;
39
-	config_.delay [0] = 120;
40
-	config_.delay [1] = 122;
41
-	config_.feedback  = 0.2f;
42
-	config_.treble    = 0.4f;
43
-
44
-	static float const sep = 0.8f;
45
-	config_.side_chans [0].pan = -sep;
46
-	config_.side_chans [1].pan = +sep;
47
-	config_.side_chans [0].vol = 1.0f;
48
-	config_.side_chans [1].vol = 1.0f;
49
-
50
-	memset( &s, 0, sizeof s );
51
-	clear();
38
+	this->config_.enabled = false;
39
+	this->config_.delay[0] = 120;
40
+	this->config_.delay[1] = 122;
41
+	this->config_.feedback = 0.2f;
42
+	this->config_.treble = 0.4f;
43
+
44
+	static const float sep = 0.8f;
45
+	this->config_.side_chans[0].pan = -sep;
46
+	this->config_.side_chans[1].pan = sep;
47
+	this->config_.side_chans[0].vol = this->config_.side_chans[1].vol = 1.0f;
48
+
49
+	memset(&this->s, 0, sizeof(this->s));
50
+	this->clear();
52 51
 }
53 52
 
54 53
 Effects_Buffer::~Effects_Buffer()
55 54
 {
56
-	delete_bufs();
55
+	this->delete_bufs();
57 56
 }
58 57
 
59 58
 // avoid using new []
60
-blargg_err_t Effects_Buffer::new_bufs( int size )
59
+blargg_err_t Effects_Buffer::new_bufs(int size)
61 60
 {
62
-	bufs = (buf_t*) malloc( size * sizeof *bufs );
63
-	CHECK_ALLOC( bufs );
64
-	for ( int i = 0; i < size; i++ )
65
-		new (bufs + i) buf_t;
66
-	bufs_size = size;
61
+	this->delete_bufs();
62
+	this->bufs.resize(size);
63
+	for (int i = 0; i < size; ++i)
64
+		this->bufs[i].reset(new buf_t);
65
+	this->bufs_size = size;
67 66
 	return 0;
68 67
 }
69 68
 
70 69
 void Effects_Buffer::delete_bufs()
71 70
 {
72
-	if ( bufs )
73
-	{
74
-		for ( int i = bufs_size; --i >= 0; )
75
-			bufs [i].~buf_t();
76
-		free( bufs );
77
-		bufs = 0;
78
-	}
79
-	bufs_size = 0;
71
+	this->bufs.clear();
72
+	this->bufs_size = 0;
80 73
 }
81 74
 
82
-blargg_err_t Effects_Buffer::set_sample_rate( long rate, int msec )
75
+blargg_err_t Effects_Buffer::set_sample_rate(long rate, int msec)
83 76
 {
84 77
 	// extra to allow farther past-the-end pointers
85
-	mixer.samples_read = 0;
86
-	RETURN_ERR( echo.resize( echo_size + stereo ) );
87
-	return Multi_Buffer::set_sample_rate( rate, msec );
78
+	this->mixer.samples_read = 0;
79
+	this->echo.resize(echo_size + stereo);
80
+	return Multi_Buffer::set_sample_rate(rate, msec);
88 81
 }
89 82
 
90
-void Effects_Buffer::clock_rate( long rate )
83
+void Effects_Buffer::clock_rate(long rate)
91 84
 {
92
-	clock_rate_ = rate;
93
-	for ( int i = bufs_size; --i >= 0; )
94
-		bufs [i].clock_rate( clock_rate_ );
85
+	this->clock_rate_ = rate;
86
+	for (int i = this->bufs_size; --i >= 0; )
87
+		this->bufs[i]->clock_rate(this->clock_rate_);
95 88
 }
96 89
 
97
-void Effects_Buffer::bass_freq( int freq )
90
+void Effects_Buffer::bass_freq(int freq)
98 91
 {
99
-	bass_freq_ = freq;
100
-	for ( int i = bufs_size; --i >= 0; )
101
-		bufs [i].bass_freq( bass_freq_ );
92
+	this->bass_freq_ = freq;
93
+	for (int i = this->bufs_size; --i >= 0; )
94
+		this->bufs[i]->bass_freq(this->bass_freq_);
102 95
 }
103 96
 
104
-blargg_err_t Effects_Buffer::set_channel_count( int count, int const* types )
97
+blargg_err_t Effects_Buffer::set_channel_count(int count, const int *types)
105 98
 {
106
-	RETURN_ERR( Multi_Buffer::set_channel_count( count, types ) );
99
+	Multi_Buffer::set_channel_count(count, types);
107 100
 
108
-	delete_bufs();
101
+	this->delete_bufs();
109 102
 
110
-	mixer.samples_read = 0;
103
+	this->mixer.samples_read = 0;
111 104
 
112
-	RETURN_ERR( chans.resize( count + extra_chans ) );
105
+	this->chans.resize(count + extra_chans);
113 106
 
114
-	RETURN_ERR( new_bufs( min( bufs_max, count + extra_chans ) ) );
107
+	this->new_bufs(std::min(this->bufs_max, count + extra_chans));
115 108
 
116
-	for ( int i = bufs_size; --i >= 0; )
117
-		RETURN_ERR( bufs [i].set_sample_rate( sample_rate(), length() ) );
109
+	for (int i = this->bufs_size; --i >= 0; )
110
+		RETURN_ERR(this->bufs[i]->set_sample_rate(this->sample_rate(), this->length()));
118 111
 
119
-	for ( int i = chans.size(); --i >= 0; )
112
+	for (int i = this->chans.size(); --i >= 0; )
120 113
 	{
121
-		chan_t& ch = chans [i];
122
-		ch.cfg.vol      = 1.0f;
123
-		ch.cfg.pan      = 0.0f;
124
-		ch.cfg.surround = false;
125
-		ch.cfg.echo     = false;
114
+		auto &ch = this->chans[i];
115
+		ch.cfg.vol = 1.0f;
116
+		ch.cfg.pan = 0.0f;
117
+		ch.cfg.surround = ch.cfg.echo = false;
126 118
 	}
127 119
 	// side channels with echo
128
-	chans [2].cfg.echo = true;
129
-	chans [3].cfg.echo = true;
120
+	this->chans[2].cfg.echo = this->chans[3].cfg.echo = true;
130 121
 
131
-	clock_rate( clock_rate_ );
132
-	bass_freq( bass_freq_ );
133
-	apply_config();
134
-	clear();
122
+	this->clock_rate(this->clock_rate_);
123
+	this->bass_freq(this->bass_freq_);
124
+	this->apply_config();
125
+	this->clear();
135 126
 
136 127
 	return 0;
137 128
 }
138 129
 
139 130
 void Effects_Buffer::clear_echo()
140 131
 {
141
-	if ( echo.size() )
142
-		memset( echo.begin(), 0, echo.size() * sizeof echo [0] );
132
+	if (!this->echo.empty())
133
+		memset(&this->echo[0], 0, this->echo.size() * sizeof(echo[0]));
143 134
 }
144 135
 
145 136
 void Effects_Buffer::clear()
146 137
 {
147
-	echo_pos       = 0;
148
-	s.low_pass [0] = 0;
149
-	s.low_pass [1] = 0;
150
-	mixer.samples_read = 0;
151
-
152
-	for ( int i = bufs_size; --i >= 0; )
153
-		bufs [i].clear();
154
-	clear_echo();
138
+	this->echo_pos = 0;
139
+	this->s.low_pass[0] = this->s.low_pass[1] = 0;
140
+	this->mixer.samples_read = 0;
141
+
142
+	for (int i = this->bufs_size; --i >= 0; )
143
+		this->bufs[i]->clear();
144
+	this->clear_echo();
155 145
 }
156 146
 
157
-Effects_Buffer::channel_t Effects_Buffer::channel( int i )
147
+auto Effects_Buffer::channel(int i) -> channel_t
158 148
 {
159 149
 	i += extra_chans;
160
-	require( extra_chans <= i && i < (int) chans.size() );
161
-	return chans [i].channel;
150
+	assert(extra_chans <= i && i < static_cast<int>(this->chans.size()));
151
+	return this->chans[i].channel;
162 152
 }
163 153
 
164
-
165 154
 // Configuration
166 155
 
167 156
 // 3 wave positions with/without surround, 2 multi (one with same config as wave)
168
-int const simple_bufs = 3 * 2 + 2 - 1;
157
+static const int simple_bufs = 3 * 2 + 2 - 1;
169 158
 
170
-Simple_Effects_Buffer::Simple_Effects_Buffer() :
171
-	Effects_Buffer( extra_chans + simple_bufs, 18 * 1024L )
159
+Simple_Effects_Buffer::Simple_Effects_Buffer() : Effects_Buffer(extra_chans + simple_bufs, 18 * 1024L)
172 160
 {
173
-	config_.echo     = 0.20f;
174
-	config_.stereo   = 0.20f;
175
-	config_.surround = true;
176
-	config_.enabled  = false;
161
+	this->config_.echo = 0.20f;
162
+	this->config_.stereo = 0.20f;
163
+	this->config_.surround = true;
164
+	this->config_.enabled = false;
177 165
 }
178 166
 
179 167
 void Simple_Effects_Buffer::apply_config()
180 168
 {
181
-	Effects_Buffer::config_t& c = Effects_Buffer::config();
169
+	auto &c = Effects_Buffer::config();
182 170
 
183
-	c.enabled = config_.enabled;
184
-	if ( c.enabled )
171
+	c.enabled = this->config_.enabled;
172
+	if (c.enabled)
185 173
 	{
186
-		c.delay [0] = 120;
187
-		c.delay [1] = 122;
188
-		c.feedback  = config_.echo * 0.7f;
189
-		c.treble    = 0.6f - 0.3f * config_.echo;
174
+		c.delay[0] = 120;
175
+		c.delay[1] = 122;
176
+		c.feedback = this->config_.echo * 0.7f;
177
+		c.treble = 0.6f - 0.3f * this->config_.echo;
190 178
 
191
-		float sep = config_.stereo + 0.80f;
192
-		if ( sep > 1.0f )
179
+		float sep = this->config_.stereo + 0.80f;
180
+		if (sep > 1.0f)
193 181
 			sep = 1.0f;
194 182
 
195
-		c.side_chans [0].pan = -sep;
196
-		c.side_chans [1].pan = +sep;
183
+		c.side_chans[0].pan = -sep;
184
+		c.side_chans[1].pan = sep;
197 185
 
198
-		for ( int i = channel_count(); --i >= 0; )
186
+		for (int i = this->channel_count(); --i >= 0; )
199 187
 		{
200
-			chan_config_t& ch = Effects_Buffer::chan_config( i );
188
+			auto &ch = Effects_Buffer::chan_config(i);
201 189
 
202
-			ch.pan      = 0.0f;
203
-			ch.surround = config_.surround;
204
-			ch.echo     = false;
190
+			ch.pan = 0.0f;
191
+			ch.surround = this->config_.surround;
192
+			ch.echo = false;
205 193
 
206
-			int const type = (channel_types() ? channel_types() [i] : 0);
207
-			if ( !(type & noise_type) )
194
+			int type = this->channel_types() ? this->channel_types()[i] : 0;
195
+			if (!(type & noise_type))
208 196
 			{
209 197
 				int index = (type & type_index_mask) % 6 - 3;
210
-				if ( index < 0 )
198
+				if (index < 0)
211 199
 				{
212 200
 					index += 3;
213 201
 					ch.surround = false;
214
-					ch.echo     = true;
202
+					ch.echo = true;
215 203
 				}
216
-				if ( index >= 1 )
204
+				if (index >= 1)
217 205
 				{
218
-					ch.pan = config_.stereo;
219
-					if ( index == 1 )
206
+					ch.pan = this->config_.stereo;
207
+					if (index == 1)
220 208
 						ch.pan = -ch.pan;
221 209
 				}
222 210
 			}
223
-			else if ( type & 1 )
224
-			{
211
+			else if (type & 1)
225 212
 				ch.surround = false;
226
-			}
227 213
 		}
228 214
 	}
229 215
 
... ...
@@ -232,183 +218,183 @@ void Simple_Effects_Buffer::apply_config()
232 218
 
233 219
 int Effects_Buffer::min_delay() const
234 220
 {
235
-	require( sample_rate() );
236
-	return max_read * 1000L / sample_rate();
221
+	assert(this->sample_rate());
222
+	return max_read * 1000L / this->sample_rate();
237 223
 }
238 224
 
239 225
 int Effects_Buffer::max_delay() const
240 226
 {
241
-	require( sample_rate() );
242
-	return (echo_size / stereo - max_read) * 1000L / sample_rate();
227
+	assert(this->sample_rate());
228
+	return (this->echo_size / stereo - max_read) * 1000L / this->sample_rate();
243 229
 }
244 230
 
245 231
 void Effects_Buffer::apply_config()
246 232
 {
247
-	int i;
248
-
249
-	if ( !bufs_size )
233
+	if (!this->bufs_size)
250 234
 		return;
251 235
 
252
-	s.treble = TO_FIXED( config_.treble );
236
+	this->s.treble = TO_FIXED(this->config_.treble);
253 237
 
254 238
 	bool echo_dirty = false;
255 239
 
256
-	fixed_t old_feedback = s.feedback;
257
-	s.feedback = TO_FIXED( config_.feedback );
258
-	if ( !old_feedback && s.feedback )
240
+	fixed_t old_feedback = this->s.feedback;
241
+	this->s.feedback = TO_FIXED(this->config_.feedback);
242
+	if (!old_feedback && this->s.feedback)
259 243
 		echo_dirty = true;
260 244
 
261 245
 	// delays
262
-	for ( i = stereo; --i >= 0; )
246
+	int i;
247
+	for (i = stereo; --i >= 0;)
263 248
 	{
264
-		long delay = config_.delay [i] * sample_rate() / 1000 * stereo;
265
-		delay = max( delay, long (max_read * stereo) );
266
-		delay = min( delay, long (echo_size - max_read * stereo) );
267
-		if ( s.delay [i] != delay )
249
+		long delay = this->config_.delay[i] * this->sample_rate() / 1000 * stereo;
250
+		delay = std::max<long>(delay, max_read * stereo);
251
+		delay = std::min<long>(delay, this->echo_size - max_read * stereo);
252
+		if (this->s.delay[i] != delay)
268 253
 		{
269
-			s.delay [i] = delay;
254
+			this->s.delay[i] = delay;
270 255
 			echo_dirty = true;
271 256
 		}
272 257
 	}
273 258
 
274 259
 	// side channels
275
-	for ( i = 2; --i >= 0; )
260
+	for (i = 2; --i >= 0; )
276 261
 	{
277
-		chans [i+2].cfg.vol = chans [i].cfg.vol = config_.side_chans [i].vol * 0.5f;
278
-		chans [i+2].cfg.pan = chans [i].cfg.pan = config_.side_chans [i].pan;
262
+		this->chans[i + 2].cfg.vol = this->chans[i].cfg.vol = this->config_.side_chans[i].vol * 0.5f;
263
+		this->chans[i + 2].cfg.pan = this->chans[i].cfg.pan = this->config_.side_chans[i].pan;
279 264
 	}
280 265
 
281 266
 	// convert volumes
282
-	for ( i = chans.size(); --i >= 0; )
267
+	for (i = this->chans.size(); --i >= 0; )
283 268
 	{
284
-		chan_t& ch = chans [i];
285
-		ch.vol [0] = TO_FIXED( ch.cfg.vol - ch.cfg.vol * ch.cfg.pan );
286
-		ch.vol [1] = TO_FIXED( ch.cfg.vol + ch.cfg.vol * ch.cfg.pan );
287
-		if ( ch.cfg.surround )
288
-			ch.vol [0] = -ch.vol [0];
269
+		auto &ch = this->chans[i];
270
+		ch.vol[0] = TO_FIXED(ch.cfg.vol - ch.cfg.vol * ch.cfg.pan);
271
+		ch.vol[1] = TO_FIXED(ch.cfg.vol + ch.cfg.vol * ch.cfg.pan);
272
+		if (ch.cfg.surround)
273
+			ch.vol[0] = -ch.vol [0];
289 274
 	}
290 275
 
291
-	assign_buffers();
276
+	this->assign_buffers();
292 277
 
293 278
 	// set side channels
294
-	for ( i = chans.size(); --i >= 0; )
279
+	for (i = this->chans.size(); --i >= 0; )
295 280
 	{
296
-		chan_t& ch = chans [i];
297
-		ch.channel.left  = chans [ch.cfg.echo*2  ].channel.center;
298
-		ch.channel.right = chans [ch.cfg.echo*2+1].channel.center;
281
+		auto &ch = chans[i];
282
+		ch.channel.left = this->chans[ch.cfg.echo * 2].channel.center;
283
+		ch.channel.right = this->chans[ch.cfg.echo * 2 + 1].channel.center;
299 284
 	}
300 285
 
301
-	bool old_echo = !no_echo && !no_effects;
286
+	bool old_echo = !this->no_echo && !this->no_effects;
302 287
 
303 288
 	// determine whether effects and echo are needed at all
304
-	no_effects = true;
305
-	no_echo    = true;
306
-	for ( i = chans.size(); --i >= extra_chans; )
289
+	this->no_effects = this->no_echo = true;
290
+	for (i = this->chans.size(); --i >= extra_chans; )
307 291
 	{
308
-		chan_t& ch = chans [i];
309
-		if ( ch.cfg.echo && s.feedback )
310
-			no_echo = false;
292
+		auto &ch = this->chans[i];
293
+		if (ch.cfg.echo && this->s.feedback)
294
+			this->no_echo = false;
311 295
 
312
-		if ( ch.vol [0] != TO_FIXED( 1 ) || ch.vol [1] != TO_FIXED( 1 ) )
313
-			no_effects = false;
296
+		if (ch.vol[0] != TO_FIXED(1) || ch.vol[1] != TO_FIXED(1))
297
+			this->no_effects = false;
314 298
 	}
315
-	if ( !no_echo )
316
-		no_effects = false;
299
+	if (!this->no_echo)
300
+		this->no_effects = false;
317 301
 
318
-	if (    chans [0].vol [0] != TO_FIXED( 1 ) ||
319
-			chans [0].vol [1] != TO_FIXED( 0 ) ||
320
-			chans [1].vol [0] != TO_FIXED( 0 ) ||
321
-			chans [1].vol [1] != TO_FIXED( 1 ) )
322
-		no_effects = false;
302
+	if (this->chans[0].vol[0] != TO_FIXED(1) || this->chans[0].vol[1] != TO_FIXED(0) || this->chans[1].vol[0] != TO_FIXED(0) || this->chans[1].vol[1] != TO_FIXED(1))
303
+		this->no_effects = false;
323 304
 
324
-	if ( !config_.enabled )
325
-		no_effects = true;
305
+	if (!this->config_.enabled)
306
+		this->no_effects = true;
326 307
 
327
-	if ( no_effects )
308
+	if (this->no_effects)
328 309
 	{
329
-		for ( i = chans.size(); --i >= 0; )
310
+		for (i = this->chans.size(); --i >= 0; )
330 311
 		{
331
-			chan_t& ch = chans [i];
332
-			ch.channel.center = &bufs [2];
333
-			ch.channel.left   = &bufs [0];
334
-			ch.channel.right  = &bufs [1];
312
+			auto &ch = this->chans[i];
313
+			ch.channel.center = this->bufs[2].get();
314
+			ch.channel.left = this->bufs[0].get();
315
+			ch.channel.right = this->bufs[1].get();
335 316
 		}
336 317
 	}
337 318
 
338
-	mixer.bufs [0] = &bufs [0];
339
-	mixer.bufs [1] = &bufs [1];
340
-	mixer.bufs [2] = &bufs [2];
319
+	this->mixer.bufs[0] = this->bufs[0].get();
320
+	this->mixer.bufs[1] = this->bufs[1].get();
321
+	this->mixer.bufs[2] = this->bufs[2].get();
341 322
 
342
-	if ( echo_dirty || (!old_echo && (!no_echo && !no_effects)) )
343
-		clear_echo();
323
+	if (echo_dirty || (!old_echo && (!this->no_echo && !this->no_effects)))
324
+		this->clear_echo();
344 325
 
345
-	channels_changed();
326
+	this->channels_changed();
346 327
 }
347 328
 
348 329
 void Effects_Buffer::assign_buffers()
349 330
 {
350 331
 	// assign channels to buffers
351 332
 	int buf_count = 0;
352
-	for ( int i = 0; i < (int) chans.size(); i++ )
333
+	for (int i = 0; i < static_cast<int>(this->chans.size()); ++i)
353 334
 	{
354 335
 		// put second two side channels at end to give priority to main channels
355 336
 		// in case closest matching is necessary
356 337
 		int x = i;
357
-		if ( i > 1 )
338
+		if (i > 1)
358 339
 			x += 2;
359
-		if ( x >= (int) chans.size() )
360
-			x -= (chans.size() - 2);
361
-		chan_t& ch = chans [x];
340
+		if (x >= static_cast<int>(this->chans.size()))
341
+			x -= this->chans.size() - 2;
342
+		auto &ch = this->chans[x];
362 343
 
363 344
 		int b = 0;
364
-		for ( ; b < buf_count; b++ )
345
+		for (; b < buf_count; ++b)
365 346
 		{
366
-			if (    ch.vol [0] == bufs [b].vol [0] &&
367
-					ch.vol [1] == bufs [b].vol [1] &&
368
-					(ch.cfg.echo == bufs [b].echo || !s.feedback) )
347
+			if (ch.vol[0] == this->bufs[b]->vol[0] && ch.vol[1] == this->bufs[b]->vol[1] && (ch.cfg.echo == this->bufs[b]->echo || !this->s.feedback))
369 348
 				break;
370 349
 		}
371 350
 
372
-		if ( b >= buf_count )
351
+		if (b >= buf_count)
373 352
 		{
374
-			if ( buf_count < bufs_max )
353
+			if (buf_count < this->bufs_max)
375 354
 			{
376
-				bufs [b].vol [0] = ch.vol [0];
377
-				bufs [b].vol [1] = ch.vol [1];
378
-				bufs [b].echo    = ch.cfg.echo;
379
-				buf_count++;
355
+				this->bufs[b]->vol[0] = ch.vol[0];
356
+				this->bufs[b]->vol[1] = ch.vol[1];
357
+				this->bufs[b]->echo = ch.cfg.echo;
358
+				++buf_count;
380 359
 			}
381 360
 			else
382 361
 			{
383 362
 				// TODO: this is a mess, needs refinement
384
-				dprintf( "Effects_Buffer ran out of buffers; using closest match\n" );
385 363
 				b = 0;
386
-				fixed_t best_dist = TO_FIXED( 8 );
387
-				for ( int h = buf_count; --h >= 0; )
364
+				fixed_t best_dist = TO_FIXED(8);
365
+				for (int h = buf_count; --h >= 0; )
388 366
 				{
389
-					#define CALC_LEVELS( vols, sum, diff, surround ) \
390
-					fixed_t sum, diff;\
391
-					bool surround = false;\
392
-					{\
393
-						fixed_t vol_0 = vols [0];\
394
-						if ( vol_0 < 0 ) vol_0 = -vol_0, surround = true;\
395
-						fixed_t vol_1 = vols [1];\
396
-						if ( vol_1 < 0 ) vol_1 = -vol_1, surround = true;\
397
-						sum  = vol_0 + vol_1;\
398
-						diff = vol_0 - vol_1;\
399
-					}
400
-					CALC_LEVELS( ch.vol,       ch_sum,  ch_diff,  ch_surround );
401
-					CALC_LEVELS( bufs [h].vol, buf_sum, buf_diff, buf_surround );
367
+					auto CALC_LEVELS = [&](fixed_t vols[], fixed_t &sum, fixed_t &diff, bool &surround)
368
+					{
369
+						fixed_t vol_0 = vols[0];
370
+						if (vol_0 < 0)
371
+						{
372
+							vol_0 = -vol_0;
373
+							surround = true;
374
+						}
375
+						fixed_t vol_1 = vols[1];
376
+						if (vol_1 < 0)
377
+						{
378
+							vol_1 = -vol_1;
379
+							surround = true;
380
+						}
381
+						sum = vol_0 + vol_1;
382
+						diff = vol_0 - vol_1;
383
+					};
384
+					fixed_t ch_sum, ch_diff, buf_sum, buf_diff;
385
+					bool ch_surround, buf_surround;
386
+					CALC_LEVELS(ch.vol, ch_sum, ch_diff, ch_surround);
387
+					CALC_LEVELS(this->bufs[h]->vol, buf_sum, buf_diff, buf_surround);
402 388
 
403
-					fixed_t dist = abs( ch_sum - buf_sum ) + abs( ch_diff - buf_diff );
389
+					fixed_t dist = std::abs(ch_sum - buf_sum) + std::abs(ch_diff - buf_diff);
404 390
 
405
-					if ( ch_surround != buf_surround )
406
-						dist += TO_FIXED( 1 ) / 2;
391
+					if (ch_surround != buf_surround)
392
+						dist += TO_FIXED(1) / 2;
407 393
 
408
-					if ( s.feedback && ch.cfg.echo != bufs [h].echo )
409
-						dist += TO_FIXED( 1 ) / 2;
394
+					if (this->s.feedback && ch.cfg.echo != this->bufs[h]->echo)
395
+						dist += TO_FIXED(1) / 2;
410 396
 
411
-					if ( best_dist > dist )
397
+					if (best_dist > dist)
412 398
 					{
413 399
 						best_dist = dist;
414 400
 						b = h;
... ...
@@ -417,32 +403,28 @@ void Effects_Buffer::assign_buffers()
417 403
 			}
418 404
 		}
419 405
 
420
-		//dprintf( "ch %d->buf %d\n", x, b );
421
-		ch.channel.center = &bufs [b];
406
+		ch.channel.center = this->bufs[b].get();
422 407
 	}
423 408
 }
424 409
 
425
-
426 410
 // Mixing
427 411
 
428
-void Effects_Buffer::end_frame( blip_time_t time )
412
+void Effects_Buffer::end_frame(blip_time_t time)
429 413
 {
430
-	for ( int i = bufs_size; --i >= 0; )
431
-		bufs [i].end_frame( time );
414
+	for (int i = bufs_size; --i >= 0; )
415
+		this->bufs[i]->end_frame(time);
432 416
 }
433 417
 
434
-long Effects_Buffer::read_samples( blip_sample_t* out, long out_size )
418
+long Effects_Buffer::read_samples(blip_sample_t *out, long out_size)
435 419
 {
436
-	out_size = min( out_size, samples_avail() );
420
+	out_size = std::min(out_size, this->samples_avail());
437 421
 
438
-	int pair_count = int (out_size >> 1);
439
-	require( pair_count * stereo == out_size ); // must read an even number of samples
440
-	if ( pair_count )
422
+	int pair_count = static_cast<int>(out_size >> 1);
423
+	assert(pair_count * stereo == out_size); // must read an even number of samples
424
+	if (pair_count)
441 425
 	{
442
-		if ( no_effects )
443
-		{
444
-			mixer.read_pairs( out, pair_count );
445
-		}
426
+		if (this->no_effects)
427
+			this->mixer.read_pairs(out, pair_count);
446 428
 		else
447 429
 		{
448 430
 			int pairs_remain = pair_count;
... ...
@@ -450,50 +432,49 @@ long Effects_Buffer::read_samples( blip_sample_t* out, long out_size )
450 432
 			{
451 433
 				// mix at most max_read pairs at a time
452 434
 				int count = max_read;
453
-				if ( count > pairs_remain )
435
+				if (count > pairs_remain)
454 436
 					count = pairs_remain;
455 437
 
456
-				if ( no_echo )
438
+				if (this->no_echo)
457 439
 				{
458 440
 					// optimization: clear echo here to keep mix_effects() a leaf function
459
-					echo_pos = 0;
460
-					memset( echo.begin(), 0, count * stereo * sizeof echo [0] );
441
+					this->echo_pos = 0;
442
+					memset(&this->echo[0], 0, count * stereo * sizeof(this->echo[0]));
461 443
 				}
462
-				mix_effects( out, count );
444
+				this->mix_effects(out, count);
463 445
 
464
-				blargg_long new_echo_pos = echo_pos + count * stereo;
465
-				if ( new_echo_pos >= echo_size )
466
-					new_echo_pos -= echo_size;
467
-				echo_pos = new_echo_pos;
468
-				assert( echo_pos < echo_size );
446
+				int32_t new_echo_pos = this->echo_pos + count * stereo;
447
+				if (new_echo_pos >= this->echo_size)
448
+					new_echo_pos -= this->echo_size;
449
+				this->echo_pos = new_echo_pos;
450
+				assert(this->echo_pos < this->echo_size);
469 451
 
470 452
 				out += count * stereo;
471
-				mixer.samples_read += count;
453
+				this->mixer.samples_read += count;
472 454
 				pairs_remain -= count;
473
-			}
474
-			while ( pairs_remain );
455
+			} while (pairs_remain);
475 456
 		}
476 457
 
477
-		if ( samples_avail() <= 0 || immediate_removal() )
458
+		if (this->samples_avail() <= 0 || this->immediate_removal())
478 459
 		{
479
-			for ( int i = bufs_size; --i >= 0; )
460
+			for (int i = this->bufs_size; --i >= 0; )
480 461
 			{
481
-				buf_t& b = bufs [i];
462
+				auto &b = this->bufs[i];
482 463
 				// TODO: might miss non-silence settling since it checks END of last read
483
-				if ( b.non_silent() )
484
-					b.remove_samples( mixer.samples_read );
464
+				if (b->non_silent())
465
+					b->remove_samples(this->mixer.samples_read);
485 466
 				else
486
-					b.remove_silence( mixer.samples_read );
467
+					b->remove_silence(this->mixer.samples_read);
487 468
 			}
488
-			mixer.samples_read = 0;
469
+			this->mixer.samples_read = 0;
489 470
 		}
490 471
 	}
491 472
 	return out_size;
492 473
 }
493 474
 
494
-void Effects_Buffer::mix_effects( blip_sample_t* out_, int pair_count )
475
+void Effects_Buffer::mix_effects(blip_sample_t *out_, int pair_count)
495 476
 {
496
-	typedef fixed_t stereo_fixed_t [stereo];
477
+	typedef fixed_t stereo_fixed_t[stereo];
497 478
 
498 479
 	// add channels with echo, do echo, add channels without echo, then convert to 16-bit and output
499 480
 	int echo_phase = 1;
... ...
@@ -501,138 +482,128 @@ void Effects_Buffer::mix_effects( blip_sample_t* out_, int pair_count )
501 482
 	{
502 483
 		// mix any modified buffers
503 484
 		{
504
-			buf_t* buf = bufs;
505
-			int bufs_remain = bufs_size;
485
+			size_t bufNum = 0;
486
+			int bufs_remain = this->bufs_size;
506 487
 			do
507 488
 			{
508
-				if ( buf->non_silent() && ( buf->echo == !!echo_phase ) )
489
+				auto &buf = this->bufs[bufNum++];
490
+				if (buf->non_silent() && (buf->echo == !!echo_phase))
509 491
 				{
510
-					stereo_fixed_t* BLIP_RESTRICT out = (stereo_fixed_t*) &echo [echo_pos];
511
-					int const bass = BLIP_READER_BASS( *buf );
512
-					BLIP_READER_BEGIN( in, *buf );
513
-					BLIP_READER_ADJ_( in, mixer.samples_read );
514
-					fixed_t const vol_0 = buf->vol [0];
515
-					fixed_t const vol_1 = buf->vol [1];
516
-
517
-					int count = unsigned (echo_size - echo_pos) / stereo;
492
+					auto out = reinterpret_cast<stereo_fixed_t *>(&this->echo[this->echo_pos]);
493
+					int bass = BLIP_READER_BASS(*buf);
494
+					BLIP_READER_BEGIN(in, *buf);
495
+					BLIP_READER_ADJ_(in, this->mixer.samples_read);
496
+					fixed_t vol_0 = buf->vol[0];
497
+					fixed_t vol_1 = buf->vol[1];
498
+
499
+					int count = static_cast<unsigned>(echo_size - echo_pos) / stereo;
518 500
 					int remain = pair_count;
519
-					if ( count > remain )
501
+					if (count > remain)
520 502
 						count = remain;
521 503
 					do
522 504
 					{
523 505
 						remain -= count;
524
-						BLIP_READER_ADJ_( in, count );
506
+						BLIP_READER_ADJ_(in, count);
525 507
 
526 508
 						out += count;
527 509
 						int offset = -count;
528 510
 						do
529 511
 						{
530
-							fixed_t s = BLIP_READER_READ( in );
531
-							BLIP_READER_NEXT_IDX_( in, bass, offset );
512
+							fixed_t s = BLIP_READER_READ(in);
513
+							BLIP_READER_NEXT_IDX_(in, bass, offset);
532 514
 
533
-							out [offset] [0] += s * vol_0;
534
-							out [offset] [1] += s * vol_1;
535
-						}
536
-						while ( ++offset );
515
+							out[offset][0] += s * vol_0;
516
+							out[offset][1] += s * vol_1;
517
+						} while ( ++offset );
537 518
 
538
-						out = (stereo_fixed_t*) echo.begin();
519
+						out = reinterpret_cast<stereo_fixed_t *>(&this->echo[0]);
539 520
 						count = remain;
540
-					}
541
-					while ( remain );
521
+					} while (remain);
542 522
 
543
-					BLIP_READER_END( in, *buf );
523
+					BLIP_READER_END(in, *buf);
544 524
 				}
545
-				buf++;
546
-			}
547
-			while ( --bufs_remain );
525
+			} while (--bufs_remain);
548 526
 		}
549 527
 
550 528
 		// add echo
551
-		if ( echo_phase && !no_echo )
529
+		if (echo_phase && !this->no_echo)
552 530
 		{
553
-			fixed_t const feedback = s.feedback;
554
-			fixed_t const treble   = s.treble;
531
+			fixed_t feedback = this->s.feedback;
532
+			fixed_t treble = this->s.treble;
555 533
 
556 534
 			int i = 1;
557 535
 			do
558 536
 			{
559
-				fixed_t low_pass = s.low_pass [i];
537
+				fixed_t low_pass = this->s.low_pass[i];
560 538
 
561
-				fixed_t* echo_end = &echo [echo_size + i];
562
-				fixed_t const* BLIP_RESTRICT in_pos = &echo [echo_pos + i];
563
-				blargg_long out_offset = echo_pos + i + s.delay [i];
564
-				if ( out_offset >= echo_size )
565
-					out_offset -= echo_size;
566
-				assert( out_offset < echo_size );
567
-				fixed_t* BLIP_RESTRICT out_pos = &echo [out_offset];
539
+				auto echo_end = &this->echo[this->echo_size + i];
540
+				auto in_pos = &this->echo[this->echo_pos + i];
541
+				int32_t out_offset = this->echo_pos + i + this->s.delay[i];
542
+				if (out_offset >= this->echo_size)
543
+					out_offset -= this->echo_size;
544
+				assert(out_offset < this->echo_size);
545
+				auto out_pos = &this->echo[out_offset];
568 546
 
569 547
 				// break into up to three chunks to avoid having to handle wrap-around
570 548
 				// in middle of core loop
571 549
 				int remain = pair_count;
572 550
 				do
573 551
 				{
574
-					fixed_t const* pos = in_pos;
575
-					if ( pos < out_pos )
552
+					auto pos = in_pos;
553
+					if (pos < out_pos)
576 554
 						pos = out_pos;
577
-					int count = blargg_ulong ((char*) echo_end - (char const*) pos) /
578
-							unsigned (stereo * sizeof (fixed_t));
579
-					if ( count > remain )
555
+					int count = static_cast<uint32_t>(reinterpret_cast<char *>(echo_end) - reinterpret_cast<const char *>(pos)) / (stereo * sizeof(fixed_t));
556
+					if (count > remain)
580 557
 						count = remain;
581 558
 					remain -= count;
582 559
 
583
-					in_pos  += count * stereo;
560
+					in_pos += count * stereo;
584 561
 					out_pos += count * stereo;
585 562
 					int offset = -count;
586 563
 					do
587 564
 					{
588
-						low_pass += FROM_FIXED( in_pos [offset * stereo] - low_pass ) * treble;
589
-						out_pos [offset * stereo] = FROM_FIXED( low_pass ) * feedback;
590
-					}
591
-					while ( ++offset );
592
-
593
-					if (  in_pos >= echo_end )  in_pos -= echo_size;
594
-					if ( out_pos >= echo_end ) out_pos -= echo_size;
595
-				}
596
-				while ( remain );
597
-
598
-				s.low_pass [i] = low_pass;
599
-			}
600
-			while ( --i >= 0 );
565
+						low_pass += FROM_FIXED(in_pos[offset * stereo] - low_pass) * treble;
566
+						out_pos[offset * stereo] = FROM_FIXED(low_pass) * feedback;
567
+					} while (++offset);
568
+
569
+					if (in_pos >= echo_end)
570
+						in_pos -= echo_size;
571
+					if (out_pos >= echo_end)
572
+						out_pos -= echo_size;
573
+				} while (remain);
574
+
575
+				this->s.low_pass [i] = low_pass;
576
+			} while (--i >= 0);
601 577
 		}
602
-	}
603
-	while ( --echo_phase >= 0 );
578
+	} while (--echo_phase >= 0);
604 579
 
605 580
 	// clamp to 16 bits
581
+	auto in = reinterpret_cast<stereo_fixed_t *>(&this->echo[this->echo_pos]);
582
+	typedef blip_sample_t stereo_blip_sample_t[stereo];
583
+	auto out = reinterpret_cast<stereo_blip_sample_t *>(out_);
584
+	int count = static_cast<unsigned>(this->echo_size - this->echo_pos) / stereo;
585
+	int remain = pair_count;
586
+	if (count > remain)
587
+		count = remain;
588
+	do
606 589
 	{
607
-		stereo_fixed_t const* BLIP_RESTRICT in = (stereo_fixed_t*) &echo [echo_pos];
608
-		typedef blip_sample_t stereo_blip_sample_t [stereo];
609
-		stereo_blip_sample_t* BLIP_RESTRICT out = (stereo_blip_sample_t*) out_;
610
-		int count = unsigned (echo_size - echo_pos) / (unsigned) stereo;
611
-		int remain = pair_count;
612
-		if ( count > remain )
613
-			count = remain;
590
+		remain -= count;
591
+		in  += count;
592
+		out += count;
593
+		int offset = -count;
614 594
 		do
615 595
 		{
616
-			remain -= count;
617
-			in  += count;
618
-			out += count;
619
-			int offset = -count;
620
-			do
621
-			{
622
-				fixed_t in_0 = FROM_FIXED( in [offset] [0] );
623
-				fixed_t in_1 = FROM_FIXED( in [offset] [1] );
596
+			fixed_t in_0 = FROM_FIXED(in[offset][0]);
597
+			fixed_t in_1 = FROM_FIXED(in[offset][1]);
624 598
 
625
-				BLIP_CLAMP( in_0, in_0 );
626
-				out [offset] [0] = (blip_sample_t) in_0;
599
+			BLIP_CLAMP(in_0, in_0);
600
+			out[offset][0] = static_cast<blip_sample_t>(in_0);
627 601
 
628
-				BLIP_CLAMP( in_1, in_1 );
629
-				out [offset] [1] = (blip_sample_t) in_1;
630
-			}
631
-			while ( ++offset );
602
+			BLIP_CLAMP(in_1, in_1);
603
+			out[offset][1] = static_cast<blip_sample_t>(in_1);
604
+		} while (++offset);
632 605
 
633
-			in = (stereo_fixed_t*) echo.begin();
634
-			count = remain;
635
-		}
636
-		while ( remain );
637
-	}
606
+		in = reinterpret_cast<stereo_fixed_t *>(&this->echo[0]);
607
+		count = remain;
608
+	} while (remain);
638 609
 }
Browse code

Import actual code.

Naram Qashat authored on 2013/03/26 02:41:19
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,638 @@
1
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
2
+
3
+#include "Effects_Buffer.h"
4
+
5
+#include <string.h>
6
+
7
+/* Copyright (C) 2006-2007 Shay Green. This module is free software; you
8
+can redistribute it and/or modify it under the terms of the GNU Lesser
9
+General Public License as published by the Free Software Foundation; either
10
+version 2.1 of the License, or (at your option) any later version. This
11
+module is distributed in the hope that it will be useful, but WITHOUT ANY
12
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14
+details. You should have received a copy of the GNU Lesser General Public
15
+License along with this module; if not, write to the Free Software Foundation,
16
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
17
+
18
+#include "blargg_source.h"
19
+
20
+int const fixed_shift = 12;
21
+#define TO_FIXED( f )   fixed_t ((f) * ((fixed_t) 1 << fixed_shift))
22
+#define FROM_FIXED( f ) ((f) >> fixed_shift)
23
+
24
+int const max_read = 2560; // determines minimum delay
25
+
26
+Effects_Buffer::Effects_Buffer( int max_bufs, long echo_size_ ) : Multi_Buffer( stereo )
27
+{
28
+	echo_size   = max( max_read * (long) stereo, echo_size_ & ~1 );
29
+	clock_rate_ = 0;
30
+	bass_freq_  = 90;
31
+	bufs        = 0;
32
+	bufs_size   = 0;
33
+	bufs_max    = max( max_bufs, (int) extra_chans );
34
+	no_echo     = true;
35
+	no_effects  = true;
36
+
37
+	// defaults
38
+	config_.enabled   = false;
39
+	config_.delay [0] = 120;
40
+	config_.delay [1] = 122;
41
+	config_.feedback  = 0.2f;
42
+	config_.treble    = 0.4f;
43
+
44
+	static float const sep = 0.8f;
45
+	config_.side_chans [0].pan = -sep;
46
+	config_.side_chans [1].pan = +sep;
47
+	config_.side_chans [0].vol = 1.0f;
48
+	config_.side_chans [1].vol = 1.0f;
49
+
50
+	memset( &s, 0, sizeof s );
51
+	clear();
52
+}
53
+
54
+Effects_Buffer::~Effects_Buffer()
55
+{
56
+	delete_bufs();
57
+}
58
+
59
+// avoid using new []
60
+blargg_err_t Effects_Buffer::new_bufs( int size )
61
+{
62
+	bufs = (buf_t*) malloc( size * sizeof *bufs );
63
+	CHECK_ALLOC( bufs );
64
+	for ( int i = 0; i < size; i++ )
65
+		new (bufs + i) buf_t;
66
+	bufs_size = size;
67
+	return 0;
68
+}
69
+
70
+void Effects_Buffer::delete_bufs()
71
+{
72
+	if ( bufs )
73
+	{
74
+		for ( int i = bufs_size; --i >= 0; )
75
+			bufs [i].~buf_t();
76
+		free( bufs );
77
+		bufs = 0;
78
+	}
79
+	bufs_size = 0;
80
+}
81
+
82
+blargg_err_t Effects_Buffer::set_sample_rate( long rate, int msec )
83
+{
84
+	// extra to allow farther past-the-end pointers
85
+	mixer.samples_read = 0;
86
+	RETURN_ERR( echo.resize( echo_size + stereo ) );
87
+	return Multi_Buffer::set_sample_rate( rate, msec );
88
+}
89
+
90
+void Effects_Buffer::clock_rate( long rate )
91
+{
92
+	clock_rate_ = rate;
93
+	for ( int i = bufs_size; --i >= 0; )
94
+		bufs [i].clock_rate( clock_rate_ );
95
+}
96
+
97
+void Effects_Buffer::bass_freq( int freq )
98
+{
99
+	bass_freq_ = freq;
100
+	for ( int i = bufs_size; --i >= 0; )
101
+		bufs [i].bass_freq( bass_freq_ );
102
+}
103
+
104
+blargg_err_t Effects_Buffer::set_channel_count( int count, int const* types )
105
+{
106
+	RETURN_ERR( Multi_Buffer::set_channel_count( count, types ) );
107
+
108
+	delete_bufs();
109
+
110
+	mixer.samples_read = 0;
111
+
112
+	RETURN_ERR( chans.resize( count + extra_chans ) );
113
+
114
+	RETURN_ERR( new_bufs( min( bufs_max, count + extra_chans ) ) );
115
+
116
+	for ( int i = bufs_size; --i >= 0; )
117
+		RETURN_ERR( bufs [i].set_sample_rate( sample_rate(), length() ) );
118
+
119
+	for ( int i = chans.size(); --i >= 0; )
120
+	{
121
+		chan_t& ch = chans [i];
122
+		ch.cfg.vol      = 1.0f;
123
+		ch.cfg.pan      = 0.0f;
124
+		ch.cfg.surround = false;
125
+		ch.cfg.echo     = false;
126
+	}
127
+	// side channels with echo
128
+	chans [2].cfg.echo = true;
129
+	chans [3].cfg.echo = true;
130
+
131
+	clock_rate( clock_rate_ );
132
+	bass_freq( bass_freq_ );
133
+	apply_config();
134
+	clear();
135
+
136
+	return 0;
137
+}
138
+
139
+void Effects_Buffer::clear_echo()
140
+{
141
+	if ( echo.size() )
142
+		memset( echo.begin(), 0, echo.size() * sizeof echo [0] );
143
+}
144
+
145
+void Effects_Buffer::clear()
146
+{
147
+	echo_pos       = 0;
148
+	s.low_pass [0] = 0;
149
+	s.low_pass [1] = 0;
150
+	mixer.samples_read = 0;
151
+
152
+	for ( int i = bufs_size; --i >= 0; )
153
+		bufs [i].clear();
154
+	clear_echo();
155
+}
156
+
157
+Effects_Buffer::channel_t Effects_Buffer::channel( int i )
158
+{
159
+	i += extra_chans;
160
+	require( extra_chans <= i && i < (int) chans.size() );
161
+	return chans [i].channel;
162
+}
163
+
164
+
165
+// Configuration
166
+
167
+// 3 wave positions with/without surround, 2 multi (one with same config as wave)
168
+int const simple_bufs = 3 * 2 + 2 - 1;
169
+
170
+Simple_Effects_Buffer::Simple_Effects_Buffer() :
171
+	Effects_Buffer( extra_chans + simple_bufs, 18 * 1024L )
172
+{
173
+	config_.echo     = 0.20f;
174
+	config_.stereo   = 0.20f;
175
+	config_.surround = true;
176
+	config_.enabled  = false;
177
+}
178
+
179
+void Simple_Effects_Buffer::apply_config()
180
+{
181
+	Effects_Buffer::config_t& c = Effects_Buffer::config();
182
+
183
+	c.enabled = config_.enabled;
184
+	if ( c.enabled )
185
+	{
186
+		c.delay [0] = 120;
187
+		c.delay [1] = 122;
188
+		c.feedback  = config_.echo * 0.7f;
189
+		c.treble    = 0.6f - 0.3f * config_.echo;
190
+
191
+		float sep = config_.stereo + 0.80f;
192
+		if ( sep > 1.0f )
193
+			sep = 1.0f;
194
+
195
+		c.side_chans [0].pan = -sep;
196
+		c.side_chans [1].pan = +sep;
197
+
198
+		for ( int i = channel_count(); --i >= 0; )
199
+		{
200
+			chan_config_t& ch = Effects_Buffer::chan_config( i );
201
+
202
+			ch.pan      = 0.0f;
203
+			ch.surround = config_.surround;
204
+			ch.echo     = false;
205
+
206
+			int const type = (channel_types() ? channel_types() [i] : 0);
207
+			if ( !(type & noise_type) )
208
+			{
209
+				int index = (type & type_index_mask) % 6 - 3;
210
+				if ( index < 0 )
211
+				{
212
+					index += 3;
213
+					ch.surround = false;
214
+					ch.echo     = true;
215
+				}
216
+				if ( index >= 1 )
217
+				{
218
+					ch.pan = config_.stereo;
219
+					if ( index == 1 )
220
+						ch.pan = -ch.pan;
221
+				}
222
+			}
223
+			else if ( type & 1 )
224
+			{
225
+				ch.surround = false;
226
+			}
227
+		}
228
+	}
229
+
230
+	Effects_Buffer::apply_config();
231
+}
232
+
233
+int Effects_Buffer::min_delay() const
234
+{
235
+	require( sample_rate() );
236
+	return max_read * 1000L / sample_rate();
237
+}
238
+
239
+int Effects_Buffer::max_delay() const
240
+{
241
+	require( sample_rate() );
242
+	return (echo_size / stereo - max_read) * 1000L / sample_rate();
243
+}
244
+
245
+void Effects_Buffer::apply_config()
246
+{
247
+	int i;
248
+
249
+	if ( !bufs_size )
250
+		return;
251
+
252
+	s.treble = TO_FIXED( config_.treble );
253
+
254
+	bool echo_dirty = false;
255
+
256
+	fixed_t old_feedback = s.feedback;
257
+	s.feedback = TO_FIXED( config_.feedback );
258
+	if ( !old_feedback && s.feedback )
259
+		echo_dirty = true;
260
+
261
+	// delays
262
+	for ( i = stereo; --i >= 0; )
263
+	{
264
+		long delay = config_.delay [i] * sample_rate() / 1000 * stereo;
265
+		delay = max( delay, long (max_read * stereo) );
266
+		delay = min( delay, long (echo_size - max_read * stereo) );
267
+		if ( s.delay [i] != delay )
268
+		{
269
+			s.delay [i] = delay;
270
+			echo_dirty = true;
271
+		}
272
+	}
273
+
274
+	// side channels
275
+	for ( i = 2; --i >= 0; )
276
+	{
277
+		chans [i+2].cfg.vol = chans [i].cfg.vol = config_.side_chans [i].vol * 0.5f;
278
+		chans [i+2].cfg.pan = chans [i].cfg.pan = config_.side_chans [i].pan;
279
+	}
280
+
281
+	// convert volumes
282
+	for ( i = chans.size(); --i >= 0; )
283
+	{
284
+		chan_t& ch = chans [i];
285
+		ch.vol [0] = TO_FIXED( ch.cfg.vol - ch.cfg.vol * ch.cfg.pan );
286
+		ch.vol [1] = TO_FIXED( ch.cfg.vol + ch.cfg.vol * ch.cfg.pan );
287
+		if ( ch.cfg.surround )
288
+			ch.vol [0] = -ch.vol [0];
289
+	}
290
+
291
+	assign_buffers();
292
+
293
+	// set side channels
294
+	for ( i = chans.size(); --i >= 0; )
295
+	{
296
+		chan_t& ch = chans [i];
297
+		ch.channel.left  = chans [ch.cfg.echo*2  ].channel.center;
298
+		ch.channel.right = chans [ch.cfg.echo*2+1].channel.center;
299
+	}
300
+
301
+	bool old_echo = !no_echo && !no_effects;
302
+
303
+	// determine whether effects and echo are needed at all
304
+	no_effects = true;
305
+	no_echo    = true;
306
+	for ( i = chans.size(); --i >= extra_chans; )
307
+	{
308
+		chan_t& ch = chans [i];
309
+		if ( ch.cfg.echo && s.feedback )
310
+			no_echo = false;
311
+
312
+		if ( ch.vol [0] != TO_FIXED( 1 ) || ch.vol [1] != TO_FIXED( 1 ) )
313
+			no_effects = false;
314
+	}
315
+	if ( !no_echo )
316
+		no_effects = false;
317
+
318
+	if (    chans [0].vol [0] != TO_FIXED( 1 ) ||
319
+			chans [0].vol [1] != TO_FIXED( 0 ) ||
320
+			chans [1].vol [0] != TO_FIXED( 0 ) ||
321
+			chans [1].vol [1] != TO_FIXED( 1 ) )
322
+		no_effects = false;
323
+
324
+	if ( !config_.enabled )
325
+		no_effects = true;
326
+
327
+	if ( no_effects )
328
+	{
329
+		for ( i = chans.size(); --i >= 0; )
330
+		{
331
+			chan_t& ch = chans [i];
332
+			ch.channel.center = &bufs [2];
333
+			ch.channel.left   = &bufs [0];
334
+			ch.channel.right  = &bufs [1];
335
+		}
336
+	}
337
+
338
+	mixer.bufs [0] = &bufs [0];
339
+	mixer.bufs [1] = &bufs [1];
340
+	mixer.bufs [2] = &bufs [2];
341
+
342
+	if ( echo_dirty || (!old_echo && (!no_echo && !no_effects)) )
343
+		clear_echo();
344
+
345
+	channels_changed();
346
+}
347
+
348
+void Effects_Buffer::assign_buffers()
349
+{
350
+	// assign channels to buffers
351
+	int buf_count = 0;
352
+	for ( int i = 0; i < (int) chans.size(); i++ )
353
+	{
354
+		// put second two side channels at end to give priority to main channels
355
+		// in case closest matching is necessary
356
+		int x = i;
357
+		if ( i > 1 )
358
+			x += 2;
359
+		if ( x >= (int) chans.size() )
360
+			x -= (chans.size() - 2);
361
+		chan_t& ch = chans [x];
362
+
363
+		int b = 0;
364
+		for ( ; b < buf_count; b++ )
365
+		{
366
+			if (    ch.vol [0] == bufs [b].vol [0] &&
367
+					ch.vol [1] == bufs [b].vol [1] &&
368
+					(ch.cfg.echo == bufs [b].echo || !s.feedback) )
369
+				break;
370
+		}
371
+
372
+		if ( b >= buf_count )
373
+		{
374
+			if ( buf_count < bufs_max )
375
+			{
376
+				bufs [b].vol [0] = ch.vol [0];
377
+				bufs [b].vol [1] = ch.vol [1];
378
+				bufs [b].echo    = ch.cfg.echo;
379
+				buf_count++;
380
+			}
381
+			else
382
+			{
383
+				// TODO: this is a mess, needs refinement
384
+				dprintf( "Effects_Buffer ran out of buffers; using closest match\n" );
385
+				b = 0;
386
+				fixed_t best_dist = TO_FIXED( 8 );
387
+				for ( int h = buf_count; --h >= 0; )
388
+				{
389
+					#define CALC_LEVELS( vols, sum, diff, surround ) \
390
+					fixed_t sum, diff;\
391
+					bool surround = false;\
392
+					{\
393
+						fixed_t vol_0 = vols [0];\
394
+						if ( vol_0 < 0 ) vol_0 = -vol_0, surround = true;\
395
+						fixed_t vol_1 = vols [1];\
396
+						if ( vol_1 < 0 ) vol_1 = -vol_1, surround = true;\
397
+						sum  = vol_0 + vol_1;\
398
+						diff = vol_0 - vol_1;\
399
+					}
400
+					CALC_LEVELS( ch.vol,       ch_sum,  ch_diff,  ch_surround );
401
+					CALC_LEVELS( bufs [h].vol, buf_sum, buf_diff, buf_surround );
402
+
403
+					fixed_t dist = abs( ch_sum - buf_sum ) + abs( ch_diff - buf_diff );
404
+
405
+					if ( ch_surround != buf_surround )
406
+						dist += TO_FIXED( 1 ) / 2;
407
+
408
+					if ( s.feedback && ch.cfg.echo != bufs [h].echo )
409
+						dist += TO_FIXED( 1 ) / 2;
410
+
411
+					if ( best_dist > dist )
412
+					{
413
+						best_dist = dist;
414
+						b = h;
415
+					}
416
+				}
417
+			}
418
+		}
419
+
420
+		//dprintf( "ch %d->buf %d\n", x, b );
421
+		ch.channel.center = &bufs [b];
422
+	}
423
+}
424
+
425
+
426
+// Mixing
427
+
428
+void Effects_Buffer::end_frame( blip_time_t time )
429
+{
430
+	for ( int i = bufs_size; --i >= 0; )
431
+		bufs [i].end_frame( time );
432
+}
433
+
434
+long Effects_Buffer::read_samples( blip_sample_t* out, long out_size )
435
+{
436
+	out_size = min( out_size, samples_avail() );
437
+
438
+	int pair_count = int (out_size >> 1);
439
+	require( pair_count * stereo == out_size ); // must read an even number of samples
440
+	if ( pair_count )
441
+	{
442
+		if ( no_effects )
443
+		{
444
+			mixer.read_pairs( out, pair_count );
445
+		}
446
+		else
447
+		{
448
+			int pairs_remain = pair_count;
449
+			do
450
+			{
451
+				// mix at most max_read pairs at a time
452
+				int count = max_read;
453
+				if ( count > pairs_remain )
454
+					count = pairs_remain;
455
+
456
+				if ( no_echo )
457
+				{
458
+					// optimization: clear echo here to keep mix_effects() a leaf function
459
+					echo_pos = 0;
460
+					memset( echo.begin(), 0, count * stereo * sizeof echo [0] );
461
+				}
462
+				mix_effects( out, count );
463
+
464
+				blargg_long new_echo_pos = echo_pos + count * stereo;
465
+				if ( new_echo_pos >= echo_size )
466
+					new_echo_pos -= echo_size;
467
+				echo_pos = new_echo_pos;
468
+				assert( echo_pos < echo_size );
469
+
470
+				out += count * stereo;
471
+				mixer.samples_read += count;
472
+				pairs_remain -= count;
473
+			}
474
+			while ( pairs_remain );
475
+		}
476
+
477
+		if ( samples_avail() <= 0 || immediate_removal() )
478
+		{
479
+			for ( int i = bufs_size; --i >= 0; )
480
+			{
481
+				buf_t& b = bufs [i];
482
+				// TODO: might miss non-silence settling since it checks END of last read
483
+				if ( b.non_silent() )
484
+					b.remove_samples( mixer.samples_read );
485
+				else
486
+					b.remove_silence( mixer.samples_read );
487
+			}
488
+			mixer.samples_read = 0;
489
+		}
490
+	}
491
+	return out_size;
492
+}
493
+
494
+void Effects_Buffer::mix_effects( blip_sample_t* out_, int pair_count )
495
+{
496
+	typedef fixed_t stereo_fixed_t [stereo];
497
+
498
+	// add channels with echo, do echo, add channels without echo, then convert to 16-bit and output
499
+	int echo_phase = 1;
500
+	do
501
+	{
502
+		// mix any modified buffers
503
+		{
504
+			buf_t* buf = bufs;
505
+			int bufs_remain = bufs_size;
506
+			do
507
+			{
508
+				if ( buf->non_silent() && ( buf->echo == !!echo_phase ) )
509
+				{
510
+					stereo_fixed_t* BLIP_RESTRICT out = (stereo_fixed_t*) &echo [echo_pos];
511
+					int const bass = BLIP_READER_BASS( *buf );
512
+					BLIP_READER_BEGIN( in, *buf );
513
+					BLIP_READER_ADJ_( in, mixer.samples_read );
514
+					fixed_t const vol_0 = buf->vol [0];
515
+					fixed_t const vol_1 = buf->vol [1];
516
+
517
+					int count = unsigned (echo_size - echo_pos) / stereo;
518
+					int remain = pair_count;
519
+					if ( count > remain )
520
+						count = remain;
521
+					do
522
+					{
523
+						remain -= count;
524
+						BLIP_READER_ADJ_( in, count );
525
+
526
+						out += count;
527
+						int offset = -count;
528
+						do
529
+						{
530
+							fixed_t s = BLIP_READER_READ( in );
531
+							BLIP_READER_NEXT_IDX_( in, bass, offset );
532
+
533
+							out [offset] [0] += s * vol_0;
534
+							out [offset] [1] += s * vol_1;
535
+						}
536
+						while ( ++offset );
537
+
538
+						out = (stereo_fixed_t*) echo.begin();
539
+						count = remain;
540
+					}
541
+					while ( remain );
542
+
543
+					BLIP_READER_END( in, *buf );
544
+				}
545
+				buf++;
546
+			}
547
+			while ( --bufs_remain );
548
+		}
549
+
550
+		// add echo
551
+		if ( echo_phase && !no_echo )
552
+		{
553
+			fixed_t const feedback = s.feedback;
554
+			fixed_t const treble   = s.treble;
555
+
556
+			int i = 1;
557
+			do
558
+			{
559
+				fixed_t low_pass = s.low_pass [i];
560
+
561
+				fixed_t* echo_end = &echo [echo_size + i];
562
+				fixed_t const* BLIP_RESTRICT in_pos = &echo [echo_pos + i];
563
+				blargg_long out_offset = echo_pos + i + s.delay [i];
564
+				if ( out_offset >= echo_size )
565
+					out_offset -= echo_size;
566
+				assert( out_offset < echo_size );
567
+				fixed_t* BLIP_RESTRICT out_pos = &echo [out_offset];
568
+
569
+				// break into up to three chunks to avoid having to handle wrap-around
570
+				// in middle of core loop
571
+				int remain = pair_count;
572
+				do
573
+				{
574
+					fixed_t const* pos = in_pos;
575
+					if ( pos < out_pos )
576
+						pos = out_pos;
577
+					int count = blargg_ulong ((char*) echo_end - (char const*) pos) /
578
+							unsigned (stereo * sizeof (fixed_t));
579
+					if ( count > remain )
580
+						count = remain;
581
+					remain -= count;
582
+
583
+					in_pos  += count * stereo;
584
+					out_pos += count * stereo;
585
+					int offset = -count;
586
+					do
587
+					{
588
+						low_pass += FROM_FIXED( in_pos [offset * stereo] - low_pass ) * treble;
589
+						out_pos [offset * stereo] = FROM_FIXED( low_pass ) * feedback;
590
+					}
591
+					while ( ++offset );
592
+
593
+					if (  in_pos >= echo_end )  in_pos -= echo_size;
594
+					if ( out_pos >= echo_end ) out_pos -= echo_size;
595
+				}
596
+				while ( remain );
597
+
598
+				s.low_pass [i] = low_pass;
599
+			}
600
+			while ( --i >= 0 );
601
+		}
602
+	}
603
+	while ( --echo_phase >= 0 );
604
+
605
+	// clamp to 16 bits
606
+	{
607
+		stereo_fixed_t const* BLIP_RESTRICT in = (stereo_fixed_t*) &echo [echo_pos];
608
+		typedef blip_sample_t stereo_blip_sample_t [stereo];
609
+		stereo_blip_sample_t* BLIP_RESTRICT out = (stereo_blip_sample_t*) out_;
610
+		int count = unsigned (echo_size - echo_pos) / (unsigned) stereo;
611
+		int remain = pair_count;
612
+		if ( count > remain )
613
+			count = remain;
614
+		do
615
+		{
616
+			remain -= count;
617
+			in  += count;
618
+			out += count;
619
+			int offset = -count;
620
+			do
621
+			{
622
+				fixed_t in_0 = FROM_FIXED( in [offset] [0] );
623
+				fixed_t in_1 = FROM_FIXED( in [offset] [1] );
624
+
625
+				BLIP_CLAMP( in_0, in_0 );
626
+				out [offset] [0] = (blip_sample_t) in_0;
627
+
628
+				BLIP_CLAMP( in_1, in_1 );
629
+				out [offset] [1] = (blip_sample_t) in_1;
630
+			}
631
+			while ( ++offset );
632
+
633
+			in = (stereo_fixed_t*) echo.begin();
634
+			count = remain;
635
+		}
636
+		while ( remain );
637
+	}
638
+}