ScummVM API documentation
player_mac_intern.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 SCUMM_PLAYERS_PLAYER_MAC_INTERN_H
23 #define SCUMM_PLAYERS_PLAYER_MAC_INTERN_H
24 
25 #include "audio/audiostream.h"
26 #include "audio/mixer.h"
27 #include "common/array.h"
28 #include "common/func.h"
29 
30 namespace Scumm {
31 
33 public:
34  MacSoundDriver(Common::Mutex &mutex, uint32 deviceRate, int activeChannels, bool canInterpolate, bool internal16Bit) : _mutex(mutex),
35  _smpSize(internal16Bit ? 2 : 1), _smpMin(internal16Bit ? -32768 : -128), _smpMax(internal16Bit ? 32767 : 127) {
36  for (int i = 0; i < 4; ++i) {
37  _status[i].deviceRate = deviceRate;
38  _status[i].numExternalMixChannels = activeChannels;
39  _status[i].allowInterPolation = canInterpolate;
40  _status[i].flags = 0;
41  }
42  }
43  virtual ~MacSoundDriver() {}
44  virtual void feed(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) = 0;
45 
46  struct Status {
47  Status() : deviceRate(0), numExternalMixChannels(0), allowInterPolation(false), flags(0) {}
48  uint32 deviceRate;
49  int numExternalMixChannels;
50  bool allowInterPolation;
51  uint8 flags;
52  };
53  const Status &getStatus(Audio::Mixer::SoundType sndType = Audio::Mixer::kPlainSoundType) const { return _status[sndType]; }
54 
55  enum StatusFlag : uint8 {
56  kStatusPlaying = 1 << 0,
57  kStatusOverflow = 1 << 1,
58  kStatusStartup = 1 << 2,
59  kStatusDone = 1 << 3
60  };
61 
62  void clearFlags(uint8 flags, Audio::Mixer::SoundType sndType = Audio::Mixer::kPlainSoundType) { _status[sndType].flags &= ~flags; }
63  void setFlags(uint8 flags, Audio::Mixer::SoundType sndType = Audio::Mixer::kPlainSoundType) { _status[sndType].flags |= flags; }
64 
65 protected:
66  Common::Mutex &_mutex;
67  const int _smpSize;
68  const int16 _smpMin;
69  const int16 _smpMax;
70  Status _status[4];
71 };
72 
73 class MacSndChannel;
74 class MacLowLevelPCMDriver final : public MacSoundDriver {
75 public:
76  struct PCMSound {
77  PCMSound() : len(0), rate(0), loopst(0), loopend(0), baseFreq(0), stereo(false), enc(0) {}
78  PCMSound(Common::SharedPtr<const byte> a, uint32 b, uint32 c, uint32 d, uint32 e, byte f, byte g, bool h) : data(a), len(b), rate(c), loopst(d), loopend(e), baseFreq(f), enc(g), stereo(h) {}
80  uint32 len;
81  uint32 rate;
82  uint32 loopst;
83  uint32 loopend;
84  byte baseFreq;
85  byte enc;
86  bool stereo;
87  };
88 
89  enum SynthType : byte {
90  kSquareWaveSynth = 1,
91  kWaveTableSynth = 3,
92  kSampledSynth = 5,
93  kIgnoreSynth = 0xff
94  };
95 
96  enum ChanAttrib : byte {
97  kInitChanLeft = 2,
98  kInitChanRight = 3,
99  kWaveInitChannel0 = 4,
100  kWaveInitChannel1 = 5,
101  kWaveInitChannel2 = 6,
102  kWaveInitChannel3 = 7,
103  kNoInterp = 4,
104  kInitNoDrop = 8,
105  kInitMono = 0x80,
106  kInitStereo = 0xC0
107  };
108 
109  enum ExecMode : byte {
110  kImmediate,
111  kEnqueue,
112  };
113 
114  typedef int ChanHandle;
115 
117  public:
118  virtual ~CallbackClient() {}
119  virtual void sndChannelCallback(uint16 arg1, const void *arg2) = 0;
120  };
122 
123 public:
124  MacLowLevelPCMDriver(Common::Mutex &mutex, uint32 deviceRate, bool internal16Bit);
125  ~MacLowLevelPCMDriver() override;
126 
127  void feed(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) override;
128 
129  ChanHandle createChannel(Audio::Mixer::SoundType sndType, SynthType synthType, byte attributes, ChanCallback *callback);
130  void disposeChannel(ChanHandle handle);
131 
132  void playSamples(ChanHandle handle, ExecMode mode, const PCMSound *snd);
133  void playNote(ChanHandle handle, ExecMode mode, uint8 note, uint16 duration);
134  void quiet(ChanHandle handle, ExecMode mode);
135  void flush(ChanHandle handle, ExecMode mode);
136  void wait(ChanHandle handle, ExecMode mode, uint16 duration);
137  void loadWaveTable(ChanHandle handle, ExecMode mode, const byte *data, uint16 dataSize);
138  void loadInstrument(ChanHandle handle, ExecMode mode, const PCMSound *snd);
139  void setTimbre(ChanHandle handle, ExecMode mode, uint16 timbre);
140  void callback(ChanHandle handle, ExecMode mode, uint16 arg1, const void *arg2);
141 
142  uint8 getChannelStatus(ChanHandle handle) const;
143  void clearChannelFlags(ChanHandle handle, uint8 flags);
144 
145 private:
146  void updateStatus(Audio::Mixer::SoundType sndType);
147  MacSndChannel *findAndCheckChannel(ChanHandle h, const char *caller, byte reqSynthType) const;
148  MacSndChannel *findChannel(ChanHandle h) const;
150  int _numInternalMixChannels;
151  int32 *_mixBuffer = 0;
152  uint32 _mixBufferSize;
153 };
154 
156 public:
157  virtual ~VblTaskClientDriver() {}
158  virtual void vblCallback() = 0;
159  virtual void generateData(int8 *dst, uint32 len, Audio::Mixer::SoundType type, bool expectStereo) const = 0;
160  virtual const MacSoundDriver::Status &getDriverStatus(uint8 drvID, Audio::Mixer::SoundType sndType) const = 0;
161 };
162 
164 public:
165  MacPlayerAudioStream(VblTaskClientDriver *drv, uint32 scummVMOutputrate, bool stereo, bool interpolate, bool internal16Bit);
166  ~MacPlayerAudioStream() override;
167 
168  void initBuffers(uint32 feedBufferSize);
169  void initDrivers();
171  void setVblCallback(const CallbackProc *proc);
172  void clearBuffer();
173 
174  void setMasterVolume(Audio::Mixer::SoundType type, uint16 vol);
175 
176  // AudioStream interface
177  int readBuffer(int16 *buffer, const int numSamples) override;
178  bool isStereo() const override { return _isStereo; }
179  int getRate() const override { return _outputRate; }
180  bool endOfData() const override { return false; }
181 
182 private:
183  void generateData(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType, bool expectStereo) const;
184  void runVblTask();
185 
186  VblTaskClientDriver *_drv;
187 
188  uint32 _vblSmpQty;
189  uint32 _vblSmpQtyRem;
190  uint32 _vblCountDown;
191  uint32 _vblCountDownRem;
192  const CallbackProc *_vblCbProc;
193 
194  struct SmpBuffer {
195  SmpBuffer() : start(0), pos(0), end(0), volume(0x10000), lastL(0), lastR(0), size(0), rateConvInt(0), rateConvFrac(0), rateConvAcc(-1) {}
196  int8 *start;
197  int8 *pos;
198  const int8 *end;
199  uint32 volume;
200  int32 lastL;
201  int32 lastR;
202  uint32 size;
203  uint32 rateConvInt;
204  uint32 rateConvFrac;
205  int32 rateConvAcc;
206  } _buffers[2];
207 
208  const uint32 _outputRate;
209  const uint8 _frameSize;
210  const bool _interp;
211  const int _smpInternalSize;
212 
213  const bool _isStereo;
214 };
215 
216 class LegacyMusicDriver;
217 class Indy3MacSnd final : public VblTaskClientDriver {
218 private:
219  Indy3MacSnd(ScummEngine *vm, Audio::Mixer *mixer);
220 public:
221  ~Indy3MacSnd();
222  static Common::SharedPtr<Indy3MacSnd> open(ScummEngine *scumm, Audio::Mixer *mixer);
223  bool startDevices(uint32 outputRate, uint32 pcmDeviceRate, uint32 feedBufferSize, bool enableInterpolation, bool stereo, bool internal16Bit);
224 
225  void setMusicVolume(int vol);
226  void setSfxVolume(int vol);
227  void startSound(int id);
228  void stopSound(int id);
229  void stopAllSounds();
230  int getMusicTimer();
231  int getSoundStatus(int id) const;
232  void setQuality(int qual);
233  void saveLoadWithSerializer(Common::Serializer &ser);
234  void restoreAfterLoad();
235  void toggleMusic(bool enable);
236  void toggleSoundEffects(bool enable);
237 
238  void vblCallback() override;
239  void generateData(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) const override;
240  const MacSoundDriver::Status &getDriverStatus(uint8 drvID, Audio::Mixer::SoundType sndType) const override;
241 
242 private:
243  void startSong(int id);
244  void startSoundEffect(int id);
245  void stopSong();
246  void stopSoundEffect();
247  void stopActiveSound();
248  void finishSong();
249  void updateSong();
250  void updateSoundEffect();
251 
252  void checkRestartSoundEffects();
253  void endOfTrack();
254 
255  bool isSong(int id) const;
256  bool isHiQuality() const;
257 
258  int _curSound;
259  int _curSong;
260  int _lastSoundEffectPrio;
261  int _soundEffectNumLoops;
262  int _songTimer;
263  bool _songUnfinished;
264  uint _activeChanCount;
265  byte _songTimerInternal;
266  byte *_soundUsage;
267  byte _disableFlags;
268 
269  bool _soundEffectPlaying;
270  bool _soundEffectReschedule;
271  int _qmode;
272  bool _16bit;
273  bool _qualHi;
274  bool _mixerThread;
275 
277  MacLowLevelPCMDriver::ChanHandle _sfxChan;
278 
279  MacPlayerAudioStream *_macstr;
280  Audio::SoundHandle _soundHandle;
282 
283  ScummEngine *_vm;
284  Audio::Mixer *_mixer;
285  static Common::WeakPtr<Indy3MacSnd> *_inst;
286 
287  const byte *_musicIDTable;
288  int _musicIDTableLen;
289  const int _idRangeMax;
290 
291  LegacyMusicDriver *_mdrv;
292  MacLowLevelPCMDriver *_sdrv;
294 
295 private:
296  class MusicChannel {
297  public:
298  MusicChannel(Indy3MacSnd *pl);
299  ~MusicChannel();
300  void clear();
301 
302  void start(Common::SharedPtr<const byte> &songRes, uint16 offset, bool hq);
303  void nextTick();
304  void parseNextEvents();
305  void noteOn(uint16 duration, uint8 note);
306  uint16 checkPeriod() const;
307 
308  uint16 _frameLen;
309  uint16 _curPos;
310  uint16 _freqCur;
311  uint16 _freqIncr;
312  uint16 _freqEff;
313  uint16 _envPhase;
314  uint16 _envRate;
315  uint16 _tempo;
316  uint16 _envSust;
317  int16 _transpose;
318  uint16 _envAtt;
319  uint16 _envShape;
320  uint16 _envStep;
321  uint16 _envStepLen;
322  uint16 _modType;
323  uint16 _modState;
324  uint16 _modStep;
325  uint16 _modSensitivity;
326  uint16 _modRange;
327  uint16 _localVars[5];
329  bool _hq;
330 
331  private:
332  typedef bool (Indy3MacSnd::MusicChannel::*CtrlProc)(const byte *&);
333 
334  bool ctrl_setShape(const byte *&pos);
335  bool ctrl_modPara(const byte *&pos);
336  bool ctrl_init(const byte *&pos);
337  bool ctrl_returnFromSubroutine(const byte *&pos);
338  bool ctrl_jumpToSubroutine(const byte *&pos);
339  bool ctrl_initOther(const byte *&pos);
340  bool ctrl_decrJumpIf(const byte *&pos);
341  bool ctrl_writeVar(const byte *&pos);
342 
343  const CtrlProc *_ctrlProc;
344 
345  void limitedClear();
346  uint16 &getMemberRef(int pos);
347 
348  uint16 **_vars;
349  int _numVars;
350  uint16 &_savedOffset;
351 
352  uint16 _resSize;
353 
354  Indy3MacSnd *_player;
355  static MusicChannel *_ctrlChan;
356 
357  static const uint32 _envShapes[98];
358  const uint8 *&_modShapes;
359  const uint32 &_modShapesTableSize;
360 
361  bool ctrlProc(int procId, const byte *&arg);
362  void setFrameLen(uint8 len);
363  };
364 
365  MusicChannel **_musicChannels;
366  const int _numMusicChannels;
367  const int _numMusicTracks;
368 
369 public:
370  MusicChannel *getMusicChannel(uint8 id) const;
371 };
372 
373 class MacSndLoader;
375 private:
377 public:
378  ~LoomMonkeyMacSnd();
380  bool startDevice(uint32 outputRate, uint32 pcmDeviceRate, uint32 feedBufferSize, bool enableInterpolation, bool stereo, bool internal16Bit);
381 
382  void setMusicVolume(int vol);
383  void setSfxVolume(int vol);
384  void startSound(int id, int jumpToTick = 0);
385  void stopSound(int id);
386  void stopAllSounds();
387  int getMusicTimer();
388  int getSoundStatus(int id) const;
389  void setQuality(int qual);
390  void saveLoadWithSerializer(Common::Serializer &ser);
391  void restoreAfterLoad();
392  void toggleMusic(bool enable);
393  void toggleSoundEffects(bool enable);
394 
395  void vblCallback() override;
396  void generateData(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) const override;
397  const MacSoundDriver::Status &getDriverStatus(uint8, Audio::Mixer::SoundType sndType) const override;
398 
399  void sndChannelCallback(uint16 arg1, const void *arg2) override;
400 
401 private:
402  void sendSoundCommands(int timeStamp);
403  void stopActiveSound();
404  void setupChannels();
405  void disposeAllChannels();
406  void updateDisabledState();
407 
408  void detectQuality();
409  bool isSoundCardType10() const;
410 
411  int _curSound;
412  int _restartSound;
413  int _curSoundSaveVar;
414  int &_checkSound;
415  int _songTimer;
416  byte _songTimerInternal;
417  byte *_chanConfigTable;
418  const int _idRangeMax;
419  const byte _saveVersionChange;
420  const byte _legacySaveUnits;
421  bool _mixerThread;
422 
423  int _machineRating;
424  int _selectedQuality;
425  int _effectiveChanConfig;
426  int _defaultChanConfig;
427  bool _16bit;
428  byte _disableFlags;
429 
430  MacLowLevelPCMDriver::ChanHandle _sndChannel;
431  MacLowLevelPCMDriver::ChanHandle _musChannels[4];
432 
433  MacPlayerAudioStream *_macstr;
434  MacSndLoader *_loader;
435  MacLowLevelPCMDriver *_sdrv;
436  Audio::SoundHandle _soundHandle;
439 
440  ScummEngine *_vm;
441  Audio::Mixer *_mixer;
442  static Common::WeakPtr<LoomMonkeyMacSnd> *_inst;
443 
444  byte _curChanConfig;
445  byte _chanUse;
446  byte _curSynthType;
447  Audio::Mixer::SoundType _curSndType;
448  Audio::Mixer::SoundType _lastSndType;
449  byte _chanPlaying;
450 };
451 
452 extern const uint8 _fourToneSynthWaveForm[256];
453 extern const uint32 _fourToneSynthWaveFormSize;
454 
455 } // End of namespace Scumm
456 
457 #endif
Definition: player_mac_intern.h:76
Definition: ptr.h:115
Definition: player_mac_intern.h:217
Definition: array.h:52
Definition: player_mac_intern.h:32
int getRate() const override
Definition: player_mac_intern.h:179
bool isStereo() const override
Definition: player_mac_intern.h:178
Definition: player_mac_intern.h:116
Definition: player_mac_intern.h:46
Definition: player_mac_intern.h:155
Definition: serializer.h:79
Definition: scumm.h:518
Definition: mixer.h:49
SoundType
Definition: mixer.h:62
Definition: mixer.h:59
bool endOfData() const override
Definition: player_mac_intern.h:180
Definition: mutex.h:67
Definition: audiostream.h:50
Definition: player_mac_intern.h:163
Definition: player_mac_intern.h:74
Definition: player_mac_intern.h:374
Definition: actor.h:30
Definition: mixer.h:63