ScummVM API documentation
mac_sound_lowlevel.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_MAC_SOUND_LOWLEVEL_H
23 #define SCUMM_PLAYERS_MAC_SOUND_LOWLEVEL_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  kStatusDisabled = 1 << 7
61  };
62 
63  void clearFlags(uint8 flags, Audio::Mixer::SoundType sndType = Audio::Mixer::kPlainSoundType) { _status[sndType].flags &= ~flags; }
64  void setFlags(uint8 flags, Audio::Mixer::SoundType sndType = Audio::Mixer::kPlainSoundType) { _status[sndType].flags |= flags; }
65 
66 protected:
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 
117  struct DoubleBuffer {
118  enum Flags : uint32 {
119  kBufferReady = 1,
120  kLastBufferLast = 4
121  };
122  DoubleBuffer(ChanHandle hdl, uint32 numframes) : numFrames(numframes), flags(0), data(0), chanHandle(hdl) {}
123  ~DoubleBuffer() { delete[] data; }
124  uint32 numFrames;
125  const ChanHandle chanHandle;
126  uint32 flags;
127  byte *data;
128  };
129 
131  public:
132  virtual ~CallbackClient() {}
133  virtual void sndChannelCallback(uint16 arg1, const void *arg2) {}
134  virtual void dblBuffCallback(DoubleBuffer *dblBuffer) {}
135  };
138 
139 public:
140  MacLowLevelPCMDriver(Common::Mutex &mutex, uint32 deviceRate, bool internal16Bit);
141  ~MacLowLevelPCMDriver() override;
142 
143  void feed(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) override;
144 
145  ChanHandle createChannel(Audio::Mixer::SoundType sndType, SynthType synthType, byte attributes, ChanCallback *callback);
146  void disposeChannel(ChanHandle handle);
147 
148  void playSamples(ChanHandle handle, ExecMode mode, const PCMSound *snd);
149  void playNote(ChanHandle handle, ExecMode mode, uint8 note, uint16 duration);
150  void quiet(ChanHandle handle, ExecMode mode);
151  void flush(ChanHandle handle, ExecMode mode);
152  void wait(ChanHandle handle, ExecMode mode, uint16 duration);
153  void loadWaveTable(ChanHandle handle, ExecMode mode, const byte *data, uint16 dataSize);
154  void loadInstrument(ChanHandle handle, ExecMode mode, const PCMSound *snd);
155  void setTimbre(ChanHandle handle, ExecMode mode, uint16 timbre);
156  void callback(ChanHandle handle, ExecMode mode, uint16 arg1, const void *arg2);
157 
158  bool playDoubleBuffer(ChanHandle handle, byte numChan, byte bitsPerSample, uint32 rate, DBCallback *callback, byte numMixChan = 1);
159 
160  uint8 getChannelStatus(ChanHandle handle) const;
161  void clearChannelFlags(ChanHandle handle, uint8 flags);
162 
163  static uint32 calcRate(uint32 outRate, uint32 factor, uint32 dataRate);
164 
165 private:
166  void updateStatus(Audio::Mixer::SoundType sndType);
167  MacSndChannel *findAndCheckChannel(ChanHandle h, const char *caller, byte reqSynthType) const;
168  MacSndChannel *findChannel(ChanHandle h) const;
170  int _numInternalMixChannels[4];
171  int32 *_mixBuffer = 0;
172  uint32 _mixBufferSize;
173 };
174 
176 public:
177  virtual ~VblTaskClientDriver() {}
178  virtual void vblCallback() = 0;
179  virtual void generateData(int8 *dst, uint32 len, Audio::Mixer::SoundType type, bool expectStereo) const = 0;
180  virtual const MacSoundDriver::Status &getDriverStatus(Audio::Mixer::SoundType sndType) const = 0;
181 };
182 
184 public:
185  MacPlayerAudioStream(VblTaskClientDriver *drv, uint32 scummVMOutputrate, bool stereo, bool interpolate, bool internal16Bit);
186  ~MacPlayerAudioStream() override;
187 
188  void initBuffers(uint32 feedBufferSize);
189  void initDrivers();
190  void addVolumeGroup(Audio::Mixer::SoundType type);
191  void scaleVolume(uint upscale, uint downscale) { _upscale = upscale; _downscale = downscale; }
193  void setVblCallback(const CallbackProc *proc);
194  void clearBuffer();
195 
196  void setMasterVolume(Audio::Mixer::SoundType type, uint16 vol);
197 
198  // AudioStream interface
199  int readBuffer(int16 *buffer, const int numSamples) override;
200  bool isStereo() const override { return _isStereo; }
201  int getRate() const override { return _outputRate; }
202  bool endOfData() const override { return false; }
203 
204 private:
205  void generateData(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType, bool expectStereo) const;
206  void runVblTask();
207 
208  VblTaskClientDriver *_drv;
209  int _numGroups;
210  uint16 _upscale;
211  uint16 _downscale;
212 
213  uint32 _vblSmpQty;
214  uint32 _vblSmpQtyRem;
215  uint32 _vblCountDown;
216  uint32 _vblCountDownRem;
217  const CallbackProc *_vblCbProc;
218 
219  struct SmpBuffer {
220  SmpBuffer() : start(0), pos(0), end(0), volume(0), lastL(0), lastR(0), size(0), rateConvInt(0), rateConvFrac(0), rateConvAcc(-1), group(Audio::Mixer::kPlainSoundType) {}
221  int8 *start;
222  int8 *pos;
223  const int8 *end;
224  uint32 volume;
225  int32 lastL;
226  int32 lastR;
227  uint32 size;
228  uint32 rateConvInt;
229  uint32 rateConvFrac;
230  int32 rateConvAcc;
232  } *_buffers;
233 
234  const uint32 _outputRate;
235  const uint8 _frameSize;
236  const bool _interp;
237  const int _smpInternalSize;
238 
239  const bool _isStereo;
240 };
241 
243 public:
244  // Construct from Mac resource stream
246  // Construct from Mac sound data buffer
247  MacSndResource(uint32 id, const byte *in, uint32 size);
248  ~MacSndResource() {}
249  const MacLowLevelPCMDriver::PCMSound *data() const { return &_snd; }
250  uint32 id() const { return _id; }
251  const char* name() { return _name.c_str(); }
252 
253 private:
254  uint32 _id;
255  Common::String _name;
257 };
258 
259 extern const uint8 _fourToneSynthWaveForm[256];
260 extern const uint32 _fourToneSynthWaveFormSize;
261 
262 } // End of namespace Scumm
263 
264 #endif
Definition: mac_sound_lowlevel.h:77
Definition: str.h:59
Definition: array.h:52
Definition: mac_sound_lowlevel.h:32
int getRate() const override
Definition: mac_sound_lowlevel.h:201
bool isStereo() const override
Definition: mac_sound_lowlevel.h:200
Definition: mac_sound_lowlevel.h:130
Definition: stream.h:745
Definition: mac_sound_lowlevel.h:46
Definition: mac_sound_lowlevel.h:175
SoundType
Definition: mixer.h:62
bool endOfData() const override
Definition: mac_sound_lowlevel.h:202
Definition: func.h:452
Definition: mutex.h:67
Definition: mac_sound_lowlevel.h:117
Definition: audiostream.h:50
Definition: mac_sound_lowlevel.h:183
Definition: mac_sound_lowlevel.h:75
Definition: mac_sound_lowlevel.h:242
Definition: actor.h:30
Definition: mixer.h:63