ALSA sound cut short (gcc)

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
Hello all,

I'm trying to generate a simple beep, and am heavily basing it on an example  
found here:

http://www.linuxjournal.com/article/6735?page=0,0 Listing 3. Simple Sound  
Playback

I've removed the reading from stdin and replaced it with filling the buffer  
with a simpel square wave.

The problem is that when I set a sample rate of 8000 (instead of 44100*) the  
sound only lasts for just less than a single second, instead of the in the  
code specified 5.   I've checked both the "period time" (32 ms) as well as  
the "loop" count (156), and it all adds up to aprox. 5 sec.

*not sure if 44100 has the same problem, just that is was /very/ noticable  
using 8000.

Inserting a "snd_pcm_nonblock(handle,0)" before the "snd_pcm_drain(handle)"  
doesn't seem to change anything.    However, putting a long-enough  
"usleep( )" before the above "snd_pcm_drain( )" does show that the written  
sound is indeed 5 seconds long (the beep ends some time before the time  
delta* code is executed and printed)

*times are retrieved using "gettimeofday( )".

Remark: moving the delay to /after/ "snd_pcm_drain( )" (to see if the  
"snd_pcm_close( )" was maybe to blame) still cuts the sound short.   No idea  
why though.

Question: How do I make the program wait until the full length of the  
written sound has been played - without resorting to throwing some  
best-guess "usleep( )" hacks into into it I mean.   In other words: what is  
missing from the example program I've been using ?

Regards,
Rudy Wieser



Re: ALSA sound cut short (gcc)
Hi Rudy,

I see you've not had any response to your query. I'm not surprised. I  
don't think there are many people who have programmed the ALSA interface,  
and you have probably found there are not many tutorials on how to use it.

20 years or more ago I wrote a set of linux programs to generate the sort  
of signals a traditional lab signal generator would do. This was before  
ALSA, the kernel sound system then being the Open Sound System (OSS). It  
proved fairly easy to use. When ALSA came along, I looked at converting  
the programs, but it is Soooo.... complicated :-( and back then there was  
even less tutorial or introductory articles. So I gave up. You just might  
have got me interested in trying again.  

I hope you have made progress.

Jim

Quoted text here. Click to load it

Re: ALSA sound cut short (gcc)
Jim,

Quoted text here. Click to load it

Indeed. :-\

Quoted text here. Click to load it

Not ?   In that case, how does everybody else get user-defined sounds from  
their speakers ?    Is there another approach available ?

Quoted text here. Click to load it

Indeed again.   Some code snippets, a few "compile this" programs, and a  
list of pcm related functions.  Thats about it.

Quoted text here. Click to load it

The basic setup, as presented in that linke I provided, looks fairly simple  
to me.  Its just that when I make small changes (like changing the sample  
rate) it refuses to work (change) in a way I can make sense of. :-\

Quoted text here. Click to load it

So ?    You will have the solution for me tomorrow ? :-D (yes, that was a  
joke.  No, really :-) )

Quoted text here. Click to load it

