[alsa-devel] Basic questions
Hi everybody,
I am new to ALSA-API and would be glad, if someone give me an advice to the following questions. Up to now I used Rtaudio for cross compiling the player for windows and Linux. But know I need to go more into ALSA...
- Am I right to use async mode to get lowest latency times and using pause/play/stop?
- I used the following piece of code. But don't get any output. The callback output shows "avail" with very short count of frames...
I write a whole file (raw) to buffer, called buffer_alsa with 6894888 frames. What is going wrong?
I get this output:
Frames: 6894888 buffer_size (frames): 2048 buffer_time (frames): 46439 period_size (frames): 256 period_time (usec): 5804 periods (count): 8 Avail: 1540 Avail: 1285 Avail: 1030 Avail: 775 Avail: 520 Avail: 265 Avail: 10 Avail: 2 Avail: 2 Avail: 3 Avail: 2 ...
The code follows ...
Best regards Thomas
-----------------------------
void MyCallback(snd_async_handler_t *pcm_callback) { snd_pcm_t *handle = snd_async_handler_get_pcm(pcm_callback); snd_pcm_sframes_t avail;
//std::cout << "Period_size: " << period_size << std::endl;
avail = snd_pcm_avail_update(handle); while (avail >= period_size) { snd_pcm_writei(handle, buffer_alsa , period_size); avail = snd_pcm_avail_update(handle); std::cout << " Avail: " << avail << std::endl; } }
//----------------------------------------------------
snd_pcm_hw_params_alloca(¶ms);
if ((err = snd_pcm_hw_params_any(handle, params)) < 0) std::cout << " Error (reading configuration): " << snd_strerror(err) << std::endl;
/* Set parameters */ if ((err = snd_pcm_hw_params_set_access(handle, params,SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) //printf("ERROR: Can't set interleaved mode. %s\n", snd_strerror(err)); std::cout << " Error (can't set interleaved mode): " << snd_strerror(err) << std::endl;
if ((err = snd_pcm_hw_params_set_format(handle, params, FORMAT)) < 0) //printf("ERROR: Can't set format. %s\n", snd_strerror(err)); std::cout << " Error (can't set format): " << snd_strerror(err) << std::endl;
if ((err = snd_pcm_hw_params_set_channels(handle, params, data.channels)) < 0) //printf("ERROR: Can't set channels number. %s\n", snd_strerror(err)); std::cout << " Error (can't set channels number): " << snd_strerror(err) << std::endl;
if ((err = snd_pcm_hw_params_set_rate_near(handle, params, &fs, 0)) < 0) //printf("ERROR: Can't set rate. %s\n", snd_strerror(err)); std::cout << " Error (can't set rate): " << snd_strerror(err) << std::endl;
if ((err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &buffer_size)) < 0) std::cout << " Error (can't set buffer size): " << snd_strerror(err) << std::endl;
if ((err = snd_pcm_hw_params_set_period_size_near (handle, params, &period_size, NULL)) < 0) std::cout << " Error (can't set period size): " << snd_strerror(err) << std::endl;
/* Write parameters */ if ((err = snd_pcm_hw_params(handle, params)) < 0) //printf("ERROR: Can't set hardware parameters. %s\n", snd_strerror(err)); std::cout << " Error (can't set harware params): " << snd_strerror(err) << std::endl;
//---------------------- ------------------------------
// Get Parameters snd_pcm_hw_params_get_buffer_size(params, &buffer_sz); std::cout << " buffer_size (frames): " << buffer_sz << std::endl;
snd_pcm_hw_params_get_buffer_time(params, &buffer_tm, NULL); std::cout << " buffer_time (frames): " << buffer_tm << std::endl;
snd_pcm_hw_params_get_period_size(params, &aframes, 0); std::cout << " period_size (frames): " << aframes << std::endl;
snd_pcm_hw_params_get_period_time(params, &data.channels, NULL); // tmp Zeit in us std::cout << " period_time (usec): " << data.channels << std::endl;
snd_pcm_hw_params_get_periods(params, &piods, 0); std::cout << " periods (count): " << piods << std::endl;
// ----------------------------------------------------------------------------
//snd_pcm_hw_params_free (params);
// --------------------- Hardware-Params End ------------------------------
snd_pcm_sw_params_t *sw_params;
if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) { std::cout << " Error (can't allocate sw params): " << snd_strerror(err) << std::endl; return; } if ((err = snd_pcm_sw_params_current(handle, sw_params)) < 0) { std::cout << "Error (can't return curr sw config): " << snd_strerror(err) << std::endl; return; }
if ((err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, buffer_size)) < 0) // 0U oder 4096 ? { // This parameter controls the wake up point. If the count of available samples is equal or greater than this value, then the application will be activated. std::cout << "Error (can't set start thresh mode): " << snd_strerror(err) << std::endl; return; } /* if ((err = snd_pcm_sw_params_set_silence_threshold( handle, sw_params, 0 )) < 0) { std::cout << " Error (can't set silence thres): " << snd_strerror(err) << std::endl; return; } */ if ((err = snd_pcm_sw_params_set_avail_min (handle, sw_params, period_size)) < 0) { std::cout << " Error (can't set min avail count): " << snd_strerror(err) << std::endl; return; } // here are two options for a fix //snd_pcm_sw_params_set_silence_size( phandle, sw_params, ULONG_MAX ); /* snd_pcm_uframes_t val; if ((err = snd_pcm_sw_params_get_boundary(sw_params, &val)) < 0) { std::cout << " Error (can't get boundary): " << snd_strerror(err) << std::endl; return; } if ((err = snd_pcm_sw_params_set_silence_size(handle, sw_params, val)) < 0) { std::cout << " Error (can't set silence): " << snd_strerror(err) << std::endl; return; } */ if ((err = snd_pcm_sw_params(handle, sw_params)) < 0) { std::cout << " Error (can't set sw params): " << snd_strerror(err) << std::endl; return; } snd_pcm_sw_params_free(sw_params);
// ------------------------- SW-Params End ---------------------------------
if ((err = snd_pcm_prepare(handle)) < 0) { std::cout << " Error (can't prepare audio): " << snd_strerror(err) << std::endl; return; } snd_async_handler_t *pcm_callback; if ((err = snd_async_add_pcm_handler(&pcm_callback, handle, MyCallback, NULL)) < 0) { std::cout << " Error (can't add pcm handler): " << snd_strerror(err) << std::endl; return; } if ((err = snd_pcm_writei(handle, buffer_alsa, 2 * period_size) == -EPIPE)) { std::cout << " Error: XRUN" << std::endl; err = snd_pcm_recover(handle, err, 0); if ((err = snd_pcm_prepare (handle)) < 0) { std::cout << " Error (can't prepare audio): " << snd_strerror(err) << std::endl; return; } } if ((err = snd_pcm_start(handle)) < 0) { std::cout << " Error (can't start audio): " << snd_strerror(err) << std::endl; return; }
void MyCallback(snd_async_handler_t *pcm_callback);
tsepp2001@t-online.de wrote:
Am I right to use async mode
No. It is not supported by all devices, and almost impossible to use correctly.
to get lowest latency times
Latency depends on the buffer size, and how fast your code can react to the notification that some space is available.
and using pause/play/stop?
You probably want to use non-blocking mode.
Regards, Clemens
participants (2)
-
Clemens Ladisch
-
tsepp2001@t-online.de