Commit e625b68b04a400ba377ec0a5b958bde0bc6244ff

Authored by Simon Glass
1 parent e96fa6c911

dm: sandbox: Update sound to use two buffers

At present we use a single buffer for sound which means we cannot be
playing one sound while queueing up the next. This wouldn't matter except
that a long sound (more than a second) has to be created as a single
buffer, thus using a lot of memory. To better mimic what real sound
drivers do, add support for double buffering in sandbox.

Signed-off-by: Simon Glass <sjg@chromium.org>

Showing 1 changed file with 63 additions and 25 deletions Side-by-side Diff

arch/sandbox/cpu/sdl.c
... ... @@ -13,6 +13,21 @@
13 13 SAMPLE_RATE = 22050,
14 14 };
15 15  
  16 +/**
  17 + * struct buf_info - a data buffer holding audio data
  18 + *
  19 + * @pos: Current position playing in audio buffer
  20 + * @size: Size of data in audio buffer (0=empty)
  21 + * @alloced: Allocated size of audio buffer (max size it can hold)
  22 + * @data: Audio data
  23 + */
  24 +struct buf_info {
  25 + uint pos;
  26 + uint size;
  27 + uint alloced;
  28 + uint8_t *data;
  29 +};
  30 +
16 31 static struct sdl_info {
17 32 SDL_Surface *screen;
18 33 int width;
19 34  
20 35  
... ... @@ -20,12 +35,11 @@
20 35 int depth;
21 36 int pitch;
22 37 uint frequency;
23   - uint audio_pos;
24   - uint audio_size;
25 38 uint sample_rate;
26   - uint8_t *audio_data;
27 39 bool audio_active;
28 40 bool inited;
  41 + int cur_buf;
  42 + struct buf_info buf[2];
29 43 } sdl;
30 44  
31 45 static void sandbox_sdl_poll_events(void)
32 46  
33 47  
34 48  
35 49  
36 50  
... ... @@ -243,24 +257,37 @@
243 257  
244 258 void sandbox_sdl_fill_audio(void *udata, Uint8 *stream, int len)
245 259 {
  260 + struct buf_info *buf;
246 261 int avail;
  262 + int i;
247 263  
248   - avail = sdl.audio_size - sdl.audio_pos;
249   - if (avail < len)
250   - len = avail;
  264 + for (i = 0; i < 2; i++) {
  265 + buf = &sdl.buf[sdl.cur_buf];
  266 + avail = buf->size - buf->pos;
  267 + if (avail <= 0) {
  268 + sdl.cur_buf = 1 - sdl.cur_buf;
  269 + continue;
  270 + }
  271 + if (avail > len)
  272 + avail = len;
251 273  
252   - SDL_MixAudio(stream, sdl.audio_data + sdl.audio_pos, len,
253   - SDL_MIX_MAXVOLUME);
254   - sdl.audio_pos += len;
  274 + SDL_MixAudio(stream, buf->data + buf->pos, avail,
  275 + SDL_MIX_MAXVOLUME);
  276 + buf->pos += avail;
  277 + len -= avail;
255 278  
256   - /* Loop if we are at the end */
257   - if (sdl.audio_pos == sdl.audio_size)
258   - sdl.audio_pos = 0;
  279 + /* Move to next buffer if we are at the end */
  280 + if (buf->pos == buf->size)
  281 + buf->size = 0;
  282 + else
  283 + break;
  284 + }
259 285 }
260 286  
261 287 int sandbox_sdl_sound_init(void)
262 288 {
263 289 SDL_AudioSpec wanted;
  290 + int i;
264 291  
265 292 if (sandbox_sdl_ensure_init())
266 293 return -1;
267 294  
... ... @@ -276,13 +303,20 @@
276 303 wanted.callback = sandbox_sdl_fill_audio;
277 304 wanted.userdata = NULL;
278 305  
279   - sdl.audio_size = sizeof(uint16_t) * wanted.freq;
280   - sdl.audio_data = malloc(sdl.audio_size);
281   - if (!sdl.audio_data) {
282   - printf("%s: Out of memory\n", __func__);
283   - return -1;
  306 + for (i = 0; i < 2; i++) {
  307 + struct buf_info *buf = &sdl.buf[i];
  308 +
  309 + buf->alloced = sizeof(uint16_t) * wanted.freq * wanted.channels;
  310 + buf->data = malloc(buf->alloced);
  311 + if (!buf->data) {
  312 + printf("%s: Out of memory\n", __func__);
  313 + if (i == 1)
  314 + free(sdl.buf[0].data);
  315 + return -1;
  316 + }
  317 + buf->pos = 0;
  318 + buf->size = 0;
284 319 }
285   - sdl.audio_pos = 0;
286 320  
287 321 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
288 322 printf("Unable to initialize SDL audio: %s\n", SDL_GetError());
289 323  
290 324  
291 325  
... ... @@ -296,23 +330,27 @@
296 330 }
297 331 sdl.audio_active = true;
298 332 sdl.sample_rate = wanted.freq;
  333 + sdl.cur_buf = 0;
299 334  
300 335 return 0;
301 336  
302 337 err:
303   - free(sdl.audio_data);
  338 + for (i = 0; i < 2; i++)
  339 + free(sdl.buf[i].data);
304 340 return -1;
305 341 }
306 342  
307 343 int sandbox_sdl_sound_start(uint frequency)
308 344 {
  345 + struct buf_info *buf = &sdl.buf[0];
  346 +
309 347 if (!sdl.audio_active)
310 348 return -1;
311 349 sdl.frequency = frequency;
312   - sound_create_square_wave(sdl.sample_rate,
313   - (unsigned short *)sdl.audio_data,
314   - sdl.audio_size, frequency);
315   - sdl.audio_pos = 0;
  350 + sound_create_square_wave(sdl.sample_rate, (unsigned short *)buf->data,
  351 + buf->alloced, frequency);
  352 + buf->pos = 0;
  353 + buf->size = buf->alloced;
316 354 SDL_PauseAudio(0);
317 355  
318 356 return 0;