Example #1
0
File: main.c Project: texane/aspect
static int pcm_open(pcm_handle_t* pcm, const pcm_desc_t* desc)
{
  const snd_pcm_format_t fmt = SND_PCM_FORMAT_S16_LE;
  snd_pcm_stream_t stm;
  int err;

  if (desc->flags & PCM_FLAG_IN) stm = SND_PCM_STREAM_CAPTURE;
  else stm = SND_PCM_STREAM_PLAYBACK;

  err = snd_pcm_open
    (&pcm->pcm, desc->name, stm, SND_PCM_NONBLOCK);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_0);

  err = snd_pcm_hw_params_malloc(&pcm->hw_params);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_1);

  err = snd_pcm_hw_params_any(pcm->pcm, pcm->hw_params);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_2);

  err = snd_pcm_hw_params_set_access
    (pcm->pcm, pcm->hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_2);

  err = snd_pcm_hw_params_set_format(pcm->pcm, pcm->hw_params, fmt);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_2);

  err = snd_pcm_hw_params_set_rate
    (pcm->pcm, pcm->hw_params, desc->fsampl, 0);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_2);

  pcm->nchan = desc->nchan;
  pcm->wchan = (size_t)snd_pcm_format_physical_width(fmt) / 8;
  pcm->scale = pcm->nchan * pcm->wchan;

  err = snd_pcm_hw_params_set_channels
    (pcm->pcm, pcm->hw_params, desc->nchan);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_2);
  
  err = snd_pcm_hw_params(pcm->pcm, pcm->hw_params);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_2);

  err = snd_pcm_sw_params_malloc(&pcm->sw_params);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_2);

  err = snd_pcm_sw_params_current(pcm->pcm, pcm->sw_params);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_3);

#if 1
  err = snd_pcm_sw_params_set_avail_min
    (pcm->pcm, pcm->sw_params, 1024);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_3);
#endif

#if 1
  err = snd_pcm_sw_params_set_start_threshold
    (pcm->pcm, pcm->sw_params, 0U);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_3);
#endif

  err = snd_pcm_sw_params(pcm->pcm, pcm->sw_params);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_3);
  
  err = snd_pcm_prepare(pcm->pcm);
  if (err) PERROR_GOTO(snd_strerror(err), on_error_3);

  pcm->rpos = 0;
  pcm->wpos = 0;
  pcm->nsampl = (size_t)desc->fsampl * 10;
  pcm->buf = malloc(pcm->nsampl * pcm->scale);
  if (pcm->buf == NULL) goto on_error_3;

  return 0;

 on_error_3:
  snd_pcm_sw_params_free(pcm->sw_params);
 on_error_2:
  snd_pcm_hw_params_free(pcm->hw_params);
 on_error_1:
  snd_pcm_close(pcm->pcm);
 on_error_0:
  return -1;
  
}
Example #2
0
static pj_status_t open_capture (struct alsa_stream* stream,
			         const pjmedia_aud_param *param)
{
    snd_pcm_hw_params_t* params;
    snd_pcm_format_t format;
    int result;
    unsigned int rate;
    snd_pcm_uframes_t tmp_buf_size;
    snd_pcm_uframes_t tmp_period_size;

    if (param->rec_id < 0 || param->rec_id >= stream->af->dev_cnt)
	return PJMEDIA_EAUD_INVDEV;

    /* Open PCM for capture */
    PJ_LOG (5,(THIS_FILE, "open_capture: Open capture device '%s'",
	       stream->af->devs[param->rec_id].name));
    result = snd_pcm_open (&stream->ca_pcm,
		            stream->af->devs[param->rec_id].name,
			   SND_PCM_STREAM_CAPTURE,
			   0);
    if (result < 0)
	return PJMEDIA_EAUD_SYSERR;

    /* Allocate a hardware parameters object. */
    snd_pcm_hw_params_alloca (&params);

    /* Fill it in with default values. */
    snd_pcm_hw_params_any (stream->ca_pcm, params);

    /* Set interleaved mode */
    snd_pcm_hw_params_set_access (stream->ca_pcm, params,
				  SND_PCM_ACCESS_RW_INTERLEAVED);

    /* Set format */
    switch (param->bits_per_sample) {
    case 8:
	TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S8"));
	format = SND_PCM_FORMAT_S8;
	break;
    case 16:
	TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S16_LE"));
	format = SND_PCM_FORMAT_S16_LE;
	break;
    case 24:
	TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S24_LE"));
	format = SND_PCM_FORMAT_S24_LE;
	break;
    case 32:
	TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S32_LE"));
	format = SND_PCM_FORMAT_S32_LE;
	break;
    default:
	TRACE_((THIS_FILE, "open_capture: set format SND_PCM_FORMAT_S16_LE"));
	format = SND_PCM_FORMAT_S16_LE;
	break;
    }
    snd_pcm_hw_params_set_format (stream->ca_pcm, params, format);

    /* Set number of channels */
    TRACE_((THIS_FILE, "open_capture: set channels: %d",
	    param->channel_count));
    snd_pcm_hw_params_set_channels (stream->ca_pcm, params,
				    param->channel_count);

    /* Set clock rate */
    rate = param->clock_rate;
    TRACE_((THIS_FILE, "open_capture: set clock rate: %d", rate));
    snd_pcm_hw_params_set_rate_near (stream->ca_pcm, params, &rate, NULL);
    TRACE_((THIS_FILE, "open_capture: clock rate set to: %d", rate));

    /* Set period size to samples_per_frame frames. */
    stream->ca_frames = (snd_pcm_uframes_t) param->samples_per_frame /
					    param->channel_count;
    TRACE_((THIS_FILE, "open_capture: set period size: %d",
	    stream->ca_frames));
    tmp_period_size = stream->ca_frames;
    snd_pcm_hw_params_set_period_size_near (stream->ca_pcm, params,
					    &tmp_period_size, NULL);
    TRACE_((THIS_FILE, "open_capture: period size set to: %d",
	    tmp_period_size));

    /* Set the sound device buffer size and latency */
    if (param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY)
	tmp_buf_size = (rate / 1000) * param->input_latency_ms;
    else
	tmp_buf_size = (rate / 1000) * PJMEDIA_SND_DEFAULT_REC_LATENCY;
    snd_pcm_hw_params_set_buffer_size_near (stream->ca_pcm, params,
					    &tmp_buf_size);
    stream->param.input_latency_ms = tmp_buf_size / (rate / 1000);

    /* Set our buffer */
    stream->ca_buf_size = stream->ca_frames * param->channel_count *
			  (param->bits_per_sample/8);
    stream->ca_buf = (char*) pj_pool_alloc (stream->pool, stream->ca_buf_size);

    TRACE_((THIS_FILE, "open_capture: buffer size set to: %d",
	    (int)tmp_buf_size));
    TRACE_((THIS_FILE, "open_capture: capture_latency set to: %d ms",
	    (int)stream->param.input_latency_ms));

    /* Activate the parameters */
    result = snd_pcm_hw_params (stream->ca_pcm, params);
    if (result < 0) {
	snd_pcm_close (stream->ca_pcm);
	return PJMEDIA_EAUD_SYSERR;
    }

    PJ_LOG (5,(THIS_FILE, "Opened device alsa(%s) for capture, sample rate=%d"
	       ", ch=%d, bits=%d, period size=%d frames, latency=%d ms",
	       stream->af->devs[param->rec_id].name,
	       rate, param->channel_count,
	       param->bits_per_sample, stream->ca_frames,
	       (int)stream->param.input_latency_ms));

    return PJ_SUCCESS;
}
Example #3
0
static int
set_hwparams (GstAlsaSink * alsa)
{
  guint rrate;
  gint err;
  snd_pcm_hw_params_t *params;
  guint period_time, buffer_time;

  snd_pcm_hw_params_malloc (&params);

  GST_DEBUG_OBJECT (alsa, "Negotiating to %d channels @ %d Hz (format = %s) "
      "SPDIF (%d)", alsa->channels, alsa->rate,
      snd_pcm_format_name (alsa->format), alsa->iec958);

  /* start with requested values, if we cannot configure alsa for those values,
   * we set these values to -1, which will leave the default alsa values */
  buffer_time = alsa->buffer_time;
  period_time = alsa->period_time;

retry:
  /* choose all parameters */
  CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
  /* set the interleaved read/write format */
  CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
      wrong_access);
  /* set the sample format */
  if (alsa->iec958) {
    /* Try to use big endian first else fallback to le and swap bytes */
    if (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format) < 0) {
      alsa->format = SND_PCM_FORMAT_S16_LE;
      alsa->need_swap = TRUE;
      GST_DEBUG_OBJECT (alsa, "falling back to little endian with swapping");
    } else {
      alsa->need_swap = FALSE;
    }
  }
  CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
      no_sample_format);
  /* set the count of channels */
  CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
      no_channels);
  /* set the stream rate */
  rrate = alsa->rate;
  CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
      no_rate);
  if (rrate != alsa->rate)
    goto rate_match;

#ifndef GST_DISABLE_GST_DEBUG
  /* get and dump some limits */
  {
    guint min, max;

    snd_pcm_hw_params_get_buffer_time_min (params, &min, NULL);
    snd_pcm_hw_params_get_buffer_time_max (params, &max, NULL);

    GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u",
        alsa->buffer_time, min, max);

    snd_pcm_hw_params_get_period_time_min (params, &min, NULL);
    snd_pcm_hw_params_get_period_time_max (params, &max, NULL);

    GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u",
        alsa->period_time, min, max);

    snd_pcm_hw_params_get_periods_min (params, &min, NULL);
    snd_pcm_hw_params_get_periods_max (params, &max, NULL);

    GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max);
  }
#endif

  /* now try to configure the buffer time and period time, if one
   * of those fail, we fall back to the defaults and emit a warning. */
  if (buffer_time != -1 && !alsa->iec958) {
    /* set the buffer time */
    if ((err = snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
                &buffer_time, NULL)) < 0) {
      GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
          ("Unable to set buffer time %i for playback: %s",
              buffer_time, snd_strerror (err)));
      /* disable buffer_time the next round */
      buffer_time = -1;
      goto retry;
    }
    GST_DEBUG_OBJECT (alsa, "buffer time %u", buffer_time);
  }
  if (period_time != -1 && !alsa->iec958) {
    /* set the period time */
    if ((err = snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
                &period_time, NULL)) < 0) {
      GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
          ("Unable to set period time %i for playback: %s",
              period_time, snd_strerror (err)));
      /* disable period_time the next round */
      period_time = -1;
      goto retry;
    }
    GST_DEBUG_OBJECT (alsa, "period time %u", period_time);
  }

  /* Set buffer size and period size manually for SPDIF */
  if (G_UNLIKELY (alsa->iec958)) {
    snd_pcm_uframes_t buffer_size = SPDIF_BUFFER_SIZE;
    snd_pcm_uframes_t period_size = SPDIF_PERIOD_SIZE;

    CHECK (snd_pcm_hw_params_set_buffer_size_near (alsa->handle, params,
            &buffer_size), buffer_size);
    CHECK (snd_pcm_hw_params_set_period_size_near (alsa->handle, params,
            &period_size, NULL), period_size);
  }

  /* write the parameters to device */
  CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);

  /* now get the configured values */
  CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
      buffer_size);
  CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, NULL),
      period_size);

  GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size,
      alsa->period_size);

  snd_pcm_hw_params_free (params);
  return 0;

  /* ERRORS */
no_config:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Broken configuration for playback: no configurations available: %s",
            snd_strerror (err)));
    snd_pcm_hw_params_free (params);
    return err;
  }
wrong_access:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Access type not available for playback: %s", snd_strerror (err)));
    snd_pcm_hw_params_free (params);
    return err;
  }
no_sample_format:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Sample format not available for playback: %s", snd_strerror (err)));
    snd_pcm_hw_params_free (params);
    return err;
  }
no_channels:
  {
    gchar *msg = NULL;

    if ((alsa->channels) == 1)
      msg = g_strdup (_("Could not open device for playback in mono mode."));
    if ((alsa->channels) == 2)
      msg = g_strdup (_("Could not open device for playback in stereo mode."));
    if ((alsa->channels) > 2)
      msg =
          g_strdup_printf (_
          ("Could not open device for playback in %d-channel mode."),
          alsa->channels);
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, ("%s", msg),
        ("%s", snd_strerror (err)));
    g_free (msg);
    snd_pcm_hw_params_free (params);
    return err;
  }
no_rate:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Rate %iHz not available for playback: %s",
            alsa->rate, snd_strerror (err)));
    return err;
  }
rate_match:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err));
    snd_pcm_hw_params_free (params);
    return -EINVAL;
  }
buffer_size:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Unable to get buffer size for playback: %s", snd_strerror (err)));
    snd_pcm_hw_params_free (params);
    return err;
  }
period_size:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Unable to get period size for playback: %s", snd_strerror (err)));
    snd_pcm_hw_params_free (params);
    return err;
  }
set_hw_params:
  {
    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
        ("Unable to set hw params for playback: %s", snd_strerror (err)));
    snd_pcm_hw_params_free (params);
    return err;
  }
}
Example #4
0
int main()
{
	int fp,ff;
  unsigned int pcm, tmp, dir;
  int buff_size;
	char filename[20] = "123.wav";
  long loops;
  int rc;
  int size;
  snd_pcm_t *handle;
  snd_pcm_hw_params_t *params;
  unsigned int val;
  
  snd_pcm_uframes_t frames;
  char *buff,*ipaddress;
  int rate, channels, seconds;
//printf("aaa\n");
  /* Open PCM device for recording (capture). */
  rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0);

  if (rc < 0) 
  {
    fprintf(stderr,"unable to open pcm device: %s\n",   snd_strerror(rc));
    exit(1);
  }
  /* Allocate a hardware parameters object. */
  snd_pcm_hw_params_alloca(&params);

  /* Fill it in with default values. */
  snd_pcm_hw_params_any(handle, params);

  /* Set the desired hardware parameters. */

  /* Interleaved mode */
  snd_pcm_hw_params_set_access(handle, params,  SND_PCM_ACCESS_RW_INTERLEAVED);

  /* Signed 16-bit little-endian format */
  snd_pcm_hw_params_set_format(handle, params,SND_PCM_FORMAT_U8);

  /* Two channels (stereo) */
  snd_pcm_hw_params_set_channels(handle, params, 1);

  /* 44100 bits/second sampling rate (CD quality) */
  val = 8000;
  
  snd_pcm_hw_params_set_rate_near(handle, params,  &val, &dir);

  /* Set period size to 32 frames. */
  frames = 32;
  snd_pcm_hw_params_set_period_size_near(handle,params, &frames, &dir);

  /* Write the parameters to the driver */
  rc = snd_pcm_hw_params(handle, params);
  if (rc < 0) 
  {
    fprintf(stderr,"unable to set hw parameters: %s\n", snd_strerror(rc));
    exit(1);
  }

  /* Use a buff large enough to hold one period */

  snd_pcm_hw_params_get_period_size(params,  &frames, &dir);
  size = frames * 4; /* 2 bytes/sample, 2 channels */
  buff = (char *) malloc(size);

  /* We want to loop for 5 seconds */

  snd_pcm_hw_params_get_period_time(params, &val, &dir);
  loops = 50000000 / val;

  fp=open("123.wav",O_WRONLY);
  ipaddress = malloc(sizeof(char) * 4);

  /*printf("\n\tEnter ip : ");
  scanf("%s",ipaddress);*/

