1 //
2 // /home/ms/source/sidplay/libsidplay/emu/RCS/6581_.cpp,v
3 //
4 // --------------------------------------------------------------------------
5 // Copyright (c) 1994-1997 Michael Schwendt. All rights reserved.
6 //
7 // Contributions:
8 //
9 // Noise generation algorithm is used courtesy of Asger Alstrup Nielsen.
10 // His original publication can be found on the SID home page.
11 //
12 // Noise table optimization proposed by Phillip Wooller. The output of
13 // each table does not differ.
14 //
15 // MOS-8580 R5 combined waveforms recorded by Dennis "Deadman" Lindroos.
16 //
17 // This program is free software; you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation; either version 2 of the License, or
20 // (at your option) any later version.
21 //
22 // This program is distributed in the hope that it will be useful,
23 // but WITHOUT ANY WARRANTY; without even the implied warranty of
24 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 // GNU General Public License for more details.
26 //
27 // You should have received a copy of the GNU General Public License
28 // along with this program; if not, write to the Free Software
29 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 //
31 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
32 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 // DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
35 // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
40 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 // POSSIBILITY OF SUCH DAMAGE.
42 // --------------------------------------------------------------------------
43
44 #include "mytypes.h"
45 #include "myendian.h"
46 #include "sidtune.h"
47 #include "6510_.h"
48 #include "emucfg.h"
49 #include "envelope.h"
50 #include "opstruct.h"
51 #include "samples.h"
52 #include "wave6581.h"
53 #include "wave8580.h"
54
55 extern ubyte masterVolume;
56 extern uword masterVolumeAmplIndex;
57
58 sbyte* ampMod1x8;
59
60 sidOperator optr1, optr2, optr3;
61 // Voice 4 does not use a sidOperator structure.
62 uword voice4_gainLeft, voice4_gainRight;
63
64 static bool doAutoPanning;
65 static bool updateAutoPanning;
66 static uword apCount;
67 static const uword apSpeed = 0x4000;
68
69 bool filterEnabled = true;
70 filterfloat filterTable[0x800];
71 filterfloat bandPassParam[0x800];
72 filterfloat filterResTable[16];
73 static filterfloat filterDy, filterResDy;
74 #define lowPassParam filterTable
75 static ubyte filterType = 0;
76 static ubyte filterCurType = 0;
77 static uword filterValue;
78
79 static ubyte triangleTable[4096];
80 static ubyte sawtoothTable[4096];
81 static ubyte squareTable[2*4096];
82 static ubyte* waveform30;
83 static ubyte* waveform50;
84 static ubyte* waveform60;
85 static ubyte* waveform70;
86 #if defined(LARGE_NOISE_TABLE)
87 static ubyte noiseTableMSB[1<<8];
88 static ubyte noiseTableLSB[1L<<16];
89 #else
90 static ubyte noiseTableMSB[1<<8];
91 static ubyte noiseTableMID[1<<8];
92 static ubyte noiseTableLSB[1<<8];
93 #endif
94
95 static const udword noiseSeed = 0x7ffff8;
96 udword PCMfreq;
97 static udword PCMsid, PCMsidNoise;
98
99 // Song clock speed (PAL or NTSC). Does not affect pitch.
100 static udword sidtuneClockSpeed = 985248;
101
102 // Master clock speed. Affects pitch of SID and CIA samples.
103 udword C64_clockSpeed = 985248;
104 static float C64_fClockSpeed = 985248.4;
105
106 // -------------------------------------------------------------------- Speed
107
108 static uword calls = 50; // calls per second (here a default)
109 static uword fastForwardFactor = 128; // normal speed
110
111 #if defined(DIRECT_FIXPOINT)
112 cpuLword VALUES, VALUESadd, VALUESorg;
113 #else
114 uword VALUES, VALUESorg;
115 udword VALUESadd, VALUEScomma;
116 #endif
117
118 static uword defaultTimer, timer;
119
120
calcValuesPerCall()121 inline void calcValuesPerCall()
122 {
123 udword fastForwardFreq = PCMfreq;
124 if ( fastForwardFactor != 128 )
125 {
126 fastForwardFreq = (PCMfreq * fastForwardFactor) >> 7; // divide by 128
127 }
128 #if defined(DIRECT_FIXPOINT)
129 VALUES.l = ( VALUESorg.l = (((fastForwardFreq<<12)/calls)<<4) );
130 VALUESadd.l = 0;
131 #else
132 VALUES = (VALUESorg = (fastForwardFreq / calls));
133 VALUEScomma = ((fastForwardFreq % calls) * 65536UL) / calls;
134 VALUESadd = 0;
135 #endif
136 }
137
138
sidEmuChangeReplayingSpeed()139 static void sidEmuChangeReplayingSpeed()
140 {
141 calcValuesPerCall();
142 }
143
144 // PAL: Clock speed: 985248.4 Hz
145 // CIA 1 Timer A: $4025 (60 Hz)
146 //
147 // NTSC: Clock speed: 1022727.14 Hz
148 // CIA 1 Timer A: $4295 (60 Hz)
149
sidEmuSetClockSpeed(int clockMode)150 static void sidEmuSetClockSpeed(int clockMode)
151 {
152 switch (clockMode)
153 {
154 case SIDTUNE_CLOCK_NTSC:
155 {
156 C64_clockSpeed = 1022727;
157 C64_fClockSpeed = 1022727.14;
158 break;
159 }
160 case SIDTUNE_CLOCK_PAL:
161 default:
162 {
163 C64_clockSpeed = 985248;
164 C64_fClockSpeed = 985248.4;
165 break;
166 }
167 }
168 }
169
170
sidEmuSetReplayingSpeed(int clockMode,uword callsPerSec)171 void sidEmuSetReplayingSpeed(int clockMode, uword callsPerSec)
172 {
173 switch (clockMode)
174 {
175 case SIDTUNE_CLOCK_NTSC:
176 {
177 sidtuneClockSpeed = 1022727;
178 timer = (defaultTimer = 0x4295);
179 break;
180 }
181 case SIDTUNE_CLOCK_PAL:
182 default:
183 {
184 sidtuneClockSpeed = 985248;
185 timer = (defaultTimer = 0x4025);
186 break;
187 }
188 }
189 switch (callsPerSec)
190 {
191 case SIDTUNE_SPEED_CIA_1A:
192 {
193 timer = readLEword(c64mem2+0xdc04);
194 if (timer < 16) // prevent overflow
195 {
196 timer = defaultTimer;
197 }
198 calls = ( ((sidtuneClockSpeed<<1)/timer) +1) >>1;
199 break;
200 }
201 default:
202 {
203 calls = callsPerSec;
204 break;
205 }
206 }
207 calcValuesPerCall();
208 }
209
210
sidEmuUpdateReplayingSpeed()211 static void sidEmuUpdateReplayingSpeed()
212 {
213 if ( timer != readLEword(c64mem2+0xdc04) )
214 {
215 timer = readLEword(c64mem2+0xdc04);
216 // Prevent overflow
217 if ( timer < 16 )
218 timer = defaultTimer;
219 calls = ( ((sidtuneClockSpeed<<1)/timer) +1) >>1;
220 calcValuesPerCall();
221 }
222 }
223
224 // --------------------------------------------------------------------------
225
waveAdvance(struct sidOperator * pVoice)226 inline void waveAdvance(struct sidOperator* pVoice)
227 {
228 #if defined(DIRECT_FIXPOINT)
229 pVoice->waveStep.l += pVoice->waveStepAdd.l;
230 pVoice->waveStep.w[HI] &= 4095;
231 #else
232 pVoice->waveStepPnt += pVoice->waveStepAddPnt;
233 pVoice->waveStep += ( pVoice->waveStepAdd + ( pVoice->waveStepPnt > 65535 ));
234 pVoice->waveStepPnt &= 0xFFFF;
235 pVoice->waveStep &= 4095;
236 #endif
237 }
238
noiseAdvance(sidOperator * pVoice)239 inline void noiseAdvance(sidOperator* pVoice)
240 {
241 pVoice->noiseStep += pVoice->noiseStepAdd;
242 if (pVoice->noiseStep >= (1L<<20))
243 {
244 pVoice->noiseStep -= (1L<<20);
245 #if defined(DIRECT_FIXPOINT)
246 pVoice->noiseReg.l = (pVoice->noiseReg.l << 1) |
247 (((pVoice->noiseReg.l >> 22) ^ (pVoice->noiseReg.l >> 17)) & 1);
248 #else
249 pVoice->noiseReg = (pVoice->noiseReg << 1) |
250 (((pVoice->noiseReg >> 22) ^ (pVoice->noiseReg >> 17)) & 1);
251 #endif
252 #if defined(DIRECT_FIXPOINT) && defined(LARGE_NOISE_TABLE)
253 pVoice->noiseOutput = (noiseTableLSB[pVoice->noiseReg.w[LO]]
254 |noiseTableMSB[pVoice->noiseReg.w[HI]&0xff]);
255 #elif defined(DIRECT_FIXPOINT)
256 pVoice->noiseOutput = (noiseTableLSB[pVoice->noiseReg.b[LOLO]]
257 |noiseTableMID[pVoice->noiseReg.b[LOHI]]
258 |noiseTableMSB[pVoice->noiseReg.b[HILO]]);
259 #else
260 pVoice->noiseOutput = (noiseTableLSB[pVoice->noiseReg&0xff]
261 |noiseTableMID[pVoice->noiseReg>>8&0xff]
262 |noiseTableMSB[pVoice->noiseReg>>16&0xff]);
263 #endif
264 }
265 }
266
noiseAdvanceHp(sidOperator * pVoice)267 inline void noiseAdvanceHp(sidOperator* pVoice)
268 {
269 udword tmp = pVoice->noiseStepAdd;
270 while (tmp >= (1L<<20))
271 {
272 tmp -= (1L<<20);
273 #if defined(DIRECT_FIXPOINT)
274 pVoice->noiseReg.l = (pVoice->noiseReg.l << 1) |
275 (((pVoice->noiseReg.l >> 22) ^ (pVoice->noiseReg.l >> 17)) & 1);
276 #else
277 pVoice->noiseReg = (pVoice->noiseReg << 1) |
278 (((pVoice->noiseReg >> 22) ^ (pVoice->noiseReg >> 17)) & 1);
279 #endif
280 }
281 pVoice->noiseStep += tmp;
282 if (pVoice->noiseStep >= (1L<<20))
283 {
284 pVoice->noiseStep -= (1L<<20);
285 #if defined(DIRECT_FIXPOINT)
286 pVoice->noiseReg.l = (pVoice->noiseReg.l << 1) |
287 (((pVoice->noiseReg.l >> 22) ^ (pVoice->noiseReg.l >> 17)) & 1);
288 #else
289 pVoice->noiseReg = (pVoice->noiseReg << 1) |
290 (((pVoice->noiseReg >> 22) ^ (pVoice->noiseReg >> 17)) & 1);
291 #endif
292 }
293 #if defined(DIRECT_FIXPOINT) && defined(LARGE_NOISE_TABLE)
294 pVoice->noiseOutput = (noiseTableLSB[pVoice->noiseReg.w[LO]]
295 |noiseTableMSB[pVoice->noiseReg.w[HI]&0xff]);
296 #elif defined(DIRECT_FIXPOINT)
297 pVoice->noiseOutput = (noiseTableLSB[pVoice->noiseReg.b[LOLO]]
298 |noiseTableMID[pVoice->noiseReg.b[LOHI]]
299 |noiseTableMSB[pVoice->noiseReg.b[HILO]]);
300 #else
301 pVoice->noiseOutput = (noiseTableLSB[pVoice->noiseReg&0xff]
302 |noiseTableMID[pVoice->noiseReg>>8&0xff]
303 |noiseTableMSB[pVoice->noiseReg>>16&0xff]);
304 #endif
305 }
306
307
308 #if defined(DIRECT_FIXPOINT)
309 #define triangle triangleTable[pVoice->waveStep.w[HI]]
310 #define sawtooth sawtoothTable[pVoice->waveStep.w[HI]]
311 #define square squareTable[pVoice->waveStep.w[HI] + pVoice->pulseIndex]
312 #define triSaw waveform30[pVoice->waveStep.w[HI]]
313 #define triSquare waveform50[pVoice->waveStep.w[HI] + pVoice->SIDpulseWidth]
314 #define sawSquare waveform60[pVoice->waveStep.w[HI] + pVoice->SIDpulseWidth]
315 #define triSawSquare waveform70[pVoice->waveStep.w[HI] + pVoice->SIDpulseWidth]
316 #else
317 #define triangle triangleTable[pVoice->waveStep]
318 #define sawtooth sawtoothTable[pVoice->waveStep]
319 #define square squareTable[pVoice->waveStep + pVoice->pulseIndex]
320 #define triSaw waveform30[pVoice->waveStep]
321 #define triSquare waveform50[pVoice->waveStep + pVoice->SIDpulseWidth]
322 #define sawSquare waveform60[pVoice->waveStep + pVoice->SIDpulseWidth]
323 #define triSawSquare waveform70[pVoice->waveStep + pVoice->SIDpulseWidth]
324 #endif
325
326
sidMode00(struct sidOperator * pVoice)327 static void sidMode00(struct sidOperator* pVoice) {
328 pVoice->output = (pVoice->filtIO-0x80);
329 waveAdvance(pVoice);
330 }
331
sidModeReal00(struct sidOperator * pVoice)332 static void sidModeReal00(struct sidOperator* pVoice) {
333 pVoice->output = 0;
334 waveAdvance(pVoice);
335 }
336
sidMode10(struct sidOperator * pVoice)337 static void sidMode10(struct sidOperator* pVoice) {
338 pVoice->output = triangle;
339 waveAdvance(pVoice);
340 }
341
sidMode20(struct sidOperator * pVoice)342 static void sidMode20(struct sidOperator* pVoice) {
343 pVoice->output = sawtooth;
344 waveAdvance(pVoice);
345 }
346
sidMode30(struct sidOperator * pVoice)347 static void sidMode30(struct sidOperator* pVoice) {
348 pVoice->output = triSaw;
349 waveAdvance(pVoice);
350 }
351
sidMode40(struct sidOperator * pVoice)352 static void sidMode40(struct sidOperator* pVoice) {
353 pVoice->output = square;
354 waveAdvance(pVoice);
355 }
356
sidMode50(struct sidOperator * pVoice)357 static void sidMode50(struct sidOperator* pVoice) {
358 pVoice->output = triSquare;
359 waveAdvance(pVoice);
360 }
361
sidMode60(struct sidOperator * pVoice)362 static void sidMode60(struct sidOperator* pVoice) {
363 pVoice->output = sawSquare;
364 waveAdvance(pVoice);
365 }
366
sidMode70(struct sidOperator * pVoice)367 static void sidMode70(struct sidOperator* pVoice) {
368 pVoice->output = triSawSquare;
369 waveAdvance(pVoice);
370 }
371
sidMode80(struct sidOperator * pVoice)372 static void sidMode80(struct sidOperator* pVoice) {
373 pVoice->output = pVoice->noiseOutput;
374 waveAdvance(pVoice);
375 noiseAdvance(pVoice);
376 }
377
sidMode80hp(struct sidOperator * pVoice)378 static void sidMode80hp(struct sidOperator* pVoice) {
379 pVoice->output = pVoice->noiseOutput;
380 waveAdvance(pVoice);
381 noiseAdvanceHp(pVoice);
382 }
383
sidModeLock(sidOperator * pVoice)384 static void sidModeLock(sidOperator* pVoice)
385 {
386 pVoice->noiseIsLocked = true;
387 pVoice->output = (pVoice->filtIO-0x80);
388 waveAdvance(pVoice);
389 }
390
391 //
392 //
393 //
394
sidMode14(struct sidOperator * pVoice)395 static void sidMode14(struct sidOperator* pVoice)
396 {
397 #if defined(DIRECT_FIXPOINT)
398 if ( pVoice->modulator->waveStep.w[HI] < 2048 )
399 #else
400 if ( pVoice->modulator->waveStep < 2048 )
401 #endif
402 pVoice->output = triangle;
403 else
404 pVoice->output = 0xFF ^ triangle;
405 waveAdvance(pVoice);
406 }
407
sidMode34(struct sidOperator * pVoice)408 static void sidMode34(struct sidOperator* pVoice) {
409 #if defined(DIRECT_FIXPOINT)
410 if ( pVoice->modulator->waveStep.w[HI] < 2048 )
411 #else
412 if ( pVoice->modulator->waveStep < 2048 )
413 #endif
414 pVoice->output = triSaw;
415 else
416 pVoice->output = 0xFF ^ triSaw;
417 waveAdvance(pVoice);
418 }
419
sidMode54(struct sidOperator * pVoice)420 static void sidMode54(struct sidOperator* pVoice) {
421 #if defined(DIRECT_FIXPOINT)
422 if ( pVoice->modulator->waveStep.w[HI] < 2048 )
423 #else
424 if ( pVoice->modulator->waveStep < 2048 )
425 #endif
426 pVoice->output = triSquare;
427 else
428 pVoice->output = 0xFF ^ triSquare;
429 waveAdvance(pVoice);
430 }
431
sidMode74(struct sidOperator * pVoice)432 static void sidMode74(struct sidOperator* pVoice) {
433 #if defined(DIRECT_FIXPOINT)
434 if ( pVoice->modulator->waveStep.w[HI] < 2048 )
435 #else
436 if ( pVoice->modulator->waveStep < 2048 )
437 #endif
438 pVoice->output = triSawSquare;
439 else
440 pVoice->output = 0xFF ^ triSawSquare;
441 waveAdvance(pVoice);
442 }
443
444 //
445 //
446 //
447
waveCalcCycleLen(struct sidOperator * pVoice)448 inline void waveCalcCycleLen(struct sidOperator* pVoice)
449 {
450 #if defined(DIRECT_FIXPOINT)
451 pVoice->cycleAddLen.w[HI] = 0;
452 pVoice->cycleAddLen.l += pVoice->cycleLen.l;
453 pVoice->cycleLenCount = pVoice->cycleAddLen.w[HI];
454 #else
455 pVoice->cycleAddLenPnt += pVoice->cycleLenPnt;
456 pVoice->cycleLenCount = pVoice->cycleLen + ( pVoice->cycleAddLenPnt > 65535 );
457 pVoice->cycleAddLenPnt &= 0xFFFF;
458 #endif
459 // If we keep the value cycleLen between 1 <= x <= 65535,
460 // the following check is not required.
461 // if ( pVoice->cycleLenCount == 0 )
462 // {
463 //#if defined(DIRECT_FIXPOINT)
464 // pVoice->waveStep.l = 0;
465 //#else
466 // pVoice->waveStep = (pVoice->waveStepPnt = 0);
467 //#endif
468 // pVoice->cycleLenCount = 0;
469 // }
470 // else
471 // {
472 #if defined(DIRECT_FIXPOINT)
473 register uword diff = pVoice->cycleLenCount - pVoice->cycleLen.w[HI];
474 #else
475 register uword diff = pVoice->cycleLenCount - pVoice->cycleLen;
476 #endif
477 if ( pVoice->wavePre[diff].len != pVoice->cycleLenCount )
478 {
479 pVoice->wavePre[diff].len = pVoice->cycleLenCount;
480 #if defined(DIRECT_FIXPOINT)
481 pVoice->wavePre[diff].stp = (pVoice->waveStepAdd.l = (4096UL*65536UL) / pVoice->cycleLenCount);
482 #else
483 pVoice->wavePre[diff].stp = (pVoice->waveStepAdd = 4096UL / pVoice->cycleLenCount);
484 pVoice->wavePre[diff].pnt = (pVoice->waveStepAddPnt = ((4096UL % pVoice->cycleLenCount) * 65536UL) / pVoice->cycleLenCount);
485 #endif
486 }
487 else
488 {
489 #if defined(DIRECT_FIXPOINT)
490 pVoice->waveStepAdd.l = pVoice->wavePre[diff].stp;
491 #else
492 pVoice->waveStepAdd = pVoice->wavePre[diff].stp;
493 pVoice->waveStepAddPnt = pVoice->wavePre[diff].pnt;
494 #endif
495 }
496 // } // see above (opening bracket)
497 }
498
waveCalcFilter(struct sidOperator * pVoice)499 inline void waveCalcFilter(struct sidOperator* pVoice)
500 {
501 if ( pVoice->filtEnabled )
502 {
503 if ( filterType != 0 )
504 {
505 if ( filterType == 0x20 )
506 {
507 pVoice->filtLow += ( pVoice->filtRef * filterDy );
508 filterfloat tmp = (filterfloat)pVoice->filtIO - pVoice->filtLow;
509 tmp -= pVoice->filtRef * filterResDy;
510 pVoice->filtRef += ( tmp * (filterDy) );
511 pVoice->filtIO = (sbyte)(pVoice->filtRef-pVoice->filtLow/4);
512 }
513 else if (filterType == 0x40)
514 {
515 pVoice->filtLow += ( pVoice->filtRef * filterDy * 0.1 );
516 filterfloat tmp = (filterfloat)pVoice->filtIO - pVoice->filtLow;
517 tmp -= pVoice->filtRef * filterResDy;
518 pVoice->filtRef += ( tmp * (filterDy) );
519 filterfloat tmp2 = pVoice->filtRef - pVoice->filtIO/8;
520 if (tmp2 < -128)
521 tmp2 = -128;
522 if (tmp2 > 127)
523 tmp2 = 127;
524 pVoice->filtIO = (sbyte)tmp2;
525 }
526 else
527 {
528 pVoice->filtLow += ( pVoice->filtRef * filterDy );
529 filterfloat sample = pVoice->filtIO;
530 filterfloat sample2 = sample - pVoice->filtLow;
531 int tmp = (int)sample2;
532 sample2 -= pVoice->filtRef * filterResDy;
533 pVoice->filtRef += ( sample2 * filterDy );
534
535 if ( filterType == 0x10 )
536 {
537 pVoice->filtIO = (sbyte)pVoice->filtLow;
538 }
539 else if ( filterType == 0x30 )
540 {
541 pVoice->filtIO = (sbyte)pVoice->filtLow;
542 }
543 else if ( filterType == 0x50 )
544 {
545 pVoice->filtIO = (sbyte)(sample - (tmp >> 1));
546 }
547 else if ( filterType == 0x60 )
548 {
549 pVoice->filtIO = (sbyte)tmp;
550 }
551 else if ( filterType == 0x70 )
552 {
553 pVoice->filtIO = (sbyte)(sample - (tmp >> 1));
554 }
555 }
556 }
557 else // filterType == 0x00
558 {
559 pVoice->filtIO = 0;
560 }
561 }
562 }
563
564
waveCalcMute(struct sidOperator * pVoice)565 sbyte waveCalcMute(struct sidOperator* pVoice)
566 {
567 (*pVoice->ADSRproc)(pVoice); // just process envelope
568 return pVoice->filtIO&pVoice->outputMask;
569 }
570
571
waveCalcNormal(struct sidOperator * pVoice)572 sbyte waveCalcNormal(struct sidOperator* pVoice)
573 {
574 if ( pVoice->cycleLenCount <= 0 )
575 {
576 waveCalcCycleLen(pVoice);
577 if (( pVoice->SIDctrl & 0x40 ) == 0x40 )
578 {
579 pVoice->pulseIndex = pVoice->newPulseIndex;
580 if ( pVoice->pulseIndex > 2048 )
581 {
582 #if defined(DIRECT_FIXPOINT)
583 pVoice->waveStep.w[HI] = 0;
584 #else
585 pVoice->waveStep = 0;
586 #endif
587 }
588 }
589 }
590 (*pVoice->waveProc)(pVoice);
591 pVoice->filtIO = ampMod1x8[(*pVoice->ADSRproc)(pVoice)|pVoice->output];
592 waveCalcFilter(pVoice);
593 return pVoice->filtIO&pVoice->outputMask;
594 }
595
waveCalcRangeCheck(struct sidOperator * pVoice)596 sbyte waveCalcRangeCheck(struct sidOperator* pVoice)
597 {
598 #if defined(DIRECT_FIXPOINT)
599 pVoice->waveStepOld = pVoice->waveStep.w[HI];
600 (*pVoice->waveProc)(pVoice);
601 if (pVoice->waveStep.w[HI] < pVoice->waveStepOld)
602 #else
603 pVoice->waveStepOld = pVoice->waveStep;
604 (*pVoice->waveProc)(pVoice);
605 if (pVoice->waveStep < pVoice->waveStepOld)
606 #endif
607 {
608 // Next step switch back to normal calculation.
609 pVoice->cycleLenCount = 0;
610 pVoice->outProc = &waveCalcNormal;
611 #if defined(DIRECT_FIXPOINT)
612 pVoice->waveStep.w[HI] = 4095;
613 #else
614 pVoice->waveStep = 4095;
615 #endif
616 }
617 pVoice->filtIO = ampMod1x8[(*pVoice->ADSRproc)(pVoice)|pVoice->output];
618 waveCalcFilter(pVoice);
619 return pVoice->filtIO&pVoice->outputMask;
620 }
621
622 // -------------------------------------------------- Operator frame set-up 1
623
sidEmuSet(struct sidOperator * pVoice,uword sidIndex)624 inline void sidEmuSet(struct sidOperator* pVoice, uword sidIndex)
625 {
626 pVoice->SIDfreq = readLEword(c64mem2+sidIndex);
627
628 pVoice->SIDpulseWidth = (readLEword(c64mem2+sidIndex+2) & 0x0FFF);
629 pVoice->newPulseIndex = 4096 - pVoice->SIDpulseWidth;
630 #if defined(DIRECT_FIXPOINT)
631 if ( ((pVoice->waveStep.w[HI] + pVoice->pulseIndex) >= 0x1000)
632 && ((pVoice->waveStep.w[HI] + pVoice->newPulseIndex) >= 0x1000) )
633 {
634 pVoice->pulseIndex = pVoice->newPulseIndex;
635 }
636 else if ( ((pVoice->waveStep.w[HI] + pVoice->pulseIndex) < 0x1000)
637 && ((pVoice->waveStep.w[HI] + pVoice->newPulseIndex) < 0x1000) )
638 {
639 pVoice->pulseIndex = pVoice->newPulseIndex;
640 }
641 #else
642 if ( ((pVoice->waveStep + pVoice->pulseIndex) >= 0x1000)
643 && ((pVoice->waveStep + pVoice->newPulseIndex) >= 0x1000) )
644 {
645 pVoice->pulseIndex = pVoice->newPulseIndex;
646 }
647 else if ( ((pVoice->waveStep + pVoice->pulseIndex) < 0x1000)
648 && ((pVoice->waveStep + pVoice->newPulseIndex) < 0x1000) )
649 {
650 pVoice->pulseIndex = pVoice->newPulseIndex;
651 }
652 #endif
653
654 ubyte enveTemp, newWave, oldWave;
655
656 oldWave = pVoice->SIDctrl;
657 enveTemp = pVoice->ADSRctrl;
658 pVoice->SIDctrl = (newWave = c64mem2[sidIndex +4]);
659
660 if (( newWave & 1 ) ==0 )
661 {
662 if (( oldWave & 1 ) !=0 )
663 enveTemp = ENVE_STARTRELEASE;
664 // else if ( pVoice->gateOnCtrl )
665 // {
666 // enveTemp = ENVE_STARTSHORTATTACK;
667 // }
668 }
669 else if ( pVoice->gateOffCtrl || ((oldWave&1)==0) )
670 {
671 enveTemp = ENVE_STARTATTACK;
672 if (doAutoPanning && updateAutoPanning)
673 {
674 // Swap source/destination position.
675 uword tmp = pVoice->gainSource;
676 pVoice->gainSource = pVoice->gainDest;
677 pVoice->gainDest = tmp;
678 if ((pVoice->gainDest^pVoice->gainSource) == 0)
679 {
680 // Mute voice.
681 pVoice->gainLeft = (pVoice->gainRight = 0x0000+0x80);
682 }
683 else
684 {
685 // Start from middle position.
686 pVoice->gainLeft = pVoice->gainLeftCentered;
687 pVoice->gainRight = pVoice->gainRightCentered;
688 }
689 // Determine direction.
690 // true = L > R : L down, R up
691 // false = L < R : L up, R down
692 pVoice->gainDirec = (pVoice->gainLeft > pVoice->gainDest);
693 }
694 }
695
696 if (doAutoPanning && updateAutoPanning && (enveTemp!=ENVE_STARTATTACK))
697 {
698 if (pVoice->gainDirec)
699 {
700 if (pVoice->gainLeft > pVoice->gainDest)
701 {
702 pVoice->gainLeft -= 0x0100;
703 pVoice->gainRight += 0x0100;
704 }
705 else
706 {
707 // Swap source/destination position.
708 uword tmp = pVoice->gainSource;
709 pVoice->gainSource = pVoice->gainDest;
710 pVoice->gainDest = tmp;
711 // Inverse direction.
712 pVoice->gainDirec = false;
713 }
714 }
715 else
716 {
717 if (pVoice->gainRight > pVoice->gainSource)
718 {
719 pVoice->gainLeft += 0x0100;
720 pVoice->gainRight -= 0x0100;
721 }
722 else
723 {
724 pVoice->gainDirec = true;
725 // Swap source/destination position.
726 uword tmp = pVoice->gainSource;
727 pVoice->gainSource = pVoice->gainDest;
728 // Inverse direction.
729 pVoice->gainDest = tmp;
730 }
731 }
732 }
733
734 if ((( oldWave ^ newWave ) & 0xF0 ) != 0 )
735 {
736 pVoice->cycleLenCount = 0;
737 }
738
739 ubyte ADtemp = c64mem2[sidIndex +5];
740 ubyte SRtemp = c64mem2[sidIndex +6];
741 if ( pVoice->SIDAD != ADtemp )
742 {
743 enveTemp |= ENVE_ALTER;
744 }
745 else if ( pVoice->SIDSR != SRtemp )
746 {
747 enveTemp |= ENVE_ALTER;
748 }
749 pVoice->SIDAD = ADtemp;
750 pVoice->SIDSR = SRtemp;
751 extern const ubyte masterVolumeLevels[16]; // -> envelope.cpp
752 ubyte tmpSusVol = masterVolumeLevels[SRtemp >> 4];
753 if (pVoice->ADSRctrl != ENVE_SUSTAIN) // !!!
754 {
755 pVoice->enveSusVol = tmpSusVol;
756 }
757 else
758 {
759 if ( pVoice->enveSusVol > pVoice->enveVol )
760 pVoice->enveSusVol = 0;
761 else
762 pVoice->enveSusVol = tmpSusVol;
763 }
764
765 extern ptr2sidUwordFunc enveModeTable[]; // -> envelope.cpp
766 pVoice->ADSRproc = enveModeTable[enveTemp>>1]; // shifting out the KEY-bit
767 pVoice->ADSRctrl = enveTemp & (255-ENVE_ALTER-1);
768
769 pVoice->filtEnabled = filterEnabled &&
770 ((c64mem2[0xd417]&pVoice->filtVoiceMask)!=0);
771 }
772
773 // -------------------------------------------------- Operator frame set-up 2
774
775 // MOS-8580, MOS-6581 (no 70)
776 static ptr2sidVoidFunc sidModeNormalTable[16] =
777 {
778 sidMode00, sidMode10, sidMode20, sidMode30, sidMode40, sidMode50, sidMode60, sidMode70,
779 sidMode80, sidModeLock, sidModeLock, sidModeLock, sidModeLock, sidModeLock, sidModeLock, sidModeLock
780 };
781
782 // MOS-8580, MOS-6581 (no 74)
783 static ptr2sidVoidFunc sidModeRingTable[16] =
784 {
785 sidMode00, sidMode14, sidMode00, sidMode34, sidMode00, sidMode54, sidMode00, sidMode74,
786 sidModeLock, sidModeLock, sidModeLock, sidModeLock, sidModeLock, sidModeLock, sidModeLock, sidModeLock
787 };
788
789
sidEmuSet2(struct sidOperator * pVoice)790 inline void sidEmuSet2(struct sidOperator* pVoice)
791 {
792 pVoice->outProc = &waveCalcNormal;
793 pVoice->sync = false;
794
795 if ( (pVoice->SIDfreq < 16)
796 || ((pVoice->SIDctrl & 8) != 0) )
797 {
798 pVoice->outProc = &waveCalcMute;
799 if (pVoice->SIDfreq == 0)
800 {
801 #if defined(DIRECT_FIXPOINT)
802 pVoice->cycleLen.l = (pVoice->cycleAddLen.l = 0);
803 pVoice->waveStep.l = 0;
804 #else
805 pVoice->cycleLen = (pVoice->cycleLenPnt = 0);
806 pVoice->cycleAddLenPnt = 0;
807 pVoice->waveStep = 0;
808 pVoice->waveStepPnt = 0;
809 #endif
810 pVoice->curSIDfreq = (pVoice->curNoiseFreq = 0);
811 pVoice->noiseStepAdd = 0;
812 pVoice->cycleLenCount = 0;
813 }
814 if ((pVoice->SIDctrl & 8) != 0)
815 {
816 if (pVoice->noiseIsLocked)
817 {
818 pVoice->noiseIsLocked = false;
819 #if defined(DIRECT_FIXPOINT)
820 pVoice->noiseReg.l = noiseSeed;
821 #else
822 pVoice->noiseReg = noiseSeed;
823 #endif
824 }
825 }
826 }
827 else
828 {
829 if ( pVoice->curSIDfreq != pVoice->SIDfreq )
830 {
831 pVoice->curSIDfreq = pVoice->SIDfreq;
832 // We keep the value cycleLen between 1 <= x <= 65535.
833 // This makes a range-check in waveCalcCycleLen() unrequired.
834 #if defined(DIRECT_FIXPOINT)
835 pVoice->cycleLen.l = ((PCMsid << 12) / pVoice->SIDfreq) << 4;
836 if (pVoice->cycleLenCount > 0)
837 {
838 waveCalcCycleLen(pVoice);
839 pVoice->outProc = &waveCalcRangeCheck;
840 }
841 #else
842 pVoice->cycleLen = PCMsid / pVoice->SIDfreq;
843 pVoice->cycleLenPnt = (( PCMsid % pVoice->SIDfreq ) * 65536UL ) / pVoice->SIDfreq;
844 if (pVoice->cycleLenCount > 0)
845 {
846 waveCalcCycleLen(pVoice);
847 pVoice->outProc = &waveCalcRangeCheck;
848 }
849 #endif
850 }
851
852 if ((( pVoice->SIDctrl & 0x80 ) == 0x80 ) && ( pVoice->curNoiseFreq != pVoice->SIDfreq ))
853 {
854 pVoice->curNoiseFreq = pVoice->SIDfreq;
855 pVoice->noiseStepAdd = (PCMsidNoise * pVoice->SIDfreq) >> 8;
856 if (pVoice->noiseStepAdd >= (1L<<21))
857 sidModeNormalTable[8] = sidMode80hp;
858 else
859 sidModeNormalTable[8] = sidMode80;
860 }
861
862 if (( pVoice->SIDctrl & 2 ) != 0 )
863 {
864 if ( ( pVoice->modulator->SIDfreq == 0 ) || (( pVoice->modulator->SIDctrl & 8 ) != 0 ) )
865 {
866 ;
867 }
868 else if ( (( pVoice->carrier->SIDctrl & 2 ) != 0 ) &&
869 ( pVoice->modulator->SIDfreq >= ( pVoice->SIDfreq << 1 )) )
870 {
871 ;
872 }
873 else
874 {
875 pVoice->sync = true;
876 }
877 }
878
879 if ((( pVoice->SIDctrl & 0x14 ) == 0x14 ) && ( pVoice->modulator->SIDfreq != 0 ))
880 pVoice->waveProc = sidModeRingTable[pVoice->SIDctrl >> 4];
881 else
882 pVoice->waveProc = sidModeNormalTable[pVoice->SIDctrl >> 4];
883 }
884 }
885
886 // -------------------------------------------------------------- Buffer fill
887
888 static uword toFill;
889 ubyte bufferScale;
890 ubyte playRamRom;
891
892 #if defined(SIDEMU_TIME_COUNT)
893 static udword prevBufferLen; // need for fast_forward time count
894 static udword scaledBufferLen;
895 #endif
896
897 void* fill8bitMono(void*, udword); // only need one fill()-prototype here
898 void* (*sidEmuFillFunc)(void*, udword) = &fill8bitMono; // default
899
900
sidEmuFillBuffer(emuEngine & thisEmu,sidTune & thisTune,void * buffer,udword bufferLen)901 void sidEmuFillBuffer( emuEngine& thisEmu,
902 sidTune& thisTune,
903 void* buffer, udword bufferLen )
904 {
905 // Ensure a sane status of the whole emulator.
906 if ( thisEmu.isReady && thisTune.getStatus() )
907 {
908 // Both, 16-bit and stereo samples take more memory.
909 // Hence fewer samples fit into the buffer.
910 bufferLen >>= bufferScale;
911
912 // Split sample buffer into pieces for # voices:
913 // splitBufferLen * bytesPerSample * voices = bufferLen
914 if ( thisEmu.config.volumeControl == SIDEMU_HWMIXING )
915 {
916 bufferLen >>= 2; // or /4
917 extern udword splitBufferLen;
918 splitBufferLen = bufferLen;
919 }
920
921 #if defined(SIDEMU_TIME_COUNT)
922 if (prevBufferLen != bufferLen)
923 {
924 prevBufferLen = bufferLen;
925 scaledBufferLen = (bufferLen<<7) / fastForwardFactor;
926 }
927 thisEmu.bytesCountTotal += bufferLen;
928 thisEmu.bytesCountSong += scaledBufferLen;
929 while (thisEmu.bytesCountTotal >= thisEmu.config.frequency)
930 {
931 thisEmu.bytesCountTotal -= thisEmu.config.frequency;
932 thisEmu.secondsTotal++;
933 }
934 while (thisEmu.bytesCountSong >= thisEmu.config.frequency)
935 {
936 thisEmu.bytesCountSong -= thisEmu.config.frequency;
937 thisEmu.secondsThisSong++;
938 }
939 #endif
940
941 while ( bufferLen > 0 )
942 {
943 if ( toFill > bufferLen )
944 {
945 buffer = (*sidEmuFillFunc)(buffer, bufferLen);
946 toFill -= bufferLen;
947 bufferLen = 0;
948 }
949 else if ( toFill > 0 )
950 {
951 buffer = (*sidEmuFillFunc)(buffer, toFill);
952 bufferLen -= toFill;
953 toFill = 0;
954 }
955
956 if ( toFill == 0 )
957 {
958 optr3readWave = optr3.output;
959 optr3readEnve = optr3.enveVol;
960
961 uword replayPC = thisTune.getPlayAddr();
962 // playRamRom was set by external player interface.
963 if ( replayPC == 0 )
964 {
965 playRamRom = c64mem1[1];
966 if ((playRamRom & 2) != 0) // isKernal ?
967 {
968 replayPC = readLEword(c64mem1+0x0314); // IRQ
969 }
970 else
971 {
972 replayPC = readLEword(c64mem1+0xfffe); // NMI
973 }
974 }
975 //bool retcode =
976 interpreter(replayPC, playRamRom, 0, 0, 0);
977
978 if (thisTune.getSongSpeed() == SIDTUNE_SPEED_CIA_1A)
979 {
980 sidEmuUpdateReplayingSpeed();
981 }
982
983 masterVolume = ( c64mem2[0xd418] & 15 );
984 masterVolumeAmplIndex = masterVolume << 8;
985
986 optr1.gateOnCtrl = sidKeysOn[4];
987 optr1.gateOffCtrl = sidKeysOff[4];
988 sidEmuSet( &optr1, 0xd400 );
989 optr2.gateOnCtrl = sidKeysOn[4+7];
990 optr2.gateOffCtrl = sidKeysOff[4+7];
991 sidEmuSet( &optr2, 0xd407 );
992 optr3.gateOnCtrl = sidKeysOn[4+14];
993 optr3.gateOffCtrl = sidKeysOff[4+14];
994 sidEmuSet( &optr3, 0xd40e );
995
996 if ((c64mem2[0xd418]&0x80) &&
997 ((c64mem2[0xd417]&optr3.filtVoiceMask)==0))
998 optr3.outputMask = 0; // off
999 else
1000 optr3.outputMask = 0xff; // on
1001
1002 filterType = c64mem2[0xd418] & 0x70;
1003 if (filterType != filterCurType)
1004 {
1005 filterCurType = filterType;
1006 optr1.filtLow = (optr1.filtRef = 0);
1007 optr2.filtLow = (optr2.filtRef = 0);
1008 optr3.filtLow = (optr3.filtRef = 0);
1009 }
1010 if ( filterEnabled )
1011 {
1012 filterValue = 0x7ff & ( (c64mem2[0xd415]&7) | ( (uword)c64mem2[0xd416] << 3 ));
1013 if (filterType == 0x20)
1014 filterDy = bandPassParam[filterValue];
1015 else
1016 filterDy = lowPassParam[filterValue];
1017 filterResDy = filterResTable[c64mem2[0xd417] >> 4] - filterDy;
1018 if ( filterResDy < 1.0 )
1019 filterResDy = 1.0;
1020 }
1021
1022 sidEmuSet2( &optr1 );
1023 sidEmuSet2( &optr2 );
1024 sidEmuSet2( &optr3 );
1025
1026 sampleEmuCheckForInit();
1027
1028 #if defined(DIRECT_FIXPOINT)
1029 VALUESadd.w[HI] = 0;
1030 VALUESadd.l += VALUES.l;
1031 toFill = VALUESadd.w[HI];
1032 #else
1033 udword temp = (VALUESadd + VALUEScomma);
1034 VALUESadd = temp & 0xFFFF;
1035 toFill = VALUES + (temp > 65535);
1036 #endif
1037
1038 // Decide whether to update/start auto-panning.
1039 if ((apCount += timer) >= apSpeed)
1040 {
1041 apCount -= apSpeed;
1042 updateAutoPanning = true;
1043 }
1044 else
1045 {
1046 updateAutoPanning = false;
1047 }
1048
1049 }
1050 } // end while bufferLen
1051 } // end if status
1052 }
1053
1054
sidEmuFastForwardReplay(int percent)1055 bool sidEmuFastForwardReplay( int percent )
1056 {
1057 if (( percent < 1 ) || ( percent > 100 ))
1058 {
1059 return false;
1060 }
1061 else
1062 {
1063 fastForwardFactor = (percent<<7)/100; // we use 2^7 as divider
1064 #if defined(SIDEMU_TIME_COUNT)
1065 scaledBufferLen = (prevBufferLen<<7)/fastForwardFactor;
1066 #endif
1067 calcValuesPerCall();
1068 // Ensure that we calculate at least a single sample per player call.
1069 // Still possible would be also (0 < x < 1.0).
1070 // Else (x = 0) this would cause a deadlock in the buffer fill loop.
1071 #if defined(DIRECT_FIXPOINT)
1072 if (VALUES.w[HI] < 1)
1073 {
1074 VALUES.l = (VALUESorg.l = 0);
1075 VALUES.w[HI] = (VALUESorg.w[HI] = 1);
1076 }
1077 #else
1078 if (VALUES < 1)
1079 {
1080 VALUES = (VALUESorg = 1);
1081 VALUEScomma = 0;
1082 }
1083 #endif
1084 return true;
1085 }
1086 }
1087
1088 // --------------------------------------------------------------------- Init
1089
initWaveformTables(bool isNewSID)1090 void initWaveformTables(bool isNewSID)
1091 {
1092 int i,j;
1093 uword k;
1094
1095 k = 0;
1096 for ( i = 0; i < 256; i++ )
1097 for ( j = 0; j < 8; j++ )
1098 triangleTable[k++] = i;
1099 for ( i = 255; i >= 0; i-- )
1100 for ( j = 0; j < 8; j++ )
1101 triangleTable[k++] = i;
1102
1103 k = 0;
1104 for ( i = 0; i < 256; i++ )
1105 for ( j = 0; j < 16; j++ )
1106 sawtoothTable[k++] = i;
1107
1108 k = 0;
1109 for ( i = 0; i < 4096; i++ )
1110 squareTable[k++] = 0;
1111 for ( i = 0; i < 4096; i++ )
1112 squareTable[k++] = 255;
1113
1114 if ( isNewSID )
1115 {
1116 waveform30 = waveform30_8580;
1117 waveform50 = waveform50_8580;
1118 waveform60 = waveform60_8580;
1119 waveform70 = waveform70_8580;
1120 }
1121 else
1122 {
1123 waveform30 = waveform30_6581;
1124 waveform50 = waveform50_6581;
1125 waveform60 = waveform60_6581;
1126 waveform70 = waveform70_6581; // really audible?
1127 }
1128
1129 for ( i = 4096; i < 8192; i++ )
1130 {
1131 waveform50[i] = 0;
1132 waveform60[i] = 0;
1133 waveform70[i] = 0;
1134 }
1135
1136 if ( isNewSID )
1137 {
1138 sidModeNormalTable[3] = sidMode30;
1139 sidModeNormalTable[6] = sidMode60;
1140 sidModeNormalTable[7] = sidMode70;
1141 sidModeRingTable[7] = sidMode74;
1142 }
1143 else
1144 {
1145 sidModeNormalTable[3] = sidMode30;
1146 sidModeNormalTable[6] = sidMode60;
1147 sidModeNormalTable[7] = sidMode00; // really audible?
1148 sidModeRingTable[7] = sidMode00; //
1149 }
1150
1151 #if defined(LARGE_NOISE_TABLE)
1152 udword ni;
1153 for (ni = 0; ni < sizeof(noiseTableLSB); ni++)
1154 {
1155 noiseTableLSB[ni] = (ubyte)
1156 (((ni >> (13-4)) & 0x10) |
1157 ((ni >> (11-3)) & 0x08) |
1158 ((ni >> (7-2)) & 0x04) |
1159 ((ni >> (4-1)) & 0x02) |
1160 ((ni >> (2-0)) & 0x01));
1161 }
1162 for (ni = 0; ni < sizeof(noiseTableMSB); ni++)
1163 {
1164 noiseTableMSB[ni] = (ubyte)
1165 (((ni << (7-(22-16))) & 0x80) |
1166 ((ni << (6-(20-16))) & 0x40) |
1167 ((ni << (5-(16-16))) & 0x20));
1168 }
1169 #else
1170 udword ni;
1171 for (ni = 0; ni < sizeof(noiseTableLSB); ni++)
1172 {
1173 noiseTableLSB[ni] = (ubyte)
1174 (((ni >> (7-2)) & 0x04) |
1175 ((ni >> (4-1)) & 0x02) |
1176 ((ni >> (2-0)) & 0x01));
1177 }
1178 for (ni = 0; ni < sizeof(noiseTableMID); ni++)
1179 {
1180 noiseTableMID[ni] = (ubyte)
1181 (((ni >> (13-8-4)) & 0x10) |
1182 ((ni << (3-(11-8))) & 0x08));
1183 }
1184 for (ni = 0; ni < sizeof(noiseTableMSB); ni++)
1185 {
1186 noiseTableMSB[ni] = (ubyte)
1187 (((ni << (7-(22-16))) & 0x80) |
1188 ((ni << (6-(20-16))) & 0x40) |
1189 ((ni << (5-(16-16))) & 0x20));
1190 }
1191 #endif
1192 }
1193
1194 // Here set everything that depends on clock speed and frequency.
1195 // The player interface imports this.
sidEmuConfigureClock(int clockSpeed)1196 void sidEmuConfigureClock( int clockSpeed )
1197 {
1198 sidEmuSetClockSpeed( clockSpeed );
1199
1200 PCMsid = (udword)(PCMfreq * (16777216.0 / C64_fClockSpeed));
1201 PCMsidNoise = (udword)((C64_fClockSpeed*256.0)/PCMfreq);
1202
1203 sidEmuChangeReplayingSpeed();
1204 sampleEmuInit();
1205 }
1206
sidEmuConfigure(udword PCMfrequency,bool measuredEnveValues,bool isNewSID,bool emulateFilter,int clockSpeed)1207 void sidEmuConfigure(udword PCMfrequency, bool measuredEnveValues,
1208 bool isNewSID, bool emulateFilter, int clockSpeed)
1209 {
1210 PCMfreq = PCMfrequency;
1211 sidEmuConfigureClock( clockSpeed );
1212
1213 filterEnabled = emulateFilter;
1214 initWaveformTables(isNewSID);
1215
1216 extern void enveEmuInit(udword updateFreq, bool measuredValues);
1217 enveEmuInit(PCMfreq,measuredEnveValues);
1218 }
1219
1220
1221 // Reset.
1222
sidEmuReset()1223 bool sidEmuReset()
1224 {
1225 void clearSidOperator( struct sidOperator* );
1226 extern void enveEmuResetOperator(sidOperator* pVoice);
1227
1228 clearSidOperator( &optr1 );
1229 enveEmuResetOperator( &optr1 );
1230 clearSidOperator( &optr2 );
1231 enveEmuResetOperator( &optr2 );
1232 clearSidOperator( &optr3 );
1233 enveEmuResetOperator( &optr3 );
1234
1235 optr1.modulator = &optr3;
1236 optr3.carrier = &optr1;
1237 optr1.filtVoiceMask = 1;
1238
1239 optr2.modulator = &optr1;
1240 optr1.carrier = &optr2;
1241 optr2.filtVoiceMask = 2;
1242
1243 optr3.modulator = &optr2;
1244 optr2.carrier = &optr3;
1245 optr3.filtVoiceMask = 4;
1246
1247 // Used for detecting changes of the GATE-bit (aka KEY-bit).
1248 // 6510-interpreter clears these before each call.
1249 sidKeysOff[4] = (sidKeysOff[4+7] = (sidKeysOff[4+14] = false));
1250 sidKeysOn[4] = (sidKeysOn[4+7] = (sidKeysOn[4+14] = false));
1251
1252 sampleEmuReset();
1253
1254 filterType = (filterCurType = 0);
1255 filterValue = 0;
1256 filterDy = (filterResDy = 0);
1257
1258 toFill = 0;
1259 #if defined(SIDEMU_TIME_COUNT)
1260 prevBufferLen = (scaledBufferLen = 0);
1261 #endif
1262
1263 return true;
1264 }
1265
1266
clearSidOperator(struct sidOperator * pVoice)1267 void clearSidOperator( struct sidOperator* pVoice )
1268 {
1269 pVoice->SIDfreq = 0;
1270 pVoice->SIDctrl = 0;
1271 pVoice->SIDAD = 0;
1272 pVoice->SIDSR = 0;
1273
1274 pVoice->sync = false;
1275
1276 pVoice->pulseIndex = (pVoice->newPulseIndex = (pVoice->SIDpulseWidth = 0));
1277 pVoice->curSIDfreq = (pVoice->curNoiseFreq = 0);
1278
1279 pVoice->output = (pVoice->noiseOutput = 0);
1280 pVoice->outputMask = 0xff; // on
1281 pVoice->filtIO = 0;
1282
1283 pVoice->filtEnabled = false;
1284 pVoice->filtLow = (pVoice->filtRef = 0);
1285
1286 pVoice->cycleLenCount = 0;
1287 #if defined(DIRECT_FIXPOINT)
1288 pVoice->cycleLen.l = (pVoice->cycleAddLen.l = 0);
1289 #else
1290 pVoice->cycleLen = (pVoice->cycleLenPnt = 0);
1291 pVoice->cycleAddLenPnt = 0;
1292 #endif
1293
1294 extern sbyte waveCalcMute(struct sidOperator*);
1295 pVoice->outProc = &waveCalcMute;
1296
1297 #if defined(DIRECT_FIXPOINT)
1298 pVoice->waveStepAdd.l = (pVoice->waveStep.l = 0);
1299 pVoice->wavePre[0].len = (pVoice->wavePre[0].stp = 0);
1300 pVoice->wavePre[1].len = (pVoice->wavePre[1].stp = 0);
1301 #else
1302 pVoice->waveStepAdd = (pVoice->waveStepAddPnt = 0);
1303 pVoice->waveStep = (pVoice->waveStepPnt = 0);
1304 pVoice->wavePre[0].len = 0;
1305 pVoice->wavePre[0].stp = (pVoice->wavePre[0].pnt = 0);
1306 pVoice->wavePre[1].len = 0;
1307 pVoice->wavePre[1].stp = (pVoice->wavePre[1].pnt = 0);
1308 #endif
1309 pVoice->waveStepOld = 0;
1310
1311 #if defined(DIRECT_FIXPOINT)
1312 pVoice->noiseReg.l = noiseSeed;
1313 #else
1314 pVoice->noiseReg = noiseSeed;
1315 #endif
1316 pVoice->noiseStepAdd = (pVoice->noiseStep = 0);
1317 pVoice->noiseIsLocked = false;
1318 }
1319
1320
sidEmuResetAutoPanning(int autoPanning)1321 void sidEmuResetAutoPanning(int autoPanning)
1322 {
1323 doAutoPanning = (autoPanning!=SIDEMU_NONE);
1324 updateAutoPanning = false;
1325 apCount = 0;
1326 // Auto-panning see sidEmuSet(). Reset volume levels to default.
1327 if (doAutoPanning)
1328 {
1329 optr1.gainLeft = (optr1.gainSource = 0xa080);
1330 optr1.gainRight = (optr1.gainDest = 0x2080);
1331 optr1.gainDirec = (optr1.gainLeft > optr1.gainRight);
1332 optr1.gainLeftCentered = 0x8080; // middle
1333 optr1.gainRightCentered = 0x7f80;
1334
1335 optr2.gainLeft = (optr2.gainSource = 0x2080); // this one mirrored
1336 optr2.gainRight = (optr2.gainDest = 0xa080);
1337 optr2.gainDirec = (optr2.gainLeft > optr2.gainRight);
1338 optr2.gainLeftCentered = 0x8080; // middle
1339 optr2.gainRightCentered = 0x7f80;
1340
1341 optr3.gainLeft = (optr3.gainSource = 0xa080);
1342 optr3.gainRight = (optr3.gainDest = 0x2080);
1343 optr3.gainDirec = (optr3.gainLeft > optr3.gainRight);
1344 optr3.gainLeftCentered = 0x8080; // middle
1345 optr3.gainRightCentered = 0x7f80;
1346
1347 voice4_gainLeft = 0x8080; // middle, not moving
1348 voice4_gainRight = 0x7f80;
1349 }
1350 }
1351
1352
sidEmuSetVoiceVolume(int voice,uword leftLevel,uword rightLevel,uword total)1353 void sidEmuSetVoiceVolume(int voice, uword leftLevel, uword rightLevel, uword total)
1354 {
1355 leftLevel *= total;
1356 leftLevel >>= 8;
1357 rightLevel *= total;
1358 rightLevel >>= 8;
1359 uword centeredLeftLevel = (0x80*total)>>8;
1360 uword centeredRightLevel = (0x7f*total)>>8;
1361 // Signed 8-bit samples will be added to base array index.
1362 // So middle must be 0x80.
1363 // [-80,-81,...,-FE,-FF,0,1,...,7E,7F]
1364 uword leftIndex = 0x0080 + (leftLevel<<8);
1365 uword rightIndex = 0x0080 + (rightLevel<<8);
1366 uword gainLeftCentered = 0x0080 + (centeredLeftLevel<<8);
1367 uword gainRightCentered = 0x0080 + (centeredRightLevel<<8);
1368 switch ( voice )
1369 {
1370 case 1:
1371 {
1372 optr1.gainLeft = leftIndex;
1373 optr1.gainRight = rightIndex;
1374 //
1375 optr1.gainSource = leftIndex;
1376 optr1.gainDest = rightIndex;
1377 optr1.gainLeftCentered = gainLeftCentered;
1378 optr1.gainRightCentered = gainRightCentered;
1379 optr1.gainDirec = (optr1.gainLeft > optr1.gainDest);
1380 break;
1381 }
1382 case 2:
1383 {
1384 optr2.gainLeft = leftIndex;
1385 optr2.gainRight = rightIndex;
1386 //
1387 optr2.gainSource = leftIndex;
1388 optr2.gainDest = rightIndex;
1389 optr2.gainLeftCentered = gainLeftCentered;
1390 optr2.gainRightCentered = gainRightCentered;
1391 optr2.gainDirec = (optr2.gainLeft > optr2.gainDest);
1392 break;
1393 }
1394 case 3:
1395 {
1396 optr3.gainLeft = leftIndex;
1397 optr3.gainRight = rightIndex;
1398 //
1399 optr3.gainSource = leftIndex;
1400 optr3.gainDest = rightIndex;
1401 optr3.gainLeftCentered = gainLeftCentered;
1402 optr3.gainRightCentered = gainRightCentered;
1403 optr3.gainDirec = (optr3.gainLeft > optr3.gainDest);
1404 break;
1405 }
1406 case 4:
1407 {
1408 voice4_gainLeft = leftIndex;
1409 voice4_gainRight = rightIndex;
1410 break;
1411 }
1412 default:
1413 {
1414 break;
1415 }
1416 }
1417 }
1418
1419
sidEmuReturnVoiceVolume(int voice)1420 uword sidEmuReturnVoiceVolume( int voice )
1421 {
1422 uword left = 0;
1423 uword right = 0;
1424 switch ( voice )
1425 {
1426 case 1:
1427 {
1428 left = optr1.gainLeft;
1429 right = optr1.gainRight;
1430 break;
1431 }
1432 case 2:
1433 {
1434 left = optr2.gainLeft;
1435 right = optr2.gainRight;
1436 break;
1437 }
1438 case 3:
1439 {
1440 left = optr3.gainLeft;
1441 right = optr3.gainRight;
1442 break;
1443 }
1444 case 4:
1445 {
1446 left = voice4_gainLeft;
1447 right = voice4_gainRight;
1448 break;
1449 }
1450 default:
1451 {
1452 break;
1453 }
1454 }
1455 return (left&0xff00)|(right>>8);
1456 }
1457