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