WelcomeWelcome | FAQFAQ | DownloadsDownloads | WikiWiki

Author Topic: [Solved] how to detect audio playback using only alsa, without pulseaudio  (Read 11259 times)

Offline jazzbiker

  • Hero Member
  • *****
  • Posts: 934
Re: how to detect audio playback using only alsa, without pulseaudio
« Reply #15 on: April 02, 2021, 02:53:13 PM »
Hi, GNUser!

For my system getting alsa loopback passed flawlessly. i think You can try too. First You will need virtual audio card added with the help of

s u d o      modprobe snd-aloop

(The word, which starts with the 's' letter and ends with 'o' letter is split to avoid You know what, please ignore this extra spaces)
This will create virtual audio card with even-numbered pcm subdevices looped back to odd-numbered capture subdevices. So if Your physical sound card is hw:0, this virtual will be hw:1, and hw:1,0 sent to hw:1,1, hw:1,2 to hw:1,3 and so forth.
Then You will need .asoundrc file, which will duplicate the default alsa output stream to Your physical device and to the virtual one. I've got such an example here https://dt.iki.fi/record-system-output-alsa, placed it in my $HOME and

a l s a c t l     i n i t

These steps allow to capture the output to the default alsa device at hw:1,1, for example

a r e c o r d     -D hw:1,1 -f cd -s 1000 silence.wav

As I can see, wav file have the header sized around 0x30 bytes, followed by the sound samples. In case of silence, all the consequent samples are zeroes.

I think if You don't use some special alsa config, You can try these steps without any changes.
The only correction I've made for downloaded .asoundrc was substituting "Loopback" card name with the "1" constant at line 43.

Offline GNUser

  • Wiki Author
  • Hero Member
  • *****
  • Posts: 1530
Re: how to detect audio playback using only alsa, without pulseaudio
« Reply #16 on: April 02, 2021, 03:34:51 PM »
jazzbiker, I tried your steps and it worked perfectly! cat'ing the wav file always gives me this when there is no sound, even if mpv is open but paused:
Code: [Select]
RIFFWAVEfmt D±data
If mpv or another application is playing something, cat'ing the wav file shows the same header followed by a lot of gibberish characters (binary data representing the recorded sound).

Just brilliant :o Thank you very much. Thread may be marked as solved.

P.S. Your steps worked for me without any changes to the downloaded .asoundrc file. I kept line 43 unchanged, like this:
Code: [Select]
    pcm "hw:Loopback,0,0"Can you show me what your line 43 looks like and help me understand why you changed it?


Offline GNUser

  • Wiki Author
  • Hero Member
  • *****
  • Posts: 1530
Re: how to detect audio playback using only alsa, without pulseaudio
« Reply #17 on: April 02, 2021, 03:46:41 PM »
jazzbiker, another quick question: Whether the wav file contains sound or silence, the file is the same size (I guess just header plus a bunch of zeros if the wav contains only silence). What's the easiest way you can think of to check if somefile.wav is just header followed by zeros? (It seems it would be a simple operation, but I don't think I've ever had the need to look inside a binary file before, so I'm quite out of my element here.)

Offline jazzbiker

  • Hero Member
  • *****
  • Posts: 934
Quick answer, probably not the best one.
Code: [Select]
dd if=/dev/zero bs=1 count=1K status=none > zeroes.bin
arecord -D hw:1,1 -f cd -s 1100 2>/dev/null | dd skip=48 bs=1 count=1K status=none | cmp -s zeroes.bin
$? == 0 means playback is paused.

Edit: sorry for too fast answer :) it works, but reads samples which will not be used for compare, because sample is 4-byte. Better will be:
Code: [Select]
dd if=/dev/zero bs=4 count=1K status=none > zeroes.bin
arecord -D hw:1,1 -f cd -s 1100 2>/dev/null | dd skip=12 bs=4 count=1K status=none | cmp -s zeroes.bin
« Last Edit: April 02, 2021, 04:55:18 PM by jazzbiker »

Offline jazzbiker

  • Hero Member
  • *****
  • Posts: 934
The line 43 in my .asoundrc looks like:
Code: [Select]
    pcm "hw:1,0,0"
but referring to "Loopback" name is better, because You may have more than one physical soundcard and "Loopback" may be 1,2 or even bigger.

Offline jazzbiker

  • Hero Member
  • *****
  • Posts: 934
