All of lore.kernel.org
 help / color / mirror / Atom feed
* I thought it would simple....
@ 2003-07-23  6:54 Tom Watson
  2003-07-23 11:07 ` Carlo Wood
  0 siblings, 1 reply; 5+ messages in thread
From: Tom Watson @ 2003-07-23  6:54 UTC (permalink / raw)
  To: alsa development

I am attempting to write a "simple" audio playback program.  Well, I
thought it would be, but...
Somehow (thru strace) the 'snd_pcm_writei' call goes and eventually
does a system 'poll' call, but it doesn't return indicating that a
write is OK to do.
I've used similar parameters in 'aplay' and I see that it works.

The basis of the program I'm writing is the one described in _A
Tutorial on Using the ALSA API_
(http://equalarea.com/paul/alsa-audio.html), section entitled "A
Minimal Playback Program".

One thing I've noted:  Some of the data printed out by "snd_pcm_dump"
is different between my program and 'aplay'.  I suspect that there is a
clue somewhere, but what is the "magic"??

If necessary, I can provide the 'strace' or the output from
'snd_pcm_dump', but in the interest of brevity...

Any "great clue" would be appreciated.

Thanks.

=====
-- 
Tom Watson
tsw@johana.com

__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com


-------------------------------------------------------
This SF.net email is sponsored by: VM Ware
With VMware you can run multiple operating systems on a single machine.
WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the
same time. Free trial click here: http://www.vmware.com/wl/offer/345/0

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: I thought it would simple....
  2003-07-23  6:54 I thought it would simple Tom Watson
@ 2003-07-23 11:07 ` Carlo Wood
  2003-07-24  5:03   ` Tom Watson
  0 siblings, 1 reply; 5+ messages in thread
From: Carlo Wood @ 2003-07-23 11:07 UTC (permalink / raw)
  To: tsw; +Cc: alsa development

[-- Attachment #1: Type: text/plain, Size: 1699 bytes --]

I found that a better example for playback is
the 'pcm.c' file that you can find on the alsa site.
It contains many ways to deliver the data (a nice
sine) to your soundcard.  Playing with the parameters
gives some insight (more than reading the overall poor
documentation imho :().

Anyway - I "translated" the one you mention to C++;
it works for me.  I'll include it below.

Compile like:

g++ playback.cc -lasound

For me, this gives a lot of buffer overruns...
pcm.c doesn't suffer from that.

Note that I added:

dir = 0; // ??? According to valgrind, this value is USED (read) for a conditional jump!

Maybe that is a bug of alsa, maybe it is just badly
documented - but to be safe you should set that variable too.

On Tue, Jul 22, 2003 at 11:54:49PM -0700, Tom Watson wrote:
> I am attempting to write a "simple" audio playback program.  Well, I
> thought it would be, but...
> Somehow (thru strace) the 'snd_pcm_writei' call goes and eventually
> does a system 'poll' call, but it doesn't return indicating that a
> write is OK to do.
> I've used similar parameters in 'aplay' and I see that it works.
> 
> The basis of the program I'm writing is the one described in _A
> Tutorial on Using the ALSA API_
> (http://equalarea.com/paul/alsa-audio.html), section entitled "A
> Minimal Playback Program".
> 
> One thing I've noted:  Some of the data printed out by "snd_pcm_dump"
> is different between my program and 'aplay'.  I suspect that there is a
> clue somewhere, but what is the "magic"??
> 
> If necessary, I can provide the 'strace' or the output from
> 'snd_pcm_dump', but in the interest of brevity...
> 
> Any "great clue" would be appreciated.

-- 
Carlo Wood <carlo@alinoe.com>

[-- Attachment #2: playback.cc --]
[-- Type: text/plain, Size: 4746 bytes --]

#include <alsa/asoundlib.h>
#include <iostream>
#include <cstring>

int main(void)
{
  // Handle for the PCM device.
  snd_pcm_t* pcm_handle;

  // Playback stream.
  snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;

  // This structure contains information about
  // the hardware and can be used to specify the
  // configuration to be used for the PCM stream.
  snd_pcm_hw_params_t* hwparams;

  // Name of the PCM device, like plughw:0,0.
  // The first number is the number of the soundcard,
  // the second number is the number of the device.
  char const* pcm_name = "plughw:0,0";

  // Allocate the snd_pcm_hw_params_t structure on the stack.
  snd_pcm_hw_params_alloca(&hwparams);

  // Open PCM. The last parameter of this function is the mode.
  // If this is set to 0, the standard mode is used. Possible
  // other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC.
  // If SND_PCM_NONBLOCK is used, read / write access to the
  // PCM device will return immediately. If SND_PCM_ASYNC is
  // specified, SIGIO will be emitted whenever a period has
  // been completely processed by the soundcard.
  if (snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0)
  {
    std::cerr << "Error opening PCM device " << pcm_name << std::endl;
    return -1;
  }

  // Init hwparams with full configuration space.
  if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0)
  {
    std::cerr << "Can not configure this PCM device." << std::endl;
    return -1;
  }

  unsigned int rate = 22050;	// Sample rate.
  int exact_rate;		// Sample rate returned by snd_pcm_hw_params_set_rate_near.
  int dir;			// exact_rate == rate --> dir = 0
				// exact_rate < rate  --> dir = -1
				// exact_rate > rate  --> dir = 1
  int periods = 16;		// Number of periods.
  int periodsize = 1024;	// Periodsize (bytes).

  // Set access type. This can be either
  // SND_PCM_ACCESS_RW_INTERLEAVED or
  // SND_PCM_ACCESS_RW_NONINTERLEAVED.
  // There are also access types for MMAPed
  // access, but this is beyond the scope
  // of this introduction.
  if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
  {
    std::cerr << "Error setting access." << std::endl;
    return -1;
  }

  // Set sample format to 'Signed 16 bit Little Endian'.
  if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0)
  {
    std::cerr << "Error setting format." << std::endl;
    return(-1);
  }

  // Set sample rate.  If the exact rate is not supported
  // by the hardware, use nearest possible rate.
  dir = 0; // ??? According to valgrind, this value is USED (read) for a conditional jump!
  exact_rate = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, rate, &dir);
  if (rate != exact_rate)
  {
    std::cerr << "The rate " << rate << " Hz is not supported by your hardware.\n "
                 "==> Using " << exact_rate << " Hz instead." << std::endl;
  }

  // Set number of channels.
  if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2) < 0)
  {
    std::cerr << "Error setting channels." << std::endl;
    return -1;
  }

  // Set number of periods. Periods used to be called fragments.
  if (snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0)
  {
    std::cerr << "Error setting periods." << std::endl;
    return -1;
  }

  // Set buffer size (in frames). The resulting latency is given by
  // latency = periodsize * periods / (rate * bytes_per_frame).
  if (snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (periodsize * periods) >> 2) < 0)
  {
    std::cerr << "Error setting buffersize." << std::endl;
    return -1;
  }

  // Apply HW parameter settings to
  // PCM device and prepare device.
  if (snd_pcm_hw_params(pcm_handle, hwparams) < 0)
  {
    std::cerr << "Error setting HW params." << std::endl;
    return -1;
  }

  unsigned char* data;
  int pcmreturn;
  short s1, s2;
  int frames;

  data = (unsigned char*)malloc(periodsize);
  frames = periodsize >> 2;
  std::cout << "frames = " << frames << '\n';
  for (int l1 = 0; l1 < 100; ++l1)
  {
    for (int l2 = 0; l2 < frames; ++l2)
    {
      s1 = (l2 % 128) * 100 - 5000;  
      s2 = (l2 % 256) * 100 - 5000;  
      data[4 * l2] = (unsigned char)s1;
      data[4 * l2 + 1] = s1 >> 8;
      data[4 * l2 + 2] = (unsigned char)s2;
      data[4 * l2 + 3] = s2 >> 8;
    }
    while ((pcmreturn = snd_pcm_writei(pcm_handle, data, frames)) < 0)
    {
      if (pcmreturn == -EPIPE)
      {
	std::cout << "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>" << std::endl;
	snd_pcm_prepare(pcm_handle);
      }
      else
      {
        std::cout << "snd_pcm_writei: " << strerror(-pcmreturn) << '\n';
        break;
      }
    }
    std::cout << "pcmreturn = " << pcmreturn << '\n';
  }

  return 0;
}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: I thought it would simple....
  2003-07-23 11:07 ` Carlo Wood
@ 2003-07-24  5:03   ` Tom Watson
  2003-07-24 13:48     ` Takashi Iwai
  0 siblings, 1 reply; 5+ messages in thread
From: Tom Watson @ 2003-07-24  5:03 UTC (permalink / raw)
  To: Carlo Wood, tsw; +Cc: alsa development

[-- Attachment #1: Type: text/plain, Size: 2657 bytes --]

OK, here is more data.  The enclosed files are:
1) The "minimal playback program" described in the original message,
modified to clear the buffer, and do the "dump" of the parameters.  The
buffer size is lengthened a bit (maybe this makes a difference??)
2) The output of 'strace' on the program, it stops at the 'poll'
instruction (broken out with a ^c at the terminal).
3) A cut/pasted copy of the output sent to the terminal.  In
particular, it has the output from "snd_pcm_dump" which ought to help a
bit.

The source was compiled with 'cc simple.c -lasound -o simple'.
It was executed with './simple surround40'.

I think I'm doing everything OK, and if I solve this goodie (on the
simple program), I suspect tha I can solve the problem with my program.

P.S.  The sound card is a Turtle Beach Santa Cruz.  It can handle the 4
channel things OK (I used 'aplay' very nicely!!)

While the C++ program is nice, I'm not really into that.  It seemed to
work OK (as given).  My program is C, thus the enclosed files.

