示例#1
0
void SoundPlayer::main()
{
  BH_TRACE_INIT("SoundPlayer");
  unsigned i;
  for(i = 0; i < retries; ++i)
  {
    if(snd_pcm_open(&handle, "hw:0", SND_PCM_STREAM_PLAYBACK, 0) >= 0)
      break;
    Thread::sleep(retryDelay);
  }
  ASSERT(i < retries);
  snd_pcm_hw_params_t* params;
  VERIFY(!snd_pcm_hw_params_malloc(&params));
  VERIFY(!snd_pcm_hw_params_any(handle, params));
  VERIFY(!snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED));
  VERIFY(!snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE));
  VERIFY(!snd_pcm_hw_params_set_rate_near(handle, params, &sampleRate, 0));;
  VERIFY(!snd_pcm_hw_params_set_channels(handle, params, 2));
  VERIFY(!snd_pcm_hw_params(handle, params));
  VERIFY(!snd_pcm_hw_params_get_period_size(params, &periodSize, 0));
  snd_pcm_hw_params_free(params);

  while(isRunning() && !closing)
  {
    flush();
    VERIFY(sem.wait());
  }
  VERIFY(!snd_pcm_close(handle));
}
示例#2
0
static void alsa_log(snd_pcm_hw_params_t* hw_params, snd_pcm_sw_params_t* sw_params)
{
	unsigned period_time;
	snd_pcm_uframes_t period_size;
	unsigned period_count;
	unsigned buffer_time;
	snd_pcm_uframes_t buffer_size;
	unsigned tick_time;

	snd_pcm_uframes_t xfer_align;

	snd_pcm_hw_params_get_period_time(hw_params, &period_time, 0);
	snd_pcm_hw_params_get_period_size(hw_params, &period_size, 0);
	snd_pcm_hw_params_get_periods(hw_params, &period_count, 0);
	snd_pcm_hw_params_get_buffer_time(hw_params, &buffer_time, 0);
	snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size);
	snd_pcm_hw_params_get_tick_time(hw_params, &tick_time, 0);

	log_std(("sound:alsa: hw period_time %g [us], period_size %d, periods %d, buffer_time %g [us], buffer_size %d, tick_time %g [us]\n",
		(double)(period_time / 1000000.0), (unsigned)period_size, (unsigned)period_count, (double)(buffer_time / 1000000.0), (unsigned)buffer_size, (double)(tick_time / 1000000.0)
	));

	snd_pcm_sw_params_get_xfer_align(sw_params, &xfer_align);
	log_std(("sound:alsa: sw xfer_align %d\n",
		(unsigned)xfer_align
	));
}
示例#3
0
文件: alsa.c 项目: alyx/metrodwarf
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);
}
示例#4
0
文件: waveout.c 项目: mikekap/wine
/**************************************************************************
 * 				wodPlayer_NotifyCompletions	[internal]
 *
 * Notifies and remove from queue all wavehdrs which have been played to
 * the speaker (ie. they have cleared the ALSA buffer).  If force is true,
 * we notify all wavehdrs and remove them all from the queue even if they
 * are unplayed or part of a loop.
 */
static DWORD wodPlayer_NotifyCompletions(WINE_WAVEDEV* wwo, BOOL force)
{
    LPWAVEHDR		lpWaveHdr;

    /* Start from lpQueuePtr and keep notifying until:
     * - we hit an unwritten wavehdr
     * - we hit the beginning of a running loop
     * - we hit a wavehdr which hasn't finished playing
     */
    for (;;)
    {
        lpWaveHdr = wwo->lpQueuePtr;
        if (!lpWaveHdr) {TRACE("Empty queue\n"); break;}
        if (!force)
        {
            snd_pcm_uframes_t frames;
            snd_pcm_hw_params_get_period_size(wwo->hw_params, &frames, NULL);

            if (lpWaveHdr == wwo->lpPlayPtr) {TRACE("play %p\n", lpWaveHdr); break;}
            if (lpWaveHdr == wwo->lpLoopPtr) {TRACE("loop %p\n", lpWaveHdr); break;}
            if (lpWaveHdr->reserved > wwo->dwPlayedTotal + frames) {TRACE("still playing %p (%lu/%u)\n", lpWaveHdr, lpWaveHdr->reserved, wwo->dwPlayedTotal);break;}
        }
        wwo->dwPlayedTotal += lpWaveHdr->reserved - wwo->dwPlayedTotal;
	wwo->lpQueuePtr = lpWaveHdr->lpNext;

	lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
	lpWaveHdr->dwFlags |= WHDR_DONE;

	wodNotifyClient(wwo, WOM_DONE, (DWORD_PTR)lpWaveHdr, 0);
    }
    return  (lpWaveHdr && lpWaveHdr != wwo->lpPlayPtr && lpWaveHdr != wwo->lpLoopPtr) ?
        wodPlayer_NotifyWait(wwo, lpWaveHdr) : INFINITE;
}
示例#5
0
void initsound(int samplerate, int channels)
{
    
    int dir, pcmrc;


    /* Open the PCM device in playback mode */
    snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0);

    /* Allocate parameters object and fill it with default values*/
    snd_pcm_hw_params_alloca(&params);
    snd_pcm_hw_params_any(pcm_handle, params);
    /* Set parameters */
    snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE);
    snd_pcm_hw_params_set_channels(pcm_handle, params, channels);
    snd_pcm_hw_params_set_rate(pcm_handle, params, samplerate, 0);

    /* Write parameters */
    snd_pcm_hw_params(pcm_handle, params);


	
    /* Allocate buffer to hold single period */
    snd_pcm_hw_params_get_period_size(params, &frames, &dir);
    buf = malloc(frames * channels * 2 * BUFFER_NUM);
	
}
示例#6
0
/**
 * This method will determine, based upon the size of each frame and the number of frames between interrupts the required size of the buffer that is to store the data.
 * @return
 */
int AudioInterface::getRequiredBufferSize() {
	int dir;
	int size;
	snd_pcm_hw_params_get_period_size(params, &frames, &dir);
	size = frames * this->channels * 2; /* 2 bytes/sample */
    std::cout << "Get re: " << channels << ":" << frames << std::endl;
	return size;
}
示例#7
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;
}
示例#8
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这里用不到

}
示例#9
0
static
int set_hwparams(snd_pcm_t *handle,
                 snd_pcm_hw_params_t *params,
                 snd_pcm_access_t access)
{
    int err, dir;

    /* choose all parameters */
    err = snd_pcm_hw_params_any(handle,params);
    if (err < 0) {
        printf("Access type not available for playback: %s\n", snd_strerror(err));
        return err;
    }
    /* set the sample format */
    err = snd_pcm_hw_params_set_format(handle, params, alsa_format);
    if (err < 0) {
        printf("Sample format not available for playback: %s\n", snd_strerror(err));
        return err;
    }
    /* set the count of channels */
    err = snd_pcm_hw_params_set_channels(handle, params, channels);
    if (err < 0) {
        printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err));
        return err;
    }
    /* set the stream rate */
    err = snd_pcm_hw_params_set_rate_near(handle, params, rate, 0);
    if (err < 0) {
        printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
        return err;
    }
    if (err != rate) {
        printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
        return -EINVAL;
    }
    /* set buffer time */
    err = snd_pcm_hw_params_set_buffer_time_near(handle, params, buffer_time, &dir);
    if (err < 0) {
        printf("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
        return err;
    }
    buffer_size = snd_pcm_hw_params_get_buffer_size(params);
    /* set period time */
    err = snd_pcm_hw_params_set_period_time_near(handle, params, period_time, &dir);
    if (err < 0) {
        printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
        return err;
    }
    period_size = snd_pcm_hw_params_get_period_size(params, &dir);
    /* write the parameters to device */
    err = snd_pcm_hw_params(handle, params);
    if (err < 0) {
        printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
        return err;
    }
    return 0;
}
示例#10
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;
}
示例#11
0
文件: newPlayer1.c 项目: cty222/Note
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);
	
}
示例#12
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); 
}
示例#13
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);
}
示例#14
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));


}
示例#15
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;
}
示例#16
0
文件: alsa.c 项目: giuseppe/shpotify
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;
}
示例#17
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();
}
示例#18
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;
}
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;
}
示例#20
0
int
snd_send(FILE * fp, size_t n)
{
    snd_pcm_format_t format;
    unsigned int    nchannels;
    snd_pcm_uframes_t period;
    snd_pcm_hw_params_t *params;
    snd_pcm_hw_params_alloca(&params);
    snd_pcm_hw_params_current(pcm, params);
    snd_pcm_hw_params_get_format(params, &format);
    snd_pcm_hw_params_get_channels(params, &nchannels);
    snd_pcm_hw_params_get_period_size(params, &period, 0);
    int             framesize =
        snd_pcm_format_width(format) / 8 * nchannels;
    unsigned char   buf[period * framesize * 128];
    size_t          l;
    while (n > sizeof(buf)) {
        if ((l = fread(buf, 1, sizeof(buf), fp))) {
            switch (snd_pcm_writei(pcm, buf, l / framesize)) {
            case -EBADF:
                return -1;
            case -EPIPE:
#ifndef NDEBUG
                snd_pcm_recover(pcm, -EPIPE, 0);
#else
                snd_pcm_prepare(pcm);
#endif
            }
        } else
            goto EOS;
        n -= l;
    }
    if ((l = fread(buf, 1, n, fp)))
        snd_pcm_writei(pcm, buf, l / framesize);
    if (l < n)
      EOS:if (ftell(fp) > 0)
            eputs("Unexpected end of stream");
    return snd_pcm_drain(pcm);
}
示例#21
0
    void alsa_print_info(snd_pcm_t * handle, snd_pcm_hw_params_t * hwp) {
        printf("device [%s] opened with\n",
               snd_pcm_name(handle));
        printf("\tstate=%s\n",
               snd_pcm_state_name(snd_pcm_state(handle)));
        unsigned int val, val2;
        snd_pcm_hw_params_get_access(hwp,
                                     (snd_pcm_access_t *) &val);
        printf("\taccess_type=%s\n",
               snd_pcm_access_name((snd_pcm_access_t)val));

        snd_pcm_hw_params_get_format(hwp, (snd_pcm_format_t *) &val);
        printf("\tformat=%s\n",
               snd_pcm_format_name((snd_pcm_format_t) val)
               );

        snd_pcm_hw_params_get_channels(hwp, &val);
        printf("\tchannels=%d\n", val);

        snd_pcm_hw_params_get_rate(hwp, &val, (int *) &val2);
        printf("\trate=%d fps\n", val);

        snd_pcm_hw_params_get_period_time(hwp,
                                          &val, (int *) &val2);
        printf("\tperiod_time=%d us\n", val);

        snd_pcm_uframes_t frames;
        snd_pcm_hw_params_get_period_size(hwp,
                                          &frames, (int *) &val2);
        printf("\tperiod_size=%d frames\n", (int)frames);

        snd_pcm_hw_params_get_buffer_size(hwp,
                                          (snd_pcm_uframes_t *) &val);
        printf("\tbuffer_size=%d frames\n", val);

        snd_pcm_hw_params_get_periods(hwp, &val, (int *) &val2);
        printf("\tperiods_per_buffer=%d periods\n", val);
    }
