Exemplo n.º 1
0
static void alsa_set_sw_params(struct alsa_dev *dev, snd_pcm_t *handle,
			       int period, int thres)
{
	int ret;
	snd_pcm_sw_params_t *sw_params;

	ret = snd_pcm_sw_params_malloc(&sw_params);
	if (ret < 0)
		syslog_panic("Cannot allocate software parameters: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_sw_params_current(handle, sw_params);
	if (ret < 0)
		syslog_panic("Cannot initialize software parameters: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_sw_params_set_avail_min(handle, sw_params, period);
	if (ret < 0)
		syslog_panic("Cannot set minimum available count: %s\n",
			     snd_strerror(ret));
	if (thres) {
		ret = snd_pcm_sw_params_set_start_threshold(handle, sw_params,
							    period);
		if (ret < 0)
			syslog_panic("Cannot set start mode: %s\n",
				     snd_strerror(ret));
		
	}
	ret = snd_pcm_sw_params(handle, sw_params);
	if (ret < 0)
		syslog_panic("Cannot set software parameters: %s\n",
			     snd_strerror(ret));
	snd_pcm_sw_params_free(sw_params);
}
Exemplo n.º 2
0
static int set_sw_params(snd_pcm_t *pcm,
                         snd_pcm_sw_params_t *sw_params,
                         snd_spcm_xrun_type_t xrun_type)
{
    int err;

    err = snd_pcm_sw_params_current(pcm, sw_params);
    if (err < 0)
        return err;
    err = snd_pcm_sw_params_set_start_threshold(pcm, sw_params, (pcm->buffer_size / pcm->period_size) * pcm->period_size);
    if (err < 0)
        return err;
    err = snd_pcm_sw_params_set_avail_min(pcm, sw_params, pcm->period_size);
    if (err < 0)
        return err;
    switch (xrun_type) {
    case SND_SPCM_XRUN_STOP:
        err = snd_pcm_sw_params_set_stop_threshold(pcm, sw_params, pcm->buffer_size);
        break;
    case SND_SPCM_XRUN_IGNORE:
        err = snd_pcm_sw_params_set_stop_threshold(pcm, sw_params, pcm->boundary);
        break;
    default:
        return -EINVAL;
    }
    if (err < 0)
        return err;
    err = snd_pcm_sw_params_set_xfer_align(pcm, sw_params, 1);
    if (err < 0)
        return err;
    err = snd_pcm_sw_params(pcm, sw_params);
    if (err < 0)
        return err;
    return 0;
}
Exemplo n.º 3
0
int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams)
{
        int err;

        /* get the current swparams */
        err = snd_pcm_sw_params_current(handle, swparams);
        if (err < 0) {
                printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
                return err;
        }
        /* start the transfer when the buffer is almost full: */
        /* (buffer_size / avail_min) * avail_min */
        //err = snd_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size / period_size) * period_size);
        err = snd_pcm_sw_params_set_start_threshold(handle, swparams, period_size * periods - arnold_frame_size);
        if (err < 0) {
                printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
                return err;
        }
        /* allow the transfer when at least period_size samples can be processed */
        err = snd_pcm_sw_params_set_avail_min(handle, swparams, arnold_frame_size);
        if (err < 0) {
                printf("Unable to set avail min for playback: %s\n", snd_strerror(err));
                return err;
        }
        /* write the parameters to the playback device */
        err = snd_pcm_sw_params(handle, swparams);
        if (err < 0) {
                printf("Unable to set sw params for playback: %s\n", snd_strerror(err));
                return err;
        }
        return 0;
}
Exemplo n.º 4
0
snd_pcm_t *open_pcm(char *pcm_name) {

    snd_pcm_t *playback_handle;
    snd_pcm_hw_params_t *hw_params;
    snd_pcm_sw_params_t *sw_params;
            
    if (snd_pcm_open (&playback_handle, pcm_name, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
        fprintf (stderr, "cannot open audio device %s\n", pcm_name);
        exit (1);
    }
    snd_pcm_hw_params_alloca(&hw_params);
    snd_pcm_hw_params_any(playback_handle, hw_params);
    snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE);
    snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, 44100, 0);
    snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2);
    snd_pcm_hw_params_set_periods(playback_handle, hw_params, 2, 0);
    snd_pcm_hw_params_set_period_size(playback_handle, hw_params, BUFSIZE, 0);
    snd_pcm_hw_params(playback_handle, hw_params);
    snd_pcm_sw_params_alloca(&sw_params);
    snd_pcm_sw_params_current(playback_handle, sw_params);
    snd_pcm_sw_params_set_avail_min(playback_handle, sw_params, BUFSIZE);
    snd_pcm_sw_params(playback_handle, sw_params);
    return(playback_handle);
}
Exemplo n.º 5
0
static void audio_renderer_init() {
  int rc;
  decoder = opus_decoder_create(SAMPLE_RATE, CHANNEL_COUNT, &rc);

  snd_pcm_hw_params_t *hw_params;
  snd_pcm_sw_params_t *sw_params;
  snd_pcm_uframes_t period_size = FRAME_SIZE * CHANNEL_COUNT * 2;
  snd_pcm_uframes_t buffer_size = 12 * period_size;
  unsigned int sampleRate = SAMPLE_RATE;

  /* Open PCM device for playback. */
  CHECK_RETURN(snd_pcm_open(&handle, audio_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK))

  /* Set hardware parameters */
  CHECK_RETURN(snd_pcm_hw_params_malloc(&hw_params));
  CHECK_RETURN(snd_pcm_hw_params_any(handle, hw_params));
  CHECK_RETURN(snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED));
  CHECK_RETURN(snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE));
  CHECK_RETURN(snd_pcm_hw_params_set_rate_near(handle, hw_params, &sampleRate, NULL));
  CHECK_RETURN(snd_pcm_hw_params_set_channels(handle, hw_params, CHANNEL_COUNT));
  CHECK_RETURN(snd_pcm_hw_params_set_buffer_size_near(handle, hw_params, &buffer_size));
  CHECK_RETURN(snd_pcm_hw_params_set_period_size_near(handle, hw_params, &period_size, NULL));
  CHECK_RETURN(snd_pcm_hw_params(handle, hw_params));
  snd_pcm_hw_params_free(hw_params);

  /* Set software parameters */
  CHECK_RETURN(snd_pcm_sw_params_malloc(&sw_params));
  CHECK_RETURN(snd_pcm_sw_params_current(handle, sw_params));
  CHECK_RETURN(snd_pcm_sw_params_set_start_threshold(handle, sw_params, buffer_size - period_size));
  CHECK_RETURN(snd_pcm_sw_params_set_avail_min(handle, sw_params, period_size));
  CHECK_RETURN(snd_pcm_sw_params(handle, sw_params));
  snd_pcm_sw_params_free(sw_params);

  CHECK_RETURN(snd_pcm_prepare(handle));
}
Exemplo n.º 6
0
int VoiceStreamer::setparams_set(snd_pcm_t *handle, snd_pcm_hw_params_t *params,
      snd_pcm_sw_params_t *swparams, const char *id) {
   int err;
   snd_pcm_uframes_t val;

   if ((err = snd_pcm_hw_params(handle, params)) < 0) {
      printf("Unable to set hw params for %s: %s\n", id, snd_strerror(err));
      return err;
   }
   if ((err = snd_pcm_sw_params_current(handle, swparams)) < 0) {
      printf("Unable to determine current swparams for %s: %s\n", id,
            snd_strerror(err));
      return err;
   }
   if ((err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 
               0x7fffffff)) < 0) {
      printf("Unable to set start threshold mode for %s: %s\n", id,
            snd_strerror(err));
      return err;
   }
   val = 4;
   if ((err = snd_pcm_sw_params_set_avail_min(handle, swparams, val)) < 0) {
      printf("Unable to set sw params for %s: %s\n", id, snd_strerror(err));
      return err;
   }

   return 0;
}
// returns 1 if successful
int setSWParams(AlsaPcmInfo* info) {
    int ret;

    /* get the current swparams */
    ret = snd_pcm_sw_params_current(info->handle, info->swParams);
    if (ret < 0) {
        ERROR1("Unable to determine current swparams: %s\n", snd_strerror(ret));
        return FALSE;
    }
    /* never start the transfer automatically */
    if (!setStartThresholdNoCommit(info, FALSE /* don't use threshold */)) {
        return FALSE;
    }

    /* allow the transfer when at least period_size samples can be processed */
    ret = snd_pcm_sw_params_set_avail_min(info->handle, info->swParams, info->periodSize);
    if (ret < 0) {
        ERROR1("Unable to set avail min for playback: %s\n", snd_strerror(ret));
        return FALSE;
    }
    /* align all transfers to 1 sample */
    ret = snd_pcm_sw_params_set_xfer_align(info->handle, info->swParams, 1);
    if (ret < 0) {
        ERROR1("Unable to set transfer align: %s\n", snd_strerror(ret));
        return FALSE;
    }
    /* write the parameters to the playback device */
    ret = snd_pcm_sw_params(info->handle, info->swParams);
    if (ret < 0) {
        ERROR1("Unable to set sw params: %s\n", snd_strerror(ret));
        return FALSE;
    }
    return TRUE;
}
Exemplo n.º 8
0
int AudioAlsa::setSWParams()
{
	int err;

	// get the current swparams
	if( ( err = snd_pcm_sw_params_current( m_handle, m_swParams ) ) < 0 )
	{
		printf( "Unable to determine current swparams for playback: %s"
						"\n", snd_strerror( err ) );
		return err;
	}

	// start the transfer when a period is full
	if( ( err = snd_pcm_sw_params_set_start_threshold( m_handle,
					m_swParams, m_periodSize ) ) < 0 )
	{
		printf( "Unable to set start threshold mode for playback: %s\n",
							snd_strerror( err ) );
		return err;
	}

	// allow the transfer when at least m_periodSize samples can be
	// processed
	if( ( err = snd_pcm_sw_params_set_avail_min( m_handle, m_swParams,
							m_periodSize ) ) < 0 )
	{
		printf( "Unable to set avail min for playback: %s\n",
							snd_strerror( err ) );
		return err;
	}

	// align all transfers to 1 sample
	
#if SND_LIB_VERSION < ((1<<16)|(0)|16)
	if( ( err = snd_pcm_sw_params_set_xfer_align( m_handle,
							m_swParams, 1 ) ) < 0 )
	{
		printf( "Unable to set transfer align for playback: %s\n",
							snd_strerror( err ) );
		return err;
	}
#endif

	// write the parameters to the playback device
	if( ( err = snd_pcm_sw_params( m_handle, m_swParams ) ) < 0 )
	{
		printf( "Unable to set sw params for playback: %s\n",
							snd_strerror( err ) );
		return err;
	}

	return 0;	// all ok
}
Exemplo n.º 9
0
static void set_params(void)
{
	hwparams.format=SND_PCM_FORMAT_S16_LE;
        hwparams.channels=2;
        hwparams.rate=44100;

	snd_pcm_hw_params_t *params;
	snd_pcm_sw_params_t *swparams;

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

	snd_pcm_hw_params_any(handle, params);
	snd_pcm_hw_params_set_format(handle, params, hwparams.format);
	snd_pcm_hw_params_set_channels(handle, params, hwparams.channels);
	snd_pcm_hw_params_set_rate_near(handle, params, &hwparams.rate, 0);

	buffer_time=0;
	snd_pcm_hw_params_get_buffer_time_max(params,&buffer_time, 0);

	period_time=125000;
	snd_pcm_hw_params_set_period_time_near(handle, params,&period_time, 0);

	buffer_time = 500000;
	snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, 0);
	
	/*monotonic = */snd_pcm_hw_params_is_monotonic(params);
        /*can_pause = */snd_pcm_hw_params_can_pause(params);

	
	printf("sizeof(params) : %d\n",sizeof(params));

        snd_pcm_hw_params(handle, params);

        snd_pcm_uframes_t buffer_size;
	snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);

	size_t n=chunk_size;

	snd_pcm_sw_params_set_avail_min(handle, swparams, n);


	snd_pcm_uframes_t start_threshold, stop_threshold;	
	start_threshold=22050;
	snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
	stop_threshold=22050;
	snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
	
	snd_pcm_format_physical_width(hwparams.format);
	
}
Exemplo n.º 10
0
void mixer_open()
{
	memset(&channels, 0, sizeof(channels));
	int err = snd_pcm_open(&pcm, "default", SND_PCM_STREAM_PLAYBACK, 0);
	if (err < 0)
	{
		printf("Failed to open pcm device: %s\n", snd_strerror(err));
		exit(1);
	}
	
	unsigned int rate = 44100;
	snd_pcm_hw_params_t *hw_params = 0;
	snd_pcm_hw_params_alloca(&hw_params);
	snd_pcm_hw_params_any(pcm, hw_params);
	snd_pcm_hw_params_set_rate_resample(pcm, hw_params, 0);
	snd_pcm_hw_params_set_access(pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
	snd_pcm_hw_params_set_format(pcm, hw_params, SND_PCM_FORMAT_S16_LE);
	snd_pcm_hw_params_set_rate_near(pcm, hw_params, &rate, 0);
	snd_pcm_hw_params_set_channels(pcm, hw_params, 2);
	snd_pcm_hw_params_set_period_size(pcm, hw_params, BUFFER_SIZE, 0);
	snd_pcm_hw_params_set_buffer_size(pcm, hw_params, BUFFER_SIZE * 4);
	
	err = snd_pcm_hw_params(pcm, hw_params);
	if (err < 0)
	{
		printf("Failed to apply pcm hardware settings: %s\n", snd_strerror(err));
		exit(1);
	}
	
	snd_pcm_sw_params_t *sw_params = 0;
	snd_pcm_sw_params_alloca(&sw_params);
	snd_pcm_sw_params_current(pcm, sw_params);
	snd_pcm_sw_params_set_avail_min(pcm, sw_params, BUFFER_SIZE * 4);
	err = snd_pcm_sw_params(pcm, sw_params);
	if (err < 0)
	{
		printf("Failed to apply pcm software settings: %s\n", snd_strerror(err));
		exit(1);
	}
	
	err = snd_pcm_prepare(pcm);
	if (err < 0)
	{
		printf("Failed to prepare pcm interface: %s\n", snd_strerror(err));
		exit(1);
	}
	
	memset(delay_left, 0, sizeof(delay_left));
	memset(delay_right, 0, sizeof(delay_right));
}
Exemplo n.º 11
0
static int setparams_set(snd_pcm_t *handle,
                         snd_pcm_hw_params_t *params,
                         snd_pcm_sw_params_t *swparams,
                         snd_pcm_uframes_t start_treshold,
                         const char *id)
{
    int err;

    err = snd_pcm_hw_params(handle, params);
    if (err < 0) {
        fprintf(error_fp, "alsa: Unable to set hw params for %s: %s\n",
                id, snd_strerror(err));
        return err;
    }
    err = snd_pcm_sw_params_current(handle, swparams);
    if (err < 0) {
        fprintf(error_fp, "alsa: Unable to determine current swparams for %s: %s\n",
                id, snd_strerror(err));
        return err;
    }
    err = snd_pcm_sw_params_set_start_threshold(handle, swparams,
            start_treshold);
    if (err < 0) {
        fprintf(error_fp, "alsa: Unable to set start threshold mode for %s: %s\n",
                id, snd_strerror(err));
        return err;
    }

    err = snd_pcm_sw_params_set_avail_min(handle, swparams, 4);
    if (err < 0) {
        fprintf(error_fp, "alsa: Unable to set avail min for %s: %s\n",
                id, snd_strerror(err));
        return err;
    }

    err = snd_pcm_sw_params_set_tstamp_mode(handle, swparams, SND_PCM_TSTAMP_ENABLE);
    if (err < 0) {
        fprintf(error_fp, "alsa: Unable to enable timestamps for %s: %s\n",
                id, snd_strerror(err));
    }

    err = snd_pcm_sw_params(handle, swparams);
    if (err < 0) {
        fprintf(error_fp, "alsa: Unable to set sw params for %s: %s\n",
                id, snd_strerror(err));
        return err;
    }
    return 0;
}
Exemplo n.º 12
0
/**************************************************************************************
 * set_swparams
 * history: (1) 2014 03 30 mhb
 *
 **************************************************************************************/
static int set_swparams(snd_pcm_t *handle, 
                        snd_pcm_sw_params_t *swparams)
{
    int err;
    /* get the current swparams */
    err = snd_pcm_sw_params_current(handle, swparams);
    if (err < 0) 
    {
        printf("Unable to determine current swparams : %s\n", snd_strerror(err));
        return err;
    }
    /* start the transfer when the buffer is almost full: */
    /* (buffer_size / avail_min) * avail_min */
    err = snd_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size / period_size) * period_size);
    //err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 3*period_size);// mhb|  修改此值,太小程序会卡死
    if (err < 0) 
    {
        printf("Unable to set start threshold mode : %s\n", snd_strerror(err));
        return err;
    }
    /* allow the transfer when at least period_size samples can be processed */
    /* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
    err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_event ? buffer_size : period_size);
    //err = snd_pcm_sw_params_set_avail_min(handle, swparams, 0);//mhb
    if (err < 0) 
    {
        printf("Unable to set avail min : %s\n", snd_strerror(err));
        return err;
    }
    /* enable period events when requested */
    if (period_event) 
    {
        err = snd_pcm_sw_params_set_period_event(handle, swparams, 1);
        if (err < 0) 
        {
            printf("Unable to set period event: %s\n", snd_strerror(err));
            return err;
        }
    }
    /* write the parameters to the playback device */
    err = snd_pcm_sw_params(handle, swparams);
    if (err < 0) 
    {
        printf("Unable to set sw params : %s\n", snd_strerror(err));
        return err;
    }
    return 0;
}
int
set_mic_swparams(snd_pcm_t *handle) 
{
    // set software params

    snd_pcm_sw_params_t *swparams;
    snd_pcm_sw_params_alloca(&swparams);

    /* get the current swparams */
    int ret = snd_pcm_sw_params_current(handle, swparams);
    if (ret < 0) {
        fprintf(stderr, 
	    "Unable to determine current swparams for mic: %s\n", 
	    snd_strerror(ret));
        return ret;
    }

    /* allow transfer when at least period_frames can be processed */

    ret = snd_pcm_sw_params_set_avail_min(handle, swparams, 
	get_period_frames(handle));

    if (ret < 0) {
        fprintf(stderr, "Unable to set avail min for mic: %s\n", 
	    snd_strerror(ret));
        return ret;
    }

    /* align all transfers to 1 sample */
    ret = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
    if (ret < 0) {
        fprintf(stderr, "Unable to set transfer align for mic: %s\n", 
	    snd_strerror(ret));
        return ret;
    }

    /* write the parameters to the microphone device */
    ret = snd_pcm_sw_params(handle, swparams);
    if (ret < 0) {
        fprintf(stderr, "Unable to set sw params for mic: %s\n", 
	    snd_strerror(ret));
        return ret;
    }
	
    dump_swparams(handle);
    return 0;
}
Exemplo n.º 14
0
static int alsa_set_hwparams()
{
	snd_pcm_hw_params_t *hwp;
	snd_pcm_sw_params_t *swp;
	int dir = 1;
	unsigned period_time;
	snd_pcm_uframes_t buffer_size, period_size;

	snd_pcm_hw_params_alloca(&hwp);
	snd_pcm_sw_params_alloca(&swp);

	// ALSA bug? If we request 44100 Hz, it rounds the value up to 48000...
	alsa_hw.rate--;

	if (alsa_error("hw_params_any", snd_pcm_hw_params_any(alsa_hw.handle, hwp))
	    || alsa_error("hw_params_set_format", snd_pcm_hw_params_set_format(alsa_hw.handle, hwp, alsa_hw.format))
	    || alsa_error("hw_params_set_channels",
			  snd_pcm_hw_params_set_channels(alsa_hw.handle, hwp, alsa_hw.num_channels))
	    || alsa_error("hw_params_set_rate_near",
			  snd_pcm_hw_params_set_rate_near(alsa_hw.handle, hwp, &alsa_hw.rate, &dir))
	    || alsa_error("hw_params_set_access",
			  snd_pcm_hw_params_set_access(alsa_hw.handle, hwp, SND_PCM_ACCESS_RW_INTERLEAVED))
	    || alsa_error("hw_params_set_buffer_time_near",
			  snd_pcm_hw_params_set_buffer_time_near(alsa_hw.handle, hwp, &alsa_hw.buffer_time, 0)))
		return -1;

	/* How often to call our SIGIO handler (~40Hz) */
	period_time = alsa_hw.buffer_time / 4;
	if (alsa_error
	    ("hw_params_set_period_time_near",
	     snd_pcm_hw_params_set_period_time_near(alsa_hw.handle, hwp, &period_time, &dir))
	    || alsa_error("hw_params_get_buffer_size", snd_pcm_hw_params_get_buffer_size(hwp, &buffer_size))
	    || alsa_error("hw_params_get_period_size", snd_pcm_hw_params_get_period_size(hwp, &period_size, 0))
	    || alsa_error("hw_params", snd_pcm_hw_params(alsa_hw.handle, hwp)))
		return -1;

	snd_pcm_sw_params_current(alsa_hw.handle, swp);
	if (alsa_error
	    ("sw_params_set_start_threshold", snd_pcm_sw_params_set_start_threshold(alsa_hw.handle, swp, period_size))
	    || alsa_error("sw_params_set_avail_min", snd_pcm_sw_params_set_avail_min(alsa_hw.handle, swp, period_size))
	    || alsa_error("sw_params", snd_pcm_sw_params(alsa_hw.handle, swp)))
		return -1;

	return 0;
}
Exemplo n.º 15
0
/* setup alsa data transfer behavior */
static inline int alsa_set_swparams(ao_alsa_internal *internal)
{
	snd_pcm_sw_params_t   *params;
	int err;

	/* allocate the software parameter structure */
	snd_pcm_sw_params_alloca(&params);

	/* fetch the current software parameters */
	internal->cmd = "snd_pcm_sw_params_current";
	err = snd_pcm_sw_params_current(internal->pcm_handle, params);
	if (err < 0)
		return err;

	/* allow transfers to start when there is one period */
	internal->cmd = "snd_pcm_sw_params_set_start_threshold";
	err = snd_pcm_sw_params_set_start_threshold(internal->pcm_handle,
			params, internal->period_size);
	if (err < 0)
		return err;

	/* require a minimum of one full transfer in the buffer */
	internal->cmd = "snd_pcm_sw_params_set_avail_min";
	err = snd_pcm_sw_params_set_avail_min(internal->pcm_handle, params,
			internal->period_size);
	if (err < 0)
		return err;

	/* do not align transfers */
	internal->cmd = "snd_pcm_sw_params_set_xfer_align";
	err = snd_pcm_sw_params_set_xfer_align(internal->pcm_handle, params, 1);
	if (err < 0)
		return err;

	/* commit the params structure to ALSA */
	internal->cmd = "snd_pcm_sw_params";
	err = snd_pcm_sw_params(internal->pcm_handle, params);
	if (err < 0)
		return err;

	return 1;
}
Exemplo n.º 16
0
void AlsaRenderer::SetupSwParams()
{
    snd_pcm_sw_params_t* params;

    /* allocate a software parameters object */
    snd_pcm_sw_params_malloc(&params);

    /* get the current swparams */
    snd_pcm_sw_params_current(m_PcmHandle, params);

    /* round up to closest transfer boundary */
    snd_pcm_sw_params_set_start_threshold(m_PcmHandle, params, 1);

    /* require a minimum of one full transfer in the buffer */
    snd_pcm_sw_params_set_avail_min(m_PcmHandle, params, 1);

    snd_pcm_sw_params(m_PcmHandle, params);

    /* free */
    snd_pcm_sw_params_free(params);
}
Exemplo n.º 17
0
static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams, int period, int nperiods) {
	int err;

	/* get the current swparams */
	err = snd_pcm_sw_params_current(handle, swparams);
	if (err < 0) {
		printf("Unable to determine current swparams for capture: %s\n", snd_strerror(err));
		return err;
	}
	/* start the transfer when the buffer is full */
	err = snd_pcm_sw_params_set_start_threshold(handle, swparams, period );
	if (err < 0) {
		printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err));
		return err;
	}
	err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, -1 );
	if (err < 0) {
		printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err));
		return err;
	}
	/* allow the transfer when at least period_size samples can be processed */
	err = snd_pcm_sw_params_set_avail_min(handle, swparams, 1 );
	if (err < 0) {
		printf("Unable to set avail min for capture: %s\n", snd_strerror(err));
		return err;
	}
	/* align all transfers to 1 sample */
	err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
	if (err < 0) {
		printf("Unable to set transfer align for capture: %s\n", snd_strerror(err));
		return err;
	}
	/* write the parameters to the playback device */
	err = snd_pcm_sw_params(handle, swparams);
	if (err < 0) {
		printf("Unable to set sw params for capture: %s\n", snd_strerror(err));
		return err;
	}
	return 0;
}
int setparams_set(snd_pcm_t *handle,
		  snd_pcm_hw_params_t *params,
		  snd_pcm_sw_params_t *swparams,
		  const char *id)
{
	int err;
	snd_pcm_uframes_t val;

	err = snd_pcm_hw_params(handle, params);
	if (err < 0) {
		printf("Unable to set hw params for %s: %s\n", id, snd_strerror(err));
		return err;
	}
	err = snd_pcm_sw_params_current(handle, swparams);
	if (err < 0) {
		printf("Unable to determine current swparams for %s: %s\n", id, snd_strerror(err));
		return err;
	}
	err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0x7fffffff);
	if (err < 0) {
		printf("Unable to set start threshold mode for %s: %s\n", id, snd_strerror(err));
		return err;
	}
	if (!block)
		val = 4;
	else
		snd_pcm_hw_params_get_period_size(params, &val, NULL);
	err = snd_pcm_sw_params_set_avail_min(handle, swparams, val);
	if (err < 0) {
		printf("Unable to set avail min for %s: %s\n", id, snd_strerror(err));
		return err;
	}
	err = snd_pcm_sw_params(handle, swparams);
	if (err < 0) {
		printf("Unable to set sw params for %s: %s\n", id, snd_strerror(err));
		return err;
	}
	return 0;
}
Exemplo n.º 19
0
bool CAESinkALSA::InitializeSW(AEAudioFormat &format)
{
  snd_pcm_sw_params_t *sw_params;
  snd_pcm_uframes_t boundary;

  snd_pcm_sw_params_alloca(&sw_params);
  memset(sw_params, 0, snd_pcm_sw_params_sizeof());

  snd_pcm_sw_params_current              (m_pcm, sw_params);
  snd_pcm_sw_params_set_start_threshold  (m_pcm, sw_params, INT_MAX);
  snd_pcm_sw_params_set_silence_threshold(m_pcm, sw_params, 0);
  snd_pcm_sw_params_get_boundary         (sw_params, &boundary);
  snd_pcm_sw_params_set_silence_size     (m_pcm, sw_params, boundary);
  snd_pcm_sw_params_set_avail_min        (m_pcm, sw_params, format.m_frames);

  if (snd_pcm_sw_params(m_pcm, sw_params) < 0)
  {
    CLog::Log(LOGERROR, "CAESinkALSA::InitializeSW - Failed to set the parameters");
    return false;
  }

  return true;
}
Exemplo n.º 20
0
snd_pcm_t *open_pcm(char *pcm_name) {
    snd_pcm_t *playback_handle;
    snd_pcm_hw_params_t *hw_params;
    snd_pcm_sw_params_t *sw_params;
    if (snd_pcm_open (&playback_handle, pcm_name, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
        fprintf (stderr, "cannot open audio device %s\n", pcm_name);
      return NULL;//it seems greedy and wants exclusive control?!
    }
    snd_pcm_hw_params_alloca(&hw_params);
    snd_pcm_hw_params_any(playback_handle, hw_params);
    snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE);
    snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &rate, 0);
    snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2);
    snd_pcm_hw_params_set_periods(playback_handle, hw_params, 2, 0);
    snd_pcm_hw_params_set_period_size(playback_handle, hw_params, BUFSAMPS, 0);
    snd_pcm_hw_params(playback_handle, hw_params);
    snd_pcm_sw_params_alloca(&sw_params);
    snd_pcm_sw_params_current(playback_handle, sw_params);
    snd_pcm_sw_params_set_avail_min(playback_handle, sw_params, BUFSAMPS);
    snd_pcm_sw_params(playback_handle, sw_params);
    return(playback_handle);
}
Exemplo n.º 21
0
int ai_alsa_setup(audio_in_t *ai)
{
    snd_pcm_hw_params_t *params;
    snd_pcm_sw_params_t *swparams;
    snd_pcm_uframes_t buffer_size, period_size;
    int err;
    int dir;
    unsigned int rate;

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

    err = snd_pcm_hw_params_any(ai->alsa.handle, params);
    if (err < 0) {
	mp_tmsg(MSGT_TV, MSGL_ERR, "Broken configuration for this PCM: no configurations available.\n");
	return -1;
    }

    err = snd_pcm_hw_params_set_access(ai->alsa.handle, params,
				       SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err < 0) {
	mp_tmsg(MSGT_TV, MSGL_ERR, "Access type not available.\n");
	return -1;
    }

    err = snd_pcm_hw_params_set_format(ai->alsa.handle, params, SND_PCM_FORMAT_S16_LE);
    if (err < 0) {
	mp_tmsg(MSGT_TV, MSGL_ERR, "Sample format not available.\n");
	return -1;
    }

    err = snd_pcm_hw_params_set_channels(ai->alsa.handle, params, ai->req_channels);
    if (err < 0) {
	snd_pcm_hw_params_get_channels(params, &ai->channels);
	mp_tmsg(MSGT_TV, MSGL_ERR, "Channel count not available - reverting to default: %d\n",
	       ai->channels);
    } else {
	ai->channels = ai->req_channels;
    }

    dir = 0;
    rate = ai->req_samplerate;
    err = snd_pcm_hw_params_set_rate_near(ai->alsa.handle, params, &rate, &dir);
    if (err < 0) {
	mp_tmsg(MSGT_TV, MSGL_ERR, "Cannot set samplerate.\n");
    }
    ai->samplerate = rate;

    dir = 0;
    ai->alsa.buffer_time = 1000000;
    err = snd_pcm_hw_params_set_buffer_time_near(ai->alsa.handle, params,
						 &ai->alsa.buffer_time, &dir);
    if (err < 0) {
	mp_tmsg(MSGT_TV, MSGL_ERR, "Cannot set buffer time.\n");
    }

    dir = 0;
    ai->alsa.period_time = ai->alsa.buffer_time / 4;
    err = snd_pcm_hw_params_set_period_time_near(ai->alsa.handle, params,
						 &ai->alsa.period_time, &dir);
    if (err < 0) {
	mp_tmsg(MSGT_TV, MSGL_ERR, "Cannot set period time.\n");
    }

    err = snd_pcm_hw_params(ai->alsa.handle, params);
    if (err < 0) {
	mp_tmsg(MSGT_TV, MSGL_ERR, "Unable to install hardware parameters: %s", snd_strerror(err));
	snd_pcm_hw_params_dump(params, ai->alsa.log);
	return -1;
    }

    dir = -1;
    snd_pcm_hw_params_get_period_size(params, &period_size, &dir);
    snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
    ai->alsa.chunk_size = period_size;
    if (period_size == buffer_size) {
	mp_tmsg(MSGT_TV, MSGL_ERR, "Can't use period equal to buffer size (%u == %lu)\n", ai->alsa.chunk_size, (long)buffer_size);
	return -1;
    }

    snd_pcm_sw_params_current(ai->alsa.handle, swparams);
    err = snd_pcm_sw_params_set_avail_min(ai->alsa.handle, swparams, ai->alsa.chunk_size);

    err = snd_pcm_sw_params_set_start_threshold(ai->alsa.handle, swparams, 0);
    err = snd_pcm_sw_params_set_stop_threshold(ai->alsa.handle, swparams, buffer_size);

    if (snd_pcm_sw_params(ai->alsa.handle, swparams) < 0) {
	mp_tmsg(MSGT_TV, MSGL_ERR, "Unable to install software parameters:\n");
	snd_pcm_sw_params_dump(swparams, ai->alsa.log);
	return -1;
    }

    if (mp_msg_test(MSGT_TV, MSGL_V)) {
	snd_pcm_dump(ai->alsa.handle, ai->alsa.log);
    }

    ai->alsa.bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE);
    ai->alsa.bits_per_frame = ai->alsa.bits_per_sample * ai->channels;
    ai->blocksize = ai->alsa.chunk_size * ai->alsa.bits_per_frame / 8;
    ai->samplesize = ai->alsa.bits_per_sample;
    ai->bytes_per_sample = ai->alsa.bits_per_sample/8;

    return 0;
}
Exemplo n.º 22
0
static int capture(lua_State *lstate) {
	char *card;
	snd_pcm_sw_params_t *sparams;
	int ret, dir, i;
	snd_pcm_format_t f, format;
	unsigned int rate, buffer_time;
	if (rbuf == NULL) {
		rbuf = new_ringbuf(jack_sr, CHANNELS, BUFSECS,
					0.333, 0.667);
		}
	getstring(lstate, "card", &card);
	lua_pop(lstate, 1);
	for (i = 0; i < 20; i++) {
		ret = snd_pcm_open(&handle, card, SND_PCM_STREAM_CAPTURE, 0);
		if (ret < 0) {
			logmsg("can't open %s (%s)\n", card, snd_strerror(ret));
			}
		else {
			break;
			}
		}
	free(card);
	if (ret < 0) return 0;
	if (hparams != NULL) snd_pcm_hw_params_free(hparams);
	snd_pcm_hw_params_malloc(&hparams);
	snd_pcm_hw_params_any(handle, hparams);
	for (f = format = 0; f < SND_PCM_FORMAT_LAST; f++) {
		ret = snd_pcm_hw_params_test_format(handle, hparams, f);
		if (ret == 0) {
			logmsg("- %s\n", snd_pcm_format_name(f));
			format = f;
			}
		}
	ret = snd_pcm_hw_params_set_access(handle, hparams,
				SND_PCM_ACCESS_RW_INTERLEAVED);
	if (ret < 0) {
		logmsg("access %s\n", snd_strerror(ret));
		}
	ret = snd_pcm_hw_params_set_format(handle, hparams, format);
	logmsg("format: %s\n", snd_pcm_format_description(format));
	if (ret < 0) {
		logmsg("format error %s\n", snd_strerror(ret));
		}
	snd_pcm_hw_params_get_buffer_time_max(hparams, &buffer_time, 0);
	rate = jack_sr;
	ret = snd_pcm_hw_params_set_rate(handle, hparams, rate, 0);
logmsg("rate %d\n", rate);
	if (ret < 0) logmsg("rate error %s\n", snd_strerror(ret));
	snd_pcm_hw_params_set_channels(handle, hparams, CHANNELS);
	blocksize = BLOCKSIZE;
	snd_pcm_hw_params_set_period_size(handle, hparams, blocksize, 0);
logmsg("period %ld\n", blocksize);
	snd_pcm_hw_params_set_buffer_time_near(handle, hparams, &buffer_time, &dir);
logmsg("buffer time %u\n", buffer_time);
	if ((ret = snd_pcm_hw_params(handle, hparams)) < 0) {
		logmsg("can't set hardware: %s\n",
			snd_strerror(ret));
		return 0;
		}
	else logmsg("hardware configd\n");
	snd_pcm_sw_params_malloc(&sparams);
	snd_pcm_sw_params_current(handle, sparams);
	snd_pcm_sw_params_set_avail_min(handle, sparams, blocksize);
	snd_pcm_sw_params_set_start_threshold(handle, sparams, 0U);
	if ((ret = snd_pcm_sw_params(handle, sparams)) < 0) {
		logmsg("can't set software: %s\n",
			snd_strerror(ret));
		}
	else logmsg("software configd\n");
	snd_pcm_sw_params_free(sparams);
	pthread_create(&thread_id, NULL, dev_thread, NULL);
	return 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=-1;
    int count=0;
    unsigned int freakuency=settings.frequency();

    QString dev = 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)
        dev = QLatin1String(devices.first().constData());
