1 /* 2 ******************************************************************************************* 3 * Dgame (a D game framework) - Copyright (c) Randy Schütt 4 * 5 * This software is provided 'as-is', without any express or implied warranty. 6 * In no event will the authors be held liable for any damages arising from 7 * the use of this software. 8 * 9 * Permission is granted to anyone to use this software for any purpose, 10 * including commercial applications, and to alter it and redistribute it 11 * freely, subject to the following restrictions: 12 * 13 * 1. The origin of this software must not be misrepresented; you must not claim 14 * that you wrote the original software. If you use this software in a product, 15 * an acknowledgment in the product documentation would be appreciated but is 16 * not required. 17 * 18 * 2. Altered source versions must be plainly marked as such, and must not be 19 * misrepresented as being the original software. 20 * 21 * 3. This notice may not be removed or altered from any source distribution. 22 ******************************************************************************************* 23 */ 24 module Dgame.Audio.Sound; 25 26 private: 27 28 import derelict.sdl2.mixer; 29 30 import Dgame.Internal.Error; 31 32 public: 33 34 /** 35 * Sound represents the functionality to load and play sound files. 36 * 37 * Note: Sound is designed to load and play <b>short</b> music files, e.g. sounds for some noises. 38 * If you want to play larger music, use Music. 39 * Note: Each Sound is played in his own channel, which means, that the number of simultaneously existing Sounds is limited to 256. 40 * This limit will be increased if necessary. 41 * 42 * Supported formats are .wav, .mp3, .vorbis, .ogg, .midi 43 * 44 * Author: Randy Schuett (rswhite4@googlemail.com) 45 */ 46 struct Sound { 47 private: 48 Mix_Chunk* _chunk; 49 ushort _channel; 50 51 static ushort ChannelCount = 0; 52 53 public: 54 /** 55 * CTor 56 */ 57 @nogc 58 this(string filename, ubyte volume = 128) nothrow { 59 this.loadFromFile(filename); 60 this.setVolume(volume); 61 } 62 63 /** 64 * Postblit is disabled 65 */ 66 @disable 67 this(this); 68 69 /** 70 * DTor 71 */ 72 @nogc 73 ~this() nothrow { 74 Mix_FreeChunk(_chunk); 75 } 76 77 /** 78 * Returns the current channel in which this Sound plays. Should be in range of 1 .. 256 79 */ 80 @nogc 81 ushort getChannel() const pure nothrow { 82 return _channel; 83 } 84 85 /** 86 * Load the sound file (filename). 87 * Returns if the loading was successful. 88 * If not, an error message is showed which describes what the problem is. 89 */ 90 @nogc 91 bool loadFromFile(string filename) nothrow { 92 _chunk = Mix_LoadWAV(filename.ptr); 93 if (!_chunk) { 94 print_fmt("Could not load file: %s\n", Mix_GetError()); 95 return false; 96 } 97 98 return true; 99 } 100 101 /** 102 * Set the volume, max. is 128, min. is 0 103 * If the value is above 128, the max. will be assumed. 104 * Returns the previous volume. 105 */ 106 @nogc 107 ubyte setVolume(ubyte volume) nothrow { 108 if (_chunk) 109 return cast(ubyte) Mix_VolumeChunk(_chunk, volume); 110 return 0; 111 } 112 113 /** 114 * Returns the current volume. 115 */ 116 @nogc 117 ubyte getVolume() nothrow { 118 if (_chunk) 119 return cast(ubyte) Mix_VolumeChunk(_chunk, -1); 120 return 0; 121 } 122 123 /** 124 * Plays the sound. 125 * loops describe how often the sound shall be played. 126 * A value of -1 indicated, that the sound plays forever, 127 * a value of 0 means, that the sound plays zero times. 128 * delay is the time in ms to fade in. 129 * Any previous sound will be halted. 130 */ 131 @nogc 132 bool play(byte loops = 1, short delay = -1) nothrow { 133 if (_chunk) { 134 loops = loops > 0 ? cast(byte)(loops - 1) : loops; 135 Mix_PlayChannelTimed(_channel, _chunk, loops, delay); 136 137 return true; 138 } 139 140 return false; 141 } 142 143 /** 144 * Resume the sound playback 145 * 146 * See: pause 147 * See: stop 148 */ 149 @nogc 150 void resume() const nothrow { 151 Mix_Resume(_channel); 152 } 153 154 /** 155 * Stop/Halt the sound playback 156 * 157 * See: resume 158 */ 159 @nogc 160 void stop() const nothrow { 161 Mix_HaltChannel(_channel); 162 } 163 164 /** 165 * Pause the sound playback 166 * 167 * See: resume 168 */ 169 @nogc 170 void pause() const nothrow { 171 Mix_Pause(_channel); 172 } 173 174 /** 175 * Stop sound playback after ms milliseconds. 176 */ 177 @nogc 178 void expire(ushort ms) const nothrow { 179 Mix_ExpireChannel(_channel, ms); 180 } 181 182 /** 183 * Returns if the sound is currently playing 184 */ 185 @nogc 186 bool isPlaying() const nothrow { 187 return Mix_Playing(_channel) != 0; 188 } 189 190 /** 191 * Returns if the sound is currently paused 192 */ 193 @nogc 194 bool isPaused() const nothrow { 195 return Mix_Paused(_channel) == 0; 196 } 197 }