int setparams_bufsize(snd_pcm_t *handle,
		      snd_pcm_hw_params_t *params,
		      snd_pcm_hw_params_t *tparams,
		      snd_pcm_uframes_t bufsize,
		      const char *id)
{
	int err;
	snd_pcm_uframes_t periodsize;

	snd_pcm_hw_params_copy(params, tparams);
	periodsize = bufsize * 2;
	err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &periodsize);
	if (err < 0) {
		printf("Unable to set buffer size %li for %s: %s\n", bufsize * 2, id, snd_strerror(err));
		return err;
	}
	if (period_size > 0)
		periodsize = period_size;
	else
		periodsize /= 2;
	err = snd_pcm_hw_params_set_period_size_near(handle, params, &periodsize, 0);
	if (err < 0) {
		printf("Unable to set period size %li for %s: %s\n", periodsize, id, snd_strerror(err));
		return err;
	}
	return 0;
}
Ejemplo n.º 2
0
//open a sound device with specified period, rate, channels(0=mono,1=stereo or MONO_SOUND/STEREO_SOUND) 
//  and direction(0=playback,1=capture), returns the buffer (also PLAYBACK_DIR/CAPTURE_DIR)
snd_pcm_t* start_snd_device(size_t period, unsigned int rate, int stereo, int direction){
  //Open PCM device for playback/capture, check for errors
  snd_pcm_t *pcm_handle; //handler struct
  int dir = (direction)? SND_PCM_STREAM_CAPTURE:SND_PCM_STREAM_PLAYBACK;
  int rc = snd_pcm_open(&pcm_handle, "default",dir, 0);
  if (rc < 0){ //make sure it landed
    fprintf(stderr,"unable to open pcm device: %s\n",snd_strerror(rc));
    return 0; //return null pointer
  }

  //Setup the hardware parameters
  snd_pcm_hw_params_t *params;  //create pointer
  snd_pcm_hw_params_alloca(&params); //allocate struct
  snd_pcm_hw_params_any(pcm_handle, params); //fill with defaults
  snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); //interleaved mode
  snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE); //signed 16-bit LE
  snd_pcm_hw_params_set_channels(pcm_handle, params, (stereo+1)); //stereo mode
  unsigned int rate2 = rate; //copy rate (will be overwritten on mismatch)
  int err_dir = 0; //try to set rate exactly
  snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate2, &err_dir); //get closest match
  if(rate != rate2) printf("Rate mismatch, %d give, %d set\n",rate,rate2);
  size_t frames = period; //once again,copy value in case of mismatch
  snd_pcm_hw_params_set_period_size_near(pcm_handle, params, &period, &dir); //set the period
  if(period != frames) printf("Period size mismatch, %d given, %d set", (int)period, (int)frames);
 
  //Write the parameters to the driver
  rc = snd_pcm_hw_params(pcm_handle, params);
  if (rc < 0){ //make sure it landed
    fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
    return 0; //return null
  }
  
  return pcm_handle;
}
Ejemplo n.º 3
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));
}
Ejemplo n.º 4
0
int nv_alsa_init(unsigned int channelCount, unsigned int sampleRate, unsigned char* device) {
	int rc;
	snd_pcm_hw_params_t *params;
	int dir;
	
	/* Open PCM device for playback. */
	if ((rc = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) != 0)
		return rc;
	
	snd_pcm_hw_params_alloca(&params);
	snd_pcm_hw_params_any(handle, params);
	
	if ((rc = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED)) != 0)
                return rc;

	if ((rc = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE)) != 0)
                return rc;

	if ((rc = snd_pcm_hw_params_set_channels(handle, params, channelCount)) != 0)
                return rc;

	if ((rc = snd_pcm_hw_params_set_rate_near(handle, params, &sampleRate, &dir)) != 0)
                return rc;
	
	snd_pcm_uframes_t frames = 32;
	if ((rc = snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir)) != 0)
		return rc;
	
	if ((rc = snd_pcm_hw_params(handle, params)) != 0)
		return rc;
}
Ejemplo n.º 5
0
	// Set device parameters.
	MapilVoid ALSASoundDevice::SetParam( PCMDevConf* pConf )
	{
		_snd_pcm_format pcmFmt[] = {	SND_PCM_FORMAT_UNKNOWN,
										SND_PCM_FORMAT_U8,
										SND_PCM_FORMAT_S8,
										SND_PCM_FORMAT_U16_LE,
										SND_PCM_FORMAT_U16_BE,
										SND_PCM_FORMAT_S16_LE,
										SND_PCM_FORMAT_S16_BE };

		// Allocate hardware parameter.
		snd_pcm_hw_params_alloca( &m_pParam );
		// Get default hardware parameter.
		snd_pcm_hw_params_any( m_pHandle, m_pParam );

		// Set parameters.
		snd_pcm_hw_params_set_access( m_pHandle, m_pParam, SND_PCM_ACCESS_RW_INTERLEAVED );
		snd_pcm_hw_params_set_format( m_pHandle, m_pParam, pcmFmt[ pConf->m_Fmt ] );
		snd_pcm_hw_params_set_channels( m_pHandle, m_pParam, pConf->m_Channel );
		MapilInt32 val;
		snd_pcm_hw_params_set_rate_near( m_pHandle, m_pParam, &pConf->m_Freq, &val );
		snd_pcm_uframes_t frame = 32;
		snd_pcm_hw_params_set_period_size_near( m_pHandle, m_pParam, &frame, &val );

		if( snd_pcm_hw_params( m_pHandle, m_pParam ) < 0 ){
			exit( 1 );
		}
	}
