| 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 |
-} |
(As an aside, blargg's code style makes me go blarg myself.)
| ... | ... |
@@ -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 |
} |
| 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 |
+} |