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_NEBULAR_ASOUND_H
23 #define MADS_NEBULAR_ASOUND_H
24 
25 #include "audio/fmopl.h"
26 #include "mads/core/sound_manager.h"
27 
28 namespace MADS {
29 namespace RexNebular {
30 
31 class ASound;
32 
36 class AdlibChannel {
37 public:
38  ASound *_owner = nullptr;
39 
40  int _activeCount = 0;
41  int _pitchBend = 0; // signed pitch-bend offset added to frequency by updateFNumber()
42  int _volumeFadeStep = 0; // signed per-period volume delta applied to _volumeOffset
43  int _attenFadeStep = 0; // signed per-period delta applied to _patchAttenuation
44  int _note = 0; // note byte read from the sound-data stream
45  int _sampleIndex = 0;
46  int _volume = 0;
47  int _noteOffset = 0; // subtracted from _activeCount to derive _keyOnDelay
48  int _keyOnDelay = 0; // countdown before the key-on bit is cleared (gate time)
49  int _volumeFadeCounter = 0; // counts down to 0 before applying _volumeFadeStep
50  int _volumeFadeReload = 0; // reload value for _volumeFadeCounter
51  uint8 _attenFadeCounter = 0;// counts down to 0 before applying _attenFadeStep
52  int _attenFadeReload = 0; // reload value for _attenFadeCounter
53  int _patchAttenuation = 0; // per-note attenuation offset added on top of the patch TL
54  int _pendingStop = 0; // non-zero while the channel is fading out to silence
55  byte *_ptr1 = nullptr;
56  byte *_pSrc = nullptr;
57  byte *_innerLoopPtr = nullptr; // inner-loop restart address (opcode 0)
58  byte *_outerLoopPtr = nullptr; // outer-loop restart address (opcode 1)
59  int _innerLoopCount = 0; // remaining inner-loop iterations (opcode 0)
60  int _outerLoopCount = 0; // remaining outer-loop iterations (opcode 1)
61  byte *_soundData = nullptr;
62  int _transpose = 0; // fine-tune offset added into the frequency table lookup
63  int _volumeOffset = 0;
64  int _octaveTranspose = 0; // added to _note before the octave/semitone split
65 
66  // Extra static per-channel volume trim, confirmed via disassembly
67  // comparison to be a third additive term in updateActiveChannel()'s
68  // volume sum (volume + volumeOffset + channelAttenuation, clamped to
69  // [0, 63]). Only asound.003/asound.004's copy of the shared runtime
70  // reads this = 0; it is otherwise always 0, so summing it in unconditionally
71  // is harmless for every other driver.
72  byte _channelAttenuation = 0;
73 
74 public:
75  static bool _channelsEnabled;
76 public:
77  AdlibChannel() {}
78 
79  void reset();
80  void enable(int flag);
81  void setPtr2(byte *pData);
82  void load(byte *pData);
83  void check(byte *nullPtr);
84 };
85 
87 public:
88  int _hasNoiseMode; // non-zero if this sample drives the 2-voice noise generator
89  int _freqMask;
90  int _freqBase;
91  int _freqStep; // per-tick frequency-sweep increment
92 };
93 
94 class AdlibSample {
95 public:
96  int _attackRate;
97  int _decayRate;
98  int _sustainLevel;
99  int _releaseRate;
100  bool _egTyp;
101  bool _ksr;
102  int _totalLevel;
103  int _scalingLevel;
104  int _waveformSelect;
105  int _freqMultiple;
106  int _feedback;
107  bool _ampMod;
108  int _vib;
109  int _alg;
110  int _noiseMode; // copied into AdlibChannelData::_hasNoiseMode by loadSample()
111  int _freqMask;
112  int _freqBase;
113  int _freqStep; // copied into AdlibChannelData::_freqStep by loadSample()
114 
115  AdlibSample() {
116  }
118 };
119 
121  uint8 _regNum;
122  uint8 _value;
123 
124  RegisterValue(int regNum, int value) {
125  _regNum = regNum; _value = value;
126  }
127 };
128 
129 #define ADLIB_CHANNEL_COUNT 9
130 #define ADLIB_CHANNEL_MIDWAY 5
131 
135 class ASound : public SoundDriver {
136 private:
137  OPL::OPL *_opl;
138  uint16 _randomSeed;
139  int _masterVolume;
140 
144  void adlibInit();
145 
149  void update();
150 
154  void pollChannels();
155 
159  void checkChannels();
160 
164  void pollActiveChannel();
165 
169  void updateOctave();
170 
171  void updateChannelState();
172  void updateActiveChannel();
173 
177  void processSample();
178 
179  void updateFNumber();
180 
184  void onTimer();
185 
186 protected:
187  int _chanCommandCount;
188  int _commandParam;
189 
190  virtual void channelCommand(byte *&pSrc, bool &updateFlag) = 0;
191 
199  virtual void tickCallback() {
200  }
201 
205  byte *loadData(int offset) {
206  return &_soundData[offset];
207  }
208 
209  int getDataOffset(byte *ptr) const {
210  return ptr - &_soundData[0];
211  }
212 
216  void loadSample(int sampleIndex);
217 
221  void write(int reg, int val);
222 
226  int write2(int state, int reg, int val);
227 
231  void flush();
232 
236  void channelOn(int reg, int volume);
237 
241  void channelOff(int reg);
242 
246  void resultCheck();
247 
252  void playSound(int offset);
253 
258  void playSoundAny(int offset) {
259  playSoundData(loadData(offset), 0);
260  }
261 
267  void playSoundData(byte *pData, int startingChannel = ADLIB_CHANNEL_MIDWAY);
268 
272  bool isSoundActive(byte *pData);
273 
277  void setFrequency(int channel, int freq);
278 
282  int getRandomNumber();
283 
288  byte *getDataPtr(int nearPtr);
289 
290  virtual int command0();
291  int command1();
292  int command2();
293  int command3();
294  int command4();
295  int command5();
296  int command6();
297  int command7();
298  int command8();
299 
300  int nullCommand() {
301  return 0;
302  }
303 public:
304  AdlibChannel _channels[ADLIB_CHANNEL_COUNT];
305  AdlibChannel *_activeChannelPtr;
306  AdlibChannelData _channelData[11];
308  AdlibSample *_samplePtr;
310  int _frameCounter;
311  bool _isDisabled;
312  int _noiseTicks1; // remaining duration for noise voice 1 (byte_11F86)
313  int _noiseTicks2; // remaining duration for noise voice 2 (byte_11F87)
314  int _activeChannelNumber;
315  int _freqMask1;
316  int _freqMask2;
317  int _freqBase1;
318  int _freqBase2;
319  int _noiseChannel1, _noiseChannel2;
320  int _noiseFreqStep1; // per-tick frequency-sweep step for noise voice 1 (word_11F8A)
321  int _noiseFreqStep2; // per-tick frequency-sweep step for noise voice 2 (word_11F8C)
322  int _savedNoiseTicks1; // _noiseTicks1 saved across command6/7 (byte_194B0)
323  int _savedNoiseTicks2; // _noiseTicks2 saved across command6/7 (byte_194B1)
324  int _pollResult;
325  int _resultFlag;
326  byte _nullData[2];
327  int _ports[256];
328  bool _stateFlag;
329  int _activeChannelReg;
330  int _outputReg; // scratch OPL operator register offset used within loadSample()
331  bool _amDep, _vibDep, _splitPoint;
332 
333 public:
337  static void validate();
338 
339 public:
347  ASound(Audio::Mixer *mixer, const Common::Path &filename, int dataOffset, int dataSize);
348 
352  ~ASound() override;
353 
357  int stop() override;
358 
362  int poll() override;
363 
367  void noise() override;
368 
373  return _frameCounter;
374  }
375 
379  void setVolume(int volume) override;
380 };
381 
382 // TODO: Merge RexASound into ASound
383 class RexASound : public ASound {
384 protected:
385  void channelCommand(byte *&pSrc, bool &updateFlag) override;
386 
387 public:
388  RexASound(Audio::Mixer *mixer, const Common::Path &filename, int dataOffset, int dataSize);
389 };
390 
391 } // namespace RexNebular
392 } // namespace MADS
393 
394 #endif
Definition: asound.h:120
Definition: array.h:52
Definition: path.h:52
Definition: asound.h:86
Definition: stream.h:745
Definition: asound.h:36
void playSoundAny(int offset)
Definition: asound.h:258
byte * loadData(int offset)
Definition: asound.h:205
Definition: mixer.h:70
virtual void tickCallback()
Definition: asound.h:199
Definition: asound.h:383
Definition: asound.h:94
Definition: sound_manager.h:38
Definition: anim_timer.h:27
Definition: asound.h:135
int getFrameCounter()
Definition: asound.h:372
Definition: fmopl.h:116