Ejemplo n.º 6
0
void* audio_init(int sampling_rate)
{
    syslog(LOG_INFO, "ALSA: audio_set_driver: this sets the PCM device to :%s\n",g_card);
#ifdef DEBUGALSA
    syslog(LOG_DEBUG,"ALSA: Sample rate proposed %d\n",sampling_rate);
#endif
    int rc, dir = 0;
    snd_pcm_uframes_t frames = 32;
//    rc = snd_pcm_open(&alsa_handle, g_card, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
    rc = snd_pcm_open(&alsa_handle, g_card, SND_PCM_STREAM_PLAYBACK, 0);
    if (rc < 0) {
        syslog(LOG_ERR, "unable to open pcm device: %s\n", snd_strerror(rc));
        die("alsa initialization failed");
    }
    snd_pcm_hw_params_alloca(&alsa_params);
    snd_pcm_hw_params_any(alsa_handle, alsa_params);
    snd_pcm_hw_params_set_access(alsa_handle, alsa_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_hw_params_set_format(alsa_handle, alsa_params, SND_PCM_FORMAT_S16);
    snd_pcm_hw_params_set_channels(alsa_handle, alsa_params, NUM_CHANNELS);
    snd_pcm_hw_params_set_rate_near(alsa_handle, alsa_params, (unsigned int *)&sampling_rate, &dir);
#ifdef DEBUGALSA
    syslog(LOG_DEBUG,"ALSA: Sample rate gotten %d\n",sampling_rate);
#endif
    snd_pcm_hw_params_set_period_size_near(alsa_handle, alsa_params, &frames, &dir);
    rc = snd_pcm_hw_params(alsa_handle, alsa_params);
    if (rc < 0) {
        syslog(LOG_ERR, "unable to set hw parameters: %s\n", snd_strerror(rc));
        die("alsa initialization failed");
    }

    return alsa_handle;
}
Ejemplo n.º 7
0
void audio_init(void)
{
    int ret, dir;
    unsigned int rate;
    snd_pcm_hw_params_t * params;

    rate = 44100;
    frames = 32;
    ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);

    if (ret < 0)
    {
        fprintf(stderr, "Unable to open pcm device: %s\n", snd_strerror(ret));
        exit(EXIT_FAILURE);
    }

    snd_pcm_hw_params_alloca(&params);
    snd_pcm_hw_params_any(handle, params);
    snd_pcm_hw_params_set_access(handle, params, 
            SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
    snd_pcm_hw_params_set_channels(handle, params, 2);
    snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir);
    snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);

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

    snd_pcm_hw_params_get_period_size(params, &frames, &dir);
}
Ejemplo n.º 8
0
static void alsa_set_hw_params(struct alsa_dev *dev, snd_pcm_t *handle,
			       unsigned int rate, int channels, int period)
{
	int dir, ret;
	snd_pcm_uframes_t period_size;
	snd_pcm_uframes_t buffer_size;
	snd_pcm_hw_params_t *hw_params;

	ret = snd_pcm_hw_params_malloc(&hw_params);
	if (ret < 0)
		syslog_panic("Cannot allocate hardware parameters: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params_any(handle, hw_params);
	if (ret < 0)
		syslog_panic("Cannot initialize hardware parameters: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params_set_access(handle, hw_params,
					   SND_PCM_ACCESS_RW_INTERLEAVED);
	if (ret < 0)
		syslog_panic("Cannot set access type: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params_set_format(handle, hw_params,
					   SND_PCM_FORMAT_S16_LE);
	if (ret < 0)
		syslog_panic("Cannot set sample format: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params_set_rate_near(handle, hw_params, &rate, 0);
	if (ret < 0)
		syslog_panic("Cannot set sample rate: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params_set_channels(handle, hw_params, channels);
	if (ret < 0)
		syslog_panic("Cannot set channel number: %s\n",
			     snd_strerror(ret));
	period_size = period;
	dir = 0;
	ret = snd_pcm_hw_params_set_period_size_near(handle, hw_params,
						     &period_size, &dir);
	if (ret < 0)
		syslog_panic("Cannot set period size: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params_set_periods(handle, hw_params, PERIODS, 0);
	if (ret < 0)
		syslog_panic("Cannot set period number: %s\n",
			     snd_strerror(ret));
	buffer_size = period_size * PERIODS;
	dir = 0;
	ret = snd_pcm_hw_params_set_buffer_size_near(handle, hw_params,
						     &buffer_size);
	if (ret < 0)
		syslog_panic("Cannot set buffer size: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params(handle, hw_params);
	if (ret < 0)
		syslog_panic("Cannot set capture parameters: %s\n",
			     snd_strerror(ret));
	snd_pcm_hw_params_free(hw_params);
}
Ejemplo n.º 9
0
bool SoundProcessor::SetUpRecorder(){
  rc_m = snd_pcm_open(&handle_m, "default",
                    SND_PCM_STREAM_CAPTURE, 0);
  if (rc_m < 0) {
    fprintf(stderr,
            "unable to open pcm device: %s\n",
            snd_strerror(rc_m));
    exit(1);
  }

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

  /* Fill it in with default values. */
  snd_pcm_hw_params_any(handle_m, params_m);

  /* Set the desired hardware parameters. */

  /* Interleaved mode */
  snd_pcm_hw_params_set_access(handle_m, params_m,
                      SND_PCM_ACCESS_RW_INTERLEAVED);

  /* Signed 16-bit little-endian format */
  snd_pcm_hw_params_set_format(handle_m, params_m,
                              SND_PCM_FORMAT_U8);

  /* Two channels (stereo) */
  snd_pcm_hw_params_set_channels(handle_m, params_m, 1);

  /* 44100 bits/second sampling rate (CD quality) */
  val_m = 8000;
  snd_pcm_hw_params_set_rate_near(handle_m, params_m,
                                  &val_m, &dir_m);

  /* Set period size to 32 frames. */
  //frames = 32;
  snd_pcm_hw_params_set_period_size_near(handle_m,
                              params_m, &frames, &dir_m);

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

  /* Use a buffer large enough to hold one period */
  snd_pcm_hw_params_get_period_size(params_m,
                                      &frames, &dir_m);
  size = frames; /* 2 bytes/sample, 2 channels */
  buffer_m = (char *) malloc(size);
  /* We want to loop for 5 seconds */
  snd_pcm_hw_params_get_period_time(params_m,
                                         &val_m, &dir_m);
  return true;
}
Ejemplo n.º 10
0
void Recorder::initRecoder()
{
    int rc;
    snd_pcm_hw_params_t *params;
    unsigned int val;
    int dir=0;
    /* 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_S16_LE);

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

    /* 44100 bits/second sampling rate (CD quality) */
    val = SAMPLERATE;
    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 buffer large enough to hold one period */
    snd_pcm_hw_params_get_period_size(params,&frames, &dir);
    size = frames * 2; /* 2 bytes/sample, 2 channels */

    /* We want to loop for 5 seconds */
    snd_pcm_hw_params_get_period_time(params,&val, &dir);
    //loops = 5000000 / val;  //获取5秒中所对应的loop这里用不到

}
Ejemplo n.º 11
0
int audio_capture_init(char *audio_dev)
{
	unsigned int val;
	int dir, rc, size;

	/* 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));
		return -1;
	}

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

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

	/* Set the desired hardware parameters. */

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

	/* Signed 16-bit little-endian format */
	snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE);

	/* 1 channel mono */
	snd_pcm_hw_params_set_channels(handle, hw_params, 1);

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

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

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

	/* Use a buffer large enough to hold one period */
	snd_pcm_hw_params_get_period_size(hw_params, &frames, &dir);
	size = frames * 4;	/* 2 bytes/sample, 2 channels */
	frame_buffer = (char *) malloc(size);
	printf("- Allocated %d bytes frame buffer\n", size);

	snd_pcm_hw_params_get_period_time(hw_params, &val, &dir);

	return 0;
}
void set_hwparams(snd_pcm_t *phandle)
{
	int err;
	snd_pcm_hw_params_t *params;

	err = snd_output_stdio_attach(&log, stderr, 0);
	if (err < 0) {
		fprintf(stderr, "cannot attach output stdio\n");
		exit(0);
	}

	snd_pcm_hw_params_alloca(&params);
	err = snd_pcm_hw_params_any(phandle, params);
	if (err < 0) {
		fprintf(stderr, "Broken configuration for this PCM: no configurations available\n");
		exit(0);
	}

	err = snd_pcm_hw_params_set_access(phandle, params,
					   SND_PCM_ACCESS_RW_INTERLEAVED);
	if (err < 0) {
		fprintf(stderr, "Access type not available\n");
		exit(0);
	}
	err = snd_pcm_hw_params_set_format(phandle, params, SND_PCM_FORMAT_S16_LE);
	if (err < 0) {
		fprintf(stderr, "cannot set format\n");
		exit(0);
	}
	err = snd_pcm_hw_params_set_channels(phandle, params, 2);
	if (err < 0) {
		fprintf(stderr, "cannot set channels 2\n");
		exit(0);
	}
	err = snd_pcm_hw_params_set_rate_near(phandle, params, 44100, 0);
	if (err < 0) {
		fprintf(stderr, "cannot set rate\n");
		exit(0);
	}
	err = snd_pcm_hw_params_set_period_size_near(phandle, params, period_size);
	if (err < 0) {
		fprintf(stderr, "cannot set period size\n");
		exit(0);
	}
	err = snd_pcm_hw_params(phandle, params);
	if (err < 0) {
		fprintf(stderr, "Unable to install hw params:\n");
		exit(0);
	}
	snd_pcm_hw_params_dump(params, log);
}
Ejemplo n.º 13
0
/****************************************************************************************
*   函数名: init_alsa_play
*   输  入: 无
*   输  出: 无
*   功能说明:alsa音频播放器初始化
*
*       
******************************************************************************************/
void init_alsa_play()
{
		snd_pcm_hw_params_t *params; 
		unsigned int val; 
		int dir; 
				
		/* Open PCM device for playback. */
		rc=snd_pcm_open(&handle,"plughw:0,0", SND_PCM_STREAM_PLAYBACK, 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_S16_LE); 


		/* Two channels (stereo) 声道*/  
		snd_pcm_hw_params_set_channels(handle, params, channels); 
		/* 32000 bits/second sampling rate (CD quality) 采样率设置*/ 
		snd_pcm_hw_params_set_rate_near(handle,params, &rate, &dir);  /* Set period size to 32 frames. */ 
		frames = SAMPLERATE/1000*READMSFORONCE; 
		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 buffer large enough to hold one period*/
		snd_pcm_hw_params_get_period_size(params, &frames,  &dir); //32个采样点算一帧
		size = frames * (channels);
		/* 2 bytes/sample, 2 channels */ 
		buffer = (char *) malloc(size); 
		/* We want to loop for 5 seconds */
		snd_pcm_hw_params_get_period_time(params, &val, &dir); 
}
Ejemplo n.º 14
0
void
carmen_sound_set_device_parameters(snd_pcm_t *handle, int sampling_rate, int num_frames)
{
	int rc, dir;
	unsigned int val;
	snd_pcm_hw_params_t *params;
	snd_pcm_uframes_t frames;

	val = sampling_rate;
	frames = (snd_pcm_uframes_t) num_frames;

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

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

	/* 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_S16_LE);

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

	/* set bits/second sampling rate */
	snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);

	/* Set period size to num of frames. */
	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)
		exit(printf("unable to set hw parameters: %s\n", snd_strerror(rc)));

	/* Use a buffer large enough to hold one period */
	snd_pcm_hw_params_get_period_size(params, &frames, &dir);

	/* We want to loop for 5 seconds */
	snd_pcm_hw_params_get_period_time(params, &val, &dir);

	// @TODO: pesquisar por que tem que ler um pouco que vem vazio nao sei por que...
	char buffer[4 * 32];
	rc = snd_pcm_readi(handle, buffer, 32);
}
Ejemplo n.º 15
0
void AudioWalkera::setupAlsa(){

	int dir;

	int t = 0, i, c;

	rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0);

	if(rc < 0)
		exitError("Could not open pcm device");

	snd_pcm_hw_params_alloca(&params);
	//rc = setupHardware(handle, params, &dir);


	snd_pcm_uframes_t frames_inner;
	unsigned int val;

	snd_pcm_hw_params_any(handle, params);

	snd_pcm_hw_params_set_access(handle, params, 
			SND_PCM_ACCESS_RW_INTERLEAVED);

	snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);

	snd_pcm_hw_params_set_channels(handle, params, 1);


	val = 48000;
	snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);

	frames_inner = 2304;
	snd_pcm_hw_params_set_period_size_near(handle, params, &frames_inner, &dir);

	rc = snd_pcm_hw_params(handle, params);
 

	if(rc < 0)
		exitError("Could not set hardware parameters");

	snd_pcm_hw_params_get_period_size(params, &frames, &dir);

	buffer = (short*) calloc(frames, sizeof(short));


}
Ejemplo n.º 16
0
int
sound_init ()
{
  int rc;

  rc = snd_pcm_open (&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
  if (rc < 0)
    {
      fprintf (stderr, "unable to open pcm device: %s\n", snd_strerror (rc));
      return rc;
    }

  g_paused = 0;

  snd_pcm_hw_params_alloca (&params);

  snd_pcm_hw_params_any (handle, params);

  snd_pcm_hw_params_set_access (handle, params,
				SND_PCM_ACCESS_RW_INTERLEAVED);

  snd_pcm_hw_params_set_format (handle, params, SND_PCM_FORMAT_S16_LE);

  snd_pcm_hw_params_set_channels (handle, params, CHANNELS);

  val = RATE;
  snd_pcm_hw_params_set_rate_near (handle, params, &val, &dir);

  frames = FRAMES;
  snd_pcm_hw_params_set_period_size_near (handle, params, &frames, &dir);

  rc = snd_pcm_hw_params (handle, params);
  if (rc < 0)
    return rc;

  snd_pcm_hw_params_get_period_size (params, &frames, &dir);

  snd_pcm_hw_params_get_period_time (params, &val, &dir);

  return 0;
}
Ejemplo n.º 17
0
static void start(int sample_rate) {
    if (sample_rate != 44100)
        die("Unexpected sample rate!");

    int ret, dir = 0;
    snd_pcm_uframes_t frames = 64;
    ret = snd_pcm_open(&alsa_handle, alsa_out_dev, SND_PCM_STREAM_PLAYBACK, 0);
    if (ret < 0)
        die("Alsa initialization failed: unable to open pcm device: %s\n", snd_strerror(ret));

    snd_pcm_hw_params_alloca(&alsa_params);
    snd_pcm_hw_params_any(alsa_handle, alsa_params);
    snd_pcm_hw_params_set_access(alsa_handle, alsa_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_hw_params_set_format(alsa_handle, alsa_params, SND_PCM_FORMAT_S16);
    snd_pcm_hw_params_set_channels(alsa_handle, alsa_params, 2);
    snd_pcm_hw_params_set_rate_near(alsa_handle, alsa_params, (unsigned int *)&sample_rate, &dir);
    snd_pcm_hw_params_set_period_size_near(alsa_handle, alsa_params, &frames, &dir);
    ret = snd_pcm_hw_params(alsa_handle, alsa_params);
    if (ret < 0)
        die("unable to set hw parameters: %s\n", snd_strerror(ret));
}
Ejemplo n.º 18
0
SoundOutput_alsa::SoundOutput_alsa(int mixing_frequency, int mixing_latency) :
	SoundOutput_Impl(mixing_frequency, mixing_latency), frames_in_buffer(4096),
	frames_in_period(1024)
{
	int rc;
	snd_pcm_hw_params_t *hwparams;
	
	rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
	if (rc < 0)
	{
		log_event("warn", "ClanSound: Couldn't open sound device, disabling sound");
		handle = nullptr;
		return;
	}

	snd_pcm_hw_params_alloca(&hwparams);
	snd_pcm_hw_params_any(handle, hwparams);
	snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
	snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_FLOAT);
	snd_pcm_hw_params_set_channels(handle, hwparams, 2);
	snd_pcm_hw_params_set_rate_near(handle, hwparams,
				(unsigned int *)&this->mixing_frequency, nullptr);
	snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &frames_in_buffer);
	frames_in_period = frames_in_buffer / 4;
	snd_pcm_hw_params_set_period_size_near(handle, hwparams, &frames_in_period, nullptr);
	
	rc = snd_pcm_hw_params(handle, hwparams);
	if (rc < 0)
	{
		log_event("warn", "ClanSound: Couldn't initialize sound device, disabling sound");
		snd_pcm_close(handle);
		handle = nullptr;
		return;
	}
	
	snd_pcm_hw_params_get_period_size(hwparams, &frames_in_period, nullptr);

	start_mixer_thread();
}
Ejemplo n.º 19
0
// 声卡采集初始化
struct SoundInfo* sound_info_record_new() {
    struct SoundInfo *info = (struct SoundInfo*)malloc(sizeof(struct SoundInfo));
    int rc;
    int dir = 0;

