ScummVM API documentation
qmixer.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  * aint with this program; if not, write to the Free Software
19  *
20  */
21 
22 #ifndef TITANIC_QMIXER_H
23 #define TITANIC_QMIXER_H
24 
25 #include "audio/mixer.h"
26 #include "titanic/sound/wave_file.h"
27 
28 namespace Titanic {
29 
30 enum QMixFlag {
31  QMIX_OPENSINGLE = 0, // Open the single channel specified by iChannel
32  QMIX_OPENALL = 1, // Opens all the channels, iChannel ignored
33  QMIX_OPENCOUNT = 2, // Open iChannel Channels (eg. if iChannel = 4 will create channels 0-3)
34  QMIX_OPENAVAILABLE = 3, // Open the first unopened channel, and return channel number
35 
36  // Channel function flags
37  QMIX_ALL = 0x01, // apply to all channels
38  QMIX_NOREMIX = 0x02, // don't remix
39  QMIX_CONTROL_NOREMIX = 0x04, // don't remix
40  QMIX_USEONCE = 0x10 // settings are temporary
41 };
42 
43 // qsWaveMixEnableChannel flags: if mode==0, use conventional, high-performance
44 // stereo mixer. Non-zero modes imply some form of additional processing.
45 enum QMixChannelFlag {
46  QMIX_CHANNEL_STEREO = 0x0000, // Perform stereo mixing
47  QMIX_CHANNEL_QSOUND = 0x0001, // Perform QSound localization (default)
48  QMIX_CHANNEL_DOPPLER = 0x0002, // Calculate velocity using position updates
49  QMIX_CHANNEL_RANGE = 0x0004, // Do range effects
50  QMIX_CHANNEL_ELEVATION = 0x0008, // Do elevation effects
51  QMIX_CHANNEL_NODOPPLERPITCH = 0x0010, // Disable Doppler pitch shift for this channel
52  QMIX_CHANNEL_PITCH_COPY = 0x0000, // Pitch shifting using copying (fastest)
53  QMIX_CHANNEL_PITCH_LINEAR = 0x0100, // Pitch shifting using linear interpolation (better but slower)
54  QMIX_CHANNEL_PITCH_SPLINE = 0x0200, // Pitch shifting using spline interpolation (better yet, but much slower)
55  QMIX_CHANNEL_PITCH_FILTER = 0x0300, // Pitch shifting using FIR filter (best, but slowest)
56  QMIX_CHANNEL_PITCH_MASK = 0x0700 // Bits reserved for pitch types
57 };
58 
70 enum QMixPlayFlag {
71  QMIX_QUEUEWAVE = 0x0000, // Queue on channel
72  QMIX_CLEARQUEUE = 0x0001, // Clear queue on channel
73  QMIX_USELRUCHANNEL = 0x0002, // See notes above
74  QMIX_HIGHPRIORITY = 0x0004,
75  QMIX_WAIT = 0x0008, // Queue to be played with other sounds
76  QMIX_IMMEDIATE = 0x0020, // Apply volume/pan changes without interpolation
77 
78  QMIX_PLAY_SETEVENT = 0x0100, // Calls SetEvent in the original library when done
79  QMIX_PLAY_PULSEEVENT = 0x0200, // Calls PulseEvent in the original library when done
80  QMIX_PLAY_NOTIFYSTOP = 0x0400 // Do callback even when stopping or flushing sound
81 };
82 
86 struct QMIXCONFIG {
87  uint32 dwSize;
88  uint32 dwFlags;
89  uint32 dwSamplingRate; // Sampling rate in Hz
90  void *lpIDirectSound;
91  const void *lpGuid;
92  int iChannels; // Number of channels
93  int iOutput; // if 0, uses best output device
94  int iLatency; // (in ms) if 0, uses default for output device
95  int iMath; // style of math
96  uint hwnd;
97 
98  QMIXCONFIG() : dwSize(40), dwFlags(0), dwSamplingRate(0), lpIDirectSound(nullptr),
99  lpGuid(nullptr), iChannels(0), iOutput(0), iLatency(0), iMath(0), hwnd(0) {}
100  QMIXCONFIG(uint32 rate, int channels, int latency) : dwSize(40), dwFlags(0),
101  dwSamplingRate(rate), iChannels(channels), iLatency(latency),
102  lpIDirectSound(nullptr), lpGuid(nullptr), iOutput(0), iMath(0), hwnd(0) {}
103 };
104 
108 struct QSVECTOR {
109  double x;
110  double y;
111  double z;
112 
113  QSVECTOR() : x(0.0), y(0.0), z(0.0) {}
114  QSVECTOR(double xp, double yp, double zp) : x(xp), y(yp), z(zp) {}
115 };
116 
120 struct QSPOLAR {
121  double azimuth; // degrees
122  double range; // meters
123  double elevation; // degrees
124 
125  QSPOLAR() : azimuth(0.0), range(0.0), elevation(0.0) {}
126  QSPOLAR(double azimuth_, double range_, double elevation_) :
127  azimuth(azimuth_), range(range_), elevation(elevation_) {}
128 };
129 
131  int cbSize; // Structure size
132  double minDistance; // sounds are at full volume if closer than this
133  double maxDistance; // sounds are muted if further away than this
134  double scale; // relative amount to adjust rolloff by
135 
136  QMIX_DISTANCES() : cbSize(16), minDistance(0.0), maxDistance(0.0), scale(0.0) {}
137  QMIX_DISTANCES(double minDistance_, double maxDistance_, double scale_) :
138  cbSize(16), minDistance(minDistance_), maxDistance(maxDistance_), scale(scale_) {}
139 };
140 
141 typedef void (*LPQMIXDONECALLBACK)(int iChannel, CWaveFile *lpWave, void *dwUser);
142 
144  uint dwSize; // Size of the play structure
145  void *lpImage; // Additional preprocessed audio for high performance
146  uint hwndNotify; // if set, WOM_OPEN and WOM_DONE messages sent to that window
147  LPQMIXDONECALLBACK callback; // Callback function
148  void *dwUser; // User data accompanying callback
149  int lStart;
150  int lStartLoop;
151  int lEndLoop;
152  int lEnd;
153  const void *lpChannelParams; // initialize with these parameters
154  // Properties introduced by ScummVM
155  Audio::Mixer::SoundType _soundType;
156 
157  QMIXPLAYPARAMS() : dwSize(36), lpImage(nullptr), hwndNotify(0), callback(nullptr),
158  dwUser(nullptr), lStart(0), lStartLoop(0), lEndLoop(0), lEnd(0),
159  lpChannelParams(nullptr), _soundType(Audio::Mixer::kPlainSoundType) {}
160 };
161 
173 class QMixer {
174  struct SoundEntry {
175  bool _started;
176  CWaveFile *_waveFile;
177  Audio::SoundHandle _soundHandle;
178  LPQMIXDONECALLBACK _callback;
179  int _loops;
180  void *_userData;
181  SoundEntry() : _started(false), _waveFile(nullptr), _callback(nullptr),
182  _loops(0), _userData(nullptr) {}
183 
184  SoundEntry(CWaveFile *waveFile, LPQMIXDONECALLBACK callback, int loops, void *userData) :
185  _started(false), _waveFile(waveFile), _callback(callback), _loops(loops), _userData(userData) {}
186  };
187  struct ChannelEntry {
188  // Currently playing and any following queued sounds for the channel
189  Common::List<SoundEntry> _sounds;
190  // Current channel volume
191  byte _volume;
192  // Current time in milliseconds for paning (volume) changes
193  uint _panRate;
194  // Fields used to transition between volume levels
195  uint _volumeChangeStart;
196  uint _volumeChangeEnd;
197  byte _volumeStart;
198  byte _volumeEnd;
199  // Distance of source
200  double _distance;
201  bool _resetDistance;
202 
203  ChannelEntry() : _volume(0), _panRate(0), _volumeChangeStart(0),
204  _volumeChangeEnd(0), _volumeStart(0), _volumeEnd(0),
205  _distance(0.0), _resetDistance(true) {}
206 
211  byte getRawVolume() const;
212  };
213 private:
214  Common::Array<ChannelEntry> _channels;
215 protected:
216  Audio::Mixer *_mixer;
217 public:
218  QMixer(Audio::Mixer *mixer);
219  virtual ~QMixer();
220 
224  bool qsWaveMixInitEx(const QMIXCONFIG &config);
225 
229  void qsWaveMixActivate(bool fActivate);
230 
234  int qsWaveMixOpenChannel(int iChannel, QMixFlag mode);
235 
239  int qsWaveMixEnableChannel(int iChannel, uint flags, bool enabled);
240 
244  void qsWaveMixCloseSession();
245 
249  void qsWaveMixFreeWave(Audio::SoundHandle &handle);
250 
254  void qsWaveMixFlushChannel(int iChannel, uint flags = 0);
255 
264  void qsWaveMixSetPanRate(int iChannel, uint flags, uint rate);
265 
269  void qsWaveMixSetVolume(int iChannel, uint flags, uint volume);
270 
277  void qsWaveMixSetSourcePosition(int iChannel, uint flags, const QSVECTOR &position);
278 
285  void qsWaveMixSetPolarPosition(int iChannel, uint flags, const QSPOLAR &position);
286 
290  void qsWaveMixSetListenerPosition(const QSVECTOR &position, uint flags = 0);
291 
295  void qsWaveMixSetListenerOrientation(const QSVECTOR &direction, const QSVECTOR &up, uint flags = 0);
296 
300  void qsWaveMixSetDistanceMapping(int iChannel, uint flags, const QMIX_DISTANCES &distances);
301 
305  void qsWaveMixSetFrequency(int iChannel, uint flags, uint frequency);
306 
310  void qsWaveMixSetSourceVelocity(int iChannel, uint flags, const QSVECTOR &velocity);
311 
320  int qsWaveMixPlayEx(int iChannel, uint flags, CWaveFile *waveFile, int loops, const QMIXPLAYPARAMS &params);
321 
325  bool qsWaveMixIsChannelDone(int iChannel) const;
326 
330  void qsWaveMixPump();
331 };
332 
333 } // End of namespace Titanic
334 
335 #endif /* TITANIC_QMIXER_H */
Definition: mixer.h:49
Graphics::Surface * scale(const Graphics::Surface &srcImage, int xSize, int ySize)
SoundType
Definition: mixer.h:62
Definition: mixer.h:59
Definition: qmixer.h:173
Definition: qmixer.h:120
Definition: qmixer.h:108
Definition: arm.h:30
Definition: qmixer.h:86
Definition: wave_file.h:35
Definition: qmixer.h:143
Definition: qmixer.h:130
Definition: mixer.h:63