Linux – Command line audio – piping for simultaneous playback and recording

alsaaudiolinuxpipe

I am trying to generate sound data, convert it and store it to a WAV format. I'm almost there – except I'd like to hear the generated sound "while" it is being "recorded".

This command line just generates data and plays it back:

perl -e 'for ($c=0; $c<4*44100; $c++) {
             $k=1*sin((1500+$c/16e1)*$c*22e-6); print pack "f", $k;
         } ' |
aplay -t raw -c 1 -r 44100 -f FLOAT_LE 

(Note that if you press Ctrl-C here after sound stops playing, aplay may segfault)

Using sox and mplayer, I can record fine – but I can hear no sound at the same time:

perl -e 'for ($c=0; $c<4*44100; $c++) {
             $k=1*sin((1500+$c/16e1)*$c*22e-6); print pack "f", $k;
         } ' |
sox -V -r 44100 -c 1 -b 32 -e floating-point -t raw - \
    -c 2 -b 16 -t wav - trim 0 3 gain -1 dither |
mplayer - -cache 8092 -endpos 3 -vo null -ao pcm:waveheader:file=test.wav

Note here that play test.wav (where play is from sox package, not alsa's aplay) will state "Duration: 00:00:03.00" for the test.wav file. Also, this process seems to run faster than realtime (i.e. completes in (apparently) less than 3 secs).

By trying to cheat by using tee to capture the stream to disk,

perl -e 'for ($c=0; $c<4*44100; $c++) {
             $k=1*sin((1500+$c/16e1)*$c*22e-6); print pack "f", $k;
         } ' |
sox -V -r 44100 -c 1 -b 32 -e floating-point -t raw - \
    -c 2 -b 16 -t wav - trim 0 3 gain -1 dither |
tee test.wav |
aplay

Here apparently I get to hear the sound as it is generated – and test.wav is playable as well, however, play test.wav will report "Duration: unknown".

So I'd like to ask – is it possible to do something like the above "one-liner" command line, to both generate, play and record a sound "at the same time" – however, without the need to install jack?

PS: some relevant links:

Best Answer

You can use tee(1) to multiplex the stream, e.g.

perl -e 'for ($c=0; $c<4*44100; $c++) {
  $k=1*sin((1500+$c/16e1)*$c*22e-6); print pack "f", $k;
}' | tee >(sox -c1 -r44100 -t f32 - test.wav) \
         >(sox -c1 -r44100 -t f32 - -d) > /dev/null

You might also be interested in soxs' synth effect, which can produce most tones and sweeps, e.g.

sox -n -r 44100 test.wav synth 4 sine 100:1000
Related Question