//  printf("sending data\n");
  
  for (loops=500000 / val;loops > 0;loops--) 
  {
		bzero(buff,sizeof(buff));
		rc = snd_pcm_readi(handle, buff, frames);
		write(fp,buff,128);
		fun(buff,128,filename);
	
	//	fucntion1(ipaddress,buff,size);
		
		if (rc == -EPIPE) 
		{
		  /* EPIPE means overrun */
		  fprintf(stderr, "overrun occurred\n");
		  snd_pcm_prepare(handle);
		} 
		else if (rc < 0) 
		{
		  fprintf(stderr,"error from read: %s\n",  snd_strerror(rc));
		} 
		else if (rc != (int)frames) 
		{
		  fprintf(stderr, "short read, read %d frames\n", rc);
		}
		
	/*	rc = write(1, buff, size);
		if (rc != size)
		  fprintf(stderr,"short write: wrote %d bytes\n", rc);
	
  */
 	}
  close(fp);
  //printf("sending data\n");
 
 /* client1 call(222.wav)*/
  snd_pcm_drain(handle);
  snd_pcm_close(handle);
  
	free(buff);

	return 0;
}
bool QAudioInputPrivate::open()
{
#ifdef DEBUG_AUDIO
    QTime now(QTime::currentTime());
    qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
#endif
    clockStamp.restart();
    timeStamp.restart();
    elapsedTimeOffset = 0;

    int dir;
    int err = 0;
    int count=0;
    unsigned int freakuency=settings.frequency();

    if (!settings.isValid()) {
        qWarning("QAudioOutput: open error, invalid format.");
    } else if (settings.sampleRate() <= 0) {
        qWarning("QAudioOutput: open error, invalid sample rate (%d).",
                 settings.sampleRate());
    } else {
        err = -1;
    }

    if (err == 0) {
        errorState = QAudio::OpenError;
        deviceState = QAudio::StoppedState;
        emit errorChanged(errorState);
        return false;
    }


    QString dev = QString(QLatin1String(m_device.constData()));
    QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioInput);
    if(dev.compare(QLatin1String("default")) == 0) {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
        if (devices.size() > 0)
            dev = QLatin1String(devices.first());
        else
            return false;
#else
        dev = QLatin1String("hw:0,0");
#endif
    } else {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
        dev = QLatin1String(m_device);
#else
        int idx = 0;
        char *name;

        QString shortName = QLatin1String(m_device.mid(m_device.indexOf('=',0)+1).constData());

        while(snd_card_get_name(idx,&name) == 0) {
            if(qstrncmp(shortName.toLocal8Bit().constData(),name,shortName.length()) == 0)
                break;
            idx++;
        }
        dev = QString(QLatin1String("hw:%1,0")).arg(idx);
#endif
    }

    // Step 1: try and open the device
    while((count < 5) && (err < 0)) {
        err=snd_pcm_open(&handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0);
        if(err < 0)
            count++;
    }
    if (( err < 0)||(handle == 0)) {
        errorState = QAudio::OpenError;
        deviceState = QAudio::StoppedState;
        emit stateChanged(deviceState);
        return false;
    }
    snd_pcm_nonblock( handle, 0 );

    // Step 2: Set the desired HW parameters.
    snd_pcm_hw_params_alloca( &hwparams );

    bool fatal = false;
    QString errMessage;
    unsigned int chunks = 8;

    err = snd_pcm_hw_params_any( handle, hwparams );
    if ( err < 0 ) {
        fatal = true;
        errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_any: err = %1").arg(err);
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_rate_resample( handle, hwparams, 1 );
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_rate_resample: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_access( handle, hwparams, access );
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_access: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = setFormat();
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_format: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channels() );
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_channels: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_rate_near( handle, hwparams, &freakuency, 0 );
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_rate_near: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir);
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir);
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_period_time_near: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &chunks, &dir);
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_periods_near: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params(handle, hwparams);
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params: err = %1").arg(err);
        }
    }
    if( err < 0) {
        qWarning()<<errMessage;
        errorState = QAudio::OpenError;
        deviceState = QAudio::StoppedState;
        emit stateChanged(deviceState);
        return false;
    }
    snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames);
    buffer_size = snd_pcm_frames_to_bytes(handle,buffer_frames);
    snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &dir);
    period_size = snd_pcm_frames_to_bytes(handle,period_frames);
    snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir);
    snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir);

    // Step 3: Set the desired SW parameters.
    snd_pcm_sw_params_t *swparams;
    snd_pcm_sw_params_alloca(&swparams);
    snd_pcm_sw_params_current(handle, swparams);
    snd_pcm_sw_params_set_start_threshold(handle,swparams,period_frames);
    snd_pcm_sw_params_set_stop_threshold(handle,swparams,buffer_frames);
    snd_pcm_sw_params_set_avail_min(handle, swparams,period_frames);
    snd_pcm_sw_params(handle, swparams);

    // Step 4: Prepare audio
    if(audioBuffer == 0)
        audioBuffer = new char[buffer_size];
    snd_pcm_prepare( handle );
    snd_pcm_start(handle);

    // Step 5: Setup timer
    bytesAvailable = checkBytesReady();

    if(pullMode)
        connect(audioSource,SIGNAL(readyRead()),this,SLOT(userFeed()));

    // Step 6: Start audio processing
    chunks = buffer_size/period_size;
    timer->start(period_time*chunks/2000);

    errorState  = QAudio::NoError;

    totalTimeValue = 0;

    return true;
}
Example #6
0
static int pcm_open(struct alsa_pcm *alsa, const char *device_name,
                    snd_pcm_stream_t stream, int rate, int buffer_time)
{
    int r, dir;
    unsigned int p;
    size_t bytes;
    snd_pcm_hw_params_t *hw_params;
    
    r = snd_pcm_open(&alsa->pcm, device_name, stream, SND_PCM_NONBLOCK);
    if (!chk("open", r))
        return -1;

    snd_pcm_hw_params_alloca(&hw_params);

    r = snd_pcm_hw_params_any(alsa->pcm, hw_params);
    if (!chk("hw_params_any", r))
        return -1;
    
    r = snd_pcm_hw_params_set_access(alsa->pcm, hw_params,
                                     SND_PCM_ACCESS_RW_INTERLEAVED);
    if (!chk("hw_params_set_access", r))
        return -1;
    
    r = snd_pcm_hw_params_set_format(alsa->pcm, hw_params, SND_PCM_FORMAT_S16);
    if (!chk("hw_params_set_format", r)) {
        fprintf(stderr, "16-bit signed format is not available. "
                "You may need to use a 'plughw' device.\n");
        return -1;
    }

    r = snd_pcm_hw_params_set_rate(alsa->pcm, hw_params, rate, 0);
    if (!chk("hw_params_set_rate", r )) {
        fprintf(stderr, "%dHz sample rate not available. You may need to use "
                "a 'plughw' device.\n", rate);
        return -1;
    }
    alsa->rate = rate;

    r = snd_pcm_hw_params_set_channels(alsa->pcm, hw_params, DEVICE_CHANNELS);
    if (!chk("hw_params_set_channels", r)) {
        fprintf(stderr, "%d channel audio not available on this device.\n",
                DEVICE_CHANNELS);
        return -1;
    }

    p = buffer_time * 1000; /* microseconds */
    dir = -1;
    r = snd_pcm_hw_params_set_buffer_time_near(alsa->pcm, hw_params, &p, &dir);
    if (!chk("hw_params_set_buffer_time_near", r)) {
        fprintf(stderr, "Buffer of %dms may be too small for this hardware.\n",
                buffer_time);
        return -1;
    }

    p = 2; /* double buffering */
    dir = 1;
    r = snd_pcm_hw_params_set_periods_min(alsa->pcm, hw_params, &p, &dir);
    if (!chk("hw_params_set_periods_min", r)) {
        fprintf(stderr, "Buffer of %dms may be too small for this hardware.\n",
                buffer_time);
        return -1;
    }

    r = snd_pcm_hw_params(alsa->pcm, hw_params);
    if (!chk("hw_params", r))
        return -1;
    
    r = snd_pcm_hw_params_get_period_size(hw_params, &alsa->period, &dir);
    if (!chk("get_period_size", r))
        return -1;

    bytes = alsa->period * DEVICE_CHANNELS * sizeof(signed short);
    alsa->buf = malloc(bytes);
    if (!alsa->buf) {
        perror("malloc");
        return -1;
    }

    /* snd_pcm_readi() returns uninitialised memory on first call,
     * possibly caused by premature POLLIN. Keep valgrind happy. */

    memset(alsa->buf, 0, bytes);

    return 0;
}
Example #7
0
int main()
{
    long loops;
    int rc;
    int size;
    snd_pcm_t *rec_handle;
    snd_pcm_hw_params_t *rec_params;
    unsigned int val;
    int dir;
    snd_pcm_uframes_t frames;
    char *buffer;
    WAVEHDR wavheader;
    int total_len = 0;
    FILE *fp_rec = fopen("rec.wav", "wb");
    if(fp_rec==NULL)
    {
        return 0;
    }
    wav_start_write(fp_rec, &wavheader);
    /* Open PCM device for recording (capture). */
    rc = snd_pcm_open(&rec_handle, "default",
                      SND_PCM_STREAM_CAPTURE, 0);
    if (rc < 0) {
        fprintf(stderr,
                "unable to open pcm device: %s\n",
                snd_strerror(rc));
        exit(1);
    }

    /* Allocate a hardware parameters object. */
    snd_pcm_hw_params_alloca(&rec_params);

    /* Fill it in with default values. */
    snd_pcm_hw_params_any(rec_handle, rec_params);

    /* Set the desired hardware parameters. */

    /* Interleaved mode */
    snd_pcm_hw_params_set_access(rec_handle, rec_params,
                                 SND_PCM_ACCESS_RW_INTERLEAVED);

    /* Signed 16-bit little-endian format */
    snd_pcm_hw_params_set_format(rec_handle, rec_params,
                                 SND_PCM_FORMAT_S16_LE);

    /* Two channels (stereo) */
    snd_pcm_hw_params_set_channels(rec_handle, rec_params, 1);

    /* 44100 bits/second sampling rate (CD quality) */
    val = 8000;
    snd_pcm_hw_params_set_rate_near(rec_handle, rec_params,
                                    &val, &dir);

    /* Set period size to 32 frames. */
    frames = 32;
    snd_pcm_hw_params_set_period_size_near(rec_handle,
                                           rec_params, &frames, &dir);

    /* Write the parameters to the driver */
    rc = snd_pcm_hw_params(rec_handle, rec_params);
    if (rc < 0)
    {
        fprintf(stderr,
                "unable to set hw parameters: %s\n",
                snd_strerror(rc));
        exit(1);
    }

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

    /* We want to loop for 5 seconds */
    snd_pcm_hw_params_get_period_time(rec_params, &val, &dir);
    loops = 2000;

    while (loops-- > 0)
    {
        rc = snd_pcm_readi(rec_handle, buffer, frames);
        if (rc == -EPIPE)
        {
            /* EPIPE means overrun */
            fprintf(stderr, "overrun occurred\n");
            snd_pcm_prepare(rec_handle);
        }
        else if (rc < 0)
        {
            fprintf(stderr, "error from read: %s\n", snd_strerror(rc));
        }
        else if (rc != (int)frames)
        {
            fprintf(stderr, "short read, read %d frames\n", rc);
        }
        rc = fwrite(buffer, 1, size, fp_rec);
        total_len += size;
        printf("#\n");
        if (rc != size)
            fprintf(stderr,"short write: wrote %d bytes\n", rc);
    }
    wav_stop_write(fp_rec, &wavheader, total_len);
    snd_pcm_drain(rec_handle);
    snd_pcm_close(rec_handle);
    free(buffer);
    fclose(fp_rec);
    return 0;
}
Example #8
0
int
sound_lowlevel_init( const char *device, int *freqptr, int *stereoptr )
{
  unsigned int exact_rate, periods;
  unsigned int val, n;
  snd_pcm_hw_params_t *hw_params;
  snd_pcm_sw_params_t *sw_params;
  snd_pcm_uframes_t avail_min = 0, sound_periodsize, bsize = 0;
  static int first_init = 1;
  static int init_running = 0;
  const char *option;
  char tmp;
  int err, dir, nperiods = NUM_FRAMES;

  float hz;

  if( init_running )
    return 0;
  
  init_running = 1;
/* select a default device if we weren't explicitly given one */

  option = device;
  while( option && *option ) {
    tmp = '*';
    if( ( err = sscanf( option, " buffer=%i %n%c", &val, &n, &tmp ) > 0 ) &&
		( tmp == ',' || strlen( option ) == n ) ) {
      if( val < 1 ) {
	fprintf( stderr, "Bad value for ALSA buffer size %i, using default\n",
		    val );
      } else {
        bsize = val;
      }
    } else if( ( err = sscanf( option, " frames=%i %n%c", &val, &n, &tmp ) > 0 ) &&
		( tmp == ',' || strlen( option ) == n ) ) {
      if( val < 1 ) {
	fprintf( stderr, "Bad value for ALSA buffer size %i frames, using default (%d)\n",
		    val, NUM_FRAMES );
      } else {
        nperiods = val;
      }
    } else if( ( err = sscanf( option, " avail=%i %n%c", &val, &n, &tmp ) > 0 ) &&
		( tmp == ',' || strlen( option ) == n ) ) {
      if( val < 1 ) {
	fprintf( stderr, "Bad value for ALSA avail_min size %i frames, using default\n",
		    val );
      } else {
        avail_min = val;
      }
    } else if( ( err = sscanf( option, " verbose %n%c", &n, &tmp ) == 1 ) &&
		( tmp == ','  || strlen( option ) == n ) ) {
      verb = 1;
    } else {					/* try as device name */
	while( isspace(*option) )
          option++;
	if( *option == '\'' )		/* force device... */
	  option++;
	pcm_name = option;
	n = strlen( pcm_name );
    }
    option += n + ( tmp == ',' );
  }

/* Open the sound device
 */
  if( pcm_name == NULL || *pcm_name == '\0' )
    pcm_name = "default";
  if( snd_pcm_open( &pcm_handle, pcm_name , stream, 0 ) < 0 ) {
    if( strcmp( pcm_name, "default" ) == 0 ) {
    /* we try a last one: plughw:0,0 but what a weired ALSA conf.... */
      if( snd_pcm_open( &pcm_handle, "plughw:0,0", stream, 0 ) < 0 ) {
        settings_current.sound = 0;
        ui_error( UI_ERROR_ERROR,
                  "couldn't open sound device 'default' and 'plughw:0,0' check ALSA configuration."
                  );
	init_running = 0;
        return 1;
      } else {
        if( first_init )
          fprintf( stderr,
                    "Couldn't open sound device 'default', using 'plughw:0,0' check ALSA configuration.\n"
                    );
      }
    }
    settings_current.sound = 0;
    ui_error( UI_ERROR_ERROR, "couldn't open sound device '%s'.", pcm_name );
    init_running = 0;
    return 1;
  }

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

/* Init hw_params with full configuration space */
  if( snd_pcm_hw_params_any( pcm_handle, hw_params ) < 0 ) {
    settings_current.sound = 0;
    ui_error( UI_ERROR_ERROR,
              "couldn't get configuration space on sound device '%s'.",
              pcm_name );
    snd_pcm_close( pcm_handle );
    init_running = 0;
    return 1;
  }

  if( snd_pcm_hw_params_set_access( pcm_handle, hw_params,
                                    SND_PCM_ACCESS_RW_INTERLEAVED ) < 0) {
    settings_current.sound = 0;
    ui_error( UI_ERROR_ERROR, "couldn't set access interleaved on '%s'.",
              pcm_name );
    snd_pcm_close( pcm_handle );
    init_running = 0;
    return 1;
  }
  
    /* Set sample format */
  if( snd_pcm_hw_params_set_format( pcm_handle, hw_params, 
#if defined WORDS_BIGENDIAN
				    SND_PCM_FORMAT_S16_BE
#else
				    SND_PCM_FORMAT_S16_LE
#endif
						    ) < 0 ) {
    settings_current.sound = 0;
    ui_error( UI_ERROR_ERROR, "couldn't set format on '%s'.", pcm_name );
    snd_pcm_close( pcm_handle );
    init_running = 0;
    return 1;
  }

  ch = *stereoptr ? 2 : 1;

  if( snd_pcm_hw_params_set_channels( pcm_handle, hw_params, ch )
	    < 0 ) {
    fprintf( stderr, "Couldn't set %s to '%s'.\n", pcm_name,
    		    (*stereoptr ? "stereo" : "mono") );
    ch = *stereoptr ? 1 : 2;		/* try with opposite */
    if( snd_pcm_hw_params_set_channels( pcm_handle, hw_params, ch )
	    < 0 ) {
      ui_error( UI_ERROR_ERROR, "couldn't set %s to '%s'.", pcm_name,
    		    (*stereoptr ? "stereo" : "mono") );
      settings_current.sound = 0;
      snd_pcm_close( pcm_handle );
      init_running = 0;
      return 1;
    }
    *stereoptr = *stereoptr ? 0 : 1;		/* write back */
  }

  framesize = ch << 1;			/* we always use 16 bit sorry :-( */
/* Set sample rate. If the exact rate is not supported */
/* by the hardware, use nearest possible rate.         */ 
  exact_rate = *freqptr;
  if( snd_pcm_hw_params_set_rate_near( pcm_handle, hw_params, &exact_rate,
							NULL ) < 0) {
    settings_current.sound = 0;
    ui_error( UI_ERROR_ERROR, "couldn't set rate %d on '%s'.",
						*freqptr, pcm_name );
    snd_pcm_close( pcm_handle );
    init_running = 0;
    return 1;
  }
  if( first_init && *freqptr != exact_rate ) {
    fprintf( stderr, 
              "The rate %d Hz is not supported by your hardware. "
              "Using %d Hz instead.\n", *freqptr, exact_rate );
    *freqptr = exact_rate;
  }

  if( bsize != 0 ) {
    exact_periodsize = sound_periodsize = bsize / nperiods;
    if( bsize < 1 ) {
      fprintf( stderr,
                "bad value for ALSA buffer size %i, using default.\n",
		val );
      bsize = 0;
    }
  }

  if( bsize == 0 ) {
    hz = (float)machine_current->timings.processor_speed /
              machine_current->timings.tstates_per_frame;
    exact_periodsize = sound_periodsize = *freqptr / hz;
  }

  dir = -1;
  if( snd_pcm_hw_params_set_period_size_near( pcm_handle, hw_params,
					    &exact_periodsize, &dir ) < 0 ) {
    settings_current.sound = 0;
    ui_error( UI_ERROR_ERROR, "couldn't set period size %d on '%s'.",
                              (int)sound_periodsize, pcm_name );
    snd_pcm_close( pcm_handle );
    init_running = 0;
    return 1;
  }

  if( first_init && ( exact_periodsize < sound_periodsize / 1.5 ||
		      exact_periodsize > sound_periodsize * 1.5    ) ) {
    fprintf( stderr,
              "The period size %d is not supported by your hardware. "
              "Using %d instead.\n", (int)sound_periodsize,
              (int)exact_periodsize );
  }

  periods = nperiods;
/* Set number of periods. Periods used to be called fragments. */
  if( snd_pcm_hw_params_set_periods_near( pcm_handle, hw_params, &periods,
                                          NULL ) < 0 ) {
    settings_current.sound = 0;
    ui_error( UI_ERROR_ERROR, "couldn't set periods on '%s'.", pcm_name );
    snd_pcm_close( pcm_handle );
    init_running = 0;
    return 1;
  }

  if( first_init && periods != nperiods ) {
    fprintf( stderr, "%d periods is not supported by your hardware. "
                    	     "Using %d instead.\n", nperiods, periods );
  }

  snd_pcm_hw_params_get_buffer_size( hw_params, &exact_bsize );

  /* Apply HW parameter settings to */
  /* PCM device and prepare device  */

  if( snd_pcm_hw_params( pcm_handle, hw_params ) < 0 ) {
    settings_current.sound = 0;
    ui_error( UI_ERROR_ERROR,"couldn't set hw_params on %s", pcm_name );
    snd_pcm_close( pcm_handle );
    init_running = 0;
    return 1;
  }

  snd_pcm_sw_params_alloca( &sw_params );
  if( ( err = snd_pcm_sw_params_current( pcm_handle, sw_params ) ) < 0 ) {
    ui_error( UI_ERROR_ERROR,"couldn't get sw_params from %s: %s", pcm_name,
              snd_strerror ( err ) );
    snd_pcm_close( pcm_handle );
    init_running = 0;
    return 1;
  }

  if( ( err = snd_pcm_sw_params_set_start_threshold( pcm_handle,
		     sw_params, exact_periodsize * ( nperiods - 1 ) ) ) < 0 ) {
    ui_error( UI_ERROR_ERROR,"couldn't set start_treshold on %s: %s", pcm_name,
              snd_strerror ( err ) );
    snd_pcm_close( pcm_handle );
    init_running = 0;
    return 1;
  }

  if( !avail_min )
    avail_min = exact_periodsize >> 1;
  if( snd_pcm_sw_params_set_avail_min( pcm_handle,
		    sw_params, avail_min ) < 0 ) {
#if SND_LIB_VERSION < 0x10010
    if( ( err = snd_pcm_sw_params_set_sleep_min( pcm_handle,
    		    sw_params, 1 ) ) < 0 ) {
	fprintf( stderr, "Unable to set minimal sleep 1 for %s: %s\n", pcm_name,
              snd_strerror ( err ) );
    }
#else
    fprintf( stderr, "Unable to set avail min %s: %s\n", pcm_name,
    	     snd_strerror( err ) );
#endif
  }

#if SND_LIB_VERSION < 0x10010
  if( ( err = snd_pcm_sw_params_set_xfer_align( pcm_handle, sw_params, 1 ) ) < 0 ) {
    ui_error( UI_ERROR_ERROR,"couldn't set xfer_allign on %s: %s", pcm_name,
              snd_strerror ( err ) );
    init_running = 0;
    return 1;
  }
#endif
  
  if( ( err = snd_pcm_sw_params( pcm_handle, sw_params ) ) < 0 ) {
    ui_error( UI_ERROR_ERROR,"couldn't set sw_params on %s: %s", pcm_name,
              snd_strerror ( err ) );
    init_running = 0;
    return 1;
  }

  if( first_init ) snd_output_stdio_attach(&output, stdout, 0);

  first_init = 0;
  init_running = 0;
  return 0;	/* success */
}
Example #9
0
bool QAudioInputPrivate::open( QObject *input )
{
    // Open the Alsa capture device.
    bool    rc = true;
    int     err;

    unsigned int        freakuency = frequency;

    if ((err = snd_pcm_open(&handle,
                             m_device.constData(), //"plughw:0,0"
                             SND_PCM_STREAM_CAPTURE,
                                 0/*SND_PCM_ASYNC*/)) < 0) {

        qWarning( "QAudioInput: snd_pcm_open: error %d", err);

        rc = false;
    }
    else {
        snd_pcm_hw_params_t *hwparams;

        // We want non-blocking mode.
        snd_pcm_nonblock(handle, 1);

        // Set the desired parameters.
        snd_pcm_hw_params_alloca(&hwparams);

        err = snd_pcm_hw_params_any(handle, hwparams);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_any: err %d", err);
        }

        err = snd_pcm_hw_params_set_access(handle, hwparams,
                                           access);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_set_access: err %d",err);
        }

        err = snd_pcm_hw_params_set_format(handle, hwparams,format);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_set_format: err %d",err);
        }

        err = snd_pcm_hw_params_set_channels(handle,hwparams,(unsigned int)channels);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_set_channels: err %d",err);
        }

        err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &freakuency, 0);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_set_rate_near: err %d",err);
        }
        if(freakuency > 1.05 * frequency || freakuency < 0.95 * frequency) {
            qWarning("QAudioInput: warning, sample rate %i not supported by the hardware, using %u", frequency, freakuency);
        }

        if ( samplesPerBlock != -1 ) {
            // Set buffer and period sizes based on the supplied block size.
            sample_size = (snd_pcm_uframes_t)( samplesPerBlock * channels / 8 );
            err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &freakuency, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_rate_near: err %d",err);
            }
            if(freakuency > 1.05 * frequency || freakuency < 0.95 * frequency) {
                qWarning( "QAudioInput: warning, sample rate %i not supported by the hardware, using %u", frequency, freakuency);
            }

            err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err %d",err);
            }
            period_time = 1000000 * 256 / frequency;
            err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_period_time_near: err %d",err);
            }
        } else {
            // Use the largest buffer and period sizes we can.
            err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err %d",err);
            }
            period_time = 1000000 * 256 / frequency;
            err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_period_time_near: err %d",err);
            }
       }

        err = snd_pcm_hw_params(handle, hwparams);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params: err %d",err);
        }

        int                  dir;
        unsigned int         vval, vval2;
        snd_pcm_access_t     aval;
        snd_pcm_format_t     fval;
        snd_pcm_subformat_t  sval;

        qLog(QAudioInput) << "PCM handle name = " << snd_pcm_name(handle);
        qLog(QAudioInput) << "PCM state = " << snd_pcm_state_name(snd_pcm_state(handle));

        snd_pcm_hw_params_get_access(hwparams,&aval);
        vval = (unsigned int)aval;
        if ( (int)vval != (int)access ) {
            qLog(QAudioInput) << QString("access type not set, want %1 got %2")
                       .arg(snd_pcm_access_name((snd_pcm_access_t)access))
                       .arg(snd_pcm_access_name((snd_pcm_access_t)vval));
            access = (snd_pcm_access_t)vval;
        }
        qLog(QAudioInput) << "access type = " << snd_pcm_access_name((snd_pcm_access_t)vval);

        snd_pcm_hw_params_get_format(hwparams, &fval);
        vval = (unsigned int)fval;
        if ( (int)vval != (int)format ) {
            qLog(QAudioInput) << QString("format type not set, want %1 got %2")
                       .arg(snd_pcm_format_name((snd_pcm_format_t)format))
                       .arg(snd_pcm_format_name((snd_pcm_format_t)vval));
            format = (snd_pcm_format_t)vval;
        }
        qLog(QAudioInput) << QString("format = '%1' (%2)")
            .arg(snd_pcm_format_name((snd_pcm_format_t)vval))
            .arg(snd_pcm_format_description((snd_pcm_format_t)vval))
            .toLatin1().constData();

        snd_pcm_hw_params_get_subformat(hwparams,&sval);
        vval = (unsigned int)sval;
        qLog(QAudioInput) << QString("subformat = '%1' (%2)")
            .arg(snd_pcm_subformat_name((snd_pcm_subformat_t)vval))
            .arg(snd_pcm_subformat_description((snd_pcm_subformat_t)vval))
            .toLatin1().constData();

        snd_pcm_hw_params_get_channels(hwparams, &vval);
        if ( (int)vval != (int)channels ) {
            qLog(QAudioInput) << QString("channels type not set, want %1 got %2").arg(channels).arg(vval);
            channels = vval;
        }
        qLog(QAudioInput) << "channels = " << vval;

        snd_pcm_hw_params_get_rate(hwparams, &vval, &dir);
        if ( (int)vval != (int)frequency ) {
            qLog(QAudioInput) << QString("frequency type not set, want %1 got %2").arg(frequency).arg(vval);
            frequency = vval;
        }
        qLog(QAudioInput) << "rate =" <<  vval << " bps";

        snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir);
        qLog(QAudioInput) << "period time =" << period_time << " us";
        snd_pcm_hw_params_get_period_size(hwparams,&period_size, &dir);
        qLog(QAudioInput) << "period size =" << (int)period_size;
        snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir);
        qLog(QAudioInput) << "buffer time =" << buffer_time;
        snd_pcm_hw_params_get_buffer_size(hwparams,(snd_pcm_uframes_t *) &buffer_size);
        qLog(QAudioInput) << "buffer size =" << (int)buffer_size;
        snd_pcm_hw_params_get_periods(hwparams, &vval, &dir);
        qLog(QAudioInput) << "periods per buffer =" << vval;
        snd_pcm_hw_params_get_rate_numden(hwparams, &vval, &vval2);
        qLog(QAudioInput) << QString("exact rate = %1/%2 bps").arg(vval).arg(vval2).toLatin1().constData();
        vval = snd_pcm_hw_params_get_sbits(hwparams);
        qLog(QAudioInput) << "significant bits =" << vval;
        snd_pcm_hw_params_get_tick_time(hwparams,&vval, &dir);
        qLog(QAudioInput) << "tick time =" << vval;
        vval = snd_pcm_hw_params_is_batch(hwparams);
        qLog(QAudioInput) << "is batch =" << vval;
        vval = snd_pcm_hw_params_is_block_transfer(hwparams);
        qLog(QAudioInput) << "is block transfer =" << vval;
        vval = snd_pcm_hw_params_is_double(hwparams);
        qLog(QAudioInput) << "is double =" << vval;
        vval = snd_pcm_hw_params_is_half_duplex(hwparams);
        qLog(QAudioInput) << "is half duplex =" << vval;
        vval = snd_pcm_hw_params_is_joint_duplex(hwparams);
        qLog(QAudioInput) << "is joint duplex =" << vval;
        vval = snd_pcm_hw_params_can_overrange(hwparams);
        qLog(QAudioInput) << "can overrange =" << vval;
        vval = snd_pcm_hw_params_can_mmap_sample_resolution(hwparams);
        qLog(QAudioInput) << "can mmap =" << vval;
        vval = snd_pcm_hw_params_can_pause(hwparams);
        qLog(QAudioInput) << "can pause =" << vval;
        vval = snd_pcm_hw_params_can_resume(hwparams);
        qLog(QAudioInput) << "can resume =" << vval;
        vval = snd_pcm_hw_params_can_sync_start(hwparams);
        qLog(QAudioInput) << "can sync start =" << vval;

        snd_pcm_sw_params_t *swparams;
        snd_pcm_sw_params_alloca(&swparams);
        err = snd_pcm_sw_params_current(handle, swparams);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params_current: err %d",err);
        }
        err = snd_pcm_sw_params_set_start_threshold(handle,swparams,period_size);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params_set_start_threshold: err %d",err);
        }
        err = snd_pcm_sw_params_set_avail_min(handle, swparams,period_size);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params_set_avail_min: err %d",err);
        }
        err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params_set_xfer_align: err %d",err);
        }
        err = snd_pcm_sw_params(handle, swparams);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params: err %d",err);
        }

        snd_pcm_prepare(handle);
        snd_pcm_start(handle);

        int     count = snd_pcm_poll_descriptors_count(handle);
        pollfd  *pfds = new pollfd[count];

        snd_pcm_poll_descriptors(handle, pfds, count);

        for (int i = 0; i < count; ++i)
        {
            if ((pfds[i].events & POLLIN) != 0) {
                notifier = new QSocketNotifier(pfds[i].fd, QSocketNotifier::Read);
                QObject::connect(notifier,
                                 SIGNAL(activated(int)),
                                 input,
                                 SIGNAL(readyRead()));

                break;
            }
        }

        if (notifier == NULL) {
            rc = false;
        }

        delete pfds;
    }

    return rc;
}
Example #10
0
	main (int argc, char *argv[])
	{
		int i;
		int err;
		short buf[128];
		snd_pcm_t *capture_handle;
		snd_pcm_hw_params_t *hw_params;
	
		if ((err = snd_pcm_open (&capture_handle, argv[1], SND_PCM_STREAM_CAPTURE, 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 (capture_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 (capture_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 (capture_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 (capture_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 (capture_handle, hw_params, 2)) < 0) {
			fprintf (stderr, "cannot set channel count (%s)\n",
				 snd_strerror (err));
			exit (1);
		}
	
		if ((err = snd_pcm_hw_params (capture_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 (capture_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_readi (capture_handle, buf, 128)) != 128) {
				fprintf (stderr, "read from audio interface failed (%s)\n",
					 snd_strerror (err));
				exit (1);
			}
		}
	
		snd_pcm_close (capture_handle);
		exit (0);
	}
Example #11
0
void* play_thread(void *argv)
{
    char *__file_name = argv;
    struct WAVE *_wave;

#ifdef SOLO
    _wave = (struct WAVE*)malloc(sizeof(struct WAVE));
    memset(&_wave, 0, sizeof(struct _wave));
    if(!wave_read_file(argv, &_wave )){
	goto ERR;
    }
#else
    if(!list_count){
	fprintf(stderr,"[PLAY]: Not such wav sound file.\nPlease call \'play_read_filelist(DIR_PATH)\'\n");
	exit(1);
    }
    for(_wave=head;;_wave=_wave->next){
	if(!strcmp(_wave->file_name, __file_name))break;
	if(head->prev == _wave){
	    fprintf(stderr,"[PLAY]: Invalid file_name...\n");
	    return NULL;
	}
    }
#endif
    if(DISP)
	fprintf(stderr,"[PLAY]: Player will be playing \"%s\".\n",__file_name);

    snd_pcm_t *handle;                  // handle for sound_device
    snd_pcm_hw_params_t *params;        // params for sound_device
    int result_func = 0;                // result for function return
    unsigned int sampling_rate = _wave->rate;   // sampling rate
    int dir;    // sub unit direction
    snd_pcm_uframes_t frames = 32;        // size of frame
    unsigned int buffer_size;                   // buffer_size for frame
    int16_t *frameBuffer=NULL;                       // buffer for frame
    unsigned int approximate_period;                     // period[us]

    {// open the pcm device
	// open pcm device
	result_func = snd_pcm_open(
		&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
	if ( result_func < 0 )
	{
	    fprintf(stderr,
		    "[PLAY]: unable to open pcm device :%s\n",
		    snd_strerror(result_func));
	    goto ERR;
	}
    }

    {// set parameter to device
	// allocate device params
	snd_pcm_hw_params_alloca(&params);
	// get default param
	snd_pcm_hw_params_any(handle, params);
	// set parameter Interleaved mode
	snd_pcm_hw_params_set_access(handle, params,
		SND_PCM_ACCESS_RW_INTERLEAVED);
	// set format parameter : monoral 1ch 16bit LittleEndian
	snd_pcm_hw_params_set_format(handle, params,
		SND_PCM_FORMAT_S16_LE);
	// set output_device parameter stereo 2ch
	snd_pcm_hw_params_set_channels(handle, params, _wave->channel);
	// approximates to a specified sampling rate
	// pcm	PCM handle
	// params	Configuration space
	// val	approximate target rate / returned approximate set rate
	// dir	Sub unit direction 
	snd_pcm_hw_params_set_rate_near(
		handle, params, &sampling_rate, &dir);
	// set parameter size of frame
	snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
	// set parameter to hardware_device
	result_func = snd_pcm_hw_params(handle, params);

	// err check
	if (result_func < 0) {
	    fprintf(stderr, "[PLAY]: unable to set hw parameters: %s\n",
		    snd_strerror(result_func));
	    goto ERR;
	}

	// get bufferSize / frame
	snd_pcm_hw_params_get_period_size(params, &frames, &dir);
	// calculate buffer_size
	buffer_size = frames * 2; /*????????? 48000,monoral ver */
	// allocate buffer
	frameBuffer = (int16_t *)malloc(buffer_size);
	memset(frameBuffer, 0, sizeof(*frameBuffer));

	// get playback period
	// params	Configuration space
	// val	Returned approximate period duration in us
	// dir	Sub unit direction 
	snd_pcm_hw_params_get_period_time(params, &approximate_period, &dir);
    }


    { // playback process
	// playback time
	unsigned int ptime = approximate_period * 2 * 10;

	// playback
	while ( ptime-- )
	{
	    result_func = fread(
		    frameBuffer, sizeof(unsigned char),
		    buffer_size, _wave->fp);

	    // data is ended
	    if ( result_func == 0 )
	    {
		//fprintf(stdout, "[PLAY]: end of input devce\n");
		break;
	    }

	    // buffer_size is not correct
	    if ( result_func != buffer_size )
	    {
		/*
		   fprintf(stderr,
		   "short read: read %d bytes\n", result_func);
		   */
		break;
	    }

	    // playback
	    result_func = snd_pcm_writei(
		    handle, frameBuffer, frames);
	}
    }

    // for unplayed frame,wait sound finish
    snd_pcm_drain(handle);
    if(DISP)
	fprintf(stderr,"[PLAY]: Finished playing %s.\n",__file_name);

ERR :
    { // release
	if ( frameBuffer != NULL ){ free(frameBuffer); }
	if ( handle != NULL ) { snd_pcm_close(handle); }
    }
    return NULL;
}
Example #12
0
bool
AlsaSource::SetupHW ()
{
	bool result = false;
	bool rw_available = false;
	bool mmap_available = false;
#if DEBUG
	bool debug = debug_flags & RUNTIME_DEBUG_AUDIO;
#else
	bool debug = false;
#endif
	
	snd_pcm_hw_params_t *params = NULL;
	snd_output_t *output = NULL;
	guint32 buffer_time = 100000; // request 0.1 seconds of buffer time.
	int err = 0;
	int dir = 0;
	unsigned int rate = GetSampleRate ();
	unsigned int actual_rate = rate;
	guint32 channels = GetChannels ();

	if (debug) {
		err = snd_output_stdio_attach (&output, stdout, 0);
		if (err < 0)
			LOG_AUDIO ("AlsaSource::SetupHW (): Could not create alsa output: %s\n", snd_strerror (err));
	}

	err = snd_pcm_hw_params_malloc (&params);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (malloc): %s\n", snd_strerror (err));
		return false;
	}

	// choose all parameters
	err = snd_pcm_hw_params_any (pcm, params);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (no configurations available): %s\n", snd_strerror (err));
		goto cleanup;
	}
	
	if (debug && output != NULL) {
		LOG_AUDIO ("AlsaSource::SetupHW (): hw configurations:\n");
		snd_pcm_hw_params_dump (params, output);
	}
	
	// enable software resampling
	err = snd_pcm_hw_params_set_rate_resample (pcm, params, 1);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (could not enable resampling): %s\n", snd_strerror (err));
		goto cleanup;
	}
	
	// test for available transfer modes
	if (!(moonlight_flags & RUNTIME_INIT_AUDIO_ALSA_MMAP)) {
		err = snd_pcm_hw_params_test_access (pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED);
		if (err < 0) {
			LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup: RW access mode not supported (%s).\n", snd_strerror (err));			
		} else {
			rw_available = true;
		}
	}
	if (!(moonlight_flags & RUNTIME_INIT_AUDIO_ALSA_RW)) {
		err = snd_pcm_hw_params_test_access (pcm, params, SND_PCM_ACCESS_MMAP_INTERLEAVED);
		if (err < 0) {
			LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup: MMAP access mode not supported (%s).\n", snd_strerror (err));
		} else {
			mmap_available = true;
		}
	}
	if (mmap_available) {
		mmap = true;
	} else if (rw_available) {
		mmap = false;
	} else {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed, no available access mode\n");
		goto cleanup;
	}

	LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup: using %s access mode.\n", mmap ? "MMAP" : "RW");

	// set transfer mode (mmap or rw in our case)
	err = snd_pcm_hw_params_set_access (pcm, params, mmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED : SND_PCM_ACCESS_RW_INTERLEAVED);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (access type not available for playback): %s\n", snd_strerror (err));
		goto cleanup;
	}

	// set audio format
	switch (GetInputBytesPerSample ()) {
	case 1: // 8 bit audio
		err = snd_pcm_hw_params_set_format (pcm, params, SND_PCM_FORMAT_S16);
		SetOutputBytesPerSample (2);
		break;
	case 2: // 16 bit audio
		err = snd_pcm_hw_params_set_format (pcm, params, SND_PCM_FORMAT_S16);
		SetOutputBytesPerSample (2);
		break;
	case 3: // 24 bit audio
		// write as 32 bit audio, this is a lot easier to write to than 24 bit.
		err = snd_pcm_hw_params_set_format (pcm, params, SND_PCM_FORMAT_S32);
		SetOutputBytesPerSample (4);
		break;
	default:
		LOG_AUDIO ("AlsaSource::SetupHW (): Invalid input bytes per sample, expected 1, 2 or 3, got %i\n", GetInputBytesPerSample ());
		goto cleanup;
	}
	
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (sample format not available for playback): %s\n", snd_strerror (err));
		goto cleanup;
	}
	
	// set channel count
	err = snd_pcm_hw_params_set_channels (pcm, params, channels);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (channels count %i not available for playback): %s\n", channels, snd_strerror (err));
		goto cleanup;
	}
	
	// set sample rate
	err = snd_pcm_hw_params_set_rate_near (pcm, params, &actual_rate, 0);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (sample rate %i Hz not available for playback): %s\n", rate, snd_strerror (err));
		goto cleanup;
	} else if (actual_rate != rate) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (sample rate %i Hz not available for playback, only got %i Hz).\n", rate, actual_rate);
		goto cleanup;
	}
	
	// set the buffer time
	err = snd_pcm_hw_params_set_buffer_time_near (pcm, params, &buffer_time, &dir);
	if (err < 0) {
		LOG_AUDIO ("AudioNode::SetupHW (): Audio HW setup failed (unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror (err));
		goto cleanup;
	}

	// write the parameters to device
	err = snd_pcm_hw_params (pcm, params);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (unable to set hw params for playback: %s)\n", snd_strerror (err));
		if (debug && output != NULL) {
			LOG_AUDIO ("AlsaSource::SetupHW (): current hw configurations:\n");
			snd_pcm_hw_params_dump (params, output);
		}
		goto cleanup;
	}
	
	if (debug) {
		LOG_AUDIO ("AlsaSource::SetupHW (): hardware pause support: %s\n", snd_pcm_hw_params_can_pause (params) == 0 ? "no" : "yes"); 
		LOG_AUDIO ("AlsaSource::SetupHW (): succeeded\n");
		if (output != NULL) 
			snd_pcm_hw_params_dump (params, output);
	}

	result = true;
	
