Commit 7a24c80011d50c1716e84ab70de097caa201746f
1 parent
5b5ef0db
Rework period/buffer size setting
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4768 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
52 additions
and
138 deletions
audio/alsaaudio.c
| ... | ... | @@ -58,37 +58,15 @@ static struct { |
| 58 | 58 | int period_size_out_overridden; |
| 59 | 59 | int verbose; |
| 60 | 60 | } conf = { |
| 61 | -#define DEFAULT_BUFFER_SIZE 1024 | |
| 62 | -#define DEFAULT_PERIOD_SIZE 256 | |
| 63 | -#ifdef HIGH_LATENCY | |
| 64 | - .size_in_usec_in = 1, | |
| 65 | - .size_in_usec_out = 1, | |
| 66 | -#endif | |
| 67 | 61 | .pcm_name_out = "default", |
| 68 | 62 | .pcm_name_in = "default", |
| 69 | -#ifdef HIGH_LATENCY | |
| 70 | - .buffer_size_in = 400000, | |
| 71 | - .period_size_in = 400000 / 4, | |
| 72 | - .buffer_size_out = 400000, | |
| 73 | - .period_size_out = 400000 / 4, | |
| 74 | -#else | |
| 75 | - .buffer_size_in = DEFAULT_BUFFER_SIZE * 4, | |
| 76 | - .period_size_in = DEFAULT_PERIOD_SIZE * 4, | |
| 77 | - .buffer_size_out = DEFAULT_BUFFER_SIZE, | |
| 78 | - .period_size_out = DEFAULT_PERIOD_SIZE, | |
| 79 | - .buffer_size_in_overridden = 0, | |
| 80 | - .buffer_size_out_overridden = 0, | |
| 81 | - .period_size_in_overridden = 0, | |
| 82 | - .period_size_out_overridden = 0, | |
| 83 | -#endif | |
| 84 | - .threshold = 0, | |
| 85 | - .verbose = 0 | |
| 86 | 63 | }; |
| 87 | 64 | |
| 88 | 65 | struct alsa_params_req { |
| 89 | 66 | int freq; |
| 90 | 67 | snd_pcm_format_t fmt; |
| 91 | 68 | int nchannels; |
| 69 | + int size_in_usec; | |
| 92 | 70 | unsigned int buffer_size; |
| 93 | 71 | unsigned int period_size; |
| 94 | 72 | }; |
| ... | ... | @@ -286,17 +264,16 @@ static int alsa_open (int in, struct alsa_params_req *req, |
| 286 | 264 | snd_pcm_t *handle; |
| 287 | 265 | snd_pcm_hw_params_t *hw_params; |
| 288 | 266 | int err; |
| 267 | + int size_in_usec; | |
| 289 | 268 | unsigned int freq, nchannels; |
| 290 | 269 | const char *pcm_name = in ? conf.pcm_name_in : conf.pcm_name_out; |
| 291 | - unsigned int period_size, buffer_size; | |
| 292 | 270 | snd_pcm_uframes_t obt_buffer_size; |
| 293 | 271 | const char *typ = in ? "ADC" : "DAC"; |
| 294 | 272 | snd_pcm_format_t obtfmt; |
| 295 | 273 | |
| 296 | 274 | freq = req->freq; |
| 297 | - period_size = req->period_size; | |
| 298 | - buffer_size = req->buffer_size; | |
| 299 | 275 | nchannels = req->nchannels; |
| 276 | + size_in_usec = req->size_in_usec; | |
| 300 | 277 | |
| 301 | 278 | snd_pcm_hw_params_alloca (&hw_params); |
| 302 | 279 | |
| ... | ... | @@ -356,130 +333,61 @@ static int alsa_open (int in, struct alsa_params_req *req, |
| 356 | 333 | goto err; |
| 357 | 334 | } |
| 358 | 335 | |
| 359 | - if (!((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out))) { | |
| 360 | - if (!buffer_size) { | |
| 361 | - buffer_size = DEFAULT_BUFFER_SIZE; | |
| 362 | - period_size= DEFAULT_PERIOD_SIZE; | |
| 363 | - } | |
| 364 | - } | |
| 365 | - | |
| 366 | - if (buffer_size) { | |
| 367 | - if ((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out)) { | |
| 368 | - if (period_size) { | |
| 369 | - err = snd_pcm_hw_params_set_period_time_near ( | |
| 370 | - handle, | |
| 371 | - hw_params, | |
| 372 | - &period_size, | |
| 373 | - 0 | |
| 374 | - ); | |
| 375 | - if (err < 0) { | |
| 376 | - alsa_logerr2 (err, typ, | |
| 377 | - "Failed to set period time %d\n", | |
| 378 | - req->period_size); | |
| 379 | - goto err; | |
| 380 | - } | |
| 381 | - } | |
| 336 | + if (req->buffer_size) { | |
| 337 | + if (size_in_usec) { | |
| 338 | + int dir = 0; | |
| 339 | + unsigned int btime = req->buffer_size; | |
| 382 | 340 | |
| 383 | 341 | err = snd_pcm_hw_params_set_buffer_time_near ( |
| 384 | 342 | handle, |
| 385 | 343 | hw_params, |
| 386 | - &buffer_size, | |
| 387 | - 0 | |
| 344 | + &btime, | |
| 345 | + &dir | |
| 388 | 346 | ); |
| 389 | - | |
| 390 | - if (err < 0) { | |
| 391 | - alsa_logerr2 (err, typ, | |
| 392 | - "Failed to set buffer time %d\n", | |
| 393 | - req->buffer_size); | |
| 394 | - goto err; | |
| 395 | - } | |
| 396 | 347 | } |
| 397 | 348 | else { |
| 398 | - int dir; | |
| 399 | - snd_pcm_uframes_t minval; | |
| 400 | - | |
| 401 | - if (period_size) { | |
| 402 | - minval = period_size; | |
| 403 | - dir = 0; | |
| 404 | - | |
| 405 | - err = snd_pcm_hw_params_get_period_size_min ( | |
| 406 | - hw_params, | |
| 407 | - &minval, | |
| 408 | - &dir | |
| 409 | - ); | |
| 410 | - if (err < 0) { | |
| 411 | - alsa_logerr ( | |
| 412 | - err, | |
| 413 | - "Could not get minmal period size for %s\n", | |
| 414 | - typ | |
| 415 | - ); | |
| 416 | - } | |
| 417 | - else { | |
| 418 | - if (period_size < minval) { | |
| 419 | - if ((in && conf.period_size_in_overridden) | |
| 420 | - || (!in && conf.period_size_out_overridden)) { | |
| 421 | - dolog ("%s period size(%d) is less " | |
| 422 | - "than minmal period size(%ld)\n", | |
| 423 | - typ, | |
| 424 | - period_size, | |
| 425 | - minval); | |
| 426 | - } | |
| 427 | - period_size = minval; | |
| 428 | - } | |
| 429 | - } | |
| 349 | + snd_pcm_uframes_t bsize = req->buffer_size; | |
| 430 | 350 | |
| 431 | - err = snd_pcm_hw_params_set_period_size ( | |
| 432 | - handle, | |
| 433 | - hw_params, | |
| 434 | - period_size, | |
| 435 | - 0 | |
| 436 | - ); | |
| 437 | - if (err < 0) { | |
| 438 | - alsa_logerr2 (err, typ, "Failed to set period size %d\n", | |
| 439 | - req->period_size); | |
| 440 | - goto err; | |
| 441 | - } | |
| 442 | - } | |
| 351 | + err = snd_pcm_hw_params_set_buffer_size_near ( | |
| 352 | + handle, | |
| 353 | + hw_params, | |
| 354 | + &bsize | |
| 355 | + ); | |
| 356 | + } | |
| 357 | + if (err < 0) { | |
| 358 | + alsa_logerr2 (err, typ, "Failed to set buffer %s to %d\n", | |
| 359 | + size_in_usec ? "time" : "size", req->buffer_size); | |
| 360 | + goto err; | |
| 361 | + } | |
| 362 | + } | |
| 363 | + | |
| 364 | + if (req->period_size) { | |
| 365 | + if (size_in_usec) { | |
| 366 | + int dir = 0; | |
| 367 | + unsigned int ptime = req->period_size; | |
| 443 | 368 | |
| 444 | - minval = buffer_size; | |
| 445 | - err = snd_pcm_hw_params_get_buffer_size_min ( | |
| 369 | + err = snd_pcm_hw_params_set_period_time_near ( | |
| 370 | + handle, | |
| 446 | 371 | hw_params, |
| 447 | - &minval | |
| 372 | + &ptime, | |
| 373 | + &dir | |
| 448 | 374 | ); |
| 449 | - if (err < 0) { | |
| 450 | - alsa_logerr (err, "Could not get minmal buffer size for %s\n", | |
| 451 | - typ); | |
| 452 | - } | |
| 453 | - else { | |
| 454 | - if (buffer_size < minval) { | |
| 455 | - if ((in && conf.buffer_size_in_overridden) | |
| 456 | - || (!in && conf.buffer_size_out_overridden)) { | |
| 457 | - dolog ( | |
| 458 | - "%s buffer size(%d) is less " | |
| 459 | - "than minimal buffer size(%ld)\n", | |
| 460 | - typ, | |
| 461 | - buffer_size, | |
| 462 | - minval | |
| 463 | - ); | |
| 464 | - } | |
| 465 | - buffer_size = minval; | |
| 466 | - } | |
| 467 | - } | |
| 375 | + } | |
| 376 | + else { | |
| 377 | + snd_pcm_uframes_t psize = req->period_size; | |
| 468 | 378 | |
| 469 | - err = snd_pcm_hw_params_set_buffer_size ( | |
| 379 | + err = snd_pcm_hw_params_set_buffer_size_near ( | |
| 470 | 380 | handle, |
| 471 | 381 | hw_params, |
| 472 | - buffer_size | |
| 382 | + &psize | |
| 473 | 383 | ); |
| 474 | - if (err < 0) { | |
| 475 | - alsa_logerr2 (err, typ, "Failed to set buffer size %d\n", | |
| 476 | - req->buffer_size); | |
| 477 | - goto err; | |
| 478 | - } | |
| 479 | 384 | } |
| 480 | - } | |
| 481 | - else { | |
| 482 | - dolog ("warning: Buffer size is not set\n"); | |
| 385 | + | |
| 386 | + if (err < 0) { | |
| 387 | + alsa_logerr2 (err, typ, "Failed to set period %s to %d\n", | |
| 388 | + size_in_usec ? "time" : "size", req->period_size); | |
| 389 | + goto err; | |
| 390 | + } | |
| 483 | 391 | } |
| 484 | 392 | |
| 485 | 393 | err = snd_pcm_hw_params (handle, hw_params); |
| ... | ... | @@ -697,6 +605,7 @@ static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as) |
| 697 | 605 | req.nchannels = as->nchannels; |
| 698 | 606 | req.period_size = conf.period_size_out; |
| 699 | 607 | req.buffer_size = conf.buffer_size_out; |
| 608 | + req.size_in_usec = conf.size_in_usec_in; | |
| 700 | 609 | |
| 701 | 610 | if (alsa_open (0, &req, &obt, &handle)) { |
| 702 | 611 | return -1; |
| ... | ... | @@ -774,6 +683,7 @@ static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as) |
| 774 | 683 | req.nchannels = as->nchannels; |
| 775 | 684 | req.period_size = conf.period_size_in; |
| 776 | 685 | req.buffer_size = conf.buffer_size_in; |
| 686 | + req.size_in_usec = conf.size_in_usec_in; | |
| 777 | 687 | |
| 778 | 688 | if (alsa_open (1, &req, &obt, &handle)) { |
| 779 | 689 | return -1; |
| ... | ... | @@ -953,16 +863,20 @@ static struct audio_option alsa_options[] = { |
| 953 | 863 | {"DAC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_out, |
| 954 | 864 | "DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0}, |
| 955 | 865 | {"DAC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_out, |
| 956 | - "DAC period size", &conf.period_size_out_overridden, 0}, | |
| 866 | + "DAC period size (0 to go with system default)", | |
| 867 | + &conf.period_size_out_overridden, 0}, | |
| 957 | 868 | {"DAC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_out, |
| 958 | - "DAC buffer size", &conf.buffer_size_out_overridden, 0}, | |
| 869 | + "DAC buffer size (0 to go with system default)", | |
| 870 | + &conf.buffer_size_out_overridden, 0}, | |
| 959 | 871 | |
| 960 | 872 | {"ADC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_in, |
| 961 | 873 | "ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0}, |
| 962 | 874 | {"ADC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_in, |
| 963 | - "ADC period size", &conf.period_size_in_overridden, 0}, | |
| 875 | + "ADC period size (0 to go with system default)", | |
| 876 | + &conf.period_size_in_overridden, 0}, | |
| 964 | 877 | {"ADC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_in, |
| 965 | - "ADC buffer size", &conf.buffer_size_in_overridden, 0}, | |
| 878 | + "ADC buffer size (0 to go with system default)", | |
| 879 | + &conf.buffer_size_in_overridden, 0}, | |
| 966 | 880 | |
| 967 | 881 | {"THRESHOLD", AUD_OPT_INT, &conf.threshold, |
| 968 | 882 | "(undocumented)", NULL, 0}, | ... | ... |