Mercurial > vba-linux
diff src/sdl/SoundSDL.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/sdl/SoundSDL.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,178 @@ 1.4 +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. 1.5 +// Copyright (C) 2008 VBA-M development team 1.6 + 1.7 +// This program is free software; you can redistribute it and/or modify 1.8 +// it under the terms of the GNU General Public License as published by 1.9 +// the Free Software Foundation; either version 2, or(at your option) 1.10 +// any later version. 1.11 +// 1.12 +// This program is distributed in the hope that it will be useful, 1.13 +// but WITHOUT ANY WARRANTY; without even the implied warranty of 1.14 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.15 +// GNU General Public License for more details. 1.16 +// 1.17 +// You should have received a copy of the GNU General Public License 1.18 +// along with this program; if not, write to the Free Software Foundation, 1.19 +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 1.20 + 1.21 +#include "SoundSDL.h" 1.22 + 1.23 +extern int emulating; 1.24 +extern bool speedup; 1.25 + 1.26 +// Hold up to 100 ms of data in the ring buffer 1.27 +const float SoundSDL::_delay = 0.1f; 1.28 + 1.29 +SoundSDL::SoundSDL(): 1.30 + _rbuf(0), 1.31 + _initialized(false) 1.32 +{ 1.33 + 1.34 +} 1.35 + 1.36 +void SoundSDL::soundCallback(void *data, u8 *stream, int len) 1.37 +{ 1.38 + reinterpret_cast<SoundSDL*>(data)->read(reinterpret_cast<u16 *>(stream), len); 1.39 +} 1.40 + 1.41 +void SoundSDL::read(u16 * stream, int length) 1.42 +{ 1.43 + if (!_initialized || length <= 0 || !emulating) 1.44 + return; 1.45 + 1.46 + SDL_mutexP(_mutex); 1.47 + _rbuf.read(stream, std::min(static_cast<std::size_t>(length) / 2, _rbuf.used())); 1.48 + 1.49 + SDL_CondSignal(_cond); 1.50 + SDL_mutexV(_mutex); 1.51 +} 1.52 + 1.53 +void SoundSDL::write(u16 * finalWave, int length) 1.54 +{ 1.55 + if (!_initialized) 1.56 + return; 1.57 + 1.58 + if (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING) 1.59 + SDL_PauseAudio(0); 1.60 + 1.61 + SDL_mutexP(_mutex); 1.62 + 1.63 + unsigned int samples = length / 4; 1.64 + 1.65 + std::size_t avail; 1.66 + while ((avail = _rbuf.avail() / 2) < samples) 1.67 + { 1.68 + _rbuf.write(finalWave, avail * 2); 1.69 + 1.70 + finalWave += avail * 2; 1.71 + samples -= avail; 1.72 + 1.73 + // If emulating and not in speed up mode, synchronize to audio 1.74 + // by waiting till there is enough room in the buffer 1.75 + if (emulating && !speedup) 1.76 + { 1.77 + SDL_CondWait(_cond,_mutex); 1.78 + } 1.79 + else 1.80 + { 1.81 + // Drop the remaining of the audio data 1.82 + SDL_mutexV(_mutex); 1.83 + return; 1.84 + } 1.85 + } 1.86 + 1.87 + _rbuf.write(finalWave, samples * 2); 1.88 + 1.89 + SDL_mutexV(_mutex); 1.90 +} 1.91 + 1.92 + 1.93 +bool SoundSDL::init() 1.94 +{ 1.95 + SDL_AudioSpec audio; 1.96 + audio.freq = SDL_SAMPLE_RATE; 1.97 + audio.format = AUDIO_S16SYS; 1.98 + audio.channels = 2; 1.99 + audio.samples = 1024; 1.100 + audio.callback = soundCallback; 1.101 + audio.userdata = this; 1.102 + 1.103 + if(SDL_OpenAudio(&audio, NULL)) 1.104 + { 1.105 + fprintf(stderr,"Failed to open audio: %s\n", SDL_GetError()); 1.106 + return false; 1.107 + } 1.108 + 1.109 + _rbuf.reset(_delay * SDL_SAMPLE_RATE * 2); 1.110 + 1.111 + _cond = SDL_CreateCond(); 1.112 + _mutex = SDL_CreateMutex(); 1.113 + _initialized = true; 1.114 + 1.115 + return true; 1.116 +} 1.117 + 1.118 +SoundSDL::~SoundSDL() 1.119 +{ 1.120 + if (!_initialized) 1.121 + return; 1.122 + 1.123 + SDL_mutexP(_mutex); 1.124 + int iSave = emulating; 1.125 + emulating = 0; 1.126 + SDL_CondSignal(_cond); 1.127 + SDL_mutexV(_mutex); 1.128 + 1.129 + SDL_DestroyCond(_cond); 1.130 + _cond = NULL; 1.131 + 1.132 + SDL_DestroyMutex(_mutex); 1.133 + _mutex = NULL; 1.134 + 1.135 + SDL_CloseAudio(); 1.136 + 1.137 + emulating = iSave; 1.138 +} 1.139 + 1.140 +void SoundSDL::pause() 1.141 +{ 1.142 + if (!_initialized) 1.143 + return; 1.144 + 1.145 + SDL_PauseAudio(1); 1.146 +} 1.147 + 1.148 +void SoundSDL::resume() 1.149 +{ 1.150 + if (!_initialized) 1.151 + return; 1.152 + 1.153 + SDL_PauseAudio(0); 1.154 +} 1.155 + 1.156 +void SoundSDL::reset() 1.157 +{ 1.158 +} 1.159 + 1.160 +bool SoundSDL::setThrottle(unsigned short throttle){ 1.161 + switch(throttle){ 1.162 + case 25: 1.163 + case 50: 1.164 + case 100: 1.165 + case 200: 1.166 + case 400: 1.167 + break; 1.168 + default: 1.169 + return false; 1.170 + } 1.171 + SDL_CloseAudio(); 1.172 + SDL_AudioSpec audio; 1.173 + audio.freq = SDL_SAMPLE_RATE*throttle/100; 1.174 + audio.format = AUDIO_S16SYS; 1.175 + audio.channels = 2; 1.176 + audio.samples = 1024; 1.177 + audio.callback = soundCallback; 1.178 + audio.userdata = this; 1.179 + _rbuf.reset((_delay * SDL_SAMPLE_RATE * throttle * 2)/100); 1.180 + return !SDL_OpenAudio(&audio,NULL); 1.181 +}