Coverage Report

Created: 2026-09-01 07:42

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.4k
{
24
10.4k
  delay = 0;
25
10.4k
  last_amp = 0;
26
10.4k
  length = 0;
27
10.4k
  output_select = 3;
28
10.4k
  output = outputs [output_select];
29
10.4k
}
30
31
void Gb_Osc::clock_length()
32
20.5M
{
33
20.5M
  if ( (regs [4] & len_enabled_mask) && length )
34
672k
    length--;
35
20.5M
}
36
37
// Gb_Env
38
39
void Gb_Env::clock_envelope()
40
3.85M
{
41
3.85M
  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.85M
}
49
50
bool Gb_Env::write_register( int reg, int data )
51
277k
{
52
277k
  switch ( reg )
53
277k
  {
54
56.7k
  case 1:
55
56.7k
    length = 64 - (regs [1] & 0x3F);
56
56.7k
    break;
57
58
54.4k
  case 2:
59
54.4k
    if ( !(data >> 4) )
60
33.8k
      enabled = false;
61
54.4k
    break;
62
63
55.1k
  case 4:
64
55.1k
    if ( data & trigger )
65
23.6k
    {
66
23.6k
      env_delay = regs [2] & 7;
67
23.6k
      volume = regs [2] >> 4;
68
23.6k
      enabled = true;
69
23.6k
      if ( length == 0 )
70
5.79k
        length = 64;
71
23.6k
      return true;
72
23.6k
    }
73
277k
  }
74
253k
  return false;
75
277k
}
76
77
// Gb_Square
78
79
void Gb_Square::reset()
80
5.21k
{
81
5.21k
  phase = 0;
82
5.21k
  sweep_freq = 0;
83
5.21k
  sweep_delay = 0;
84
5.21k
  Gb_Env::reset();
85
5.21k
}
86
87
void Gb_Square::clock_sweep()
88
2.57M
{
89
2.57M
  int sweep_period = (regs [0] & period_mask) >> 4;
90
2.57M
  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.57M
}
112
113
void Gb_Square::run( blip_time_t time, blip_time_t end_time, int playing )
114
7.02M
{
115
7.02M
  if ( sweep_freq == 2048 )
116
13.3k
    playing = false;
117
118
7.02M
  static unsigned char const table [4] = { 1, 2, 4, 6 };
119
7.02M
  int const duty = table [regs [1] >> 6];
120
7.02M
  int amp = volume & playing;
121
7.02M
  if ( phase >= duty )
122
43.8k
    amp = -amp;
123
124
7.02M
  int frequency = this->frequency();
125
7.02M
  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
7.02M
  {
133
7.02M
    int delta = amp - last_amp;
134
7.02M
    if ( delta )
135
195
    {
136
195
      last_amp = amp;
137
195
      synth->offset( time, delta, output );
138
195
    }
139
7.02M
  }
140
141
7.02M
  time += delay;
142
7.02M
  if ( !playing )
143
7.02M
    time = end_time;
144
145
7.02M
  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
7.02M
  delay = time - end_time;
167
7.02M
}
168
169
// Gb_Noise
170
171
void Gb_Noise::run( blip_time_t time, blip_time_t end_time, int playing )
172
3.44M
{
173
3.44M
  int amp = volume & playing;
174
3.44M
  int tap = 13 - (regs [3] & 8);
175
3.44M
  if ( bits >> tap & 2 )
176
3.44M
    amp = -amp;
177
178
3.44M
  {
179
3.44M
    int delta = amp - last_amp;
180
3.44M
    if ( delta )
181
58
    {
182
58
      last_amp = amp;
183
58
      synth->offset( time, delta, output );
184
58
    }
185
3.44M
  }
186
187
3.44M
  time += delay;
188
3.44M
  if ( !playing )
189
3.44M
    time = end_time;
190
191
3.44M
  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.44M
  delay = time - end_time;
223
3.44M
}
224
225
// Gb_Wave
226
227
inline void Gb_Wave::write_register( int reg, int data )
228
92.8k
{
229
92.8k
  switch ( reg )
230
92.8k
  {
231
19.1k
  case 0:
232
19.1k
    if ( !(data & 0x80) )
233
17.8k
      enabled = false;
234
19.1k
    break;
235
236
17.6k
  case 1:
237
17.6k
    length = 256 - regs [1];
238
17.6k
    break;
239
240
19.3k
  case 2:
241
19.3k
    volume = data >> 5 & 3;
242
19.3k
    break;
243
244
19.1k
  case 4:
245
19.1k
    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
92.8k
  }
253
92.8k
}
254
255
void Gb_Wave::run( blip_time_t time, blip_time_t end_time, int playing )
256
3.97M
{
257
3.97M
  int volume_shift = (volume - 1) & 7; // volume = 0 causes shift = 7
258
3.97M
  int frequency;
259
3.97M
  {
260
3.97M
    int amp = (wave [wave_pos] >> volume_shift & playing) * 2;
261
262
3.97M
    frequency = this->frequency();
263
3.97M
    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.97M
    int delta = amp - last_amp;
270
3.97M
    if ( delta )
271
194
    {
272
194
      last_amp = amp;
273
194
      synth->offset( time, delta, output );
274
194
    }
275
3.97M
  }
276
277
3.97M
  time += delay;
278
3.97M
  if ( !playing )
279
3.93M
    time = end_time;
280
281
3.97M
  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.97M
  delay = time - end_time;
304
3.97M
}
305
306
// Gb_Apu::write_osc
307
308
void Gb_Apu::write_osc( int index, int reg, int data )
309
370k
{
310
370k
  reg -= index * 5;
311
370k
  Gb_Square* sq = &square2;
312
370k
  switch ( index )
313
370k
  {
314
93.3k
  case 0:
315
93.3k
    sq = &square1; // FALLTHRU
316
185k
  case 1:
317
185k
    if ( sq->write_register( reg, data ) && index == 0 )
318
6.49k
    {
319
6.49k
      square1.sweep_freq = square1.frequency();
320
6.49k
      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.49k
    }
326
185k
    break;
327
328
92.8k
  case 2:
329
92.8k
    wave.write_register( reg, data );
330
92.8k
    break;
331
332
92.2k
  case 3:
333
92.2k
    if ( noise.write_register( reg, data ) )
334
8.41k
      noise.bits = 0x7FFF;
335
370k
  }
336
370k
}