0

I'm writing a "play sound" program on Reapberry Pi with ALSA.

I called snd_pcm_writei every 1280 samples.

I wish to add a small LED, and let it "lighter while the sound is louder, and darker while the sound is quieter."

My plane is, if there's a callback every short time period(ex: 100ms), and I can get the instantaneous volume in the callback, I can control the LED in it.

In android, there's AudioTrack.setPositionNotificationPeriod. However, I've no idea how to do this under Linux with ALSA.

Could anyone give me some advise?

The playback function looks like this:

// nLeftFrameSize: Total sample number.
// hDevice: Play device handle (initialized beforehand).
// lpbyBuffer: Sample buffer.

while(nLeftFrameSize > 0){
    nRes = (int)snd_pcm_writei(( snd_pcm_t*)hDevice, lpbyBuffer, 1280);
    nLeftFrameSize -= 1280;
}

I've tried calculate RMS in the while loop before the snd_pcm_writei(), set the LED brightness, and sleep, to make sure the LED can light up while these 1280 samples are playing. But this cause the sound discontinuous.

So I'd create another thread for the LED control, and I can sleep in that thread without bothering the playback.

仕勛陳
  • 1
  • 1
  • What is your sample rate? For example 48 kHz results in a period T=1280/48000 s = 0.026 s. So every forth block, the time is slightly above 100 ms. Also, there is no such thing as instantaneous volume. It is likely that you want to compute some RMS over your period. – user877329 Aug 22 '17 at 07:21
  • My sample rate is 16 kHz. So I've to calculate the volume(RMS) by myself, and use multi-thread to control the LED? – 仕勛陳 Aug 22 '17 at 07:28
  • Computing RMS yes (and that is what you should expect from any sane audio I/O library at that level). I am not really into raw ALSA (I use JACK), so I cannot answer whether you need more threads or not. If you gave me the structure of the playback loop, I would be able to infer it. A hint: You can probably activate the led (and compute the RMS) where you fetch data to the playback buffer. – user877329 Aug 22 '17 at 07:45
  • The playback loop is simple, I edited it, and give my consideration about another thread. – 仕勛陳 Aug 22 '17 at 10:06
  • Try to use ping-pong buffering and blocking mode. You will then need two threads. When the audio thread is done, buffers are swapped (by the audio thread), and the other thread wakes up and processes the input buffer (computing RMS, updating LED), while the output buffer is playing. There will also be perfect sync. – user877329 Aug 22 '17 at 10:43

0 Answers0