Google Answers Logo
View Question
 
Q: alsa ( No Answer,   0 Comments )
Question  
Subject: alsa
Category: Computers > Programming
Asked by: ignorant-ga
List Price: $20.00
Posted: 12 Jan 2005 22:00 PST
Expires: 11 Feb 2005 22:00 PST
Question ID: 456462
snd_pcm_readi returns -11
what does -11 mean as an error code?
documentation mentions -EBADFD, -EPIPE, -ESTRPIPE, but neither specifies
what those stand for (as in what patterns of bits) nor says anything about -11

I have better ways of generating -11, so I would rather call snd_pcm_readi
to read bytes... what magic is required for that to happen, and why do
I get -11?

An answer (to what magic...) would be a MINIMAL C program that actually
gets snd_pcm_readi to work in such a manner that the bytes read are stored
in a file (and when I cat the file, I really do see the bytes).

Clarification of Question by ignorant-ga on 12 Jan 2005 22:58 PST
I had been unable to use snd_pcm_state() to determine the PCM state
because the documentation I was reading mispelled macro names which
resulted in an inability to compile.

I am past that now and have discovered that once the state is
"SND_PCM_STATE_PREPARED" then executing snd_pcm_start() does manage to get
snd_pcm_readi to read bytes (sort of), but the data seems to be garbage;
the signal into line in (of the sound card) is from a guitar, but the
captured .wav file (produced via snd_pcm_readi) plays as nothing but static.

