Mercurial > vba-clojure
view src/sdl/SoundSDL.cpp @ 546:36e5fa62eb3c
i believe this latest change will correct all A/V synching problems.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Wed, 27 Jun 2012 14:08:59 -0500 |
parents | fa7676dbf6f2 |
children |
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"19 #include <stdio.h>22 extern int emulating;23 extern bool speedup;25 // Hold up to 100 ms of data in the ring buffer26 const float SoundSDL::_delay = 0.1f;28 SoundSDL::SoundSDL():29 _rbuf(0),30 _initialized(false)31 {33 }35 void SoundSDL::soundCallback(void *data, u8 *stream, int len)36 {37 reinterpret_cast<SoundSDL*>(data)->read(reinterpret_cast<u16 *>(stream), len);38 }40 void SoundSDL::read(u16 * stream, int length)41 {42 if (!_initialized || length <= 0 || !emulating)43 return;45 SDL_mutexP(_mutex);46 _rbuf.read(stream, std::min(static_cast<std::size_t>(length) / 2, _rbuf.used()));48 SDL_CondSignal(_cond);49 SDL_mutexV(_mutex);50 }52 void SoundSDL::write(u16 * finalWave, int length)53 {54 if (!_initialized)55 return;57 if (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING){58 SDL_PauseAudio(0);59 printf("SDLPauseAudio\n");60 }62 SDL_mutexP(_mutex);64 //printf("RLM: length = %d\n", length);66 unsigned int samples = length / 4;68 // printf("RLM: length / 4 = %d\n", samples);70 std::size_t avail;71 while ((avail = _rbuf.avail() / 2) < samples)72 {73 _rbuf.write(finalWave, avail * 2);75 finalWave += avail * 2;76 samples -= avail;78 // If emulating and not in speed up mode, synchronize to audio79 // by waiting till there is enough room in the buffer80 if (emulating && !speedup)81 {82 //printf("SDL_CondWait\n");83 SDL_CondWait(_cond,_mutex);84 }85 else86 {87 // Drop the remainder of the audio data88 printf("RLM: Drop samples!\n");89 SDL_mutexV(_mutex);90 return;91 }92 }94 _rbuf.write(finalWave, samples * 2);95 //printf("RLM: writing %d samples\n", samples);96 SDL_mutexV(_mutex);97 }100 bool SoundSDL::init()101 {102 SDL_AudioSpec audio;103 audio.freq = SDL_SAMPLE_RATE;104 audio.format = AUDIO_S16SYS;105 audio.channels = 2;106 audio.samples = 1024;107 audio.callback = soundCallback;108 audio.userdata = this;110 if(SDL_OpenAudio(&audio, NULL))111 {112 fprintf(stderr,"Failed to open audio: %s\n", SDL_GetError());113 return false;114 }116 _rbuf.reset(_delay * SDL_SAMPLE_RATE * 2);118 _cond = SDL_CreateCond();119 _mutex = SDL_CreateMutex();120 _initialized = true;122 return true;123 }125 SoundSDL::~SoundSDL()126 {127 if (!_initialized)128 return;130 SDL_mutexP(_mutex);131 int iSave = emulating;132 emulating = 0;133 SDL_CondSignal(_cond);134 SDL_mutexV(_mutex);136 SDL_DestroyCond(_cond);137 _cond = NULL;139 SDL_DestroyMutex(_mutex);140 _mutex = NULL;142 SDL_CloseAudio();144 emulating = iSave;145 }147 void SoundSDL::pause()148 {149 if (!_initialized)150 return;152 SDL_PauseAudio(1);153 }155 void SoundSDL::resume()156 {157 if (!_initialized)158 return;160 SDL_PauseAudio(0);161 }163 void SoundSDL::reset()164 {165 }167 bool SoundSDL::setThrottle(unsigned short throttle){168 switch(throttle){169 case 25:170 case 50:171 case 100:172 case 200:173 case 400:174 break;175 default:176 return false;177 }178 SDL_CloseAudio();179 SDL_AudioSpec audio;180 audio.freq = SDL_SAMPLE_RATE*throttle/100;181 audio.format = AUDIO_S16SYS;182 audio.channels = 2;183 audio.samples = 1024;184 audio.callback = soundCallback;185 audio.userdata = this;186 _rbuf.reset((_delay * SDL_SAMPLE_RATE * throttle * 2)/100);187 return !SDL_OpenAudio(&audio,NULL);188 }