Logo Search packages:      
Sourcecode: lebiniou version File versions  Download package

alsa.c

/*
 *  Copyright 1994-2011 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  lebiniou is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#include "context.h"


u_long id = 1228149210;
u_long options = BEQ_THREAD;


static snd_pcm_t *pcm_handle = NULL;
static snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;
static snd_pcm_hw_params_t *hwparams = NULL;
static char *pcm_name = "default";

static unsigned int rate = 4410, exact_rate;
static int size;
static snd_pcm_uframes_t frames = 512;
static int dir;

static char *data = NULL;


static void
init()
{
  printf("[+] using %s as capture device\n", pcm_name);

  snd_pcm_hw_params_alloca(&hwparams);

  if (snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0)
    xerror("error opening PCM device %s\n", pcm_name);
  else
    printf("[+] %s ready for capture\n", pcm_name);

  if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0)
    xerror("error configuring PCM device %s\n", pcm_name);
  else
    printf("[+] %s configured\n", pcm_name);

  if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
    xerror("error setting access mode\n");
  else
    printf("[+] access mode set\n");

  if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0)
    xerror("error setting format\n");
  else
    printf("[+] format set\n");

  exact_rate = rate;
  if (snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, 0) < 0)
    xerror("error setting rate\n");
  else
    printf("[+] setting format: wanted %dHz, got %dHz\n", rate, exact_rate);

  if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2) < 0)
    xerror("error setting channels\n");
  else
    printf("[+] channels set\n");

  if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &frames, &dir) < 0)
    xerror("error setting period size");
  else
    printf("[+] period size set\n");

  if (snd_pcm_hw_params(pcm_handle, hwparams) < 0)
    xerror("error setting HW params\n");
  else
    printf("[+] HW params set\n");

  /* Use a buffer large enough to hold one period */
  snd_pcm_hw_params_get_period_size(hwparams, &frames, &dir);
  size = frames * 4; /* 2 bytes/sample, 2 channels */

  data = malloc(size * sizeof(char));
  if (NULL == data)
    xperror("malloc");
}


void
create(Context_t *ctx)
{
  init();
  ctx->input = Input_new(frames);
}


void *
jthread(void *args)
{
  Context_t *ctx = (Context_t *)args;

  while (ctx->running) {
    short *in = (short *)data;

    while (snd_pcm_readi(pcm_handle, data, frames) < 0) {
      snd_pcm_prepare(pcm_handle);
      /* fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Overrun >>>>>>>>>>>>>>>\n"); */
    }
    
    if (!ctx->input->mute) {
      unsigned int idx = 0, n = 0;
      
      for (idx = 0; idx < frames; idx++) {
      ctx->input->data[A_LEFT][idx] = 
        (float)(((float)(in[n])) / (float)-SHRT_MIN);
      n++;
      ctx->input->data[A_RIGHT][idx] = 
        (float)(((float)(in[n])) / (float)-SHRT_MIN);
      n++;
      }
      
      /* Input_set() handles the thread locking */
      Input_set(ctx->input, A_STEREO);
    }
  }

  return NULL;
}


void
destroy(Context_t *ctx)
{
  Input_delete(ctx->input);
  xfree(data);
  snd_pcm_drain(pcm_handle);
  snd_pcm_close(pcm_handle);
}

Generated by  Doxygen 1.6.0   Back to index