How to use ALSA snd_pcm_writei ()?

Can someone explain how snd_pcm_writei

snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) 

work?

I used it like this:

 for (int i = 0; i < 1; i++) { f = snd_pcm_writei(handle, buffer, frames); ... } 

Full source code http://pastebin.com/m2f28b578

Does this mean that I should not give snd_pcm_writei() number of all frames in buffer , but only

sample_rate * latency = frames

?

So, if I, for example. have: sample_rate = 44100 latency = 0.5 [s] all_frames = 100000

The number of frames that I have to provide snd_pcm_writei() will be

sample_rate * latency = frames 44100 * 0.5 = 22050

and the number of iterations that should be for the loop :?

(int) 100000/22050 = 4; with frames = 22050

and one additional, but only with

100000 mod 22050 = 11800

frames?

How it works?

Louise

http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#gf13067c0ebde29118ca05af76e5b17a9

+4
source share
4 answers

frames should be the number of frames (samples) that you want to write from the buffer. Your sound system driver will start transferring these samples to the sound card immediately, and they will play at a constant speed.

The delay is entered in several places. There is a wait time from data buffered by the driver, waiting for transmission to the card. There is at least one buffer filled with data that is transferred to the card at any given time, and there it is buffered on the application side, which bothers you.

To reduce the latency on the application side, you need to write the smallest buffer that will work for you. If your application performs the DSP task, then usually this value is in one window.

It makes no sense to write small buffers in a loop - just go ahead and write everything all at once - but there is an important point to understand: to minimize latency, your application should write to the driver no faster than the driver writes data to the sound card, or you’ll finish accumulating more data and accumulate more and more delays.

For a design that makes creating data in a lock with a sound driver relatively easy, look at the connector ( http://jackaudio.org/ ), which is based on registering a callback function with a sound engine. In fact, you are probably just better off using jack instead of trying to do it yourself if you're really concerned about the delay.

+5
source

I did some testing to determine why snd_pcm_writei() didn't seem to work for me using a few examples that I found in ALSA tutorials and I came to the conclusion that simple examples ran snd_pcm_close () before the sound device could reproduce the full stream by sending it to him.

I set the speed to 11025 , used a 128-byte random buffer and looped snd_pcm_writei() for 11025/128 for every second of sound. Two seconds took 86 * 2 calls snd_pcm_write() to get two seconds of sound.

To give the device enough time to convert data to audio, I use the for loop after the snd_pcm_writei() loop to delay the execution of the snd_pcm_close() function.

After testing, I had to conclude that the sample code did not give enough samples to overcome the latency of the device before the snd_pcm_close function was snd_pcm_close , which implies that the close function has a lower delay than the snd_pcm_write() function.

+3
source

I think the reason for the β€œpremature” closing of the device is that you need to call snd_pcm_drain(handle); to snd_pcm_close(handle); to ensure that all data will be played back before closing the device.

+3
source

If the ALSA driver startup threshold is set incorrectly (if in your case it is about 2 s), you need to call snd_pcm_start () to start rendering data immediately after snd_pcm_writei (). Or you can set the appropriate threshold in the SW settings for the ALSA device.

link

0
source

Source: https://habr.com/ru/post/1299997/


All Articles