ScummVM API documentation
rsound.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_SOUND_RSOUND_H
23 #define MADS_PHANTOM_SOUND_RSOUND_H
24 
25 #include "audio/mt32gm.h"
26 #include "mads/core/native_sound_timer.h"
27 #include "mads/core/sound_manager.h"
28 
29 namespace MADS {
30 namespace Phantom {
31 namespace Sound {
32 
33 class RSound;
34 
35 #define RSOUND_CHANNEL_COUNT 9
36 
54 class Channel {
55 public:
56  RSound *_owner = nullptr;
57  int _midiChannel = 0; // 1-9: the MIDI channel this struct drives (C++ convenience, not a real field)
58 
59  int _activeCount = 0; // gate/duration countdown; also freshly loaded from the duration byte of a note event
60  int _pitchBendFadeStep = 0; // per-step delta added to _pitchBend each ramp tick
61  int _volumeFadeStep = 0; // per-step delta added to _volume each ramp tick
62  int _panFadeStep = 0; // per-step delta added to _pan each ramp tick
63  int _note = 0; // last-played note value (note + _transpose), used to detect a note change
64  int _program = 0; // patch/instrument number, sent as a Program Change
65  int _velocity = 0; // note velocity, used by RSound::sendNoteOn()
66  int _noteOffset = 0; // subtracted from _activeCount to derive _keyOnDelay (relative mode)
67  int _keyOnDelayOverride = 0; // when non-zero, used directly as _keyOnDelay instead of the relative computation (absolute mode; new to Phantom)
68  int _keyOnDelay = 0; // countdown to RSound::Channel_flushHeldNotes()
69  int _volumeFadeCounter = 0; // counts down to 0 before applying _volumeFadeStep
70  int _volumeFadeReload = 0; // reload value for _volumeFadeCounter
71  int _pitchBendFadeCounter = 0; // counts down to 0 before applying _pitchBendFadeStep
72  int _panFadeCounter = 0; // counts down to 0 before applying _panFadeStep
73  int _panFadeReload = 0; // reload value for _panFadeCounter
74  int _pan = 0; // current pan value (MIDI CC#10); 64 = center
75  int _volume = 0; // current channel volume (MIDI CC#7)
76  int _pitchBend = 0; // current pitch bend value (status 0xEn, coarse/MSB only)
77  int _pitchBendFadeReload = 0; // reload value for _pitchBendFadeCounter
78  int _pitchBendFadeCount = 0; // total ramp steps remaining before the pitch-bend ramp halts
79  byte *_loopStartPtr = nullptr; // fixed restart anchor used by the full-reset/loop-restart opcode
80  byte *_pSrc = nullptr; // current read pointer into the sound-data stream
81  byte *_innerLoopPtr = nullptr; // inner-loop restart address
82  byte *_outerLoopPtr = nullptr; // outer-loop restart address
83  uint16 _innerLoopCount = 0; // signed byte stored as a 16-bit loop count
84  uint16 _outerLoopCount = 0; // signed byte stored as a 16-bit loop count
85  byte *_soundData = nullptr; // identity pointer used by RSound::isSoundActive()
86  byte *_branchTarget = nullptr; // resume-after-branch pointer, used by the call/return opcode pair (new to Phantom)
87  int _transpose = 0; // added to note bytes before comparison/storage (new to Phantom)
88  int _pendingStop = 0; // non-zero while the channel is fading out to silence
89 
90 public:
91  Channel() {}
92 
99  void reset(byte *startPtr);
100 
105  void enable(int flag);
106 
111  void load(byte *pData);
112 };
113 
129 class RSound : public SoundDriver {
130  friend class Channel;
131 private:
132  uint16 _randomSeed;
133  int _masterVolume = 255;
134  int _stateChangedFlag; // latches _pollResult=0xFFFF once per state change
135  MidiDriver_MT32GM *_midiDriver;
136  uint32 _driverCallbackDelta;
137  NativeSoundTimer _hostTimer;
138 
147  byte _heldNotes[RSOUND_CHANNEL_COUNT + 1][4];
148 
157  int _sysExOffset;
158 
164  byte _scriptVariables[32];
165 
172  int _fadeCheckCounter;
173 
188  int _tickCounter;
189  int _clockMedTarget; // pending value for _clockMed, set by opcode 0xC0
190  int _clockCoarseTarget; // pending value for _clockCoarse, set by opcode 0xBF
191  int _clockUnknown; // default 0; doesn't fit the 4x pattern, standalone (opcode 0xBE)
192  int _clockCoarse; // default 112 (=28*4)
193  int _clockMed; // default 28 (=7*4)
194  int _clockFine; // default 7
195  int _clockEnabled1; // set to 1 by opcode 0xBF
196  int _clockEnabled2; // set to 1 by opcode 0xBF
197 
198  void update();
199  void pollAllChannels();
200 
210  void pollActiveChannel(Channel *channel);
211 
216  int readScriptByte(byte *&pSrc);
217 
224  uint16 readScriptWord(byte *&pSrc);
225 
226  void resetAllChannels();
227  void resetChannels1to5();
228 
234  void resetChannels4to9();
235 
236  void checkFadingChannels();
237  void Channel_checkFade(Channel *channel, int midiChannel);
238  void Channel_flushHeldNotes(Channel *channel);
239 
240 protected:
241  int _commandParam;
242 
243  byte *loadData(int offset) {
244  return &_soundData[offset];
245  }
246 
259 
270 
280  void resetChannelRange(int first, int last);
281 
289  virtual void checkRandomAmbianceTrigger() {
290  }
291 
292  void resultCheck();
293 
299  virtual bool callFunction(uint16 targetOffset) {
300  (void)targetOffset;
301  return false;
302  }
303 
308  Channel *playSound(int offset);
309 
319  Channel *playSoundChannels1To5(int offset);
320 
326  Channel *playSoundAny(int offset);
327 
334  Channel *playSoundChannels5To8(int offset);
335 
341  Channel *playSoundChannels1To6(int offset);
342 
349  Channel *playSoundData(byte *pData, int startingChannel, int freeScanEnd, int fallbackScanEnd);
350 
354  bool isSoundActive(byte *pData);
355 
356  int getRandomNumber();
357 
358  // ---- Low-level MIDI send helpers -------------------------------
359  void sendNoteOn(int midiChannel, int note, int velocity);
360  void sendProgramChange(int midiChannel, int program);
361  void sendVolume(int midiChannel, int volume);
362  void sendVolumeCC(int midiChannel, int volume);
363  void resetPitchBend(int midiChannel);
364  void sendPitchBend(int midiChannel, int value);
365  void sendPan(int midiChannel, int value);
366  void muteChannel(int midiChannel);
367 
373  void sendGmReset(int count);
374 
388  const byte *sendSysExData(const byte *pData, uint maxLength);
389 
391  const byte *sendSysEx(int offset);
392 
402  void sendSysExSequence();
403 
415  void restorePatchMemory();
416 
424  void sendReverbSysEx(int mode, int time, int level);
425  void onTimer();
426  static void timerCallback(void *data);
427 
432  void noOpHandler(int param) {
433  }
434 
435  virtual int command0();
436  int command1();
437  int command2();
438  int command3();
439 
445  void enableUpperChannels();
446 
451  void resetAndGmResetUpperChannels();
452 
458  virtual int command4() = 0;
459  virtual int command5() = 0;
460  int command6();
461  int command7();
462  int command8();
463 
464  int nullCommand() {
465  return 0;
466  }
467 
468 public:
469  Channel _channels[RSOUND_CHANNEL_COUNT];
470  int _frameCounter;
471  bool _isDisabled;
472  int _pollResult;
473 
474 public:
478  static void validate();
479 
480 public:
489  RSound(Audio::Mixer *mixer, const Common::Path &filename,
490  int dataOffset, int dataSize, int sysExOffset);
491 
492  ~RSound() override;
493 
494  int stop() override;
495  int poll() override;
496  void noise() override {
497  // No equivalent in the Roland driver - noise() is an Adlib/OPL-only concept
498  }
499  void setVolume(int volume) override;
500 
501  int getFrameCounter() {
502  return _frameCounter;
503  }
504 };
505 
506 } // namespace Sound
507 } // namespace Phantom
508 } // namespace MADS
509 
510 #endif
Definition: rsound.h:129
Definition: mt32gm.h:111
virtual void checkRandomAmbianceTrigger()
Definition: rsound.h:289
int _randomAmbianceTriggerFlag
Definition: rsound.h:258
Definition: path.h:52
void noOpHandler(int param)
Definition: rsound.h:432
Definition: mixer.h:70
virtual bool callFunction(uint16 targetOffset)
Definition: rsound.h:299
Definition: native_sound_timer.h:33
int _fadeCheckPeriod
Definition: rsound.h:269
Definition: sound_manager.h:40
Definition: rsound.h:54
Definition: anim_timer.h:27
void reset(byte *startPtr)
void noise() override
Definition: rsound.h:496