cleanup:
	snd_pcm_hw_params_free (params);
	
	return result;
}
Example #13
0
void SetupSound(void)
{
 snd_pcm_hw_params_t *hwparams;
 snd_pcm_sw_params_t *swparams;
 snd_pcm_status_t *status;
 int pspeed;
 int pchannels;
 int format;
 int buffer_time;
 int period_time;
 int err;

 if(iDisStereo) pchannels=1;
 else pchannels=2;

 pspeed=48000;
 format=SND_PCM_FORMAT_S16_LE;
 buffer_time=500000;
 period_time=buffer_time/4;

 if((err=snd_pcm_open(&handle, "default", 
                      SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK))<0)
  {
   printf("Audio open error: %s\n", snd_strerror(err));
   return;
  }

 if((err=snd_pcm_nonblock(handle, 0))<0)
  {
   printf("Can't set blocking moded: %s\n", snd_strerror(err));
   return;
  }

 snd_pcm_hw_params_alloca(&hwparams);
 snd_pcm_sw_params_alloca(&swparams);
 if((err=snd_pcm_hw_params_any(handle, hwparams))<0)
  {
   printf("Broken configuration for this PCM: %s\n", snd_strerror(err));
   return;
  }

 if((err=snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED))<0)
  {
   printf("Access type not available: %s\n", snd_strerror(err));
   return;
  }

 if((err=snd_pcm_hw_params_set_format(handle, hwparams, format))<0)
  {
   printf("Sample format not available: %s\n", snd_strerror(err));
   return;
  }

 if((err=snd_pcm_hw_params_set_channels(handle, hwparams, pchannels))<0)
  {
   printf("Channels count not available: %s\n", snd_strerror(err));
   return;
  }

 if((err=snd_pcm_hw_params_set_rate_near(handle, hwparams, &pspeed, 0))<0)
  {
   printf("Rate not available: %s\n", snd_strerror(err));
   return;
  }

 if((err=snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0))<0)
  {
   printf("Buffer time error: %s\n", snd_strerror(err));
   return;
  }

 if((err=snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0))<0)
  {
   printf("Period time error: %s\n", snd_strerror(err));
   return;
  }

 if((err=snd_pcm_hw_params(handle, hwparams))<0)
  {
   printf("Unable to install hw params: %s\n", snd_strerror(err));
   return;
  }

 snd_pcm_status_alloca(&status);
 if((err=snd_pcm_status(handle, status))<0)
  {
   printf("Unable to get status: %s\n", snd_strerror(err));
   return;
  }

 buffer_size=snd_pcm_status_get_avail(status);
}
Example #14
0
/* Initialise audio devices. */
int digi_init()
{
	int err, tmp;
	char *device = "plughw:0,0";
	snd_pcm_hw_params_t *params;
 pthread_attr_t attr;
 pthread_mutexattr_t mutexattr;

 //added on 980905 by adb to init sound kill system
 memset(SampleHandles, 255, sizeof(SampleHandles));
 //end edit by adb

 /* Open the ALSA sound device */
	if ((err = snd_pcm_open(&snd_devhandle, device, SND_PCM_STREAM_PLAYBACK)) < 0)
	{
     con_printf(CON_CRITICAL, "open failed: %s\n", snd_strerror( err ));  
     return -1; 
	}

	snd_pcm_hw_params_alloca(&params);
	err = snd_pcm_hw_params_any(snd_devhandle, params);
	if (err < 0)
	{
		con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err));
		return -1;
	}
	err = snd_pcm_hw_params_set_access(snd_devhandle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
	if (err < 0)
	{
		con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err));
		return -1;
	}
	err = snd_pcm_hw_params_set_format(snd_devhandle, params, SND_PCM_FORMAT_U8);
	if (err < 0)
	{
		con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err));
		return -1;
	}
	err = snd_pcm_hw_params_set_channels(snd_devhandle, params, 2);
	if (err < 0)
	{
		con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err));
		return -1;
	}
	tmp = 11025;
	err = snd_pcm_hw_params_set_rate_near(snd_devhandle, params, &tmp, NULL);
	if (err < 0)
	{
		con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err));
		return -1;
	}
	snd_pcm_hw_params_set_periods(snd_devhandle, params, 3, 0);
	snd_pcm_hw_params_set_buffer_size(snd_devhandle,params, (SOUND_BUFFER_SIZE*3)/2);

	err = snd_pcm_hw_params(snd_devhandle, params);
	if (err < 0)
	{
		con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err));
		return -1;
	}

 /* Start the mixer thread */

 /* We really should check the results of these */
 pthread_mutexattr_init(&mutexattr);
 pthread_mutex_init(&mutex,&mutexattr);
 pthread_mutexattr_destroy(&mutexattr);
 
 if (pthread_attr_init(&attr) != 0) {
  con_printf(CON_CRITICAL, "failed to init attr\n");
  snd_pcm_close( snd_devhandle ); 
  return -1;
 }

 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

 pthread_create(&thread_id,&attr,mixer_thread,NULL);
 pthread_attr_destroy(&attr);

 digi_initialised = 1;
 return 0;
}
Example #15
0
/**
 * This method prepares ALSA system for 22050hz signed 16bits Little Endian
 * playback.
 */
