1 /* 2 * QEMU "simple" Windows audio driver 3 * 4 * Copyright (c) 2007 The Android Open Source Project 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 #define WIN32_LEAN_AND_MEAN 25 #include <windows.h> 26 #include <mmsystem.h> 27 28 #define AUDIO_CAP "winaudio" 29 #include "audio_int.h" 30 31 /* define DEBUG to 1 to dump audio debugging info at runtime to stderr */ 32 #define DEBUG 0 33 34 #if 1 35 # define D_ACTIVE 1 36 #else 37 # define D_ACTIVE DEBUG 38 #endif 39 40 #if DEBUG 41 # define D(...) do{ if (D_ACTIVE) printf(__VA_ARGS__); } while(0) 42 #else 43 # define D(...) ((void)0) 44 #endif 45 46 static struct { 47 int nb_samples; 48 } conf = { 49 1024 50 }; 51 52 #if DEBUG 53 int64_t start_time; 54 int64_t last_time; 55 #endif 56 57 #define NUM_OUT_BUFFERS 8 /* must be at least 2 */ 58 59 /** COMMON UTILITIES 60 **/ 61 62 #if DEBUG 63 static void 64 dump_mmerror( const char* func, MMRESULT error ) 65 { 66 const char* reason = NULL; 67 68 fprintf(stderr, "%s returned error: ", func); 69 switch (error) { 70 case MMSYSERR_ALLOCATED: reason="specified resource is already allocated"; break; 71 case MMSYSERR_BADDEVICEID: reason="bad device id"; break; 72 case MMSYSERR_NODRIVER: reason="no driver is present"; break; 73 case MMSYSERR_NOMEM: reason="unable to allocate or lock memory"; break; 74 case WAVERR_BADFORMAT: reason="unsupported waveform-audio format"; break; 75 case WAVERR_SYNC: reason="device is synchronous"; break; 76 default: 77 fprintf(stderr, "unknown(%d)\n", error); 78 } 79 if (reason) 80 fprintf(stderr, "%s\n", reason); 81 } 82 #else 83 # define dump_mmerror(func,error) ((void)0) 84 #endif 85 86 87 /** AUDIO OUT 88 **/ 89 90 typedef struct WinAudioOut { 91 HWVoiceOut hw; 92 HWAVEOUT waveout; 93 int silence; 94 CRITICAL_SECTION lock; 95 unsigned char* buffer_bytes; 96 WAVEHDR buffers[ NUM_OUT_BUFFERS ]; 97 int write_index; /* starting first writable buffer */ 98 int write_count; /* available writable buffers count */ 99 int write_pos; /* position in current writable buffer */ 100 int write_size; /* size in bytes of each buffer */ 101 } WinAudioOut; 102 103 /* The Win32 callback that is called when a buffer has finished playing */ 104 static void CALLBACK 105 winaudio_out_buffer_done (HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, 106 DWORD dwParam1, DWORD dwParam2) 107 { 108 WinAudioOut* s = (WinAudioOut*) dwInstance; 109 110 /* Only service "buffer done playing" messages */ 111 if ( uMsg != WOM_DONE ) 112 return; 113 114 /* Signal that we are done playing a buffer */ 115 EnterCriticalSection( &s->lock ); 116 if (s->write_count < NUM_OUT_BUFFERS) 117 s->write_count += 1; 118 LeaveCriticalSection( &s->lock ); 119 } 120 121 static int 122 winaudio_out_write (SWVoiceOut *sw, void *buf, int len) 123 { 124 return audio_pcm_sw_write (sw, buf, len); 125 } 126 127 static void 128 winaudio_out_fini (HWVoiceOut *hw) 129 { 130 WinAudioOut* s = (WinAudioOut*) hw; 131 int i; 132 133 if (s->waveout) { 134 waveOutReset(s->waveout); 135 s->waveout = 0; 136 } 137 138 for ( i=0; i<NUM_OUT_BUFFERS; ++i ) { 139 if ( s->buffers[i].dwUser != 0xFFFF ) { 140 waveOutUnprepareHeader( 141 s->waveout, &s->buffers[i], sizeof(s->buffers[i]) ); 142 s->buffers[i].dwUser = 0xFFFF; 143 } 144 } 145 146 if (s->buffer_bytes != NULL) { 147 qemu_free(s->buffer_bytes); 148 s->buffer_bytes = NULL; 149 } 150 151 if (s->waveout) { 152 waveOutClose(s->waveout); 153 s->waveout = NULL; 154 } 155 } 156 157 158 static int 159 winaudio_out_init (HWVoiceOut *hw, struct audsettings *as) 160 { 161 WinAudioOut* s = (WinAudioOut*) hw; 162 MMRESULT result; 163 WAVEFORMATEX format; 164 int shift, i, samples_size; 165 166 s->waveout = NULL; 167 InitializeCriticalSection( &s->lock ); 168 for (i = 0; i < NUM_OUT_BUFFERS; i++) { 169 s->buffers[i].dwUser = 0xFFFF; 170 } 171 s->buffer_bytes = NULL; 172 173 /* compute desired wave output format */ 174 format.wFormatTag = WAVE_FORMAT_PCM; 175 format.nChannels = as->nchannels; 176 format.nSamplesPerSec = as->freq; 177 format.nAvgBytesPerSec = as->freq*as->nchannels; 178 179 s->silence = 0; 180 181 switch (as->fmt) { 182 case AUD_FMT_S8: shift = 0; break; 183 case AUD_FMT_U8: shift = 0; s->silence = 0x80; break; 184 case AUD_FMT_S16: shift = 1; break; 185 case AUD_FMT_U16: shift = 1; s->silence = 0x8000; break; 186 default: 187 fprintf(stderr, "qemu: winaudio: Bad output audio format: %d\n", 188 as->fmt); 189 return -1; 190 } 191 192 format.nAvgBytesPerSec = (format.nSamplesPerSec & format.nChannels) << shift; 193 format.nBlockAlign = format.nChannels << shift; 194 format.wBitsPerSample = 8 << shift; 195 format.cbSize = 0; 196 197 /* open the wave out device */ 198 result = waveOutOpen( &s->waveout, WAVE_MAPPER, &format, 199 (DWORD_PTR)winaudio_out_buffer_done, (DWORD_PTR) hw, 200 CALLBACK_FUNCTION); 201 if ( result != MMSYSERR_NOERROR ) { 202 dump_mmerror( "qemu: winaudio: waveOutOpen()", result); 203 return -1; 204 } 205 206 samples_size = format.nBlockAlign * conf.nb_samples; 207 s->buffer_bytes = qemu_malloc( NUM_OUT_BUFFERS * samples_size ); 208 if (s->buffer_bytes == NULL) { 209 waveOutClose( s->waveout ); 210 s->waveout = NULL; 211 fprintf(stderr, "not enough memory for Windows audio buffers\n"); 212 return -1; 213 } 214 215 for (i = 0; i < NUM_OUT_BUFFERS; i++) { 216 memset( &s->buffers[i], 0, sizeof(s->buffers[i]) ); 217 s->buffers[i].lpData = (LPSTR)(s->buffer_bytes + i*samples_size); 218 s->buffers[i].dwBufferLength = samples_size; 219 s->buffers[i].dwFlags = WHDR_DONE; 220 221 result = waveOutPrepareHeader( s->waveout, &s->buffers[i], 222 sizeof(s->buffers[i]) ); 223 if ( result != MMSYSERR_NOERROR ) { 224 dump_mmerror("waveOutPrepareHeader()", result); 225 return -1; 226 } 227 } 228 229 #if DEBUG 230 /* Check the sound device we retrieved */ 231 { 232 WAVEOUTCAPS caps; 233 234 result = waveOutGetDevCaps((UINT) s->waveout, &caps, sizeof(caps)); 235 if ( result != MMSYSERR_NOERROR ) { 236 dump_mmerror("waveOutGetDevCaps()", result); 237 } else 238 printf("Audio out device: %s\n", caps.szPname); 239 } 240 #endif 241 242 audio_pcm_init_info (&hw->info, as); 243 hw->samples = conf.nb_samples*2; 244 245 s->write_index = 0; 246 s->write_count = NUM_OUT_BUFFERS; 247 s->write_pos = 0; 248 s->write_size = samples_size; 249 return 0; 250 } 251 252 253 static int 254 winaudio_out_run (HWVoiceOut *hw) 255 { 256 WinAudioOut* s = (WinAudioOut*) hw; 257 int played = 0; 258 int has_buffer; 259 int live = audio_pcm_hw_get_live_out (hw); 260 261 if (!live) { 262 return 0; 263 } 264 265 EnterCriticalSection( &s->lock ); 266 has_buffer = (s->write_count > 0); 267 LeaveCriticalSection( &s->lock ); 268 269 if (has_buffer) { 270 while (live > 0) { 271 WAVEHDR* wav_buffer = s->buffers + s->write_index; 272 int wav_bytes = (s->write_size - s->write_pos); 273 int wav_samples = audio_MIN(wav_bytes >> hw->info.shift, live); 274 int hw_samples = audio_MIN(hw->samples - hw->rpos, live); 275 struct st_sample* src = hw->mix_buf + hw->rpos; 276 uint8_t* dst = (uint8_t*)wav_buffer->lpData + s->write_pos; 277 278 if (wav_samples > hw_samples) { 279 wav_samples = hw_samples; 280 } 281 282 wav_bytes = wav_samples << hw->info.shift; 283 284 //D("run_out: buffer:%d pos:%d size:%d wsamples:%d wbytes:%d live:%d rpos:%d hwsamples:%d\n", s->write_index, 285 // s->write_pos, s->write_size, wav_samples, wav_bytes, live, hw->rpos, hw->samples); 286 hw->clip (dst, src, wav_samples); 287 hw->rpos += wav_samples; 288 if (hw->rpos >= hw->samples) 289 hw->rpos -= hw->samples; 290 291 live -= wav_samples; 292 played += wav_samples; 293 s->write_pos += wav_bytes; 294 if (s->write_pos == s->write_size) { 295 #if xxDEBUG 296 int64_t now = qemu_get_clock(vm_clock) - start_time; 297 int64_t diff = now - last_time; 298 299 D("run_out: (%7.3f:%7d):waveOutWrite buffer:%d\n", 300 now/1e9, (now-last_time)/1e9, s->write_index); 301 last_time = now; 302 #endif 303 waveOutWrite( s->waveout, wav_buffer, sizeof(*wav_buffer) ); 304 s->write_pos = 0; 305 s->write_index += 1; 306 if (s->write_index == NUM_OUT_BUFFERS) 307 s->write_index = 0; 308 309 EnterCriticalSection( &s->lock ); 310 if (--s->write_count == 0) { 311 live = 0; 312 } 313 LeaveCriticalSection( &s->lock ); 314 } 315 } 316 317 } 318 return played; 319 } 320 321 static int 322 winaudio_out_ctl (HWVoiceOut *hw, int cmd, ...) 323 { 324 WinAudioOut* s = (WinAudioOut*) hw; 325 326 switch (cmd) { 327 case VOICE_ENABLE: 328 waveOutRestart( s->waveout ); 329 break; 330 331 case VOICE_DISABLE: 332 waveOutPause( s->waveout ); 333 break; 334 } 335 return 0; 336 } 337 338 /** AUDIO IN 339 **/ 340 341 #define NUM_IN_BUFFERS 2 342 343 typedef struct WinAudioIn { 344 HWVoiceIn hw; 345 HWAVEIN wavein; 346 CRITICAL_SECTION lock; 347 unsigned char* buffer_bytes; 348 WAVEHDR buffers[ NUM_IN_BUFFERS ]; 349 int read_index; 350 int read_count; 351 int read_pos; 352 int read_size; 353 } WinAudioIn; 354 355 /* The Win32 callback that is called when a buffer has finished playing */ 356 static void CALLBACK 357 winaudio_in_buffer_done (HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, 358 DWORD dwParam1, DWORD dwParam2) 359 { 360 WinAudioIn* s = (WinAudioIn*) dwInstance; 361 362 /* Only service "buffer done playing" messages */ 363 if ( uMsg != WIM_DATA ) 364 return; 365 366 /* Signal that we are done playing a buffer */ 367 EnterCriticalSection( &s->lock ); 368 if (s->read_count < NUM_IN_BUFFERS) 369 s->read_count += 1; 370 //D(".%c",s->read_count + '0'); fflush(stdout); 371 LeaveCriticalSection( &s->lock ); 372 } 373 374 static void 375 winaudio_in_fini (HWVoiceIn *hw) 376 { 377 WinAudioIn* s = (WinAudioIn*) hw; 378 int i; 379 380 if (s->wavein) { 381 waveInReset(s->wavein); 382 s->wavein = 0; 383 } 384 385 for ( i=0; i<NUM_OUT_BUFFERS; ++i ) { 386 if ( s->buffers[i].dwUser != 0xFFFF ) { 387 waveInUnprepareHeader( 388 s->wavein, &s->buffers[i], sizeof(s->buffers[i]) ); 389 s->buffers[i].dwUser = 0xFFFF; 390 } 391 } 392 393 if (s->buffer_bytes != NULL) { 394 qemu_free(s->buffer_bytes); 395 s->buffer_bytes = NULL; 396 } 397 398 if (s->wavein) { 399 waveInClose(s->wavein); 400 s->wavein = NULL; 401 } 402 } 403 404 405 static int 406 winaudio_in_init (HWVoiceIn *hw, struct audsettings *as) 407 { 408 WinAudioIn* s = (WinAudioIn*) hw; 409 MMRESULT result; 410 WAVEFORMATEX format; 411 int shift, i, samples_size; 412 413 s->wavein = NULL; 414 InitializeCriticalSection( &s->lock ); 415 for (i = 0; i < NUM_OUT_BUFFERS; i++) { 416 s->buffers[i].dwUser = 0xFFFF; 417 } 418 s->buffer_bytes = NULL; 419 420 /* compute desired wave input format */ 421 format.wFormatTag = WAVE_FORMAT_PCM; 422 format.nChannels = as->nchannels; 423 format.nSamplesPerSec = as->freq; 424 format.nAvgBytesPerSec = as->freq*as->nchannels; 425 426 switch (as->fmt) { 427 case AUD_FMT_S8: shift = 0; break; 428 case AUD_FMT_U8: shift = 0; break; 429 case AUD_FMT_S16: shift = 1; break; 430 case AUD_FMT_U16: shift = 1; break; 431 default: 432 fprintf(stderr, "qemu: winaudio: Bad input audio format: %d\n", 433 as->fmt); 434 return -1; 435 } 436 437 format.nAvgBytesPerSec = (format.nSamplesPerSec * format.nChannels) << shift; 438 format.nBlockAlign = format.nChannels << shift; 439 format.wBitsPerSample = 8 << shift; 440 format.cbSize = 0; 441 442 /* open the wave in device */ 443 result = waveInOpen( &s->wavein, WAVE_MAPPER, &format, 444 (DWORD_PTR)winaudio_in_buffer_done, (DWORD_PTR) hw, 445 CALLBACK_FUNCTION); 446 if ( result != MMSYSERR_NOERROR ) { 447 dump_mmerror( "qemu: winaudio: waveInOpen()", result); 448 return -1; 449 } 450 451 samples_size = format.nBlockAlign * conf.nb_samples; 452 s->buffer_bytes = qemu_malloc( NUM_IN_BUFFERS * samples_size ); 453 if (s->buffer_bytes == NULL) { 454 waveInClose( s->wavein ); 455 s->wavein = NULL; 456 fprintf(stderr, "not enough memory for Windows audio buffers\n"); 457 return -1; 458 } 459 460 for (i = 0; i < NUM_IN_BUFFERS; i++) { 461 memset( &s->buffers[i], 0, sizeof(s->buffers[i]) ); 462 s->buffers[i].lpData = (LPSTR)(s->buffer_bytes + i*samples_size); 463 s->buffers[i].dwBufferLength = samples_size; 464 s->buffers[i].dwFlags = WHDR_DONE; 465 466 result = waveInPrepareHeader( s->wavein, &s->buffers[i], 467 sizeof(s->buffers[i]) ); 468 if ( result != MMSYSERR_NOERROR ) { 469 dump_mmerror("waveInPrepareHeader()", result); 470 return -1; 471 } 472 473 result = waveInAddBuffer( s->wavein, &s->buffers[i], 474 sizeof(s->buffers[i]) ); 475 if ( result != MMSYSERR_NOERROR ) { 476 dump_mmerror("waveInAddBuffer()", result); 477 return -1; 478 } 479 } 480 481 #if DEBUG 482 /* Check the sound device we retrieved */ 483 { 484 WAVEINCAPS caps; 485 486 result = waveInGetDevCaps((UINT) s->wavein, &caps, sizeof(caps)); 487 if ( result != MMSYSERR_NOERROR ) { 488 dump_mmerror("waveInGetDevCaps()", result); 489 } else 490 printf("Audio in device: %s\n", caps.szPname); 491 } 492 #endif 493 494 audio_pcm_init_info (&hw->info, as); 495 hw->samples = conf.nb_samples*2; 496 497 s->read_index = 0; 498 s->read_count = 0; 499 s->read_pos = 0; 500 s->read_size = samples_size; 501 return 0; 502 } 503 504 505 /* report the number of captured samples to the audio subsystem */ 506 static int 507 winaudio_in_run (HWVoiceIn *hw) 508 { 509 WinAudioIn* s = (WinAudioIn*) hw; 510 int captured = 0; 511 int has_buffer; 512 int live = hw->samples - hw->total_samples_captured; 513 514 if (!live) { 515 #if 0 516 static int counter; 517 if (++counter == 100) { 518 D("0"); fflush(stdout); 519 counter = 0; 520 } 521 #endif 522 return 0; 523 } 524 525 EnterCriticalSection( &s->lock ); 526 has_buffer = (s->read_count > 0); 527 LeaveCriticalSection( &s->lock ); 528 529 if (has_buffer > 0) { 530 while (live > 0) { 531 WAVEHDR* wav_buffer = s->buffers + s->read_index; 532 int wav_bytes = (s->read_size - s->read_pos); 533 int wav_samples = audio_MIN(wav_bytes >> hw->info.shift, live); 534 int hw_samples = audio_MIN(hw->samples - hw->wpos, live); 535 struct st_sample* dst = hw->conv_buf + hw->wpos; 536 uint8_t* src = (uint8_t*)wav_buffer->lpData + s->read_pos; 537 538 if (wav_samples > hw_samples) { 539 wav_samples = hw_samples; 540 } 541 542 wav_bytes = wav_samples << hw->info.shift; 543 544 D("%s: buffer:%d pos:%d size:%d wsamples:%d wbytes:%d live:%d wpos:%d hwsamples:%d\n", 545 __FUNCTION__, s->read_index, s->read_pos, s->read_size, wav_samples, wav_bytes, live, 546 hw->wpos, hw->samples); 547 548 hw->conv(dst, src, wav_samples, &nominal_volume); 549 550 hw->wpos += wav_samples; 551 if (hw->wpos >= hw->samples) 552 hw->wpos -= hw->samples; 553 554 live -= wav_samples; 555 captured += wav_samples; 556 s->read_pos += wav_bytes; 557 if (s->read_pos == s->read_size) { 558 s->read_pos = 0; 559 s->read_index += 1; 560 if (s->read_index == NUM_IN_BUFFERS) 561 s->read_index = 0; 562 563 waveInAddBuffer( s->wavein, wav_buffer, sizeof(*wav_buffer) ); 564 565 EnterCriticalSection( &s->lock ); 566 if (--s->read_count == 0) { 567 live = 0; 568 } 569 LeaveCriticalSection( &s->lock ); 570 } 571 } 572 } 573 return captured; 574 } 575 576 577 static int 578 winaudio_in_read (SWVoiceIn *sw, void *buf, int len) 579 { 580 int ret = audio_pcm_sw_read (sw, buf, len); 581 if (ret > 0) 582 D("%s: (%d) returned %d\n", __FUNCTION__, len, ret); 583 return ret; 584 } 585 586 587 static int 588 winaudio_in_ctl (HWVoiceIn *hw, int cmd, ...) 589 { 590 WinAudioIn* s = (WinAudioIn*) hw; 591 592 switch (cmd) { 593 case VOICE_ENABLE: 594 D("%s: enable audio in\n", __FUNCTION__); 595 waveInStart( s->wavein ); 596 break; 597 598 case VOICE_DISABLE: 599 D("%s: disable audio in\n", __FUNCTION__); 600 waveInStop( s->wavein ); 601 break; 602 } 603 return 0; 604 } 605 606 /** AUDIO STATE 607 **/ 608 609 typedef struct WinAudioState { 610 int dummy; 611 } WinAudioState; 612 613 static WinAudioState g_winaudio; 614 615 static void* 616 winaudio_init(void) 617 { 618 WinAudioState* s = &g_winaudio; 619 620 #if DEBUG 621 start_time = qemu_get_clock(vm_clock); 622 last_time = 0; 623 #endif 624 625 return s; 626 } 627 628 629 static void 630 winaudio_fini (void *opaque) 631 { 632 } 633 634 static struct audio_option winaudio_options[] = { 635 {"SAMPLES", AUD_OPT_INT, &conf.nb_samples, 636 "Size of Windows audio buffer in samples", NULL, 0}, 637 {NULL, 0, NULL, NULL, NULL, 0} 638 }; 639 640 static struct audio_pcm_ops winaudio_pcm_ops = { 641 winaudio_out_init, 642 winaudio_out_fini, 643 winaudio_out_run, 644 winaudio_out_write, 645 winaudio_out_ctl, 646 647 winaudio_in_init, 648 winaudio_in_fini, 649 winaudio_in_run, 650 winaudio_in_read, 651 winaudio_in_ctl 652 }; 653 654 struct audio_driver win_audio_driver = { 655 INIT_FIELD (name = ) "winaudio", 656 INIT_FIELD (descr = ) "Windows wave audio", 657 INIT_FIELD (options = ) winaudio_options, 658 INIT_FIELD (init = ) winaudio_init, 659 INIT_FIELD (fini = ) winaudio_fini, 660 INIT_FIELD (pcm_ops = ) &winaudio_pcm_ops, 661 INIT_FIELD (can_be_default = ) 1, 662 INIT_FIELD (max_voices_out = ) 1, 663 INIT_FIELD (max_voices_in = ) 1, 664 INIT_FIELD (voice_size_out = ) sizeof (WinAudioOut), 665 INIT_FIELD (voice_size_in = ) sizeof (WinAudioIn) 666 }; 667