1 module arsd.audio; 2 3 import sdl.SDL; 4 import sdl.SDL_mixer; 5 6 import std.string; 7 8 import arsd.engine; 9 10 bool audioIsLoaded; // potential hack material 11 12 class Sound { 13 public: 14 this(char[] filename){ 15 if(!audioIsLoaded) 16 return; 17 sfx = Mix_LoadWAV(std..string.toStringz(filename)); 18 if(sfx is null) 19 throw new Exception(immutableString("Sound load " ~ filename)); 20 } 21 22 /* 23 this(Wav wav){ 24 auto w = wav.toMemory; 25 SDL_RWops* a = SDL_RWFromMem(w, w.length) 26 if(a is null) throw new Exception("sdl rw ops"); 27 scope(exit) SDL_FreeRW(a); 28 sfx = Mix_LoadWAV_RW(a, 0); 29 if(sfx is null) throw new Exception("loadwav rw"); 30 } 31 */ 32 33 ~this(){ 34 if(sfx !is null) 35 Mix_FreeChunk(sfx); 36 } 37 38 private: 39 Mix_Chunk* sfx; 40 } 41 42 class Music { 43 public: 44 this(char[] filename){ 45 if(!audioIsLoaded) 46 return; 47 mus = Mix_LoadMUS(std..string.toStringz(filename)); 48 if(mus is null) 49 throw new Exception(immutableString("Music load " ~ filename)); 50 } 51 52 ~this(){ 53 if(mus !is null) 54 Mix_FreeMusic(mus); 55 } 56 private: 57 Mix_Music* mus; 58 } 59 60 class Audio{ 61 public: 62 this(bool act = true){ 63 if(audioIsLoaded) 64 throw new Exception("Cannot load audio twice"); 65 66 if(!act){ 67 audioIsLoaded = false; 68 active = false; 69 return; 70 } 71 if(Mix_OpenAudio(22050, AUDIO_S16SYS, 2, 4096/2 /* the /2 is new */) != 0){ 72 active = false; //throw new Error; 73 error = true; 74 audioIsLoaded = false; 75 } else { 76 active = true; 77 error = false; 78 audioIsLoaded = true; 79 } 80 81 sfxChannel = 1; 82 83 careAboutErrors = false; 84 } 85 86 void activate(){ 87 if(!audioIsLoaded) return; 88 if(!error) 89 active = true; 90 } 91 92 void deactivate(){ 93 if(!audioIsLoaded) return; 94 active = false; 95 } 96 97 void toggleActivation(){ 98 if(!audioIsLoaded) return; 99 if(error) 100 return; 101 active = !active; 102 } 103 104 ~this(){ 105 if(audioIsLoaded){ 106 Mix_HaltMusic(); 107 Mix_HaltChannel(-1); 108 Mix_CloseAudio(); 109 } 110 } 111 112 void playEffect(Sound snd, bool loop = false){ 113 if(!active || snd is null) 114 return; 115 116 //if(Mix_Playing(sfxChannel)) 117 // return; 118 119 sfxChannel = Mix_PlayChannel(-1, snd.sfx, loop == true ? -1 : 0); 120 121 } 122 void stopEffect(){ 123 if(!active) 124 return; 125 126 Mix_HaltChannel(sfxChannel); 127 } 128 129 void playMusic(Music mus, bool loop = true){ 130 if(!active || mus is null) 131 return; 132 133 if(Mix_PlayMusic(mus.mus, loop == true ? -1 : 0) == -1) 134 throw new Exception("play music"); 135 // musicIsPlaying = false; 136 else 137 musicIsPlaying = true; 138 } 139 140 void pauseMusic(){ 141 if(!active) 142 return; 143 144 if(musicIsPlaying){ 145 Mix_PauseMusic(); 146 musicIsPaused = true; 147 } 148 } 149 150 void unpauseMusic(){ 151 if(!active) 152 return; 153 154 if(musicIsPaused){ 155 Mix_ResumeMusic(); 156 musicIsPaused = false; 157 } 158 } 159 160 void stopMusic(){ 161 if(!active) 162 return; 163 164 Mix_HaltMusic(); 165 } 166 167 168 void stopAll(){ 169 if(!active) 170 return; 171 172 Mix_HaltMusic(); 173 Mix_HaltChannel(-1); 174 } 175 176 private: 177 int sfxChannel; 178 bool active; 179 bool error; 180 181 bool musicIsPaused; 182 bool musicIsPlaying; 183 184 bool careAboutErrors; 185 } 186 187 int Mix_PlayChannel(int channel, Mix_Chunk* chunk, int loops) { 188 return Mix_PlayChannelTimed(channel,chunk,loops,-1); 189 } 190 Mix_Chunk * Mix_LoadWAV(in char *file) { 191 return Mix_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1); 192 }