Just this morning I tried some super-simple code using  
"snd_pcm_set_params( )" and a single buffer (  
https://stackoverflow.com/questions/40399046/how-to-play-short-tones-with-alsa )  
and found out that by lowering with the latency parameter value (the last  
one) I could get the same "cut short" effect my origionally mentioned code  
suffers from.

That made me think that maybe the internal ALSA buffer empties before a new  
set of data (my programs buffer) is written into it ...    Which is as far  
as I currently got.

Though no idea why, when I put a seconds long "usleep( )" before the  
"snd_pcm_drain( )", the whole sound is played without me hearing any kind of  
hickups.


And again, if you know of another, more dependable way to generate sounds in  
a C program than I would really like to know (as in a different API).

Regards,
Rudy Wieser

P.s.
I tried to set a bigger internal buffer  
(snd_pcm_hw_params_set_buffer_size_near( ) ), but could not get it to change  
from 32768.



Re: ALSA sound cut short (gcc)
On Fri, 3 Jan 2020 12:49:36 +0100

Quoted text here. Click to load it

ALSA is quite complicated at first. It's some time since I've worked on it,
but this is what I found out.

It is a series of negotiations. You can't just say I want 2 channels at 16bit,
for example. You make a request, and based on the hardware driver and ALSA's
internal capabilities you are told what you've got.

Number of channels is a particular GOTCHA as it seems you'll usually get back
whatever is available regardless of what you ask for so you have to watch out
for buffer sizes, and channel numbers.

Also, 16bit usually seems to be done as interleaved short integers, which means
you have to pair up adjacent channels (with one of the 16bit shifted).

HTH

--  
W J G


Re: ALSA sound cut short (gcc)
Folderol,

Quoted text here. Click to load it
[snip]

Setting up the whole thing doesn't seem to be creating any kind of problems.

And even though the code in the link I provided doesn't do a lot of error  
checking it does use the values returned by ALSA to both determine the size  
of the programs buffer as well as how many times it should send it.

Its just that I have zero idea why the sound gets cut short, even though  
inserting a seconds long usleep( ) just before the snd_pcm_drain( ) call  
shows that the whole length of sound is there.

Regards,
Rudy Wieser



Re: ALSA sound cut short (gcc)
On Fri, 3 Jan 2020 15:38:15 +0100

Quoted text here. Click to load it

Does it return the same number of channels as you want to send? If not you need
to work out *when* to actually send them!

Quoted text here. Click to load it

Alternatively, suggests a periods V buffersize issue to me.
I can't remember for sure, but I think ALSA runs 2 periods per buffer, so one
half of the buffer is played while you send to the other half, so if your
sample is longer than 1/2 buffer you'll lose the rest.

--  
W J G


Re: ALSA sound cut short (gcc)
Folderol,

Quoted text here. Click to load it

Yes, two.


Thats not what the code I linked to (in my initial message) seems to  
indicate.

And as far as I know "snd_pcm_writei( )" function will block until all  
frames are written (which some other, later found code (link also posted)  
seems to confirm)..

Besides, even if the code in the first link I've provided causes half of the  
frames to be dropped I should get two-and-a-half seconds worth (instead of  
five), not just shy of a single one.   Apart from me assuming that the  
"snd_pcm_writei( )" will than either return a different number of accepted  
frames than what gets provided, or throw an error - both of which are  
catched and displayed.

Next to that, I /do/ get the full five seconds worth of writes (even though  
I write as many frames as returned by the  
"snd_pcm_hw_params_set_period_size_near( )" call) - as long as I preceede  
"snd_pcm_drain( )" with a few seconds of "usleep( )".

That is part of the problem: I can not make head-or-tails of how/when the  
cut-off happens.   And no errors of any kind.

Regards,
Rudy Wieser



Re: ALSA sound cut short (gcc)
declaimed the following:

Quoted text here. Click to load it

    This description is very perplexing to me...

    A usleep() before the snd_pcm_drain() implies that the OS is during
something BEFORE you invoke the snd_pcm_drain() call. So focusing on that
call is a red-herring. It indicates, to me, that some call before the
usleep() needs to be investigated.

    Something like an asynchronous buffering operation which is returning
before the entire buffer has been transferred, and your subsequent
operations are interrupting/terminating the remaining transfer.

Just some random Google results...
https://github.com/raspberrypi/linux/issues/999
https://stackoverflow.com/questions/18034132/alsa-snd-pcm-drainhandle-the-stream-isnt-played-to-the-end


--  
    Wulfraed                 Dennis Lee Bieber         AF6VN
     snipped-for-privacy@ix.netcom.com    http://wlfraed.microdiversity.freeddns.org/

Re: ALSA sound cut short (gcc)
Dennis,

Quoted text here. Click to load it

I would hope so !   :-)

Quoted text here. Click to load it

Why do you think so ?    Because there is already sound before the  
snd_pcm_drain() is called ?   That doesn't seem strange to me, as I assume  
it notices its internal buffer being totally filled up, and thus starts to  
play that.

Quoted text here. Click to load it

I've posted the link to the code I've used, so please do tell which one you  
think is involved, as I'm at the end of my rope here (remember that I  
removed the reading from stdin and changed the bitrate to 8000).   FWI, the  
last-called function before snd_pcm_drain() is snd_pcm_writei().

I've also just tried to make the buffer (much) larger and smaller (ofcourse  
adjusting the loopcount too), but the sound kept playing for just a second  
...

Quoted text here. Click to load it

To me it feels like the internal ALSA buffer goes empty (due to task  
switching ?), causing the snd_pcm_drain() function to end the sound output  
and return - ignoring/discarding the rest of the data that is still waiting  
to be played.

Quoted text here. Click to load it

Found that one too.   But as it uses an usleep() where none should be  
present and no explanation is given (that I can see) I skipped it.

Quoted text here. Click to load it

Also found that one, and tried what happened when I included the  
"snd_pcm_nonblock(handle, 0)" call.  Alas, nothing changed.

Found a few others too, but no explanation or solution in sight.

Regards,
Rudy Wieser



Re: ALSA sound cut short (gcc)
Quoted text here. Click to load it

