1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "audio/softsynth/fmtowns_pc98/towns_audio.h"
24 #include "audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
25
26 #include "common/debug.h"
27 #include "common/endian.h"
28 #include "common/util.h"
29 #include "common/textconsole.h"
30 #include "backends/audiocd/audiocd.h"
31
32 class TownsAudio_WaveTable {
33 friend class TownsAudioInterfaceInternal;
34 friend class TownsAudio_PcmChannel;
35 public:
36 TownsAudio_WaveTable();
37 ~TownsAudio_WaveTable();
38
39 private:
40 void readHeader(const uint8 *buffer);
41 void readData(const uint8 *buffer);
42 void clear();
43
44 char name[9];
45 int32 id;
46 uint32 size;
47 uint32 loopStart;
48 uint32 loopLen;
49 uint16 rate;
50 uint16 rateOffs;
51 uint16 baseNote;
52 int8 *data;
53 };
54
55 class TownsAudio_PcmChannel {
56 public:
57 TownsAudio_PcmChannel();
58 ~TownsAudio_PcmChannel();
59
60 void clear();
61
62 void loadData(TownsAudio_WaveTable *w);
63 void loadData(uint8 *buffer, uint32 size);
64
65 int initInstrument(uint8 ¬e, TownsAudio_WaveTable *&tables, int numTables);
66 void keyOn(uint8 note, uint8 velo, TownsAudio_WaveTable *w);
67 void keyOff();
68
69 void updateEnvelopeGenerator();
70
71 void setInstrument(uint8 *instr);
72 void setLevel(uint8 lvl);
73 void setPitch(uint32 pt);
74 void setBalance(uint8 blc);
75
76 void updateOutput();
77 int32 currentSampleLeft();
78 int32 currentSampleRight();
79
80 bool _keyPressed;
81 bool _reserved;
82 bool _activeKey;
83 bool _activeEffect;
84 bool _activeOutput;
85
86 private:
87 void setupLoop(uint32 loopStart, uint32 loopLen);
88 void setNote(uint8 note, TownsAudio_WaveTable *w, bool stepLimit = false);
89 void setVelo(uint8 velo);
90
91 void envAttack();
92 void envDecay();
93 void envSustain();
94 void envRelease();
95
96 uint8 *_curInstrument;
97
98 uint8 _note;
99
100 uint8 _velo;
101 uint8 _level;
102 uint8 _tl;
103
104 uint8 _panLeft;
105 uint8 _panRight;
106
107 int8 *_data;
108
109 uint32 _loopStart;
110 uint32 _loopLen;
111 uint32 _dataEnd;
112
113 uint16 _stepNote;
114 uint16 _stepPitch;
115 uint16 _step;
116
117 uint32 _pos;
118
119 uint8 _envTotalLevel;
120 uint8 _envAttackRate;
121 uint8 _envDecayRate;
122 uint8 _envSustainLevel;
123 uint8 _envSustainRate;
124 uint8 _envReleaseRate;
125 int16 _envStep;
126 int16 _envCurrentLevel;
127
128 EnvelopeState _envState;
129
130 int8 *_extData;
131
132 static const uint16 _pcmPhase1[];
133 static const uint16 _pcmPhase2[];
134 };
135
136 class TownsAudioInterfaceInternal : public TownsPC98_FmSynth {
137 private:
138 TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutex);
139 public:
140 ~TownsAudioInterfaceInternal();
141
142 static TownsAudioInterfaceInternal *addNewRef(Audio::Mixer *mixer, TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutex);
143 static void releaseRef(TownsAudioInterface *owner);
144
145 bool init();
146
147 int callback(int command, ...);
148 int processCommand(int command, va_list &args);
149
150 void setMusicVolume(int volume);
151 void setSoundEffectVolume(int volume);
152 // Defines the channels used as sound effect channels for the purpose of ScummVM GUI volume control.
153 // The first 6 bits are the 6 fm channels. The next 8 bits are pcm channels.
154 void setSoundEffectChanMask(int mask);
155
156 private:
157 bool assignPluginDriver(TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver);
158 void removePluginDriver(TownsAudioInterface *owner);
159
160 void nextTickEx(int32 *buffer, uint32 bufferSize);
161
162 void timerCallbackA();
163 void timerCallbackB();
164
165 typedef int (TownsAudioInterfaceInternal::*TownsAudioIntfCallback)(va_list &);
166 const TownsAudioIntfCallback *_intfOpcodes;
167
168 int intf_reset(va_list &args);
169 int intf_keyOn(va_list &args);
170 int intf_keyOff(va_list &args);
171 int intf_setPanPos(va_list &args);
172 int intf_setInstrument(va_list &args);
173 int intf_loadInstrument(va_list &args);
174 int intf_setPitch(va_list &args);
175 int intf_setLevel(va_list &args);
176 int intf_chanOff(va_list &args);
177 int intf_writeReg(va_list &args);
178 int intf_writeRegBuffer(va_list &args);
179 int intf_readRegBuffer(va_list &args);
180 int intf_setTimerA(va_list &args);
181 int intf_setTimerB(va_list &args);
182 int intf_enableTimerA(va_list &args);
183 int intf_enableTimerB(va_list &args);
184 int intf_loadSamples(va_list &args);
185 int intf_reserveEffectChannels(va_list &args);
186 int intf_loadWaveTable(va_list &args);
187 int intf_unloadWaveTable(va_list &args);
188 int intf_pcmPlayEffect(va_list &args);
189 int intf_pcmChanOff(va_list &args);
190 int intf_pcmEffectPlaying(va_list &args);
191 int intf_pcmDisableAllChannels(va_list &args);
192 int intf_fmKeyOn(va_list &args);
193 int intf_fmKeyOff(va_list &args);
194 int intf_fmSetPanPos(va_list &args);
195 int intf_fmSetInstrument(va_list &args);
196 int intf_fmLoadInstrument(va_list &args);
197 int intf_fmSetPitch(va_list &args);
198 int intf_fmSetLevel(va_list &args);
199 int intf_fmReset(va_list &args);
200 int intf_setOutputVolume(va_list &args);
201 int intf_resetOutputVolume(va_list &args);
202 int intf_getOutputVolume(va_list &args);
203 int intf_setOutputMute(va_list &args);
204 int intf_cdaToggle(va_list &args);
205 int intf_getOutputVolume2(va_list &args);
206 int intf_getOutputMute(va_list &args);
207 int intf_pcmUpdateEnvelopeGenerator(va_list &args);
208
209 int intf_notImpl(va_list &args);
210
211 void fmReset();
212 int fmKeyOn(int chan, int note, int velo);
213 int fmKeyOff(int chan);
214 int fmChanOff(int chan);
215 int fmSetPanPos(int chan, int mode);
216 int fmSetInstrument(int chan, int instrId);
217 int fmLoadInstrument(int instrId, const uint8 *data);
218 int fmSetPitch(int chan, int pitch);
219 int fmSetLevel(int chan, int lvl);
220
221 void bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value);
222
223 uint8 _fmChanPlaying;
224 uint8 _fmChanNote[6];
225 int16 _fmChanPitch[6];
226
227 uint8 *_fmSaveReg[2];
228 uint8 *_fmInstruments;
229
230 void pcmReset();
231 int pcmKeyOn(int chan, int note, int velo);
232 int pcmKeyOff(int chan);
233 int pcmChanOff(int chan);
234 int pcmSetPanPos(int chan, int mode);
235 int pcmSetInstrument(int chan, int instrId);
236 int pcmLoadInstrument(int instrId, const uint8 *data);
237 int pcmSetPitch(int chan, int pitch);
238 int pcmSetLevel(int chan, int lvl);
239
240 TownsAudio_PcmChannel *_pcmChan;
241
242 uint8 _numReservedChannels;
243 uint8 *_pcmInstruments;
244
245 TownsAudio_WaveTable *_waveTables;
246 uint8 _numWaveTables;
247 uint32 _waveTablesTotalDataSize;
248
249 void updateOutputVolume();
250 void updateOutputVolumeInternal();
251 uint8 _outputVolumeFlags;
252 uint8 _outputLevel[16];
253 uint8 _outputMute[16];
254 bool _updateOutputVol;
255
256 const uint32 _tickLength;
257 const uint32 _envDuration;
258 uint32 _timer;
259
260 uint16 _musicVolume;
261 uint16 _sfxVolume;
262 int _pcmSfxChanMask;
263
264 TownsAudioInterfacePluginDriver *_drv;
265 void *_drvOwner;
266 bool _externalMutex;
267 bool _ready;
268
269 static TownsAudioInterfaceInternal *_refInstance;
270 static int _refCount;
271
272 static const uint8 _chanFlags[];
273 static const uint16 _frequency[];
274 static const uint8 _carrier[];
275 static const uint8 _fmDefaultInstrument[];
276 };
277
TownsAudioInterfaceInternal(Audio::Mixer * mixer,TownsAudioInterface * owner,TownsAudioInterfacePluginDriver * driver,bool externalMutex)278 TownsAudioInterfaceInternal::TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutex) :
279 TownsPC98_FmSynth(mixer, kTypeTowns), _fmInstruments(0), _pcmInstruments(0), _pcmChan(0), _waveTables(0), _waveTablesTotalDataSize(0),
280 _tickLength(0x08), _envDuration(0x30), _timer(0), _drv(driver), _drvOwner(owner), _externalMutex(externalMutex), _pcmSfxChanMask(0), _outputVolumeFlags(0),
281 _fmChanPlaying(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume),
282 _numReservedChannels(0), _numWaveTables(0), _updateOutputVol(false), _ready(false) {
283
284 #define INTCB(x) &TownsAudioInterfaceInternal::intf_##x
285 static const TownsAudioIntfCallback intfCb[] = {
286 // 0
287 INTCB(reset),
288 INTCB(keyOn),
289 INTCB(keyOff),
290 INTCB(setPanPos),
291 // 4
292 INTCB(setInstrument),
293 INTCB(loadInstrument),
294 INTCB(notImpl),
295 INTCB(setPitch),
296 // 8
297 INTCB(setLevel),
298 INTCB(chanOff),
299 INTCB(notImpl),
300 INTCB(notImpl),
301 // 12
302 INTCB(notImpl),
303 INTCB(notImpl),
304 INTCB(notImpl),
305 INTCB(notImpl),
306 // 16
307 INTCB(notImpl),
308 INTCB(writeReg),
309 INTCB(notImpl),
310 INTCB(writeRegBuffer),
311 // 20
312 INTCB(readRegBuffer),
313 INTCB(setTimerA),
314 INTCB(setTimerB),
315 INTCB(enableTimerA),
316 // 24
317 INTCB(enableTimerB),
318 INTCB(notImpl),
319 INTCB(notImpl),
320 INTCB(notImpl),
321 // 28
322 INTCB(notImpl),
323 INTCB(notImpl),
324 INTCB(notImpl),
325 INTCB(notImpl),
326 // 32
327 INTCB(loadSamples),
328 INTCB(reserveEffectChannels),
329 INTCB(loadWaveTable),
330 INTCB(unloadWaveTable),
331 // 36
332 INTCB(notImpl),
333 INTCB(pcmPlayEffect),
334 INTCB(notImpl),
335 INTCB(pcmChanOff),
336 // 40
337 INTCB(pcmEffectPlaying),
338 INTCB(pcmDisableAllChannels),
339 INTCB(notImpl),
340 INTCB(notImpl),
341 // 44
342 INTCB(notImpl),
343 INTCB(notImpl),
344 INTCB(notImpl),
345 INTCB(notImpl),
346 // 48
347 INTCB(notImpl),
348 INTCB(notImpl),
349 INTCB(fmKeyOn),
350 INTCB(fmKeyOff),
351 // 52
352 INTCB(fmSetPanPos),
353 INTCB(fmSetInstrument),
354 INTCB(fmLoadInstrument),
355 INTCB(notImpl),
356 // 56
357 INTCB(fmSetPitch),
358 INTCB(fmSetLevel),
359 INTCB(fmReset),
360 INTCB(notImpl),
361 // 60
362 INTCB(notImpl),
363 INTCB(notImpl),
364 INTCB(notImpl),
365 INTCB(notImpl),
366 // 64
367 INTCB(notImpl),
368 INTCB(notImpl),
369 INTCB(notImpl),
370 INTCB(setOutputVolume),
371 // 68
372 INTCB(resetOutputVolume),
373 INTCB(getOutputVolume),
374 INTCB(setOutputMute),
375 INTCB(notImpl),
376 // 72
377 INTCB(notImpl),
378 INTCB(cdaToggle),
379 INTCB(getOutputVolume2),
380 INTCB(getOutputMute),
381 // 76
382 INTCB(notImpl),
383 INTCB(notImpl),
384 INTCB(notImpl),
385 INTCB(notImpl),
386 // 80
387 INTCB(pcmUpdateEnvelopeGenerator),
388 INTCB(notImpl)
389 };
390 #undef INTCB
391
392 _intfOpcodes = intfCb;
393
394 memset(_fmSaveReg, 0, sizeof(_fmSaveReg));
395 memset(_fmChanNote, 0, sizeof(_fmChanNote));
396 memset(_fmChanPitch, 0, sizeof(_fmChanPitch));
397 memset(_outputLevel, 0, sizeof(_outputLevel));
398 memset(_outputMute, 0, sizeof(_outputMute));
399 }
400
~TownsAudioInterfaceInternal()401 TownsAudioInterfaceInternal::~TownsAudioInterfaceInternal() {
402 deinit();
403 Common::StackLock lock(_mutex);
404 _ready = false;
405
406 delete[] _fmSaveReg[0];
407 delete[] _fmSaveReg[1];
408 delete[] _fmInstruments;
409 delete[] _pcmInstruments;
410 delete[] _waveTables;
411 delete[] _pcmChan;
412 }
413
addNewRef(Audio::Mixer * mixer,TownsAudioInterface * owner,TownsAudioInterfacePluginDriver * driver,bool externalMutex)414 TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::addNewRef(Audio::Mixer *mixer, TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutex) {
415 _refCount++;
416 if (_refCount == 1 && _refInstance == 0)
417 _refInstance = new TownsAudioInterfaceInternal(mixer, owner, driver, externalMutex);
418 else if (_refCount < 2 || _refInstance == 0)
419 error("TownsAudioInterfaceInternal::addNewRef(): Internal reference management failure");
420 else if (!_refInstance->assignPluginDriver(owner, driver))
421 error("TownsAudioInterfaceInternal::addNewRef(): Plugin driver conflict");
422
423 return _refInstance;
424 }
425
releaseRef(TownsAudioInterface * owner)426 void TownsAudioInterfaceInternal::releaseRef(TownsAudioInterface *owner) {
427 if (!_refCount)
428 return;
429
430 _refCount--;
431
432 if (_refCount) {
433 if (_refInstance)
434 _refInstance->removePluginDriver(owner);
435 } else {
436 delete _refInstance;
437 _refInstance = 0;
438 }
439 }
440
init()441 bool TownsAudioInterfaceInternal::init() {
442 if (_ready)
443 return true;
444
445 _fmSaveReg[0] = new uint8[256];
446 _fmSaveReg[1] = new uint8[256];
447 _fmInstruments = new uint8[128 * 48];
448 _pcmInstruments = new uint8[32 * 128];
449 _waveTables = new TownsAudio_WaveTable[128];
450 _pcmChan = new TownsAudio_PcmChannel[8];
451
452 _timer = 0;
453
454 if (!TownsPC98_FmSynth::init())
455 return false;
456
457
458 setVolumeChannelMasks(-1, 0);
459
460 _ready = true;
461 callback(0);
462
463 return true;
464 }
465
callback(int command,...)466 int TownsAudioInterfaceInternal::callback(int command, ...) {
467 Common::StackLock lock(_mutex);
468 if (!_ready)
469 return 1;
470
471 va_list args;
472 va_start(args, command);
473
474 int res = processCommand(command, args);
475
476 va_end(args);
477 return res;
478 }
479
processCommand(int command,va_list & args)480 int TownsAudioInterfaceInternal::processCommand(int command, va_list &args) {
481 Common::StackLock lock(_mutex);
482 if (!_ready)
483 return 1;
484
485 if (command < 0 || command > 81)
486 return 4;
487
488 int res = (this->*_intfOpcodes[command])(args);
489
490 return res;
491 }
492
setMusicVolume(int volume)493 void TownsAudioInterfaceInternal::setMusicVolume(int volume) {
494 Common::StackLock lock(_mutex);
495 _musicVolume = CLIP<uint16>(volume, 0, Audio::Mixer::kMaxMixerVolume);
496 setVolumeIntern(_musicVolume, _sfxVolume);
497 }
498
setSoundEffectVolume(int volume)499 void TownsAudioInterfaceInternal::setSoundEffectVolume(int volume) {
500 Common::StackLock lock(_mutex);
501 _sfxVolume = CLIP<uint16>(volume, 0, Audio::Mixer::kMaxMixerVolume);
502 setVolumeIntern(_musicVolume, _sfxVolume);
503 }
504
setSoundEffectChanMask(int mask)505 void TownsAudioInterfaceInternal::setSoundEffectChanMask(int mask) {
506 Common::StackLock lock(_mutex);
507 _pcmSfxChanMask = mask >> 6;
508 mask &= 0x3f;
509 setVolumeChannelMasks(~mask, mask);
510 }
511
assignPluginDriver(TownsAudioInterface * owner,TownsAudioInterfacePluginDriver * driver)512 bool TownsAudioInterfaceInternal::assignPluginDriver(TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver) {
513 Common::StackLock lock(_mutex);
514 if (_refCount <= 1)
515 return true;
516
517 if (_drv) {
518 if (driver && driver != _drv)
519 return false;
520 } else {
521 _drv = driver;
522 _drvOwner = owner;
523 }
524
525 return true;
526 }
527
removePluginDriver(TownsAudioInterface * owner)528 void TownsAudioInterfaceInternal::removePluginDriver(TownsAudioInterface *owner) {
529 Common::StackLock lock(_mutex);
530 if (_drvOwner == owner)
531 _drv = 0;
532 }
533
nextTickEx(int32 * buffer,uint32 bufferSize)534 void TownsAudioInterfaceInternal::nextTickEx(int32 *buffer, uint32 bufferSize) {
535 Common::StackLock lock(_mutex);
536 if (!_ready)
537 return;
538
539 if (_updateOutputVol)
540 updateOutputVolumeInternal();
541
542 for (uint32 i = 0; i < bufferSize; i++) {
543 _timer += _tickLength;
544 while (_timer >= _envDuration) {
545 _timer -= _envDuration;
546
547 for (int ii = 0; ii < 8; ii++)
548 _pcmChan[ii].updateOutput();
549 }
550
551 int32 finOutL = 0;
552 int32 finOutR = 0;
553
554 for (int ii = 0; ii < 8; ii++) {
555 if (_pcmChan[ii]._activeOutput) {
556 int32 oL = _pcmChan[ii].currentSampleLeft();
557 int32 oR = _pcmChan[ii].currentSampleRight();
558 if ((1 << ii) & (~_pcmSfxChanMask)) {
559 oL = (oR * _musicVolume) / Audio::Mixer::kMaxMixerVolume;
560 oR = (oR * _musicVolume) / Audio::Mixer::kMaxMixerVolume;
561 }
562 if ((1 << ii) & _pcmSfxChanMask) {
563 oL = (oL * _sfxVolume) / Audio::Mixer::kMaxMixerVolume;
564 oR = (oR * _sfxVolume) / Audio::Mixer::kMaxMixerVolume;
565 }
566 finOutL += oL;
567 finOutR += oR;
568
569 if (!(_pcmChan[ii]._activeKey || _pcmChan[ii]._activeEffect))
570 _pcmChan[ii]._activeOutput = false;
571 }
572 }
573
574 buffer[i << 1] += finOutL;
575 buffer[(i << 1) + 1] += finOutR;
576 }
577 }
578
timerCallbackA()579 void TownsAudioInterfaceInternal::timerCallbackA() {
580 if (_drv && _ready) {
581 int restore = 0;
582 if (_externalMutex) {
583 for (; restore < _mixerThreadLockCounter; ++restore)
584 _mutex.unlock();
585 }
586 _drv->timerCallback(0);
587 while (restore--)
588 _mutex.lock();
589 }
590 }
591
timerCallbackB()592 void TownsAudioInterfaceInternal::timerCallbackB() {
593 if (_ready) {
594 if (_drv) {
595 int restore = 0;
596 if (_externalMutex) {
597 for (; restore < _mixerThreadLockCounter; ++restore)
598 _mutex.unlock();
599 }
600 _drv->timerCallback(1);
601 while (restore--)
602 _mutex.lock();
603 }
604 callback(80);
605 }
606 }
607
intf_reset(va_list & args)608 int TownsAudioInterfaceInternal::intf_reset(va_list &args) {
609 fmReset();
610 pcmReset();
611 callback(68);
612 return 0;
613 }
614
intf_keyOn(va_list & args)615 int TownsAudioInterfaceInternal::intf_keyOn(va_list &args) {
616 int chan = va_arg(args, int);
617 int note = va_arg(args, int);
618 int velo = va_arg(args, int);
619 return (chan & 0x40) ? pcmKeyOn(chan, note, velo) : fmKeyOn(chan, note, velo);
620 }
621
intf_keyOff(va_list & args)622 int TownsAudioInterfaceInternal::intf_keyOff(va_list &args) {
623 int chan = va_arg(args, int);
624 return (chan & 0x40) ? pcmKeyOff(chan) : fmKeyOff(chan);
625 }
626
intf_setPanPos(va_list & args)627 int TownsAudioInterfaceInternal::intf_setPanPos(va_list &args) {
628 int chan = va_arg(args, int);
629 int mode = va_arg(args, int);
630 return (chan & 0x40) ? pcmSetPanPos(chan, mode) : fmSetPanPos(chan, mode);
631 }
632
intf_setInstrument(va_list & args)633 int TownsAudioInterfaceInternal::intf_setInstrument(va_list &args) {
634 int chan = va_arg(args, int);
635 int instrId = va_arg(args, int);
636 return (chan & 0x40) ? pcmSetInstrument(chan, instrId) : fmSetInstrument(chan, instrId);
637 }
638
intf_loadInstrument(va_list & args)639 int TownsAudioInterfaceInternal::intf_loadInstrument(va_list &args) {
640 int chanType = va_arg(args, int);
641 int instrId = va_arg(args, int);
642 uint8 *instrData = va_arg(args, uint8 *);
643 return (chanType & 0x40) ? pcmLoadInstrument(instrId, instrData) : fmLoadInstrument(instrId, instrData);
644 }
645
intf_setPitch(va_list & args)646 int TownsAudioInterfaceInternal::intf_setPitch(va_list &args) {
647 int chan = va_arg(args, int);
648 int16 pitch = (int16)(va_arg(args, int) & 0xffff);
649 return (chan & 0x40) ? pcmSetPitch(chan, pitch) : fmSetPitch(chan, pitch);
650 }
651
intf_setLevel(va_list & args)652 int TownsAudioInterfaceInternal::intf_setLevel(va_list &args) {
653 int chan = va_arg(args, int);
654 int lvl = va_arg(args, int);
655 return (chan & 0x40) ? pcmSetLevel(chan, lvl) : fmSetLevel(chan, lvl);
656 }
657
intf_chanOff(va_list & args)658 int TownsAudioInterfaceInternal::intf_chanOff(va_list &args) {
659 int chan = va_arg(args, int);
660 return (chan & 0x40) ? pcmChanOff(chan) : fmChanOff(chan);
661 }
662
intf_writeReg(va_list & args)663 int TownsAudioInterfaceInternal::intf_writeReg(va_list &args) {
664 int part = va_arg(args, int) ? 1 : 0;
665 int reg = va_arg(args, int);
666 int val = va_arg(args, int);
667 if ((!part && reg < 0x20) || (part && reg < 0x30) || (reg > 0xb6))
668 return 3;
669
670 bufferedWriteReg(part, reg, val);
671 return 0;
672 }
673
intf_writeRegBuffer(va_list & args)674 int TownsAudioInterfaceInternal::intf_writeRegBuffer(va_list &args) {
675 int part = va_arg(args, int) ? 1 : 0;
676 int reg = va_arg(args, int);
677 int val = va_arg(args, int);
678
679 if ((!part && reg < 0x20) || (part && reg < 0x30) || (reg > 0xef))
680 return 3;
681
682 _fmSaveReg[part][reg] = val;
683 return 0;
684 }
685
intf_readRegBuffer(va_list & args)686 int TownsAudioInterfaceInternal::intf_readRegBuffer(va_list &args) {
687 int part = va_arg(args, int) ? 1 : 0;
688 int reg = va_arg(args, int);
689 uint8 *dst = va_arg(args, uint8 *);
690 *dst = 0;
691
692 if ((!part && reg < 0x20) || (part && reg < 0x30) || (reg > 0xef))
693 return 3;
694
695 *dst = _fmSaveReg[part][reg];
696 return 0;
697 }
698
intf_setTimerA(va_list & args)699 int TownsAudioInterfaceInternal::intf_setTimerA(va_list &args) {
700 int enable = va_arg(args, int);
701 int tempo = va_arg(args, int);
702
703 if (enable) {
704 bufferedWriteReg(0, 0x25, tempo & 3);
705 bufferedWriteReg(0, 0x24, (tempo >> 2) & 0xff);
706 bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x05);
707 } else {
708 bufferedWriteReg(0, 0x27, (_fmSaveReg[0][0x27] & 0xfa) | 0x10);
709 }
710
711 return 0;
712 }
713
intf_setTimerB(va_list & args)714 int TownsAudioInterfaceInternal::intf_setTimerB(va_list &args) {
715 int enable = va_arg(args, int);
716 int tempo = va_arg(args, int);
717
718 if (enable) {
719 bufferedWriteReg(0, 0x26, tempo & 0xff);
720 bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x0A);
721 } else {
722 bufferedWriteReg(0, 0x27, (_fmSaveReg[0][0x27] & 0xf5) | 0x20);
723 }
724
725 return 0;
726 }
727
intf_enableTimerA(va_list & args)728 int TownsAudioInterfaceInternal::intf_enableTimerA(va_list &args) {
729 bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x15);
730 return 0;
731 }
732
intf_enableTimerB(va_list & args)733 int TownsAudioInterfaceInternal::intf_enableTimerB(va_list &args) {
734 bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x2a);
735 return 0;
736 }
737
intf_loadSamples(va_list & args)738 int TownsAudioInterfaceInternal::intf_loadSamples(va_list &args) {
739 uint32 dest = va_arg(args, uint32);
740 int size = va_arg(args, int);
741 uint8 *src = va_arg(args, uint8*);
742
743 if (dest >= 65536 || size == 0 || size > 65536)
744 return 3;
745 if (size + dest > 65536)
746 // EOB II FM-TOWNS tries to load more than 65536 bytes of wave sounds for the outro sequence.
747 // This means that some sfx would not play. Since we don't really need the memory limit,
748 // I have commented out the error return and added a debug message instead.
749 debugN(9, "FM-TOWNS AUDIO: exceeding wave memory size by %d bytes", size + dest - 65536);
750 // return 5;
751
752 int dwIndex = _numWaveTables - 1;
753 for (uint32 t = _waveTablesTotalDataSize; dwIndex && (dest < t); dwIndex--)
754 t -= _waveTables[dwIndex].size;
755
756 TownsAudio_WaveTable *s = &_waveTables[dwIndex];
757 _waveTablesTotalDataSize -= s->size;
758 s->size = size;
759 s->readData(src);
760 _waveTablesTotalDataSize += s->size;
761
762 return 0;
763 }
764
intf_reserveEffectChannels(va_list & args)765 int TownsAudioInterfaceInternal::intf_reserveEffectChannels(va_list &args) {
766 int numChan = va_arg(args, int);
767 if (numChan > 8)
768 return 3;
769 if ((numChan << 13) + _waveTablesTotalDataSize > 65536)
770 return 5;
771
772 if (numChan == _numReservedChannels)
773 return 0;
774
775 if (numChan < _numReservedChannels) {
776 int c = 8 - _numReservedChannels;
777 for (int i = numChan; i; i--)
778 _pcmChan[c--]._activeEffect = false;
779 } else {
780 int c = 7 - _numReservedChannels;
781 for (int i = numChan - _numReservedChannels; i; i--) {
782 _pcmChan[c]._keyPressed = false;
783 _pcmChan[c--]._activeKey = false;
784 }
785 }
786
787 _numReservedChannels = numChan;
788 for (int i = 0; i < 8; i++)
789 _pcmChan[i]._reserved = i >= (8 - _numReservedChannels) ? true : false;
790
791 return 0;
792 }
793
intf_loadWaveTable(va_list & args)794 int TownsAudioInterfaceInternal::intf_loadWaveTable(va_list &args) {
795 uint8 *data = va_arg(args, uint8 *);
796 if (_numWaveTables > 127)
797 return 3;
798
799 TownsAudio_WaveTable w;
800 w.readHeader(data);
801 if (!w.size)
802 return 6;
803
804 if (_waveTablesTotalDataSize + w.size > 65504)
805 return 5;
806
807 callback(41);
808
809 for (int i = 0; i < _numWaveTables; i++) {
810 if (_waveTables[i].id == w.id)
811 return 10;
812 }
813
814 TownsAudio_WaveTable *s = &_waveTables[_numWaveTables++];
815 s->readHeader(data);
816
817 _waveTablesTotalDataSize += s->size;
818 int res = callback(32, _waveTablesTotalDataSize, s->size, data + 32);
819 if (res) {
820 _waveTablesTotalDataSize -= s->size;
821 _numWaveTables--;
822 }
823
824 return res;
825 }
826
intf_unloadWaveTable(va_list & args)827 int TownsAudioInterfaceInternal::intf_unloadWaveTable(va_list &args) {
828 int id = va_arg(args, int);
829 callback(41);
830
831 if (id == -1) {
832 for (int i = 0; i < 128; i++)
833 _waveTables[i].clear();
834 _numWaveTables = 0;
835 _waveTablesTotalDataSize = 0;
836 } else {
837 if (_waveTables) {
838 for (int i = 0; i < _numWaveTables; i++) {
839 if (_waveTables[i].id == id) {
840 _numWaveTables--;
841 _waveTablesTotalDataSize -= _waveTables[i].size;
842 _waveTables[i].clear();
843 for (; i < _numWaveTables; i++)
844 _waveTables[i] = _waveTables[i + 1];
845 return 0;
846 }
847 }
848 return 9;
849 }
850 }
851
852 return 0;
853 }
854
intf_pcmPlayEffect(va_list & args)855 int TownsAudioInterfaceInternal::intf_pcmPlayEffect(va_list &args) {
856 int chan = va_arg(args, int);
857 int note = va_arg(args, int);
858 int velo = va_arg(args, int);
859 uint8 *data = va_arg(args, uint8 *);
860
861 if (chan < 0x40 || chan > 0x47)
862 return 1;
863
864 if (note & 0x80 || velo & 0x80)
865 return 3;
866
867 chan -= 0x40;
868
869 if (!_pcmChan[chan]._reserved)
870 return 7;
871
872 if (_pcmChan[chan]._activeEffect)
873 return 2;
874
875 TownsAudio_WaveTable w;
876 w.readHeader(data);
877
878 if (w.size < (w.loopStart + w.loopLen))
879 return 13;
880
881 if (!w.size)
882 return 6;
883
884 TownsAudio_PcmChannel *p = &_pcmChan[chan];
885
886 p->loadData(data + 32, w.size);
887 p->keyOn(note, velo, &w);
888
889 return 0;
890 }
891
intf_pcmChanOff(va_list & args)892 int TownsAudioInterfaceInternal::intf_pcmChanOff(va_list &args) {
893 int chan = va_arg(args, int);
894 pcmChanOff(chan);
895 return 0;
896 }
897
intf_pcmEffectPlaying(va_list & args)898 int TownsAudioInterfaceInternal::intf_pcmEffectPlaying(va_list &args) {
899 int chan = va_arg(args, int);
900 if (chan < 0x40 || chan > 0x47)
901 return 1;
902 chan -= 0x40;
903 return _pcmChan[chan]._activeEffect ? 1 : 0;
904 }
905
intf_pcmDisableAllChannels(va_list & args)906 int TownsAudioInterfaceInternal::intf_pcmDisableAllChannels(va_list &args) {
907 for (int i = 0; i < 8; ++i)
908 _pcmChan[i]._activeOutput = false;
909 return 0;
910 }
911
intf_fmKeyOn(va_list & args)912 int TownsAudioInterfaceInternal::intf_fmKeyOn(va_list &args) {
913 int chan = va_arg(args, int);
914 int note = va_arg(args, int);
915 int velo = va_arg(args, int);
916 return fmKeyOn(chan, note, velo);
917 }
918
intf_fmKeyOff(va_list & args)919 int TownsAudioInterfaceInternal::intf_fmKeyOff(va_list &args) {
920 int chan = va_arg(args, int);
921 return fmKeyOff(chan);
922 }
923
intf_fmSetPanPos(va_list & args)924 int TownsAudioInterfaceInternal::intf_fmSetPanPos(va_list &args) {
925 int chan = va_arg(args, int);
926 int mode = va_arg(args, int);
927 return fmSetPanPos(chan, mode);
928 }
929
intf_fmSetInstrument(va_list & args)930 int TownsAudioInterfaceInternal::intf_fmSetInstrument(va_list &args) {
931 int chan = va_arg(args, int);
932 int instrId = va_arg(args, int);
933 return fmSetInstrument(chan, instrId);
934 }
935
intf_fmLoadInstrument(va_list & args)936 int TownsAudioInterfaceInternal::intf_fmLoadInstrument(va_list &args) {
937 int instrId = va_arg(args, int);
938 uint8 *instrData = va_arg(args, uint8 *);
939 return fmLoadInstrument(instrId, instrData);
940 }
941
intf_fmSetPitch(va_list & args)942 int TownsAudioInterfaceInternal::intf_fmSetPitch(va_list &args) {
943 int chan = va_arg(args, int);
944 uint16 freq = va_arg(args, int) & 0xffff;
945 return fmSetPitch(chan, freq);
946 }
947
intf_fmSetLevel(va_list & args)948 int TownsAudioInterfaceInternal::intf_fmSetLevel(va_list &args) {
949 int chan = va_arg(args, int);
950 int lvl = va_arg(args, int);
951 return fmSetLevel(chan, lvl);
952 }
953
intf_fmReset(va_list & args)954 int TownsAudioInterfaceInternal::intf_fmReset(va_list &args) {
955 fmReset();
956 return 0;
957 }
958
intf_setOutputVolume(va_list & args)959 int TownsAudioInterfaceInternal::intf_setOutputVolume(va_list &args) {
960 int chanType = va_arg(args, int);
961 int left = va_arg(args, int);
962 int right = va_arg(args, int);
963
964 if (left & 0xff80 || right & 0xff80)
965 return 3;
966
967 static const uint8 flags[] = { 0x0C, 0x30, 0x40, 0x80 };
968
969 uint8 chan = (chanType & 0x40) ? 8 : 12;
970
971 chanType &= 3;
972 left = (left & 0x7e) >> 1;
973 right = (right & 0x7e) >> 1;
974
975 if (chan == 12)
976 _outputVolumeFlags |= flags[chanType];
977 else
978 _outputVolumeFlags &= ~flags[chanType];
979
980 if (chanType > 1) {
981 _outputLevel[chan + chanType] = left;
982 _outputMute[chan + chanType] = 0;
983 } else {
984 if (chanType == 0)
985 chan -= 8;
986 _outputLevel[chan] = left;
987 _outputLevel[chan + 1] = right;
988 _outputMute[chan] = _outputMute[chan + 1] = 0;
989 }
990
991 updateOutputVolume();
992
993 return 0;
994 }
995
intf_resetOutputVolume(va_list & args)996 int TownsAudioInterfaceInternal::intf_resetOutputVolume(va_list &args) {
997 memset(_outputLevel, 0, sizeof(_outputLevel));
998 _outputVolumeFlags = 0;
999 updateOutputVolume();
1000 return 0;
1001 }
1002
intf_getOutputVolume(va_list & args)1003 int TownsAudioInterfaceInternal::intf_getOutputVolume(va_list &args) {
1004 int chanType = va_arg(args, int);
1005 int *left = va_arg(args, int*);
1006 int *right = va_arg(args, int*);
1007
1008 uint8 chan = (chanType & 0x40) ? 8 : 12;
1009 chanType &= 3;
1010
1011 if (chanType > 1) {
1012 *left = _outputLevel[chan + chanType] & 0x3f;
1013 } else {
1014 if (chanType == 0)
1015 chan -= 8;
1016 *left = _outputLevel[chan] & 0x3f;
1017 *right = _outputLevel[chan + 1] & 0x3f;
1018 }
1019
1020 return 0;
1021 }
1022
intf_setOutputMute(va_list & args)1023 int TownsAudioInterfaceInternal::intf_setOutputMute(va_list &args) {
1024 int flags = va_arg(args, int);
1025 _outputVolumeFlags = flags;
1026 uint8 mute = flags & 3;
1027 uint8 f = flags & 0xff;
1028
1029 memset(_outputMute, 1, 8);
1030 if (mute & 2)
1031 memset(&_outputMute[12], 1, 4);
1032 if (mute & 1)
1033 memset(&_outputMute[8], 1, 4);
1034
1035 _outputMute[(f < 0x80) ? 11 : 15] = 0;
1036 f += f;
1037 _outputMute[(f < 0x80) ? 10 : 14] = 0;
1038 f += f;
1039 _outputMute[(f < 0x80) ? 8 : 12] = 0;
1040 f += f;
1041 _outputMute[(f < 0x80) ? 9 : 13] = 0;
1042 f += f;
1043 _outputMute[(f < 0x80) ? 0 : 4] = 0;
1044 f += f;
1045 _outputMute[(f < 0x80) ? 1 : 5] = 0;
1046 f += f;
1047
1048 updateOutputVolume();
1049 return 0;
1050 }
1051
intf_cdaToggle(va_list & args)1052 int TownsAudioInterfaceInternal::intf_cdaToggle(va_list &args) {
1053 //int mode = va_arg(args, int);
1054 //_unkMask = mode ? 0x7f : 0x3f;
1055 return 0;
1056 }
1057
intf_getOutputVolume2(va_list & args)1058 int TownsAudioInterfaceInternal::intf_getOutputVolume2(va_list &args) {
1059 return 0;
1060 }
1061
intf_getOutputMute(va_list & args)1062 int TownsAudioInterfaceInternal::intf_getOutputMute (va_list &args) {
1063 return 0;
1064 }
1065
intf_pcmUpdateEnvelopeGenerator(va_list & args)1066 int TownsAudioInterfaceInternal::intf_pcmUpdateEnvelopeGenerator(va_list &args) {
1067 for (int i = 0; i < 8; i++)
1068 _pcmChan[i].updateEnvelopeGenerator();
1069 return 0;
1070 }
1071
intf_notImpl(va_list & args)1072 int TownsAudioInterfaceInternal::intf_notImpl(va_list &args) {
1073 return 4;
1074 }
1075
fmReset()1076 void TownsAudioInterfaceInternal::fmReset() {
1077 TownsPC98_FmSynth::reset();
1078
1079 _fmChanPlaying = 0;
1080 memset(_fmChanNote, 0, sizeof(_fmChanNote));
1081 memset(_fmChanPitch, 0, sizeof(_fmChanPitch));
1082
1083 memset(_fmSaveReg[0], 0, 240);
1084 memset(&_fmSaveReg[0][240], 0x7f, 16);
1085 memset(_fmSaveReg[1], 0, 256);
1086 memset(&_fmSaveReg[1][240], 0x7f, 16);
1087 _fmSaveReg[0][243] = _fmSaveReg[0][247] = _fmSaveReg[0][251] = _fmSaveReg[0][255] = _fmSaveReg[1][243] = _fmSaveReg[1][247] = _fmSaveReg[1][251] = _fmSaveReg[1][255] = 0xff;
1088
1089 for (int i = 0; i < 128; i++)
1090 fmLoadInstrument(i, _fmDefaultInstrument);
1091
1092 bufferedWriteReg(0, 0x21, 0);
1093 bufferedWriteReg(0, 0x2C, 0x80);
1094 bufferedWriteReg(0, 0x2B, 0);
1095 bufferedWriteReg(0, 0x27, 0x30);
1096
1097 for (int i = 0; i < 6; i++) {
1098 fmKeyOff(i);
1099 fmSetInstrument(i, 0);
1100 fmSetLevel(i, 127);
1101 }
1102 }
1103
fmKeyOn(int chan,int note,int velo)1104 int TownsAudioInterfaceInternal::fmKeyOn(int chan, int note, int velo) {
1105 if (chan > 5)
1106 return 1;
1107 if (note < 12 || note > 107 || (velo & 0x80))
1108 return 3;
1109 if (_fmChanPlaying & _chanFlags[chan])
1110 return 2;
1111
1112 _fmChanPlaying |= _chanFlags[chan];
1113 note -= 12;
1114
1115 _fmChanNote[chan] = note;
1116 int16 pitch = _fmChanPitch[chan];
1117
1118 uint8 part = chan > 2 ? 1 : 0;
1119 if (chan > 2)
1120 chan -= 3;
1121
1122 int frq = 0;
1123 uint8 bl = 0;
1124
1125 if (note) {
1126 frq = _frequency[(note - 1) % 12];
1127 bl = (note - 1) / 12;
1128 } else {
1129 frq = 616;
1130 }
1131
1132 frq += pitch;
1133
1134 if (frq < 616) {
1135 if (!bl) {
1136 frq = 616;
1137 } else {
1138 frq += 616;
1139 --bl;
1140 }
1141 } else if (frq > 1232) {
1142 if (bl == 7) {
1143 frq = 15500;
1144 } else {
1145 frq -= 616;
1146 ++bl;
1147 }
1148 }
1149
1150 frq |= (bl << 11);
1151
1152 bufferedWriteReg(part, chan + 0xa4, (frq >> 8) & 0xff);
1153 bufferedWriteReg(part, chan + 0xa0, frq & 0xff);
1154
1155 velo = (velo >> 2) + 96;
1156 uint16 c = _carrier[_fmSaveReg[part][0xb0 + chan] & 7];
1157 _fmSaveReg[part][0xe0 + chan] = velo;
1158
1159 for (uint8 reg = 0x40 + chan; reg < 0x50; reg += 4) {
1160 c += c;
1161 if (c & 0x100) {
1162 c &= 0xff;
1163 bufferedWriteReg(part, reg, (((((((_fmSaveReg[part][0x80 + reg] ^ 0x7f) * velo) >> 7) + 1) * _fmSaveReg[part][0xd0 + chan]) >> 7) + 1) ^ 0x7f);
1164 }
1165 }
1166
1167 uint8 v = chan;
1168 if (part)
1169 v |= 4;
1170
1171 for (uint8 reg = 0x80 + chan; reg < 0x90; reg += 4)
1172 writeReg(part, reg, _fmSaveReg[part][reg] | 0x0f);
1173
1174 writeReg(0, 0x28, v);
1175
1176 for (uint8 reg = 0x80 + chan; reg < 0x90; reg += 4)
1177 writeReg(part, reg, _fmSaveReg[part][reg]);
1178
1179 bufferedWriteReg(0, 0x28, v | 0xf0);
1180
1181 return 0;
1182 }
1183
fmKeyOff(int chan)1184 int TownsAudioInterfaceInternal::fmKeyOff(int chan) {
1185 if (chan > 5)
1186 return 1;
1187 _fmChanPlaying &= ~_chanFlags[chan];
1188 if (chan > 2)
1189 chan++;
1190 bufferedWriteReg(0, 0x28, chan);
1191 return 0;
1192 }
1193
fmChanOff(int chan)1194 int TownsAudioInterfaceInternal::fmChanOff(int chan) {
1195 if (chan > 5)
1196 return 1;
1197 _fmChanPlaying &= ~_chanFlags[chan];
1198
1199 uint8 part = chan > 2 ? 1 : 0;
1200 if (chan > 2)
1201 chan -= 3;
1202
1203 for (uint8 reg = 0x80 + chan; reg < 0x90; reg += 4)
1204 writeReg(part, reg, _fmSaveReg[part][reg] | 0x0f);
1205
1206 if (part)
1207 chan += 4;
1208 writeReg(0, 0x28, chan);
1209 return 0;
1210 }
1211
fmSetPanPos(int chan,int value)1212 int TownsAudioInterfaceInternal::fmSetPanPos(int chan, int value) {
1213 if (chan > 5)
1214 return 1;
1215
1216 uint8 part = chan > 2 ? 1 : 0;
1217 if (chan > 2)
1218 chan -= 3;
1219
1220 if (value > 0x40)
1221 value = 0x40;
1222 else if (value < 0x40)
1223 value = 0x80;
1224 else
1225 value = 0xC0;
1226
1227 bufferedWriteReg(part, 0xb4 + chan, (_fmSaveReg[part][0xb4 + chan] & 0x3f) | value);
1228 return 0;
1229 }
1230
fmSetInstrument(int chan,int instrId)1231 int TownsAudioInterfaceInternal::fmSetInstrument(int chan, int instrId) {
1232 if (chan > 5)
1233 return 1;
1234 if (instrId > 127)
1235 return 3;
1236
1237 uint8 part = chan > 2 ? 1 : 0;
1238 if (chan > 2)
1239 chan -= 3;
1240
1241 uint8 *src = &_fmInstruments[instrId * 48 + 8];
1242
1243 uint16 c = _carrier[src[24] & 7];
1244 uint8 reg = 0x30 + chan;
1245
1246 for (; reg < 0x40; reg += 4)
1247 bufferedWriteReg(part, reg, *src++);
1248
1249 for (; reg < 0x50; reg += 4) {
1250 uint8 v = *src++;
1251 _fmSaveReg[part][0x80 + reg] = _fmSaveReg[part][reg] = v;
1252 c += c;
1253 if (c & 0x100) {
1254 c &= 0xff;
1255 v = 127;
1256 }
1257 writeReg(part, reg, v);
1258 }
1259
1260 for (; reg < 0x90; reg += 4)
1261 bufferedWriteReg(part, reg, *src++);
1262
1263 reg += 0x20;
1264 bufferedWriteReg(part, reg, *src++);
1265
1266 uint8 v = *src++;
1267 reg += 4;
1268 if (v < 64)
1269 v |= (_fmSaveReg[part][reg] & 0xc0);
1270 bufferedWriteReg(part, reg, v);
1271
1272 return 0;
1273 }
1274
fmLoadInstrument(int instrId,const uint8 * data)1275 int TownsAudioInterfaceInternal::fmLoadInstrument(int instrId, const uint8 *data) {
1276 if (instrId > 127)
1277 return 3;
1278 assert(data);
1279 memcpy(&_fmInstruments[instrId * 48], data, 48);
1280 return 0;
1281 }
1282
fmSetPitch(int chan,int pitch)1283 int TownsAudioInterfaceInternal::fmSetPitch(int chan, int pitch) {
1284 if (chan > 5)
1285 return 1;
1286
1287 uint8 bl = _fmChanNote[chan];
1288 int frq = 0;
1289
1290 if (pitch < 0) {
1291 if (bl) {
1292 if (pitch < -8008)
1293 pitch = -8008;
1294 pitch *= -1;
1295 pitch /= 13;
1296 frq = _frequency[(bl - 1) % 12] - pitch;
1297 bl = (bl - 1) / 12;
1298 _fmChanPitch[chan] = -pitch;
1299
1300 if (frq < 616) {
1301 if (bl) {
1302 frq += 616;
1303 bl--;
1304 } else {
1305 frq = 616;
1306 bl = 0;
1307 }
1308 }
1309 } else {
1310 frq = 616;
1311 bl = 0;
1312 }
1313
1314 } else if (pitch > 0) {
1315 if (bl < 96) {
1316 if (pitch > 8008)
1317 pitch = 8008;
1318 pitch /= 13;
1319
1320 if (bl) {
1321 frq = _frequency[(bl - 1) % 12] + pitch;
1322 bl = (bl - 1) / 12;
1323 } else {
1324 frq = 616;
1325 bl = 0;
1326 }
1327
1328 _fmChanPitch[chan] = pitch;
1329
1330 if (frq > 1232) {
1331 if (bl < 7) {
1332 frq -= 616;
1333 bl++;
1334 } else {
1335 frq = 1164;
1336 bl = 7;
1337 }
1338 } else {
1339 if (bl >= 7 && frq > 1164)
1340 frq = 1164;
1341 }
1342
1343 } else {
1344 frq = 1164;
1345 bl = 7;
1346 }
1347 } else {
1348 _fmChanPitch[chan] = 0;
1349 if (bl) {
1350 frq = _frequency[(bl - 1) % 12];
1351 bl = (bl - 1) / 12;
1352 } else {
1353 frq = 616;
1354 bl = 0;
1355 }
1356 }
1357
1358 uint8 part = chan > 2 ? 1 : 0;
1359 if (chan > 2)
1360 chan -= 3;
1361
1362 frq |= (bl << 11);
1363
1364 bufferedWriteReg(part, chan + 0xa4, (frq >> 8));
1365 bufferedWriteReg(part, chan + 0xa0, (frq & 0xff));
1366
1367 return 0;
1368 }
1369
fmSetLevel(int chan,int lvl)1370 int TownsAudioInterfaceInternal::fmSetLevel(int chan, int lvl) {
1371 if (chan > 5)
1372 return 1;
1373 if (lvl > 127)
1374 return 3;
1375
1376 uint8 part = chan > 2 ? 1 : 0;
1377 if (chan > 2)
1378 chan -= 3;
1379
1380 uint16 c = _carrier[_fmSaveReg[part][0xb0 + chan] & 7];
1381 _fmSaveReg[part][0xd0 + chan] = lvl;
1382
1383 for (uint8 reg = 0x40 + chan; reg < 0x50; reg += 4) {
1384 c += c;
1385 if (c & 0x100) {
1386 c &= 0xff;
1387 bufferedWriteReg(part, reg, (((((((_fmSaveReg[part][0x80 + reg] ^ 0x7f) * lvl) >> 7) + 1) * _fmSaveReg[part][0xe0 + chan]) >> 7) + 1) ^ 0x7f);
1388 }
1389 }
1390 return 0;
1391 }
1392
bufferedWriteReg(uint8 part,uint8 regAddress,uint8 value)1393 void TownsAudioInterfaceInternal::bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value) {
1394 _fmSaveReg[part][regAddress] = value;
1395 writeReg(part, regAddress, value);
1396 }
1397
pcmReset()1398 void TownsAudioInterfaceInternal::pcmReset() {
1399 _numReservedChannels = 0;
1400
1401 for (int i = 0; i < 8; i++)
1402 _pcmChan[i].clear();
1403
1404 memset(_pcmInstruments, 0, 128 * 32);
1405 static uint8 name[] = { 0x4E, 0x6F, 0x20, 0x44, 0x61, 0x74, 0x61, 0x21 };
1406 for (int i = 0; i < 32; i++)
1407 memcpy(_pcmInstruments + i * 128, name, 8);
1408
1409 for (int i = 0; i < 128; i++)
1410 _waveTables[i].clear();
1411 _numWaveTables = 0;
1412 _waveTablesTotalDataSize = 0;
1413
1414 for (int i = 0x40; i < 0x48; i++) {
1415 pcmSetInstrument(i, 0);
1416 pcmSetLevel(i, 127);
1417 }
1418 }
1419
pcmKeyOn(int chan,int note,int velo)1420 int TownsAudioInterfaceInternal::pcmKeyOn(int chan, int note, int velo) {
1421 if (chan < 0x40 || chan > 0x47)
1422 return 1;
1423
1424 if (note & 0x80 || velo & 0x80)
1425 return 3;
1426
1427 chan -= 0x40;
1428 uint8 noteT = note;
1429 TownsAudio_PcmChannel *p = &_pcmChan[chan];
1430
1431 if (p->_reserved || p->_keyPressed)
1432 return 2;
1433
1434 TownsAudio_WaveTable *w = _waveTables;
1435 int res = p->initInstrument(noteT, w, _numWaveTables);
1436 if (res)
1437 return res;
1438
1439 p->loadData(w);
1440 p->keyOn(noteT, velo, w);
1441
1442 return 0;
1443 }
1444
pcmKeyOff(int chan)1445 int TownsAudioInterfaceInternal::pcmKeyOff(int chan) {
1446 if (chan < 0x40 || chan > 0x47)
1447 return 1;
1448
1449 chan -= 0x40;
1450 _pcmChan[chan].keyOff();
1451 return 0;
1452 }
1453
pcmChanOff(int chan)1454 int TownsAudioInterfaceInternal::pcmChanOff(int chan) {
1455 if (chan < 0x40 || chan > 0x47)
1456 return 1;
1457
1458 chan -= 0x40;
1459 _pcmChan[chan]._keyPressed = _pcmChan[chan]._activeEffect = _pcmChan[chan]._activeKey = _pcmChan[chan]._activeOutput = false;
1460
1461 return 0;
1462 }
1463
pcmSetPanPos(int chan,int mode)1464 int TownsAudioInterfaceInternal::pcmSetPanPos(int chan, int mode) {
1465 if (chan > 0x47)
1466 return 1;
1467 if (mode & 0x80)
1468 return 3;
1469
1470 chan -= 0x40;
1471 uint8 blc = 0x77;
1472
1473 if (mode > 64) {
1474 mode -= 64;
1475 blc = ((blc ^ (mode >> 3)) + (mode << 4)) & 0xff;
1476 } else if (mode < 64) {
1477 mode = (mode >> 3) ^ 7;
1478 blc = ((119 + mode) ^ (mode << 4)) & 0xff;
1479 }
1480
1481 _pcmChan[chan].setBalance(blc);
1482
1483 return 0;
1484 }
1485
pcmSetInstrument(int chan,int instrId)1486 int TownsAudioInterfaceInternal::pcmSetInstrument(int chan, int instrId) {
1487 if (chan > 0x47)
1488 return 1;
1489 if (instrId > 31)
1490 return 3;
1491 chan -= 0x40;
1492 _pcmChan[chan].setInstrument(&_pcmInstruments[instrId * 128]);
1493
1494 return 0;
1495 }
1496
pcmLoadInstrument(int instrId,const uint8 * data)1497 int TownsAudioInterfaceInternal::pcmLoadInstrument(int instrId, const uint8 *data) {
1498 if (instrId > 31)
1499 return 3;
1500 assert(data);
1501 memcpy(&_pcmInstruments[instrId * 128], data, 128);
1502 return 0;
1503 }
1504
pcmSetPitch(int chan,int pitch)1505 int TownsAudioInterfaceInternal::pcmSetPitch(int chan, int pitch) {
1506 if (chan > 0x47)
1507 return 1;
1508
1509 if (pitch < -8192 || pitch > 8191)
1510 return 3;
1511
1512 chan -= 0x40;
1513 TownsAudio_PcmChannel *p = &_pcmChan[chan];
1514
1515 uint32 pts = 0x4000;
1516
1517 if (pitch < 0)
1518 pts = (0x20000000 / (-pitch + 0x2001)) >> 2;
1519 else if (pitch > 0)
1520 pts = (((pitch + 0x2001) << 16) / 0x2000) >> 2;
1521
1522 p->setPitch(pts);
1523
1524 return 0;
1525 }
1526
pcmSetLevel(int chan,int lvl)1527 int TownsAudioInterfaceInternal::pcmSetLevel(int chan, int lvl) {
1528 if (chan > 0x47)
1529 return 1;
1530
1531 if (lvl & 0x80)
1532 return 3;
1533
1534 chan -= 0x40;
1535 _pcmChan[chan].setLevel(lvl);
1536
1537 return 0;
1538 }
1539
updateOutputVolume()1540 void TownsAudioInterfaceInternal::updateOutputVolume() {
1541 // Avoid calls to g_system->getAudioCDManager() functions from the main thread
1542 // since this can cause mutex lockups.
1543 _updateOutputVol = true;
1544 }
1545
updateOutputVolumeInternal()1546 void TownsAudioInterfaceInternal::updateOutputVolumeInternal() {
1547 if (!_ready)
1548 return;
1549
1550 // FM Towns seems to support volumes of 0 - 63 for each channel.
1551 // We recalculate sane values for our 0 to 255 volume range and
1552 // balance values for our -128 to 127 volume range
1553
1554 // CD-AUDIO
1555 uint32 maxVol = MAX(_outputLevel[12] * (_outputMute[12] ^ 1), _outputLevel[13] * (_outputMute[13] ^ 1));
1556
1557 int volume = (int)(((float)(maxVol * 255) / 63.0f));
1558 int balance = maxVol ? (int)( ( ((int)_outputLevel[13] * (_outputMute[13] ^ 1) - _outputLevel[12] * (_outputMute[12] ^ 1)) * 127) / (float)maxVol) : 0;
1559
1560 g_system->getAudioCDManager()->setVolume(volume);
1561 g_system->getAudioCDManager()->setBalance(balance);
1562
1563 _updateOutputVol = false;
1564 }
1565
1566 TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::_refInstance = 0;
1567
1568 int TownsAudioInterfaceInternal::_refCount = 0;
1569
1570 const uint8 TownsAudioInterfaceInternal::_chanFlags[] = {
1571 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
1572 };
1573
1574 const uint16 TownsAudioInterfaceInternal::_frequency[] = {
1575 0x028C, 0x02B4, 0x02DC, 0x030A, 0x0338, 0x0368, 0x039C, 0x03D4, 0x040E, 0x044A, 0x048C, 0x04D0
1576 };
1577
1578 const uint8 TownsAudioInterfaceInternal::_carrier[] = {
1579 0x10, 0x10, 0x10, 0x10, 0x30, 0x70, 0x70, 0xF0
1580 };
1581
1582 const uint8 TownsAudioInterfaceInternal::_fmDefaultInstrument[] = {
1583 0x45, 0x4C, 0x45, 0x50, 0x49, 0x41, 0x4E, 0x4F, 0x01, 0x0A, 0x02, 0x01,
1584 0x1E, 0x32, 0x05, 0x00, 0x9C, 0xDC, 0x9C, 0xDC, 0x07, 0x03, 0x14, 0x08,
1585 0x00, 0x03, 0x05, 0x05, 0x55, 0x45, 0x27, 0xA7, 0x04, 0xC0, 0x00, 0x00,
1586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1587 };
1588
TownsAudio_PcmChannel()1589 TownsAudio_PcmChannel::TownsAudio_PcmChannel() {
1590 _extData = 0;
1591 clear();
1592 }
1593
~TownsAudio_PcmChannel()1594 TownsAudio_PcmChannel::~TownsAudio_PcmChannel() {
1595 clear();
1596 }
1597
clear()1598 void TownsAudio_PcmChannel::clear() {
1599 _curInstrument = 0;
1600 _note = _tl = _level = _velo = 0;
1601
1602 _data = 0;
1603 _dataEnd = 0;
1604 _loopLen = 0;
1605
1606 _pos = 0;
1607 _loopStart = 0;
1608
1609 _step = 0;
1610 _stepNote = 0x4000;
1611 _stepPitch = 0x4000;
1612
1613 _panLeft = _panRight = 7;
1614
1615 _envTotalLevel = _envAttackRate = _envDecayRate = _envSustainLevel = _envSustainRate = _envReleaseRate = 0;
1616 _envStep = _envCurrentLevel = 0;
1617
1618 _envState = kEnvReady;
1619
1620 _activeKey = _activeEffect = _activeOutput = _keyPressed = _reserved = false;
1621
1622 delete[] _extData;
1623 _extData = 0;
1624 }
1625
loadData(TownsAudio_WaveTable * w)1626 void TownsAudio_PcmChannel::loadData(TownsAudio_WaveTable *w) {
1627 _data = w->data;
1628 _dataEnd = w->size << 11;
1629 _pos = 0;
1630 }
1631
loadData(uint8 * buffer,uint32 size)1632 void TownsAudio_PcmChannel::loadData(uint8 *buffer, uint32 size) {
1633 delete[] _extData;
1634 _extData = new int8[size];
1635 int8 *src = (int8 *)buffer;
1636 int8 *dst = _extData;
1637 for (uint32 i = 0; i < size; i++)
1638 *dst++ = *src & 0x80 ? (*src++ & 0x7f) : -*src++;
1639
1640 _data = _extData;
1641 _dataEnd = size << 11;
1642 _pos = 0;
1643 }
1644
initInstrument(uint8 & note,TownsAudio_WaveTable * & tables,int numTables)1645 int TownsAudio_PcmChannel::initInstrument(uint8 ¬e, TownsAudio_WaveTable *&tables, int numTables) {
1646 int i = 0;
1647 for (; i < 8; i++) {
1648 if (note <= _curInstrument[16 + 2 * i])
1649 break;
1650 }
1651
1652 if (i == 8)
1653 return 8;
1654
1655 uint8 *d = &_curInstrument[(i << 3) + 64];
1656 _envTotalLevel = d[0];
1657 _envAttackRate = d[1];
1658 _envDecayRate = d[2];
1659 _envSustainLevel = d[3];
1660 _envSustainRate = d[4];
1661 _envReleaseRate = d[5];
1662 _envStep = 0;
1663 note += d[6];
1664
1665 int32 id = (int32)READ_LE_UINT32(&_curInstrument[i * 4 + 32]);
1666
1667 for (i = 0; i < numTables; i++) {
1668 if (id == tables[i].id)
1669 break;
1670 }
1671
1672 if (i == numTables)
1673 return 9;
1674
1675 tables = &tables[i];
1676 return 0;
1677 }
1678
keyOn(uint8 note,uint8 velo,TownsAudio_WaveTable * w)1679 void TownsAudio_PcmChannel::keyOn(uint8 note, uint8 velo, TownsAudio_WaveTable *w) {
1680 setupLoop(w->loopLen ? w->loopStart : w->size, w->loopLen);
1681 setNote(note, w, _reserved);
1682 setVelo(velo);
1683
1684 if (_reserved)
1685 _activeEffect = true;
1686 else
1687 _keyPressed = _activeKey = true;
1688
1689 _activeOutput = true;
1690 }
1691
keyOff()1692 void TownsAudio_PcmChannel::keyOff() {
1693 _keyPressed = false;
1694 envRelease();
1695 }
1696
updateEnvelopeGenerator()1697 void TownsAudio_PcmChannel::updateEnvelopeGenerator() {
1698 if (!_envCurrentLevel) {
1699 _activeKey = false;
1700 _envState = kEnvReady;
1701 }
1702
1703 if (!_activeKey)
1704 return;
1705
1706 switch (_envState) {
1707 case kEnvAttacking:
1708 if (((_envCurrentLevel + _envStep) >> 8) > _envTotalLevel) {
1709 envDecay();
1710 return;
1711 } else {
1712 _envCurrentLevel += _envStep;
1713 }
1714 break;
1715
1716 case kEnvDecaying:
1717 if (((_envCurrentLevel - _envStep) >> 8) < _envSustainLevel) {
1718 envSustain();
1719 return;
1720 } else {
1721 _envCurrentLevel -= _envStep;
1722 }
1723 break;
1724
1725 case kEnvSustaining:
1726 case kEnvReleasing:
1727 _envCurrentLevel -= _envStep;
1728 if (_envCurrentLevel <= 0)
1729 _envCurrentLevel = 0;
1730 break;
1731
1732 default:
1733 break;
1734 }
1735 _tl = (_envCurrentLevel >> 8) << 1;
1736 }
1737
setInstrument(uint8 * instr)1738 void TownsAudio_PcmChannel::setInstrument(uint8 *instr) {
1739 _curInstrument = instr;
1740 }
1741
setLevel(uint8 lvl)1742 void TownsAudio_PcmChannel::setLevel(uint8 lvl) {
1743 if (_reserved) {
1744 _velo = lvl;
1745 _tl = lvl << 1;
1746 } else {
1747 int32 t = _envStep * lvl;
1748 if (_level)
1749 t /= _level;
1750 _envStep = t;
1751 t = _envCurrentLevel * lvl;
1752 if (_level)
1753 t /= _level;
1754 _envCurrentLevel = t;
1755 _level = lvl;
1756 _tl = _envCurrentLevel >> 8;
1757 }
1758 }
1759
setPitch(uint32 pt)1760 void TownsAudio_PcmChannel::setPitch(uint32 pt) {
1761 _stepPitch = pt & 0xffff;
1762 _step = (_stepNote * _stepPitch) >> 14;
1763
1764 // if (_pcmChanUnkFlag & _chanFlags[chan])
1765 // unk[chan] = (((p->step * 1000) << 11) / 98) / 20833;
1766
1767 /*else*/
1768 if (_activeEffect && (_step > 2048))
1769 _step = 2048;
1770 }
1771
setBalance(uint8 blc)1772 void TownsAudio_PcmChannel::setBalance(uint8 blc) {
1773 _panLeft = blc & 0x0f;
1774 _panRight = blc >> 4;
1775 }
1776
updateOutput()1777 void TownsAudio_PcmChannel::updateOutput() {
1778 if (_activeKey || _activeEffect) {
1779 _pos += _step;
1780
1781 if (_pos >= _dataEnd) {
1782 if (_loopStart != _dataEnd) {
1783 _pos = _loopStart;
1784 _dataEnd = _loopLen;
1785 } else {
1786 _pos = 0;
1787 _activeKey = _activeEffect = false;
1788 }
1789 }
1790 }
1791 }
1792
currentSampleLeft()1793 int32 TownsAudio_PcmChannel::currentSampleLeft() {
1794 return (_activeOutput && _panLeft) ? (((_data[_pos >> 11] * _tl) * _panLeft) >> 3) : 0;
1795 }
1796
currentSampleRight()1797 int32 TownsAudio_PcmChannel::currentSampleRight() {
1798 return (_activeOutput && _panRight) ? (((_data[_pos >> 11] * _tl) * _panRight) >> 3) : 0;
1799 }
1800
setupLoop(uint32 loopStart,uint32 loopLen)1801 void TownsAudio_PcmChannel::setupLoop(uint32 loopStart, uint32 loopLen) {
1802 _loopStart = loopStart << 11;
1803 _loopLen = loopLen << 11;
1804 }
1805
setNote(uint8 note,TownsAudio_WaveTable * w,bool stepLimit)1806 void TownsAudio_PcmChannel::setNote(uint8 note, TownsAudio_WaveTable *w, bool stepLimit) {
1807 _note = note;
1808 int8 diff = _note - w->baseNote;
1809 uint16 r = w->rate + w->rateOffs;
1810 uint16 bl = 0;
1811 uint32 s = 0;
1812
1813 if (diff < 0) {
1814 diff *= -1;
1815 bl = diff % 12;
1816 diff /= 12;
1817 s = (r >> diff);
1818 if (bl)
1819 s = (s * _pcmPhase2[bl]) >> 16;
1820
1821 } else if (diff > 0) {
1822 bl = diff % 12;
1823 diff /= 12;
1824 s = (r << diff);
1825 if (bl)
1826 s += ((s * _pcmPhase1[bl]) >> 16);
1827
1828 } else {
1829 s = r;
1830 }
1831
1832 _stepNote = s & 0xffff;
1833 _step = (s * _stepPitch) >> 14;
1834
1835 if (stepLimit && _step > 2048)
1836 _step = 2048;
1837 }
1838
setVelo(uint8 velo)1839 void TownsAudio_PcmChannel::setVelo(uint8 velo) {
1840 if (_reserved) {
1841 _velo = velo;
1842 _tl = velo << 1;
1843 } else {
1844 _velo = velo;
1845 uint32 lvl = _level * _velo;
1846 _envTotalLevel = ((_envTotalLevel * lvl) >> 14) & 0xff;
1847 _envSustainLevel = ((_envSustainLevel * lvl) >> 14) & 0xff;
1848 envAttack();
1849 _tl = (_envCurrentLevel >> 8) << 1;
1850 }
1851 }
1852
envAttack()1853 void TownsAudio_PcmChannel::envAttack() {
1854 _envState = kEnvAttacking;
1855 int16 t = _envTotalLevel << 8;
1856 if (_envAttackRate == 127) {
1857 _envCurrentLevel = _envStep = 0;
1858 } else if (_envAttackRate) {
1859 _envStep = t / _envAttackRate;
1860 _envCurrentLevel = 1;
1861 } else {
1862 _envCurrentLevel = t;
1863 envDecay();
1864 }
1865 }
1866
envDecay()1867 void TownsAudio_PcmChannel::envDecay() {
1868 _envState = kEnvDecaying;
1869 int16 t = _envTotalLevel - _envSustainLevel;
1870 if (t < 0 || _envDecayRate == 127) {
1871 _envStep = 0;
1872 } else if (_envDecayRate) {
1873 _envStep = (t << 8) / _envDecayRate;
1874 } else {
1875 _envCurrentLevel = _envSustainLevel << 8;
1876 envSustain();
1877 }
1878 }
1879
envSustain()1880 void TownsAudio_PcmChannel::envSustain() {
1881 _envState = kEnvSustaining;
1882 if (_envSustainLevel && _envSustainRate)
1883 _envStep = (_envSustainRate == 127) ? 0 : (_envCurrentLevel / _envSustainRate) >> 1;
1884 else
1885 _envStep = _envCurrentLevel = 1;
1886 }
1887
envRelease()1888 void TownsAudio_PcmChannel::envRelease() {
1889 _envState = kEnvReleasing;
1890 if (_envReleaseRate == 127)
1891 _envStep = 0;
1892 else if (_envReleaseRate)
1893 _envStep = _envCurrentLevel / _envReleaseRate;
1894 else
1895 _envStep = _envCurrentLevel = 1;
1896 }
1897
1898 const uint16 TownsAudio_PcmChannel::_pcmPhase1[] = {
1899 0x879B, 0x0F37, 0x1F58, 0x306E, 0x4288, 0x55B6, 0x6A08, 0x7F8F, 0x965E, 0xAE88, 0xC882, 0xE341
1900 };
1901
1902 const uint16 TownsAudio_PcmChannel::_pcmPhase2[] = {
1903 0xFEFE, 0xF1A0, 0xE411, 0xD744, 0xCB2F, 0xBFC7, 0xB504, 0xAAE2, 0xA144, 0x9827, 0x8FAC
1904 };
1905
TownsAudio_WaveTable()1906 TownsAudio_WaveTable::TownsAudio_WaveTable() {
1907 data = 0;
1908 clear();
1909 }
1910
~TownsAudio_WaveTable()1911 TownsAudio_WaveTable::~TownsAudio_WaveTable() {
1912 clear();
1913 }
1914
readHeader(const uint8 * buffer)1915 void TownsAudio_WaveTable::readHeader(const uint8 *buffer) {
1916 memcpy(name, buffer, 8);
1917 name[8] = 0;
1918 id = READ_LE_UINT32(&buffer[8]);
1919 size = READ_LE_UINT32(&buffer[12]);
1920 loopStart = READ_LE_UINT32(&buffer[16]);
1921 loopLen = READ_LE_UINT32(&buffer[20]);
1922 rate = READ_LE_UINT16(&buffer[24]);
1923 rateOffs = READ_LE_UINT16(&buffer[26]);
1924 baseNote = READ_LE_UINT32(&buffer[28]);
1925 }
1926
readData(const uint8 * buffer)1927 void TownsAudio_WaveTable::readData(const uint8 *buffer) {
1928 if (!size)
1929 return;
1930
1931 delete[] data;
1932 data = new int8[size];
1933
1934 const int8 *src = (const int8 *)buffer;
1935 int8 *dst = data;
1936 for (uint32 i = 0; i < size; i++)
1937 *dst++ = *src & 0x80 ? (*src++ & 0x7f) : -*src++;
1938 }
1939
clear()1940 void TownsAudio_WaveTable::clear() {
1941 name[0] = name[8] = 0;
1942 id = -1;
1943 size = 0;
1944 loopStart = 0;
1945 loopLen = 0;
1946 rate = 0;
1947 rateOffs = 0;
1948 baseNote = 0;
1949 delete[] data;
1950 data = 0;
1951 }
1952
TownsAudioInterface(Audio::Mixer * mixer,TownsAudioInterfacePluginDriver * driver,bool externalMutex)1953 TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutex) {
1954 _intf = TownsAudioInterfaceInternal::addNewRef(mixer, this, driver, externalMutex);
1955 }
1956
~TownsAudioInterface()1957 TownsAudioInterface::~TownsAudioInterface() {
1958 TownsAudioInterfaceInternal::releaseRef(this);
1959 _intf = 0;
1960 }
1961
init()1962 bool TownsAudioInterface::init() {
1963 return _intf->init();
1964 }
1965
callback(int command,...)1966 TownsAudioInterface::ErrorCode TownsAudioInterface::callback(int command, ...) {
1967 va_list args;
1968 va_start(args, command);
1969
1970 int res = _intf->processCommand(command, args);
1971
1972 va_end(args);
1973 return (TownsAudioInterface::ErrorCode)res;
1974 }
1975
setMusicVolume(int volume)1976 void TownsAudioInterface::setMusicVolume(int volume) {
1977 _intf->setMusicVolume(volume);
1978 }
1979
setSoundEffectVolume(int volume)1980 void TownsAudioInterface::setSoundEffectVolume(int volume) {
1981 _intf->setSoundEffectVolume(volume);
1982 }
1983
setSoundEffectChanMask(int mask)1984 void TownsAudioInterface::setSoundEffectChanMask(int mask) {
1985 _intf->setSoundEffectChanMask(mask);
1986 }
1987