…Show last 363 lines
61 -63, -63, -63, -62, -62, -61, -61, -60, -59, -59, -58, -57, -57, -56, -55, -54, -53, -53, -51, -51, -50, -49, -48, -46, -46, -44, -43, -42, -40, -40, -38, -37, -36, -34, -33, -31, -30, -29, -27, -26,
62 -24, -23, -22, -20, -18, -17, -15, -14, -12, -11, -9, -7, -6, -4, -3, -1
63 },
64
65 {
66 0, 1, 3, 4, 6, 7, 9, 11, 12, 14, 15, 17, 18, 20, 22, 23, 24, 26, 27, 29,30, 31, 33, 34, 36, 37, 38, 40, 40, 42, 43, 44, 46, 46, 48, 49, 50, 51, 51, 53,
67 53, 54, 55, 56, 57, 57, 58, 59, 59, 60, 61, 61, 62, 62, 63, 63, 63, 64, 64, 64, 116, 116, 116, 116, 116, 116, 116, 116, 116, 64, 64, 64, 63, 63, 63, 62, 62, 61, 61, 60,
68 59, 59, 58, 57, 57, 56, 55, 54, 53, 53, 51, 51, 50, 49, 48, 46, 46, 44, 43, 42, 40, 40, 38, 37, 36, 34, 33, 31, 30, 29, 27, 26, 24, 23, 22, 20, 18, 17, 15, 14,
69 12, 11, 9, 7, 6, 4, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
73 },
74
75
76 {
77 0, 1, 3, 4, 6, 7, 9, 11, 12, 14, 15, 17, 18, 20, 22, 23, 24, 26, 27, 29, 30, 31, 33, 34, 36, 37, 38, 40, 40, 42, 43, 44, 46, 46, 48, 49, 50, 51, 51, 53,
78 53, 54, 55, 56, 57, 57, 58, 59, 59, 60, 61, 61, 62, 62, 63, 63, 63, 64, 64, 64, 116, 116, 116, 116, 116, 116, 116, 116, 116, 64, 64, 64, 63, 63, 63, 62, 62, 61, 61, 60,
79 59, 59, 58, 57, 57, 56, 55, 54, 53, 53, 51, 51, 50, 49, 48, 46, 46, 44, 43, 42, 40, 40, 38, 37, 36, 34, 33, 31, 30, 29, 27, 26, 24, 23, 22, 20, 18, 17, 15, 14,
80 12, 11, 9, 7, 6, 4, 3, 1, 0, 1, 3, 4, 6, 7, 9, 11, 12, 14, 15, 17, 18, 20, 22, 23, 24, 26, 27, 29, 30, 31, 33, 34, 36, 37, 38, 40, 40, 42, 43, 44,
81 46, 46, 48, 49, 50, 51, 51, 53, 53, 54, 55, 56, 57, 57, 58, 59, 59, 60, 61, 61, 62, 62, 63, 63, 63, 64, 64, 64, 116, 116, 116, 116, 116, 116, 116, 116, 116, 64, 64, 64,
82 63, 63, 63, 62, 62, 61, 61, 60, 59, 59, 58, 57, 57, 56, 55, 54, 53, 53, 51, 51, 50, 49, 48, 46, 46, 44, 43, 42, 40, 40, 38, 37, 36, 34, 33, 31, 30, 29, 27, 26,
83 24, 23, 22, 20, 18, 17, 15, 14, 12, 11, 9, 7, 6, 4, 3, 1
84 },
85
86
87 {
88 0, 1, 3, 4, 6, 7, 9, 11, 12, 14, 15, 17, 18, 20, 22, 23, 24, 26, 27, 29, 30, 31, 33, 34, 36, 37, 38, 40, 40, 42, 43, 44, 46, 46, 48, 49, 50, 51, 51, 53,
89 53, 54, 55, 56, 57, 57, 58, 59, 59, 60, 61, 61, 62, 62, 63, 63, 63, 64, 64, 64, 116, 116, 116, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
90 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
91 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 4, 6, 7, 9, 11, 12, 14, 15, 17, 18, 20, 22, 23, 24, 26, 27, 29, 30, 31, 33, 34, 36, 37, 38, 40, 40, 42, 43, 44,
92 46, 46, 48, 49, 50, 51, 51, 53, 53, 54, 55, 56, 57, 57, 58, 59, 59, 60, 61, 61, 62, 62, 63, 63, 63, 64, 64, 64, 116, 116, 116, 116, 0, 0, 0, 0, 0, 0, 0, 0,
93 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
94 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
95 }
96
97};
98
99byte adliboperators[2][9] = { //Groupings of 22 registers! (20,40,60,80,E0)
100 { 0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12 },
101 { 0x03, 0x04, 0x05, 0x0B, 0x0C, 0x0D, 0x13, 0x14, 0x15 }
102};
103
104byte adliboperatorsreverse[0x16] = { 0, 1, 2, 0, 1, 2,
105 255, 255,
106 3, 4, 5, 3, 4, 5,
107 255, 255,
108 6, 7, 8, 6, 7, 8}; //Channel lookup of adlib operators!
109
110byte wavemask = 0; //Wave select mask!
111
112struct structadlibop {
113 uint8_t wavesel;
114 uint8_t AM; //Amplitude modulation enabled?
115 float ModulatorFrequencyMultiple; //What harmonic to sound?
116} adlibop[0x10];
117
118struct structadlibchan {
119 uint16_t freq;
120 double convfreq;
121 uint8_t keyon;
122 uint16_t octave;
123 uint8_t synthmode; //What synthesizer mode (1=Additive synthesis, 0=Frequency modulation)
124} adlibch[0x10];
125
126double attacktable[0x10] = { 1.0003, 1.00025, 1.0002, 1.00015, 1.0001, 1.00009, 1.00008, 1.00007, 1.00006, 1.00005, 1.00004, 1.00003, 1.00002, 1.00001, 1.000005 }; //1.003, 1.05, 1.01, 1.015, 1.02, 1.025, 1.03, 1.035, 1.04, 1.045, 1.05, 1.055, 1.06, 1.065, 1.07, 1.075 };
127double decaytable[0x10] = { 0.99999, 0.999985, 0.99998, 0.999975, 0.99997, 0.999965, 0.99996, 0.999955, 0.99995, 0.999945, 0.99994, 0.999935, 0.99994, 0.999925, 0.99992, 0.99991 };
128double adlibenv[0x20], adlibdecay[0x20], adlibattack[0x20];
129uint8_t adlibdidattack[0x20], adlibpercussion = 0, adlibstatus = 0;
130
131float AMDepth = 0.0f; //AM depth in dB!
132
133uint16_t adlibport = 0x388;
134
135OPTINLINE double dB2factor(double dB, double fMaxLevelDB)
136{
137 return pow(10, ((dB - fMaxLevelDB) / 20));
138}
139
140OPTINLINE float calcModulatorFrequencyMultiple(byte data)
141{
142 switch (data)
143 {
144 case 0: return 0.5f;
145 case 11: return 10.0f;
146 case 13: return 12.0f;
147 case 14: return 15.0f;
148 default: return (float)data; //The same number!
149 }
150}
151
152void outadlib (uint16_t portnum, uint8_t value) {
153 if (portnum==adlibport) {
154 adlibaddr = value;
155 return;
156 }
157 portnum = adlibaddr;
158 adlibregmem[portnum] = value;
159 switch (portnum) {
160 case 0: //Waveform select enable
161 wavemask = (adlibregmem[0] & 0x20) ? 3 : 0; //Apply waveform mask!
162 break;
163 case 4: //timer control
164 if (value&0x80) {
165 adlibstatus = 0;
166 adlibregmem[4] = 0;
167 }
168 break;
169 case 0xBD:
170 if (value & 0x10) adlibpercussion = 1;
171 else adlibpercussion = 0;
172 AMDepth = (value & 0x80) ? dB2factor(4.8f, __MAX_DB) : dB2factor(1.0f, __MAX_DB); //AM depth in dB!
173 break;
174 }
175 if ((portnum >= 0x20) && (portnum <= 0x35)) //Various flags
176 {
177 portnum &= 0x1F;
178 adlibop[portnum].AM = (adlibregmem[0x20 + portnum] & 0x80) ? 1 : 0; //Take the AM bit!
179 adlibop[portnum].ModulatorFrequencyMultiple = calcModulatorFrequencyMultiple(adlibregmem[0x20 + portnum] & 0xF); //Which harmonic to use?
180 }
181 else if ( (portnum >= 0x60) && (portnum <= 0x75) ) { //attack/decay
182 portnum &= 0x1F;
183 adlibattack[portnum] = attacktable[15- (value>>4) ]*1.006;
184 adlibdecay[portnum] = decaytable[value&15];
185 }
186 else if ( (portnum >= 0xA0) && (portnum <= 0xB8) ) { //octave, freq, key on
187 if (portnum & 0x8) return; //Ignore A8-AF!
188 portnum &= 0x7; //Only 9 channels
189 if (!adlibch[portnum].keyon && ( (adlibregmem[0xB0+portnum]>>5) &1) ) {
190 adlibdidattack[adliboperators[0][portnum]] = 0;
191 adlibdidattack[adliboperators[1][portnum]] = 0;
192 adlibenv[adliboperators[0][portnum]] = 0.0025;
193 adlibenv[adliboperators[1][portnum]] = 0.0025;
194 }
195 adlibch[portnum].freq = adlibregmem[0xA0+portnum] | ( (adlibregmem[0xB0+portnum]&3) <<8);
196 adlibch[portnum].convfreq = ( (double) adlibch[portnum].freq * 0.7626459);
197 adlibch[portnum].keyon = (adlibregmem[0xB0+portnum]>>5) &1;
198 adlibch[portnum].octave = (adlibregmem[0xB0+portnum]>>2) &7;
199 }
200 else if ((portnum >= 0xC0) && (portnum <= 0xC8))
201 {
202 portnum &= 7;
203 adlibch[portnum].synthmode = (adlibregmem[0xC0 + portnum] & 1); //Save the synthesis mode!
204 }
205 else if ( (portnum >= 0xE0) && (portnum <= 0xF5) ) { //waveform select
206 portnum &= 0x1F;
207 adlibop[portnum].wavesel = value&3;
208 }
209}
210
211uint8_t inadlib (uint16_t portnum) {
212 if (!adlibregmem[4]) adlibstatus = 0;
213 else adlibstatus = 0x80;
214 adlibstatus = adlibstatus + (adlibregmem[4]&1) *0x40 + (adlibregmem[4]&2) *0x10;
215 return (adlibstatus);
216}
217
218uint16_t adlibfreq (sbyte operatornumber, uint8_t chan) {
219 //uint8_t downoct[4] = { 3, 2, 1, 0 };
220 //uint8_t upoct[3] = { 1, 2, 3 };
221 if (chan > 8) return (0); //Invalid channel: we only have 9 channels!
222 uint16_t tmpfreq;
223 if (!adlibch[chan].keyon) return (0);
224 tmpfreq = (uint16_t) adlibch[chan].convfreq;
225 //if (adlibch[chan].octave<4) tmpfreq = tmpfreq>>1;
226 //if (adlibch[chan].octave>4) tmpfreq = tmpfreq<<1;
227 switch (adlibch[chan].octave) {
228 case 0:
229 tmpfreq = tmpfreq >> 4;
230 break;
231 case 1:
232 tmpfreq = tmpfreq >> 3;
233 break;
234 case 2:
235 tmpfreq = tmpfreq >> 2;
236 break;
237 case 3:
238 tmpfreq = tmpfreq >> 1;
239 break;
240 //case 4: tmpfreq = tmpfreq >> 1; break;
241 case 5:
242 tmpfreq = tmpfreq << 1;
243 break;
244 case 6:
245 tmpfreq = tmpfreq << 2;
246 break;
247 case 7:
248 tmpfreq = tmpfreq << 3;
249 }
250 if (operatornumber != -1) //Apply frequency multiplication factor?
251 {
252 tmpfreq *= adlibop[operatornumber].ModulatorFrequencyMultiple; //Apply the frequency multiplication factor!
253 }
254 return (tmpfreq);
255}
256
257//Original again!
258OPTINLINE char adlibsample (uint8_t curchan) {
259 static uint64_t adlibstep[0x20];
260 float fullstep1, fullstep2, tempsample, result, tempstep, effectivemodulator, effectivecarrier;
261 byte operator1, operator2; //What operator is our modulator and carrier?
262
263 if (curchan >= NUMITEMS(adlibch)) return 0; //No sample with invalid channel!
264 if (adlibpercussion && (curchan >= 6) && (curchan <= 8)) //We're percussion?
265 {
266 return 0; //Percussion isn't supported yet!
267 }
268
269 //Determine our active operators!
270 operator1 = adliboperators[0][curchan]; //First operator to use!
271 operator2 = adliboperators[1][curchan]; //Second operator to use!
272
273 //Determine the type of modulation!
274 //Operator 1!
275 effectivemodulator = adlibfreq(operator1,curchan); //Effective modulator frequency!
276 fullstep1 = usesamplerate / effectivemodulator;
277 tempsample = oplwave[adlibop[operator1].wavesel&wavemask][(uint8_t)((double)adlibstep[operator1]++ / ((double)fullstep1 / (double)256))];
278 if (adlibop[operator1].AM) tempsample *= AMDepth; //Apply AM depth!
279
280 //Apply the volume envelope for operator 1!
281 tempstep = adlibenv[operator1]; //Current volume!
282 tempsample *= tempstep;
283 tempsample *= 2.0f;
284
285 //Operator 2!
286 effectivecarrier = adlibfreq(operator2,curchan); //Effective carrier init!
287 if (!adlibch[curchan].synthmode) effectivecarrier += tempsample; //FM using the first operator when needed!
288 fullstep2 = usesamplerate / effectivecarrier;
289 result = oplwave[adlibop[operator2].wavesel&wavemask][(uint8_t)((double)adlibstep[operator2]++ / ((double)fullstep2 / (double)256))];
290 if (adlibop[operator2].AM) result *= AMDepth; //Apply AM depth!
291
292 //Apply the volume envelope for operator 2!
293 tempstep = adlibenv[operator2]; //Current volume!
294 if (tempstep > 1.0f) tempstep = 1.0f; //Limit volume to 100%!
295 result *= tempstep;
296 result *= 2.0f;
297
298 //Perform additive synthesis when asked to do so.
299 if (adlibch[curchan].synthmode) result += tempsample; //Perform additive synthesis when needed!
300
301 //Make sure we don't overflow!
302 if (adlibstep[operator1] > fullstep1) adlibstep[operator1] = 0;
303 if (adlibstep[operator2] > fullstep2) adlibstep[operator2] = 0;
304
305 return (char)(result);
306}
307
308OPTINLINE char adlibgensample() {
309 uint8_t curchan;
310 char adlibaccum;
311 adlibaccum = 0;
312 for (curchan = 0; curchan < 9; curchan++)
313 {
314 if (adlibfreq(-1,curchan) != 0)
315 {
316 adlibaccum += adlibsample(curchan);
317 }
318 }
319 return (adlibaccum);
320}
321
322void tickadlib() {
323 uint8_t curchan;
324 for (curchan = 0; curchan<0x16; curchan++)
325 {
326 if (adlibfreq(-1,adliboperatorsreverse[curchan]) != 0)
327 {
328 if (adlibdidattack[curchan])
329 {
330 if (adlibenv[curchan]>0.0001f)
331 {
332 adlibenv[curchan] *= adlibdecay[curchan];
333 }
334 else
335 {
336 adlibenv[curchan] = 0; //Clear: nothing to be heard!
337 }
338 }
339 else
340 {
341 adlibenv[curchan] *= adlibattack[curchan];
342 if (adlibenv[curchan] >= 1.0) adlibdidattack[curchan] = 1;
343 }
344 }
345 }
346}
347
348byte adlib_soundGenerator(void* buf, uint_32 length, byte stereo, void *userdata) //Generate a sample!
349{
350 if (stereo) return 0; //We don't support stereo!
351
352 byte filled,curchan;
353 filled = 0; //Default: not filled!
354 for (curchan=0; curchan<9; curchan++) { //Check for active channels!
355 if (adlibfreq (-1,curchan) !=0) {
356 filled = 1; //We're filled!
357 break; //Stop searching!
358 }
359 }
360
361 if (!filled) //Not filled?
362 {
363 return 0; //Unused channel!
364 }
365
366 uint_32 c;
367 c = length; //Init c!
368 char *data_mono;
369 data_mono = (char *)buf; //The data in correct samples!
370 for (;;) //Fill it!
371 {
372 //Left and right are the same!
373 *data_mono++ = adlibgensample(); //Generate a mono sample!
374 if (!--c) return SOUNDHANDLER_RESULT_FILLED; //Next item!
375 }
376}
377
378//Multicall speedup!
379#define ADLIBMULTIPLIER 0
380
381void initAdlib()
382{
383 if (__HW_DISABLED) return; //Abort!
384
385 //All input!
386 AMDepth = dB2factor(1.0f, __MAX_DB);
387
388 if (__SOUND_ADLIB)
389 {
390 if (!addchannel(&adlib_soundGenerator,NULL,"Adlib",usesamplerate,0,0,SMPL8S)) //Start the sound emulation (mono) with automatic samples buffer?
391 {
392 dolog("adlib","Error registering sound channel for output!");
393 }
394 else
395 {
396 setVolume(&adlib_soundGenerator,NULL,ADLIB_VOLUME);
397 }
398 }
399 //dolog("adlib","sound channel added. registering ports...");
400 //Ignore unregistered channel, we need to be used by software!
401 register_PORTIN(baseport,&inadlib); //Status port (R)
402 //All output!
403 register_PORTOUT(baseport,&outadlib); //Address port (W)
404 register_PORTOUT(baseport+1,&outadlib); //Data port (W/O)
405 //dolog("adlib","Registering timer...");
406 addtimer(usesamplerate,&tickadlib,"AdlibAttackDecay",ADLIBMULTIPLIER,0,NULL); //We run at 49.716Khz, about every 20us.
407 //dolog("adlib","Ready"); //Ready to run!
408}
409
410void doneAdlib()
411{
412 if (__HW_DISABLED) return; //Abort!
413 removetimer("AdlibAttackDecay"); //Stop the audio channel!
414 if (__SOUND_ADLIB)
415 {
416 removechannel(&adlib_soundGenerator,NULL,0); //Stop the sound emulation?
417 }
418 //Unregister the ports!
419 register_PORTIN(baseport,NULL);
420 //All output!
421 register_PORTOUT(baseport,NULL);
422 register_PORTOUT(baseport+1,NULL);
423}