示例#22
0
void sound_dev_prepare(const char *device, struct sound_device_t *dev, unsigned int sample_rate, unsigned int channels){
    int rc;
    rc = snd_pcm_open(&(*dev).handle, device, SND_PCM_STREAM_PLAYBACK, 0);
    if (rc < 0){
        exception(snd_strerror(rc),BAD_PCM_DEV);
    }
    snd_pcm_hw_params_alloca(&(*dev).params);
    snd_pcm_hw_params_any((*dev).handle, (*dev).params);
    snd_pcm_hw_params_set_access((*dev).handle, (*dev).params, SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_hw_params_set_format((*dev).handle, (*dev).params, SND_PCM_FORMAT_S16_LE);
    snd_pcm_hw_params_set_channels((*dev).handle, (*dev).params, channels);
    snd_pcm_hw_params_set_rate_near((*dev).handle, (*dev).params, &sample_rate, &(*dev).dir);
    rc = snd_pcm_hw_params((*dev).handle, (*dev).params);
    if (rc < 0){
        exception(snd_strerror(rc), BAD_HW_PARAMS);
    }
    snd_pcm_hw_params_get_period_size((*dev).params, &(*dev).frames, &(*dev).dir);
    (*dev).size = (*dev).frames * 4;
    snd_pcm_hw_params_get_period_time((*dev).params, &(*dev).val, &(*dev).dir);
    (*dev).loops = TIME / (*dev).val;
    (*dev).buff_size_bytes = (*dev).size * (*dev).loops;
    (*dev).buff_size_frames = (*dev).frames * (*dev).loops;
}
示例#23
0
int set_pcm_play(FILE *fp)
{
	int rc;
	int ret;
	int size;
	snd_pcm_t* handle; //PCI设备句柄
	snd_pcm_hw_params_t* params;//硬件信息和PCM流配置
	unsigned int val;
	int dir=0;
	snd_pcm_uframes_t frames;
	char *buffer;
	int channels=wav_header.wChannels;
	int frequency=wav_header.nSamplesPersec;
	int bit=wav_header.wBitsPerSample;
	int datablock=wav_header.wBlockAlign;
	unsigned char ch[100]; //用来存储wav文件的头信息

	rc=snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
	if(rc<0)
	{
		perror("\nopen PCM device failed:");
		exit(1);
	}

	snd_pcm_hw_params_alloca(&params); //分配params结构体
	if(rc<0)
	{
		perror("\nsnd_pcm_hw_params_alloca:");
		exit(1);
	}
	rc=snd_pcm_hw_params_any(handle, params);//初始化params
	if(rc<0)
	{
		perror("\nsnd_pcm_hw_params_any:");
		exit(1);
	}
	rc=snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); //初始化访问权限
	if(rc<0)
	{
		perror("\nsed_pcm_hw_set_access:");
		exit(1);

	}

	//采样位数
	switch(bit/8)
	{
		case 1:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8);
		       break ;
		case 2:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
		       break ;
		case 3:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S24_LE);
		       break ;

	}
	rc=snd_pcm_hw_params_set_channels(handle, params, channels); //设置声道,1表示单声>道,2表示立体声
	if(rc<0)
	{
		perror("\nsnd_pcm_hw_params_set_channels:");
		exit(1);
	}
	val = frequency;
	rc=snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); //设置>频率
	if(rc<0)
	{
		perror("\nsnd_pcm_hw_params_set_rate_near:");
		exit(1);
	}

	rc = snd_pcm_hw_params(handle, params);
	if(rc<0)
	{
		perror("\nsnd_pcm_hw_params: ");
		exit(1);
	}

	rc=snd_pcm_hw_params_get_period_size(params, &frames, &dir); /*获取周期长度*/
	if(rc<0)
	{
		perror("\nsnd_pcm_hw_params_get_period_size:");
		exit(1);
	}

	size = frames * datablock; /*4 代表数据快长度*/

	buffer =(char*)malloc(size);
	fseek(fp,58,SEEK_SET); //定位歌曲到数据区

	while (1)
	{
		memset(buffer,0,sizeof(buffer));
		ret = fread(buffer, 1, size, fp);
		if(ret == 0)
		{
			printf("歌曲写入结束\n");
			break;
		}
		else if (ret != size)
		{
		}

		// 写音频数据到PCM设备 
		while(ret = snd_pcm_writei(handle, buffer, frames)<0)
		{
			usleep(2000); 
			if (ret == -EPIPE)
			{
				/* EPIPE means underrun */
				fprintf(stderr, "underrun occurred\n");
				//完成硬件参数设置,使设备准备好 
				snd_pcm_prepare(handle);
			}
			else if (ret < 0)
			{
				fprintf(stderr, "error from writei: %s\n", snd_strerror(ret));
			}
		}
	}

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

	return 0;
}
示例#24
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;
}
示例#25
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;
  }