    info->channels = 2; 
    info->frequency = 44100;

    rc = snd_pcm_open(&info->handle, "default", SND_PCM_STREAM_CAPTURE, 0);

    snd_pcm_hw_params_alloca(&info->params);

    rc = snd_pcm_hw_params_any(info->handle, info->params);

    rc = snd_pcm_hw_params_set_access(info->handle, info->params, SND_PCM_ACCESS_RW_INTERLEAVED);

    snd_pcm_hw_params_set_format(info->handle, info->params, SND_PCM_FORMAT_S16_LE);

    rc = snd_pcm_hw_params_set_channels(info->handle, info->params, info->channels);

    unsigned int val = info->frequency;
    rc = snd_pcm_hw_params_set_rate_near(info->handle, info->params, &val, &dir);

    rc = snd_pcm_hw_params(info->handle, info->params);

    info->frames = 32;//"frames"=channel*size/8=4, frames = "frames"*8 one period contains 8 "frames"    
    snd_pcm_hw_params_set_period_size_near(info->handle, info->params, &info->frames, &dir);

    rc = snd_pcm_hw_params(info->handle, info->params);

    snd_pcm_hw_params_get_period_size(info->params, &info->frames, &dir);

    info->bufferSize = info->frames * 4;
    info->buffer = (char*) malloc(info->bufferSize);
    snd_pcm_hw_params_get_period_time(info->params, &val, &dir);
    memset(info->buffer, 0, info->bufferSize);