Maybe there is a solution out there.

Thanks to all.  ALSA is the way of the future!!

--- Carlo Wood <carlo@alinoe.com> wrote:
> I found that a better example for playback is
> the 'pcm.c' file that you can find on the alsa site.
> It contains many ways to deliver the data (a nice
> sine) to your soundcard.  Playing with the parameters
> gives some insight (more than reading the overall poor
> documentation imho :().
> 
<<<deletia>>>
> On Tue, Jul 22, 2003 at 11:54:49PM -0700, Tom Watson wrote:
> > I am attempting to write a "simple" audio playback program.  Well,
> I
> > thought it would be, but...
> > Somehow (thru strace) the 'snd_pcm_writei' call goes and eventually
> > does a system 'poll' call, but it doesn't return indicating that a
> > write is OK to do.
> > I've used similar parameters in 'aplay' and I see that it works.
> > 
> > The basis of the program I'm writing is the one described in _A
> > Tutorial on Using the ALSA API_
> > (http://equalarea.com/paul/alsa-audio.html), section entitled "A
> > Minimal Playback Program".
> > 
> > One thing I've noted:  Some of the data printed out by
> "snd_pcm_dump"
> > is different between my program and 'aplay'.  I suspect that there
> is a
> > clue somewhere, but what is the "magic"??
> > 
> > If necessary, I can provide the 'strace' or the output from
> > 'snd_pcm_dump', but in the interest of brevity...
> > 
> > Any "great clue" would be appreciated.
<<<deletia of C++ program...>>>

=====
-- 
Tom Watson
tsw@johana.com

__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com

[-- Attachment #2: simple.c --]
[-- Type: application/octet-stream, Size: 2474 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <alsa/asoundlib.h>
#define CHAN 4
#define BSIZ 4096	/* Number of frames */
main (int argc, char *argv[])
{
int i;
int err;
short buf[CHAN * BSIZ];
snd_pcm_t *playback_handle;
snd_pcm_hw_params_t *hw_params;
snd_output_t *log;              /* For the log goodie */

/* Just set it to something empty */
memset (buf, 0, sizeof(buf));
if ((err = snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
	fprintf (stderr, "cannot open audio device %s (%s)\n", 
	 argv[1], snd_strerror (err));
	exit (1);
	}
	   
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
	fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
	 snd_strerror (err));
	exit (1);
	}
			 
if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) {
	fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
	 snd_strerror (err));
	exit (1);
	}

if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
	fprintf (stderr, "cannot set access type (%s)\n",
	 snd_strerror (err));
	exit (1);
	}

if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
	fprintf (stderr, "cannot set sample format (%s)\n",
	 snd_strerror (err));
	exit (1);
	}

