Why is ALSA giving me xruns?
I am new to Linux and I am new to ALSA. I am working on an embedded Linux system with Kernel 2.6.16.11 (PPC arch). I am using ALSA 1.0.9a. I am trying to route audio from usb to a TLV codec. I figured the easiest way to do this for demo purposes was to just pipe arecord's output to aplay (e.g. arecord -D hw:1,0 -f dat | aplay). This works except for the audio pausing frequently and printing "underrun!!! (at least 120.315 ms long)" with a different value for the time in ms every time. I have played with the value of every parameter in arecord's options and all it does is change the value of time in ms (not linearly) and usually making the pausing worse. I thought this could be a clock drift problem so I tried just using arecord and I still get overruns. I have used multiple audio sources over usb and I have also used audio from a mic which uses a completely different driver so I don't think it has to do with my codec driver and I am using the generic snd-usb-audio driver from linux which seems to be working fine for what it needs to be doing. This leads me to believe that there is something wrong with arecord. When I studied the aplay.c source file from the alsa-utils package I found that whether I am using capture or playback (overrun or underrun) it is getting to the same snd_pcm_state which is xrun. Can anyone explain to me why it is getting in this xrun state and what I can possibly do to prevent this? Any insight would be useful, thanks.
|
I'd check the pipe. Check if you have the buffer full.
|
How can I check the pipe? Remember I am running with a limited command set on this embedded system.
|
while i'm not sure and the reasons for this can me a mind blowing pile of things
the alsa people have been making a mess of incorprating dmix into the "default" device settings lately so try to bypass dmix first i think try arecord with this -D plughw:0,0 |
I get the same result when I use both -D hw:1,0 and -D plughw:1,0
|
you said you tried al parameters so just YELL if i am rehashing.
alsa uses a ring buffer like a snake eating its tail so like you discovered overruns underuns are basically the same thing. i think it might have to do with the -r "rate" i see you are using the -f dat shortcut i'm sure you tried decreasing that but did you go all the way to the default -f U8 -c1 -r8000 and work your way up also might be quite possible to need to go faster beyond DAT seems crazy but might work also buffer size of course generally when you get overruns its because the audio hardware has slow throughput and requires a larger buffer. might be you need a smaller buffer if your usb hardware is very fast. just general setting to use would be -F2 --period-size=1024 --buffer-size=2052 some other common buffer size settings 16384 8192 4096 and common period size settings 128 512 2048 4096 might want to try -F0 as well good luck |
I changed the buffer and time settings to what you suggested and it did not help. For every format variation I get underruns when I try to pipe from arecord thru aplay, but interesting enough there is one variation where I do not get any overruns when I use arecord only to record to a file. For U8, 8kHz, Mono (Default) I can successfully record to a file, but the thing is I get an error of unsupported format when I use "arecord -D hw:1,0 tst.wav". It only works when I use "arecord -D plughw:1,0 tst.wav". I have tried to use the plug plugin on other formats as well and it does not help. This is very strange. If there are any other ideas, please enlighten me. Thanks for the help thus far!
|
and you have tried
arecord -D plughw:1,0 | aplay -D plughw:1,0 the alsa guys have temporarily created a bug in the default device. something about a timing issue with libao or something... alsa is soooooooo confusing |
ok I tried
arecord -D plughw:1,0 | aplay -D plughw:0,0 and I am still getting underruns. I had not tried the plug plugin for aplay so I thought that might work, but same result. are you familiar with ecasound? I am trying to incorporate ecasound into my build so that I can capture with that app instead of arecord to see if it is just that arecord has been written poorly. Because it makes no sense to me that I would get overruns when I am using arecord just to capture to a file... |
yes ecasound is good
i used to use it and a TK frontend to do multitrack recording and it worked flawlessly. might want to check this out as well http://www.opensourcepartners.nl/~costar/gramofile/ this might be one of those need a new version of alsa type things as well if it is as i suspect a buggy implementation of dmix. i have seen an awfull lot of people sudenly posting dmix problems since they did a "new" thing with it. |
There is something interesting that I noticed on Friday. If I use arecord | aplay and pass the same device -D plughw:x,x to both, then it works flawlessly. I have a driver that controls a TLV codec and if I record with a mic through it and playback to speakers through it then everything sounds good with no xruns. Similarly I have a Griffin iMic adapter to send/receive audio over usb and when I use the snd-usb-audio driver to record the audio from it and playback audio to the headphones on the output port then everything sounds good with no xruns. The problem occurs when I try and capture audio from usb and send the playback to the codec. I think that this tells me that there is not a timing issue, but possibly a buffer issue with the two drivers. Do the buffer sizes in both the snd-usb-audio and the codec driver have to be equal? What should I look for in these drivers?
|
be aware i don't know very much about what you are doing but you might want to try booting the kernel with CFQ I/O schedular.
it will give a more balanced sheduling without letting one or the other take over. you just have to ge the info out of the codec to the alsa buffer, you got to figure the usb can keep up ok. that would mean buffering playback more?? i'm trying to think if there is any way in the kernel to adjust (increase) the latency across the usb port ? for larger bursts and less hogging. try something like setpci -v -s 00:0b.0 latency_timer=ff where 00:0b.0 is the usb controller (look at lspci -v) or even changing overall pci latency setpci -v -d *:* latency_timer=ff im not so sure im alot of help -- what you are doing is a bit beyond my pay grade |
I found this thread on this forum: Alsa sound *jumpy*: alsa-space: xrun of at least 11.449 msecs. resetting stream
And I followed what they did and it definitely helped my problem. I did not have .asoundrc so I created it and added the text someone suggested. Now I can use arecord -Dplughw:1,0 -f dat | aplay -D default and the underrun timing is always under 0.5 ms. I can change the time value and the frequency of occurance by changing the period_size and buffer_size, but I can never get it to be fixed. The period_size has to be half of the buffer_size or less from the testing I have done thus far. The main thing seems to be either have a small buffer_size so that the underruns occur frequently, but only a small glitch in the sound constantly or a large buffer_size so that underruns are few and far between with perfect sound, but when they occur it is very noticable glitching and pausing. I would like to get the best of both worlds with good sound, but no constant glitches. Do you know anything about .asoundrc? |
only what i wrote there
foo_bar_foo was me in a previous incarnation on this board (got flamed alot and left for a while) might want to try not using the dmix plugin but rather going directly see if you can replace type dmix with type hw |
When I try simply replacing "type dmix" with "type hw" I get the error:
# arecord -D plughw:1,0 -f dat | aplay ALSA lib pcm_hw.c:1341:(_snd_pcm_hw_open) Unknown field ipc_key aplay: main:533: audio open error: Invalid argument When I comment out the ipc_key field I get the error: # arecord -D plughw:1,0 -f dat | aplay Recording WAVE 'stdout' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo ALSA lib pcm_hw.c:1341:(_snd_pcm_hw_open) Unknown field slave aplay: main:533: audio open error: Invalid argument The next thing I did was replace the entire pcm.dmixer portion of .asoundrc: Old .asoundrc pcm.dsp { type plug slave.pcm "dmixer" } pcm.!default { type plug slave.pcm "dmixer" } ctl.!default { type hw card 0 } pcm.dmixer { type dmix ipc_key 1024 slave { pcm "hw:0,0" period_time 0 # period_time 84000 # buffer_time 0 # buffer_time 3400000 # period_size 131072 # period_size 4096 period_size 512 # buffer_size 262144 # buffer_size 8192 # buffer_size 4096 buffer_size 2048 # rate 44100 rate 48000 } bindings { 0 0 1 1 } } ctl.dmixer { type hw card 0 } New .asoundrc pcm.dsp { type plug slave.pcm "dmixer" } pcm.!default { type plug slave.pcm "dmixer" } ctl.!default { type hw card 0 } pcm.dmixer { type hw card 0 } ctl.dmixer { type hw card 0 } When I tried this new .asoundrc the results were the same as when I just added -D hw:0,0 to the options of aplay. I still received underruns at around the same frequency at about 120 ms long. It seems that the dmix plugin is helping me out because the underruns are always under 0.5 ms long (usually about 0.026 ms) and much less noticable when I have a small buffer_size. What do you think that I should try next with this file? |
sorry about that. .
i should have gone and looked at the docs before i answered here are the syntax docs for the .asoundrc http://www.alsa-project.org/alsa-doc...m_plugins.html it seems the only other type of plugin to take the same type parameters is dshare and i think it uses the same mechanism. a couple of options are a part of dmix that i didn't use in my original (for sblive) file. channels INT might help to make only one channel also might want to bind only one channel ? bindings { # note: this is client independent!!! N INT # maps slave channel to client channel N } # this also one might do something ? slowptr BOOL # slow but more precise pointer updates } |
I tried the channels, slowptr, and I took out the bindings, but nothing made a difference. My .asoundrc now looks like:
pcm.!default { type plug slave.pcm "dmixer" } pcm.dmixer { type dmix ipc_key 1024 slave { pcm "hw:0,0" period_time 0 period_size 64 buffer_size 512 } } ctl.dmixer { type hw card 0 } I don't know if this means anything, but today I noticed something else weird about this problem. I tried using the default formats for arecord and aplay and for a minute or so it looked like I fixed it, but then I started seeing overruns. The weird thing is when I change only the rate to 8kHz I start to get overruns instead of underruns and there are much less. Even at 9kHz rate I get underruns just as frequent with the same time in (ms) as I do at 48kHz. I don't know if alsa actually samples at the exact rate that the user enters, but when I enter 8999Hz as the rate I get overruns just like at 8kHz. It must round down or something because why would it give my overruns at 8999Hz and underruns at 9000Hz? |
its very confusing so i don't want to mislead but all i know is (and thats not alot)
when you use dmix plugin (which is what you .asoundrc is doing) all alsa throughput is software resampled to the rate set by the dmix plugin. 48000Hz is the default unless you override in your .asoundrc this is so lots of different programs can use the sound at the same time all using the same rate. the conversion is a simple linear interpolation algorithm within alsa that is fast but creates some level of errors.that is ALSA using dmix internally converts everything to 1024 samples per period at 48kHz. ?? i think i'm not really sure whats going on with the settings in aplay, arecord in relationship to alsa and dmix. I thought in the begining of this thread by using hwplug and setting the buffers and rates we were bypassing any dmix/alsa involvement and setting parameters directly. perhaps within aplay arecord you are getting software conversion then resampled again in dmix to 48000. for those of us who use alsa for audio processing we compile alsa against a library called libsamplerate so we get an extra alsa rate plugin rate 48000 } rate_converter "samplerate_best" } this uses a different better algorithm to do the conversion but its strictly a quality thing. what i do is mostly just use 44100 so no conversion is needed i think the equation gets so compilated because the drivers may also be using their own rates. hardware can be using interupt ticks that can be set in the kernel to run at vastly different rates. the whole thing makes my head spin. its a wonder any of it works at all ! |
I have been looking into using Jack Audio Connection Kit. Do you know anything about JACK? I have already downloaded JACK 0.103.0, but I am not quite sure what to do from here. I need to cross compile on an i386 arch host for a PPC arch target. The README does not tell me how to configure, build, and install.
|
All times are GMT -5. The time now is 10:02 AM. |