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