They use existing software.  

  system("aplay somesound.wav");

Yes I know :-(

The other way is hardware. Use a spare gpio pin to switch on and off a  
ceramic sounder.  

Jim

Re: ALSA sound cut short (gcc)
On Fri, 03 Jan 2020 18:07:55 +0000, Jim Jackson wrote:

Quoted text here. Click to load it
so take a look at the source code for a play
Quoted text here. Click to load it





--  
But Officer, I stopped for the last one, and it was green!

Re: ALSA sound cut short (gcc)
Alister,

Quoted text here. Click to load it

Like this one ?

https://www.alsa-project.org/alsa-doc/alsa-lib/_2test_2pcm_8c-example.html

or this one ?

https://raw.githubusercontent.com/bear24rw/alsa-utils/master/speaker-test/speaker-test.c

Even though they might work flawlessly* , they are far from being a  
simple/clear examples. :-(

*I'm not even sure of that, as the example I got (link in first post) works  
great - using a sample rate of 44100 ...

Regards,
Rudy Wieser



Re: ALSA sound cut short (gcc)
Jim,

Quoted text here. Click to load it
...

You got it. :-)

Quoted text here. Click to load it

Yeah, have been thinking of (something like) that too.   Needs extra  
hardware though (not much, but not always available).

And there is ofcourse my own "if some program can do it, why can't I ?"  
grumbling.  For some reason I now just have to try my damn best to battle  
ALSA to do my bidding.

Yeah, I know.   Stubbornness.  I'm cursed with it. :-(  :-)

Regards,
Rudy Wieser



Re: ALSA sound cut short (gcc)
On 03/01/2020 19:21, R.Wieser wrote:
Quoted text here. Click to load it
If its any consolati I too tried some code under alsa. It (alsa)was  
badly documented and illogical. I just looked at it, but I dont even  
understand what I wrote and its late.

Maybe I'll dig it up and see if it bears any relationship. It did work  
but at 44k frame rate - never tried anything else.


--  
The biggest threat to humanity comes from socialism, which has utterly  
diverted our attention away from what really matters to our existential  
We've slightly trimmed the long signature. Click to see the full one.
Re: ALSA sound cut short (gcc)
On Fri, 03 Jan 2020 23:57:14 +0000, The Natural Philosopher wrote:

Quoted text here. Click to load it

I agree the ALSA documentation is a mess - there are broken links in the  
documentation part of the website. the C library API documentation is a  
mess, but a quick glance shows that there seems to be some good stuff in:

http://www.volkerschatz.com/noise/alsa.html
  (describes the architecture and module map)

https://www.alsa-project.org/wiki/Asoundrc
  (describes the config files and where to find them)

.. and the example programs are worth a look too.


--  
Martin    | martin at
Gregorie  | gregorie dot org


Re: ALSA sound cut short (gcc)
Quoted text here. Click to load it

All four listings on that page work for me.

Quoted text here. Click to load it

So I have to wonder if you've introduced a bug in your code changes
which you have described but not shared.

Quoted text here. Click to load it

You might have more luck in a more general Linux group
(comp.os.linux.misc gets a fair amount of traffic) or a programming
group (comp.lang.c is active). But include your actual code.

I used a wrapper around "aplay" for ALSA sound playback when I made an
alarm clock. I fork a program that loops aplay for however long it takes
to play the sound file for one minute, while the parent program checks
the state of a GPIO input to detect silence button pushed. On push, it
then kills the child process.

Elijah
------
requires GPIO in both states at least once to handle either NO or NC switches

Re: ALSA sound cut short (gcc)
Eli,

Quoted text here. Click to load it

Thats strange to say the least: In the code I posted the link to I had to  
initialize the "dir" variable (to zero) to get rid of an initial delay (in  
the "snd_pcm_hw_params_set_rate_near( )" function).   Compiler differences ?  
(I'm using gcc)

Besides that, the code worked alright for me too.   Up until I changed the  
sample rate from 44100 to 8000 that is.  Than the sound became much shorter.

Quoted text here. Click to load it

I just re-started with the code I took from the link I posted, and changed  
the "val = 44100;" line into
val = 8000;
dir = 0;

Thats all I need to get the (much) shorter sound.

And just now, after re-adding the code to measure the time from the start of  
the loop until after "snd_pcm_drain()", I noticed that even with the  
origional bitrate of 44100 the sound now only goes for 4.3 seconds ...

Quoted text here. Click to load it

I have been thinking of that too, but I currently regard the problem as  
being ALSA, and possibly Raspberry Pi specific, not one of the language  
itself.

Regards,
Rudy Wieser



Site Timeline