cat an audio file into the microphone/recording device

I need to simulate the process of recording an audio file, using an existing recording.

I'm running ubuntu 8.10 and had thought this would be quite simple but it seems now to be rather not so simple.

My 'concept' of what I want to do is,


$ cat myaudio.wav > /dev/mic

There is another program listening/waiting for the input.

Edit: Maybe it isn't clear from the way I explained this, but I want to basically spoof the microphone input by streaming a pre-recorded soundfile into the microphone device.
I can do


$ cat /dev/dsp > myfile.au 

to capture the raw input, and


$ cat myfile.au > /dev/dsp

to stream recorded input to my speakers, so I'm a bit confused as to why I can't do something analogous with the microphone/recording function? I still know next to nothing about low level sound stuff on linux but it seems odd that this isn't possible.


Solution 1:

Substitute the device node for something else

Move away the device node, or recompile the sound library to open something else. That way, you could put in your own fifo, or bogus loopback sound driver, or something.

Solution 2:

Thanks for all the responses. This turned out to be quite a learning experience. In particular I learned that linux still has some crufty areas and the sound setup is ( perhaps the largest ) one of them.

It's quite easy to cat the microphone input into a file ( or socket ), and intuitively it should be equally simple to cat a file into whatever the mic reads into - so that whatever reads from the mic can read said sound file. This however is, unfortunately not the case.

As a result I ended up modifying the listening program so that it could listen on a socket instead of the raw mic input. I then wrote a simple perl client to redirect the mic input to the socket,



#!/usr/bin/perl -w                                                                                                           
use strict;
use warnings;
use IO::Socket;

my $dspdev = '/dev/dsp';
my $port   = 8000;
my $host   = "127.0.0.1";

my $sock = new IO::Socket::INET(
    PeerAddr => $host,
    PeerPort => $port,
    Type     => SOCK_STREAM,
    Proto    => "tcp",
    ) || die "Couldn't open socket: $!\n";

open(DSP, "<", $dspdev)||die "can't open $dspdev: $!\n";

while( 1 ) {
    my $rbuf = "";
    sysread(DSP, $rbuf, 4096);
    syswrite($sock, $rbuf);
}

At this stage, this is all I needed, however it seems it required a bit more effort than it should have. I've come up with a solution, but I haven't actually answered my original question, so I'll leave this open.

edit: decided to close this as it doesn't seem to be attracting any more attention.