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_RSOUND_H
23 #define MADS_PHANTOM_RSOUND_H
24 
25 #include "mads/core/sound_manager.h"
26 
27 namespace MADS {
28 namespace Phantom {
29 
30 class RSound;
31 
32 #define RSOUND_CHANNEL_COUNT 9
33 
51 class Channel {
52 public:
53  RSound *_owner = nullptr;
54  int _midiChannel = 0; // 1-9: the MIDI channel this struct drives (C++ convenience, not a real field)
55 
56  int _activeCount = 0; // gate/duration countdown; also freshly loaded from the duration byte of a note event
57  int _pitchBendFadeStep = 0; // per-step delta added to _pitchBend each ramp tick
58  int _volumeFadeStep = 0; // per-step delta added to _volume each ramp tick
59  int _panFadeStep = 0; // per-step delta added to _pan each ramp tick
60  int _note = 0; // last-played note value (note + _transpose), used to detect a note change
61  int _program = 0; // patch/instrument number, sent as a Program Change
62  int _velocity = 0; // note velocity, used by RSound::sendNoteOn()
63  int _noteOffset = 0; // subtracted from _activeCount to derive _keyOnDelay (relative mode)
64  int _keyOnDelayOverride = 0; // when non-zero, used directly as _keyOnDelay instead of the relative computation (absolute mode; new to Phantom)
65  int _keyOnDelay = 0; // countdown to RSound::Channel_flushHeldNotes()
66  int _volumeFadeCounter = 0; // counts down to 0 before applying _volumeFadeStep
67  int _volumeFadeReload = 0; // reload value for _volumeFadeCounter
68  int _pitchBendFadeCounter = 0; // counts down to 0 before applying _pitchBendFadeStep
69  int _panFadeCounter = 0; // counts down to 0 before applying _panFadeStep
70  int _panFadeReload = 0; // reload value for _panFadeCounter
71  int _pan = 0; // current pan value (MIDI CC#10); 64 = center
72  int _volume = 0; // current channel volume (MIDI CC#7)
73  int _pitchBend = 0; // current pitch bend value (status 0xEn, coarse/MSB only)
74  int _pitchBendFadeReload = 0; // reload value for _pitchBendFadeCounter
75  int _pitchBendFadeCount = 0; // total ramp steps remaining before the pitch-bend ramp halts
76  byte *_loopStartPtr = nullptr; // fixed restart anchor used by the full-reset/loop-restart opcode
77  byte *_pSrc = nullptr; // current read pointer into the sound-data stream
78  byte *_innerLoopPtr = nullptr; // inner-loop restart address
79  byte *_outerLoopPtr = nullptr; // outer-loop restart address
80  int _innerLoopCount = 0;
81  int _outerLoopCount = 0;
82  byte *_soundData = nullptr; // identity pointer used by RSound::isSoundActive()
83  byte *_branchTarget = nullptr; // resume-after-branch pointer, used by the call/return opcode pair (new to Phantom)
84  int _transpose = 0; // added to note bytes before comparison/storage (new to Phantom)
85  int _pendingStop = 0; // non-zero while the channel is fading out to silence
86 
87 public:
88  Channel() {}
89 
96  void reset(byte *startPtr);
97 
102  void enable(int flag);
103 
108  void load(byte *pData);
109 };
110 
131 class RSound : public SoundDriver {
132  friend class Channel;
133 private:
134  uint16 _randomSeed;
135  byte _lastMidiStatus; // running-status cache, avoids resending an unchanged status byte
136  byte _sysexChecksum;
137  int _stateChangedFlag; // word_12BB8 in the disassembly; latches _pollResult=0xFFFF once per state change
138 
152  byte _heldNotes[RSOUND_CHANNEL_COUNT + 1][4];
153 
162  int _sysExOffset;
163 
170  byte _scriptVariables[32];
171 
178  int _fadeCheckCounter;
179 
192  int _tickCounter; // word_12BE5
193  int _clockMedTarget; // word_12BE7 - pending value for _clockMed, set by opcode 0xC0
194  int _clockCoarseTarget; // word_12BE9 - pending value for _clockCoarse, set by opcode 0xBF
195  int _clockUnknown; // word_12BEB - default 0; doesn't fit the 4x pattern, standalone (opcode 0xBE)
196  int _clockCoarse; // word_12BEE - default 112 (=28*4)
197  int _clockMed; // word_12BF0 - default 28 (=7*4)
198  int _clockFine; // word_12BF2 - default 7
199  int _clockEnabled1; // word_12BD3 - set to 1 by opcode 0xBF
200  int _clockEnabled2; // word_12BE3 - set to 1 by opcode 0xBF
201 
202  void update();
203  void pollAllChannels();
204 
214  void pollActiveChannel(Channel *channel);
215 
220  int readScriptByte(byte *&pSrc);
221 
228  uint16 readScriptWord(byte *&pSrc);
229 
230  void resetAllChannels();
231  void resetChannels1to5();
232 
238  void resetChannels4to9();
239 
240  void checkFadingChannels();
241  void Channel_checkFade(Channel *channel, int midiChannel);
242  void Channel_flushHeldNotes(Channel *channel);
243 
244 protected:
245  int _commandParam;
246 
247  byte *loadData(int offset) {
248  return &_soundData[offset];
249  }
250 
264 
275 
285  void resetChannelRange(int first, int last);
286 
294  virtual void checkRandomAmbianceTrigger() {
295  }
296 
297  void resultCheck();
298 
303  Channel *playSound(int offset);
304 
314  Channel *playSoundChannels1To5(int offset);
315 
322  Channel *playSoundAny(int offset);
323 
330  Channel *playSoundChannels5To8(int offset);
331 
337  Channel *playSoundChannels1To6(int offset);
338 
345  Channel *playSoundData(byte *pData, int startingChannel, int freeScanEnd, int fallbackScanEnd);
346 
350  bool isSoundActive(byte *pData);
351 
352  int getRandomNumber();
353 
354  // ---- Low-level MIDI send helpers -------------------------------
355  // All funnel through sendMidiByte(), the single hook point for
356  // wiring up real MT-32/MIDI output.
357  void sendMidiByte(byte value);
358  void sendStatus(int midiChannel, byte statusNibble);
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 
384  void sendSysExData(const byte *pData);
385 
391  void sendSysEx(int offset);
392 
401  void sendPatchInitSequence();
402 
411  void sendReverbSysEx(int mode, int time, int level);
412 
417  void noOpHandler(int param) {
418  }
419 
420  virtual int command0();
421  int command1();
422  int command2();
423  int command3();
424 
430  void enableUpperChannels();
431 
436  void resetAndGmResetUpperChannels();
437 
450  virtual int command4() = 0;
451  virtual int command5() = 0;
452  int command6();
453  int command7();
454  int command8();
455 
456  int nullCommand() {
457  return 0;
458  }
459 
460 public:
461  Channel _channels[RSOUND_CHANNEL_COUNT];
462  int _frameCounter;
463  bool _isDisabled;
464  int _pollResult;
465 
466 public:
475  RSound(Audio::Mixer *mixer, const Common::Path &filename,
476  int dataOffset, int dataSize, int sysExOffset);
477 
478  ~RSound() override {
479  }
480 
481  int stop() override;
482  int poll() override;
483  void noise() override {
484  // No equivalent in the Roland driver - noise() is an Adlib/OPL-only concept
485  }
486  void setVolume(int volume) override;
487 
488  int getFrameCounter() {
489  return _frameCounter;
490  }
491 };
492 
493 } // namespace Phantom
494 } // namespace MADS
495 
496 #endif
int _fadeCheckPeriod
Definition: rsound.h:274
void noise() override
Definition: rsound.h:483
void load(byte *pData)
void reset(byte *startPtr)
virtual void checkRandomAmbianceTrigger()
Definition: rsound.h:294
Definition: path.h:52
int _randomAmbianceTriggerFlag
Definition: rsound.h:263
Definition: mixer.h:70
Definition: rsound.h:131
void noOpHandler(int param)
Definition: rsound.h:417
Definition: sound_manager.h:38
Definition: anim_timer.h:27
void enable(int flag)
Definition: rsound.h:51