Coverage Report

Created: 2026-11-12 07:28

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