1 module d2d.audio.sound; 2 3 version(BindSDL_Mixer): 4 5 import d2d; 6 7 /// Thin wrap around Mix_Chunk including loading [FLAC, MikMod, Ogg Vorbis, MP3, Wav] using SDL_Mixer. 8 class Sound : IVerifiable, IDisposable 9 { 10 private Mix_Chunk* _handle; 11 12 /// Handle to the `Mix_Chunk*`. 13 public @property Mix_Chunk* handle() 14 { 15 return _handle; 16 } 17 18 /// Checks if the handle is not null. 19 public @property bool valid() 20 { 21 return _handle !is null; 22 } 23 24 private this(Mix_Chunk * handle) 25 { 26 _handle = handle; 27 } 28 29 /// Loads a sound file 30 public this(string path) 31 { 32 // Confusing name, this can load any format 33 _handle = Mix_LoadWAV(path.toStringz()); 34 } 35 36 public ~this() 37 { 38 dispose(); 39 } 40 41 /// Creates sound from a `Mix_Chunk*`. 42 public static Sound fromChunk(Mix_Chunk* chunk) 43 { 44 return new Sound(chunk); 45 } 46 47 /// Returns the latest sound related error 48 public static @property string error() 49 { 50 return cast(string) Mix_GetError().fromStringz(); 51 } 52 53 /// Deallocates the memory and invalidates `this`. 54 public void dispose() 55 { 56 if (valid) 57 { 58 stop(); 59 Mix_FreeChunk(_handle); 60 _handle = null; 61 } 62 } 63 64 /// Plays this sound in the selected channel. 65 /// Params: 66 /// loops = -1 loops will play forever. 0 plays once. 67 /// channel = -1 loops will choose the first free unreserved channel. 68 /// maxTicks = Maximum milliseconds to play this sound. If not enough loops or the sample chunk is not long enough, then the sample may stop before this timeout occurs. -1 means play forever. 69 /// Returns: the channel the sample is played on. On any errors, -1 is returned. 70 public int play(int loops = 0, int channel = -1, int maxTicks = -1) 71 { 72 return Mix_PlayChannelTimed(channel, _handle, loops, maxTicks); 73 } 74 75 /// Plays this sound in the selected channel with a fade in effect. 76 /// Params: 77 /// ms = Milliseconds for the fade-in effect to complete. 78 /// loops = -1 loops will play forever. 0 plays once. 79 /// channel = -1 loops will choose the first free unreserved channel. 80 /// maxTicks = Maximum milliseconds to play this sound. If not enough loops or the sample chunk is not long enough, then the sample may stop before this timeout occurs. -1 means play forever. 81 /// Returns: the channel the sample is played on. On any errors, -1 is returned. 82 public int fadeIn(int ms, int loops = 1, int channel = -1, int maxTicks = -1) 83 { 84 return Mix_FadeInChannelTimed(channel, _handle, loops, ms, maxTicks); 85 } 86 87 /// Halt playback of sound. This interrupts sound fader effects. 88 /// Params: 89 /// channel = Channel to stop playing, or -1 for all channels. 90 public static void stop(int channel = -1) 91 { 92 Mix_HaltChannel(channel); 93 } 94 95 /// Pause the sound playback. You may halt paused sounds. 96 /// Params: 97 /// channel = Channel to stop playing, or -1 for all channels. 98 /// Note: Sound can only be paused if it is actively playing. 99 public static void pause(int channel = -1) 100 { 101 Mix_Pause(channel); 102 } 103 104 /// Unpause the sound. This is safe to use on halted, paused, and already playing sounds. 105 /// Params: 106 /// channel = Channel to stop playing, or -1 for all channels. 107 public static void resume(int channel = -1) 108 { 109 Mix_Resume(channel); 110 } 111 112 /// Returns the current volume as float in range 0.0 to 1.0 113 /// Params: 114 /// channel = -1 for all channels. 115 public static float getVolume(int channel = -1) 116 { 117 return Mix_Volume(channel, -1) * INV_MIX_MAX_VOLUME; 118 } 119 120 /// Sets the current volume as float in range 0.0 to 1.0 121 /// Params: 122 /// value = volume between 0.0 and 1.0. 123 /// channel = -1 for all channels. 124 public static void setVolume(float value, int channel = -1) 125 { 126 Mix_Volume(channel, cast(int) (value * MIX_MAX_VOLUME)); 127 } 128 129 /// Tells you how many channels are playing if set to -1 130 /// Params: 131 /// channel = -1 for all channels. 132 public static @property int isPlaying(int channel = -1) 133 { 134 return Mix_Playing(channel); 135 } 136 137 /// Tells you how many channels are paused if set to -1 138 /// Params: 139 /// channel = -1 for all channels. 140 public static @property int isPaused(int channel = -1) 141 { 142 return Mix_Paused(channel); 143 } 144 145 /// 146 /// Params: 147 /// channel = -1 is invalid. 148 public static @property FadingStatus fadingStatus(int channel) 149 { 150 assert(channel != -1); 151 return cast(FadingStatus) Mix_FadingChannel(channel); 152 } 153 }