Help with ALSA application development

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello:

I am still trying to write my own basic application that captures and plays
audio. I am working in an embedded linux environment and have the drivers
working well. I can use arecord/aplay without any problem. However, I have
been trying to follow some web examples for simple capture and playback
without any success. Does anyone know of some sample code for S8 formatted,
8k rate capture and playback. I think my problem is two-fold.

First is getting the hw-params set correctly. I have a function call that
sets the interface up. I am trying to use the same params that aplay -v
returns to me, but perhaps I have them wrong somehow.

Secondly is buffering the samples. I am not sure I have that correct. Does
anyone have some pointers on that?

I have attached my code. If anyone has some time and insight into this, I
would greatly appreciate it. Thanks.

Paul
/* GRH Audio Program
 *
 * Author: Paul Kavan, Project Engineer
 * Date: July 3, 2007
 */

#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>

/*************************************
 * Variable and Function Declarations 
 *************************************/
long                    loops;
unsigned int            val;
int                     nchannels = 1;
static snd_pcm_uframes_t period_frames = 1000;
static snd_pcm_uframes_t buffer_frames = 4000;
static unsigned         period_time = 125000;
unsigned int            sample_rate = 8000;
char                    *buffer;
snd_pcm_t               *pcm_handle;

int grh_capture(void);
int grh_playback(void);
int grh_pcm_config(void);

/*************************************
 * Main Program Section
 *************************************/
int main(void)
{
  int err;
  //Testing routine
  printf("Press enter to begin recording\n");
  getchar();
  err = grh_capture();
  printf("Audio Captured. Press enter to playback\n");
  while(1){
  getchar();
  err = grh_playback();
  printf("Audio playback complete. Again?\n");}
  return 0;
}

/*************************************************
 * Capture Function:
 * This fuction should capture audio from the PCM 
 * and store it in a buffer for transmission
 *************************************************/
int grh_capture(void)
{
  int err;

  /************************************
   * Open the pcm interface
   ************************************/
  if ((err = snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_CAPTURE, 0)) < 0)
  {
    fprintf(stderr, "Failed to open input audio device %s: %s\n", "default", snd_strerror(err));
    exit(1);
  }

  /************************************
   * Configure the devices
   ************************************/
  err = grh_pcm_config();

  /******************************************
   * Perform capture and store to buffer
   ******************************************/
  while(loops > 0) {
    loops--;
    if ((err = snd_pcm_readi (pcm_handle, buffer, period_frames)) != period_frames) {
      fprintf (stderr, "read from audio interface failed (%s)\n",snd_strerror (err));
      exit (1);
    }
  }

  /*******************************************
   * Close PCM interface and exit
   *******************************************/
  snd_pcm_close (pcm_handle);
  return 0;
}

/************************************************
 * Playback Function:
 * This function should retrieve audio from a 
 * buffer and send it to the PCM for playback
 ************************************************/
int grh_playback(void)
{
  int err;

  /************************************
   * Open the pcm interface
   ************************************/
  if ((err = snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) 
  {
    fprintf(stderr, "Failed to open output audio device %s: %s\n", "default", snd_strerror(err));
    exit(1);
  }

  /************************************
   * Configure the devices
   ************************************/
  err = grh_pcm_config();

  /******************************************
   * Playback from buffer
   ******************************************/
  while (loops > 0) {
    loops--;
    if ((err = snd_pcm_writei (pcm_handle, buffer, period_frames)) != period_frames) {
      fprintf (stderr, "write to audio interface failed (%s)\n",snd_strerror (err));
      exit (1);
    }
  }

  /*******************************************
   * Close PCM interface and exit
   *******************************************/
  snd_pcm_close (pcm_handle);
  return 0;
}


/*************************************************
 * PCM configure function
 * This function configures the pcm for an audio
 * operation. Most params stay the same, the only 
 * difference is in the pcm_handle
 *************************************************/
int grh_pcm_config(void)
{
  int err;
  snd_pcm_hw_params_t *hw_params;
    
  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 (pcm_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 (pcm_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 (pcm_handle, hw_params, SND_PCM_FORMAT_S8)) < 0) {
    fprintf (stderr, "cannot set sample format (%s)\n",snd_strerror (err));
    exit (1);
  }

  if ((err = snd_pcm_hw_params_set_rate_near (pcm_handle, hw_params, &sample_rate, 0)) < 0) 
  {
    fprintf (stderr, "Cannot set sample rate (%s)\n",snd_strerror (err));
    exit (1);
  }

  if ((err = snd_pcm_hw_params_set_period_size_near(pcm_handle, hw_params, &period_frames, 0)) < 0)
  {
    fprintf (stderr, "Cannot set period size (%s)\n",snd_strerror (err));
    exit (1);
  }

  	
  if ((err = snd_pcm_hw_params_set_period_time_near(pcm_handle, hw_params, &period_time, 0)) < 0)
  {
    fprintf (stderr, "cannot set period time (%s)\n",snd_strerror (err));
    exit (1);
  }

  if ((err = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hw_params, &buffer_frames)) < 0)
  {
    fprintf (stderr, "cannot set buffer_size (%s)\n",snd_strerror (err));
    exit (1);
  }

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

  if ((err = snd_pcm_hw_params (pcm_handle, hw_params)) < 0) {
    fprintf (stderr, "cannot set parameters (%s)\n",snd_strerror (err));
    exit (1);
  }

  snd_pcm_hw_params_free (hw_params);

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

  /* Use a buffer large enough to hold one period */
  snd_pcm_hw_params_get_period_size(hw_params, &period_frames, 0);
  buffer = (char *) malloc(period_frames);

  /* We want to loop for 5 seconds */
  snd_pcm_hw_params_get_period_time(hw_params, &val, 0);
  loops = 5000000 / val;
  return 0;
}
_______________________________________________
Alsa-devel mailing list
Alsa-devel@xxxxxxxxxxxxxxxx
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux