view src/sdl/SoundSDL.cpp @ 535:2de44c6184ee

refactored functionality of play-midi into midi-bytes for reuse.
author Robert McIntyre <rlm@mit.edu>
date Mon, 25 Jun 2012 14:15:38 -0500
parents fa7676dbf6f2
children
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"
19 #include <stdio.h>
22 extern int emulating;
23 extern bool speedup;
25 // Hold up to 100 ms of data in the ring buffer
26 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 audio
79 // by waiting till there is enough room in the buffer
80 if (emulating && !speedup)
81 {
82 //printf("SDL_CondWait\n");
83 SDL_CondWait(_cond,_mutex);
84 }
85 else
86 {
87 // Drop the remainder of the audio data
88 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 }