void SoundThread::initAlsa()
{
	int err;
	ostringstream oss;

	/* Get a handle on the PCM device. */

	if ((err = snd_pcm_open (&playback_handle, deviceName, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
	{
		oss << "cannot open audio device : " << deviceName << snd_strerror(err) << endl;
		throw oss.str();
	}

	/* Allocate snd_pcm_hw_params_t structure. */
	if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0)
	{
		oss << "cannot allocate hardware parameter structure : " << snd_strerror (err) << endl;
		throw oss.str();
	}

	/* Retrieve current parameters. */
	if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0)
	{
		oss << "cannot initialize hardware parameter structure : " << snd_strerror (err) << endl;
		throw oss.str();
	}


	/* Set Sample are NON Interleaved (mono !) */
	if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED)) < 0)
	{
		oss << "cannot set access type : " << snd_strerror (err) << endl;
		throw oss.str();
	}

	/* Set Sample format: Signed 16bit little endian. */
	if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0)
	{
		oss << "cannot set sample format : " << snd_strerror (err) << endl;
		throw oss.str();
	}

	/* Set the Sample rate. */
	if ((err = snd_pcm_hw_params_set_rate (playback_handle, hw_params, 22050, 0)) < 0)
	{
		oss << "cannot set sample rate : " << snd_strerror (err) << endl;
		throw oss.str();
	}

	/* Set Channel number (MONO). */
	if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 1)) < 0)
	{
		oss << "cannot set channel count : " << snd_strerror (err) << endl;
		throw oss.str();
	}


	if ((err = snd_pcm_hw_params_set_buffer_size(playback_handle, hw_params, 2048)) < 0)
	{
		oss << "cannot set channel buffer size : " << snd_strerror (err) << endl;
		throw oss.str();
	}



	/* Apply these parameters. */
	if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0)
	{
		oss << "cannot apply parameters : " << snd_strerror (err) << endl;
		throw oss.str();
	}

	snd_pcm_uframes_t bufferSize;
	snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize );
	//cout << "initAlsa: Buffer size = " << bufferSize << " frames." << endl;

	/* Free memoray allocated for snd_pcm_hw_params_t */
	snd_pcm_hw_params_free (hw_params);

	/* tell ALSA to wake us up whenever 4096 or more frames
	   of playback data can be delivered. Also, tell
	   ALSA that we'll start the device ourselves.
	*/

	/* Allocate snd_pcm_sw_params_t structure. */
	if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0)
	{
		oss << "cannot allocate software parameters structure : " << snd_strerror (err) << endl;
		throw oss.str();
	}

	/* Get the current software configuration*/
	if ((err = snd_pcm_sw_params_current (playback_handle, sw_params)) < 0)
	{
		oss << "cannot initialize software parameters structure : " << snd_strerror (err) << endl;
		throw oss.str();
	}

	/* Set the wake up point to 2048 (92.9 ms). The minimum data available before asking*/
	/* for new ones. */
	if ((err = snd_pcm_sw_params_set_avail_min (playback_handle, sw_params, 2048U)) < 0)
	{
		oss << "cannot set minimum available count : " << snd_strerror (err) << endl;
		throw oss.str();
	}

	/* Set when ALSA starts to play. */
	if ((err = snd_pcm_sw_params_set_start_threshold (playback_handle, sw_params, 1024U)) < 0)
	{
		oss << "cannot set start mode : " << snd_strerror (err) << endl;
		throw oss.str();
	}

	/* Apply parameters. */
	if ((err = snd_pcm_sw_params (playback_handle, sw_params)) < 0)
	{
		oss << "cannot apply software parameters : " << snd_strerror (err) << endl;
		throw oss.str();
	}

	/* the interface will interrupt the kernel every 4096 frames, and ALSA
	   will wake up this program very soon after that.
	*/

	if ((err = snd_pcm_prepare (playback_handle)) < 0)
	{
		oss << "cannot prepare audio interface for use : " << snd_strerror (err) << endl;
		throw oss.str();
	}
}
Example #16
0
Player::Player() {
//    printf("Player::Player()\n");
    int rc=0;
    unsigned int val=0;
    int dir=0;
    /* Open PCM device for playback. */
    rc = snd_pcm_open(&(this->m_pHandle), "default",
                SND_PCM_STREAM_PLAYBACK, 0);
    if (rc < 0) {
        printf("unable to open pcm device: %s\n",
                snd_strerror(rc));
        exit(1);
    }

    /* Allocate a hardware parameters object. */
    snd_pcm_hw_params_alloca(&(this->m_pParams));

    /* Fill it in with default values. */
    rc = snd_pcm_hw_params_any(this->m_pHandle, this->m_pParams);
    if (rc < 0) {
        printf("Can not configure this PCM device: %s\n",
                snd_strerror(rc));
        exit(1);
    }
    /* Set the desired hardware parameters. */

    /* Interleaved mode */
    rc = snd_pcm_hw_params_set_access(this->m_pHandle, this->m_pParams,
                    SND_PCM_ACCESS_RW_INTERLEAVED);
    if (rc < 0) {
        printf("Failed to set PCM device to interleaved: %s\n",
                snd_strerror(rc));
        exit(1);
    }
    /* Signed 16-bit little-endian format */
    rc = snd_pcm_hw_params_set_format(this->m_pHandle, this->m_pParams,
                    SND_PCM_FORMAT_S16_LE);
    if (rc < 0) {
        printf("Failed to set PCM device to 16-bit signed PCM: %s\n",
                snd_strerror(rc));
        exit(1);
    }
    /* Two channels (mono) */
    rc = snd_pcm_hw_params_set_channels(this->m_pHandle, this->m_pParams,channels);
    if (rc < 0) {
        printf("Failed to set PCM device to mono: %s\n",
                snd_strerror(rc));
        exit(1);
    }
    /* 44100 bits/second sampling rate (CD quality) */
    val = rate;
    rc = snd_pcm_hw_params_set_rate_near(this->m_pHandle, this->m_pParams,
                    &val, 0);
    if (rc < 0) {
        printf("Failed to set PCM device to sample rate =%d: %s\n",
                rate,snd_strerror(rc));
        exit(1);
    }
	if(val != rate){
		printf("Rate doesn't match (request %iHz, get %iHz\n",rate,val);
		exit(1);
	}


	rc = snd_pcm_hw_params_set_buffer_time_near(this->m_pHandle, this->m_pParams, &buffer_time, &dir);
    if (rc < 0) {
        fprintf(stderr, "Failed to set PCM device to buffer time=%d: %s\n",
                    val,snd_strerror(rc));
        exit(1);
    }

	rc = snd_pcm_hw_params_set_period_time_near(this->m_pHandle, this->m_pParams, &period_time, &dir);
	if (rc < 0) {
        fprintf(stderr, "Failed to set PCM device to period time=%d: %s\n",
                    val,snd_strerror(rc));
        exit(1);
    }
	
	//chunk size
	rc = snd_pcm_hw_params_get_period_size(this->m_pParams, &period_size, &dir);
	if(rc < 0){
		fprintf(stderr, "Failed to get period size for capture: %s\n", snd_strerror(rc));
		exit(1);
	}
	this->m_frames = period_size;

	rc = snd_pcm_hw_params_get_buffer_size(this->m_pParams, &buffer_size);
	if(rc < 0){
		fprintf(stderr, "Failed to get buffer size for capture: %s\n", snd_strerror(rc));
		exit(1);
	}

#ifdef DEBUG
	printf("Recorder alsa driver hw params setting\n");
	printf("period size =%d frames\n", (int)period_size);
	printf("buffer size =%d frames\n", (int)buffer_size);
	snd_pcm_hw_params_get_period_time(this->m_pParams,&val, &dir);
	printf("period time =%d us\n",val);
	snd_pcm_hw_params_get_buffer_time(this->m_pParams,&val, &dir);
	printf("buffer time =%d us\n", val);
	snd_pcm_hw_params_get_periods(this->m_pParams, &val, &dir);
	printf("period per buffer =%d frames\n", val);
#endif	

   /* Write the parameters to the driver */
    rc = snd_pcm_hw_params(this->m_pHandle, this->m_pParams);
    if (rc < 0) {
        printf("unable to set hw parameters: %s\n",
                    snd_strerror(rc));
        exit(1);
    }
    
#ifdef ALSA_OPT
	snd_pcm_sw_params_t *swparams;
	snd_pcm_sw_params_alloca(&swparams);

    /* get the current swparams */
    rc = snd_pcm_sw_params_current(this->m_pHandle, swparams);
    if (rc < 0) {
            printf("Unable to determine current swparams for playback: %s\n", snd_strerror(rc));
            exit(1);
    }
    /* start the transfer when the buffer is almost full: */
    /* (buffer_size / avail_min) * avail_min */
    rc = snd_pcm_sw_params_set_start_threshold(this->m_pHandle, swparams, (buffer_size / period_size) * period_size);
    if (rc < 0) {
            printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(rc));
            exit(1);
    }

    rc = snd_pcm_sw_params_set_avail_min(this->m_pHandle, swparams, period_size);
    if (rc < 0) {
            printf("Unable to set avail min for playback: %s\n", snd_strerror(rc));
            exit(1);
    }
    /* write the parameters to the playback device */
    rc = snd_pcm_sw_params(this->m_pHandle, swparams);
    if (rc < 0) {
            printf("Unable to set sw params for playback: %s\n", snd_strerror(rc));
            exit(1);
    }

