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/Gb_Oscs.cpp
Line
Count
Source
1
// Gb_Snd_Emu 0.1.5. http://www.slack.net/~ant/
2
3
#include "Gb_Apu.h"
4
5
#include <string.h>
6
7
/* Copyright (C) 2003-2006 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
// Gb_Osc
21
22
void Gb_Osc::reset()
23
10.2k
{
24
10.2k
  delay = 0;
25
10.2k
  last_amp = 0;
26
10.2k
  length = 0;
27
10.2k
  output_select = 3;
28
10.2k
  output = outputs [output_select];
29
10.2k
}
30
31
void Gb_Osc::clock_length()
32
19.6M
{
33
19.6M
  if ( (regs [4] & len_enabled_mask) && length )
34
670k
    length--;
35
19.6M
}
36
37
// Gb_Env
38
39
void Gb_Env::clock_envelope()
40
3.68M
{
41
3.68M
  if ( env_delay && !--env_delay )
42
36.3k
  {
43
36.3k
    env_delay = regs [2] & 7;
44
36.3k
    int v = volume - 1 + (regs [2] >> 2 & 2);
45
36.3k
    if ( (unsigned) v < 15 )
46
4.24k
      volume = v;
47
36.3k
  }
48
3.68M
}
49
50
bool Gb_Env::write_register( int reg, int data )
51
274k
{
52
274k
  switch ( reg )
53
274k
  {
54
56.1k
  case 1:
55
56.1k
    length = 64 - (regs [1] & 0x3F);
56
56.1k
    break;
57
58
53.7k
  case 2:
59
53.7k
    if ( !(data >> 4) )
60
33.3k
      enabled = false;
61
53.7k
    break;
62
63
54.4k
  case 4:
64
54.4k
    if ( data & trigger )
65
23.1k
    {
66
23.1k
      env_delay = regs [2] & 7;
67
23.1k
      volume = regs [2] >> 4;
68
23.1k
      enabled = true;
69
23.1k
      if ( length == 0 )
70
5.79k
        length = 64;
71
23.1k
      return true;
72
23.1k
    }
73
274k
  }
74
250k
  return false;
75
274k
}
76
77
// Gb_Square
78
79
void Gb_Square::reset()
80
5.10k
{
81
5.10k
  phase = 0;
82
5.10k
  sweep_freq = 0;
83
5.10k
  sweep_delay = 0;
84
5.10k
  Gb_Env::reset();
85
5.10k
}
86
87
void Gb_Square::clock_sweep()
88
2.45M
{
89
2.45M
  int sweep_period = (regs [0] & period_mask) >> 4;
90
2.45M
  if ( sweep_period && sweep_delay && !--sweep_delay )
91
21.3k
  {
92
21.3k
    sweep_delay = sweep_period;
93
21.3k
    regs [3] = sweep_freq & 0xFF;
94
21.3k
    regs [4] = (regs [4] & ~0x07) | (sweep_freq >> 8 & 0x07);
95
96
21.3k
    int offset = sweep_freq >> (regs [0] & shift_mask);
97
21.3k
    if ( regs [0] & 0x08 )
98
19.6k
      offset = -offset;
99
21.3k
    sweep_freq += offset;
100
101
21.3k
    if ( sweep_freq < 0 )
102
0
    {
103
0
      sweep_freq = 0;
104
0
    }
105
21.3k
    else if ( sweep_freq >= 2048 )
106
172
    {
107
172
      sweep_delay = 0; // don't modify channel frequency any further
108
172
      sweep_freq = 2048; // silence sound immediately
109
172
    }
110
21.3k
  }
111
2.45M
}
112
113
void Gb_Square::run( blip_time_t time, blip_time_t end_time, int playing )
114
6.74M
{
115
6.74M
  if ( sweep_freq == 2048 )
116
13.3k
    playing = false;
117
118
6.74M
  static unsigned char const table [4] = { 1, 2, 4, 6 };
119
6.74M
  int const duty = table [regs [1] >> 6];
120
6.74M
  int amp = volume & playing;
121
6.74M
  if ( phase >= duty )
122
43.8k
    amp = -amp;
123
124
6.74M
  int frequency = this->frequency();
125
6.74M
  if ( unsigned (frequency - 1) > 2040 ) // frequency < 1 || frequency > 2041
126
34.5k
  {
127
    // really high frequency results in DC at half volume
128
34.5k
    amp = volume >> 1;
129
34.5k
    playing = false;
130
34.5k
  }
131
132
6.74M
  {
133
6.74M
    int delta = amp - last_amp;
134
6.74M
    if ( delta )
135
195
    {
136
195
      last_amp = amp;
137
195
      synth->offset( time, delta, output );
138
195
    }
139
6.74M
  }
140
141
6.74M
  time += delay;
142
6.74M
  if ( !playing )
143
6.74M
    time = end_time;
144
145
6.74M
  if ( time < end_time )
146
1.46k
  {
147
1.46k
    int const period = (2048 - frequency) * 4;
148
1.46k
    Blip_Buffer* const output = this->output;
149
1.46k
    int phase = this->phase;
150
1.46k
    int delta = amp * 2;
151
1.46k
    do
152
9.81k
    {
153
9.81k
      phase = (phase + 1) & 7;
154
9.81k
      if ( phase == 0 || phase == duty )
155
2.43k
      {
156
2.43k
        delta = -delta;
157
2.43k
        synth->offset_inline( time, delta, output );
158
2.43k
      }
159
9.81k
      time += period;
160
9.81k
    }
161
9.81k
    while ( time < end_time );
162
163
1.46k
    this->phase = phase;
164
1.46k
    last_amp = delta >> 1;
165
1.46k
  }
166
6.74M
  delay = time - end_time;
167
6.74M
}
168
169
// Gb_Noise
170
171
void Gb_Noise::run( blip_time_t time, blip_time_t end_time, int playing )
172
3.30M
{
173
3.30M
  int amp = volume & playing;
174
3.30M
  int tap = 13 - (regs [3] & 8);
175
3.30M
  if ( bits >> tap & 2 )
176
3.30M
    amp = -amp;
177
178
3.30M
  {
179
3.30M
    int delta = amp - last_amp;
180
3.30M
    if ( delta )
181
58
    {
182
58
      last_amp = amp;
183
58
      synth->offset( time, delta, output );
184
58
    }
185
3.30M
  }
186
187
3.30M
  time += delay;
188
3.30M
  if ( !playing )
189
3.30M
    time = end_time;
190
191
3.30M
  if ( time < end_time )
192
1.98k
  {
193
1.98k
    static unsigned char const table [8] = { 8, 16, 32, 48, 64, 80, 96, 112 };
194
1.98k
    int period = table [regs [3] & 7] << (regs [3] >> 4);
195
196
    // keep parallel resampled time to eliminate time conversion in the loop
197
1.98k
    Blip_Buffer* const output = this->output;
198
1.98k
    const blip_resampled_time_t resampled_period =
199
1.98k
        output->resampled_duration( period );
200
1.98k
    blip_resampled_time_t resampled_time = output->resampled_time( time );
201
1.98k
    unsigned bits = this->bits;
202
1.98k
    int delta = amp * 2;
203
204
1.98k
    do
205
65.8k
    {
206
65.8k
      unsigned changed = (bits >> tap) + 1;
207
65.8k
      time += period;
208
65.8k
      bits <<= 1;
209
65.8k
      if ( changed & 2 )
210
32.4k
      {
211
32.4k
        delta = -delta;
212
32.4k
        bits |= 1;
213
32.4k
        synth->offset_resampled( resampled_time, delta, output );
214
32.4k
      }
215
65.8k
      resampled_time += resampled_period;
216
65.8k
    }
217
65.8k
    while ( time < end_time );
218
219
1.98k
    this->bits = bits;
220
1.98k
    last_amp = delta >> 1;
221
1.98k
  }
222
3.30M
  delay = time - end_time;
223
3.30M
}
224
225
// Gb_Wave
226
227
inline void Gb_Wave::write_register( int reg, int data )
228
91.7k
{
229
91.7k
  switch ( reg )
230
91.7k
  {
231
18.9k
  case 0:
232
18.9k
    if ( !(data & 0x80) )
233
17.6k
      enabled = false;
234
18.9k
    break;
235
236
17.3k
  case 1:
237
17.3k
    length = 256 - regs [1];
238
17.3k
    break;
239
240
19.1k
  case 2:
241
19.1k
    volume = data >> 5 & 3;
242
19.1k
    break;
243
244
18.9k
  case 4:
245
18.9k
    if ( data & trigger & regs [0] )
246
936
    {
247
936
      wave_pos = 0;
248
936
      enabled = true;
249
936
      if ( length == 0 )
250
190
        length = 256;
251
936
    }
252
91.7k
  }
253
91.7k
}
254
255
void Gb_Wave::run( blip_time_t time, blip_time_t end_time, int playing )
256
3.83M
{
257
3.83M
  int volume_shift = (volume - 1) & 7; // volume = 0 causes shift = 7
258
3.83M
  int frequency;
259
3.83M
  {
260
3.83M
    int amp = (wave [wave_pos] >> volume_shift & playing) * 2;
261
262
3.83M
    frequency = this->frequency();
263
3.83M
    if ( unsigned (frequency - 1) > 2044 ) // frequency < 1 || frequency > 2045
264
21.4k
    {
265
21.4k
      amp = 30 >> volume_shift & playing;
266
21.4k
      playing = false;
267
21.4k
    }
268
269
3.83M
    int delta = amp - last_amp;
270
3.83M
    if ( delta )
271
194
    {
272
194
      last_amp = amp;
273
194
      synth->offset( time, delta, output );
274
194
    }
275
3.83M
  }
276
277
3.83M
  time += delay;
278
3.83M
  if ( !playing )
279
3.79M
    time = end_time;
280
281
3.83M
  if ( time < end_time )
282
31.0k
  {
283
31.0k
    Blip_Buffer* const output = this->output;
284
31.0k
    int const period = (2048 - frequency) * 2;
285
31.0k
    int wave_pos = (this->wave_pos + 1) & (wave_size - 1);
286
287
31.0k
    do
288
260k
    {
289
260k
      int amp = (wave [wave_pos] >> volume_shift) * 2;
290
260k
      wave_pos = (wave_pos + 1) & (wave_size - 1);
291
260k
      int delta = amp - last_amp;
292
260k
      if ( delta )
293
209k
      {
294
209k
        last_amp = amp;
295
209k
        synth->offset_inline( time, delta, output );
296
209k
      }
297
260k
      time += period;
298
260k
    }
299
260k
    while ( time < end_time );
300
301
31.0k
    this->wave_pos = (wave_pos - 1) & (wave_size - 1);
302
31.0k
  }
303
3.83M
  delay = time - end_time;
304
3.83M
}
305
306
// Gb_Apu::write_osc
307
308
void Gb_Apu::write_osc( int index, int reg, int data )
309
365k
{
310
365k
  reg -= index * 5;
311
365k
  Gb_Square* sq = &square2;
312
365k
  switch ( index )
313
365k
  {
314
92.2k
  case 0:
315
92.2k
    sq = &square1; // FALLTHRU
316
182k
  case 1:
317
182k
    if ( sq->write_register( reg, data ) && index == 0 )
318
6.32k
    {
319
6.32k
      square1.sweep_freq = square1.frequency();
320
6.32k
      if ( (regs [0] & sq->period_mask) && (regs [0] & sq->shift_mask) )
321
678
      {
322
678
        square1.sweep_delay = 1; // cause sweep to recalculate now
323
678
        square1.clock_sweep();
324
678
      }
325
6.32k
    }
326
182k
    break;
327
328
91.7k
  case 2:
329
91.7k
    wave.write_register( reg, data );
330
91.7k
    break;
331
332
91.0k
  case 3:
333
91.0k
    if ( noise.write_register( reg, data ) )
334
8.24k
      noise.bits = 0x7FFF;
335
365k
  }
336
365k
}