#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;
        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 ) {
        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;
        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;
}
Exemplo n.º 24
0
void
ags_devout_alsa_init(AgsSoundcard *soundcard,
		     GError **error)
{
  AgsDevout *devout;
  
  int rc;
  snd_pcm_t *handle;
  snd_pcm_hw_params_t *hwparams;
  unsigned int val;
  snd_pcm_uframes_t frames;
  unsigned int rate;
  unsigned int rrate;
  unsigned int channels;
  snd_pcm_uframes_t size;
  snd_pcm_sframes_t buffer_size;
  snd_pcm_sframes_t period_size;
  snd_pcm_sw_params_t *swparams;
  int period_event = 0;
  int err, dir;

  static unsigned int period_time = 100000;
  static snd_pcm_format_t format = SND_PCM_FORMAT_S16;

  devout = AGS_DEVOUT(soundcard);
  
  /*  */
  devout->flags |= (AGS_DEVOUT_BUFFER3 |
		    AGS_DEVOUT_START_PLAY |
		    AGS_DEVOUT_PLAY |
		    AGS_DEVOUT_NONBLOCKING);

  devout->note_offset = 0;

  memset(devout->buffer[0], 0, devout->dsp_channels * devout->buffer_size * sizeof(signed short));
  memset(devout->buffer[1], 0, devout->dsp_channels * devout->buffer_size * sizeof(signed short));
  memset(devout->buffer[2], 0, devout->dsp_channels * devout->buffer_size * sizeof(signed short));
  memset(devout->buffer[3], 0, devout->dsp_channels * devout->buffer_size * sizeof(signed short));

  /* Open PCM device for playback. */
  if ((err = snd_pcm_open(&handle, devout->out.alsa.device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
    printf("Playback open error: %s\n", snd_strerror(err));
    g_set_error(error,
		AGS_DEVOUT_ERROR,
		AGS_DEVOUT_ERROR_LOCKED_SOUNDCARD,
		"unable to open pcm device: %s\n\0",
		snd_strerror(err));
    return;
  }

  snd_pcm_hw_params_alloca(&hwparams);
  snd_pcm_sw_params_alloca(&swparams);

  /* choose all parameters */
  err = snd_pcm_hw_params_any(handle, hwparams);
  if (err < 0) {
    printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
    return;
  }

  /* set hardware resampling */
  err = snd_pcm_hw_params_set_rate_resample(handle, hwparams, 1);
  if (err < 0) {
    printf("Resampling setup failed for playback: %s\n", snd_strerror(err));
    return;
  }

  /* set the interleaved read/write format */
  err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
  if (err < 0) {
    printf("Access type not available for playback: %s\n", snd_strerror(err));
    return;
  }

  /* set the sample format */
  err = snd_pcm_hw_params_set_format(handle, hwparams, format);
  if (err < 0) {
    printf("Sample format not available for playback: %s\n", snd_strerror(err));
    return;
  }

  /* set the count of channels */
  channels = devout->dsp_channels;
  err = snd_pcm_hw_params_set_channels(handle, hwparams, channels);
  if (err < 0) {
    printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err));
    return;
  }

  /* set the stream rate */
  rate = devout->samplerate;
  rrate = rate;
  err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rrate, 0);
  if (err < 0) {
    printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
    return;
  }

  if (rrate != rate) {
    printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
    //    exit(-EINVAL);
    return;
  }

  /* set the buffer size */
  size = devout->buffer_size;
  err = snd_pcm_hw_params_set_buffer_size(handle, hwparams, size);
  if (err < 0) {
    printf("Unable to set buffer size %i for playback: %s\n", size, snd_strerror(err));
    return;
  }

  buffer_size = size;

  /* set the period time */
  period_time = MSEC_PER_SEC / devout->samplerate;
  dir = -1;
  err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir);
  if (err < 0) {
    printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
    return;
  }

  err = snd_pcm_hw_params_get_period_size(hwparams, &size, &dir);
  if (err < 0) {
    printf("Unable to get period size for playback: %s\n", snd_strerror(err));
    return;
  }
  period_size = size;

  /* write the parameters to device */
  err = snd_pcm_hw_params(handle, hwparams);
  if (err < 0) {
    printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
    return;
  }

  /* get the current swparams */
  err = snd_pcm_sw_params_current(handle, swparams);
  if (err < 0) {
    printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
    return;
  }

  /* start the transfer when the buffer is almost full: */
  /* (buffer_size / avail_min) * avail_min */
  err = snd_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size / period_size) * period_size);
  if (err < 0) {
    printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
    return;
  }

  /* allow the transfer when at least period_size samples can be processed */
  /* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
  err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_event ? buffer_size : period_size);
  if (err < 0) {
    printf("Unable to set avail min for playback: %s\n", snd_strerror(err));
    return;
  }

  /* write the parameters to the playback device */
  err = snd_pcm_sw_params(handle, swparams);
  if (err < 0) {
    printf("Unable to set sw params for playback: %s\n", snd_strerror(err));
    return;
  }

  /*  */
  devout->out.alsa.handle = handle;
  devout->delay_counter = 0.0;
  devout->tic_counter = 0;
}
Exemplo n.º 25
0
static void set_params(void)
{
	snd_pcm_hw_params_t *params;
	snd_pcm_sw_params_t *swparams;
	snd_pcm_uframes_t buffer_size;
	int err;
	size_t n;
	snd_pcm_uframes_t xfer_align;
	unsigned int rate;
	snd_pcm_uframes_t start_threshold, stop_threshold;
	snd_pcm_hw_params_alloca(&params);
	snd_pcm_sw_params_alloca(&swparams);
	err = snd_pcm_hw_params_any(handle, params);
	if (err < 0) {
		error(_("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) {
		error(_("Access type not available"));
		exit(EXIT_FAILURE);
	}
	err = snd_pcm_hw_params_set_format(handle, params, hwparams.format);
	if (err < 0) {
		error(_("Sample format non available"));
		exit(EXIT_FAILURE);
	}
	err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels);
	if (err < 0) {
		error(_("Channels count non available"));
		exit(EXIT_FAILURE);
	}

#if 0
	err = snd_pcm_hw_params_set_periods_min(handle, params, 2);
	assert(err >= 0);
#endif
	rate = hwparams.rate;
	err = snd_pcm_hw_params_set_rate_near(handle, params, &hwparams.rate, 0);
	assert(err >= 0);
	if ((float)rate * 1.05 < hwparams.rate || (float)rate * 0.95 > hwparams.rate) {
		if (!quiet_mode) {
			char plugex[64];
			const char *pcmname = snd_pcm_name(handle);
			fprintf(stderr, _("Warning: rate is not accurate (requested = %iHz, got = %iHz)\n"), rate, hwparams.rate);
			if (! pcmname || strchr(snd_pcm_name(handle), ':'))
				*plugex = 0;
			else
				snprintf(plugex, sizeof(plugex), "(-Dplug:%s)",
					 snd_pcm_name(handle));
			fprintf(stderr, _("         please, try the plug plugin %s\n"),
				plugex);
		}
	}
	rate = hwparams.rate;
	if (buffer_time == 0 && buffer_frames == 0) {
		err = snd_pcm_hw_params_get_buffer_time_max(params,
							    &buffer_time, 0);
		assert(err >= 0);
		if (buffer_time > 500000)
			buffer_time = 500000;
	}
	if (period_time == 0 && period_frames == 0) {
		if (buffer_time > 0)
			period_time = buffer_time / 4;
		else
			period_frames = buffer_frames / 4;
	}
	if (period_time > 0)
		err = snd_pcm_hw_params_set_period_time_near(handle, params,
							     &period_time, 0);
	else
		err = snd_pcm_hw_params_set_period_size_near(handle, params,
							     &period_frames, 0);
	assert(err >= 0);
	if (buffer_time > 0) {
		err = snd_pcm_hw_params_set_buffer_time_near(handle, params,
							     &buffer_time, 0);
	} else {
		err = snd_pcm_hw_params_set_buffer_size_near(handle, params,
							     &buffer_frames);
	}
	assert(err >= 0);
	err = snd_pcm_hw_params(handle, params);
	if (err < 0) {
		error(_("Unable to install hw params:"));
		snd_pcm_hw_params_dump(params, log);
		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) {
		error(_("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_get_xfer_align(swparams, &xfer_align);
	if (err < 0) {
		error(_("Unable to obtain xfer align\n"));
		exit(EXIT_FAILURE);
	}
	if (sleep_min)
		xfer_align = 1;
	err = snd_pcm_sw_params_set_sleep_min(handle, swparams,
					      sleep_min);
	assert(err >= 0);
	if (avail_min < 0)
		n = chunk_size;
	else
		n = (double) rate * avail_min / 1000000;
	err = snd_pcm_sw_params_set_avail_min(handle, swparams, n);

	// round up to closest transfer boundary
	n = (buffer_size / xfer_align) * xfer_align;
	start_threshold = n;
	if (start_threshold < 1)
		start_threshold = 1;
	if (start_threshold > n)
		start_threshold = n;
	err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
	assert(err >= 0);
	stop_threshold = buffer_size;
	err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
	assert(err >= 0);

	err = snd_pcm_sw_params_set_xfer_align(handle, swparams, xfer_align);
	assert(err >= 0);

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

	bits_per_sample = snd_pcm_format_physical_width(hwparams.format);
	bits_per_frame = bits_per_sample * hwparams.channels;
	chunk_bytes = chunk_size * bits_per_frame / 8;
	audiobuf = realloc(audiobuf, chunk_bytes);
	if (audiobuf == NULL) {
		error(_("not enough memory"));
		exit(EXIT_FAILURE);
	}
	// fprintf(stderr, "real chunk_size = %i, frags = %i, total = %i\n", chunk_size, setup.buf.block.frags, setup.buf.block.frags * chunk_size);
}
Exemplo n.º 26
0
static int
set_swparams (GstAlsaSink * alsa)
{
    int err;
    snd_pcm_sw_params_t *params;

    snd_pcm_sw_params_malloc (&params);

    /* get the current swparams */
    CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
    /* start the transfer when the buffer is almost full: */
    /* (buffer_size / avail_min) * avail_min */
    CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
            (alsa->buffer_size / alsa->period_size) * alsa->period_size),
           start_threshold);

    /* allow the transfer when at least period_size samples can be processed */
    CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
                                            alsa->period_size), set_avail);

#if GST_CHECK_ALSA_VERSION(1,0,16)
    /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
#else
    /* align all transfers to 1 sample */
    CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
#endif

    /* write the parameters to the playback device */
    CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);

    snd_pcm_sw_params_free (params);
    return 0;

    /* ERRORS */
