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 }