Coverage Report

Created: 2026-08-14 07:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/contrib/contrib-build/game-music-emu/gme/Spc_Dsp.cpp
Line
Count
Source
1
// Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/
2
3
#include "Spc_Dsp.h"
4
5
#include "blargg_endian.h"
6
#include <string.h>
7
8
/* Copyright (C) 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
#ifdef BLARGG_ENABLE_OPTIMIZER
22
  #include BLARGG_ENABLE_OPTIMIZER
23
#endif
24
25
#if INT_MAX < 0x7FFFFFFF
26
  #error "Requires that int type have at least 32 bits"
27
#endif
28
29
30
// TODO: add to blargg_endian.h
31
55.3M
#define GET_LE16SA( addr )      ((int16_t) GET_LE16( addr ))
32
221M
#define GET_LE16A( addr )       GET_LE16( addr )
33
55.3M
#define SET_LE16A( addr, data ) SET_LE16( addr, data )
34
35
static uint8_t const initial_regs [Spc_Dsp::register_count] =
36
{
37
  0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80,
38
  0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF,
39
  0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A,
40
  0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF,
41
  0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67,
42
  0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x9C,0x4E,0x7B,0xFF,
43
  0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F,
44
  0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF
45
};
46
47
// if ( io < -32768 ) io = -32768;
48
// if ( io >  32767 ) io =  32767;
49
110M
#define CLAMP16( io )\
50
110M
{\
51
110M
  if ( (int16_t) io != io )\
52
110M
    io = (io >> 31) ^ 0x7FFF;\
53
110M
}
54
55
// Access global DSP register
56
1.06G
#define REG(n)      m.regs [r_##n]
57
58
// Access voice DSP register
59
443M
#define VREG(r,n)   r [v_##n]
60
61
27.6M
#define WRITE_SAMPLES( l, r, out ) \
62
27.6M
{\
63
27.6M
  out [0] = l;\
64
27.6M
  out [1] = r;\
65
27.6M
  out += 2;\
66
27.6M
  if ( out >= m.out_end )\
67
27.6M
  {\
68
17.3k
    check( out == m.out_end );\
69
17.3k
    check( m.out_end != &m.extra [extra_size] || \
70
17.3k
      (m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\
71
17.3k
    out       = m.extra;\
72
17.3k
    m.out_end = &m.extra [extra_size];\
73
17.3k
  }\
74
27.6M
}\
75
76
void Spc_Dsp::set_output( sample_t* out, int size )
77
17.8k
{
78
17.8k
  require( (size & 1) == 0 ); // must be even
79
17.8k
  if ( !out )
80
498
  {
81
498
    out  = m.extra;
82
498
    size = extra_size;
83
498
  }
84
17.8k
  m.out_begin = out;
85
17.8k
  m.out       = out;
86
17.8k
  m.out_end   = out + size;
87
17.8k
}
88
89
// Volume registers and efb are signed! Easy to forget int8_t cast.
90
// Prefixes are to avoid accidental use of locals with same names.
91
92
// Interleved gauss table (to improve cache coherency)
93
// interleved_gauss [i] = gauss [(i & 1) * 256 + 255 - (i >> 1 & 0xFF)]
94
static short const interleved_gauss [512] =
95
{
96
 370,1305, 366,1305, 362,1304, 358,1304, 354,1304, 351,1304, 347,1304, 343,1303,
97
 339,1303, 336,1303, 332,1302, 328,1302, 325,1301, 321,1300, 318,1300, 314,1299,
98
 311,1298, 307,1297, 304,1297, 300,1296, 297,1295, 293,1294, 290,1293, 286,1292,
99
 283,1291, 280,1290, 276,1288, 273,1287, 270,1286, 267,1284, 263,1283, 260,1282,
100
 257,1280, 254,1279, 251,1277, 248,1275, 245,1274, 242,1272, 239,1270, 236,1269,
101
 233,1267, 230,1265, 227,1263, 224,1261, 221,1259, 218,1257, 215,1255, 212,1253,
102
 210,1251, 207,1248, 204,1246, 201,1244, 199,1241, 196,1239, 193,1237, 191,1234,
103
 188,1232, 186,1229, 183,1227, 180,1224, 178,1221, 175,1219, 173,1216, 171,1213,
104
 168,1210, 166,1207, 163,1205, 161,1202, 159,1199, 156,1196, 154,1193, 152,1190,
105
 150,1186, 147,1183, 145,1180, 143,1177, 141,1174, 139,1170, 137,1167, 134,1164,
106
 132,1160, 130,1157, 128,1153, 126,1150, 124,1146, 122,1143, 120,1139, 118,1136,
107
 117,1132, 115,1128, 113,1125, 111,1121, 109,1117, 107,1113, 106,1109, 104,1106,
108
 102,1102, 100,1098,  99,1094,  97,1090,  95,1086,  94,1082,  92,1078,  90,1074,
109
  89,1070,  87,1066,  86,1061,  84,1057,  83,1053,  81,1049,  80,1045,  78,1040,
110
  77,1036,  76,1032,  74,1027,  73,1023,  71,1019,  70,1014,  69,1010,  67,1005,
111
  66,1001,  65, 997,  64, 992,  62, 988,  61, 983,  60, 978,  59, 974,  58, 969,
112
  56, 965,  55, 960,  54, 955,  53, 951,  52, 946,  51, 941,  50, 937,  49, 932,
113
  48, 927,  47, 923,  46, 918,  45, 913,  44, 908,  43, 904,  42, 899,  41, 894,
114
  40, 889,  39, 884,  38, 880,  37, 875,  36, 870,  36, 865,  35, 860,  34, 855,
115
  33, 851,  32, 846,  32, 841,  31, 836,  30, 831,  29, 826,  29, 821,  28, 816,
116
  27, 811,  27, 806,  26, 802,  25, 797,  24, 792,  24, 787,  23, 782,  23, 777,
117
  22, 772,  21, 767,  21, 762,  20, 757,  20, 752,  19, 747,  19, 742,  18, 737,
118
  17, 732,  17, 728,  16, 723,  16, 718,  15, 713,  15, 708,  15, 703,  14, 698,
119
  14, 693,  13, 688,  13, 683,  12, 678,  12, 674,  11, 669,  11, 664,  11, 659,
120
  10, 654,  10, 649,  10, 644,   9, 640,   9, 635,   9, 630,   8, 625,   8, 620,
121
   8, 615,   7, 611,   7, 606,   7, 601,   6, 596,   6, 592,   6, 587,   6, 582,
122
   5, 577,   5, 573,   5, 568,   5, 563,   4, 559,   4, 554,   4, 550,   4, 545,
123
   4, 540,   3, 536,   3, 531,   3, 527,   3, 522,   3, 517,   2, 513,   2, 508,
124
   2, 504,   2, 499,   2, 495,   2, 491,   2, 486,   1, 482,   1, 477,   1, 473,
125
   1, 469,   1, 464,   1, 460,   1, 456,   1, 451,   1, 447,   1, 443,   1, 439,
126
   0, 434,   0, 430,   0, 426,   0, 422,   0, 418,   0, 414,   0, 410,   0, 405,
127
   0, 401,   0, 397,   0, 393,   0, 389,   0, 385,   0, 381,   0, 378,   0, 374,
128
};
129
130
131
//// Counters
132
133
#define RATE( rate, div )\
134
  (rate >= div ? rate / div * 8 - 1 : rate - 1)
135
136
static unsigned const counter_mask [32] =
137
{
138
  RATE(   2,2), RATE(2048,4), RATE(1536,3),
139
  RATE(1280,5), RATE(1024,4), RATE( 768,3),
140
  RATE( 640,5), RATE( 512,4), RATE( 384,3),
141
  RATE( 320,5), RATE( 256,4), RATE( 192,3),
142
  RATE( 160,5), RATE( 128,4), RATE(  96,3),
143
  RATE(  80,5), RATE(  64,4), RATE(  48,3),
144
  RATE(  40,5), RATE(  32,4), RATE(  24,3),
145
  RATE(  20,5), RATE(  16,4), RATE(  12,3),
146
  RATE(  10,5), RATE(   8,4), RATE(   6,3),
147
  RATE(   5,5), RATE(   4,4), RATE(   3,3),
148
                RATE(   2,4),
149
                RATE(   1,4)
150
};
151
#undef RATE
152
153
inline void Spc_Dsp::init_counter()
154
498
{
155
  // counters start out with this synchronization
156
498
  m.counters [0] =     1;
157
498
  m.counters [1] =     0;
158
498
  m.counters [2] =  uMinus(0x20u);
159
498
  m.counters [3] =  0x0B;
160
161
498
  int n = 2;
162
15.9k
  for ( int i = 1; i < 32; i++ )
163
15.4k
  {
164
15.4k
    m.counter_select [i] = &m.counters [n];
165
15.4k
    if ( !--n )
166
4.98k
      n = 3;
167
15.4k
  }
168
498
  m.counter_select [ 0] = &m.counters [0];
169
498
  m.counter_select [30] = &m.counters [2];
170
498
}
171
172
inline void Spc_Dsp::run_counter( int i )
173
83.0M
{
174
83.0M
  int n = m.counters [i];
175
83.0M
  if ( !(n-- & 7) )
176
21.6M
    n -= 6 - i;
177
83.0M
  m.counters [i] = n;
178
83.0M
}
179
180
#define READ_COUNTER( rate )\
181
27.6M
  (*m.counter_select [rate] & counter_mask [rate])
182
183
184
//// Emulation
185
186
void Spc_Dsp::run( int clock_count )
187
18.2k
{
188
18.2k
  int new_phase = m.phase + clock_count;
189
18.2k
  int count = new_phase >> 5;
190
18.2k
  m.phase = new_phase & 31;
191
18.2k
  if ( !count )
192
0
    return;
193
194
18.2k
  uint8_t* const ram = m.ram;
195
#ifdef SPC_ISOLATED_ECHO_BUFFER
196
  uint8_t* const echo_ram = m.echo_ram;
197
#endif
198
18.2k
  uint8_t const* const dir = &ram [REG(dir) * 0x100];
199
18.2k
  int const slow_gaussian = (REG(pmon) >> 1) | REG(non);
200
18.2k
  int const noise_rate = REG(flg) & 0x1F;
201
202
  // Global volume
203
18.2k
  int mvoll = (int8_t) REG(mvoll);
204
18.2k
  int mvolr = (int8_t) REG(mvolr);
205
18.2k
  int evoll = (int8_t) REG(evoll);
206
18.2k
  int evolr = (int8_t) REG(evolr);
207
208
18.2k
  if ( !m.echo_enable)
209
0
  {
210
0
    mvoll = 127;
211
0
    mvolr = 127;
212
0
    evoll = 0;
213
0
    evolr = 0;
214
0
  }
215
216
18.2k
  if ( mvoll * mvolr < m.surround_threshold )
217
0
    mvoll = -mvoll; // eliminate surround
218
219
18.2k
  do
220
27.6M
  {
221
    // KON/KOFF reading
222
27.6M
    if ( (m.every_other_sample ^= 1) != 0 )
223
13.8M
    {
224
13.8M
      m.new_kon &= ~m.kon;
225
13.8M
      m.kon    = m.new_kon;
226
13.8M
      m.t_koff = REG(koff);
227
13.8M
    }
228
229
27.6M
    run_counter( 1 );
230
27.6M
    run_counter( 2 );
231
27.6M
    run_counter( 3 );
232
233
    // Noise
234
27.6M
    if ( !READ_COUNTER( noise_rate ) )
235
0
    {
236
0
      int feedback = (m.noise << 13) ^ (m.noise << 14);
237
0
      m.noise = (feedback & 0x4000) ^ (m.noise >> 1);
238
0
    }
239
240
    // Voices
241
27.6M
    int pmon_input = 0;
242
27.6M
    int main_out_l = 0;
243
27.6M
    int main_out_r = 0;
244
27.6M
    int echo_out_l = 0;
245
27.6M
    int echo_out_r = 0;
246
27.6M
    voice_t* v = m.voices;
247
27.6M
    uint8_t* v_regs = m.regs;
248
27.6M
    int vbit = 1;
249
27.6M
    do
250
221M
    {
251
221M
      #define SAMPLE_PTR(i) GET_LE16A( &dir [VREG(v_regs,srcn) * 4 + i * 2] )
252
253
221M
      int brr_header = ram [v->brr_addr];
254
221M
      int kon_delay = v->kon_delay;
255
256
      // Pitch
257
221M
      int pitch = GET_LE16A( &VREG(v_regs,pitchl) ) & 0x3FFF;
258
221M
      if ( REG(pmon) & vbit )
259
3.19k
        pitch += ((pmon_input >> 5) * pitch) >> 10;
260
261
      // KON phases
262
221M
      if ( --kon_delay >= 0 )
263
0
      {
264
0
        v->kon_delay = kon_delay;
265
266
        // Get ready to start BRR decoding on next sample
267
0
        if ( kon_delay == 4 )
268
0
        {
269
0
          v->brr_addr   = SAMPLE_PTR( 0 );
270
0
          v->brr_offset = 1;
271
0
          v->buf_pos    = v->buf;
272
0
          brr_header    = 0; // header is ignored on this sample
273
0
        }
274
275
        // Envelope is never run during KON
276
0
        v->env        = 0;
277
0
        v->hidden_env = 0;
278
279
        // Disable BRR decoding until last three samples
280
0
        v->interp_pos = (kon_delay & 3 ? 0x4000 : 0);
281
282
        // Pitch is never added during KON
283
0
        pitch = 0;
284
0
      }
285
286
221M
      int env = v->env;
287
288
      // Gaussian interpolation
289
221M
      {
290
221M
        int output = 0;
291
221M
        VREG(v_regs,envx) = (uint8_t) (env >> 4);
292
221M
        if ( env )
293
0
        {
294
          // Make pointers into gaussian based on fractional position between samples
295
0
          int offset = (unsigned) v->interp_pos >> 3 & 0x1FE;
296
0
          short const* fwd = interleved_gauss       + offset;
297
0
          short const* rev = interleved_gauss + 510 - offset; // mirror left half of gaussian
298
299
0
          int const* in = &v->buf_pos [(unsigned) v->interp_pos >> 12];
300
301
0
          if ( !(slow_gaussian & vbit) ) // 99%
302
0
          {
303
            // Faster approximation when exact sample value isn't necessary for pitch mod
304
0
            output = (fwd [0] * in [0] +
305
0
                      fwd [1] * in [1] +
306
0
                      rev [1] * in [2] +
307
0
                      rev [0] * in [3]) >> 11;
308
0
            output = (output * env) >> 11;
309
0
          }
310
0
          else
311
0
          {
312
0
            output = (int16_t) (m.noise * 2);
313
0
            if ( !(REG(non) & vbit) )
314
0
            {
315
0
              output  = (fwd [0] * in [0]) >> 11;
316
0
              output += (fwd [1] * in [1]) >> 11;
317
0
              output += (rev [1] * in [2]) >> 11;
318
0
              output = (int16_t) output;
319
0
              output += (rev [0] * in [3]) >> 11;
320
321
0
              CLAMP16( output );
322
0
              output &= ~1;
323
0
            }
324
0
            output = (output * env) >> 11 & ~1;
325
0
          }
326
327
          // Output
328
0
          int l = output * v->volume [0];
329
0
          int r = output * v->volume [1];
330
331
0
          main_out_l += l;
332
0
          main_out_r += r;
333
334
0
          if ( REG(eon) & vbit )
335
0
          {
336
0
            echo_out_l += l;
337
0
            echo_out_r += r;
338
0
          }
339
0
        }
340
341
221M
        pmon_input = output;
342
221M
        VREG(v_regs,outx) = (uint8_t) (output >> 8);
343
221M
      }
344
345
      // Soft reset or end of sample
346
221M
      if ( REG(flg) & 0x80 || (brr_header & 3) == 1 )
347
5.41k
      {
348
5.41k
        v->env_mode = env_release;
349
5.41k
        env         = 0;
350
5.41k
      }
351
352
221M
      if ( m.every_other_sample )
353
110M
      {
354
        // KOFF
355
110M
        if ( m.t_koff & vbit )
356
0
          v->env_mode = env_release;
357
358
        // KON
359
110M
        if ( m.kon & vbit )
360
0
        {
361
0
          v->kon_delay = 5;
362
0
          v->env_mode  = env_attack;
363
0
          REG(endx) &= ~vbit;
364
0
        }
365
110M
      }
366
367
      // Envelope
368
221M
      if ( !v->kon_delay )
369
221M
      {
370
221M
        if ( v->env_mode == env_release ) // 97%
371
221M
        {
372
221M
          env -= 0x8;
373
221M
          v->env = env;
374
221M
          if ( env <= 0 )
375
221M
          {
376
221M
            v->env = 0;
377
221M
            goto skip_brr; // no BRR decoding for you!
378
221M
          }
379
221M
        }
380
0
        else // 3%
381
0
        {
382
0
          int rate;
383
0
          int const adsr0 = VREG(v_regs,adsr0);
384
0
          int env_data = VREG(v_regs,adsr1);
385
0
          if ( adsr0 >= 0x80 ) // 97% ADSR
386
0
          {
387
0
            if ( v->env_mode > env_decay ) // 89%
388
0
            {
389
0
              env--;
390
0
              env -= env >> 8;
391
0
              rate = env_data & 0x1F;
392
393
              // optimized handling
394
0
              v->hidden_env = env;
395
0
              if ( READ_COUNTER( rate ) )
396
0
                goto exit_env;
397
0
              v->env = env;
398
0
              goto exit_env;
399
0
            }
400
0
            else if ( v->env_mode == env_decay )
401
0
            {
402
0
              env--;
403
0
              env -= env >> 8;
404
0
              rate = (adsr0 >> 3 & 0x0E) + 0x10;
405
0
            }
406
0
            else // env_attack
407
0
            {
408
0
              rate = (adsr0 & 0x0F) * 2 + 1;
409
0
              env += rate < 31 ? 0x20 : 0x400;
410
0
            }
411
0
          }
412
0
          else // GAIN
413
0
          {
414
0
            int mode;
415
0
            env_data = VREG(v_regs,gain);
416
0
            mode = env_data >> 5;
417
0
            if ( mode < 4 ) // direct
418
0
            {
419
0
              env = env_data * 0x10;
420
0
              rate = 31;
421
0
            }
422
0
            else
423
0
            {
424
0
              rate = env_data & 0x1F;
425
0
              if ( mode == 4 ) // 4: linear decrease
426
0
              {
427
0
                env -= 0x20;
428
0
              }
429
0
              else if ( mode < 6 ) // 5: exponential decrease
430
0
              {
431
0
                env--;
432
0
                env -= env >> 8;
433
0
              }
434
0
              else // 6,7: linear increase
435
0
              {
436
0
                env += 0x20;
437
0
                if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 )
438
0
                  env += 0x8 - 0x20; // 7: two-slope linear increase
439
0
              }
440
0
            }
441
0
          }
442
443
          // Sustain level
444
0
          if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay )
445
0
            v->env_mode = env_sustain;
446
447
0
          v->hidden_env = env;
448
449
          // unsigned cast because linear decrease going negative also triggers this
450
0
          if ( (unsigned) env > 0x7FF )
451
0
          {
452
0
            env = (env < 0 ? 0 : 0x7FF);
453
0
            if ( v->env_mode == env_attack )
454
0
              v->env_mode = env_decay;
455
0
          }
456
457
0
          if ( !READ_COUNTER( rate ) )
458
0
            v->env = env; // nothing else is controlled by the counter
459
0
        }
460
221M
      }
461
0
    exit_env:
462
463
0
      {
464
        // Apply pitch
465
0
        int old_pos = v->interp_pos;
466
0
        int interp_pos = (old_pos & 0x3FFF) + pitch;
467
0
        if ( interp_pos > 0x7FFF )
468
0
          interp_pos = 0x7FFF;
469
0
        v->interp_pos = interp_pos;
470
471
        // BRR decode if necessary
472
0
        if ( old_pos >= 0x4000 )
473
0
        {
474
          // Arrange the four input nybbles in 0xABCD order for easy decoding
475
0
          int nybbles = ram [(v->brr_addr + v->brr_offset) & 0xFFFF] * 0x100 +
476
0
              ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
477
478
          // Advance read position
479
0
          int const brr_block_size = 9;
480
0
          int brr_offset = v->brr_offset;
481
0
          if ( (brr_offset += 2) >= brr_block_size )
482
0
          {
483
            // Next BRR block
484
0
            int brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF;
485
0
            assert( brr_offset == brr_block_size );
486
0
            if ( brr_header & 1 )
487
0
            {
488
0
              brr_addr = SAMPLE_PTR( 1 );
489
0
              if ( !v->kon_delay )
490
0
                REG(endx) |= vbit;
491
0
            }
492
0
            v->brr_addr = brr_addr;
493
0
            brr_offset  = 1;
494
0
          }
495
0
          v->brr_offset = brr_offset;
496
497
          // Decode
498
499
          // 0: >>1  1: <<0  2: <<1 ... 12: <<11  13-15: >>4 <<11
500
0
          static unsigned char const shifts [16 * 2] = {
501
0
            13,12,12,12,12,12,12,12,12,12,12, 12, 12, 16, 16, 16,
502
0
             0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 11, 11
503
0
          };
504
0
          int const scale = brr_header >> 4;
505
0
          int const right_shift = shifts [scale];
506
0
          int const left_shift  = shifts [scale + 16];
507
508
          // Write to next four samples in circular buffer
509
0
          int* pos = v->buf_pos;
510
0
          int* end;
511
512
          // Decode four samples
513
0
          for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 )
514
0
          {
515
            // Extract upper nybble and scale appropriately. Every cast is
516
            // necessary to maintain correctness and avoid undef behavior
517
0
            int s = int16_t(uint16_t((int16_t) nybbles >> right_shift) << left_shift);
518
519
            // Apply IIR filter (8 is the most commonly used)
520
0
            int const filter = brr_header & 0x0C;
521
0
            int const p1 = pos [brr_buf_size - 1];
522
0
            int const p2 = pos [brr_buf_size - 2] >> 1;
523
0
            if ( filter >= 8 )
524
0
            {
525
0
              s += p1;
526
0
              s -= p2;
527
0
              if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875
528
0
              {
529
0
                s += p2 >> 4;
530
0
                s += (p1 * -3) >> 6;
531
0
              }
532
0
              else // s += p1 * 0.8984375 - p2 * 0.40625
533
0
              {
534
0
                s += (p1 * -13) >> 7;
535
0
                s += (p2 * 3) >> 4;
536
0
              }
537
0
            }
538
0
            else if ( filter ) // s += p1 * 0.46875
539
0
            {
540
0
              s += p1 >> 1;
541
0
              s += (-p1) >> 5;
542
0
            }
543
544
            // Adjust and write sample
545
0
            CLAMP16( s );
546
0
            s = (int16_t) (s * 2);
547
0
            pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around
548
0
          }
549
550
0
          if ( pos >= &v->buf [brr_buf_size] )
551
0
            pos = v->buf;
552
0
          v->buf_pos = pos;
553
0
        }
554
0
      }
555
221M
skip_brr:
556
      // Next voice
557
221M
      vbit <<= 1;
558
221M
      v_regs += 0x10;
559
221M
      v++;
560
221M
    }
561
221M
    while ( vbit < 0x100 );
562
563
    // Echo position
564
27.6M
    int echo_offset = m.echo_offset;
565
#ifdef SPC_ISOLATED_ECHO_BUFFER
566
    // And here, we win no awards for accuracy, but gain playback of dodgy Super Mario World mod SPCs
567
    uint8_t* const echo_ptr = &echo_ram [(REG(esa) * 0x100 + echo_offset) & 0xFFFF];
568
#else
569
27.6M
    uint8_t* const echo_ptr = &ram [(REG(esa) * 0x100 + echo_offset) & 0xFFFF];
570
27.6M
#endif
571
27.6M
    if ( !echo_offset )
572
27.6M
      m.echo_length = (REG(edl) & 0x0F) * 0x800;
573
27.6M
    echo_offset += 4;
574
27.6M
    if ( echo_offset >= m.echo_length )
575
27.6M
      echo_offset = 0;
576
27.6M
    m.echo_offset = echo_offset;
577
578
    // FIR
579
27.6M
    int echo_in_l = GET_LE16SA( echo_ptr + 0 );
580
27.6M
    int echo_in_r = GET_LE16SA( echo_ptr + 2 );
581
582
27.6M
    int (*echo_hist_pos) [2] = m.echo_hist_pos;
583
27.6M
    if ( ++echo_hist_pos >= &m.echo_hist [echo_hist_size] )
584
3.46M
      echo_hist_pos = m.echo_hist;
585
27.6M
    m.echo_hist_pos = echo_hist_pos;
586
587
27.6M
    echo_hist_pos [0] [0] = echo_hist_pos [8] [0] = echo_in_l;
588
27.6M
    echo_hist_pos [0] [1] = echo_hist_pos [8] [1] = echo_in_r;
589
590
443M
    #define CALC_FIR_( i, in )  ((in) * (int8_t) REG(fir + i * 0x10))
591
27.6M
    echo_in_l = CALC_FIR_( 7, echo_in_l );
592
27.6M
    echo_in_r = CALC_FIR_( 7, echo_in_r );
593
594
387M
    #define CALC_FIR( i, ch )   CALC_FIR_( i, echo_hist_pos [i + 1] [ch] )
595
27.6M
    #define DO_FIR( i )\
596
193M
      echo_in_l += CALC_FIR( i, 0 );\
597
193M
      echo_in_r += CALC_FIR( i, 1 );
598
27.6M
    DO_FIR( 0 );
599
27.6M
    DO_FIR( 1 );
600
27.6M
    DO_FIR( 2 );
601
    #if defined (__MWERKS__) && __MWERKS__ < 0x3200
602
      __eieio(); // keeps compiler from stupidly "caching" things in memory
603
    #endif
604
27.6M
    DO_FIR( 3 );
605
27.6M
    DO_FIR( 4 );
606
27.6M
    DO_FIR( 5 );
607
27.6M
    DO_FIR( 6 );
608
609
    // Echo out
610
27.6M
    if ( !(REG(flg) & 0x20) )
611
27.6M
    {
612
27.6M
      int l = (echo_out_l >> 7) + ((echo_in_l * (int8_t) REG(efb)) >> 14);
613
27.6M
      int r = (echo_out_r >> 7) + ((echo_in_r * (int8_t) REG(efb)) >> 14);
614
615
      // just to help pass more validation tests
616
      #if SPC_MORE_ACCURACY
617
        l &= ~1;
618
        r &= ~1;
619
      #endif
620
621
27.6M
      CLAMP16( l );
622
27.6M
      CLAMP16( r );
623
624
27.6M
      SET_LE16A( echo_ptr + 0, l );
625
27.6M
      SET_LE16A( echo_ptr + 2, r );
626
27.6M
    }
627
628
    // Sound out
629
27.6M
    int l = (main_out_l * mvoll + echo_in_l * evoll) >> 14;
630
27.6M
    int r = (main_out_r * mvolr + echo_in_r * evolr) >> 14;
631
632
27.6M
    CLAMP16( l );
633
27.6M
    CLAMP16( r );
634
635
27.6M
    if ( (REG(flg) & 0x40) )
636
0
    {
637
0
      l = 0;
638
0
      r = 0;
639
0
    }
640
641
27.6M
    sample_t* out = m.out;
642
27.6M
    WRITE_SAMPLES( l, r, out );
643
27.6M
    m.out = out;
644
27.6M
  }
645
27.6M
  while ( --count );
646
18.2k
}
647
648
649
//// Setup
650
651
void Spc_Dsp::mute_voices( int mask )
652
826
{
653
826
  m.mute_mask = mask;
654
7.43k
  for ( int i = 0; i < voice_count; i++ )
655
6.60k
  {
656
6.60k
    m.voices [i].enabled = (mask >> i & 1) - 1;
657
6.60k
    update_voice_vol( i * 0x10 );
658
6.60k
  }
659
826
}
660
661
Spc_Dsp::Spc_Dsp()
662
170
{
663
170
  memset(&m, 0, sizeof(state_t));
664
170
}
665
666
void Spc_Dsp::init( void* ram_64k )
667
170
{
668
170
  m.ram = (uint8_t*) ram_64k;
669
170
  mute_voices( 0 );
670
170
  disable_surround( false );
671
170
  disable_echo( false );
672
170
  set_output( 0, 0 );
673
170
  reset();
674
675
  // be sure this sign-extends
676
170
  blaarg_static_assert( (int16_t) 0x8000 == -0x8000, "This compiler doesn't sign-extend during integer promotion" );
677
678
  // be sure right shift preserves sign
679
170
  blaarg_static_assert( (-1 >> 1) == -1, "This compiler doesn't preserve sign on right-shift" );
680
681
  #ifndef NDEBUG
682
    // check clamp macro
683
    int i;
684
    i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF );
685
    i = -0x8001; CLAMP16( i ); assert( i == -0x8000 );
686
687
    blargg_verify_byte_order();
688
  #endif
689
170
}
690
691
void Spc_Dsp::soft_reset_common()
692
498
{
693
498
  require( m.ram ); // init() must have been called already
694
695
498
  m.noise              = 0x4000;
696
498
  m.echo_hist_pos      = m.echo_hist;
697
498
  m.every_other_sample = 1;
698
498
  m.echo_offset        = 0;
699
498
  m.phase              = 0;
700
701
498
  init_counter();
702
498
}
703
704
void Spc_Dsp::soft_reset()
705
0
{
706
0
  REG(flg) = 0xE0;
707
0
  soft_reset_common();
708
0
}
709
710
void Spc_Dsp::load( uint8_t const regs [register_count] )
711
498
{
712
498
  memcpy( m.regs, regs, sizeof m.regs );
713
498
  memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count );
714
715
  // Internal state
716
498
  int i;
717
4.48k
  for ( i = voice_count; --i >= 0; )
718
3.98k
  {
719
3.98k
    voice_t& v = m.voices [i];
720
3.98k
    v.brr_offset = 1;
721
3.98k
    v.buf_pos    = v.buf;
722
3.98k
  }
723
498
  m.new_kon = REG(kon);
724
725
498
  mute_voices( m.mute_mask );
726
498
  soft_reset_common();
727
498
}
728
729
340
void Spc_Dsp::reset() { load( initial_regs ); }