view src/sdl/SoundSDL.cpp @ 135:eb6ba88088d3

Wrote a more efficient input-number-assembly program; 91 oc -> 60 oc.
author Dylan Holmes <ocsenave@gmail.com>
date Sun, 18 Mar 2012 05:13:19 -0500
parents f9f4f1b99eed
children fa7676dbf6f2
line wrap: on
line source
1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 2008 VBA-M development team
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // 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 of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // 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 buffer
24 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 audio
71 // by waiting till there is enough room in the buffer
72 if (emulating && !speedup)
73 {
74 SDL_CondWait(_cond,_mutex);
75 }
76 else
77 {
78 // Drop the remaining of the audio data
79 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 }