    return info;
}
    optional<int> AudioOutputDeviceAlsa::ParameterFragmentSize::DefaultAsInt(std::map<String,String> Parameters) {
        if (!Parameters.count("CARD")) return optional<int>::nothing;

        // obtain information from given sound card
        ParameterCard card(Parameters["CARD"]);
        String pcm_name = "hw:" + card.ValueAsString();
        snd_pcm_t* pcm_handle = NULL;
        if (snd_pcm_open(&pcm_handle, pcm_name.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) return optional<int>::nothing;
        snd_pcm_hw_params_t* hwparams;
        snd_pcm_hw_params_alloca(&hwparams);
        if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
            snd_pcm_close(pcm_handle);
            return optional<int>::nothing;
        }
        snd_pcm_uframes_t size = 128;
        if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &size, NULL) < 0) {
            snd_pcm_close(pcm_handle);
            return optional<int>::nothing;
        }
        snd_pcm_close(pcm_handle);
        return size;
    }
Ejemplo n.º 21
0
/**
 * This method will open the given device so that it can be accessed.
 */
void AudioInterface::open() {
	int rc; // This variable is to be used to store the return code from various calls.
	int dir;

	/* Open PCM device. */
	snd_pcm_open(&handle, this->deviceName, this->direction, 0);

	/* 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_S16_LE);

	/* Two channels (stereo) */
	snd_pcm_hw_params_set_channels(handle, params, this->channels);

	// Set the sampling rate appropriately.
	snd_pcm_hw_params_set_rate_near(handle, params, &(this->samplingRate),
			&dir);

	/* Set period size to the given number of frames. */
	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);
	}
}
Ejemplo n.º 22
0
static snd_pcm_t * bg_alsa_open(const char * card,
                                gavl_audio_format_t * format,
                                snd_pcm_stream_t stream,
                                gavl_time_t buffer_time,
                                int * convert_4_3)
  {
  unsigned int i_tmp;
  int dir, err;
  snd_pcm_hw_params_t *hw_params = NULL;
  //  snd_pcm_sw_params_t *sw_params = NULL;
  snd_pcm_t *ret                 = NULL;
  
  snd_pcm_uframes_t buffer_size;
  snd_pcm_uframes_t period_size;
  
  snd_pcm_uframes_t period_size_min = 0; 
  snd_pcm_uframes_t period_size_max = 0; 
  snd_pcm_uframes_t buffer_size_min = 0;
  snd_pcm_uframes_t buffer_size_max = 0;
  /* We open in non blocking mode so our process won't hang if the card is
     busy */
  
  if((err = snd_pcm_open(&ret,
                         card,
                         stream,  // SND_PCM_STREAM_PLAYBACK SND_PCM_STREAM_CAPTURE
                         SND_PCM_NONBLOCK  //   SND_PCM_ASYNC
                         ) < 0))
    {
    ret = NULL;
    bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_open failed for device %s (%s)",
           card, snd_strerror(err));
    goto fail;
    }

  /* Now, set blocking mode */

  snd_pcm_nonblock(ret, 0);
  
  if(snd_pcm_hw_params_malloc(&hw_params) < 0)
    {
    bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_malloc failed");
    goto fail;
    }
  if(snd_pcm_hw_params_any(ret, hw_params) < 0)
    {
    bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_any failed");
    goto fail;
    }

  /* Interleave mode */
  
  if(snd_pcm_hw_params_set_access(ret, hw_params,
                                  SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
    {
    bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_access failed");
    goto fail;
    }
  else
    format->interleave_mode = GAVL_INTERLEAVE_ALL;
  
  /* Sample format */

  switch(format->sample_format)
    {
    case GAVL_SAMPLE_S8:
    case GAVL_SAMPLE_U8:
      if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S8) < 0)
        //  if(1)
          {
        /* Soundcard support no 8-bit, try 16 */
        if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0)
          {
          /* Hopeless */
          bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed");
          goto fail;
          }
        else
          format->sample_format = GAVL_SAMPLE_S16;
        }
        else
        format->sample_format = GAVL_SAMPLE_S8;
      break;
    case GAVL_SAMPLE_S16:
    case GAVL_SAMPLE_U16:
      if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0)
        {
        /* Hopeless */
        bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed");
        goto fail;
        }
      else
        format->sample_format = GAVL_SAMPLE_S16;
      break;
    case GAVL_SAMPLE_S32:
#ifndef WORDS_BIGENDIAN
      if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_LE) < 0)
#else
      if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_BE) < 0)
#endif
        {
        /* Soundcard supports no 32-bit, try 24
           (more probably supported but needs conversion) */
#ifndef WORDS_BIGENDIAN
        if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3LE) < 0)
#else
        if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3BE) < 0)
#endif
          {
          /* No 24 bit, try 16 */
          if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0)
            {
            /* Hopeless */
            bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed");
            goto fail;
            }
          else
            format->sample_format = GAVL_SAMPLE_S16;
          }
        else
          {
          format->sample_format = GAVL_SAMPLE_S32;
          if(convert_4_3)
            *convert_4_3 = 1;
          }
        }
      else
        format->sample_format = GAVL_SAMPLE_S32;
      break;
    case GAVL_SAMPLE_FLOAT:
    case GAVL_SAMPLE_DOUBLE:
      if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_FLOAT) < 0)
       {

#ifndef WORDS_BIGENDIAN
        if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_LE) < 0)
#else
        if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_BE) < 0)
#endif
          {
            /* Soundcard supports no 32-bit, try 24
               (more probably supported but needs conversion) */
#ifndef WORDS_BIGENDIAN
          if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3LE) < 0)
#else
          if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3BE) < 0)
#endif
            {
            /* No 24 bit, try 16 */
            if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0)
              {
              /* Hopeless */
              bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed");
              goto fail;
              }
            else
              format->sample_format = GAVL_SAMPLE_S16;
            }
          else
            {
            format->sample_format = GAVL_SAMPLE_S32;
            if(convert_4_3)
              *convert_4_3 = 1;
            }
          }
        else
          format->sample_format = GAVL_SAMPLE_S32;
       }
      else
        format->sample_format = GAVL_SAMPLE_FLOAT;
      break;
    case GAVL_SAMPLE_NONE:
      goto fail;
      break;
    }

  /* Channels */
  if(snd_pcm_hw_params_set_channels(ret, hw_params,
                                    format->num_channels) < 0)
    {
    if(format->num_channels == 1) /* Mono doesn't work, try stereo */
      {
      if(snd_pcm_hw_params_set_channels(ret, hw_params,
                                        2) < 0)
        {
        bg_log(BG_LOG_ERROR, LOG_DOMAIN,
               "snd_pcm_hw_params_set_channels failed (Format has %d channels)",
               format->num_channels);
        goto fail;
        }
      else
        {
        format->num_channels = 2;
        format->channel_locations[0] = GAVL_CHID_FRONT_LEFT;
        format->channel_locations[1] = GAVL_CHID_FRONT_RIGHT;
        }
      }
    else
      {
      bg_log(BG_LOG_ERROR, LOG_DOMAIN,
             "snd_pcm_hw_params_set_channels failed (Format has %d channels)",
             format->num_channels);
      goto fail;
      }
    }
  
  /* Switch off driver side resampling */
#if SND_LIB_VERSION >= 0x010009
  snd_pcm_hw_params_set_rate_resample(ret, hw_params, 0);
#endif
  
  /* Samplerate */
  i_tmp = format->samplerate;
  if(snd_pcm_hw_params_set_rate_near(ret, hw_params,
                                     &i_tmp,
                                     0) < 0)
    {
    bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_rate_near failed");
    goto fail;
    }
  if(format->samplerate != i_tmp)
    {
    bg_log(BG_LOG_INFO, LOG_DOMAIN,
           "Samplerate %d not supported by device %s, using %d",
           format->samplerate, card, i_tmp);

    }
  format->samplerate = i_tmp;
  
  dir = 0;

  /* Buffer size */

  snd_pcm_hw_params_get_buffer_size_min(hw_params, &buffer_size_min);
  snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size_max);
  dir=0;
  snd_pcm_hw_params_get_period_size_min(hw_params, &period_size_min,&dir);
  dir=0;
  snd_pcm_hw_params_get_period_size_max(hw_params, &period_size_max,&dir);
  
  buffer_size = gavl_time_to_samples(format->samplerate, buffer_time);

  
  if(buffer_size > buffer_size_max)
    buffer_size = buffer_size_max;
  if(buffer_size < buffer_size_min)
    buffer_size = buffer_size_min;

  period_size = buffer_size / 8;
  buffer_size = period_size * 8;

  dir = 0;
  if(snd_pcm_hw_params_set_period_size_near(ret, hw_params, &period_size, &dir) < 0)
    {
    bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_period_size failed");
    goto fail;
    }
  dir = 0;
  snd_pcm_hw_params_get_period_size(hw_params, &period_size, &dir);

  dir = 0;
  if(snd_pcm_hw_params_set_buffer_size_near(ret, hw_params, &buffer_size) < 0)
    {
    bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_buffer_size failed");
    goto fail;
    }
  
  snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size);

  
  format->samples_per_frame = period_size;
  
  /* Write params to card */
  if(snd_pcm_hw_params (ret, hw_params) < 0)
    {
    bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params failed");
    goto fail;
    }
  snd_pcm_hw_params_free(hw_params);
  
  gavl_set_channel_setup(format);
  //  gavl_audio_format_dump(format);
  
  return ret;
  fail:
  
  bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Alsa initialization failed");
  if(ret)
    snd_pcm_close(ret);
  if(hw_params)
    snd_pcm_hw_params_free(hw_params);
  return NULL;
  }