Edit2 to Reply #18:
Code: [Select]
arecord -D hw:Loopback,1 -f cd -s 1100 2>/dev/null | dd skip=12 bs=4 count=1K status=none | cmp -s zeroes.bin
works fine.

Offline GNUser

  • Wiki Author
  • Hero Member
  • *****
  • Posts: 1530
but referring to "Loopback" name is better, because You may have more than one physical soundcard and "Loopback" may be 1,2 or even bigger.
Thanks, jazzbiker. I'll just use the .asoundrc without modification, then.

Code: [Select]
arecord -D hw:Loopback,1 -f cd -s 1100 2>/dev/null | dd skip=12 bs=4 count=1K status=none | cmp -s zeroes.bin
works fine.
Wow, that's beautiful. Hats off to you. I wondered about the question in the thread's subject line for for a long time before finally starting this thread. Thank you very much for helping me finally solve the mystery :)

Offline jazzbiker

  • Hero Member
  • *****
  • Posts: 934
Hi, GNUser!

Right question is half an answer itself. At this moment I don't need to capture my audio, but if such need will appear, I will exactly know what to do :) Thanks to curaga for pushing into right direction and this guy https://bbs.archlinux.org/viewtopic.php?pid=1153194#p1153194 for config template.

Best regards!

PS: arecord has quiet option, so probably
Code: [Select]
arecord -q -D hw:Loopback,1 -f cd -s 1100 | dd skip=12 bs=4 count=1K status=none | cmp -s zeroes.bin
will avoid producing bytes in order to waste them
« Last Edit: April 03, 2021, 03:46:47 AM by jazzbiker »

Offline Rich

  • Administrator
  • Hero Member
  • *****
  • Posts: 11704
Hi GNUser
You can also use  arecord  as a command line VU meter:
Code: [Select]
echo -ne '\033[?25l' # Turns off cursor so it's not flickering.
arecord -D hw:Loopback,1 -V stereo -c 2 -f cd -q /dev/null

To make the cursor visible again:
Code: [Select]
echo -ne '\033[?25h'or:
Code: [Select]
echo -ne '\e[?25h'

Offline jazzbiker

  • Hero Member
  • *****
  • Posts: 934
Hi, Rich!
Nice functionality, thanks for the tip! And its CPU time consumption is very close to zero.

Offline GNUser

  • Wiki Author
  • Hero Member
  • *****
  • Posts: 1530
Hi, jazzbiker. Byte counts and wav headers are tripping me up, so I dumbed it down for my own use.

I noticed that the wav header changes depending on source, but it is always exactly 44 bytes long.

So dummy approach is to first record known silence and strip the wav header:
Code: [Select]
arecord -q -D hw:Loopback,1 -f cd -s 1000 | dd skip=44 bs=1 2>/dev/null > $HOME/known-silence.wav
Now we have a reference file that we know represents silence.

After that, we can compare periodic samples of same size (likewise with stripped wav header), to our reference file:
[attached because of broken posting]

Offline jazzbiker

  • Hero Member
  • *****
  • Posts: 934
Hi, GNUser!
The "skip" parameter of dd tells about number of blocks to skip, not bytes,, maybe this looks unexpected.

Offline Rich

  • Administrator
  • Hero Member
  • *****
  • Posts: 11704
Hi GNUser
Does this attachment work?

Offline Rich

  • Administrator
  • Hero Member
  • *****
  • Posts: 11704
Hi jazzbiker
The "skip" parameter of dd tells about number of blocks to skip, not bytes,, maybe this looks unexpected.
Yes, but doesn't this set the block size to 1 byte:
Code: [Select]
bs=1

Offline GNUser

  • Wiki Author
  • Hero Member
  • *****
  • Posts: 1530
Hi, jazzbiker. I'm good with dd's "skip" and "bs"--that wasn't the trouble. The issue was that sometimes cmp would give unexpected results ($? == 0 when there's sound, $? != 0 when there's silence).

I tried to troubleshoot but was not able to pinpoint the trouble. Using "count=1K" for zeroes.bin but "-s 1100" for the audio samples was particularly confusing to me.

Thanks for introducing me to  cmp  by the way. Hadn't used that one before. I love the Unix philosophy of having such tiny tools to do one specific job really well :)

Thanks, Rich. The approach in reply #25 is working reliably and I can understand it, so I'm perfectly happy with it.