no_config:
    {
        GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
                           ("Unable to determine current swparams for playback: %s",
                            snd_strerror (err)));
        snd_pcm_sw_params_free (params);
        return err;
    }
start_threshold:
    {
        GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
                           ("Unable to set start threshold mode for playback: %s",
                            snd_strerror (err)));
        snd_pcm_sw_params_free (params);
        return err;
    }
set_avail:
    {
        GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
                           ("Unable to set avail min for playback: %s", snd_strerror (err)));
        snd_pcm_sw_params_free (params);
        return err;
    }
#if !GST_CHECK_ALSA_VERSION(1,0,16)
set_align:
    {
        GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
                           ("Unable to set transfer align for playback: %s", snd_strerror (err)));
        snd_pcm_sw_params_free (params);
        return err;
    }
#endif
set_sw_params:
    {
        GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
                           ("Unable to set sw params for playback: %s", snd_strerror (err)));
        snd_pcm_sw_params_free (params);
        return err;
    }
}
Exemplo n.º 27
0
static int aplaypop_open(void)
{
    int err;
    snd_pcm_t *handle;

    if (pcm_handle)
        return 0;

    snd_pcm_info_t *info;
    snd_pcm_info_alloca(&info);

    snd_output_t *log;
    err = snd_output_stdio_attach(&log, stderr, 0);
    assert(err == 0);

    err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0);
    if (err != 0) {
        fprintf(stderr, "snd_pcm_open(): %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }
    err = snd_pcm_nonblock(handle, 0);
    if (err != 0) {
        fprintf(stderr, "snd_pcm_nonblock(): %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }
    err = snd_pcm_info(handle, info);
    if (err != 0) {
        fprintf(stderr, "snd_pcm_info(): %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }

    // DOESN'T WORK!
    err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE,
        SND_PCM_ACCESS_RW_INTERLEAVED, CHANNELS, RATE, 1, 50000);
    if (err != 0) {
        fprintf(stderr, "snd_pcm_set_params(): %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }

    // RIGHT WAY:
    snd_pcm_hw_params_t *hwparams;
    snd_pcm_sw_params_t *swparams;

    snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
    unsigned int channels = CHANNELS;
    unsigned int rate = RATE;

    snd_pcm_hw_params_alloca(&hwparams);
    snd_pcm_sw_params_alloca(&swparams);

    err = snd_pcm_hw_params_any(handle, hwparams);
    if (err != 0) {
        fprintf(stderr, "Broken configuration for this PCM: %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }
    err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err != 0) {
        fprintf(stderr, "snd_pcm_hw_params_set_access(): %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }
    err = snd_pcm_hw_params_set_format(handle, hwparams, format);
    if (err != 0) {
        fprintf(stderr, "snd_pcm_hw_params_set_format(): %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }
    err = snd_pcm_hw_params_set_channels(handle, hwparams, channels);
    if (err != 0) {
        fprintf(stderr, "snd_pcm_hw_params_set_channels(): %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }
    err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, 0);
    if (err != 0) {
        fprintf(stderr, "snd_pcm_hw_params_set_rate_near(): %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }
/*
    unsigned buffer_time = 0;
    snd_pcm_uframes_t buffer_frames = 0;

    if (buffer_time == 0 && buffer_frames == 0) {
        err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time, 0);
        assert(err == 0);
        if (buffer_time > 500000)
            buffer_time = 500000;
    }

    unsigned period_time = 0;
    snd_pcm_uframes_t period_frames = 0;

    if (period_time == 0 && period_frames == 0) {
        if (buffer_time > 0)
            period_time = buffer_time / 4;
        else
            period_frames = buffer_frames / 4;
    }

    if (period_time > 0)
        err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0);
    else
        err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_frames, 0);
    assert(err == 0);

    if (buffer_time > 0)
        err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0);
    else
        err = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_frames);
    assert(err == 0);

    int monotonic = snd_pcm_hw_params_is_monotonic(hwparams);
    int can_pause = snd_pcm_hw_params_can_pause(hwparams);
*/
    err = snd_pcm_hw_params(handle, hwparams);
    if (err != 0) {
        fprintf(stderr, "snd_pcm_hw_params(): %s\n", snd_strerror(err));
        snd_pcm_hw_params_dump(hwparams, log);
        exit(EXIT_FAILURE);
    }
    snd_pcm_uframes_t chunk_size = 0;
    snd_pcm_hw_params_get_period_size(hwparams, &chunk_size, 0);
    snd_pcm_uframes_t buffer_size;
    snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
    if (chunk_size == buffer_size) {
        fprintf(stderr, "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);
    assert(err == 0);

    /* round up to closest transfer boundary */
    int start_delay = 0;
    snd_pcm_uframes_t start_threshold;
    if (start_delay <= 0)
        start_threshold = buffer_size + (double) rate * start_delay / 1000000;
    else
        start_threshold = (double) rate * start_delay / 1000000;
    start_threshold = start_threshold < 1 ? 1 : start_threshold > buffer_size ? buffer_size : start_threshold;
    err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
    assert(err == 0);

    int stop_delay = 0;
    snd_pcm_uframes_t stop_threshold;
    if (stop_delay <= 0)
        stop_threshold = buffer_size + (double) rate * stop_delay / 1000000;
    else
        stop_threshold = (double) rate * stop_delay / 1000000;
    err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
    assert(err == 0);

    err = snd_pcm_sw_params(handle, swparams);
    if (err != 0) {
        fprintf(stderr, "snd_pcm_sw_params(): %s\n", snd_strerror(err));
        snd_pcm_sw_params_dump(swparams, log);
        exit(EXIT_FAILURE);
    }
    // END OF THE RIGHT WAY

//  snd_pcm_dump(handle, log);

    size_t bits_per_sample = snd_pcm_format_physical_width(format);
    size_t bits_per_frame = bits_per_sample * channels;
    size_t chunk_bytes = chunk_size * bits_per_frame / 8;
    //audiobuf = realloc(audiobuf, chunk_bytes);

    fprintf(stderr, "%s: %s, Rate %d Hz, Channels=%u\n",
        snd_pcm_format_name(format), snd_pcm_format_description(format),
        rate, channels);
    fprintf(stderr, "  bits_per_sample=%u, bits_per_frame=%u, chunk_bytes=%u\n",
        bits_per_sample, bits_per_frame, chunk_bytes);

    frame_bytes = bits_per_frame / 8;
    pcm_handle = handle;
    return 0;
}
Exemplo n.º 28
0
int
ga_alsa_set_param(struct Xcap_alsa_param *param) {
	snd_pcm_hw_params_t *hwparams = NULL;
	snd_pcm_sw_params_t *swparams = NULL;
	size_t bits_per_sample;
	unsigned int rate;
	unsigned int buffer_time = 500000;	// in the unit of microsecond
	unsigned int period_time = 125000;	// = buffer_time/4;
	int monotonic = 0;
	snd_pcm_uframes_t start_threshold, stop_threshold;
	int err;
	//
	snd_pcm_hw_params_alloca(&hwparams);
	snd_pcm_sw_params_alloca(&swparams);
	if((err = snd_pcm_hw_params_any(param->handle, hwparams)) < 0) {
		ga_error("ALSA: set_param - no configurations available\n");
		return -1;
	}
	if((err = snd_pcm_hw_params_set_access(param->handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
		ga_error("ALSA: set_param - access type (interleaved) not available\n");
		return -1;
	}
	if((err = snd_pcm_hw_params_set_format(param->handle, hwparams, param->format)) < 0) {
		ga_error("ALSA: set_param - unsupported sample format.\n");
		return -1;
	}
	if((err = snd_pcm_hw_params_set_channels(param->handle, hwparams, param->channels)) < 0) {
		ga_error("ALSA: set_param - channles count not available\n");
		return -1;
	}
	rate = param->samplerate;
	if((err = snd_pcm_hw_params_set_rate_near(param->handle, hwparams, &rate, 0)) < 0) {
		ga_error("ALSA: set_param - set rate failed.\n");
		return -1;
	}
	if((double)param->samplerate*1.05 < rate || (double)param->samplerate*0.95 > rate) {
		ga_error("ALSA: set_param/warning - inaccurate rate (req=%iHz, got=%iHz)\n", param->samplerate, rate);
	}
	//
	period_time = buffer_time/4;
	if((err = snd_pcm_hw_params_set_period_time_near(param->handle, hwparams, &period_time, 0)) < 0) {
		ga_error("ALSA: set_param - set period time failed.\n");
		return -1;
	}
	if((err = snd_pcm_hw_params_set_buffer_time_near(param->handle, hwparams, &buffer_time, 0)) < 0) {
		ga_error("ALSA: set_param - set buffer time failed.\n");
		return -1;
	}
	//
	monotonic = snd_pcm_hw_params_is_monotonic(hwparams);
	if((err = snd_pcm_hw_params(param->handle, hwparams)) < 0) {
		ga_error("ALSA: set_param - unable to install hw params:");
		snd_pcm_hw_params_dump(hwparams, sndlog);
		return -1;
	}
	snd_pcm_hw_params_get_period_size(hwparams, &param->chunk_size, 0);
	snd_pcm_hw_params_get_buffer_size(hwparams, &param->buffer_size);
	if(param->chunk_size == param->buffer_size) {
		ga_error("ALSA: set_param - cannot use period equal to buffer size (%lu==%lu)\n",
			param->chunk_size, param->buffer_size);
		return -1;
	}
	//
	snd_pcm_sw_params_current(param->handle, swparams);
	err = snd_pcm_sw_params_set_avail_min(param->handle, swparams, param->chunk_size);
	// start_delay = 1 for capture
	start_threshold = (double) param->samplerate * /*start_delay=*/ 1 / 1000000;
	if(start_threshold < 1)				start_threshold = 1;
	if(start_threshold > param->buffer_size)	start_threshold = param->buffer_size;
	if((err = snd_pcm_sw_params_set_start_threshold(param->handle, swparams, start_threshold)) < 0) {
		ga_error("ALSA: set_param - set start threshold failed.\n");
		return -1;
	}
	// stop_delay = 0
	stop_threshold = param->buffer_size;
	if((err = snd_pcm_sw_params_set_stop_threshold(param->handle, swparams, stop_threshold)) < 0) {
		ga_error("ALSA: set_param - set stop threshold failed.\n");
		return -1;
	}
	//
	if(snd_pcm_sw_params(param->handle, swparams) < 0) {
		ga_error("ALSA: set_param - unable to install sw params:");
		snd_pcm_sw_params_dump(swparams, sndlog);
		return -1;
	}

	bits_per_sample = snd_pcm_format_physical_width(param->format);
	if(param->bits_per_sample != bits_per_sample) {
		ga_error("ALSA: set_param - BPS/HW configuration mismatched %d != %d)\n",
			param->bits_per_sample, bits_per_sample);
	}
	param->bits_per_frame = param->bits_per_sample * param->channels;
	param->chunk_bytes = param->chunk_size * param->bits_per_frame / 8;

	return 0;
}
Exemplo n.º 29
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;

  xassert (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;
      const char *file = sd->file ? sd->file : DEFAULT_ALSA_SOUND_DEVICE;

      if (snd_mixer_open (&handle, 0) >= 0)
        {
          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);
        }
    }
}
Exemplo n.º 30
0
static snd_pcm_t *alsa_open(char *dev, int rate, int channels)
{
	snd_pcm_hw_params_t *hwp;
	snd_pcm_sw_params_t *swp;
	snd_pcm_t *h;
	int r;
	int dir;
	snd_pcm_uframes_t period_size_min;
	snd_pcm_uframes_t period_size_max;
	snd_pcm_uframes_t buffer_size_min;
	snd_pcm_uframes_t buffer_size_max;
	snd_pcm_uframes_t period_size;
	snd_pcm_uframes_t buffer_size;

	if ((r = snd_pcm_open(&h, dev, SND_PCM_STREAM_PLAYBACK, 0) < 0))
		return NULL;

	hwp = alloca(snd_pcm_hw_params_sizeof());
	memset(hwp, 0, snd_pcm_hw_params_sizeof());
	snd_pcm_hw_params_any(h, hwp);

	snd_pcm_hw_params_set_access(h, hwp, SND_PCM_ACCESS_RW_INTERLEAVED);
	snd_pcm_hw_params_set_format(h, hwp, SND_PCM_FORMAT_S16_LE);
	snd_pcm_hw_params_set_rate(h, hwp, rate, 0);
	snd_pcm_hw_params_set_channels(h, hwp, channels);

	/* Configurue period */

	dir = 0;
	snd_pcm_hw_params_get_period_size_min(hwp, &period_size_min, &dir);
	dir = 0;
	snd_pcm_hw_params_get_period_size_max(hwp, &period_size_max, &dir);

	period_size = 1024;

	dir = 0;
	r = snd_pcm_hw_params_set_period_size_near(h, hwp, &period_size, &dir);

	if (r < 0) {
		fprintf(stderr, "audio: Unable to set period size %lu (%s)\n",
		        period_size, snd_strerror(r));
		snd_pcm_close(h);
		return NULL;
	}

	dir = 0;
	r = snd_pcm_hw_params_get_period_size(hwp, &period_size, &dir);

	if (r < 0) {
		fprintf(stderr, "audio: Unable to get period size (%s)\n",
		        snd_strerror(r));
		snd_pcm_close(h);
		return NULL;
	}

	/* Configurue buffer size */

	snd_pcm_hw_params_get_buffer_size_min(hwp, &buffer_size_min);
	snd_pcm_hw_params_get_buffer_size_max(hwp, &buffer_size_max);
	buffer_size = period_size * 4;

	dir = 0;
	r = snd_pcm_hw_params_set_buffer_size_near(h, hwp, &buffer_size);

	if (r < 0) {
		fprintf(stderr, "audio: Unable to set buffer size %lu (%s)\n",
		        buffer_size, snd_strerror(r));
		snd_pcm_close(h);
		return NULL;
	}

	r = snd_pcm_hw_params_get_buffer_size(hwp, &buffer_size);

	if (r < 0) {
		fprintf(stderr, "audio: Unable to get buffer size (%s)\n",
		        snd_strerror(r));
		snd_pcm_close(h);
		return NULL;
	}

	/* write the hw params */
	r = snd_pcm_hw_params(h, hwp);

	if (r < 0) {
		fprintf(stderr, "audio: Unable to configure hardware parameters (%s)\n",
		        snd_strerror(r));
		snd_pcm_close(h);
		return NULL;
	}

	/*
	 * Software parameters
	 */

	swp = alloca(snd_pcm_sw_params_sizeof());
	memset(hwp, 0, snd_pcm_sw_params_sizeof());
	snd_pcm_sw_params_current(h, swp);

	r = snd_pcm_sw_params_set_avail_min(h, swp, period_size);

	if (r < 0) {
		fprintf(stderr, "audio: Unable to configure wakeup threshold (%s)\n",
		        snd_strerror(r));
		snd_pcm_close(h);
		return NULL;
	}

	snd_pcm_sw_params_set_start_threshold(h, swp, 0);

	if (r < 0) {
		fprintf(stderr, "audio: Unable to configure start threshold (%s)\n",
		        snd_strerror(r));
		snd_pcm_close(h);
		return NULL;
	}

	r = snd_pcm_sw_params(h, swp);

	if (r < 0) {
		fprintf(stderr, "audio: Cannot set soft parameters (%s)\n",
		snd_strerror(r));
		snd_pcm_close(h);
		return NULL;
	}

	r = snd_pcm_prepare(h);
	if (r < 0) {
		fprintf(stderr, "audio: Cannot prepare audio for playback (%s)\n",
		snd_strerror(r));
		snd_pcm_close(h);
		return NULL;
	}

	return h;
}