1 module dgt.sound; 2 import derelict.sdl2.mixer; 3 import dgt.io; 4 import dgt.util : nullTerminate; 5 6 /** 7 A loaded chunk of sound data 8 */ 9 struct SoundClip 10 { 11 private Mix_Chunk* source; 12 13 @disable this(); 14 @disable this(this); 15 16 @nogc nothrow: 17 ///Load the clip from the specified path 18 this(in string path) 19 { 20 auto pathNullTerminated = nullTerminate(path); 21 source = Mix_LoadWAV(pathNullTerminated.ptr); 22 pathNullTerminated.destroy(); 23 if(source == null) 24 println("Sound file at ", path, " not found."); 25 } 26 27 ~this() 28 { 29 Mix_FreeChunk(source); 30 } 31 32 ///Get the volume for the sound clip 33 @property int volume() { return Mix_VolumeChunk(source, -1); } 34 ///Set the volume for the sound clip 35 @property int volume(in int value) { return Mix_VolumeChunk(source, value); } 36 ///Play a sound a certain number of times, returning an instance 37 SoundInstance play(in int times = 1) 38 { 39 return SoundInstance(Mix_PlayChannel(-1, source, times - 1)); 40 } 41 } 42 43 /** 44 A specific instance of a playing sound 45 46 The sound instance is invalid once the sound has stopped 47 */ 48 struct SoundInstance 49 { 50 private int id; 51 52 @nogc nothrow: 53 this(in int id) { this.id = id; } 54 55 ///Pause the current clip 56 void pause() { Mix_Pause(id); } 57 ///Resume the clip 58 void resume() { Mix_Resume(id); } 59 ///Stop the clip 60 void stop() { Mix_HaltChannel(id); } 61 ///Fade the clip to silence over a certain number of milliseconds 62 void fadeOut(in int ms) { Mix_FadeOutChannel(id, ms); } 63 ///Checks if the sound is playing 64 @property bool isPlaying() const { return Mix_Playing(id) != 0; } 65 ///Checks if the sound is paused 66 @property bool isPaused() const { return Mix_Paused(id) != 0; } 67 }