#endif
}
Example #17
0
/*------------------------------------------------------------------------------
 *  Open the audio source
 *----------------------------------------------------------------------------*/
bool
AlsaDspSource :: open ( void )                       throw ( Exception )
{
    unsigned int        u;
    snd_pcm_format_t    format;
    snd_pcm_hw_params_t *hwParams;

    if ( isOpen() ) {
        return false;
    }

    switch ( getBitsPerSample() ) {
        case 8:
            format = SND_PCM_FORMAT_S8;
            break;

        case 16:
            format = SND_PCM_FORMAT_S16;
            break;
            
        default:
            return false;
    }

    if (snd_pcm_open(&captureHandle, pcmName, SND_PCM_STREAM_CAPTURE, 0) < 0) {
        captureHandle = 0;
        return false;
    }

    if (snd_pcm_hw_params_malloc(&hwParams) < 0) {
        close();
        throw Exception( __FILE__, __LINE__, "can't alloc hardware "\
                        "parameter structure");
    }

    if (snd_pcm_hw_params_any(captureHandle, hwParams) < 0) {
        snd_pcm_hw_params_free(hwParams);
        close();
        throw Exception( __FILE__, __LINE__, "can't initialize hardware "\
                        "parameter structure");
    }

    if (snd_pcm_hw_params_set_access(captureHandle, hwParams,
                                     SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
        snd_pcm_hw_params_free(hwParams);
        close();
        throw Exception( __FILE__, __LINE__, "can't set access type");
    }

    if (snd_pcm_hw_params_set_format(captureHandle, hwParams, format) < 0) {
        snd_pcm_hw_params_free(hwParams);
        close();
        throw Exception( __FILE__, __LINE__, "can't set sample format");
    }

    u = getSampleRate();
    if (snd_pcm_hw_params_set_rate_near(captureHandle, hwParams, &u, 0) < 0) {
        snd_pcm_hw_params_free(hwParams);
        close();
        throw Exception( __FILE__, __LINE__, "can't set sample rate", u);
    }

    u = getChannel();
    if (snd_pcm_hw_params_set_channels(captureHandle, hwParams, u) < 0) {
        snd_pcm_hw_params_free(hwParams);
        close();
        throw Exception( __FILE__, __LINE__, "can't set channels", u);
    }

    u = 4;
    if (snd_pcm_hw_params_set_periods_near(captureHandle, hwParams, &u, 0)
                                                                          < 0) {
        snd_pcm_hw_params_free(hwParams);
        close();
        throw Exception( __FILE__, __LINE__, "can't set interrupt frequency");
    }

    u = getBufferTime();
    if (snd_pcm_hw_params_set_buffer_time_near(captureHandle, hwParams, &u, 0)
                                                                          < 0) {
        snd_pcm_hw_params_free(hwParams);
        close();
        throw Exception( __FILE__, __LINE__, "can't set buffer size");
    }

    if (snd_pcm_hw_params(captureHandle, hwParams) < 0) {
        snd_pcm_hw_params_free(hwParams);
        close();
        throw Exception( __FILE__, __LINE__, "can't set hardware parameters");
    }

    snd_pcm_hw_params_free(hwParams);

    if (snd_pcm_prepare(captureHandle) < 0) {
        close();
        throw Exception( __FILE__, __LINE__, "can't prepare audio interface "\
                        "for use");
    }

    bytesPerFrame = getChannel() * getBitsPerSample() / 8;

    return true;
}
Example #18
0
static void SetOptions(unsigned int rate, int opt)
{
	int err;
	snd_pcm_format_t format;
	unsigned int val;
	/* start with setting default values, if we bail out */
	plrRate=rate;
	plrOpt=opt;

	alsaOpenDevice();
	if (!alsa_pcm)
		return;

#ifdef ALSA_DEBUG
	fprintf(stderr, "ALSA snd_pcm_hw_params_any(alsa_pcm, hwparams) = ");
#endif
	if ((err=snd_pcm_hw_params_any(alsa_pcm, hwparams))<0) /* we need to check for <0 here, due to a bug in the ALSA PulseAudio plugin */
	{
#ifdef ALSA_DEBUG
		fprintf(stderr, "failed: %s\n", snd_strerror(-err));
#endif
		fprintf(stderr, "ALSA: snd_pcm_hw_params_any() failed: %s\n", snd_strerror(-err));
		return;
	}
#ifdef ALSA_DEBUG
	fprintf(stderr, "ok\n");
	fprintf(stderr, "ALSA snd_pcm_hw_params_set_access(alsa_pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) = ");
#endif

	if ((err=snd_pcm_hw_params_set_access(alsa_pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)))
	{

#ifdef ALSA_DEBUG
		fprintf(stderr, "failed: %s\n", snd_strerror(-err));
#endif
		fprintf(stderr, "ALSA: snd_pcm_hw_params_set_access() failed: %s\n", snd_strerror(-err));
		return;
	}
#ifdef ALSA_DEBUG
	fprintf(stderr, "ok\n");
#endif
	if (opt&PLR_16BIT)
		if (opt&PLR_SIGNEDOUT)
			format=SND_PCM_FORMAT_S16;
		else
			format=SND_PCM_FORMAT_U16;
	else
		if (opt&PLR_SIGNEDOUT)
			format=SND_PCM_FORMAT_S8;
		else
			format=SND_PCM_FORMAT_U8;
#ifdef ALSA_DEBUG
	fprintf(stderr, "ALSA snd_pcm_hw_params_set_format(alsa_pcm, hwparams, format %i) = ", format);
#endif
	if ((err=snd_pcm_hw_params_set_format(alsa_pcm, hwparams, format)))
	{
#ifdef ALSA_DEBUG
		fprintf(stderr, "failed: %s\n", snd_strerror(-err));
		fprintf(stderr, "ALSA snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_S16) = ");
#endif
		if ((err=snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_S16))==0)
		{
			opt|=PLR_16BIT|PLR_SIGNEDOUT;
		} else {
#ifdef ALSA_DEBUG
			fprintf(stderr, "failed: %s\n", snd_strerror(-err));
			fprintf(stderr, "ALSA snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_U16) = ");
#endif
			if ((err=snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_U16))==0)
			{
				opt&=~(PLR_16BIT|PLR_SIGNEDOUT);
				opt|=PLR_16BIT;
			} else 
			{
#ifdef ALSA_DEBUG
			fprintf(stderr, "failed: %s\n", snd_strerror(-err));
			fprintf(stderr, "ALSA snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_S8) = ");
#endif
			if ((err=snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_S8))>=0)
				{
					opt&=~(PLR_16BIT|PLR_SIGNEDOUT);
					opt|=PLR_SIGNEDOUT;
				} else 
				{
#ifdef ALSA_DEBUG
				fprintf(stderr, "failed: %s\n", snd_strerror(-err));
				fprintf(stderr, "ALSA snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_U8) = ");
#endif
					if ((err=snd_pcm_hw_params_set_format(alsa_pcm, hwparams, SND_PCM_FORMAT_U8))>=0)
					{
						opt&=~(PLR_16BIT|PLR_SIGNEDOUT);
					} else {
#ifdef ALSA_DEBUG
						fprintf(stderr, "failed: %s\n", snd_strerror(-err));
#endif
						fprintf(stderr, "ALSA: snd_pcm_hw_params_set_format() failed: %s\n", snd_strerror(-err));
						return;
					}
				}
			}
		}
	}
#ifdef ALSA_DEBUG
	fprintf(stderr, "ok\n");
#endif
	bit16=!!(opt&PLR_16BIT);
	if (opt&PLR_STEREO)
		val=2;
	else
		val=1;
#ifdef ALSA_DEBUG
	fprintf(stderr, "ALSA snd_pcm_hw_params_set_channels_near(alsa_pcm, hwparams, &channels=%i) = ", val);
#endif
	if ((err=snd_pcm_hw_params_set_channels_near(alsa_pcm, hwparams, &val))<0)
	{
#ifdef ALSA_DEBUG
		fprintf(stderr, "failed: %s\n", snd_strerror(-err));
#endif
		fprintf(stderr, "ALSA: snd_pcm_hw_params_set_channels_near() failed: %s\n", snd_strerror(-err));
		return;
	}
#ifdef ALSA_DEBUG
	fprintf(stderr, "ok (channels=%i)\n", val);
#endif
	if (val==1)
	{
		stereo=0;
		opt&=~PLR_STEREO;
	} else if (val==2)
	{
		stereo=1;
		opt|=PLR_STEREO;
	} else {
		fprintf(stderr, "ALSA: snd_pcm_hw_params_set_channels_near() gave us %d channels\n", val);
		return;
	}
#ifdef ALSA_DEBUG
	fprintf(stderr, "ALSA snd_pcm_hw_params_set_rate_near(alsa_pcm, hwparams, &rate = %i, 0) = ", rate);
#endif
	if ((err=snd_pcm_hw_params_set_rate_near(alsa_pcm, hwparams, &rate, 0))<0)
	{
#ifdef ALSA_DEBUG
		fprintf(stderr, "failed: %s\n", snd_strerror(-err));
#endif
		fprintf(stderr, "ALSA: snd_pcm_hw_params_set_rate_near() failed: %s\n", snd_strerror(-err));
		return;
	}
#ifdef ALSA_DEBUG
	fprintf(stderr, "ok, rate=%i\n", rate);
#endif
	if (rate==0)
	{
		fprintf(stderr, "ALSA: No usable samplerate available.\n");
		return;
	}
#ifdef ALSA_DEBUG
	fprintf(stderr, "ALSA snd_pcm_hw_params_set_buffer_time_near(alsa_pcm, hwparams, 500000 uS, 0) = ");
#endif
	val = 500000;
	if ((err=snd_pcm_hw_params_set_buffer_time_near(alsa_pcm, hwparams, &val, 0)))
	{
#ifdef ALSA_DEBUG
		fprintf(stderr, "failed: %s\n", snd_strerror(-err));
#endif
		fprintf(stderr, "ALSA: snd_pcm_hw_params_set_buffer_time_near() failed: %s\n", snd_strerror(-err));
		return;
	}
#ifdef ALSA_DEBUG
	fprintf(stderr, "ok, latency = %d uS\n", val);
	fprintf(stderr, "ALSA snd_pcm_hw_params(alsa_pcm, hwparams) = ");
#endif
	if ((err=snd_pcm_hw_params(alsa_pcm, hwparams))<0)
	{
#ifdef ALSA_DEBUG
		fprintf(stderr, "failed: %s\n", snd_strerror(-err));
#endif
		fprintf(stderr, "ALSA: snd_pcm_hw_params() failed: %s\n", snd_strerror(-err));
		return;
	}
#ifdef ALSA_DEBUG
	fprintf(stderr, "ok\n");
	fprintf(stderr, "ALSA snd_pcm_sw_params_current(alsa_pcm, swparams) = ");
#endif
	if ((err=snd_pcm_sw_params_current(alsa_pcm, swparams))<0)
	{
#ifdef ALSA_DEBUG
		fprintf(stderr, "failed: %s\n", snd_strerror(-err));
#endif
		fprintf(stderr, "ALSA: snd_pcm_sw_params_any() failed: %s\n", snd_strerror(-err));
		return;
	}
#ifdef ALSA_DEBUG
	fprintf(stderr, "ok\n");
	fprintf(stderr, "ALSA snd_pcm_sw_params(alsa_pcm, swparams) = ");
#endif
	if ((err=snd_pcm_sw_params(alsa_pcm, swparams))<0)
	{
#ifdef ALSA_DEBUG
		fprintf(stderr, "failed: %s\n", snd_strerror(-err));
#endif
		fprintf(stderr, "ALSA: snd_pcm_sw_params() failed: %s\n", snd_strerror(-err));
		return;
	}
#ifdef ALSA_DEBUG
	fprintf(stderr, "ok\n");
