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