[alsa-devel] Need help on getting raw audio stream from a dummy sound card
Hi everyone :)
I'm currently assigned to a task that requires me to capture raw audio stream from a dummy sound card. Is this even possible?
Previously, I have been able to capture raw audio stream from my default sound card, by using the following example I got from http://www.linuxjournal.com/article/6735
/* This example reads from the default PCM device
and writes to standard output for 5 seconds of data.
*/
/* Use the newer ALSA API */ #define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
int main() { long loops; int rc; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; int dir; snd_pcm_uframes_t frames; char *buffer;
/* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); }
/* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms);
/* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params);
/* Set the desired hardware parameters. */
/* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
/* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 2);
/* 44100 bits/second sampling rate (CD quality) */ val = 44100; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
/* Set period size to 32 frames. */ frames = 32; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
/* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); }
/* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * 4; /* 2 bytes/sample, 2 channels */ buffer = (char *) malloc(size);
/* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); loops = 5000000 / val;
while (loops > 0) { loops--; rc = snd_pcm_readi(handle, buffer, frames); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } rc = write(1, buffer, size); if (rc != size) fprintf(stderr, "short write: wrote %d bytes\n", rc); }
snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer);
return 0; }
The above example allows me to capture 5 seconds of raw audio. I can use aplay to play the recorded sound and it plays nicely. But right now, I'm working on a project that involves the usage of a small development board. Basically, this board does not have a sound card or an actual speaker. So I thought, I can use the dummy soundcard provided by the linux kernel by calling out modprobe snd-dummy. Right now, I'm still testing it in my PC so to simulate the board's environment. I have configured the .asoundrc file and create a new dummy pcm by putting the lines below onto my .asoundrc file.
pcm.dummy{ type hw card Dummy }
So, I change the above ecample code, so it listens to this new dummy pcm rather than the 'default'. Like this :
rc = snd_pcm_open(&handle, "dummy", SND_PCM_STREAM_CAPTURE, 0); Supposedly, the above modification would allow me to record from this dummy pcm, no? I do this by playing a song, using aplay -f cd -D dummy song.wav and at the same time, execute the above example. As expected, no sound was coming out from my speaker. When the program finished recording for 5 seconds, I play back the result, but all i heard was just noise.
Of curiousity, I try using file plugins. I modify my .asoundrc file like this:
pcm.dummy{ type plug slave{ pcm file format S16_LE channels 2 rate 44100 } }
pcm.file{ type file slave{ pcm d } file /home/mydir/out.raw }
pcm.d{ type hw card Dummy }
Then i called aplay -f cd -D dummy song.wav again, well.. still no sound coming out from the speaker, but it does output the raw audio file into my /home/mydir/out.raw file. I play the out.raw using aplay -f cd /home/mydir/out.raw it's flawless.
But I can't use this for my implementation. What I need is actually a way to read raw audio data (or stream) from the dummy sound card, to a buffer inside my program. I need this because I'm going to stream the buffer to my server, so I can listen the sound from my server. I can't afford to use the file plugin approach, basically because later on, in my development board, i won't have that much space.
So, the question is: capturing raw audio data from a dummy soundcard, is this possible? I'm pretty sure that if the file plugin works, means that the raw audio data is there. It's just that i'm probably doing a wrong approach to read it. Hence, needs explanation and help..
Please help me.. :(
Thank you so much for reading my long request.
At Thu, 5 Mar 2009 08:34:03 -0800 (PST), Santo Chow wrote:
Hi everyone :)
I'm currently assigned to a task that requires me to capture raw audio stream from a dummy sound card. Is this even possible?
You can use aloop driver in alsa-driver tree for such a purpose. Then you can capture streams freely from the currently running playbacks.
Takashi
Takashi,
Thanks for the great response. I've searched for this aloop documentation, but no luck :(. I've managed to follow the wiki, and modprobbed the snd-aloop. Now i'll experiment a little with the aloop. If you have further guide about this aloop, can you please send to me? Thanks.. you've made my day :D
Santo
________________________________ From: Takashi Iwai tiwai@suse.de To: Santo Chow santo_chow@yahoo.com Cc: alsa-devel@alsa-project.org Sent: Tuesday, March 10, 2009 11:25:03 PM Subject: Re: [alsa-devel] Need help on getting raw audio stream from a dummy sound card
At Thu, 5 Mar 2009 08:34:03 -0800 (PST), Santo Chow wrote:
Hi everyone :)
I'm currently assigned to a task that requires me to capture raw audio stream from a dummy sound card. Is this even possible?
You can use aloop driver in alsa-driver tree for such a purpose. Then you can capture streams freely from the currently running playbacks.
Takashi
Hi Takashi,
I have followed your suggestion and now i'm faced with another problem. So, right now, i have a Loopback soundcard as my default. My .asoundrc looks like this:
pcm.!default{ type hw card 1 }
Card 0 is my actual soundcard (that can actually produce sound). Card 1, when i checked on the /proc/asound/cards actually pointing to Loopback card. So right now, the way i test the card 1, is to call arecord from card 1, and play it to card 0. Right now, i'm still developing this in my ubuntu PC.
so i ran this arecord -f cd -D hw:1,1 | aplay -f cd -D hw:0
in one terminal, and in the other terminal i can play mplayer, watching youtube, etc.. and the sound would come out nicely. (Thanks to all of your efforts, nevertheless)
But I notice that, when i play mplayer, then i open a web-browser, and surf youtube, the sound from youtube is gone. But if i close the browser, close the mplayer, then reopen the browser, go to youtube and play a video, i can hear the sound nicely. but then, if during the time i start mplayer, it will complain about 'no sound'. Turns out, I have to use dmix. So, i modify my .asoundrc like this:
pcm.!default { type plug slave.pcm "dmixer" }
pcm.dmixer { type dmix ipc_key 1025 slave { pcm "hw:0,0" rate 44100 } bindings {
0 0 1 1 } } i put 'pcm "hw:0,0" ' over there, because i want to make sure that this setting works with my actual sound card first. If it works with my card 0, it should work with my card 1. with the above .asoundrc file, i can play multiple sound from different application at the same time. I even tried to remove the "bindings" tag, and it still able to play multiple sound very well. so i guess, this should work on my card 1.
then i change the .asoundrc become like this again:
pcm.!default { type plug slave.pcm "dmixer" }
pcm.dmixer { type dmix ipc_key 1025 slave { pcm "hw:1,1" period_time 0 period_size 881 buffer_size 3524 rate 44100
} }the value for perio_time, period_size, and buffer_size have been adjusted by me to suits my hardware requirement. This is the setting that works on my machine. It's just that, in the end, I'm still ended up with one sound at a time. I can't run mplayer + youtube at the same time. I can only run one of them. And furthermore, if i just paused the mplayer, the audio device is still locks. It will be good enough if someone can hint me a way to unlock the audio device.
So, what i want to ask is.. can this Loopback card handle more than 1 sound at a time? Have anyone tried this before? I have tried changing the value of .asoundrc, switching the slave pcm to pcm "hw:1,0" (not working) pcm "hw:1" (works, but only 1 sound too). Any idea guys?
Santo
________________________________ From: Takashi Iwai tiwai@suse.de To: Santo Chow santo_chow@yahoo.com Cc: alsa-devel@alsa-project.org Sent: Tuesday, March 10, 2009 11:25:03 PM Subject: Re: [alsa-devel] Need help on getting raw audio stream from a dummy sound card
At Thu, 5 Mar 2009 08:34:03 -0800 (PST), Santo Chow wrote:
Hi everyone :)
I'm currently assigned to a task that requires me to capture raw audio stream from a dummy sound card. Is this even possible?
You can use aloop driver in alsa-driver tree for such a purpose. Then you can capture streams freely from the currently running playbacks.
Takashi
participants (2)
-
Santo Chow
-
Takashi Iwai