#endif
	plrRate=rate;
	plrOpt=opt;
}
Example #19
0
static int set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm)
{
	snd_pcm_hw_params_t *params;
	unsigned int buffer_time = 0;
	unsigned int period_time = 0;
	unsigned int rate;
	int err;
	const char *device_name = snd_pcm_name(sndpcm->handle);

	/* Allocate a hardware parameters object. */
	snd_pcm_hw_params_alloca(&params);

	/* Fill it in with default values. */
	err = snd_pcm_hw_params_any(sndpcm->handle, params);
	if (err < 0) {
		fprintf(bat->err, _("Set parameter to device error: "));
		fprintf(bat->err, _("default params: %s: %s(%d)\n"),
				device_name, snd_strerror(err), err);
		return err;
	}

	/* Set access mode */
	err = snd_pcm_hw_params_set_access(sndpcm->handle, params,
			SND_PCM_ACCESS_RW_INTERLEAVED);
	if (err < 0) {
		fprintf(bat->err, _("Set parameter to device error: "));
		fprintf(bat->err, _("access type: %s: %s(%d)\n"),
				device_name, snd_strerror(err), err);
		return err;
	}

	/* Set format */
	err = snd_pcm_hw_params_set_format(sndpcm->handle, params, bat->format);
	if (err < 0) {
		fprintf(bat->err, _("Set parameter to device error: "));
		fprintf(bat->err, _("PCM format: %d %s: %s(%d)\n"),
				bat->format,
				device_name, snd_strerror(err), err);
		return err;
	}

	/* Set channels */
	err = snd_pcm_hw_params_set_channels(sndpcm->handle,
			params, bat->channels);
	if (err < 0) {
		fprintf(bat->err, _("Set parameter to device error: "));
		fprintf(bat->err, _("channel number: %d %s: %s(%d)\n"),
				bat->channels,
				device_name, snd_strerror(err), err);
		return err;
	}

	/* Set sampling rate */
	rate = bat->rate;
	err = snd_pcm_hw_params_set_rate_near(sndpcm->handle,
			params, &bat->rate,
			0);
	if (err < 0) {
		fprintf(bat->err, _("Set parameter to device error: "));
		fprintf(bat->err, _("sample rate: %d %s: %s(%d)\n"),
				bat->rate,
				device_name, snd_strerror(err), err);
		return err;
	}
	if ((float) rate * (1 + RATE_RANGE) < bat->rate
			|| (float) rate * (1 - RATE_RANGE) > bat->rate) {
		fprintf(bat->err, _("Invalid parameters: sample rate: "));
		fprintf(bat->err, _("requested %dHz, got %dHz\n"),
				rate, bat->rate);
		return -EINVAL;
	}

	if (snd_pcm_hw_params_get_buffer_time_max(params,
			&buffer_time, 0) < 0) {
		fprintf(bat->err, _("Get parameter from device error: "));
		fprintf(bat->err, _("buffer time: %d %s: %s(%d)\n"),
				buffer_time,
				device_name, snd_strerror(err), err);
		return -EINVAL;
	}

	if (buffer_time > MAX_BUFFERTIME)
		buffer_time = MAX_BUFFERTIME;

	period_time = buffer_time / DIV_BUFFERTIME;

	/* Set buffer time and period time */
	err = snd_pcm_hw_params_set_buffer_time_near(sndpcm->handle, params,
			&buffer_time, 0);
	if (err < 0) {
		fprintf(bat->err, _("Set parameter to device error: "));
		fprintf(bat->err, _("buffer time: %d %s: %s(%d)\n"),
				buffer_time,
				device_name, snd_strerror(err), err);
		return err;
	}

	err = snd_pcm_hw_params_set_period_time_near(sndpcm->handle, params,
			&period_time, 0);
	if (err < 0) {
		fprintf(bat->err, _("Set parameter to device error: "));
		fprintf(bat->err, _("period time: %d %s: %s(%d)\n"),
				period_time,
				device_name, snd_strerror(err), err);
		return err;
	}

	/* Write the parameters to the driver */
	if (snd_pcm_hw_params(sndpcm->handle, params) < 0) {
		fprintf(bat->err, _("Set parameter to device error: "));
		fprintf(bat->err, _("hw params: %s: %s(%d)\n"),
				device_name, snd_strerror(err), err);
		return -EINVAL;
	}

	err = snd_pcm_hw_params_get_period_size(params,
			&sndpcm->period_size, 0);
	if (err < 0) {
		fprintf(bat->err, _("Get parameter from device error: "));
		fprintf(bat->err, _("period size: %lu %s: %s(%d)\n"),
				sndpcm->period_size,
				device_name, snd_strerror(err), err);
		return err;
	}

	err = snd_pcm_hw_params_get_buffer_size(params, &sndpcm->buffer_size);
	if (err < 0) {
		fprintf(bat->err, _("Get parameter from device error: "));
		fprintf(bat->err, _("buffer size: %lu %s: %s(%d)\n"),
				sndpcm->buffer_size,
				device_name, snd_strerror(err), err);
		return err;
	}

	if (sndpcm->period_size == sndpcm->buffer_size) {
		fprintf(bat->err, _("Invalid parameters: can't use period "));
		fprintf(bat->err, _("equal to buffer size (%lu)\n"),
				sndpcm->period_size);
		return -EINVAL;
	}

	err = snd_pcm_format_physical_width(bat->format);
	if (err < 0) {
		fprintf(bat->err, _("Invalid parameters: "));
		fprintf(bat->err, _("snd_pcm_format_physical_width: %d\n"),
				err);
		return err;
	}
	sndpcm->sample_bits = err;

	sndpcm->frame_bits = sndpcm->sample_bits * bat->channels;

	/* Calculate the period bytes */
	sndpcm->period_bytes = sndpcm->period_size * sndpcm->frame_bits / 8;
	sndpcm->buffer = (char *) malloc(sndpcm->period_bytes);
	if (sndpcm->buffer == NULL) {
		fprintf(bat->err, _("Not enough memory: size=%zd\n"),
				sndpcm->period_bytes);
		return -ENOMEM;
	}

	return 0;
}
Example #20
0
int setup_pcmdev(char *pcm_name)
{
  snd_pcm_hw_params_t *params;
  snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; 
  int rate = 44100, dir;
  snd_pcm_uframes_t persize, persize2;

  int maxrate, minrate;
  unsigned int pertime, perTmin, perTmax;
  snd_pcm_uframes_t bufsize, perSmin, perSmax, bufSmin, bufSmax;
  

  /* Allocate the snd_pcm_hw_params_t structure on the stack. */ 
  snd_pcm_hw_params_alloca(&params);
  
  /* Open PCM device for playback. */
  if (snd_pcm_open(&handle, pcm_name, stream, 0) < 0) {
    fprintf(stderr, "Error opening PCM device %s\n", pcm_name);
    return(-1);
  }
  
  /* Init params with full configuration space */
  if (snd_pcm_hw_params_any(handle, params) < 0) {
    fprintf(stderr, "Can not configure this PCM device.\n");
    return(-1);
  }
  
  /* set interleaved mode */
  if (snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
    fprintf(stderr, "Error setting access.\n");
    return(-1);
  }
  
  /* Set sample format */
  if (snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE) < 0) {
    fprintf(stderr, "Error setting format.\n");
    return(-1);
  }
  
  /* Set sample rate.*/ 
  if (snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0) < 0) {
    fprintf(stderr, "Error setting rate.\n");
    return(-1);
  }
  
  /* Set number of channels */
  if (snd_pcm_hw_params_set_channels(handle, params, nchan) < 0) {
    fprintf(stderr, "Error setting channels.\n");
    return(-1);
  }
  
  /* Set period size to n frames (samples). */
  persize = 1024; dir=0;
  if (snd_pcm_hw_params_set_period_size_near(handle,params, &persize, &dir)< 0) {
    fprintf(stderr, "Error setting period size to %d.\n", (int) persize);
    return(-1);
  }
    
  
  /* Apply HW parameter settings to PCM device */
  if (snd_pcm_hw_params(handle, params) < 0) {
    fprintf(stderr, "Error setting HW params.\n");
    return(-1);
  }

  /*get some inof about the hardware*/
  
  // printf("\n ---------- hardware parameters ------------ \n");
  snd_pcm_hw_params_get_rate_min (params, &minrate, &dir);
  //printf("min rate: %d samples per sec\n",minrate);
  snd_pcm_hw_params_get_rate_max (params, &maxrate, &dir);
  //printf("max rate: %d samples per sec\n",maxrate);
  snd_pcm_hw_params_get_period_time (params, &pertime, &dir);
  //printf("period: %d microseconds\n",pertime);
  snd_pcm_hw_params_get_period_time_min (params, &perTmin, &dir);
  snd_pcm_hw_params_get_period_time_min (params, &perTmax, &dir);
  //printf("min period time: %d microseconds\n",perTmin);
  //printf("max period time: %d microseconds\n",perTmax);
  snd_pcm_hw_params_get_period_size (params, &persize2, &dir);
  //printf("period: %d frames\n",(int) persize2);
  snd_pcm_hw_params_get_period_size_min (params, &perSmin, &dir);
  snd_pcm_hw_params_get_period_size_min (params, &perSmax, &dir);
  //printf("min period size: %d frames\n",(int) perSmin);
  //printf("max period size: %d frames\n",(int) perSmax);
  snd_pcm_hw_params_get_buffer_size (params, &bufsize);
  //printf("buffer size: %d frames\n",(int) bufsize);
  snd_pcm_hw_params_get_buffer_size_min (params, &bufSmin);
  snd_pcm_hw_params_get_buffer_size_min (params, &bufSmax);
  //printf("min buffer size: %d frames\n",(int) bufSmin);
  //printf("max buffer size: %d frames\n",(int) bufSmax);
  
  return (double) persize2;
}
Example #21
0
static void
alsa_configure (struct sound_device *sd)
{
  int val, err, dir;
  unsigned uval;
  struct alsa_params *p = (struct alsa_params *) sd->data;
  snd_pcm_uframes_t buffer_size;

  eassert (p->handle != 0);

  err = snd_pcm_hw_params_malloc (&p->hwparams);
  if (err < 0)
    alsa_sound_perror ("Could not allocate hardware parameter structure", err);

  err = snd_pcm_sw_params_malloc (&p->swparams);
  if (err < 0)
    alsa_sound_perror ("Could not allocate software parameter structure", err);

  err = snd_pcm_hw_params_any (p->handle, p->hwparams);
  if (err < 0)
    alsa_sound_perror ("Could not initialize hardware parameter structure", err);

  err = snd_pcm_hw_params_set_access (p->handle, p->hwparams,
                                      SND_PCM_ACCESS_RW_INTERLEAVED);
  if (err < 0)
    alsa_sound_perror ("Could not set access type", err);

  val = sd->format;
  err = snd_pcm_hw_params_set_format (p->handle, p->hwparams, val);
  if (err < 0)
    alsa_sound_perror ("Could not set sound format", err);

  uval = sd->sample_rate;
  err = snd_pcm_hw_params_set_rate_near (p->handle, p->hwparams, &uval, 0);
  if (err < 0)
    alsa_sound_perror ("Could not set sample rate", err);

  val = sd->channels;
  err = snd_pcm_hw_params_set_channels (p->handle, p->hwparams, val);
  if (err < 0)
    alsa_sound_perror ("Could not set channel count", err);

  err = snd_pcm_hw_params (p->handle, p->hwparams);
  if (err < 0)
    alsa_sound_perror ("Could not set parameters", err);


  err = snd_pcm_hw_params_get_period_size (p->hwparams, &p->period_size, &dir);
  if (err < 0)
    alsa_sound_perror ("Unable to get period size for playback", err);

  err = snd_pcm_hw_params_get_buffer_size (p->hwparams, &buffer_size);
  if (err < 0)
    alsa_sound_perror ("Unable to get buffer size for playback", err);

  err = snd_pcm_sw_params_current (p->handle, p->swparams);
  if (err < 0)
    alsa_sound_perror ("Unable to determine current swparams for playback",
                       err);

  /* Start the transfer when the buffer is almost full */
  err = snd_pcm_sw_params_set_start_threshold (p->handle, p->swparams,
                                               (buffer_size / p->period_size)
                                               * p->period_size);
  if (err < 0)
    alsa_sound_perror ("Unable to set start threshold mode for playback", err);

  /* Allow the transfer when at least period_size samples can be processed */
  err = snd_pcm_sw_params_set_avail_min (p->handle, p->swparams, p->period_size);
  if (err < 0)
    alsa_sound_perror ("Unable to set avail min for playback", err);

  err = snd_pcm_sw_params (p->handle, p->swparams);
  if (err < 0)
    alsa_sound_perror ("Unable to set sw params for playback\n", err);

  snd_pcm_hw_params_free (p->hwparams);
  p->hwparams = NULL;
  snd_pcm_sw_params_free (p->swparams);
  p->swparams = NULL;

  err = snd_pcm_prepare (p->handle);
  if (err < 0)
    alsa_sound_perror ("Could not prepare audio interface for use", err);

  if (sd->volume > 0)
    {
      int chn;
      snd_mixer_t *handle;
      snd_mixer_elem_t *e;
      if (snd_mixer_open (&handle, 0) >= 0)
        {
	  char const *file = string_default (sd->file,
					     DEFAULT_ALSA_SOUND_DEVICE);
          if (snd_mixer_attach (handle, file) >= 0
              && snd_mixer_load (handle) >= 0
              && snd_mixer_selem_register (handle, NULL, NULL) >= 0)
            for (e = snd_mixer_first_elem (handle);
                 e;
                 e = snd_mixer_elem_next (e))
              {
                if (snd_mixer_selem_has_playback_volume (e))
                  {
                    long pmin, pmax, vol;
                    snd_mixer_selem_get_playback_volume_range (e, &pmin, &pmax);
                    vol = pmin + (sd->volume * (pmax - pmin)) / 100;

                    for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++)
                      snd_mixer_selem_set_playback_volume (e, chn, vol);
                  }
              }
          snd_mixer_close (handle);
        }
    }
}
Example #22
0
static snd_pcm_uframes_t set_params(snd_pcm_t *handle, snd_pcm_stream_t stream)
{
	snd_pcm_hw_params_t *params;
	snd_pcm_sw_params_t *swparams;
	snd_pcm_uframes_t buffer_size;
	snd_pcm_uframes_t chunk_size = 0;
	snd_pcm_uframes_t start_threshold;
	unsigned period_time = 0;
	unsigned buffer_time = 0;
	size_t chunk_bytes = 0;
	int err;

	snd_pcm_hw_params_alloca(&params);
	snd_pcm_sw_params_alloca(&swparams);

	err = snd_pcm_hw_params_any(handle, params);
	if (err < 0) {
		printf("Broken configuration for this PCM: no configurations available");
		exit(EXIT_FAILURE);
	}

	err = snd_pcm_hw_params_set_access(handle, params,
						   SND_PCM_ACCESS_RW_INTERLEAVED);
	if (err < 0) {
		printf("Access type not available");
		exit(EXIT_FAILURE);
	}

    printf("format = %s, channels = %d, rate = %d\n",
            snd_pcm_format_name(hwparams.format),hwparams.channels,hwparams.rate);

	//err = snd_pcm_hw_params_set_format(handle, params, hwparams.format);
    err = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
	if (err < 0) {
		printf("Sample format non available");
		exit(EXIT_FAILURE);
	}

	//err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels);
    err = snd_pcm_hw_params_set_channels(handle, params, 2);
	if (err < 0) {
		printf("Channels count non available");
		exit(EXIT_FAILURE);
	}

#if 0
	//add by yjc 2012/08/21
	err = set_audio_clk_freq(hwparams.rate);
	if (err < 0){
		printf("set_audio_clk_freq fail..........\n");
		exit(EXIT_FAILURE);
	}
#endif

	err = snd_pcm_hw_params_set_rate(handle, params, hwparams.rate, 0);
    if (err < 0) {
		printf("Rate non available");
		exit(EXIT_FAILURE);
	}


	err = snd_pcm_hw_params_get_buffer_time_max(params,
						    &buffer_time, 0);
	assert(err >= 0);
	if (buffer_time > 500000)
		buffer_time = 500000;


	period_time = buffer_time / 4;

	err = snd_pcm_hw_params_set_period_time_near(handle, params,
		                        &period_time, 0);
	assert(err >= 0);

	err = snd_pcm_hw_params_set_buffer_time_near(handle, params,
							     &buffer_time, 0);

	assert(err >= 0);

	err = snd_pcm_hw_params(handle, params);
	if (err < 0) {
		printf("Unable to install hw params:");
		exit(EXIT_FAILURE);
	}
	snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
	snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
	if (chunk_size == buffer_size) {
		printf("Can't use period equal to buffer size (%lu == %lu)",
		      chunk_size, buffer_size);
		exit(EXIT_FAILURE);
	}

	snd_pcm_sw_params_current(handle, swparams);

	err = snd_pcm_sw_params_set_avail_min(handle, swparams, chunk_size);

	if(stream == SND_PCM_STREAM_PLAYBACK)
		start_threshold = (buffer_size / chunk_size) * chunk_size;
	else
		start_threshold = 1;
	err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
	assert(err >= 0);

	err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, buffer_size);
	assert(err >= 0);

	if (snd_pcm_sw_params(handle, swparams) < 0) {
		printf("unable to install sw params:");
		exit(EXIT_FAILURE);
	}

	//bits_per_sample = snd_pcm_format_physical_width(hwparams.format);
    bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE);
	//bits_per_frame = bits_per_sample * hwparams.channels;
	bits_per_frame = bits_per_sample * 2;
	chunk_bytes = chunk_size * bits_per_frame / 8;

    printf("chunk_size = %d,chunk_bytes = %d,buffer_size = %d\n\n",
        (int)chunk_size,chunk_bytes,(int)buffer_size);

	return chunk_size;

}
Example #23
0
// input: ALSA
void* input_alsa(void* data)
{
    struct audio_data *audio = (struct audio_data *)data;
    signed char *buffer;
    snd_pcm_t *handle;
    snd_pcm_hw_params_t *params;
    unsigned int val;
    snd_pcm_uframes_t frames;
    val = 44100;
    int i, n, o, size, dir, err;
    int tempr, templ;
    int radj, ladj;

    // alsa: open device to capture audio
    if ((err = snd_pcm_open(&handle, audio-> source, SND_PCM_STREAM_CAPTURE, 0) < 0)) {
        fprintf(stderr,
                "error opening stream: %s\n",
                snd_strerror(err));
        exit(EXIT_FAILURE);
    }

    #ifdef DEBUG
        else printf("open stream successful\n");
    #endif

    snd_pcm_hw_params_alloca(&params); //assembling params
    snd_pcm_hw_params_any (handle, params); //setting defaults or something
    snd_pcm_hw_params_set_access(handle, params,
                                 SND_PCM_ACCESS_RW_INTERLEAVED); //interleaved mode right left right left
    snd_pcm_hw_params_set_format(handle, params,
                                 SND_PCM_FORMAT_S16_LE); //trying to set 16bit
    snd_pcm_hw_params_set_channels(handle, params, 2); //assuming stereo
    val = 44100;
    snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); //trying 44100 rate
    frames = 256;
    snd_pcm_hw_params_set_period_size_near(handle, params, &frames,
                                           &dir); //number of frames pr read

    err = snd_pcm_hw_params(handle, params); //attempting to set params
    if (err < 0) {
        fprintf(stderr,
                "unable to set hw parameters: %s\n",
                snd_strerror(err));
        exit(EXIT_FAILURE);
    }

    snd_pcm_hw_params_get_format(params,
                                 (snd_pcm_format_t * )&val); //getting actual format
    //converting result to number of bits
    if (val < 6)audio->format = 16;
    else if (val > 5 && val < 10)audio->format = 24;
    else if (val > 9)audio->format = 32;

    snd_pcm_hw_params_get_rate(params, &audio->rate, &dir); //getting rate
    snd_pcm_hw_params_get_period_size(params, &frames, &dir);
    snd_pcm_hw_params_get_period_time(params,  &val, &dir);

    size = frames * (audio->format / 8) * 2; // frames * bits/8 * 2 channels
    buffer = malloc(size);
    radj = audio->format / 4; //adjustments for interleaved
    ladj = audio->format / 8;
    o = 0;
    while (1) {
        err = snd_pcm_readi(handle, buffer, frames);
        if (err == -EPIPE) {
            /* EPIPE means overrun */
            #ifdef DEBUG
                fprintf(stderr, "overrun occurred\n");
            #endif
            snd_pcm_prepare(handle);
        } else if (err < 0) {
            #ifdef DEBUG
                fprintf(stderr, "error from read: %s\n", snd_strerror(err));
            #endif
        } else if (err != (int)frames) {
            #ifdef DEBUG
                fprintf(stderr, "short read, read %d %d frames\n", err, (int)frames);
            #endif
        }

        //sorting out one channel and only biggest octet
        n = 0; //frame counter
        
        for (i = 0; i < size ; i = i + (ladj) * 2) {
            //first channel
            tempr = (buffer[i + (radj) - 1]);
            //other channel
            templ = (buffer[i + (ladj) - 1]);

            //first channel
            //using the 10 upper bits this would give me a vert res of 1024, enough...
            //tempr = ((buffer[i + (radj) - 1 ] << 2)); 
            //lo = ((buffer[i + (radj) - 2] >> 6));
            //if (lo < 0)lo = abs(lo) + 1;
            //if (tempr >= 0)tempr = tempr + lo;
            //if (tempr < 0)tempr = tempr - lo;

           //other channel
            //templ = (buffer[i + (ladj) - 1] << 2);
            //lo = (buffer[i + (ladj) - 2] >> 6);
            //if (lo < 0)lo = abs(lo) + 1;
            //if (templ >= 0)templ = templ + lo;
            //else templ = templ - lo;
            //mono: adding channels and storing it in the buffer
            
            if (audio->channels == 1) audio->audio_out_l[o] = (tempr + templ) / 2;
            //stereo storing channels in buffer
            if (audio->channels == 2) {
                audio->audio_out_l[o] = templ;
                audio->audio_out_r[o] = tempr;
            }

            //o++;
            //if (o == 2047) o = 0;
            o = (o + 1) % 2047;
            n++;
        }
    }
}
Example #24
0
static int
setparams(int32 sps, snd_pcm_t * handle)
{
    snd_pcm_hw_params_t *hwparams;
    unsigned int out_sps, buffer_time, period_time;
    int err;

    snd_pcm_hw_params_alloca(&hwparams);
    err = snd_pcm_hw_params_any(handle, hwparams);
    if (err < 0) {
        fprintf(stderr, "Can not configure this PCM device: %s\n",
                snd_strerror(err));
        return -1;
    }

    err =
        snd_pcm_hw_params_set_access(handle, hwparams,
                                     SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err < 0) {
        fprintf(stderr,
                "Failed to set PCM device to interleaved: %s\n",
                snd_strerror(err));
        return -1;
    }

    err =
        snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16);
    if (err < 0) {
        fprintf(stderr,
                "Failed to set PCM device to 16-bit signed PCM: %s\n",
                snd_strerror(err));
        return -1;
    }

    err = snd_pcm_hw_params_set_channels(handle, hwparams, 1);
    if (err < 0) {
        fprintf(stderr, "Failed to set PCM device to mono: %s\n",
                snd_strerror(err));
        return -1;
    }

    out_sps = sps;
    err =
        snd_pcm_hw_params_set_rate_near(handle, hwparams, &out_sps, NULL);
    if (err < 0) {
        fprintf(stderr, "Failed to set sampling rate: %s\n",
                snd_strerror(err));
        return -1;
    }
    if (abs(out_sps - sps) > SPS_EPSILON) {
        fprintf(stderr,
                "Available samping rate %d is too far from requested %d\n",
                out_sps, sps);
        return -1;
    }

    /* Set buffer time to the maximum. */
    err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time, 0);
    period_time = buffer_time / 4;
    err = snd_pcm_hw_params_set_period_time_near(handle, hwparams,
                                                 &period_time, 0);
    if (err < 0) {
        fprintf(stderr, "Failed to set period time to %u: %s\n",
                period_time, snd_strerror(err));
        return -1;
    }
    err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams,
                                                 &buffer_time, 0);
    if (err < 0) {
        fprintf(stderr, "Failed to set buffer time to %u: %s\n",
                buffer_time, snd_strerror(err));
        return -1;
    }

    err = snd_pcm_hw_params(handle, hwparams);
    if (err < 0) {
        fprintf(stderr, "Failed to set hwparams: %s\n", snd_strerror(err));
        return -1;
    }

    err = snd_pcm_nonblock(handle, 1);
    if (err < 0) {
        fprintf(stderr, "Failed to set non-blocking mode: %s\n",
                snd_strerror(err));
        return -1;
    }
    return 0;
}
Example #25
0
AlsaDevice *alsa_device_open(char *device_name, unsigned int rate, int channels, int period)
{
   int dir;
   int err;
   snd_pcm_hw_params_t *hw_params;
   snd_pcm_sw_params_t *sw_params;
   snd_pcm_uframes_t period_size = period;
   snd_pcm_uframes_t buffer_size = PERIODS*period;
   static snd_output_t *jcd_out;
   AlsaDevice *dev = malloc(sizeof(*dev));
   if (!dev)
      return NULL;
   dev->device_name = malloc(1+strlen(device_name));
   if (!dev->device_name)
   {
      free(dev);
      return NULL;
   }
   strcpy(dev->device_name, device_name);
   dev->channels = channels;
   dev->period = period;
   err = snd_output_stdio_attach(&jcd_out, stdout, 0);
   
   if ((err = snd_pcm_open (&dev->capture_handle, dev->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
      fprintf (stderr, "cannot open audio device %s (%s)\n",
               dev->device_name,
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
      fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_any (dev->capture_handle, hw_params)) < 0) {
      fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_set_access (dev->capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
      fprintf (stderr, "cannot set access type (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_set_format (dev->capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
      fprintf (stderr, "cannot set sample format (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_set_rate_near (dev->capture_handle, hw_params, &rate, 0)) < 0) {
      fprintf (stderr, "cannot set sample rate (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   /*fprintf (stderr, "rate = %d\n", rate);*/

   if ((err = snd_pcm_hw_params_set_channels (dev->capture_handle, hw_params, channels)) < 0) {
      fprintf (stderr, "cannot set channel count (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   period_size = period;
   dir = 0;
   if ((err = snd_pcm_hw_params_set_period_size_near (dev->capture_handle, hw_params, &period_size, &dir)) < 0) {
      fprintf (stderr, "cannot set period size (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   if ((err = snd_pcm_hw_params_set_periods (dev->capture_handle, hw_params, PERIODS, 0)) < 0) {
      fprintf (stderr, "cannot set number of periods (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   buffer_size = period_size * PERIODS;
   dir=0;
   if ((err = snd_pcm_hw_params_set_buffer_size_near (dev->capture_handle, hw_params, &buffer_size)) < 0) {
      fprintf (stderr, "cannot set buffer time (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   if ((err = snd_pcm_hw_params (dev->capture_handle, hw_params)) < 0) {
      fprintf (stderr, "cannot set capture parameters (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   /*snd_pcm_dump_setup(dev->capture_handle, jcd_out);*/
   snd_pcm_hw_params_free (hw_params);

   if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) {
      fprintf (stderr, "cannot allocate software parameters structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params_current (dev->capture_handle, sw_params)) < 0) {
      fprintf (stderr, "cannot initialize software parameters structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params_set_avail_min (dev->capture_handle, sw_params, period)) < 0) {
      fprintf (stderr, "cannot set minimum available count (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params (dev->capture_handle, sw_params)) < 0) {
      fprintf (stderr, "cannot set software parameters (%s)\n",
               snd_strerror (err));
      assert(0);
   }   
   
   
   if ((err = snd_pcm_open (&dev->playback_handle, dev->device_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
      fprintf (stderr, "cannot open audio device %s (%s)\n",
               dev->device_name,
               snd_strerror (err));
      assert(0);
   }
   
   if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
      fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_any (dev->playback_handle, hw_params)) < 0) {
      fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }

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

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

   if ((err = snd_pcm_hw_params_set_rate_near (dev->playback_handle, hw_params, &rate, 0)) < 0) {
      fprintf (stderr, "cannot set sample rate (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   /*fprintf (stderr, "rate = %d\n", rate);*/

   if ((err = snd_pcm_hw_params_set_channels (dev->playback_handle, hw_params, channels)) < 0) {
      fprintf (stderr, "cannot set channel count (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   period_size = period;
   dir = 0;
   if ((err = snd_pcm_hw_params_set_period_size_near (dev->playback_handle, hw_params, &period_size, &dir)) < 0) {
      fprintf (stderr, "cannot set period size (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_hw_params_set_periods (dev->playback_handle, hw_params, PERIODS, 0)) < 0) {
      fprintf (stderr, "cannot set number of periods (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   buffer_size = period_size * PERIODS;
   dir=0;
   if ((err = snd_pcm_hw_params_set_buffer_size_near (dev->playback_handle, hw_params, &buffer_size)) < 0) {
      fprintf (stderr, "cannot set buffer time (%s)\n",
               snd_strerror (err));
      assert(0);
   }


   if ((err = snd_pcm_hw_params (dev->playback_handle, hw_params)) < 0) {
      fprintf (stderr, "cannot set playback parameters (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   /*snd_pcm_dump_setup(dev->playback_handle, jcd_out);*/
   snd_pcm_hw_params_free (hw_params);

   
   if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) {
      fprintf (stderr, "cannot allocate software parameters structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params_current (dev->playback_handle, sw_params)) < 0) {
      fprintf (stderr, "cannot initialize software parameters structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params_set_avail_min (dev->playback_handle, sw_params, period)) < 0) {
      fprintf (stderr, "cannot set minimum available count (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params_set_start_threshold (dev->playback_handle, sw_params, period)) < 0) {
      fprintf (stderr, "cannot set start mode (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params (dev->playback_handle, sw_params)) < 0) {
      fprintf (stderr, "cannot set software parameters (%s)\n",
               snd_strerror (err));
      assert(0);
   }
  
   
   snd_pcm_link(dev->capture_handle, dev->playback_handle);
   if ((err = snd_pcm_prepare (dev->capture_handle)) < 0) {
      fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_prepare (dev->playback_handle)) < 0) {
      fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   dev->readN = snd_pcm_poll_descriptors_count(dev->capture_handle);
   dev->writeN = snd_pcm_poll_descriptors_count(dev->playback_handle);

   dev->read_fd = malloc(dev->readN*sizeof(*dev->read_fd));
   /*printf ("descriptors: %d %d\n", dev->readN, dev->writeN);*/
   if (snd_pcm_poll_descriptors(dev->capture_handle, dev->read_fd, dev->readN) != dev->readN)
   {
      fprintf (stderr, "cannot obtain capture file descriptors (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   dev->write_fd = malloc(dev->writeN*sizeof(*dev->read_fd));
   if (snd_pcm_poll_descriptors(dev->playback_handle, dev->write_fd, dev->writeN) != dev->writeN)
   {
      fprintf (stderr, "cannot obtain playback file descriptors (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   return dev;
}
Example #26
0
int AlsaAudioPlugin::init(shared_ptr<t_CPC> cpc, shared_ptr<t_PSG> psg)
{
	if(!cpc->snd_enabled)
	{
		InfoLogMessage("[ALSA Audio Plugin] Not opening audio because disabled in the config");
		return 0;
	}
    /*  TODO */
    unsigned int rate = cpc->snd_playback_rate;
    int channels = cpc->snd_stereo ? 2 : 1;

	snd_pcm_format_t format = SND_PCM_FORMAT_S16;
	switch(cpc->snd_bits)
	{
		case 8:
			format = SND_PCM_FORMAT_U8;
			break;
		case 16:
			format = SND_PCM_FORMAT_S16;
			break;
		case 24:
			format = SND_PCM_FORMAT_S24;
			break;
		case 32:
			format = SND_PCM_FORMAT_S32;
			break;
		default:
			WarningLogMessage("[ALSA Audio Plugin] Warning, %d bits format unknown, fallback to %s.", cpc->snd_bits, snd_pcm_format_name(format));
	}

    int periods = 2;
    periodsize = 4096;

    unsigned int exact_rate;
    int dir, err;

    /* 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 *pcm_name = strdup("plughw:0,0");
	WarningLogMessage("TODO [%s:%d]: pcm_name need to be configurable.", __FILE__, __LINE__);
  
    /* 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(err = snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0) {
        ErrorLogMessage("[ALSA Audio Plugin] Error opening PCM device %s (Error: %s)", pcm_name, snd_strerror(err));
        return 1;
    }

    /* Init hwparams with full configuration space */
    if(err = snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
        ErrorLogMessage("[ALSA Audio Plugin] Can not configure PCM device %s. (Error: %s)", pcm_name, snd_strerror(err));
        return 1;
    }

    /* 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(err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
        ErrorLogMessage("[ALSA Audio Plugin] Error setting access on device %s. (Error: %s)", pcm_name, snd_strerror(err));
        return 1;
    }
  
    /* Set sample format */ 
    if(err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format) < 0) {
        ErrorLogMessage("[ALSA Audio Plugin] Error setting format %s on device %s. (Error: %s)", snd_pcm_format_name(format), pcm_name, snd_strerror(err));
        return 1;
    }
    
    /* Set sample rate. If the exact rate is not supported */
    /* by the hardware, use nearest possible rate.         */ 
#if 0 // Segfault... Humf... TODO
    exact_rate = rate;
    if(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, &dir) < 0)
    {
        ErrorLogMessage("Error setting rate (%d) on device %s.", rate, pcm_name);
    }
    if(dir != 0) {
        WarningLogMessage("The rate %d Hz is not supported by your hardware on device %s.\n" \
                "==> Using %d Hz instead.", pcm_name, rate, exact_rate);
    }
#else
	exact_rate = rate;
    if(err = snd_pcm_hw_params_set_rate(pcm_handle, hwparams, exact_rate, 0) < 0)
    {
        ErrorLogMessage("[ALSA Audio Plugin] Error setting rate (%d) on device %s. (Error: %s)", rate, pcm_name, snd_strerror(err));
    }
#endif
    
    /* Set number of channels */
    if(err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels) < 0) {
        ErrorLogMessage("[ALSA Audio Plugin] Error setting channels (%d) on device %s. (Error: %s)", channels, pcm_name, snd_strerror(err));
        return 1;
    }

    /* Set number of periods. Periods used to be called fragments. */ 
    if(err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0) {
        ErrorLogMessage("[ALSA Audio Plugin] Error setting periods (%d) on device %s. (Error: %s)", periods, pcm_name, snd_strerror(err));
        return 1;
    }

    /* Set buffer size (in frames). The resulting latency is given by */
    /* latency = periodsize * periods / (rate * bytes_per_frame)     */
    int buffer_size = (periodsize * periods) >> 2;
    if(err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, buffer_size) < 0) {
        ErrorLogMessage("[ALSA Audio Plugin] Error setting buffersize (%d) on device %s. (Error: %s)", buffer_size, pcm_name, snd_strerror(err));
        return 1;
    }
    
    /* Apply HW parameter settings to */
    /* PCM device and prepare device  */
    if(err = snd_pcm_hw_params(pcm_handle, hwparams) < 0) {
        ErrorLogMessage("[ALSA Audio Plugin] Error setting HW params on device %s. (Error: %s)", pcm_name, snd_strerror(err));
        return 1;
    }

	sndBuffer = new uint8_t[periodsize*4*2];
	if(!sndBuffer)
	{
		ErrorLogMessage("[ALSA Audio Plugin] sndBuffer allocation error.");
		return 1;
	}
    sndBufferPtr = sndBuffer;

	InfoLogMessage("[ALSA Audio Plugin] PCM device %s open at %d Hz %s, %d channels.", pcm_name, rate, snd_pcm_format_name(format), channels);

    return 0;
}
Example #27
0
bool QAudioOutputPrivate::open()
{
    if(opened)
        return true;

#ifdef DEBUG_AUDIO
    QTime now(QTime::currentTime());
    qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
#endif
    timeStamp.restart();
    elapsedTimeOffset = 0;

    int dir;
    int err = 0;
    int count=0;
    unsigned int freakuency=settings.frequency();

    if (!settings.isValid()) {
        qWarning("QAudioOutput: open error, invalid format.");
    } else if (settings.sampleRate() <= 0) {
        qWarning("QAudioOutput: open error, invalid sample rate (%d).",
                 settings.sampleRate());
    } else {
        err = -1;
    }

    if (err == 0) {
        errorState = QAudio::OpenError;
        deviceState = QAudio::StoppedState;
        emit errorChanged(errorState);
        return false;
    }

    QString dev = QString(QLatin1String(m_device.constData()));
    QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput);
    if(dev.compare(QLatin1String("default")) == 0) {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
        if (devices.size() > 0)
            dev = QLatin1String(devices.first());
        else
            return false;
#else
        dev = QLatin1String("hw:0,0");
#endif
    } else {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
        dev = QLatin1String(m_device);
#else
        int idx = 0;
        char *name;

        QString shortName = QLatin1String(m_device.mid(m_device.indexOf('=',0)+1).constData());

        while(snd_card_get_name(idx,&name) == 0) {
            if(qstrncmp(shortName.toLocal8Bit().constData(),name,shortName.length()) == 0)
                break;
            idx++;
        }
        dev = QString(QLatin1String("hw:%1,0")).arg(idx);
#endif
    }

    // Step 1: try and open the device
    while((count < 5) && (err < 0)) {
        err=snd_pcm_open(&handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0);
        if(err < 0)
            count++;
    }
    if (( err < 0)||(handle == 0)) {
        errorState = QAudio::OpenError;
        emit errorChanged(errorState);
        deviceState = QAudio::StoppedState;
        return false;
    }
    snd_pcm_nonblock( handle, 0 );

    // Step 2: Set the desired HW parameters.
    snd_pcm_hw_params_alloca( &hwparams );

    bool fatal = false;
    QString errMessage;
    unsigned int chunks = 8;

    err = snd_pcm_hw_params_any( handle, hwparams );
    if ( err < 0 ) {
        fatal = true;
        errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_any: err = %1").arg(err);
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_rate_resample( handle, hwparams, 1 );
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_rate_resample: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_access( handle, hwparams, access );
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_access: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = setFormat();
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_format: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channels() );
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_channels: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_rate_near( handle, hwparams, &freakuency, 0 );
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_rate_near: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        unsigned int maxBufferTime = 0;
        unsigned int minBufferTime = 0;
        unsigned int maxPeriodTime = 0;
        unsigned int minPeriodTime = 0;

        err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &maxBufferTime, &dir);
        if ( err >= 0)
            err = snd_pcm_hw_params_get_buffer_time_min(hwparams, &minBufferTime, &dir);
        if ( err >= 0)
            err = snd_pcm_hw_params_get_period_time_max(hwparams, &maxPeriodTime, &dir);
        if ( err >= 0)
            err = snd_pcm_hw_params_get_period_time_min(hwparams, &minPeriodTime, &dir);

        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioOutput: buffer/period min and max: err = %1").arg(err);
        } else {
            if (maxBufferTime < buffer_time || buffer_time < minBufferTime || maxPeriodTime < period_time || minPeriodTime > period_time) {
#ifdef DEBUG_AUDIO
                qDebug()<<"defaults out of range";
                qDebug()<<"pmin="<<minPeriodTime<<", pmax="<<maxPeriodTime<<", bmin="<<minBufferTime<<", bmax="<<maxBufferTime;
#endif
                period_time = minPeriodTime;
                if (period_time*4 <= maxBufferTime) {
                    // Use 4 periods if possible
                    buffer_time = period_time*4;
                    chunks = 4;
                } else if (period_time*2 <= maxBufferTime) {
                    // Use 2 periods if possible
                    buffer_time = period_time*2;
                    chunks = 2;
                } else {
                    qWarning()<<"QAudioOutput: alsa only supports single period!";
                    fatal = true;
                }
#ifdef DEBUG_AUDIO
                qDebug()<<"used: buffer_time="<<buffer_time<<", period_time="<<period_time;
#endif
            }
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir);
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir);
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_period_time_near: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &chunks, &dir);
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_periods_near: err = %1").arg(err);
        }
    }
    if ( !fatal ) {
        err = snd_pcm_hw_params(handle, hwparams);
        if ( err < 0 ) {
            fatal = true;
            errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params: err = %1").arg(err);
        }
    }
    if( err < 0) {
        qWarning()<<errMessage;
        errorState = QAudio::OpenError;
        emit errorChanged(errorState);
        deviceState = QAudio::StoppedState;
        return false;
    }
    snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames);
    buffer_size = snd_pcm_frames_to_bytes(handle,buffer_frames);
    snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &dir);
    period_size = snd_pcm_frames_to_bytes(handle,period_frames);
    snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir);
    snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir);

    // Step 3: Set the desired SW parameters.
    snd_pcm_sw_params_t *swparams;
    snd_pcm_sw_params_alloca(&swparams);
    snd_pcm_sw_params_current(handle, swparams);
    snd_pcm_sw_params_set_start_threshold(handle,swparams,period_frames);
    snd_pcm_sw_params_set_stop_threshold(handle,swparams,buffer_frames);
    snd_pcm_sw_params_set_avail_min(handle, swparams,period_frames);
    snd_pcm_sw_params(handle, swparams);

    // Step 4: Prepare audio
    if(audioBuffer == 0)
        audioBuffer = new char[snd_pcm_frames_to_bytes(handle,buffer_frames)];
    snd_pcm_prepare( handle );
    snd_pcm_start(handle);

    // Step 5: Setup callback and timer fallback
    snd_async_add_pcm_handler(&ahandler, handle, async_callback, this);
    bytesAvailable = bytesFree();

    // Step 6: Start audio processing
    timer->start(period_time/1000);

    clockStamp.restart();
    timeStamp.restart();
    elapsedTimeOffset = 0;
    errorState  = QAudio::NoError;
    totalTimeValue = 0;
    opened = true;

    return true;
}
Example #28
0
static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access, int rate, int channels, int period, int nperiods ) {
	int err, dir=0;
	unsigned int buffer_time;
	unsigned int period_time;
	unsigned int rrate;
	unsigned int rchannels;

	/* choose all parameters */
	err = snd_pcm_hw_params_any(handle, params);
	if (err < 0) {
		printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
		return err;
	}
	/* set the interleaved read/write format */
	err = snd_pcm_hw_params_set_access(handle, params, access);
	if (err < 0) {
		printf("Access type not available for playback: %s\n", snd_strerror(err));
		return err;
	}

	/* set the sample format */
	err = set_hwformat(handle, params);
	if (err < 0) {
		printf("Sample format not available for playback: %s\n", snd_strerror(err));
		return err;
	}
	/* set the count of channels */
	rchannels = channels;
	err = snd_pcm_hw_params_set_channels_near(handle, params, &rchannels);
	if (err < 0) {
		printf("Channels count (%i) not available for record: %s\n", channels, snd_strerror(err));
		return err;
	}
	if (rchannels != channels) {
		printf("WARNING: chennel count does not match (requested %d got %d)\n", channels, rchannels);
		num_channels = rchannels;
	}
	/* set the stream rate */
	rrate = rate;
	err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
	if (err < 0) {
		printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
		return err;
	}
	if (rrate != rate) {
		printf("WARNING: Rate doesn't match (requested %iHz, get %iHz)\n", rate, rrate);
		sample_rate = rrate;
	}
	/* set the buffer time */

	buffer_time = 1000000*(uint64_t)period*nperiods/rate;
	err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir);
	if (err < 0) {
		printf("Unable to set buffer time %i for playback: %s\n",  1000000*period*nperiods/rate, snd_strerror(err));
		return err;
	}
	err = snd_pcm_hw_params_get_buffer_size( params, &real_buffer_size );
	if (err < 0) {
		printf("Unable to get buffer size back: %s\n", snd_strerror(err));
		return err;
	}
	if( real_buffer_size != nperiods * period ) {
	    printf( "WARNING: buffer size does not match: (requested %d, got %d)\n", nperiods * period, (int) real_buffer_size );
	}
	/* set the period time */
	period_time = 1000000*(uint64_t)period/rate;
	err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir);
	if (err < 0) {
		printf("Unable to set period time %i for playback: %s\n", 1000000*period/rate, snd_strerror(err));
		return err;
	}
	err = snd_pcm_hw_params_get_period_size(params, &real_period_size, NULL );
	if (err < 0) {
		printf("Unable to get period size back: %s\n", snd_strerror(err));
		return err;
	}
	if( real_period_size != period ) {
	    printf( "WARNING: period size does not match: (requested %i, got %i)\n", period, (int)real_period_size );
	}
	/* write the parameters to device */
	err = snd_pcm_hw_params(handle, params);
	if (err < 0) {
		printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
		return err;
	}
	return 0;
}
Example #29
0
bool CAESinkALSA::InitializeHW(AEAudioFormat &format)
{
  snd_pcm_hw_params_t *hw_params;

  snd_pcm_hw_params_alloca(&hw_params);
  memset(hw_params, 0, snd_pcm_hw_params_sizeof());

  snd_pcm_hw_params_any(m_pcm, hw_params);
  snd_pcm_hw_params_set_access(m_pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);

  unsigned int sampleRate   = format.m_sampleRate;
  unsigned int channelCount = format.m_channelLayout.Count();
  snd_pcm_hw_params_set_rate_near    (m_pcm, hw_params, &sampleRate, NULL);
  snd_pcm_hw_params_set_channels_near(m_pcm, hw_params, &channelCount);

  /* ensure we opened X channels or more */
  if (format.m_channelLayout.Count() > channelCount)
  {
    CLog::Log(LOGINFO, "CAESinkALSA::InitializeHW - Unable to open the required number of channels");
  }

  /* update the channelLayout to what we managed to open */
  format.m_channelLayout.Reset();
  for (unsigned int i = 0; i < channelCount; ++i)
    format.m_channelLayout += ALSAChannelMap[i];

  snd_pcm_format_t fmt = AEFormatToALSAFormat(format.m_dataFormat);
  if (fmt == SND_PCM_FORMAT_UNKNOWN)
  {
    /* if we dont support the requested format, fallback to float */
    format.m_dataFormat = AE_FMT_FLOAT;
    fmt                 = SND_PCM_FORMAT_FLOAT;
  }

  /* try the data format */
  if (snd_pcm_hw_params_set_format(m_pcm, hw_params, fmt) < 0)
  {
    /* if the chosen format is not supported, try each one in decending order */
    CLog::Log(LOGINFO, "CAESinkALSA::InitializeHW - Your hardware does not support %s, trying other formats", CAEUtil::DataFormatToStr(format.m_dataFormat));
    for (enum AEDataFormat i = AE_FMT_MAX; i > AE_FMT_INVALID; i = (enum AEDataFormat)((int)i - 1))
    {
      if (AE_IS_RAW(i) || i == AE_FMT_MAX)
        continue;

      if (m_passthrough && i != AE_FMT_S16BE && i != AE_FMT_S16LE)
	continue;

      fmt = AEFormatToALSAFormat(i);

      if (fmt == SND_PCM_FORMAT_UNKNOWN || snd_pcm_hw_params_set_format(m_pcm, hw_params, fmt) < 0)
      {
        fmt = SND_PCM_FORMAT_UNKNOWN;
        continue;
      }

      int fmtBits = CAEUtil::DataFormatToBits(i);
      int bits    = snd_pcm_hw_params_get_sbits(hw_params);
      if (bits != fmtBits)
      {
        /* if we opened in 32bit and only have 24bits, pack into 24 */
        if (fmtBits == 32 && bits == 24)
          i = AE_FMT_S24NE4;
        else
          continue;
      }

      /* record that the format fell back to X */
      format.m_dataFormat = i;
      CLog::Log(LOGINFO, "CAESinkALSA::InitializeHW - Using data format %s", CAEUtil::DataFormatToStr(format.m_dataFormat));
      break;
    }

    /* if we failed to find a valid output format */
    if (fmt == SND_PCM_FORMAT_UNKNOWN)
    {
      CLog::Log(LOGERROR, "CAESinkALSA::InitializeHW - Unable to find a suitable output format");
      return false;
    }
  }

  snd_pcm_uframes_t periodSize, bufferSize;
  snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufferSize);
  snd_pcm_hw_params_get_period_size_max(hw_params, &periodSize, NULL);

  /* 
   We want to make sure, that we have max 200 ms Buffer with 
   a periodSize of approx 50 ms. Choosing a higher bufferSize
   will cause problems with menu sounds. Buffer will be increased
   after those are fixed.
  */
  periodSize  = std::min(periodSize, (snd_pcm_uframes_t) sampleRate / 20);
  bufferSize  = std::min(bufferSize, (snd_pcm_uframes_t) sampleRate / 5);
  
  /* 
   According to upstream we should set buffer size first - so make sure it is always at least
   4x period size to not get underruns (some systems seem to have issues with only 2 periods)
  */
  periodSize = std::min(periodSize, bufferSize / 4);

  CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Request: periodSize %lu, bufferSize %lu", periodSize, bufferSize);

  snd_pcm_hw_params_t *hw_params_copy;
  snd_pcm_hw_params_alloca(&hw_params_copy);
  snd_pcm_hw_params_copy(hw_params_copy, hw_params); // copy what we have and is already working
  
  // first trying bufferSize, PeriodSize
  // for more info see here:
  // http://mailman.alsa-project.org/pipermail/alsa-devel/2009-September/021069.html
  // the last three tries are done as within pulseaudio

  // backup periodSize and bufferSize first. Restore them after every failed try
  snd_pcm_uframes_t periodSizeTemp, bufferSizeTemp;
  periodSizeTemp = periodSize;
  bufferSizeTemp = bufferSize;
  if (snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize) != 0
    || snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL) != 0
    || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
  {
    bufferSize = bufferSizeTemp;
    periodSize = periodSizeTemp;
    // retry with PeriodSize, bufferSize
    snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restore working copy
    if (snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL) != 0
      || snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize) != 0
      || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
    {
      // try only periodSize
      periodSize = periodSizeTemp;
      snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restore working copy
      if(snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL) != 0 
        || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
      {
        // try only BufferSize
        bufferSize = bufferSizeTemp;
        snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restory working copy
        if (snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize) != 0
          || snd_pcm_hw_params(m_pcm, hw_params_copy) != 0)
        {
          // set default that Alsa would choose
          CLog::Log(LOGWARNING, "CAESinkAlsa::IntializeHW - Using default alsa values - set failed");
          if (snd_pcm_hw_params(m_pcm, hw_params) != 0)
          {
            CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Could not init a valid sink");
            return false;
          }
        }
      }
      // reread values when alsa default was kept
      snd_pcm_get_params(m_pcm, &bufferSize, &periodSize);
    }
  }
  
  CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Got: periodSize %lu, bufferSize %lu", periodSize, bufferSize);

  /* set the format parameters */
  format.m_sampleRate   = sampleRate;
  format.m_frames       = periodSize;
  format.m_frameSamples = periodSize * format.m_channelLayout.Count();
  format.m_frameSize    = snd_pcm_frames_to_bytes(m_pcm, 1);

  m_bufferSize = (unsigned int)bufferSize;
  m_timeout    = std::ceil((double)(bufferSize * 1000) / (double)sampleRate);

  CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Setting timeout to %d ms", m_timeout);

  return true;
}
Example #30
0
/*----------------------------------------------------------------
 TIesrFA_ALSA_open

 Try to open an ALSA audio PCM channel.
  ----------------------------------------------------------------*/
TIesrFA_ALSA_Error_t TIesrFA_ALSA_open( TIesrFA_t * const aTIesrFAInstance )
{
    int rtnStatus;
    int openSuccess = 0;
    snd_pcm_uframes_t numSamples;
    snd_pcm_hw_params_t *hw_params = 0;
    snd_pcm_sw_params_t *sw_params = 0;


    TIesrFA_ALSA_t * const ALSAData = (TIesrFA_ALSA_t * const) aTIesrFAInstance->impl_data;

    /* Try to open a handle to the ALSA pcm in blocking mode. */
    rtnStatus = snd_pcm_open( &ALSAData->alsa_handle,
            aTIesrFAInstance->channel_name,
            SND_PCM_STREAM_CAPTURE,
            0 );
    if( rtnStatus < 0 )
        goto openExit;

    /* Set up the information for recording from the audio channelport.  This
     will include data specified by the user, such as data in
     aTIesrFAInstance->encoding, etc.   If setup fails, then the audio channel
     should be shut down and failure reported. */

    /* Setup hardware parameters of the ALSA pcm */
    rtnStatus = snd_pcm_hw_params_malloc( &hw_params );
    if( rtnStatus < 0 )
        goto openExit;

    rtnStatus = snd_pcm_hw_params_any( ALSAData->alsa_handle, hw_params );
    if( rtnStatus < 0 )
        goto openExit;

    /* There will only be a single channel */
    rtnStatus = snd_pcm_hw_params_set_channels( ALSAData->alsa_handle,
            hw_params, 1 );
    if( rtnStatus < 0 )
        goto openExit;

    /* Even though only one channel, must specify type of read. */
    rtnStatus = snd_pcm_hw_params_set_access( ALSAData->alsa_handle,
            hw_params,
            SND_PCM_ACCESS_RW_INTERLEAVED );
    if( rtnStatus < 0 )
        goto openExit;


    /* Format type - only 16 bit linear for now */
    rtnStatus = snd_pcm_hw_params_set_format( ALSAData->alsa_handle,
            hw_params,
            SND_PCM_FORMAT_S16 );
    if( rtnStatus < 0 )
        goto openExit;

    /* Set sample rate, it must be exactly supported */
    rtnStatus = snd_pcm_hw_params_set_rate( ALSAData->alsa_handle,
            hw_params,
            aTIesrFAInstance->sample_rate, 0 );
    if( rtnStatus < 0 )
        goto openExit;


    /* Size of ALSA PCM ring buffer is set to approximately the desired 
     number of multiples of read_samples in the buffer */
    numSamples = aTIesrFAInstance->num_audio_buffer_frames *
            ALSAData->read_samples;
    rtnStatus = snd_pcm_hw_params_set_buffer_size_near( ALSAData->alsa_handle,
            hw_params, &numSamples );
    if( rtnStatus < 0 )
        goto openExit;


    /* Set the hardware parameters in the PCM*/
    rtnStatus = snd_pcm_hw_params( ALSAData->alsa_handle, hw_params );
    if( rtnStatus < 0 )
        goto openExit;



    /* Set software parameters to interrupt at the end of an audio buffer 
     number of samples and to start-up manually */
    rtnStatus = snd_pcm_sw_params_malloc( &sw_params );
    if( rtnStatus < 0 )
        goto openExit;

    rtnStatus = snd_pcm_sw_params_current( ALSAData->alsa_handle, sw_params );
    if( rtnStatus < 0 )
        goto openExit;

    /* Number of samples needed in PCM buffer prior to interrupt */
    rtnStatus = snd_pcm_sw_params_set_avail_min( ALSAData->alsa_handle,
            sw_params, ALSAData->read_samples );
    if( rtnStatus < 0 )
        goto openExit;

    /* Set start threshold so startup is done manually */
    rtnStatus = snd_pcm_sw_params_set_start_threshold( ALSAData->alsa_handle,
            sw_params, ULONG_MAX );
    if( rtnStatus < 0 )
        goto openExit;

    /* Channel opened successfully */
    openSuccess = 1;


openExit:

    if( hw_params != NULL )
        snd_pcm_hw_params_free( hw_params );

    if( sw_params != NULL )
        snd_pcm_sw_params_free( sw_params );


    if( openSuccess )
        return TIesrFA_ALSAErrNone;

    return TIesrFA_ALSAErrFail;
}