ScummVM API documentation
asound.h
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 modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (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, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef MADS_PHANTOM_ASOUND_H
23 #define MADS_PHANTOM_ASOUND_H
24 
25 #include "audio/fmopl.h"
26 #include "common/mutex.h"
27 #include "common/queue.h"
28 #include "common/util.h"
29 #include "mads/core/sound_manager.h"
30 
31 namespace MADS {
32 namespace Phantom {
33 
34 #define ADLIB_CHANNEL_COUNT 9
35 
36 struct AdlibChannel {
37  static bool _isDisabled;
38  uint8 _activeCount = 0;
39  uint8 _pitchBend = 0;
40  uint8 _volumeFadeStep = 0;
41  uint8 _vibratoDepth = 0;
42  uint8 _note = 0;
43  uint8 _sampleIndex = 0;
44  uint8 _volume = 0;
45  uint8 _noteOffset = 0;
46  uint8 _keyOnDelay = 0;
47  uint8 _fadePeriodCounter = 0;
48  uint8 _fadePeriodReload = 0;
49  uint8 _vibPeriodCounter = 0;
50  uint8 _vibPeriodReload = 0;
51  uint8 _patchAttenuation = 0;
52  byte *_loopStartPtr = nullptr;
53  byte *_pSrc = nullptr;
54  byte *_innerLoopPtr = nullptr;
55  byte *_outerLoopPtr = nullptr;
56  byte *_soundData = nullptr;
57  byte *_branchTargetPtr = nullptr;
58  uint16 _innerLoopCount = 0;
59  uint16 _outerLoopCount = 0;
60  uint16 _noiseFreqMask = 0;
61  uint16 _freqAccum = 0;
62  uint16 _freqStep = 0;
63  uint8 _freqSweepCounter = 0;
64  uint8 _savedFreqSweep = 0;
65  uint8 _transpose = 0;
66  uint8 _velocity = 0;
67  uint8 _opVolBytes = 0;
68  uint8 _opVolBytes2 = 0;
69  uint8 _octaveTranspose = 0;
70  uint8 _pendingStop = 0;
71  uint8 _durationOverride = 0;
72 
77  void reset();
78 
83  void load(byte *soundData);
84 
89  void setPtr2(byte *ptr);
90 
95  void enable();
96 
102  void processChannelFade();
103 };
104 
105 struct AdlibSample {
106  uint8 _attackRate = 0;
107  uint8 _decayRate = 0;
108  uint8 _sustainLevel = 0;
109  uint8 _releaseRate = 0;
110  uint8 _egTyp = 0;
111  uint8 _ksr = 0;
112  uint8 _totalLevel = 0;
113  uint8 _scalingLevel = 0;
114  uint8 _waveformSelect = 0;
115  uint8 _freqMultiple = 0;
116  uint8 _feedback = 0;
117  uint8 _ampMod = 0;
118  uint8 _vib = 0;
119  uint8 _alg = 0;
120  uint8 _freqSweepInit = 0;
121  uint8 _reserved = 0;
122  uint16 _freqMask = 0;
123  uint16 _freqBase = 0;
124  uint16 _outerLoopPtr = 0;
125 
126  AdlibSample() {
127  }
129 };
130 
131 class ASound : public SoundDriver {
132 private:
133  OPL::OPL *_opl = OPL::Config::create();
134  uint16 _callbackCounter = 0; // Period counter
135  uint16 _callbackPeriod = 0; // Period reload
136  AdlibChannel *_activeChannelPtr = NULL;
137  uint8 _activeChannelNumber = 0;
138  uint16 _activeChannelReg = 0;
139  uint16 _currentOpBase = 0; // Current operator base
140  AdlibSample *_samplePtr = NULL;
141  byte *pSrc = nullptr; // Current read pointer
142  int16 _pollResult = 0;
143  int16 _resultFlag = 0;
144  uint16 _randomSeed = 0x4D2;
145  uint8 _isDisabled = 0;
146  uint8 _findChannelMode = 0; // findFreeChannel mode
147  uint8 _ch5SweepLive = 0; // Channel5 savedFreqSweep shadow
148  uint8 _ch5SweepSaved = 0; // Channel5 savedFreqSweep shadow 2
149  uint8 _ch5PendingStop = 0; // Channel5 pendingStop shadow
150  uint8 _anySweepActive = 0; // any-sweep-active flag
151  int _frameNumber2 = 0;
152  uint8 _scriptVars[32]; // General-purpose script registers
153  uint16 _tickEnabled = 1;
154  uint16 _tickCounter = 0;
155  uint16 _tempoReload = 0;
156  uint16 _tempoTarget = 0;
157  uint16 _tempoShift = 0;
158  uint16 _tempoBase = 0xA0;
159  uint16 _tempoCurrent = 0x28;
160  uint16 _tempoScale = 0x0A;
161 
165  void onTimer();
166 
170  void clearCallback();
171  void resetCallback() {
172  clearCallback();
173  }
174 
180  void adlib_channelOff(uint8 portIndex);
181 
182 
191  void writeVolume();
192 
197  void writeFrequency();
198 
203  void writePitchBend();
204 
209  void updateOctave();
210 
216  void noteOn();
217 
222  void writeSampleRegs();
223 
228  void loadSample();
229 
233  void update();
234 
241  void update1(int channelIndex);
242 
246  void setFrequency(uint8 voice, uint16 freq);
247 
252  void noise_inner(int channelIndex);
253 
257  void updateAllChannels();
258 
262  uint16 readWord_impl();
263 
264 protected:
265  AdlibChannel _channel0, _channel1, _channel2;
266  AdlibChannel _channel3, _channel4, _channel5;
267  AdlibChannel _channel6, _channel7, _channel8;
268  AdlibChannel *_channels[ADLIB_CHANNEL_COUNT] = {
269  &_channel0, &_channel1, &_channel2, &_channel3, &_channel4,
270  &_channel5, &_channel6, &_channel7, &_channel8
271  };
272 
273  uint8 _adlibPorts[0x100] = { 0 };
275 
276 protected:
284  void write(uint8 reg, uint8 value);
285 
289  uint16 getRandomNumber();
290 
296  void adlib_channelOn(uint8 portIndex, uint8 vol);
297 
301  void signalSoundPlaying();
302 
306  void pollAllChannels();
307 
318  void pollActiveChannel();
319 
323  bool isSoundActive(byte *ptr) const;
324 
334  void findFreeChannel(byte *soundData);
335 
340  void findFreeChannelFull(byte *soundData);
341 
345  byte *loadData(int offset) {
346  return &_soundData[offset];
347  }
348 
349 protected:
353  void playSound(int offset);
354 
363  int command0();
364 
365  /*
366  * Fade out all channels (calls command2 + command4 via
367  * the command3/command5 helpers that enable pending-stop on each channel).
368  */
369  int command1();
370 
374  int command2();
375 
379  int command3();
380 
384  int command4();
385 
386  /*
387  * Stop SFX channels (6-8) with pending-stop flag.
388  *
389  * Marks each of the three SFX channels (6, 7, 8) as pending-stop by setting
390  * their _pendingStop field to 0xFF and redirecting their sound-data pointer
391  * to the null/silence stream. Channels that are already inactive
392  * (_activeCount == 0) are skipped.
393  *
394  * Unlike command4 (which forces an immediate fade-out via AdlibChannel_setPtr2),
395  * this command lets each channel finish its current envelope naturally:
396  * asound_processChannelFade checks _pendingStop each frame and only silences
397  * the channel once both _velocity and _volume have reached zero.
398  */
399  int command5();
400 
406  int command6();
407 
422  int command7();
423 
428  int command8();
429 
434  virtual void callFunction(uint16 offset);
435 
436 public:
440  static void validate(bool isDemo);
441 
442 public:
449  ASound(Audio::Mixer *mixer, const Common::Path &filename,
450  int dataOffset, int dataSize);
451 
455  ~ASound() override {
456  delete _opl;
457  }
458 
462  virtual int stop() override;
463 
467  int poll() override;
468 
473  void noise() override;
474 
475  void setVolume(int volume) override {
476  // TODO: Does this need implementation?
477  }
478 };
479 
480 } // namespace Phantom
481 } // namespace MADS
482 
483 #endif
~ASound() override
Definition: asound.h:455
Definition: array.h:52
Definition: path.h:52
Definition: stream.h:745
static OPL * create(DriverId driver, OplType type)
Definition: asound.h:105
Definition: mixer.h:70
Definition: asound.h:131
Definition: asound.h:36
Definition: sound_manager.h:38
Definition: anim_timer.h:27
void setVolume(int volume) override
Definition: asound.h:475
void load(byte *soundData)
byte * loadData(int offset)
Definition: asound.h:345
Definition: fmopl.h:116