All of lore.kernel.org
 help / color / mirror / Atom feed
From: Carlo Wood <carlo@alinoe.com>
To: tsw@johana.com
Cc: alsa development <alsa-devel@lists.sourceforge.net>
Subject: Re: I thought it would simple....
Date: Wed, 23 Jul 2003 13:07:50 +0200	[thread overview]
Message-ID: <20030723110750.GA2492@alinoe.com> (raw)
In-Reply-To: <20030723065449.40812.qmail@web21508.mail.yahoo.com>

[-- 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;
}

  reply	other threads:[~2003-07-23 11:07 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-07-23  6:54 I thought it would simple Tom Watson
2003-07-23 11:07 ` Carlo Wood [this message]
2003-07-24  5:03   ` Tom Watson
2003-07-24 13:48     ` Takashi Iwai
2003-08-11 21:30       ` Tom Watson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030723110750.GA2492@alinoe.com \
    --to=carlo@alinoe.com \
    --cc=alsa-devel@lists.sourceforge.net \
    --cc=tsw@johana.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.