comparison libao2/ao_macosx.c @ 19427:ada359817b61

fix buffering issues with short audio samples on macosx. patch by Chris Roccati <roccati@pobox.com>
author nplourde
date Fri, 18 Aug 2006 01:19:19 +0000
parents 99e20a22d5d0
children 2d786b7625d7
comparison
equal deleted inserted replaced
19426:99f95ed2d1e5 19427:ada359817b61
73 typedef struct ao_macosx_s 73 typedef struct ao_macosx_s
74 { 74 {
75 /* AudioUnit */ 75 /* AudioUnit */
76 AudioUnit theOutputUnit; 76 AudioUnit theOutputUnit;
77 int packetSize; 77 int packetSize;
78 int paused;
78 79
79 /* Ring-buffer */ 80 /* Ring-buffer */
80 /* does not need explicit synchronization, but needs to allocate 81 /* does not need explicit synchronization, but needs to allocate
81 * (num_chunks + 1) * chunk_size memory to store num_chunks * chunk_size 82 * (num_chunks + 1) * chunk_size memory to store num_chunks * chunk_size
82 * data */ 83 * data */
309 ao_msg(MSGT_AO,MSGL_WARN, "AudioUnitGetProperty returned %d when getting kAudioDevicePropertyBufferSize\n", (int)err); 310 ao_msg(MSGT_AO,MSGL_WARN, "AudioUnitGetProperty returned %d when getting kAudioDevicePropertyBufferSize\n", (int)err);
310 return CONTROL_FALSE; 311 return CONTROL_FALSE;
311 } 312 }
312 313
313 ao->chunk_size = maxFrames;//*inDesc.mBytesPerFrame; 314 ao->chunk_size = maxFrames;//*inDesc.mBytesPerFrame;
314 ao_msg(MSGT_AO,MSGL_V, "%5d chunk size\n", (int)ao->chunk_size);
315 315
316 ao->num_chunks = NUM_BUFS; 316 ao_data.samplerate = inDesc.mSampleRate;
317 ao_data.channels = inDesc.mChannelsPerFrame;
318 ao_data.bps = ao_data.samplerate * inDesc.mBytesPerFrame;
319 ao_data.outburst = ao->chunk_size;
320 ao_data.buffersize = ao_data.bps;
321
322 ao->num_chunks = (ao_data.bps+ao->chunk_size-1)/ao->chunk_size;
317 ao->buffer_len = (ao->num_chunks + 1) * ao->chunk_size; 323 ao->buffer_len = (ao->num_chunks + 1) * ao->chunk_size;
318 ao->buffer = aoIsCreated ? realloc(ao->buffer,(ao->num_chunks + 1)*ao->chunk_size) 324 ao->buffer = aoIsCreated ? realloc(ao->buffer,(ao->num_chunks + 1)*ao->chunk_size)
319 : calloc(ao->num_chunks + 1, ao->chunk_size); 325 : calloc(ao->num_chunks + 1, ao->chunk_size);
320 326
321 ao_data.samplerate = inDesc.mSampleRate; 327 ao_msg(MSGT_AO,MSGL_V, "using %5d chunks of %d bytes (buffer len %d bytes)\n", (int)ao->num_chunks, (int)ao->chunk_size, (int)ao->buffer_len);
322 ao_data.channels = inDesc.mChannelsPerFrame;
323 ao_data.outburst = ao_data.buffersize = ao->chunk_size;
324 ao_data.bps = ao_data.samplerate * inDesc.mBytesPerFrame;
325 328
326 renderCallback.inputProc = theRenderProc; 329 renderCallback.inputProc = theRenderProc;
327 renderCallback.inputProcRefCon = 0; 330 renderCallback.inputProcRefCon = 0;
328 err = AudioUnitSetProperty(ao->theOutputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof(AURenderCallbackStruct)); 331 err = AudioUnitSetProperty(ao->theOutputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof(AURenderCallbackStruct));
329 if (err) { 332 if (err) {
330 ao_msg(MSGT_AO, MSGL_WARN, "Unable to set the render callback (err=%d)\n", err); 333 ao_msg(MSGT_AO, MSGL_WARN, "Unable to set the render callback (err=%d)\n", err);
331 return CONTROL_FALSE; 334 return CONTROL_FALSE;
332 } 335 }
333 336
334 audio_pause(); 337 reset();
335 ao->buf_read_pos=0;
336 ao->buf_write_pos=0;
337 338
338 return CONTROL_OK; 339 return CONTROL_OK;
339 } 340 }
340 341
341 342
342 static int play(void* output_samples,int num_bytes,int flags) 343 static int play(void* output_samples,int num_bytes,int flags)
343 { 344 {
345 int wrote=write_buffer(output_samples, num_bytes);
346
344 audio_resume(); 347 audio_resume();
345 return write_buffer(output_samples, num_bytes); 348 return wrote;
346 } 349 }
347 350
348 /* set variables and buffer to initial state */ 351 /* set variables and buffer to initial state */
349 static void reset(void) 352 static void reset(void)
350 { 353 {
351 audio_pause(); 354 audio_pause();
352 /* reset ring-buffer state */ 355 /* reset ring-buffer state */
353 ao->buf_read_pos=0; 356 ao->buf_read_pos=0;
354 ao->buf_write_pos=0; 357 ao->buf_write_pos=0;
355 audio_resume();
356 358
357 return; 359 return;
358 } 360 }
359 361
360 362
378 static void uninit(int immed) 380 static void uninit(int immed)
379 { 381 {
380 int i; 382 int i;
381 OSErr status; 383 OSErr status;
382 384
383 reset(); 385 if (!immed) {
386 long long timeleft=(1000000LL*buf_used())/ao_data.bps;
387 ao_msg(MSGT_AO,MSGL_DBG2, "%d bytes left @%d bps (%ld usec)\n", buf_used(), ao_data.bps, (int)timeleft);
388 usec_sleep((int)timeleft);
389 }
384 390
385 AudioOutputUnitStop(ao->theOutputUnit); 391 AudioOutputUnitStop(ao->theOutputUnit);
386 AudioUnitUninitialize(ao->theOutputUnit); 392 AudioUnitUninitialize(ao->theOutputUnit);
387 CloseComponent(ao->theOutputUnit); 393 CloseComponent(ao->theOutputUnit);
388 394
400 /* stop callback */ 406 /* stop callback */
401 status=AudioOutputUnitStop(ao->theOutputUnit); 407 status=AudioOutputUnitStop(ao->theOutputUnit);
402 if (status) 408 if (status)
403 ao_msg(MSGT_AO,MSGL_WARN, "AudioOutputUnitStop returned %d\n", 409 ao_msg(MSGT_AO,MSGL_WARN, "AudioOutputUnitStop returned %d\n",
404 (int)status); 410 (int)status);
411 ao->paused=1;
405 } 412 }
406 413
407 414
408 /* resume playing, after audio_pause() */ 415 /* resume playing, after audio_pause() */
409 static void audio_resume(void) 416 static void audio_resume(void)
410 { 417 {
418 if(ao->paused) {
411 OSErr status=noErr; 419 OSErr status=noErr;
412 420 /* start callback */
413 status=AudioOutputUnitStart(ao->theOutputUnit); 421 status=AudioOutputUnitStart(ao->theOutputUnit);
414 if (status) 422 if (status)
415 ao_msg(MSGT_AO,MSGL_WARN, "AudioOutputUnitStart returned %d\n", 423 ao_msg(MSGT_AO,MSGL_WARN, "AudioOutputUnitStart returned %d\n",
416 (int)status); 424 (int)status);
417 } 425 ao->paused=0;
426 }
427 }