1 // Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
3 #include "nes_vrc6_apu.h"
5 /* Copyright (C) 2003-2006 Shay Green. This module is free software; you
6 can redistribute it and/or modify it under the terms of the GNU Lesser
7 General Public License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version. This
9 module is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 details. You should have received a copy of the GNU Lesser General Public
13 License along with this module; if not, write to the Free Software Foundation,
14 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
16 #include "blargg_source.h"
18 void Vrc6_init( struct Nes_Vrc6_Apu
* this )
20 Synth_init( &this->saw_synth
);
21 Synth_init( &this->square_synth
);
23 Vrc6_output( this, NULL
);
24 Vrc6_volume( this, 1.0 );
28 void Vrc6_reset( struct Nes_Vrc6_Apu
* this )
32 for ( i
= 0; i
< vrc6_osc_count
; i
++ )
34 struct Vrc6_Osc
* osc
= &this->oscs
[i
];
36 for ( j
= 0; j
< vrc6_reg_count
; j
++ )
45 void Vrc6_output( struct Nes_Vrc6_Apu
* this, struct Blip_Buffer
* buf
)
48 for ( i
= 0; i
< vrc6_osc_count
; i
++ )
49 Vrc6_osc_output( this, i
, buf
);
52 void run_square( struct Nes_Vrc6_Apu
* this, struct Vrc6_Osc
* osc
, blip_time_t end_time
);
53 void run_saw( struct Nes_Vrc6_Apu
* this, blip_time_t end_time
);
54 void Vrc6_run_until( struct Nes_Vrc6_Apu
* this, blip_time_t time
)
56 require( time
>= this->last_time
);
57 run_square( this, &this->oscs
[0], time
);
58 run_square( this, &this->oscs
[1], time
);
59 run_saw( this, time
);
60 this->last_time
= time
;
63 void Vrc6_write_osc( struct Nes_Vrc6_Apu
* this, blip_time_t time
, int osc_index
, int reg
, int data
)
65 require( (unsigned) osc_index
< vrc6_osc_count
);
66 require( (unsigned) reg
< vrc6_reg_count
);
68 Vrc6_run_until( this, time
);
69 this->oscs
[osc_index
].regs
[reg
] = data
;
72 void Vrc6_end_frame( struct Nes_Vrc6_Apu
* this, blip_time_t time
)
74 if ( time
> this->last_time
)
75 Vrc6_run_until( this, time
);
77 assert( this->last_time
>= time
);
78 this->last_time
-= time
;
81 void run_square( struct Nes_Vrc6_Apu
* this, struct Vrc6_Osc
* osc
, blip_time_t end_time
)
83 struct Blip_Buffer
* output
= osc
->output
;
86 Blip_set_modified( output
);
88 int volume
= osc
->regs
[0] & 15;
89 if ( !(osc
->regs
[2] & 0x80) )
92 int gate
= osc
->regs
[0] & 0x80;
93 int duty
= ((osc
->regs
[0] >> 4) & 7) + 1;
94 int delta
= ((gate
|| osc
->phase
< duty
) ? volume
: 0) - osc
->last_amp
;
95 blip_time_t time
= this->last_time
;
98 osc
->last_amp
+= delta
;
99 Synth_offset( &this->square_synth
, time
, delta
, output
);
104 int period
= Vrc6_osc_period( osc
);
105 if ( volume
&& !gate
&& period
> 4 )
107 if ( time
< end_time
)
109 int phase
= osc
->phase
;
117 osc
->last_amp
= volume
;
118 Synth_offset( &this->square_synth
, time
, volume
, output
);
123 Synth_offset( &this->square_synth
, time
, -volume
, output
);
127 while ( time
< end_time
);
131 osc
->delay
= time
- end_time
;
135 void run_saw( struct Nes_Vrc6_Apu
* this, blip_time_t end_time
)
137 struct Vrc6_Osc
* osc
= &this->oscs
[2];
138 struct Blip_Buffer
* output
= osc
->output
;
141 Blip_set_modified( output
);
144 int amp_step
= osc
->regs
[0] & 0x3F;
145 blip_time_t time
= this->last_time
;
146 int last_amp
= osc
->last_amp
;
147 if ( !(osc
->regs
[2] & 0x80) || !(amp_step
| amp
) )
150 int delta
= (amp
>> 3) - last_amp
;
152 Synth_offset( &this->saw_synth
, time
, delta
, output
);
157 if ( time
< end_time
)
159 int period
= Vrc6_osc_period( osc
) * 2;
160 int phase
= osc
->phase
;
170 int delta
= (amp
>> 3) - last_amp
;
174 Synth_offset( &this->saw_synth
, time
, delta
, output
);
178 amp
= (amp
+ amp_step
) & 0xFF;
180 while ( time
< end_time
);
186 osc
->delay
= time
- end_time
;
189 osc
->last_amp
= last_amp
;