Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/quicknes/nes_emu/Nes_Fme7_Apu.cpp
2 views
1
2
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
3
4
#include "Nes_Fme7_Apu.h"
5
6
#include <string.h>
7
8
/* Copyright (C) 2003-2006 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
15
more details. You should have received a copy of the GNU Lesser General
16
Public License along with this module; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18
19
#include "blargg_source.h"
20
21
void Nes_Fme7_Apu::reset()
22
{
23
last_time = 0;
24
25
for ( int i = 0; i < osc_count; i++ )
26
oscs [i].last_amp = 0;
27
28
fme7_apu_state_t* state = this;
29
memset( state, 0, sizeof *state );
30
}
31
32
unsigned char Nes_Fme7_Apu::amp_table [16] =
33
{
34
#define ENTRY( n ) (unsigned char) (n * amp_range + 0.5)
35
ENTRY(0.0000), ENTRY(0.0078), ENTRY(0.0110), ENTRY(0.0156),
36
ENTRY(0.0221), ENTRY(0.0312), ENTRY(0.0441), ENTRY(0.0624),
37
ENTRY(0.0883), ENTRY(0.1249), ENTRY(0.1766), ENTRY(0.2498),
38
ENTRY(0.3534), ENTRY(0.4998), ENTRY(0.7070), ENTRY(1.0000)
39
#undef ENTRY
40
};
41
42
void Nes_Fme7_Apu::run_until( blip_time_t end_time )
43
{
44
require( end_time >= last_time );
45
46
for ( int index = 0; index < osc_count; index++ )
47
{
48
int mode = regs [7] >> index;
49
int vol_mode = regs [010 + index];
50
int volume = amp_table [vol_mode & 0x0f];
51
52
if ( !oscs [index].output )
53
continue;
54
55
// check for unsupported mode
56
#ifndef NDEBUG
57
if ( (mode & 011) <= 001 && vol_mode & 0x1f )
58
dprintf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n",
59
mode, vol_mode & 0x1f );
60
#endif
61
62
if ( (mode & 001) | (vol_mode & 0x10) )
63
volume = 0; // noise and envelope aren't supported
64
65
// period
66
int const period_factor = 16;
67
unsigned period = (regs [index * 2 + 1] & 0x0f) * 0x100 * period_factor +
68
regs [index * 2] * period_factor;
69
if ( period < 50 ) // around 22 kHz
70
{
71
volume = 0;
72
if ( !period ) // on my AY-3-8910A, period doesn't have extra one added
73
period = period_factor;
74
}
75
76
// current amplitude
77
int amp = volume;
78
if ( !phases [index] )
79
amp = 0;
80
int delta = amp - oscs [index].last_amp;
81
if ( delta )
82
{
83
oscs [index].last_amp = amp;
84
synth.offset( last_time, delta, oscs [index].output );
85
}
86
87
blip_time_t time = last_time + delays [index];
88
if ( time < end_time )
89
{
90
Blip_Buffer* const osc_output = oscs [index].output;
91
int delta = amp * 2 - volume;
92
93
if ( volume )
94
{
95
do
96
{
97
delta = -delta;
98
synth.offset_inline( time, delta, osc_output );
99
time += period;
100
}
101
while ( time < end_time );
102
103
oscs [index].last_amp = (delta + volume) >> 1;
104
phases [index] = (delta > 0);
105
}
106
else
107
{
108
// maintain phase when silent
109
int count = (end_time - time + period - 1) / period;
110
phases [index] ^= count & 1;
111
time += (long) count * period;
112
}
113
}
114
115
delays [index] = time - end_time;
116
}
117
118
last_time = end_time;
119
}
120
121
122