Mercurial > vba-clojure
comparison 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 | fa7676dbf6f2 |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. | |
2 // Copyright (C) 2008 VBA-M development team | |
3 | |
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. | |
17 | |
18 #include "SoundSDL.h" | |
19 | |
20 extern int emulating; | |
21 extern bool speedup; | |
22 | |
23 // Hold up to 100 ms of data in the ring buffer | |
24 const float SoundSDL::_delay = 0.1f; | |
25 | |
26 SoundSDL::SoundSDL(): | |
27 _rbuf(0), | |
28 _initialized(false) | |
29 { | |
30 | |
31 } | |
32 | |
33 void SoundSDL::soundCallback(void *data, u8 *stream, int len) | |
34 { | |
35 reinterpret_cast<SoundSDL*>(data)->read(reinterpret_cast<u16 *>(stream), len); | |
36 } | |
37 | |
38 void SoundSDL::read(u16 * stream, int length) | |
39 { | |
40 if (!_initialized || length <= 0 || !emulating) | |
41 return; | |
42 | |
43 SDL_mutexP(_mutex); | |
44 _rbuf.read(stream, std::min(static_cast<std::size_t>(length) / 2, _rbuf.used())); | |
45 | |
46 SDL_CondSignal(_cond); | |
47 SDL_mutexV(_mutex); | |
48 } | |
49 | |
50 void SoundSDL::write(u16 * finalWave, int length) | |
51 { | |
52 if (!_initialized) | |
53 return; | |
54 | |
55 if (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING) | |
56 SDL_PauseAudio(0); | |
57 | |
58 SDL_mutexP(_mutex); | |
59 | |
60 unsigned int samples = length / 4; | |
61 | |
62 std::size_t avail; | |
63 while ((avail = _rbuf.avail() / 2) < samples) | |
64 { | |
65 _rbuf.write(finalWave, avail * 2); | |
66 | |
67 finalWave += avail * 2; | |
68 samples -= avail; | |
69 | |
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 } | |
83 | |
84 _rbuf.write(finalWave, samples * 2); | |
85 | |
86 SDL_mutexV(_mutex); | |
87 } | |
88 | |
89 | |
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; | |
99 | |
100 if(SDL_OpenAudio(&audio, NULL)) | |
101 { | |
102 fprintf(stderr,"Failed to open audio: %s\n", SDL_GetError()); | |
103 return false; | |
104 } | |
105 | |
106 _rbuf.reset(_delay * SDL_SAMPLE_RATE * 2); | |
107 | |
108 _cond = SDL_CreateCond(); | |
109 _mutex = SDL_CreateMutex(); | |
110 _initialized = true; | |
111 | |
112 return true; | |
113 } | |
114 | |
115 SoundSDL::~SoundSDL() | |
116 { | |
117 if (!_initialized) | |
118 return; | |
119 | |
120 SDL_mutexP(_mutex); | |
121 int iSave = emulating; | |
122 emulating = 0; | |
123 SDL_CondSignal(_cond); | |
124 SDL_mutexV(_mutex); | |
125 | |
126 SDL_DestroyCond(_cond); | |
127 _cond = NULL; | |
128 | |
129 SDL_DestroyMutex(_mutex); | |
130 _mutex = NULL; | |
131 | |
132 SDL_CloseAudio(); | |
133 | |
134 emulating = iSave; | |
135 } | |
136 | |
137 void SoundSDL::pause() | |
138 { | |
139 if (!_initialized) | |
140 return; | |
141 | |
142 SDL_PauseAudio(1); | |
143 } | |
144 | |
145 void SoundSDL::resume() | |
146 { | |
147 if (!_initialized) | |
148 return; | |
149 | |
150 SDL_PauseAudio(0); | |
151 } | |
152 | |
153 void SoundSDL::reset() | |
154 { | |
155 } | |
156 | |
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 } |