示例#26
0
文件: alsa.c 项目: sailfish009/vlc
static int Open (vlc_object_t *obj)
{
    demux_t *demux = (demux_t *)obj;
    demux_sys_t *sys = vlc_obj_malloc(obj, sizeof (*sys));
    if (unlikely(sys == NULL))
        return VLC_ENOMEM;

    /* Open the device */
    const char *device = demux->psz_location;
    if (device == NULL || !device[0])
        device = "default";

    const int mode = SND_PCM_NONBLOCK
                 /*| SND_PCM_NO_AUTO_RESAMPLE*/
                   | SND_PCM_NO_AUTO_CHANNELS
                 /*| SND_PCM_NO_AUTO_FORMAT*/;
    snd_pcm_t *pcm;
    int val = snd_pcm_open (&pcm, device, SND_PCM_STREAM_CAPTURE, mode);
    if (val != 0)
    {
        msg_Err (demux, "cannot open ALSA device \"%s\": %s", device,
                 snd_strerror (val));
        return VLC_EGENERIC;
    }
    sys->pcm = pcm;
    msg_Dbg (demux, "using ALSA device: %s", device);
    DumpDevice (VLC_OBJECT(demux), pcm);

    /* Negotiate capture parameters */
    snd_pcm_hw_params_t *hw;
    es_format_t fmt;
    unsigned param;
    int dir;

    snd_pcm_hw_params_alloca (&hw);
    snd_pcm_hw_params_any (pcm, hw);
    Dump (demux, "initial hardware setup:\n", snd_pcm_hw_params_dump, hw);

    val = snd_pcm_hw_params_set_rate_resample (pcm, hw, 0);
    if (val)
    {
        msg_Err (demux, "cannot disable resampling: %s", snd_strerror (val));
        goto error;
    }

    val = snd_pcm_hw_params_set_access (pcm, hw,
                                        SND_PCM_ACCESS_RW_INTERLEAVED);
    if (val)
    {
        msg_Err (demux, "cannot set access mode: %s", snd_strerror (val));
        goto error;
    }

    snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
    for (size_t i = 0; i < sizeof (choices) / sizeof (choices[0]); i++)
        if (snd_pcm_hw_params_test_format (pcm, hw, choices[i]) == 0)
        {
            val = snd_pcm_hw_params_set_format (pcm, hw, choices[i]);
            if (val)
            {
                msg_Err (demux, "cannot set sample format: %s",
                         snd_strerror (val));
                goto error;
            }
            format = choices[i];
            break;
        }

    if (format == SND_PCM_FORMAT_UNKNOWN)
    {
        msg_Err (demux, "no supported sample format");
        goto error;
    }

    assert ((size_t)format < (sizeof (formats) / sizeof (formats[0])));
    es_format_Init (&fmt, AUDIO_ES, formats[format]);
    fmt.audio.i_format = fmt.i_codec;

    param = 1 + var_InheritBool (demux, "alsa-stereo");
    val = snd_pcm_hw_params_set_channels_max (pcm, hw, &param);
    if (val)
    {
        msg_Err (demux, "cannot restrict channels count: %s",
                 snd_strerror (val));
        goto error;
    }
    val = snd_pcm_hw_params_set_channels_last (pcm, hw, &param);
    if (val)
    {
        msg_Err (demux, "cannot set channels count: %s", snd_strerror (val));
        goto error;
    }
    assert (param > 0);
    assert (param < (sizeof (channel_maps) / sizeof (channel_maps[0])));
    fmt.audio.i_channels = param;
    fmt.audio.i_physical_channels = channel_maps[param - 1];

    param = var_InheritInteger (demux, "alsa-samplerate");
    val = snd_pcm_hw_params_set_rate_max (pcm, hw, &param, NULL);
    if (val)
    {
        msg_Err (demux, "cannot restrict rate to %u Hz or less: %s", 192000,
                 snd_strerror (val));
        goto error;
    }
    val = snd_pcm_hw_params_set_rate_last (pcm, hw, &param, &dir);
    if (val)
    {
        msg_Err (demux, "cannot set sample rate: %s", snd_strerror (val));
        goto error;
    }
    if (dir)
        msg_Warn (demux, "sample rate is not integral");
    fmt.audio.i_rate = param;
    sys->rate = param;

    sys->start = mdate ();
    sys->caching = INT64_C(1000) * var_InheritInteger (demux, "live-caching");
    param = sys->caching;
    val = snd_pcm_hw_params_set_buffer_time_near (pcm, hw, &param, NULL);
    if (val)
    {
        msg_Err (demux, "cannot set buffer duration: %s", snd_strerror (val));
        goto error;
    }

    param /= 4;
    val = snd_pcm_hw_params_set_period_time_near (pcm, hw, &param, NULL);
    if (val)
    {
        msg_Err (demux, "cannot set period: %s", snd_strerror (val));
        goto error;
    }

    val = snd_pcm_hw_params_get_period_size (hw, &sys->period_size, &dir);
    if (val)
    {
        msg_Err (demux, "cannot get period size: %s", snd_strerror (val));
        goto error;
    }
    if (dir > 0)
        sys->period_size++;

    /* Commit hardware parameters */
    val = snd_pcm_hw_params (pcm, hw);
    if (val)
    {
        msg_Err (demux, "cannot commit hardware parameters: %s",
                 snd_strerror (val));
        goto error;
    }
    Dump (demux, "final HW setup:\n", snd_pcm_hw_params_dump, hw);

    /* Kick recording */
    aout_FormatPrepare (&fmt.audio);
    sys->es = es_out_Add (demux->out, &fmt);
    demux->p_sys = sys;

    if (vlc_clone (&sys->thread, Thread, demux, VLC_THREAD_PRIORITY_INPUT))
    {
        es_out_Del (demux->out, sys->es);
        goto error;
    }

    demux->pf_demux = NULL;
    demux->pf_control = Control;
    return VLC_SUCCESS;
error:
    snd_pcm_close (pcm);
    return VLC_EGENERIC;
}
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;
}
示例#28
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;
}
示例#29
0
static void *alsa_thread_init(const char *device,
      unsigned rate, unsigned latency)
{
   snd_pcm_uframes_t buffer_size;
   snd_pcm_format_t format;
   snd_pcm_hw_params_t *params    = NULL;
   snd_pcm_sw_params_t *sw_params = NULL;
   const char *alsa_dev           = device ? device : "default";
   unsigned latency_usec          = latency * 1000 / 2;
   unsigned channels              = 2;
   unsigned periods               = 4;
   alsa_thread_t            *alsa = (alsa_thread_t*)
      calloc(1, sizeof(alsa_thread_t));

   if (!alsa)
      return NULL;

   TRY_ALSA(snd_pcm_open(&alsa->pcm, alsa_dev, SND_PCM_STREAM_PLAYBACK, 0));

   TRY_ALSA(snd_pcm_hw_params_malloc(&params));
   alsa->has_float = alsathread_find_float_format(alsa->pcm, params);
   format = alsa->has_float ? SND_PCM_FORMAT_FLOAT : SND_PCM_FORMAT_S16;

   TRY_ALSA(snd_pcm_hw_params_any(alsa->pcm, params));
   TRY_ALSA(snd_pcm_hw_params_set_access(
            alsa->pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED));
   TRY_ALSA(snd_pcm_hw_params_set_format(alsa->pcm, params, format));
   TRY_ALSA(snd_pcm_hw_params_set_channels(alsa->pcm, params, channels));
   TRY_ALSA(snd_pcm_hw_params_set_rate(alsa->pcm, params, rate, 0));

   TRY_ALSA(snd_pcm_hw_params_set_buffer_time_near(
            alsa->pcm, params, &latency_usec, NULL));
   TRY_ALSA(snd_pcm_hw_params_set_periods_near(
            alsa->pcm, params, &periods, NULL));

   TRY_ALSA(snd_pcm_hw_params(alsa->pcm, params));

   /* Shouldn't have to bother with this, 
    * but some drivers are apparently broken. */
   if (snd_pcm_hw_params_get_period_size(params, &alsa->period_frames, NULL))
      snd_pcm_hw_params_get_period_size_min(
            params, &alsa->period_frames, NULL);
   RARCH_LOG("ALSA: Period size: %d frames\n", (int)alsa->period_frames);
   if (snd_pcm_hw_params_get_buffer_size(params, &buffer_size))
      snd_pcm_hw_params_get_buffer_size_max(params, &buffer_size);
   RARCH_LOG("ALSA: Buffer size: %d frames\n", (int)buffer_size);

   alsa->buffer_size = snd_pcm_frames_to_bytes(alsa->pcm, buffer_size);
   alsa->period_size = snd_pcm_frames_to_bytes(alsa->pcm, alsa->period_frames);

   TRY_ALSA(snd_pcm_sw_params_malloc(&sw_params));
   TRY_ALSA(snd_pcm_sw_params_current(alsa->pcm, sw_params));
   TRY_ALSA(snd_pcm_sw_params_set_start_threshold(
            alsa->pcm, sw_params, buffer_size / 2));
   TRY_ALSA(snd_pcm_sw_params(alsa->pcm, sw_params));

   snd_pcm_hw_params_free(params);
   snd_pcm_sw_params_free(sw_params);

   alsa->fifo_lock = slock_new();
   alsa->cond_lock = slock_new();
   alsa->cond = scond_new();
   alsa->buffer = fifo_new(alsa->buffer_size);
   if (!alsa->fifo_lock || !alsa->cond_lock || !alsa->cond || !alsa->buffer)
      goto error;

   alsa->worker_thread = sthread_create(alsa_worker_thread, alsa);
   if (!alsa->worker_thread)
   {
      RARCH_ERR("error initializing worker thread");
      goto error;
   }

   return alsa;

error:
   RARCH_ERR("ALSA: Failed to initialize...\n");
   if (params)
      snd_pcm_hw_params_free(params);

   if (sw_params)
      snd_pcm_sw_params_free(sw_params);

   alsa_thread_free(alsa);

   return NULL;
}
示例#30
0
文件: rec.cpp 项目: industral/Nexuz
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;
}