@modplayjs/fmt-sid 0.0.0-stage → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -2
- package/dist/c64.d.ts +8 -0
- package/dist/c64.d.ts.map +1 -0
- package/dist/c64.js +325 -0
- package/dist/c64.js.map +1 -0
- package/dist/c64types.d.ts +209 -0
- package/dist/c64types.d.ts.map +1 -0
- package/dist/c64types.js +181 -0
- package/dist/c64types.js.map +1 -0
- package/dist/cia.d.ts +19 -0
- package/dist/cia.d.ts.map +1 -0
- package/dist/cia.js +160 -0
- package/dist/cia.js.map +1 -0
- package/dist/combiwaves.d.ts +9 -0
- package/dist/combiwaves.d.ts.map +1 -0
- package/dist/combiwaves.js +533 -0
- package/dist/combiwaves.js.map +1 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +23 -0
- package/dist/config.js.map +1 -0
- package/dist/cpu.d.ts +12 -0
- package/dist/cpu.d.ts.map +1 -0
- package/dist/cpu.js +848 -0
- package/dist/cpu.js.map +1 -0
- package/dist/filtercurves.d.ts +13 -0
- package/dist/filtercurves.d.ts.map +1 -0
- package/dist/filtercurves.js +546 -0
- package/dist/filtercurves.js.map +1 -0
- package/dist/host.d.ts +4 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +14 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/instance.d.ts +119 -0
- package/dist/instance.d.ts.map +1 -0
- package/dist/instance.js +51 -0
- package/dist/instance.js.map +1 -0
- package/dist/loader.d.ts +26 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +383 -0
- package/dist/loader.js.map +1 -0
- package/dist/mem.d.ts +30 -0
- package/dist/mem.d.ts.map +1 -0
- package/dist/mem.js +187 -0
- package/dist/mem.js.map +1 -0
- package/dist/psiddigi.d.ts +3 -0
- package/dist/psiddigi.d.ts.map +1 -0
- package/dist/psiddigi.js +73 -0
- package/dist/psiddigi.js.map +1 -0
- package/dist/settings.d.ts +41 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +64 -0
- package/dist/settings.js.map +1 -0
- package/dist/sid.d.ts +21 -0
- package/dist/sid.d.ts.map +1 -0
- package/dist/sid.js +78 -0
- package/dist/sid.js.map +1 -0
- package/dist/sidadsr.d.ts +9 -0
- package/dist/sidadsr.d.ts.map +1 -0
- package/dist/sidadsr.js +105 -0
- package/dist/sidadsr.js.map +1 -0
- package/dist/sidoscwaves.d.ts +15 -0
- package/dist/sidoscwaves.d.ts.map +1 -0
- package/dist/sidoscwaves.js +475 -0
- package/dist/sidoscwaves.js.map +1 -0
- package/dist/sidoutputs.d.ts +17 -0
- package/dist/sidoutputs.d.ts.map +1 -0
- package/dist/sidoutputs.js +185 -0
- package/dist/sidoutputs.js.map +1 -0
- package/dist/sidplugin.d.ts +18 -0
- package/dist/sidplugin.d.ts.map +1 -0
- package/dist/sidplugin.js +174 -0
- package/dist/sidplugin.js.map +1 -0
- package/dist/sidrouting.d.ts +8 -0
- package/dist/sidrouting.d.ts.map +1 -0
- package/dist/sidrouting.js +560 -0
- package/dist/sidrouting.js.map +1 -0
- package/dist/sidseek.d.ts +8 -0
- package/dist/sidseek.d.ts.map +1 -0
- package/dist/sidseek.js +60 -0
- package/dist/sidseek.js.map +1 -0
- package/dist/sincwindow.d.ts +3 -0
- package/dist/sincwindow.d.ts.map +1 -0
- package/dist/sincwindow.js +78 -0
- package/dist/sincwindow.js.map +1 -0
- package/dist/songlengths.d.ts +20 -0
- package/dist/songlengths.d.ts.map +1 -0
- package/dist/songlengths.js +81 -0
- package/dist/songlengths.js.map +1 -0
- package/dist/vic.d.ts +14 -0
- package/dist/vic.d.ts.map +1 -0
- package/dist/vic.js +63 -0
- package/dist/vic.js.map +1 -0
- package/package.json +48 -4
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
// Copyright (c) 2026 Bitti09 — modplayjs contributors
|
|
3
|
+
// Ported from: cRSID 1.58 libcRSID/C64/SID_Outputs.c — SID filter, $D418
|
|
4
|
+
// volume-register digi, and output/mixing stages.
|
|
5
|
+
// (c) Hermit (Mihaly Horvath), license: WTF ("do what the frick you want").
|
|
6
|
+
import { CRSID_FILTERTABLE_RESOLUTION, CRSID_OVERSAMPLING_FILTERTABLE_RESOLUTION, } from './config.js';
|
|
7
|
+
import { CRAudioLevels } from './c64types.js';
|
|
8
|
+
import { cRSID_C64 } from './instance.js';
|
|
9
|
+
import { CRSID_CutoffMul8580_44100Hz, CRSID_CutoffMul6581_44100Hz, CRSID_CutoffMul8580_OverSampleRate, CRSID_CutoffMul6581_OverSampleRate, CRSID_Resonances8580, CRSID_Resonances6581, } from './filtercurves.js';
|
|
10
|
+
// Specs (SID_Outputs.c:5-21)
|
|
11
|
+
const FRACTIONAL_BITS = 12;
|
|
12
|
+
const FRACTIONAL_SHIFTS = FRACTIONAL_BITS;
|
|
13
|
+
const CRSID_FILTERTABLE_SHIFTS = CRSID_FILTERTABLE_RESOLUTION;
|
|
14
|
+
const CRSID_FILTERTABLE_MAGNITUDE = 1 << CRSID_FILTERTABLE_RESOLUTION;
|
|
15
|
+
const CHANNELS = 3 + 1, VOLUME_MAX = 0xf;
|
|
16
|
+
const D418_DIGI_VOL = 1 * 16;
|
|
17
|
+
const D418_DIGI_MUL = D418_DIGI_VOL / CRAudioLevels.CRSID_WAVGEN_PREDIV; // digi-channel is counted too as full-volume 4th channel in attenuation/volume vs SIDcount
|
|
18
|
+
const SID_CUTOFF_BITS = 11;
|
|
19
|
+
const SID_CUTOFF_RANGE = 1 << SID_CUTOFF_BITS;
|
|
20
|
+
const SID_CUTOFF_MAX = SID_CUTOFF_RANGE - 1;
|
|
21
|
+
const OFF3_BITVAL = 0x80, HIGHPASS_BITVAL = 0x40, BANDPASS_BITVAL = 0x20, LOWPASS_BITVAL = 0x10;
|
|
22
|
+
void CHANNELS;
|
|
23
|
+
void VOLUME_MAX;
|
|
24
|
+
void OFF3_BITVAL;
|
|
25
|
+
void CRSID_FILTERTABLE_SHIFTS;
|
|
26
|
+
/** C integer division (truncates toward zero; JS `/` is not integer and
|
|
27
|
+
* `Math.floor` rounds down — not the same for negative operands). */
|
|
28
|
+
function divTrunc(a, b) {
|
|
29
|
+
return Math.trunc(a / b);
|
|
30
|
+
}
|
|
31
|
+
/** cRSID_emulateSIDoutputStage (SID_Outputs.c:23-101) — filter + output-
|
|
32
|
+
* mixing (main-volume / attenuator) stage. */
|
|
33
|
+
export function cRSID_emulateSIDoutputStage(C64, SID) {
|
|
34
|
+
const W = C64.IObankWR;
|
|
35
|
+
let Tmp;
|
|
36
|
+
let FilterOutput;
|
|
37
|
+
let Cutoff;
|
|
38
|
+
let Resonance;
|
|
39
|
+
const FilterSwitchReso = W[SID.BasePtr + 0x17];
|
|
40
|
+
const VolumeBand = W[SID.BasePtr + 0x18];
|
|
41
|
+
Cutoff = (W[SID.BasePtr + 0x16] << 3) + (W[SID.BasePtr + 0x15] & 7);
|
|
42
|
+
Resonance = FilterSwitchReso >> 4;
|
|
43
|
+
const NonFilted = SID.NonFiltedSample;
|
|
44
|
+
const FilterInput = SID.FilterInputSample;
|
|
45
|
+
// Filter
|
|
46
|
+
FilterOutput = 0;
|
|
47
|
+
// if ( CALMLY (!nofilter) ) {
|
|
48
|
+
if (SID.ChipModel === 8580) {
|
|
49
|
+
Cutoff = CRSID_CutoffMul8580_44100Hz[Cutoff];
|
|
50
|
+
Resonance = CRSID_Resonances8580[Resonance];
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// 6581
|
|
54
|
+
Cutoff += Math.imul(FilterInput, 105) >> 16; // MOSFET-VCR control-voltage calculation (resistance-modulation aka 6581 filter distortion) emulation
|
|
55
|
+
if (Cutoff > SID_CUTOFF_MAX)
|
|
56
|
+
Cutoff = SID_CUTOFF_MAX;
|
|
57
|
+
else if (Cutoff < 0)
|
|
58
|
+
Cutoff = 0; // can really go below 0 when FilterInput is negative
|
|
59
|
+
Cutoff = CRSID_CutoffMul6581_44100Hz[Cutoff];
|
|
60
|
+
Resonance = CRSID_Resonances6581[Resonance];
|
|
61
|
+
}
|
|
62
|
+
// shifting negative integers in C is implementation-dependent, so using
|
|
63
|
+
// normal division by power of 2, that might luckily be optimized as
|
|
64
|
+
// arithmetic-shift by the compiler
|
|
65
|
+
Tmp = FilterInput + divTrunc(SID.PrevBandPass * Resonance, CRSID_FILTERTABLE_MAGNITUDE) + SID.PrevLowPass;
|
|
66
|
+
if (VolumeBand & HIGHPASS_BITVAL)
|
|
67
|
+
FilterOutput -= Tmp;
|
|
68
|
+
Tmp = SID.PrevBandPass - divTrunc(Tmp * Cutoff, CRSID_FILTERTABLE_MAGNITUDE); // >> CRSID_FILTERTABLE_SHIFTS ); //12 );
|
|
69
|
+
SID.PrevBandPass = Tmp;
|
|
70
|
+
if (VolumeBand & BANDPASS_BITVAL)
|
|
71
|
+
FilterOutput -= Tmp;
|
|
72
|
+
Tmp = SID.PrevLowPass + divTrunc(Tmp * Cutoff, CRSID_FILTERTABLE_MAGNITUDE); // >> CRSID_FILTERTABLE_SHIFTS ); // 12 );
|
|
73
|
+
SID.PrevLowPass = Tmp;
|
|
74
|
+
if (VolumeBand & LOWPASS_BITVAL)
|
|
75
|
+
FilterOutput += Tmp;
|
|
76
|
+
// }
|
|
77
|
+
// Output-mixing (main-volume / attenuator) stage
|
|
78
|
+
//
|
|
79
|
+
// For $D418 volume-register digi playback: an AC / DC separation for $D418
|
|
80
|
+
// value at low (20Hz or so) cutoff-frequency, sending AC (highpass) value
|
|
81
|
+
// to a 4th 'digi' channel mixed to the master output, and set ONLY the DC
|
|
82
|
+
// (lowpass) value to the volume-control. This solved 2 issues: Thanks to
|
|
83
|
+
// the lowpass filtering of the volume-control, SID tunes where digi is
|
|
84
|
+
// played together with normal SID channels, won't sound distorted anymore,
|
|
85
|
+
// and the volume-clicks disappear when setting SID-volume. (This is useful
|
|
86
|
+
// for fade-in/out tunes like Hades Nebula, where clicking ruins the intro.)
|
|
87
|
+
let MainVolume;
|
|
88
|
+
if (C64.RealSIDmode) {
|
|
89
|
+
Tmp = (VolumeBand & 0xf) << FRACTIONAL_SHIFTS; // 12 );
|
|
90
|
+
SID.Digi = (Tmp - SID.PrevVolume) * D418_DIGI_MUL; // highpass is digi, adding it to output must be before digifilter-code
|
|
91
|
+
SID.PrevVolume += divTrunc(Tmp - SID.PrevVolume, 1024); // >> (FRACTIONAL_SHIFTS-2); //10; //arithmetic shift amount determines digi lowpass-frequency
|
|
92
|
+
MainVolume = SID.PrevVolume >> FRACTIONAL_SHIFTS; // 12; //lowpass is main volume
|
|
93
|
+
}
|
|
94
|
+
else
|
|
95
|
+
MainVolume = VolumeBand & 0xf;
|
|
96
|
+
SID.Output = (NonFilted + FilterOutput) * MainVolume + SID.Digi;
|
|
97
|
+
// Output = SID.Output / cRSID_C64.Attenuation — (faster being done once
|
|
98
|
+
// outside, not in all individual SIDs)
|
|
99
|
+
return SID.Output; // master output of a SID
|
|
100
|
+
}
|
|
101
|
+
/** cRSID_precalculateHQoutputParameters (SID_Outputs.c:103-157) — called by
|
|
102
|
+
* resampler at samplerate-pace. */
|
|
103
|
+
export function cRSID_precalculateHQoutputParameters(C64, SID) {
|
|
104
|
+
// enum { FRACTIONAL_BITS = 12, FRACTIONAL_SHIFTS = (FRACTIONAL_BITS) } —
|
|
105
|
+
// same values as in emulateSIDoutputStage
|
|
106
|
+
const VOLUME_DIGI_SEPARATION_CUTOFF_DIV = 1 << 10;
|
|
107
|
+
const VolumeBand = C64.IObankWR[SID.BasePtr + 0x18]; // FilterSwitchReso = SID->BasePtr[0x17];
|
|
108
|
+
// Resonance = SID->BasePtr[0x17] >> 4; //FilterSwitchReso >> 4;
|
|
109
|
+
const Cutoff = (C64.IObankWR[SID.BasePtr + 0x16] << 3) + (C64.IObankWR[SID.BasePtr + 0x15] & 7);
|
|
110
|
+
if (SID.ChipModel === 8580) {
|
|
111
|
+
SID.Cutoff = CRSID_CutoffMul8580_OverSampleRate[Cutoff];
|
|
112
|
+
SID.Resonance = CRSID_Resonances8580[C64.IObankWR[SID.BasePtr + 0x17] >> 4];
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
// 6581
|
|
116
|
+
SID.Cutoff = CRSID_CutoffMul6581_OverSampleRate[Cutoff];
|
|
117
|
+
SID.Resonance = CRSID_Resonances6581[C64.IObankWR[SID.BasePtr + 0x17] >> 4];
|
|
118
|
+
}
|
|
119
|
+
SID.HighPassBit = VolumeBand & HIGHPASS_BITVAL;
|
|
120
|
+
SID.BandPassBit = VolumeBand & BANDPASS_BITVAL;
|
|
121
|
+
SID.LowPassBit = VolumeBand & LOWPASS_BITVAL;
|
|
122
|
+
// For $D418 volume-register digi playback: (see long comment at
|
|
123
|
+
// cRSID_emulateSIDoutputStage above — same AC/DC separation applies here)
|
|
124
|
+
if (C64.RealSIDmode) {
|
|
125
|
+
const Tmp = (VolumeBand & 0xf) << FRACTIONAL_SHIFTS; // 12 );
|
|
126
|
+
SID.Digi = (Tmp - SID.PrevVolume) * D418_DIGI_MUL; // highpass is digi, adding it to output must be before digifilter-code
|
|
127
|
+
SID.PrevVolume += divTrunc(Tmp - SID.PrevVolume, VOLUME_DIGI_SEPARATION_CUTOFF_DIV); // / 1024; — arithmetic shift amount determines digi lowpass-frequency
|
|
128
|
+
SID.Volume = SID.PrevVolume >> FRACTIONAL_SHIFTS; // 12; //lowpass is main volume
|
|
129
|
+
}
|
|
130
|
+
else
|
|
131
|
+
SID.Volume = VolumeBand & 0xf;
|
|
132
|
+
}
|
|
133
|
+
/** cRSID_emulateHQresampledSIDoutputStage (SID_Outputs.c:159-206) — called by
|
|
134
|
+
* resampler at oversample-rate. */
|
|
135
|
+
export function cRSID_emulateHQresampledSIDoutputStage(C64, SID, waves) {
|
|
136
|
+
void C64;
|
|
137
|
+
const CRSID_OVERSAMPLING_FILTERTABLE_MAGNITUDE = 1 << CRSID_OVERSAMPLING_FILTERTABLE_RESOLUTION;
|
|
138
|
+
// HQ_6581_CUTOFF_MAX = 0xA82 //0x1505 //0x541 — cutoff-max from HQ-filter oversampled cutoff-table (unused: bound-check commented out in C)
|
|
139
|
+
let Tmp; // , FilterInput;
|
|
140
|
+
let FilterOutput;
|
|
141
|
+
let Cutoff;
|
|
142
|
+
// FilterInput = waves.FilterInput;
|
|
143
|
+
if (SID.ChipModel === 8580)
|
|
144
|
+
Cutoff = SID.Cutoff;
|
|
145
|
+
else {
|
|
146
|
+
Cutoff = SID.Cutoff + divTrunc(waves.FilterInput, 1024); // MOSFET-VCR control-voltage calculation (resistance-modulation aka 6581 filter distortion) emulation
|
|
147
|
+
/* if ( Cutoff > HQ_6581_CUTOFF_MAX ) Cutoff = HQ_6581_CUTOFF_MAX; else */
|
|
148
|
+
if (Cutoff < 0)
|
|
149
|
+
Cutoff = 0; // can really go below 0 when FilterInput is negative
|
|
150
|
+
}
|
|
151
|
+
FilterOutput = 0; // shifting negative integers in C is implementation-dependent, so using normal division by power of 2, that might luckily be optimized as arithmetic-shift by the compiler
|
|
152
|
+
Tmp =
|
|
153
|
+
waves.FilterInput + divTrunc(SID.PrevBandPass * SID.Resonance, CRSID_FILTERTABLE_MAGNITUDE) + SID.PrevLowPass;
|
|
154
|
+
if (SID.HighPassBit)
|
|
155
|
+
FilterOutput -= Tmp;
|
|
156
|
+
Tmp = SID.PrevBandPass - divTrunc(Tmp * Cutoff, CRSID_OVERSAMPLING_FILTERTABLE_MAGNITUDE);
|
|
157
|
+
SID.PrevBandPass = Tmp;
|
|
158
|
+
if (SID.BandPassBit)
|
|
159
|
+
FilterOutput -= Tmp;
|
|
160
|
+
Tmp = SID.PrevLowPass + divTrunc(Tmp * Cutoff, CRSID_OVERSAMPLING_FILTERTABLE_MAGNITUDE);
|
|
161
|
+
SID.PrevLowPass = Tmp;
|
|
162
|
+
if (SID.LowPassBit)
|
|
163
|
+
FilterOutput += Tmp;
|
|
164
|
+
return (waves.NonFilted + FilterOutput) * SID.Volume;
|
|
165
|
+
}
|
|
166
|
+
/** cRSID_emulateHQresampledSIDdigi (SID_Outputs.c:208-260) — called by
|
|
167
|
+
* resampler at samplerate-pace, only digis. */
|
|
168
|
+
export function cRSID_emulateHQresampledSIDdigi(C64, SID, signal) {
|
|
169
|
+
// VolumeBand=SID->BasePtr[0x18]; (unused in C — commented out)
|
|
170
|
+
if (C64.RealSIDmode) {
|
|
171
|
+
// only processing digi here
|
|
172
|
+
if (SID.Channel === 1 /* CRSID_CHANNEL_LEFT */)
|
|
173
|
+
signal.L += SID.Digi * 2;
|
|
174
|
+
else if (SID.Channel === 2 /* CRSID_CHANNEL_RIGHT */)
|
|
175
|
+
signal.R += SID.Digi * 2;
|
|
176
|
+
else {
|
|
177
|
+
signal.L += SID.Digi;
|
|
178
|
+
signal.R += SID.Digi;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// The C file reads the file-global cRSID_C64 inside the RealSIDmode branches;
|
|
183
|
+
// the TS port threads `C64` through — the import documents that parity.
|
|
184
|
+
void cRSID_C64;
|
|
185
|
+
//# sourceMappingURL=sidoutputs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidoutputs.js","sourceRoot":"","sources":["../src/sidoutputs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DspPlugin, FormatPlugin, LoadCtx, ModuleData } from '@modplayjs/core';
|
|
2
|
+
export declare function cRSID_sidTest(bytes: Uint8Array): boolean;
|
|
3
|
+
export declare function cRSID_sidLoad(bytes: Uint8Array, ctx: LoadCtx): ModuleData;
|
|
4
|
+
/**
|
|
5
|
+
* Start (or restart) SID playback for a previously-loaded SID file. Call
|
|
6
|
+
* after core.loadModule(sidPlugin.load(bytes, ctx)).
|
|
7
|
+
*
|
|
8
|
+
* The C player calls (host/file.c → libcRSID.c):
|
|
9
|
+
* cRSID_init(rate, 0) — once, on first use
|
|
10
|
+
* cRSID_processSIDfileData — during load
|
|
11
|
+
* cRSID_initSIDtune(hdr, subtune) — init-routine + playaddress
|
|
12
|
+
* cRSID_playSIDtune() — unpause
|
|
13
|
+
*/
|
|
14
|
+
export declare function sidStartTune(bytes: Uint8Array, sampleRate: number, subtune?: number): void;
|
|
15
|
+
/** The DSP: renders the SID engine at exact host-buffer pacing. */
|
|
16
|
+
export declare const sidDsp: DspPlugin;
|
|
17
|
+
export declare const plugin: FormatPlugin;
|
|
18
|
+
//# sourceMappingURL=sidplugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidplugin.d.ts","sourceRoot":"","sources":["../src/sidplugin.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAqB,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAW,MAAM,iBAAiB,CAAC;AAahH,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAMxD;AAaD,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,GAAG,UAAU,CAuEzE;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,SAAI,GAAG,IAAI,CAQrF;AAED,mEAAmE;AACnE,eAAO,MAAM,MAAM,EAAE,SAuBpB,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,YAQpB,CAAC"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
// Copyright (c) 2026 Bitti09 — modplayjs contributors
|
|
3
|
+
// @modplayjs/fmt-sid — plugin surface.
|
|
4
|
+
//
|
|
5
|
+
// The SID engine is sample-paced (the 6510 play routine is called every
|
|
6
|
+
// FrameCycles CPU cycles inside cRSID_emulateC64), not row/tick paced. The
|
|
7
|
+
// integration therefore is:
|
|
8
|
+
// - FormatPlugin: signature test + load; produces a stub ModuleData whose
|
|
9
|
+
// single pattern loops forever (restart=0, len=1) so CorePlayer keeps
|
|
10
|
+
// ticking a bare tracker; the SID DSP ignores tracker state entirely and
|
|
11
|
+
// drives cRSID_generateSample() at exact host-buffer pacing.
|
|
12
|
+
// - DspPlugin 'sid': renderFrame(out, ticks) fills out with
|
|
13
|
+
// out.length/2 samples from cRSID_generateSample() — out.length/2 is
|
|
14
|
+
// authoritative (ticks*ticksize is only an upper bound).
|
|
15
|
+
//
|
|
16
|
+
// Loop semantics: playBuffer(loop) stops when loop_count >= loop. The stub
|
|
17
|
+
// module loops the single pattern through restart=0 (sequence loop), which
|
|
18
|
+
// increments loop_count once per pass; drivers that pass loop=1 therefore
|
|
19
|
+
// stop after one tracker pass — for SID the demo passes loop=0 (infinite).
|
|
20
|
+
// The engine has no song-end concept beyond cRSID.PlayTime vs
|
|
21
|
+
// SubtuneDurations (no SongLengths database is loaded).
|
|
22
|
+
import { cRSID_init, cRSID_initSIDtune, cRSID_generateSample, cRSID_processSIDfileData, cRSID_playSIDtune } from './loader.js';
|
|
23
|
+
import { applySongLengthsFor } from './songlengths.js';
|
|
24
|
+
import { sidRememberTune } from './sidseek.js';
|
|
25
|
+
import { sidApplyInitOverrides } from './settings.js';
|
|
26
|
+
/** Track count for the stub pattern: one silent channel. */
|
|
27
|
+
const SID_STUB_CHANNELS = 1;
|
|
28
|
+
/** Rows per stub pattern (64 = typical tracker pattern height). */
|
|
29
|
+
const SID_STUB_ROWS = 64;
|
|
30
|
+
export function cRSID_sidTest(bytes) {
|
|
31
|
+
// host/file.c cRSID_processSIDfileData magic check (P/R + "SID"), plus the
|
|
32
|
+
// v1 header-size gate (files shorter than 0x7C cannot be v2 headers).
|
|
33
|
+
if (bytes.length < 0x7c)
|
|
34
|
+
return false;
|
|
35
|
+
if (bytes[0] !== 0x50 /* P */ && bytes[0] !== 0x52 /* R */)
|
|
36
|
+
return false;
|
|
37
|
+
return bytes[1] === 0x53 /* S */ && bytes[2] === 0x49 /* I */ && bytes[3] === 0x44 /* D */;
|
|
38
|
+
}
|
|
39
|
+
/** Header strings are latin1 (C char[] fields printed via %s). */
|
|
40
|
+
function headerString(b, off) {
|
|
41
|
+
let s = '';
|
|
42
|
+
for (let i = 0; i < 32; ++i) {
|
|
43
|
+
const c = b[off + i];
|
|
44
|
+
if (c === 0)
|
|
45
|
+
break;
|
|
46
|
+
s += String.fromCharCode(c);
|
|
47
|
+
}
|
|
48
|
+
return s;
|
|
49
|
+
}
|
|
50
|
+
export function cRSID_sidLoad(bytes, ctx) {
|
|
51
|
+
void ctx;
|
|
52
|
+
const header = cRSID_processSIDfileData(bytes, bytes.length);
|
|
53
|
+
if (header === null) {
|
|
54
|
+
throw new Error('fmt-sid: not a PSID/RSID file');
|
|
55
|
+
}
|
|
56
|
+
// HVSC Songlengths lookup (no-op until a DB is loaded): fills
|
|
57
|
+
// cRSID.SubtuneDurations like the C host's cRSID_getPlaylengths.
|
|
58
|
+
const durations = applySongLengthsFor(bytes, header.SubtuneAmount);
|
|
59
|
+
const subtune = header.DefaultSubtune || 1;
|
|
60
|
+
const tuneSeconds = durations[subtune] ?? durations[1] ?? 0;
|
|
61
|
+
// Stub tracker module: 1 order, 1 pattern, silent; the SID DSP produces
|
|
62
|
+
// all audio. speed/bpm chosen so ticksize ≈ 25 samples/tick at 44.1kHz
|
|
63
|
+
// (irrelevant to output, only paces playBuffer chunks).
|
|
64
|
+
const tracks = [];
|
|
65
|
+
for (let c = 0; c < SID_STUB_CHANNELS; ++c) {
|
|
66
|
+
const event = [];
|
|
67
|
+
for (let r = 0; r < SID_STUB_ROWS; ++r)
|
|
68
|
+
event.push({ note: 0, ins: 0, vol: -1, fxt: 0, fxp: 0, f2t: 0, f2p: 0 });
|
|
69
|
+
tracks.push({ rows: SID_STUB_ROWS, event });
|
|
70
|
+
}
|
|
71
|
+
const patterns = [{ rows: SID_STUB_ROWS, tracks }];
|
|
72
|
+
const channels = [];
|
|
73
|
+
for (let c = 0; c < SID_STUB_CHANNELS; ++c)
|
|
74
|
+
channels.push({ pan: 0x80, vol: 0x40, flg: 0 });
|
|
75
|
+
const mod = {
|
|
76
|
+
title: headerString(bytes, 0x16),
|
|
77
|
+
format: 'sid',
|
|
78
|
+
comment: `${headerString(bytes, 0x36)}${headerString(bytes, 0x56) ? ' — ' + headerString(bytes, 0x56) : ''}`,
|
|
79
|
+
chn: SID_STUB_CHANNELS,
|
|
80
|
+
pat: 1,
|
|
81
|
+
ins: 0,
|
|
82
|
+
len: 1,
|
|
83
|
+
restart: 0,
|
|
84
|
+
xxo: [0],
|
|
85
|
+
channels,
|
|
86
|
+
patterns,
|
|
87
|
+
instruments: [],
|
|
88
|
+
samples: [],
|
|
89
|
+
num_sequences: 1,
|
|
90
|
+
sequences: [
|
|
91
|
+
{
|
|
92
|
+
ord: 0,
|
|
93
|
+
entry_point: 0,
|
|
94
|
+
duration: Math.round(tuneSeconds * 1000),
|
|
95
|
+
time: 0,
|
|
96
|
+
speed: 6,
|
|
97
|
+
bpm: 125,
|
|
98
|
+
gvl: -1,
|
|
99
|
+
start_row: 0,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
speed: 6,
|
|
103
|
+
bpm: 125,
|
|
104
|
+
volbase: 0x40,
|
|
105
|
+
gvolbase: 0x80,
|
|
106
|
+
gvol: 0x80,
|
|
107
|
+
quirks: 0,
|
|
108
|
+
flowMode: 0,
|
|
109
|
+
readEventType: 0 /* ReadEventType.MOD (const-enum value inline for isolatedModules) */,
|
|
110
|
+
periodType: 0,
|
|
111
|
+
defpan: 0x80,
|
|
112
|
+
time_factor: 10,
|
|
113
|
+
rrate: 250,
|
|
114
|
+
c4rate: 8363,
|
|
115
|
+
compare_vblank: false,
|
|
116
|
+
tracker: `cRSID (PSID v${header.Version})`,
|
|
117
|
+
endless: true, // SID tunes never end — playBuffer treats loop as infinite
|
|
118
|
+
};
|
|
119
|
+
return mod;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Start (or restart) SID playback for a previously-loaded SID file. Call
|
|
123
|
+
* after core.loadModule(sidPlugin.load(bytes, ctx)).
|
|
124
|
+
*
|
|
125
|
+
* The C player calls (host/file.c → libcRSID.c):
|
|
126
|
+
* cRSID_init(rate, 0) — once, on first use
|
|
127
|
+
* cRSID_processSIDfileData — during load
|
|
128
|
+
* cRSID_initSIDtune(hdr, subtune) — init-routine + playaddress
|
|
129
|
+
* cRSID_playSIDtune() — unpause
|
|
130
|
+
*/
|
|
131
|
+
export function sidStartTune(bytes, sampleRate, subtune = 1) {
|
|
132
|
+
cRSID_init(sampleRate, 0);
|
|
133
|
+
sidApplyInitOverrides(); // re-apply after cRSID_init wipes the globals
|
|
134
|
+
const header = cRSID_processSIDfileData(bytes, bytes.length);
|
|
135
|
+
applySongLengthsFor(bytes, header.SubtuneAmount); // re-fill SubtuneDurations (init resets)
|
|
136
|
+
sidRememberTune(bytes, header, subtune, sampleRate);
|
|
137
|
+
cRSID_initSIDtune(header, subtune);
|
|
138
|
+
cRSID_playSIDtune();
|
|
139
|
+
}
|
|
140
|
+
/** The DSP: renders the SID engine at exact host-buffer pacing. */
|
|
141
|
+
export const sidDsp = {
|
|
142
|
+
name: 'sid',
|
|
143
|
+
channels: 1,
|
|
144
|
+
renderFrame(core, out, ticks) {
|
|
145
|
+
void core;
|
|
146
|
+
// DSP contract: render exactly ticks × ticksize frames (the caller may
|
|
147
|
+
// hand a larger scratch buffer; the player consumes a fixed
|
|
148
|
+
// ticksize×2 slice — over-rendering would drift the engine).
|
|
149
|
+
const frames = ticks * core.ticksize;
|
|
150
|
+
for (let i = 0; i < frames; ++i) {
|
|
151
|
+
const s = cRSID_generateSample();
|
|
152
|
+
out[i * 2] = s.L / 32768;
|
|
153
|
+
out[i * 2 + 1] = s.R / 32768;
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
reset() {
|
|
157
|
+
// C: nothing to reset on the host side (emulation state is reset by
|
|
158
|
+
// cRSID_initSIDtune); keep the engine running across player restarts.
|
|
159
|
+
},
|
|
160
|
+
onRow(_core, _chn, _ev) {
|
|
161
|
+
// SID has no per-row DSP hook semantics (the paula DSP uses it for
|
|
162
|
+
// sample-position resets); C equivalent: none in libcRSID.
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
export const plugin = {
|
|
166
|
+
name: 'sid',
|
|
167
|
+
test: cRSID_sidTest,
|
|
168
|
+
load: cRSID_sidLoad,
|
|
169
|
+
readEvent() {
|
|
170
|
+
// SID has no tracker events; the stub module's single silent event
|
|
171
|
+
// reader is a no-op (the SID DSP owns all audio).
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
//# sourceMappingURL=sidplugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidplugin.js","sourceRoot":"","sources":["../src/sidplugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type CRC64instance, type CRSIDOutput } from './c64types.js';
|
|
2
|
+
export declare function cRSID_emulateLightSIDs(C64: CRC64instance): CRSIDOutput;
|
|
3
|
+
export declare function cRSID_emulateOversampledSIDwaves(C64: CRC64instance): void;
|
|
4
|
+
export declare function cRSID_emulateOversampledSIDoutputs(C64: CRC64instance): CRSIDOutput;
|
|
5
|
+
export declare function cRSID_emulateHQresampledSIDs(C64: CRC64instance): void;
|
|
6
|
+
export declare function cRSID_emulateHQresampledSIDoutputs(C64: CRC64instance): CRSIDOutput;
|
|
7
|
+
export { cRSID_playPSIDdigi } from './psiddigi.js';
|
|
8
|
+
//# sourceMappingURL=sidrouting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidrouting.d.ts","sourceRoot":"","sources":["../src/sidrouting.ts"],"names":[],"mappings":"AAcA,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,WAAW,EAEjB,MAAM,eAAe,CAAC;AAqBvB,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,aAAa,GAAG,WAAW,CAmHtE;AAOD,wBAAgB,gCAAgC,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAsFzE;AA8BD,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,aAAa,GAAG,WAAW,CAqHlF;AAQD,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CA4GrE;AA2BD,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,aAAa,GAAG,WAAW,CAelF;AAED,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC"}
|