if ((err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, 44100, 0)) < 0) {
	fprintf (stderr, "cannot set sample rate (%s)\n",
	 snd_strerror (err));
	exit (1);
	}

if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, CHAN)) < 0) {
	fprintf (stderr, "cannot set channel count (%s)\n",
	 snd_strerror (err));
	exit (1);
	}

if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) {
	fprintf (stderr, "cannot set parameters (%s)\n",
	 snd_strerror (err));
	exit (1);
	}
err = snd_output_stdio_attach(&log, stderr, 0);
if (err < 0)
	{
	fprintf (stderr, "Can\'t do stdio attach (%d)\n", err);
	exit (1);
	}
snd_pcm_dump (playback_handle, log);
      
/* snd_pcm_hw_params_free (hw_params); */

if ((err = snd_pcm_prepare (playback_handle)) < 0) {
	fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
	 snd_strerror (err));
	exit (1);
	}

for (i = 0; i < 10; ++i) {
	if ((err = snd_pcm_writei (playback_handle, buf, BSIZ)) != BSIZ) {
		fprintf (stderr, "write to audio interface failed (%s)\n",
			 snd_strerror (err));
		exit (1);
		}
	}

snd_pcm_close (playback_handle);
exit (0);
}


[-- Attachment #3: simple.tr --]
[-- Type: application/x-troff, Size: 26330 bytes --]

[-- Attachment #4: simple.sout --]
[-- Type: application/octet-stream, Size: 1682 bytes --]

Multi PCM

Channel bindings:
0: slave 0, channel 0
1: slave 0, channel 1
2: slave 1, channel 0
3: slave 1, channel 1

Its setup is:
stream       : PLAYBACK
access       : RW_INTERLEAVED
format       : S16_LE
subformat    : STD
channels     : 4
rate         : 44100
exact rate   : 44100 (44100/1)
msbits       : 16
buffer_size  : 8192
period_size  : 8
period_time  : 181
tick_time    : 10000
tstamp_mode  : NONE
period_step  : 1
sleep_min    : 0
avail_min    : 8
xfer_align   : 8
start_threshold  : 1
stop_threshold   : 8192
silence_threshold: 0
silence_size : 0
boundary     : 1073741824

Slave #0: Hardware PCM card 0 'Sound Fusion CS46xx' device 0 subdevice 0

Its setup is:
stream       : PLAYBACK
access       : MMAP_INTERLEAVED
format       : S16_LE
subformat    : STD
channels     : 2
rate         : 44100
exact rate   : 44100 (44100/1)
msbits       : 16
buffer_size  : 8192
period_size  : 8
period_time  : 181
tick_time    : 10000
tstamp_mode  : NONE
period_step  : 1
sleep_min    : 0
avail_min    : 8
xfer_align   : 8
start_threshold  : 1
stop_threshold   : 8192
silence_threshold: 0
silence_size : 0
boundary     : 1073741824

Slave #1: Hardware PCM card 0 'Sound Fusion CS46xx' device 1 subdevice 0

Its setup is:
stream       : PLAYBACK
access       : MMAP_INTERLEAVED
format       : S16_LE
subformat    : STD
channels     : 2
rate         : 44100
exact rate   : 44100 (44100/1)
msbits       : 16
buffer_size  : 8192
period_size  : 8
period_time  : 181
tick_time    : 10000
tstamp_mode  : NONE
period_step  : 1
sleep_min    : 0
avail_min    : 8
xfer_align   : 8
start_threshold  : 1
stop_threshold   : 8192
silence_threshold: 0
silence_size : 0
boundary     : 1073741824

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: I thought it would simple....
  2003-07-24  5:03   ` Tom Watson
@ 2003-07-24 13:48     ` Takashi Iwai
  2003-08-11 21:30       ` Tom Watson
  0 siblings, 1 reply; 5+ messages in thread
From: Takashi Iwai @ 2003-07-24 13:48 UTC (permalink / raw)
  To: tsw; +Cc: alsa-devel

At Wed, 23 Jul 2003 22:03:25 -0700 (PDT),
Tom Watson wrote:
> 
> OK, here is more data.  The enclosed files are:
> 1) The "minimal playback program" described in the original message,
> modified to clear the buffer, and do the "dump" of the parameters.  The
> buffer size is lengthened a bit (maybe this makes a difference??)

in general, it'd better to specify proper period and buffer sizes in
hw_params.  (you can use *_near() for that purpose, too, in the case
the hardware doesn't support the request size.)

note that the configuration of buffer and period sizes is often
sensitive to the card type.  and they define the stability and the
latency of the application.  that's why many applications have options
to set up these things.

also, calling snd_pcm_prepare() is not necessary.  it's called
automatically after hw_params().  it's needed only after xrun/suspend
occurs.

many programs have the xrun recovery.  in the playback direction, if
a buffer underrun occurs, snd_pcm_writei() returns -EPIPE (and
-ESTRPIPE if the suspend occurs).  and ALSA drivers don't recover this
status automatically as default.  you need to call snd_pcm_prepare()
to recover the status. so,


Takashi


-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: I thought it would simple....
  2003-07-24 13:48     ` Takashi Iwai
@ 2003-08-11 21:30       ` Tom Watson
  0 siblings, 0 replies; 5+ messages in thread
From: Tom Watson @ 2003-08-11 21:30 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel

Sorry I could not get back to you...  Vacation and travel over 9 time
zones in the last 36 hours...

The soundcard appears to work quite nicely using 'aplay' (default
parameters, but device 'surround40').  I just want to get an idea of
what I'm doing that causes this problem.  The "sample" program OUGHT to
work, after all it is a "sample", isn't it...

Maybe there could be a "debugging" version of the library that is
similar to "strace" for the library calls.  Setting an environment
variable (output device file??) turns it on.  That way people could
analyze the flow thru the library, which is much less verbiage and raw
data then the true I/O calls.  Maybe an install option, or something in
the library.

Just an idea.  I suspect that if it were available, the sequence used
by 'aplay' would be immediately obvious (DUH!), and I could modify my
dumb program.

In any event, I'll try the suggestions to see what comes next. 
Anything is possible!!
--- Takashi Iwai <tiwai@suse.de> wrote:
> At Wed, 23 Jul 2003 22:03:25 -0700 (PDT),
> Tom Watson wrote:
> > 
> > OK, here is more data.  The enclosed files are:
> > 1) The "minimal playback program" described in the original
> message,
> > modified to clear the buffer, and do the "dump" of the parameters. 
> The
> > buffer size is lengthened a bit (maybe this makes a difference??)
> 
> in general, it'd better to specify proper period and buffer sizes in
> hw_params.  (you can use *_near() for that purpose, too, in the case
> the hardware doesn't support the request size.)
> 
> note that the configuration of buffer and period sizes is often
> sensitive to the card type.  and they define the stability and the
> latency of the application.  that's why many applications have
> options
> to set up these things.
> 
> also, calling snd_pcm_prepare() is not necessary.  it's called
> automatically after hw_params().  it's needed only after xrun/suspend
> occurs.
> 
> many programs have the xrun recovery.  in the playback direction, if
> a buffer underrun occurs, snd_pcm_writei() returns -EPIPE (and
> -ESTRPIPE if the suspend occurs).  and ALSA drivers don't recover
> this
> status automatically as default.  you need to call snd_pcm_prepare()
> to recover the status. so,
> 
> 
> Takashi
> 
> 
> -------------------------------------------------------
> This SF.Net email sponsored by: Free pre-built ASP.NET sites
> including
> Data Reports, E-commerce, Portals, and Forums are available now.
> Download today and enter to win an XBOX or Visual Studio .NET.
>
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/alsa-devel


=====
-- 
Tom Watson
tsw@johana.com

__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com


-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2003-08-11 21:30 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-23  6:54 I thought it would simple Tom Watson
2003-07-23 11:07 ` Carlo Wood
2003-07-24  5:03   ` Tom Watson
2003-07-24 13:48     ` Takashi Iwai
2003-08-11 21:30       ` Tom Watson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.