annotate src/console/Ay_Apu.cxx @ 3196:0f7180e3b163

alsa-ng: Enforce a minimum buffer size of 500ms.
author William Pitcock <nenolod@atheme.org>
date Sun, 12 Jul 2009 08:30:13 -0500
parents 986f098da058
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
341
986f098da058 [svn] - merge in blargg's changes
nenolod
parents: 316
diff changeset
1 // Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
316
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
2
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
3 #include "Ay_Apu.h"
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
4
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
5 /* Copyright (C) 2006 Shay Green. This module is free software; you
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
6 can redistribute it and/or modify it under the terms of the GNU Lesser
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
7 General Public License as published by the Free Software Foundation; either
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
8 version 2.1 of the License, or (at your option) any later version. This
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
9 module is distributed in the hope that it will be useful, but WITHOUT ANY
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
11 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
12 details. You should have received a copy of the GNU Lesser General Public
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
13 License along with this module; if not, write to the Free Software Foundation,
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
14 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
15
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
16 #include "blargg_source.h"
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
17
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
18 // Emulation inaccuracies:
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
19 // * Noise isn't run when not in use
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
20 // * Changes to envelope and noise periods are delayed until next reload
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
21 // * Super-sonic tone should attenuate output to about 60%, not 50%
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
22
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
23 // Tones above this frequency are treated as disabled tone at half volume.
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
24 // Power of two is more efficient (avoids division).
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
25 unsigned const inaudible_freq = 16384;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
26
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
27 int const period_factor = 16;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
28
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
29 static byte const amp_table [16] =
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
30 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
31 #define ENTRY( n ) byte (n * Ay_Apu::amp_range + 0.5)
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
32 // With channels tied together and 1K resistor to ground (as datasheet recommends),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
33 // output nearly matches logarithmic curve as claimed. Approx. 1.5 dB per step.
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
34 ENTRY(0.000000),ENTRY(0.007813),ENTRY(0.011049),ENTRY(0.015625),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
35 ENTRY(0.022097),ENTRY(0.031250),ENTRY(0.044194),ENTRY(0.062500),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
36 ENTRY(0.088388),ENTRY(0.125000),ENTRY(0.176777),ENTRY(0.250000),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
37 ENTRY(0.353553),ENTRY(0.500000),ENTRY(0.707107),ENTRY(1.000000),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
38
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
39 /*
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
40 // Measured from an AY-3-8910A chip with date code 8611.
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
41
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
42 // Direct voltages without any load (very linear)
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
43 ENTRY(0.000000),ENTRY(0.046237),ENTRY(0.064516),ENTRY(0.089785),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
44 ENTRY(0.124731),ENTRY(0.173118),ENTRY(0.225806),ENTRY(0.329032),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
45 ENTRY(0.360215),ENTRY(0.494624),ENTRY(0.594624),ENTRY(0.672043),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
46 ENTRY(0.766129),ENTRY(0.841935),ENTRY(0.926882),ENTRY(1.000000),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
47 // With only some load
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
48 ENTRY(0.000000),ENTRY(0.011940),ENTRY(0.017413),ENTRY(0.024876),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
49 ENTRY(0.036318),ENTRY(0.054229),ENTRY(0.072637),ENTRY(0.122388),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
50 ENTRY(0.174129),ENTRY(0.239303),ENTRY(0.323881),ENTRY(0.410945),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
51 ENTRY(0.527363),ENTRY(0.651741),ENTRY(0.832338),ENTRY(1.000000),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
52 */
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
53 #undef ENTRY
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
54 };
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
55
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
56 static byte const modes [8] =
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
57 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
58 #define MODE( a0,a1, b0,b1, c0,c1 ) \
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
59 (a0 | a1<<1 | b0<<2 | b1<<3 | c0<<4 | c1<<5)
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
60 MODE( 1,0, 1,0, 1,0 ),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
61 MODE( 1,0, 0,0, 0,0 ),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
62 MODE( 1,0, 0,1, 1,0 ),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
63 MODE( 1,0, 1,1, 1,1 ),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
64 MODE( 0,1, 0,1, 0,1 ),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
65 MODE( 0,1, 1,1, 1,1 ),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
66 MODE( 0,1, 1,0, 0,1 ),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
67 MODE( 0,1, 0,0, 0,0 ),
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
68 };
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
69
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
70 Ay_Apu::Ay_Apu()
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
71 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
72 // build full table of the upper 8 envelope waveforms
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
73 for ( int m = 8; m--; )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
74 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
75 byte* out = env.modes [m];
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
76 int flags = modes [m];
341
986f098da058 [svn] - merge in blargg's changes
nenolod
parents: 316
diff changeset
77 for ( int x = 3; --x >= 0; )
316
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
78 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
79 int amp = flags & 1;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
80 int end = flags >> 1 & 1;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
81 int step = end - amp;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
82 amp *= 15;
341
986f098da058 [svn] - merge in blargg's changes
nenolod
parents: 316
diff changeset
83 for ( int y = 16; --y >= 0; )
316
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
84 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
85 *out++ = amp_table [amp];
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
86 amp += step;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
87 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
88 flags >>= 2;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
89 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
90 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
91
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
92 output( 0 );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
93 volume( 1.0 );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
94 reset();
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
95 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
96
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
97 void Ay_Apu::reset()
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
98 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
99 last_time = 0;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
100 noise.delay = 0;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
101 noise.lfsr = 1;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
102
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
103 osc_t* osc = &oscs [osc_count];
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
104 do
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
105 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
106 osc--;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
107 osc->period = period_factor;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
108 osc->delay = 0;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
109 osc->last_amp = 0;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
110 osc->phase = 0;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
111 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
112 while ( osc != oscs );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
113
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
114 for ( int i = sizeof regs; --i >= 0; )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
115 regs [i] = 0;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
116 regs [7] = 0xFF;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
117 write_data_( 13, 0 );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
118 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
119
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
120 void Ay_Apu::write_data_( int addr, int data )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
121 {
341
986f098da058 [svn] - merge in blargg's changes
nenolod
parents: 316
diff changeset
122 assert( (unsigned) addr < reg_count );
986f098da058 [svn] - merge in blargg's changes
nenolod
parents: 316
diff changeset
123
316
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
124 if ( (unsigned) addr >= 14 )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
125 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
126 #ifdef dprintf
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
127 dprintf( "Wrote to I/O port %02X\n", (int) addr );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
128 #endif
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
129 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
130
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
131 // envelope mode
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
132 if ( addr == 13 )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
133 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
134 if ( !(data & 8) ) // convert modes 0-7 to proper equivalents
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
135 data = (data & 4) ? 15 : 9;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
136 env.wave = env.modes [data - 7];
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
137 env.pos = -48;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
138 env.delay = 0; // will get set to envelope period in run_until()
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
139 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
140 regs [addr] = data;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
141
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
142 // handle period changes accurately
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
143 int i = addr >> 1;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
144 if ( i < osc_count )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
145 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
146 blip_time_t period = (regs [i * 2 + 1] & 0x0F) * (0x100L * period_factor) +
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
147 regs [i * 2] * period_factor;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
148 if ( !period )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
149 period = period_factor;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
150
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
151 // adjust time of next timer expiration based on change in period
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
152 osc_t& osc = oscs [i];
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
153 if ( (osc.delay += period - osc.period) < 0 )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
154 osc.delay = 0;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
155 osc.period = period;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
156 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
157
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
158 // TODO: same as above for envelope timer, and it also has a divide by two after it
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
159 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
160
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
161 int const noise_off = 0x08;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
162 int const tone_off = 0x01;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
163
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
164 void Ay_Apu::run_until( blip_time_t final_end_time )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
165 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
166 require( final_end_time >= last_time );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
167
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
168 // noise period and initial values
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
169 blip_time_t const noise_period_factor = period_factor * 2; // verified
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
170 blip_time_t noise_period = (regs [6] & 0x1F) * noise_period_factor;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
171 if ( !noise_period )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
172 noise_period = noise_period_factor;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
173 blip_time_t const old_noise_delay = noise.delay;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
174 blargg_ulong const old_noise_lfsr = noise.lfsr;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
175
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
176 // envelope period
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
177 blip_time_t const env_period_factor = period_factor * 2; // verified
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
178 blip_time_t env_period = (regs [12] * 0x100L + regs [11]) * env_period_factor;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
179 if ( !env_period )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
180 env_period = env_period_factor; // same as period 1 on my AY chip
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
181 if ( !env.delay )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
182 env.delay = env_period;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
183
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
184 // run each osc separately
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
185 for ( int index = 0; index < osc_count; index++ )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
186 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
187 osc_t* const osc = &oscs [index];
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
188 int osc_mode = regs [7] >> index;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
189
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
190 // output
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
191 Blip_Buffer* const osc_output = osc->output;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
192 if ( !osc_output )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
193 continue;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
194 osc_output->set_modified();
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
195
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
196 // period
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
197 int half_vol = 0;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
198 blip_time_t inaudible_period = (blargg_ulong) (osc_output->clock_rate() +
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
199 inaudible_freq) / (inaudible_freq * 2);
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
200 if ( osc->period <= inaudible_period && !(osc_mode & tone_off) )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
201 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
202 half_vol = 1; // Actually around 60%, but 50% is close enough
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
203 osc_mode |= tone_off;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
204 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
205
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
206 // envelope
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
207 blip_time_t start_time = last_time;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
208 blip_time_t end_time = final_end_time;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
209 int const vol_mode = regs [0x08 + index];
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
210 int volume = amp_table [vol_mode & 0x0F] >> half_vol;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
211 int osc_env_pos = env.pos;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
212 if ( vol_mode & 0x10 )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
213 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
214 volume = env.wave [osc_env_pos] >> half_vol;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
215 // use envelope only if it's a repeating wave or a ramp that hasn't finished
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
216 if ( !(regs [13] & 1) || osc_env_pos < -32 )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
217 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
218 end_time = start_time + env.delay;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
219 if ( end_time >= final_end_time )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
220 end_time = final_end_time;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
221
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
222 //if ( !(regs [12] | regs [11]) )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
223 // dprintf( "Used envelope period 0\n" );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
224 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
225 else if ( !volume )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
226 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
227 osc_mode = noise_off | tone_off;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
228 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
229 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
230 else if ( !volume )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
231 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
232 osc_mode = noise_off | tone_off;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
233 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
234
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
235 // tone time
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
236 blip_time_t const period = osc->period;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
237 blip_time_t time = start_time + osc->delay;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
238 if ( osc_mode & tone_off ) // maintain tone's phase when off
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
239 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
240 blargg_long count = (final_end_time - time + period - 1) / period;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
241 time += count * period;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
242 osc->phase ^= count & 1;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
243 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
244
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
245 // noise time
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
246 blip_time_t ntime = final_end_time;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
247 blargg_ulong noise_lfsr = 1;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
248 if ( !(osc_mode & noise_off) )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
249 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
250 ntime = start_time + old_noise_delay;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
251 noise_lfsr = old_noise_lfsr;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
252 //if ( (regs [6] & 0x1F) == 0 )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
253 // dprintf( "Used noise period 0\n" );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
254 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
255
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
256 // The following efficiently handles several cases (least demanding first):
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
257 // * Tone, noise, and envelope disabled, where channel acts as 4-bit DAC
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
258 // * Just tone or just noise, envelope disabled
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
259 // * Envelope controlling tone and/or noise
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
260 // * Tone and noise disabled, envelope enabled with high frequency
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
261 // * Tone and noise together
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
262 // * Tone and noise together with envelope
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
263
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
264 // This loop only runs one iteration if envelope is disabled. If envelope
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
265 // is being used as a waveform (tone and noise disabled), this loop will
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
266 // still be reasonably efficient since the bulk of it will be skipped.
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
267 while ( 1 )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
268 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
269 // current amplitude
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
270 int amp = 0;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
271 if ( (osc_mode | osc->phase) & 1 & (osc_mode >> 3 | noise_lfsr) )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
272 amp = volume;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
273 {
341
986f098da058 [svn] - merge in blargg's changes
nenolod
parents: 316
diff changeset
274 int delta = amp - osc->last_amp;
986f098da058 [svn] - merge in blargg's changes
nenolod
parents: 316
diff changeset
275 if ( delta )
986f098da058 [svn] - merge in blargg's changes
nenolod
parents: 316
diff changeset
276 {
986f098da058 [svn] - merge in blargg's changes
nenolod
parents: 316
diff changeset
277 osc->last_amp = amp;
986f098da058 [svn] - merge in blargg's changes
nenolod
parents: 316
diff changeset
278 synth_.offset( start_time, delta, osc_output );
986f098da058 [svn] - merge in blargg's changes
nenolod
parents: 316
diff changeset
279 }
316
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
280 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
281
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
282 // Run wave and noise interleved with each catching up to the other.
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
283 // If one or both are disabled, their "current time" will be past end time,
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
284 // so there will be no significant performance hit.
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
285 if ( ntime < end_time || time < end_time )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
286 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
287 // Since amplitude was updated above, delta will always be +/- volume,
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
288 // so we can avoid using last_amp every time to calculate the delta.
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
289 int delta = amp * 2 - volume;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
290 int delta_non_zero = delta != 0;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
291 int phase = osc->phase | (osc_mode & tone_off); assert( tone_off == 0x01 );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
292 do
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
293 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
294 // run noise
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
295 blip_time_t end = end_time;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
296 if ( end_time > time ) end = time;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
297 if ( phase & delta_non_zero )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
298 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
299 while ( ntime <= end ) // must advance *past* time to avoid hang
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
300 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
301 int changed = noise_lfsr + 1;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
302 noise_lfsr = (-(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1);
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
303 if ( changed & 2 )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
304 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
305 delta = -delta;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
306 synth_.offset( ntime, delta, osc_output );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
307 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
308 ntime += noise_period;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
309 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
310 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
311 else
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
312 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
313 // 20 or more noise periods on average for some music
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
314 blargg_long remain = end - ntime;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
315 blargg_long count = remain / noise_period;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
316 if ( remain >= 0 )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
317 ntime += noise_period + count * noise_period;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
318 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
319
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
320 // run tone
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
321 end = end_time;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
322 if ( end_time > ntime ) end = ntime;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
323 if ( noise_lfsr & delta_non_zero )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
324 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
325 while ( time < end )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
326 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
327 delta = -delta;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
328 synth_.offset( time, delta, osc_output );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
329 time += period;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
330 //phase ^= 1;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
331 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
332 //assert( phase == (delta > 0) );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
333 phase = unsigned (-delta) >> (CHAR_BIT * sizeof (unsigned) - 1);
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
334 // (delta > 0)
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
335 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
336 else
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
337 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
338 // loop usually runs less than once
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
339 //SUB_CASE_COUNTER( (time < end) * (end - time + period - 1) / period );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
340
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
341 while ( time < end )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
342 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
343 time += period;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
344 phase ^= 1;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
345 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
346 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
347 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
348 while ( time < end_time || ntime < end_time );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
349
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
350 osc->last_amp = (delta + volume) >> 1;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
351 if ( !(osc_mode & tone_off) )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
352 osc->phase = phase;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
353 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
354
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
355 if ( end_time >= final_end_time )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
356 break; // breaks first time when envelope is disabled
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
357
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
358 // next envelope step
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
359 if ( ++osc_env_pos >= 0 )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
360 osc_env_pos -= 32;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
361 volume = env.wave [osc_env_pos] >> half_vol;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
362
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
363 start_time = end_time;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
364 end_time += env_period;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
365 if ( end_time > final_end_time )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
366 end_time = final_end_time;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
367 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
368 osc->delay = time - final_end_time;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
369
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
370 if ( !(osc_mode & noise_off) )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
371 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
372 noise.delay = ntime - final_end_time;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
373 noise.lfsr = noise_lfsr;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
374 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
375 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
376
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
377 // TODO: optimized saw wave envelope?
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
378
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
379 // maintain envelope phase
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
380 blip_time_t remain = final_end_time - last_time - env.delay;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
381 if ( remain >= 0 )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
382 {
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
383 blargg_long count = (remain + env_period) / env_period;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
384 env.pos += count;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
385 if ( env.pos >= 0 )
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
386 env.pos = (env.pos & 31) - 32;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
387 remain -= count * env_period;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
388 assert( -remain <= env_period );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
389 }
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
390 env.delay = -remain;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
391 assert( env.delay > 0 );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
392 assert( env.pos < 0 );
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
393
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
394 last_time = final_end_time;
fb513e10174e [svn] - merge libconsole-blargg into mainline libconsole:
nenolod
parents:
diff changeset
395 }