Clarification of Question by ignorant-ga on 12 Jan 2005 23:23 PST
By the way, the misspelling was "SND_PCM_STATE_PREPARE" 
(http://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html)
but it needs to be "SND_PCM_STATE_PREPARED".

moving on, I should be able to learn enough with a debugger 
(hope springs eternal) if I could get aplay.c to compile
( -gdwarf-2 -g3 ), BUT where do I find aconfig.h?

Clarification of Question by ignorant-ga on 13 Jan 2005 07:44 PST
I know why I couldn't find aconfig.h
In alsa-utils-1.0.8/include one finds aconfig.h.in
Evidently aconfig.h is a generated file.

moving on,
gcc  -gdwarf-2 -g3 -o aplay aplay.c  -I/usr/local/include -lm -lasound 
is successful, so now maybe I can sort out my problems with capture by
using the debugger to probe this example app.

Clarification of Question by ignorant-ga on 13 Jan 2005 17:09 PST
Ok, so looking at the source for aplay.c indicates that if one does

cp aplay arecord

then I should be able to record; man arecord indicates that 

arecord -d 10 -f cd -t wav -D copy foobar.wav

will record.  Of course it doesn't, and generates error
messages instead:

ALSA lib pcm.c:1972:(snd_pcm_open_noupdate) Unknown PCM copy
arecord: main:507: audio open error: No such file or directory

Googling around indicates that one should leave out the -D option,
but (you guessed it) whereas

arecord -d 10 -f cd -t wav  foobar.wav 

does produce a wave file, it contains nothing but silence.  I tried 
successfully emerged media-sound/alsaplayer (I run gentoo), but of course
that also produces only wave files of silence.

My original question -- and goal -- was to capture with snd_pcm_readi,
but now I will settle for someone telling me how to make arecord actually
record!

Clarification of Question by ignorant-ga on 13 Jan 2005 17:48 PST
ok, so alsamixer displays a variety of inputs for capture,
and since I am plugged into line, I naively supposed enabling
line for capture (via the space bar) was appropriate...
silly me:  I need the input I am plugged into to show up
as being DISABLED, and I need something called "mix mono"
to be enabled... then arecord works (damn strange world!).

So now perhaps my debugging adventure (tracing the execution
of arecord -- which is simply aplay by a different name)
will shed light on snd_pcm_readi

If anyone is interested, feel free to beat me to the punch
(i.e., make a minimal C program that gets snd_pcm_readi to work)
and the money is yours.

If not, when I eventually succeed I'll post an answer.

Clarification of Question by ignorant-ga on 15 Jan 2005 12:18 PST
As you will see in the code below, there are a mess of calls in pre_record() of
the form snd_pcm_...  Honestly, I have little clue about why; they seem to be
needed to make recording work.  If anyone can give an in depth explanation of
what is going on with them, the money is yours --- and i'm increasing it to $20

Following is a reasonably "minimal" program that records (I promised to post):

#define _GNU_SOURCE
#include <stdlib.h>
#include <alsa/asoundlib.h>
#include "formats.h"

static struct 
{
  snd_pcm_format_t format;
  unsigned int     channels;
  unsigned int     rate;
} Hwparams = {SND_PCM_FORMAT_S16_LE, 2, 44100};

static snd_pcm_uframes_t Frames;
static size_t            Bytes_per_frame;
static snd_pcm_t        *Handle;

void pcm_read_frames(u_char *d)
{
  long r, s = Frames;

  while (s > 0) {
    if ((r = snd_pcm_readi(Handle,d,s)) > 0) {
      s -= r;
      d += r * Bytes_per_frame;
    } else if (r == -EAGAIN || ((r < s) && !(r < 0)))
      snd_pcm_wait(Handle,1000);
  }
}

#define Sz(x) sizeof(x)

void pre_record(int fd, long bytes)
{
  long                 buffer_time = 500000, period_time = buffer_time/4; 
  snd_pcm_uframes_t    buffer_frames, buffer_size, period_frames, xfer_align;
  WaveChunkHeader      wch, ch = {WAV_FMT,16};
  WaveHeader           h;
  WaveFmtBody          f;
  snd_pcm_hw_params_t *params; 
  snd_pcm_sw_params_t *swparams;

  snd_pcm_open(&Handle,"default",SND_PCM_STREAM_CAPTURE,0);

  wch.type     = WAV_DATA;
  wch.length   = bytes & 0x7fffffff;
  h.magic      = WAV_RIFF;
  h.length     = bytes+Sz(WaveHeader)+Sz(WaveChunkHeader)+Sz(WaveFmtBody)+Sz(WaveChunkHeader)-8;
  h.type       = WAV_WAVE;
  f.format     = WAV_PCM_CODE;
  f.modus      = Hwparams.channels;
  f.sample_fq  = Hwparams.rate;
  f.byte_p_spl = Hwparams.channels*snd_pcm_format_physical_width(Hwparams.format)/8;
  f.byte_p_sec = f.byte_p_spl*Hwparams.rate;
  f.bit_p_spl  = 16;
    
  write(fd, &h , Sz(WaveHeader)     );
  write(fd, &ch, Sz(WaveChunkHeader));
  write(fd, &f , Sz(WaveFmtBody)    );
  write(fd, &wch, Sz(WaveChunkHeader));

  snd_pcm_hw_params_alloca(&params);
  snd_pcm_sw_params_alloca(&swparams);
  snd_pcm_hw_params_any(Handle,params);
  snd_pcm_hw_params_set_access(Handle,params,SND_PCM_ACCESS_RW_INTERLEAVED);
  snd_pcm_hw_params_set_format(Handle,params,Hwparams.format);
  snd_pcm_hw_params_set_channels(Handle,params,Hwparams.channels);
  snd_pcm_hw_params_set_rate_near(Handle,params,&Hwparams.rate, 0);
  snd_pcm_hw_params_set_period_time_near(Handle,params,(unsigned *)&period_time,0);
  snd_pcm_hw_params_set_buffer_time_near(Handle,params,(unsigned *)&buffer_time,0);
  snd_pcm_hw_params(Handle,params);
  snd_pcm_hw_params_get_period_size(params,&Frames,0);
  snd_pcm_hw_params_get_buffer_size(params,&buffer_size);
  snd_pcm_sw_params_current(Handle,swparams);
  snd_pcm_sw_params_get_xfer_align(swparams,&xfer_align);
  snd_pcm_sw_params_set_sleep_min(Handle,swparams,0);
  snd_pcm_sw_params_set_avail_min(Handle,swparams,Frames);
  snd_pcm_sw_params_set_start_threshold(Handle,swparams,1);
  snd_pcm_sw_params_set_stop_threshold(Handle,swparams,buffer_size);
  snd_pcm_sw_params_set_xfer_align(Handle,swparams,xfer_align);
  snd_pcm_sw_params(Handle,swparams);
}

void post_record(int fd, long bytes)
{
  WaveChunkHeader cd          = {WAV_DATA, bytes & 0x7fffffff};
  off64_t         seek        = Sz(WaveHeader) + Sz(WaveChunkHeader) +
Sz(WaveFmtBody);
  u_int           wave_size   = bytes + 2*Sz(WaveChunkHeader) +
Sz(WaveFmtBody) + 4;

  lseek64(fd,4   ,SEEK_SET); write(fd, &wave_size, 4                  );
  lseek64(fd,seek,SEEK_SET); write(fd, &cd       , Sz(WaveChunkHeader));
  close(fd);
  snd_pcm_close(Handle);
  snd_config_update_free_global();
}

main(int argc, char *argv[])
{
  char *audiobuf;  long bytes, c, fd, time;  sscanf(argv[2],"%d",&time);

  fd    = open64(argv[1], O_WRONLY|O_CREAT|O_TRUNC, 0644);
  bytes = time*snd_pcm_format_size(Hwparams.format,
Hwparams.rate*Hwparams.channels);

  pre_record(fd,bytes);  // side effect : sets Frames

  Bytes_per_frame = Hwparams.channels*snd_pcm_format_physical_width(Hwparams.format)/8;
  audiobuf        = malloc(Frames*Bytes_per_frame);
  c               = bytes;

  do
    pcm_read_frames(audiobuf);
  while (0 < (c -= write(fd,audiobuf,Frames*Bytes_per_frame)));

  post_record(fd,bytes);
  free(audiobuf);
  return 0;
}
// gcc  -gdwarf-2 -g3 -o m m.c  -I/usr/local/include -lm -lasound
Answer  
There is no answer at this time.

Comments  
There are no comments at this time.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy