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 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (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, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef AUDIO_MIDIDRV_MS_H 24 #define AUDIO_MIDIDRV_MS_H 25 26 #include "common/mutex.h" 27 28 #include "audio/mididrv.h" 29 30 /** 31 * Abstract base class for MIDI drivers supporting multiple simultaneous 32 * sources of MIDI data. 33 * 34 * These drivers support the following features: 35 * 36 * - Multiple MIDI sources 37 * If the game plays multiple streams of MIDI data at the same time, each 38 * stream can be marked with a source number. When a source has finished 39 * playing, it must be deinitialized to release any resources allocated to 40 * it. This is done automatically when an End Of Track MIDI meta event is 41 * received, or manually by calling deinitSource. 42 * Using source numbers enables the following features: 43 * - Music/SFX volume 44 * Using setSourceType a MIDI source can be designated as music or sound 45 * effects. The driver will then apply the appropriate user volume setting 46 * to the MIDI channel volume. This setting sticks after deinitializing a 47 * source, so if you use the same source numbers for the same types of MIDI 48 * data, you don't need to set the source type repeatedly. The default setup 49 * is music for source 0 and SFX for sources 1 and higher. 50 * - Source volume 51 * If the game changes the volume of the MIDI playback, you can use 52 * setSourceVolume to set the volume level for a source. The driver will 53 * then adjust the current MIDI channel volume and any received MIDI volume 54 * controller messages. Use setSourceNeutralVolume to set the neutral volume 55 * for a source (MIDI volume is not changed when source volume is at this 56 * level; if it is lower or higher, MIDI volume is reduced or increased). 57 * - Volume fading 58 * If the game needs to gradually change the volume of the MIDI playback 59 * (typically for a fade-out), you can use the startFade function. You can 60 * check the status of the fade using isFading, and abort a fade using 61 * abortFade. An active fade is automatically aborted when the fading source 62 * is deinitialized. 63 * The fading functionality uses the source volume, so you should not set 64 * this while a fade is active. After the fade the source volume will remain 65 * at the target level, so if you perform f.e. a fade-out, the source volume 66 * will remain at 0. If you want to start playback again using this source, 67 * use setSourceVolume to set the correct playback volume. 68 * Note that when you stop MIDI playback, notes will not be immediately 69 * silent but will gradually die out ("release"). So if you fade out a 70 * source, stop playback, and immediately reset the source volume, the 71 * note release will be audible. It is recommended to wait about 0.5s 72 * before resetting the source volume. 73 * 74 * - User volume settings 75 * The driver can scale the MIDI channel volume using the user specified 76 * volume settings. Just call syncSoundSettings when the user has changed the 77 * volume settings. Set the USER_VOLUME_SCALING property to true to enable 78 * this functionality. 79 * 80 * A driver extending this class must implement the following functions: 81 * - send(source, data): process a MIDI event for a specific source. 82 * - stopAllNotes(source, channel): stop all active notes for a source and/or 83 * MIDI channel (called when a source is deinitialized). 84 * - applySourceVolume(source): set the current source volume on active notes 85 * and/or MIDI channels. 86 */ 87 class MidiDriver_Multisource : public MidiDriver { 88 public: 89 /** 90 * The maximum number of sources supported. This can be increased if 91 * necessary, but this will consume more memory and processing time. 92 */ 93 static const uint8 MAXIMUM_SOURCES = 10; 94 /** 95 * The default neutral volume level for a source. If the source volume is 96 * set to this level, the volume levels in the MIDI data are used directly; 97 * if source volume is lower or higher, output volume is decreased or 98 * increased, respectively. Use @see setSourceNeutralVolume to change the 99 * default neutral volume. 100 */ 101 static const uint16 DEFAULT_SOURCE_NEUTRAL_VOLUME = 255; 102 103 protected: 104 // Timeout between updates of the channel volume for fades (25ms) 105 static const uint16 FADING_DELAY = 25 * 1000; 106 107 public: 108 /** 109 * The type of audio produced by a MIDI source (music or sound effects). 110 */ 111 enum SourceType { 112 /** 113 * Source type not specified (generally treated as music). 114 */ 115 SOURCE_TYPE_UNDEFINED, 116 /** 117 * Source produces music. 118 */ 119 SOURCE_TYPE_MUSIC, 120 /** 121 * Source produces sound effects. 122 */ 123 SOURCE_TYPE_SFX 124 }; 125 126 /** 127 * Specifies what happens to the volume when a fade is aborted. 128 */ 129 enum FadeAbortType { 130 /** 131 * The volume is set to the fade's end volume level. 132 */ 133 FADE_ABORT_TYPE_END_VOLUME, 134 /** 135 * The volume remains at the current level. 136 */ 137 FADE_ABORT_TYPE_CURRENT_VOLUME, 138 /** 139 * The volume is reset to the fade's start volume level. 140 */ 141 FADE_ABORT_TYPE_START_VOLUME 142 }; 143 144 protected: 145 // This stores data about a specific source of MIDI data. 146 struct MidiSource { 147 // Whether this source sends music or SFX MIDI data. 148 SourceType type; 149 // The source volume (relative volume for this source as defined by the 150 // game). Default is the default neutral value (255). 151 uint16 volume; 152 // The source volume level at which no scaling is performed (volume as 153 // defined in the MIDI data is used directly). Volume values below this 154 // decrease volume, values above increase volume (up to the maximum MIDI 155 // channel volume). Set this to match the volume values used by the game 156 // engine to avoid having to convert them. Default value is 255; minimum 157 // value is 1. 158 uint16 neutralVolume; 159 // The volume level at which the fade started. 160 uint16 fadeStartVolume; 161 // The target volume level for the fade. 162 uint16 fadeEndVolume; 163 // How much time (microseconds) has passed since the start of the fade. 164 int32 fadePassedTime; 165 // The total duration of the fade (microseconds). 166 int32 fadeDuration; 167 168 MidiSource(); 169 }; 170 171 public: 172 MidiDriver_Multisource(); 173 174 // MidiDriver functions 175 using MidiDriver_BASE::send; 176 void send(uint32 b) override; 177 void send(int8 source, uint32 b) override = 0; 178 179 uint32 property(int prop, uint32 param) override; 180 181 /** 182 * Deinitializes a source. This will abort active fades and stop any active 183 * notes. 184 * 185 * @param source The source to deinitialize. 186 */ 187 virtual void deinitSource(uint8 source); 188 /** 189 * Sets the type for all sources (music or SFX). 190 * 191 * @param type The new type for all sources. 192 */ 193 void setSourceType(SourceType type); 194 /** 195 * Sets the type for a specific sources (music or SFX). 196 * 197 * @param source The source for which the type should be set. 198 * @param type The new type for the specified source. 199 */ 200 void setSourceType(uint8 source, SourceType type); 201 /** 202 * Sets the source volume for all sources. 203 * 204 * @param volume The new source volume for all sources. 205 */ 206 void setSourceVolume(uint16 volume); 207 /** 208 * Sets the volume for this source. The volume values in the MIDI data sent 209 * by this source will be scaled by the source volume. 210 * 211 * @param source The source for which the source volume should be set. 212 * @param volume The new source volume for the specified source. 213 */ 214 void setSourceVolume(uint8 source, uint16 volume); 215 /** 216 * Resets the source volume for all sources to each source's neutral volume. 217 */ 218 void resetSourceVolume(); 219 /** 220 * Resets the volume for this source to its neutral volume. 221 */ 222 void resetSourceVolume(uint8 source); 223 /** 224 * Sets the neutral volume for all sources. See the source-specific 225 * setSourceNeutralVolume function for details. 226 * 227 * @param volume The new neutral volume for all sources. 228 */ 229 void setSourceNeutralVolume(uint16 volume); 230 /** 231 * Sets the neutral volume for this source. If the source volume is at this 232 * level, the volume values in the MIDI data sent by this source will not 233 * be changed. At source volumes below or above this value, the MIDI volume 234 * values will be decreased or increased accordingly. 235 * 236 * @param source The source for which the neutral volume should be set. 237 * @param volume The new neutral volume for the specified source. 238 */ 239 void setSourceNeutralVolume(uint8 source, uint16 volume); 240 241 /** 242 * Starts a fade for all sources. 243 * See the source-specific startFade function for more information. 244 * 245 * @param duration The fade duration in milliseconds 246 * @param targetVolume The volume at the end of the fade 247 */ 248 void startFade(uint16 duration, uint16 targetVolume); 249 /** 250 * Starts a fade for a source. This will linearly increase or decrease the 251 * volume of the MIDI channels used by the source to the specified target 252 * value over the specified length of time. 253 * 254 * @param source The source to fade 255 * @param duration The fade duration in milliseconds 256 * @param targetVolume The volume at the end of the fade 257 */ 258 void startFade(uint8 source, uint16 duration, uint16 targetVolume); 259 /** 260 * Aborts any active fades for all sources. 261 * See the source-specific abortFade function for more information. 262 * 263 * @param abortType How to set the volume when aborting the fade (default: 264 * set to the target fade volume). 265 */ 266 void abortFade(FadeAbortType abortType = FADE_ABORT_TYPE_END_VOLUME); 267 /** 268 * Aborts an active fade for a source. Depending on the abort type, the 269 * volume will remain at the current value or be set to the start or end 270 * volume. If there is no active fade for the specified source, this 271 * function does nothing. 272 * 273 * @param source The source that should have its fade aborted 274 * @param abortType How to set the volume when aborting the fade (default: 275 * set to the target fade volume). 276 */ 277 void abortFade(uint8 source, FadeAbortType abortType = FADE_ABORT_TYPE_END_VOLUME); 278 /** 279 * Check if any source has an active fade. 280 * 281 * @return True if any source has an active fade. 282 */ 283 bool isFading(); 284 /** 285 * Check if the specified source has an active fade. 286 * 287 * @return True if the specified source has an active fade. 288 */ 289 bool isFading(uint8 source); 290 291 /** 292 * Applies the user volume settings to the MIDI driver. MIDI channel 293 * volumes will be scaled using the user volume. 294 * This function must be called by the engine when the user has changed the 295 * volume settings. 296 */ 297 void syncSoundSettings(); 298 299 using MidiDriver::stopAllNotes; 300 /** 301 * Stops all active notes (including sustained notes) for the specified 302 * source and MIDI channel. For both source and channel the value 0xFF can 303 * be specified, in which case active notes will be stopped for all sources 304 * and/or MIDI channels. 305 * 306 * @param source The source for which all notes should be stopped, or all 307 * sources if 0xFF is specified. 308 * @param channel The MIDI channel on which all notes should be stopped, or 309 * all channels if 0xFF is specified. 310 */ 311 virtual void stopAllNotes(uint8 source, uint8 channel) = 0; 312 313 /** 314 * Sets a callback which will be called whenever the driver's timer 315 * callback is called by the underlying emulator or hardware driver. The 316 * callback will only be called when the driver is open. Use 317 * @see getBaseTempo to get the delay between each callback invocation. 318 * 319 * @param timer_param A parameter that will be passed to the callback 320 * function. Optional. 321 * @param timer_proc The function that should be called. 322 */ setTimerCallback(void * timer_param,Common::TimerManager::TimerProc timer_proc)323 void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) override { 324 _timer_param = timer_param; 325 _timer_proc = timer_proc; 326 } 327 328 protected: 329 /** 330 * Applies the current source volume to the active notes and/or MIDI 331 * channels of the specified source. 0xFF can be specified to apply the 332 * source volume for all sources. 333 * 334 * @param source The source for which the source volume should be applied, 335 * or all sources if 0xFF is specified. 336 */ 337 virtual void applySourceVolume(uint8 source) = 0; 338 /** 339 * Processes active fades and sets new volume values if necessary. 340 */ 341 void updateFading(); 342 /** 343 * Runs the MIDI driver's timer related functionality. Will update volume 344 * fades and calls the timer callback if necessary. 345 */ 346 virtual void onTimer(); 347 348 // MIDI source data 349 MidiSource _sources[MAXIMUM_SOURCES]; 350 351 // True if the driver should scale MIDI channel volume to the user 352 // specified volume settings. 353 bool _userVolumeScaling; 354 355 // User volume settings 356 uint16 _userMusicVolume; 357 uint16 _userSfxVolume; 358 bool _userMute; 359 360 Common::Mutex _fadingMutex; // For operations on fades 361 362 // The number of microseconds to wait before the next fading step. 363 uint16 _fadeDelay; 364 365 // The number of microseconds between timer callback invocations. 366 uint32 _timerRate; 367 368 // External timer callback 369 void *_timer_param; 370 Common::TimerManager::TimerProc _timer_proc; 371 }; 372 373 class MidiDriver_NULL_Multisource : public MidiDriver_Multisource { 374 public: 375 ~MidiDriver_NULL_Multisource(); 376 377 int open() override; isOpen()378 bool isOpen() const override { return true; } close()379 void close() override { } getBaseTempo()380 uint32 getBaseTempo() override { return 10000; } allocateChannel()381 MidiChannel *allocateChannel() override { return 0; } getPercussionChannel()382 MidiChannel *getPercussionChannel() override { return 0; } 383 384 using MidiDriver_Multisource::send; send(int8 source,uint32 b)385 void send(int8 source, uint32 b) override { } 386 using MidiDriver_Multisource::stopAllNotes; stopAllNotes(uint8 source,uint8 channel)387 void stopAllNotes(uint8 source, uint8 channel) override { } 388 389 static void timerCallback(void *data); 390 391 protected: applySourceVolume(uint8 source)392 void applySourceVolume(uint8 source) override { } 393 }; 394 395 #endif 396