Ejemplo n.º 23
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

  // Make sure to not initialize too large to not cause underruns
  snd_pcm_uframes_t periodSizeMax = bufferSize / 3;
  if(snd_pcm_hw_params_set_period_size_max(m_pcm, hw_params_copy, &periodSizeMax, NULL) != 0)
  {
    snd_pcm_hw_params_copy(hw_params_copy, hw_params); // restore working copy
    CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Request: Failed to limit periodSize to %lu", periodSizeMax);
  }
  
  // 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;
}
Ejemplo n.º 24
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;
}
Ejemplo n.º 25
0
int main(int argc, char *argv[]) 
{
    int32_t dwLoopsToRecord;
    int32_t dwStatus;
    int32_t dwAudioBufferSize;
    snd_pcm_t *AlsaHandle;
    snd_pcm_hw_params_t *AlsaParams;
    uint32_t dwSamplingRate;
    int32_t dwDirection;
    snd_pcm_uframes_t AlsaFrames;
    int8_t *bAudioBuffer;
    uint32_t dwChannels;
    wave_t WavFile;
    
    /* confirm there are enough parameters */
    if(argc < 4)
    {
        printf("Usage: alsa_record <interface> <sampling_rate> <channels>");
        exit(1);
    }
    
    printf("Alsa Record Opening device: %s\n",argv[1]);
    
    /* Open PCM device for recording (capture). */
    dwStatus = snd_pcm_open(&AlsaHandle, argv[1],
                    SND_PCM_STREAM_CAPTURE, 0);
    if (dwStatus < 0) 
    {
        fprintf(stderr,"unable to open pcm device: %s\n",snd_strerror(dwStatus));
        exit(1);
    }

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

    /* Fill it in with default values. */
    snd_pcm_hw_params_any(AlsaHandle, AlsaParams);

    /* Set the desired hardware parameters. */

    /* Interleaved mode */
    snd_pcm_hw_params_set_access(AlsaHandle, AlsaParams,
                      SND_PCM_ACCESS_RW_INTERLEAVED);

    /* Signed 16-bit little-endian format */
    snd_pcm_hw_params_set_format(AlsaHandle, AlsaParams,
                              SND_PCM_FORMAT_S16_LE);

    /* Get the channels from the parameter */
    dwChannels = atoi(argv[3]);

    printf("Alsa Record Recording %d channels\n",dwChannels);    
    
    /* assign the channels for the wav file */     
    WavFile.wChannels = dwChannels;
    
    /* set channels to ALSA */	
    snd_pcm_hw_params_set_channels(AlsaHandle, AlsaParams, dwChannels);

    /* bits/second sampling rate */
    dwSamplingRate = atoi(argv[2]);
    
    printf("Alsa Record Sampling rate: %i\n", dwSamplingRate);

    /* Set the sampling rate for the wav file */
    WavFile.dwSampleRate = dwSamplingRate;

    /* Set the sampling rate to ASLA */
    snd_pcm_hw_params_set_rate_near(AlsaHandle, AlsaParams,
                                  &dwSamplingRate, &dwDirection);
    
    
    /* Set period size to 32 frames. */
    AlsaFrames = 32;
    snd_pcm_hw_params_set_period_size_near(AlsaHandle,
                              AlsaParams, &AlsaFrames, &dwDirection);

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

    /* Use a buffer large enough to hold one period */
    snd_pcm_hw_params_get_period_size(AlsaParams,
                                      &AlsaFrames, &dwDirection);
    /* 2 bytes/sample, 2 channels */	
    dwAudioBufferSize = AlsaFrames * 2 * dwChannels; 
    bAudioBuffer = (int8_t *) malloc(dwAudioBufferSize);

    /* We want to loop for 5 seconds */
    snd_pcm_hw_params_get_period_time(AlsaParams,
                                         &dwSamplingRate, &dwDirection);
    /* Will record 5 seconds, get the amount of frames required */
    dwLoopsToRecord = TIME_TO_RECORD_IN_US / dwSamplingRate;

    printf("SoundCard enabled and configured...\n");

    printf("Opening output file\n");
    
    /* Open the file and configure the wav header */
    WavFile.dwWaveFileDescriptor = open("audio_mic.wav", O_WRONLY|O_CREAT,S_IRUSR|S_IRGRP|S_IROTH);

    WavFile.dwSeconds = TIME_TO_RECORD_IN_S;

    WavBuilder_vfnSetHeader(&WavFile);

    printf("Recording\n");

    while (dwLoopsToRecord) 
    {
        dwLoopsToRecord--;
	
	/* Read an audio frame */
        dwStatus = snd_pcm_readi(AlsaHandle, bAudioBuffer, AlsaFrames);
        
        if (dwStatus == -EPIPE) 
        {
            /* EPIPE means overrun */
            fprintf(stderr, "overrun occurred\n");
            snd_pcm_prepare(AlsaHandle);
        } 
        else if (dwStatus < 0) 
        {
            fprintf(stderr,"error from read: %s\n",snd_strerror(dwStatus));
        } 
        else if (dwStatus != (int32_t)AlsaFrames) 
        {
            fprintf(stderr, "short read, read %d AlsaFrames\n", dwStatus);
        }

	/* Take the buffer and write it to the file */
        WavBuilder_vfnWriteData(&WavFile,bAudioBuffer, dwAudioBufferSize);
        
    }

    printf("Done\n");
    /* Once everything is done, close and release all resources */
    snd_pcm_drain(AlsaHandle);
    snd_pcm_close(AlsaHandle);
    close(WavFile.dwWaveFileDescriptor);
    free(bAudioBuffer);

  return 0;
}
Ejemplo n.º 26
0
eBool tfAlsa::openDevice(const eChar *device, eU32 freq, eU32 bits, eU32 channels)
{
	eInt err = 0;

	if (device == eNULL)
		return eFALSE;

	printf ("opening device '%s' for playback\n", device);

	if ((err = snd_pcm_open (&m_handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) 
	{
		fprintf (stderr, "cannot open audio device '%s' for playback(%s)\n", device, snd_strerror (err));
		return eFALSE;
	}

	snd_pcm_hw_params_t *hw_params;
	snd_pcm_format_t format;
	snd_pcm_uframes_t buffer_size = BUFFERSIZE;
	snd_pcm_uframes_t period_size = PERIODSIZE;

	printf("setting device to %i hz %i bits %i channels\n", freq, bits, channels);

	if (bits == 16)
		format = SND_PCM_FORMAT_S16_LE;
	else
		format = SND_PCM_FORMAT_S8;

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

	if ((err = snd_pcm_hw_params_any (m_handle, hw_params)) < 0) 
	{
		fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err));
		return false;
	}

	if ((err = snd_pcm_hw_params_set_access (m_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) 
	{
		fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err));
		return false;
	}

	if ((err = snd_pcm_hw_params_set_format (m_handle, hw_params, format)) < 0) 
	{
		fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err));
		return false;
	}

	if ((err = snd_pcm_hw_params_set_rate_near (m_handle, hw_params, (unsigned int *)&freq, 0)) < 0) 
	{
		fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err));
		return false;
	}

	if ((err = snd_pcm_hw_params_set_channels (m_handle, hw_params, channels)) < 0) 
	{
		fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err));
		return false;
	}

	if ((err = snd_pcm_hw_params_set_buffer_size_near (m_handle, hw_params, &buffer_size)) < 0) 
	{
		fprintf (stderr, "cannot set buffer size (%s)\n", snd_strerror (err));
		return false;
	}

	if ((err = snd_pcm_hw_params_set_period_size_near (m_handle, hw_params, &period_size, NULL)) < 0) 
	{
		fprintf (stderr, "cannot set period size (%s)\n", snd_strerror (err));
		return false;
	}

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

	snd_pcm_hw_params_free (hw_params);

	return eTRUE;
}
Ejemplo n.º 27
0
int main() {
    long loops;
    int rc;
    int size;
    snd_pcm_t *handle;
    snd_pcm_hw_params_t *params;
    unsigned int val;
    int dir;
    snd_pcm_uframes_t frames;
    char *buffer;

    /* 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_S16_LE);

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

    /* 44100 bits/second sampling rate (CD quality) */
    val = 44100;
    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 buffer large enough to hold one period */
    snd_pcm_hw_params_get_period_size(params, &frames, &dir);
    size = frames * 4; /* 2 bytes/sample, 2 channels */
    buffer = (char *) malloc(size);

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

    while (loops > 0) {
        loops--;
        rc = snd_pcm_readi(handle, buffer, frames);
        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, buffer, size);
        if (rc != size)
            fprintf(stderr, "short write: wrote %d bytes\n", rc);
    }

    snd_pcm_drain(handle);
    snd_pcm_close(handle);
    free(buffer);

    return 0;
}
Ejemplo n.º 28
0
snd_pcm_t * open_capture (char *name,unsigned int set_rate, int channel, int bit)
{

    snd_pcm_hw_params_t* params;
    snd_pcm_format_t format;
    int result;
    snd_pcm_uframes_t tmp_buf_size;
    snd_pcm_uframes_t tmp_period_size;

    snd_pcm_t *ca_pcm;

    /* Open PCM for capture */

    result = snd_pcm_open (&ca_pcm,name,SND_PCM_STREAM_CAPTURE,0);
    if (result < 0)
    	printf("error \n");


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

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

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

    /* Set format */


    format = SND_PCM_FORMAT_S16_LE;
    	switch(bit/8){
    		case 1:format=SND_PCM_FORMAT_U8;
    				break ;
    		case 3:format=SND_PCM_FORMAT_S24_LE;
    				break ;
    	}

    snd_pcm_hw_params_set_format (ca_pcm, params, format);

    /* Set number of channels */

    snd_pcm_hw_params_set_channels (ca_pcm, params,channel);

    /* Set clock rate */

    snd_pcm_hw_params_set_rate_near (ca_pcm, params, &set_rate, NULL);


    /* Set the sound device buffer size and latency */

	tmp_buf_size = 4096;//(set_rate / 1000) * input_latency_ms;
	//设置缓冲区
	snd_pcm_hw_params_set_buffer_size_near (ca_pcm, params,
						&tmp_buf_size);

	input_latency_ms = tmp_buf_size / (set_rate / 1000);

    /* Set period size to samples_per_frame frames. */
    //ca_frames = (snd_pcm_uframes_t) samples_per_frame /channel;
	
    tmp_period_size = tmp_buf_size/8;//ca_frames;
	//设置周期
    snd_pcm_hw_params_set_period_size_near (ca_pcm, params,
					    &tmp_period_size, NULL);


    /* Set our buffer */
    ca_buf_size = tmp_period_size/2;//ca_frames * channel * (bits_per_sample/8);

    printf("ca_buf_size is %d\n",ca_buf_size);

    ca_buf = (u_char *)malloc(ca_buf_size);


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

    return ca_pcm;

}
static int drvHostALSAAudioOpen(bool fIn,
                                PALSAAUDIOSTREAMCFG pCfgReq,
                                PALSAAUDIOSTREAMCFG pCfgObt,
                                snd_pcm_t **pphPCM)
{
    snd_pcm_t *phPCM = NULL;
    int rc;

    unsigned int cChannels = pCfgReq->nchannels;
    unsigned int uFreq = pCfgReq->freq;
    snd_pcm_uframes_t obt_buffer_size;

    do
    {
        const char *pszDev = fIn ? s_ALSAConf.pcm_name_in : s_ALSAConf.pcm_name_out;
        if (!pszDev)
        {
            LogRel(("ALSA: Invalid or no %s device name set\n",
                    fIn ? "input" : "output"));
            rc = VERR_INVALID_PARAMETER;
            break;
        }

        int err = snd_pcm_open(&phPCM, pszDev,
                               fIn ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
                               SND_PCM_NONBLOCK);
        if (err < 0)
        {
            LogRel(("ALSA: Failed to open \"%s\" as %s: %s\n", pszDev,
                    fIn ? "ADC" : "DAC", snd_strerror(err)));
            rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
            break;
        }

        snd_pcm_hw_params_t *pHWParms;
        snd_pcm_hw_params_alloca(&pHWParms); /** @todo Check for successful allocation? */
        err = snd_pcm_hw_params_any(phPCM, pHWParms);
        if (err < 0)
        {
            LogRel(("ALSA: Failed to initialize hardware parameters: %s\n",
                    snd_strerror(err)));
            rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
            break;
        }

        err = snd_pcm_hw_params_set_access(phPCM, pHWParms,
                                           SND_PCM_ACCESS_RW_INTERLEAVED);
        if (err < 0)
        {
            LogRel(("ALSA: Failed to set access type: %s\n", snd_strerror(err)));
            rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
            break;
        }

        err = snd_pcm_hw_params_set_format(phPCM, pHWParms, pCfgReq->fmt);
        if (err < 0)
        {
            LogRel(("ALSA: Failed to set audio format to %d: %s\n",
                    pCfgReq->fmt, snd_strerror(err)));
            rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
            break;
        }

        err = snd_pcm_hw_params_set_rate_near(phPCM, pHWParms, &uFreq, 0);
        if (err < 0)
        {
            LogRel(("ALSA: Failed to set frequency to %dHz: %s\n",
                    pCfgReq->freq, snd_strerror(err)));
            rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
            break;
        }

        err = snd_pcm_hw_params_set_channels_near(phPCM, pHWParms, &cChannels);
        if (err < 0)
        {
            LogRel(("ALSA: Failed to set number of channels to %d\n", pCfgReq->nchannels));
            rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
            break;
        }

        if (   cChannels != 1
            && cChannels != 2)
        {
            LogRel(("ALSA: Number of audio channels (%u) not supported\n", cChannels));
            rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
            break;
        }

        unsigned int period_size = pCfgReq->period_size;
        unsigned int buffer_size = pCfgReq->buffer_size;

        if (   !((fIn && s_ALSAConf.size_in_usec_in)
            ||  (!fIn && s_ALSAConf.size_in_usec_out)))
        {
            if (!buffer_size)
            {
                buffer_size = DEFAULT_BUFFER_SIZE;
                period_size = DEFAULT_PERIOD_SIZE;
            }
        }

        if (buffer_size)
        {
            if (   ( fIn && s_ALSAConf.size_in_usec_in)
                || (!fIn && s_ALSAConf.size_in_usec_out))
            {
                if (period_size)
                {
                    err = snd_pcm_hw_params_set_period_time_near(phPCM, pHWParms,
                                                                 &period_size, 0);
                    if (err < 0)
                    {
                        LogRel(("ALSA: Failed to set period time %d\n", pCfgReq->period_size));
                        rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
                        break;
                    }
                }

                err = snd_pcm_hw_params_set_buffer_time_near(phPCM, pHWParms,
                                                             &buffer_size, 0);
                if (err < 0)
                {
                    LogRel(("ALSA: Failed to set buffer time %d\n", pCfgReq->buffer_size));
                    rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
                    break;
                }
            }
            else
            {
                snd_pcm_uframes_t period_size_f = (snd_pcm_uframes_t)period_size;
                snd_pcm_uframes_t buffer_size_f = (snd_pcm_uframes_t)buffer_size;

                snd_pcm_uframes_t minval;

                if (period_size_f)
                {
                    minval = period_size_f;

                    int dir = 0;
                    err = snd_pcm_hw_params_get_period_size_min(pHWParms,
                                                                &minval, &dir);
                    if (err < 0)
                    {
                        LogRel(("ALSA: Could not determine minimal period size\n"));
                        rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
                        break;
                    }
                    else
                    {
                        LogFunc(("Minimal period size is: %ld\n", minval));
                        if (period_size_f < minval)
                        {
                            if (   ( fIn && s_ALSAConf.period_size_in_overriden)
                                || (!fIn && s_ALSAConf.period_size_out_overriden))
                            {
                                LogFunc(("Period size %RU32 is less than minimal period size %RU32\n",
                                         period_size_f, minval));
                            }

                            period_size_f = minval;
                        }
                    }

                    err = snd_pcm_hw_params_set_period_size_near(phPCM, pHWParms,
                                                                 &period_size_f, 0);
                    LogFunc(("Period size is: %RU32\n", period_size_f));
                    if (err < 0)
                    {
                        LogRel(("ALSA: Failed to set period size %d (%s)\n",
                                period_size_f, snd_strerror(err)));
                        rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
                        break;
                    }
                }

                /* Calculate default buffer size here since it might have been changed
                 * in the _near functions */
                buffer_size_f = 4 * period_size_f;

                minval = buffer_size_f;
                err = snd_pcm_hw_params_get_buffer_size_min(pHWParms, &minval);
                if (err < 0)
                {
                    LogRel(("ALSA: Could not retrieve minimal buffer size\n"));
                    rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
                    break;
                }
                else
                {
                    LogFunc(("Minimal buffer size is: %RU32\n", minval));
                    if (buffer_size_f < minval)
                    {
                        if (   ( fIn && s_ALSAConf.buffer_size_in_overriden)
                            || (!fIn && s_ALSAConf.buffer_size_out_overriden))
                        {
                            LogFunc(("Buffer size %RU32 is less than minimal buffer size %RU32\n",
                                     buffer_size_f, minval));
                        }

                        buffer_size_f = minval;
                    }
                }

                err = snd_pcm_hw_params_set_buffer_size_near(phPCM,
                                                             pHWParms, &buffer_size_f);
                LogFunc(("Buffer size is: %RU32\n", buffer_size_f));
                if (err < 0)
                {
                    LogRel(("ALSA: Failed to set buffer size %d: %s\n",
                            buffer_size_f, snd_strerror(err)));
                    rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
                    break;
                }
            }
        }
        else
            LogFunc(("Warning: Buffer size is not set\n"));

        err = snd_pcm_hw_params(phPCM, pHWParms);
        if (err < 0)
        {
            LogRel(("ALSA: Failed to apply audio parameters\n"));
            rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
            break;
        }

        err = snd_pcm_hw_params_get_buffer_size(pHWParms, &obt_buffer_size);
        if (err < 0)
        {
            LogRel(("ALSA: Failed to get buffer size\n"));
            rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
            break;
        }

        snd_pcm_uframes_t obt_period_size;
        int dir = 0;
        err = snd_pcm_hw_params_get_period_size(pHWParms, &obt_period_size, &dir);
        if (err < 0)
        {
            LogRel(("ALSA: Failed to get period size\n"));
            rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
            break;
        }

        LogFunc(("Freq=%dHz, period size=%RU32, buffer size=%RU32\n",
                 pCfgReq->freq, obt_period_size, obt_buffer_size));

        err = snd_pcm_prepare(phPCM);
        if (err < 0)
        {
            LogRel(("ALSA: Could not prepare hPCM %p\n", (void *)phPCM));
            rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
            break;
        }

        if (   !fIn
            && s_ALSAConf.threshold)
        {
            unsigned uShift;
            rc = drvHostALSAAudioALSAGetShift(pCfgReq->fmt, &uShift);
            if (RT_SUCCESS(rc))
            {
                int bytes_per_sec = uFreq
                    << (cChannels == 2)
                    << uShift;

                snd_pcm_uframes_t threshold
                    = (s_ALSAConf.threshold * bytes_per_sec) / 1000;

                rc = drvHostALSAAudioSetThreshold(phPCM, threshold);
            }
        }
        else
            rc = VINF_SUCCESS;
    }
    while (0);

    if (RT_SUCCESS(rc))
    {
        pCfgObt->fmt       = pCfgReq->fmt;
        pCfgObt->nchannels = cChannels;
        pCfgObt->freq      = uFreq;
        pCfgObt->samples   = obt_buffer_size;

        *pphPCM = phPCM;
    }
    else
        drvHostALSAAudioClose(&phPCM);

    LogFlowFuncLeaveRC(rc);
    return rc;
}
Ejemplo n.º 30
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);
}