Mercurial > vba-clojure
view src/sdl/SoundSDL.cpp @ 118:be4ec0e60c16
mode 0 of bootstrapping state machine complete
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 16 Mar 2012 20:03:10 -0500 |
parents | f9f4f1b99eed |
children | fa7676dbf6f2 |
line wrap: on
line source
1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.2 // Copyright (C) 2008 VBA-M development team4 // This program is free software; you can redistribute it and/or modify5 // it under the terms of the GNU General Public License as published by6 // the Free Software Foundation; either version 2, or(at your option)7 // any later version.8 //9 // This program is distributed in the hope that it will be useful,10 // but WITHOUT ANY WARRANTY; without even the implied warranty of11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12 // GNU General Public License for more details.13 //14 // You should have received a copy of the GNU General Public License15 // along with this program; if not, write to the Free Software Foundation,16 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.18 #include "SoundSDL.h"20 extern int emulating;21 extern bool speedup;23 // Hold up to 100 ms of data in the ring buffer24 const float SoundSDL::_delay = 0.1f;26 SoundSDL::SoundSDL():27 _rbuf(0),28 _initialized(false)29 {31 }33 void SoundSDL::soundCallback(void *data, u8 *stream, int len)34 {35 reinterpret_cast<SoundSDL*>(data)->read(reinterpret_cast<u16 *>(stream), len);36 }38 void SoundSDL::read(u16 * stream, int length)39 {40 if (!_initialized || length <= 0 || !emulating)41 return;43 SDL_mutexP(_mutex);44 _rbuf.read(stream, std::min(static_cast<std::size_t>(length) / 2, _rbuf.used()));46 SDL_CondSignal(_cond);47 SDL_mutexV(_mutex);48 }50 void SoundSDL::write(u16 * finalWave, int length)51 {52 if (!_initialized)53 return;55 if (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING)56 SDL_PauseAudio(0);58 SDL_mutexP(_mutex);60 unsigned int samples = length / 4;62 std::size_t avail;63 while ((avail = _rbuf.avail() / 2) < samples)64 {65 _rbuf.write(finalWave, avail * 2);67 finalWave += avail * 2;68 samples -= avail;70 // If emulating and not in speed up mode, synchronize to audio71 // by waiting till there is enough room in the buffer72 if (emulating && !speedup)73 {74 SDL_CondWait(_cond,_mutex);75 }76 else77 {78 // Drop the remaining of the audio data79 SDL_mutexV(_mutex);80 return;81 }82 }84 _rbuf.write(finalWave, samples * 2);86 SDL_mutexV(_mutex);87 }90 bool SoundSDL::init()91 {92 SDL_AudioSpec audio;93 audio.freq = SDL_SAMPLE_RATE;94 audio.format = AUDIO_S16SYS;95 audio.channels = 2;96 audio.samples = 1024;97 audio.callback = soundCallback;98 audio.userdata = this;100 if(SDL_OpenAudio(&audio, NULL))101 {102 fprintf(stderr,"Failed to open audio: %s\n", SDL_GetError());103 return false;104 }106 _rbuf.reset(_delay * SDL_SAMPLE_RATE * 2);108 _cond = SDL_CreateCond();109 _mutex = SDL_CreateMutex();110 _initialized = true;112 return true;113 }115 SoundSDL::~SoundSDL()116 {117 if (!_initialized)118 return;120 SDL_mutexP(_mutex);121 int iSave = emulating;122 emulating = 0;123 SDL_CondSignal(_cond);124 SDL_mutexV(_mutex);126 SDL_DestroyCond(_cond);127 _cond = NULL;129 SDL_DestroyMutex(_mutex);130 _mutex = NULL;132 SDL_CloseAudio();134 emulating = iSave;135 }137 void SoundSDL::pause()138 {139 if (!_initialized)140 return;142 SDL_PauseAudio(1);143 }145 void SoundSDL::resume()146 {147 if (!_initialized)148 return;150 SDL_PauseAudio(0);151 }153 void SoundSDL::reset()154 {155 }157 bool SoundSDL::setThrottle(unsigned short throttle){158 switch(throttle){159 case 25:160 case 50:161 case 100:162 case 200:163 case 400:164 break;165 default:166 return false;167 }168 SDL_CloseAudio();169 SDL_AudioSpec audio;170 audio.freq = SDL_SAMPLE_RATE*throttle/100;171 audio.format = AUDIO_S16SYS;172 audio.channels = 2;173 audio.samples = 1024;174 audio.callback = soundCallback;175 audio.userdata = this;176 _rbuf.reset((_delay * SDL_SAMPLE_RATE * throttle * 2)/100);177 return !SDL_OpenAudio(&audio,NULL);178 }