Example #1
0
            ALSA(unsigned channels, unsigned samplerate, const std::string& device = "default") : runnable(true), pcm(nullptr), params(nullptr), fps(samplerate)
            {
               int rc = snd_pcm_open(&pcm, device.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
               if (rc < 0)
               {
                  runnable = false;
                  throw DeviceException(General::join("Unable to open PCM device ", snd_strerror(rc)));
               }

               snd_pcm_format_t fmt = type_to_format(T());

               if (snd_pcm_hw_params_malloc(&params) < 0)
               {
                  runnable = false;
                  throw DeviceException("Failed to allocate memory.");
               }

               runnable = false;
               if (
                     (snd_pcm_hw_params_any(pcm, params) < 0) ||
                     (snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) ||
                     (snd_pcm_hw_params_set_channels(pcm, params, channels) < 0) ||
                     (snd_pcm_hw_params_set_format(pcm, params, fmt) < 0) ||
                     (snd_pcm_hw_params_set_rate(pcm, params, samplerate, 0) < 0) ||
                     ((rc = snd_pcm_hw_params(pcm, params)) < 0)
                  )
                  throw DeviceException(General::join("Unable to install HW params: ", snd_strerror(rc)));

               runnable = true;
            }
Example #2
0
internal
void hhxcb_init_alsa(hhxcb_context *context, hhxcb_sound_output *sound_output)
{
    // NOTE: "hw:0,0" doesn't seem to work with alsa running on top of pulseaudio
    char *device = (char *)"default";
    // char *device = (char *)"hw:0,0";

    int err;
    snd_pcm_sframes_t frames;
    err = snd_output_stdio_attach(&context->alsa_log, stderr, 0);

    if ((err = snd_pcm_open(&context->handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
    {
            printf("Playback open error: %s\n", snd_strerror(err));
            exit(EXIT_FAILURE);
    }

    snd_pcm_hw_params_t *hwparams;
    snd_pcm_hw_params_alloca(&hwparams);

    snd_pcm_hw_params_any(context->handle, hwparams);
    snd_pcm_hw_params_set_rate_resample(context->handle, hwparams, 0);
    snd_pcm_hw_params_set_access(context->handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_hw_params_set_format(context->handle, hwparams, SND_PCM_FORMAT_S16_LE);
    snd_pcm_hw_params_set_channels(context->handle, hwparams, 2);
    snd_pcm_hw_params_set_rate(context->handle, hwparams, sound_output->samples_per_second, 0);
    snd_pcm_hw_params_set_period_size(context->handle, hwparams, sound_output->samples_per_second / 60, 0);
    // NOTE: restricting this buffer size too much seems to crash the game
    sound_output->secondary_buffer_size = 48000 / 2;
    snd_pcm_hw_params_set_buffer_size(context->handle, hwparams, sound_output->secondary_buffer_size);
    snd_pcm_hw_params(context->handle, hwparams);
    snd_pcm_dump(context->handle, context->alsa_log);
}
Example #3
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);
	
}
Example #4
0
static int set_rate(Instance *pi, const char *value)
{
  int rc;
  unsigned int rate = atoi(value);
  ALSAio_private *priv = (ALSAio_private *)pi;

  if (!priv->c.handle) {
    fprintf(stderr, "*** device is not open!\n");
    return 1;
  }

  rc = snd_pcm_hw_params_set_rate(priv->c.handle,
                                  priv->c.hwparams,
                                  rate, 0);

  if (rc == 0) {
    fprintf(stderr, "rate set to %d\n", rate);
    priv->c.rate = rate;
  }
  else {
    fprintf(stderr, "*** error setting rate %d (%s)\n", rate, snd_strerror(rc));

  }

  return rc;
}
StackAudioDevice *stack_alsa_audio_device_create(const char *name, uint32_t channels, uint32_t sample_rate)
{
	// Debug
	fprintf(stderr, "stack_alsa_audio_device_create(\"%s\", %u, %u) called\n", name, channels, sample_rate);
	
	// Allocate the new device
	StackAlsaAudioDevice *device = new StackAlsaAudioDevice();
	device->stream = NULL;
	if (snd_pcm_open(&device->stream, name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) != 0)
	{
		fprintf(stderr, "stack_alsa_audio_device_create: snd_pcm_open() failed\n");
		return NULL;
	}

	// Get some initial hardware parameters
	snd_pcm_hw_params_t *hw_params = NULL;
	snd_pcm_hw_params_malloc(&hw_params);
	snd_pcm_hw_params_any(device->stream, hw_params);

	// Choose the correct sample rate
	if (snd_pcm_hw_params_set_rate(device->stream, hw_params, sample_rate, 0) < 0)
	{
		fprintf(stderr, "stack_alsa_audio_device_create: snd_pcm_hw_params_set_rate() failed\n");
	}

	// Set the correct number of channels
	if (snd_pcm_hw_params_set_channels(device->stream, hw_params, channels) < 0)
	{
		fprintf(stderr, "stack_alsa_audio_device_create: snd_pcm_hw_params_set_channels() failed\n");
	}

	// Set the format to 32-bit floating point, which is what Stack
	// uses internally
	if (snd_pcm_hw_params_set_format(device->stream, hw_params, SND_PCM_FORMAT_FLOAT_LE) < 0)
	{
		fprintf(stderr, "stack_alsa_audio_device_create: snd_pcm_hw_params_set_format() failed\n");
	}

	// Apply the hardware parameters to the device
	snd_pcm_hw_params(device->stream, hw_params);

	// Set up superclass	
	STACK_AUDIO_DEVICE(device)->_class_name = "StackAlsaAudioDevice";
	STACK_AUDIO_DEVICE(device)->channels = channels;
	STACK_AUDIO_DEVICE(device)->sample_rate = sample_rate;

	// Start the PCM stream
	if (snd_pcm_start(device->stream) < 0)
	{
		fprintf(stderr, "stack_alsa_audio_device_create: snd_pcm_start() failed\n");
	}

	// Return the newly created device
	return STACK_AUDIO_DEVICE(device);
}
Example #6
0
static int setup_params(void)
{
	snd_pcm_hw_params_t *hw;

	/* FIXME: more finer error checks */
	snd_pcm_hw_params_alloca(&hw);
	snd_pcm_hw_params_any(pcm, hw);
	snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED);
	snd_pcm_hw_params_set_format(pcm, hw, format);
	snd_pcm_hw_params_set_channels(pcm, hw, channels);
	snd_pcm_hw_params_set_rate(pcm, hw, rate, 0);
	snd_pcm_hw_params_set_period_size(pcm, hw, periodsize, 0);
	snd_pcm_hw_params_set_buffer_size(pcm, hw, bufsize);
	if (snd_pcm_hw_params(pcm, hw) < 0) {
		fprintf(stderr, "snd_pcm_hw_params error\n");
		return 1;
	}
	return 0;
}
Example #7
0
int audio_drv_init(char const * const device)
{
	unsigned int rate = 44100;
	int err;
	snd_pcm_hw_params_t *hw_params;

	if ((err = snd_pcm_open(&playback_handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
		return -1;

	if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
		return -2;

	if ((err = snd_pcm_hw_params_any(playback_handle, hw_params)) < 0)
		return -3;

	if ((err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
		return -4;

	if ((err = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0)
		return -5;

	if ((err = snd_pcm_hw_params_set_rate(playback_handle, hw_params, rate, 0)) < 0)
		return -6;

	if ((err = snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2)) < 0)
		return -7;

	if ((err = snd_pcm_hw_params_set_period_size(playback_handle, hw_params, 2048, 0)) < 0)
		return -8;

	if ((err = snd_pcm_hw_params_set_periods(playback_handle, hw_params, 4, 0)) < 0)
		return -9;

	if ((err = snd_pcm_hw_params(playback_handle, hw_params)) < 0)
		return -10;

	snd_pcm_hw_params_free(hw_params);

	if ((err = snd_pcm_prepare(playback_handle)) < 0)
		return -11;

	return 0;
}
Example #8
0
int AudioAlsa::setHWParams( const ch_cnt_t _channels, snd_pcm_access_t _access )
{
	int err, dir;

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

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

	// set the sample format
	if( ( snd_pcm_hw_params_set_format( m_handle, m_hwParams,
						SND_PCM_FORMAT_S16_LE ) ) < 0 )
	{
		if( ( snd_pcm_hw_params_set_format( m_handle, m_hwParams,
						SND_PCM_FORMAT_S16_BE ) ) < 0 )
		{
			printf( "Neither little- nor big-endian available for "
					"playback: %s\n", snd_strerror( err ) );
			return err;
		}
		m_convertEndian = isLittleEndian();
	}
	else
	{
		m_convertEndian = !isLittleEndian();
	}

	// set the count of channels
	if( ( err = snd_pcm_hw_params_set_channels( m_handle, m_hwParams,
							_channels ) ) < 0 )
	{
		printf( "Channel count (%i) not available for playbacks: %s\n"
				"(Does your soundcard not support surround?)\n",
					_channels, snd_strerror( err ) );
		return err;
	}

	// set the sample rate
	if( ( err = snd_pcm_hw_params_set_rate( m_handle, m_hwParams,
						sampleRate(), 0 ) ) < 0 )
	{
		if( ( err = snd_pcm_hw_params_set_rate( m_handle, m_hwParams,
				mixer()->baseSampleRate(), 0 ) ) < 0 )
		{
			printf( "Could not set sample rate: %s\n",
							snd_strerror( err ) );
			return err;
		}
	}

	m_periodSize = mixer()->framesPerPeriod();
	m_bufferSize = m_periodSize * 8;
	dir = 0;
	err = snd_pcm_hw_params_set_period_size_near( m_handle, m_hwParams,
							&m_periodSize, &dir );
	if( err < 0 )
	{
		printf( "Unable to set period size %lu for playback: %s\n",
					m_periodSize, snd_strerror( err ) );
		return err;
	}
	dir = 0;
	err = snd_pcm_hw_params_get_period_size( m_hwParams, &m_periodSize,
									&dir );
	if( err < 0 )
	{
		printf( "Unable to get period size for playback: %s\n",
							snd_strerror( err ) );
	}

	dir = 0;
	err = snd_pcm_hw_params_set_buffer_size_near( m_handle, m_hwParams,
								&m_bufferSize );
	if( err < 0 )
	{
		printf( "Unable to set buffer size %lu for playback: %s\n",
					m_bufferSize, snd_strerror( err ) );
		return ( err );
	}
	err = snd_pcm_hw_params_get_buffer_size( m_hwParams, &m_bufferSize );

	if( 2 * m_periodSize > m_bufferSize )
	{
		printf( "buffer to small, could not use\n" );
		return ( err );
	}


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

	return ( 0 );	// all ok
}
Example #9
0
static int
laudio_alsa_open(void)
{
  snd_pcm_hw_params_t *hw_params;
  snd_pcm_uframes_t bufsize;
  int ret;

  hw_params = NULL;

  ret = snd_pcm_open(&hdl, card_name, SND_PCM_STREAM_PLAYBACK, 0);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not open playback device: %s\n", snd_strerror(ret));

      return -1;
    }

  /* HW params */
  ret = snd_pcm_hw_params_malloc(&hw_params);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not allocate hw params: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  ret = snd_pcm_hw_params_any(hdl, hw_params);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not retrieve hw params: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  ret = snd_pcm_hw_params_set_access(hdl, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not set access method: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  ret = snd_pcm_hw_params_set_format(hdl, hw_params, SND_PCM_FORMAT_S16_LE);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not set S16LE format: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  ret = snd_pcm_hw_params_set_channels(hdl, hw_params, 2);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not set stereo output: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  ret = snd_pcm_hw_params_set_rate(hdl, hw_params, 44100, 0);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Hardware doesn't support 44.1 kHz: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  ret = snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufsize);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not get max buffer size: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  DPRINTF(E_DBG, L_LAUDIO, "Max buffer size is %lu samples\n", bufsize);

  ret = snd_pcm_hw_params_set_buffer_size_max(hdl, hw_params, &bufsize);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not set buffer size to max: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  DPRINTF(E_DBG, L_LAUDIO, "Buffer size is %lu samples\n", bufsize);

  ret = snd_pcm_hw_params(hdl, hw_params);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not set hw params: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  snd_pcm_hw_params_free(hw_params);
  hw_params = NULL;

  pcm_pos = 0;
  pcm_last_error = 0;
  pcm_recovery = 0;
  pcm_buf_threshold = (bufsize / AIRTUNES_V2_PACKET_SAMPLES) * AIRTUNES_V2_PACKET_SAMPLES;

  ret = mixer_open();
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not open mixer\n");

      goto out_fail;
    }

  update_status(LAUDIO_OPEN);

  return 0;

 out_fail:
  if (hw_params)
    snd_pcm_hw_params_free(hw_params);

  snd_pcm_close(hdl);
  hdl = NULL;

  return -1;
}
Example #10
0
static snd_pcm_uframes_t set_params(snd_pcm_t *handle, snd_pcm_stream_t stream)
{
	snd_pcm_hw_params_t *params;
	snd_pcm_sw_params_t *swparams;
	snd_pcm_uframes_t buffer_size;
	snd_pcm_uframes_t chunk_size = 0;
	snd_pcm_uframes_t start_threshold;
	unsigned period_time = 0;
	unsigned buffer_time = 0;
	size_t chunk_bytes = 0;
	int err;

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

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

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

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

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

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

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

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


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


	period_time = buffer_time / 4;

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

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

	assert(err >= 0);

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

	snd_pcm_sw_params_current(handle, swparams);

	err = snd_pcm_sw_params_set_avail_min(handle, swparams, chunk_size);

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

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

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

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

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

	return chunk_size;

}
Example #11
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;
}
Example #12
0
bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const
{
    // Set nearest to closest settings that do work.
    // See if what is in settings will work (return value).
    int err = 0;
    snd_pcm_t* handle;
    snd_pcm_hw_params_t *params;
    QString dev = device;

    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 = device;
#else
        int idx = 0;
        char *name;

        QString shortName = device.mid(device.indexOf(QLatin1String("="),0)+1);

        while(snd_card_get_name(idx,&name) == 0) {
            if(shortName.compare(QLatin1String(name)) == 0)
                break;
            idx++;
        }
        dev = QString(QLatin1String("hw:%1,0")).arg(idx);
#endif
    }
    if(mode == QAudio::AudioOutput) {
        err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0);
    } else {
        err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0);
    }
    if(err < 0) {
        handle = 0;
        return false;
    }

    bool testChannel = false;
    bool testCodec = false;
    bool testFreq = false;
    bool testType = false;
    bool testSize = false;

    int  dir = 0;

    snd_pcm_nonblock( handle, 0 );
    snd_pcm_hw_params_alloca( &params );
    snd_pcm_hw_params_any( handle, params );

    // set the values!
    snd_pcm_hw_params_set_channels(handle,params,format.channels());
    snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir);

    err = -1;

    switch(format.sampleSize()) {
        case 8:
            if(format.sampleType() == QAudioFormat::SignedInt)
                err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8);
            else if(format.sampleType() == QAudioFormat::UnSignedInt)
                err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8);
            break;
        case 16:
            if(format.sampleType() == QAudioFormat::SignedInt) {
                if(format.byteOrder() == QAudioFormat::LittleEndian)
                    err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
                else if(format.byteOrder() == QAudioFormat::BigEndian)
                    err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE);
            } else if(format.sampleType() == QAudioFormat::UnSignedInt) {
                if(format.byteOrder() == QAudioFormat::LittleEndian)
                    err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE);
                else if(format.byteOrder() == QAudioFormat::BigEndian)
                    err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE);
            }
            break;
        case 32:
            if(format.sampleType() == QAudioFormat::SignedInt) {
                if(format.byteOrder() == QAudioFormat::LittleEndian)
                    err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE);
                else if(format.byteOrder() == QAudioFormat::BigEndian)
                    err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE);
            } else if(format.sampleType() == QAudioFormat::UnSignedInt) {
                if(format.byteOrder() == QAudioFormat::LittleEndian)
                    err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE);
                else if(format.byteOrder() == QAudioFormat::BigEndian)
                    err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE);
            }
    }

    // For now, just accept only audio/pcm codec
    if(!format.codec().startsWith(QLatin1String("audio/pcm"))) {
        err=-1;
    } else
        testCodec = true;

    if(err>=0 && format.channels() != -1) {
        err = snd_pcm_hw_params_test_channels(handle,params,format.channels());
        if(err>=0)
            err = snd_pcm_hw_params_set_channels(handle,params,format.channels());
        if(err>=0)
            testChannel = true;
    }

    if(err>=0 && format.frequency() != -1) {
        err = snd_pcm_hw_params_test_rate(handle,params,format.frequency(),0);
        if(err>=0)
            err = snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir);
        if(err>=0)
            testFreq = true;
    }

    if((err>=0 && format.sampleSize() != -1) &&
            (format.sampleType() != QAudioFormat::Unknown)) {
        switch(format.sampleSize()) {
            case 8:
                if(format.sampleType() == QAudioFormat::SignedInt)
                    err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8);
                else if(format.sampleType() == QAudioFormat::UnSignedInt)
                    err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8);
                break;
            case 16:
                if(format.sampleType() == QAudioFormat::SignedInt) {
                    if(format.byteOrder() == QAudioFormat::LittleEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
                    else if(format.byteOrder() == QAudioFormat::BigEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE);
                } else if(format.sampleType() == QAudioFormat::UnSignedInt) {
                    if(format.byteOrder() == QAudioFormat::LittleEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE);
                    else if(format.byteOrder() == QAudioFormat::BigEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE);
                }
                break;
            case 32:
                if(format.sampleType() == QAudioFormat::SignedInt) {
                    if(format.byteOrder() == QAudioFormat::LittleEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE);
                    else if(format.byteOrder() == QAudioFormat::BigEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE);
                } else if(format.sampleType() == QAudioFormat::UnSignedInt) {
                    if(format.byteOrder() == QAudioFormat::LittleEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE);
                    else if(format.byteOrder() == QAudioFormat::BigEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE);
                }
        }
        if(err>=0) {
            testSize = true;
            testType = true;
        }
    }
    if(err>=0)
        err = snd_pcm_hw_params(handle, params);

    if(err == 0) {
        // settings work
        // close()
        if(handle)
            snd_pcm_close(handle);
        return true;
    }
    if(handle)
        snd_pcm_close(handle);

    return false;
}
Example #13
0
static int initalsa(char *filename)
{
	snd_pcm_hw_params_t *hw_params;
	int err;

	if ((err =
	     snd_pcm_open(&capture_handle, filename,
			  SND_PCM_STREAM_CAPTURE, 0)) < 0) {
		fprintf(stderr, "cannot open audio device %s (%s)\n",
			filename, snd_strerror(err));
		return 0;
	}

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

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

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

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

	if ((err =
	     snd_pcm_hw_params_set_rate(capture_handle, hw_params, 48000,
					0)) < 0) {
		fprintf(stderr, "cannot set sample rate (%s)\n",
			snd_strerror(err));
		return 0;
	}

	for(nbch=2;nbch>0;nbch--)  {
		if (snd_pcm_hw_params_set_channels(capture_handle, hw_params, nbch)==0)	
			break;
	}

	if (nbch ==0) {
		fprintf(stderr, "cannot set number of channels\n");
		return 0;
	}

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

	if ((err = snd_pcm_prepare(capture_handle)) < 0) {
		fprintf(stderr,
			"cannot prepare audio interface for use (%s)\n",
			snd_strerror(err));
		return 0;
	}
	return nbch;
}
Example #14
0
bool AlsaRenderer::SetupHwParams()
{
    snd_pcm_hw_params_t* params;

    /* allocate a hardware parameters object */
    snd_pcm_hw_params_malloc(&params);

    /* choose all parameters */
    snd_pcm_hw_params_any(m_PcmHandle, params);

    /* enable hardware resampling */
    snd_pcm_hw_params_set_rate_resample(m_PcmHandle, params, m_Resample);

    /* set the interleaved read/write format */
    snd_pcm_hw_params_set_access(m_PcmHandle, params, SND_PCM_ACCESS_RW_INTERLEAVED);

    /* signed 16-bit little-endian format */
    snd_pcm_hw_params_set_format(m_PcmHandle, params, SND_PCM_FORMAT_S16_LE);

    /* set the count of channels */
    snd_pcm_hw_params_get_channels_max(params, &m_Channels.max);
    snd_pcm_hw_params_get_channels_min(params, &m_Channels.min);
    if (m_Channels.val < m_Channels.min || m_Channels.val > m_Channels.max) 
        m_Channels.val = m_Channels.min;
    snd_pcm_hw_params_set_channels(m_PcmHandle, params, m_Channels.val);

    /* set the stream rate */
    snd_pcm_hw_params_get_rate_max(params, &m_SampleRate.max, &m_Dir);
    snd_pcm_hw_params_get_rate_min(params, &m_SampleRate.min, &m_Dir);
    if (m_SampleRate.val < m_SampleRate.min || m_SampleRate.val > m_SampleRate.max)
        m_SampleRate.val = m_SampleRate.min;
    printf("sample rate max:%d, min:%d, val:%d\n", 
            m_SampleRate.max, m_SampleRate.min, m_SampleRate.val);
    snd_pcm_hw_params_set_rate(m_PcmHandle, params, m_SampleRate.val, m_Dir);

    /* we can set period and buffer by size or time */
    /* by default we use "size" (count of frames)   */

    /* set how many frames in a buffer (a buffer cantains several periods) */
    snd_pcm_hw_params_get_buffer_size_max(params, &m_BufferSize.max);
    snd_pcm_hw_params_get_buffer_size_min(params, &m_BufferSize.min);

    /* detect period time and buffer time range  */
    snd_pcm_hw_params_get_buffer_time_max(params, &m_BufferTime.max, &m_Dir);
    snd_pcm_hw_params_get_buffer_time_min(params, &m_BufferTime.min, &m_Dir);
    m_BufferTime.val = std::max(m_BufferTime.max / 2, m_BufferTime.min); 
    //m_BufferTime.val = m_BufferTime.min + (m_BufferTime.max - m_BufferTime.min) /2; 
    printf("buffer time max:%d, min:%d, val:%d\n", 
            m_BufferTime.max, m_BufferTime.min, m_BufferTime.val);
    //(m_BufferTime.max > 120000) ? 120000 : m_BufferTime.max;//120000
    snd_pcm_hw_params_set_buffer_time_near(m_PcmHandle, params, &m_BufferTime.val, &m_Dir);

    snd_pcm_hw_params_get_period_time_max(params, &m_PeriodTime.max, &m_Dir);
    snd_pcm_hw_params_get_period_time_min(params, &m_PeriodTime.min, &m_Dir);
    m_PeriodTime.val = m_BufferTime.val / 4;
    //m_PeriodTime.val = m_PeriodTime.min + (m_PeriodTime.max - m_PeriodTime.min) / 2;
    printf("period time max:%d, min:%d, val:%d\n", 
            m_PeriodTime.max, m_PeriodTime.min, m_PeriodTime.val);
    snd_pcm_hw_params_set_period_time_near(m_PcmHandle, params, &m_PeriodTime.val, &m_Dir);

    int ret = snd_pcm_hw_params(m_PcmHandle, params);

    if (ret != 0) {
        snd_pcm_hw_params_free(params);
        return false;
    }

    // get period size again
    snd_pcm_hw_params_get_period_size(params, &m_PeriodSize.val, &m_Dir);
    snd_pcm_hw_params_get_buffer_size(params, &m_BufferSize.val);

    m_BitsPerSample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE);
    m_FrameLength = (m_BitsPerSample/8 * m_Channels.val);
    //mPeriodBufferLength = m_PeriodSize.val * m_FrameLength ;

    snd_pcm_hw_params_free(params);

    return true;
}
Example #15
0
cst_audiodev *audio_open_alsa(unsigned int sps, int channels)
{
  cst_audiodev *ad;
  int err;

  /* alsa specific stuff */
  snd_pcm_t *pcm_handle;
  snd_pcm_hw_params_t *hwparams;
  snd_pcm_format_t format;

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

  /* Open pcm device */
  err = snd_pcm_open(&pcm_handle, pcm_dev_name, SND_PCM_STREAM_PLAYBACK, 0);
  if (err < 0) 
  {
	cst_errmsg("audio_open_alsa: failed to open audio device %s. %s\n",
			   pcm_dev_name, snd_strerror(err));
	return NULL;
  }

  /* Init hwparams with full configuration space */
  err = snd_pcm_hw_params_any(pcm_handle, hwparams);
  if (err < 0) 
  {
	snd_pcm_close(pcm_handle);
        snd_config_update_free_global();
	cst_errmsg("audio_open_alsa: failed to get hardware parameters from audio device. %s\n", snd_strerror(err));
	return NULL;
  }

  /* Set access mode */
  err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
  if (err < 0) 
  {
	snd_pcm_close(pcm_handle);
        snd_config_update_free_global();
	cst_errmsg("audio_open_alsa: failed to set access mode. %s.\n", snd_strerror(err));
	return NULL;
  }

#ifdef WORDS_BIGENDIAN
  format = SND_PCM_FORMAT_S16_BE;
#else
  format = SND_PCM_FORMAT_S16_LE;
#endif

  /* Set sample format */
  err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format);
  if (err <0) 
  {
	snd_pcm_close(pcm_handle);
        snd_config_update_free_global();
	cst_errmsg("audio_open_alsa: failed to set format. %s.\n", snd_strerror(err));
	return NULL;
  }

  /* Set sample rate */
  err = snd_pcm_hw_params_set_rate(pcm_handle, hwparams, sps, 0);
  if (err < 0)   
  {
	snd_pcm_close(pcm_handle);
        snd_config_update_free_global();
	cst_errmsg("audio_open_alsa: failed to set sample rate near %d. %s.\n", sps, snd_strerror(err));
	return NULL;
  }

  /* Set number of channels */
  assert(channels >0);
  err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels);
  if (err < 0) 
  {
	snd_pcm_close(pcm_handle);
        snd_config_update_free_global();
	cst_errmsg("audio_open_alsa: failed to set number of channels to %d. %s.\n", channels, snd_strerror(err));
	return NULL;
  }

  /* Commit hardware parameters */
  err = snd_pcm_hw_params(pcm_handle, hwparams);
  if (err < 0) 
  {
	snd_pcm_close(pcm_handle);
        snd_config_update_free_global();
	cst_errmsg("audio_open_alsa: failed to set hw parameters. %s.\n", snd_strerror(err));
	return NULL;
  }

  /* Make sure the device is ready to accept data */
  assert(snd_pcm_state(pcm_handle) == SND_PCM_STATE_PREPARED);

  /* Write hardware parameters to audio device data structure */
  ad = cst_alloc(cst_audiodev, 1);
  assert(ad != NULL);
  ad->sps = sps;
  ad->channels = channels;
  ad->platform_data = (void *) pcm_handle;

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

    snd_pcm_hw_params_alloca(&hw_params);

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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


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



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

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

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

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

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

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

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

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

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

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

	if ((err = snd_pcm_prepare (playback_handle)) < 0)
	{
		oss << "cannot prepare audio interface for use : " << snd_strerror (err) << endl;
		throw oss.str();
	}
}
Example #18
0
int AlsaAudioPlugin::init(shared_ptr<t_CPC> cpc, shared_ptr<t_PSG> psg)
{
	if(!cpc->snd_enabled)
	{
		InfoLogMessage("[ALSA Audio Plugin] Not opening audio because disabled in the config");
		return 0;
	}
    /*  TODO */
    unsigned int rate = cpc->snd_playback_rate;
    int channels = cpc->snd_stereo ? 2 : 1;

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

    int periods = 2;
    periodsize = 4096;

    unsigned int exact_rate;
    int dir, err;

    /* Handle for the PCM device */ 
    //snd_pcm_t *pcm_handle;          

    /* Playback stream */
    snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;

    /* This structure contains information about    */
    /* the hardware and can be used to specify the  */      
    /* configuration to be used for the PCM stream. */ 
    snd_pcm_hw_params_t *hwparams;

    /* Name of the PCM device, like plughw:0,0          */
    /* The first number is the number of the soundcard, */
    /* the second number is the number of the device.   */
    char *pcm_name = strdup("plughw:0,0");
	WarningLogMessage("TODO [%s:%d]: pcm_name need to be configurable.", __FILE__, __LINE__);
  
    /* Allocate the snd_pcm_hw_params_t structure on the stack. */
    snd_pcm_hw_params_alloca(&hwparams);

    /* Open PCM. The last parameter of this function is the mode. */
    /* If this is set to 0, the standard mode is used. Possible   */
    /* other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC.       */ 
    /* If SND_PCM_NONBLOCK is used, read / write access to the    */
    /* PCM device will return immediately. If SND_PCM_ASYNC is    */
    /* specified, SIGIO will be emitted whenever a period has     */
    /* been completely processed by the soundcard.                */
    if(err = snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0) {
        ErrorLogMessage("[ALSA Audio Plugin] Error opening PCM device %s (Error: %s)", pcm_name, snd_strerror(err));
        return 1;
    }

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

    /* Set access type. This can be either    */
    /* SND_PCM_ACCESS_RW_INTERLEAVED or       */
    /* SND_PCM_ACCESS_RW_NONINTERLEAVED.      */
    /* There are also access types for MMAPed */
    /* access, but this is beyond the scope   */
    /* of this introduction.                  */
    if(err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
        ErrorLogMessage("[ALSA Audio Plugin] Error setting access on device %s. (Error: %s)", pcm_name, snd_strerror(err));
        return 1;
    }
  
    /* Set sample format */ 
    if(err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format) < 0) {
        ErrorLogMessage("[ALSA Audio Plugin] Error setting format %s on device %s. (Error: %s)", snd_pcm_format_name(format), pcm_name, snd_strerror(err));
        return 1;
    }
    
    /* Set sample rate. If the exact rate is not supported */
    /* by the hardware, use nearest possible rate.         */ 
#if 0 // Segfault... Humf... TODO
    exact_rate = rate;
    if(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, &dir) < 0)
    {
        ErrorLogMessage("Error setting rate (%d) on device %s.", rate, pcm_name);
    }
    if(dir != 0) {
        WarningLogMessage("The rate %d Hz is not supported by your hardware on device %s.\n" \
                "==> Using %d Hz instead.", pcm_name, rate, exact_rate);
    }
#else
	exact_rate = rate;
    if(err = snd_pcm_hw_params_set_rate(pcm_handle, hwparams, exact_rate, 0) < 0)
    {
        ErrorLogMessage("[ALSA Audio Plugin] Error setting rate (%d) on device %s. (Error: %s)", rate, pcm_name, snd_strerror(err));
    }
#endif
    
    /* Set number of channels */
    if(err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels) < 0) {
        ErrorLogMessage("[ALSA Audio Plugin] Error setting channels (%d) on device %s. (Error: %s)", channels, pcm_name, snd_strerror(err));
        return 1;
    }

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

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

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

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

    return 0;
}
Example #19
0
static ALCenum alsa_open_capture(ALCdevice *Device, const ALCchar *deviceName)
{
    const char *driver = NULL;
    snd_pcm_hw_params_t *hp;
    snd_pcm_uframes_t bufferSizeInFrames;
    snd_pcm_uframes_t periodSizeInFrames;
    ALboolean needring = AL_FALSE;
    snd_pcm_format_t format;
    const char *funcerr;
    alsa_data *data;
    int err;

    if(deviceName)
    {
        size_t idx;

        if(!allCaptureDevNameMap)
            allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames);

        for(idx = 0;idx < numCaptureDevNames;idx++)
        {
            if(strcmp(deviceName, allCaptureDevNameMap[idx].name) == 0)
            {
                driver = allCaptureDevNameMap[idx].device;
                break;
            }
        }
        if(idx == numCaptureDevNames)
            return ALC_INVALID_VALUE;
    }
    else
    {
        deviceName = alsaDevice;
        driver = GetConfigValue("alsa", "capture", "default");
    }

    data = (alsa_data*)calloc(1, sizeof(alsa_data));

    err = snd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
    if(err < 0)
    {
        ERR("Could not open capture device '%s': %s\n", driver, snd_strerror(err));
        free(data);
        return ALC_INVALID_VALUE;
    }

    format = -1;
    switch(Device->FmtType)
    {
        case DevFmtByte:
            format = SND_PCM_FORMAT_S8;
            break;
        case DevFmtUByte:
            format = SND_PCM_FORMAT_U8;
            break;
        case DevFmtShort:
            format = SND_PCM_FORMAT_S16;
            break;
        case DevFmtUShort:
            format = SND_PCM_FORMAT_U16;
            break;
        case DevFmtInt:
            format = SND_PCM_FORMAT_S32;
            break;
        case DevFmtUInt:
            format = SND_PCM_FORMAT_U32;
            break;
        case DevFmtFloat:
            format = SND_PCM_FORMAT_FLOAT;
            break;
    }

    funcerr = NULL;
    bufferSizeInFrames = maxu(Device->UpdateSize*Device->NumUpdates,
                              100*Device->Frequency/1000);
    periodSizeInFrames = minu(bufferSizeInFrames, 25*Device->Frequency/1000);

    snd_pcm_hw_params_malloc(&hp);
#define CHECK(x) if((funcerr=#x),(err=(x)) < 0) goto error
    CHECK(snd_pcm_hw_params_any(data->pcmHandle, hp));
    /* set interleaved access */
    CHECK(snd_pcm_hw_params_set_access(data->pcmHandle, hp, SND_PCM_ACCESS_RW_INTERLEAVED));
    /* set format (implicitly sets sample bits) */
    CHECK(snd_pcm_hw_params_set_format(data->pcmHandle, hp, format));
    /* set channels (implicitly sets frame bits) */
    CHECK(snd_pcm_hw_params_set_channels(data->pcmHandle, hp, ChannelsFromDevFmt(Device->FmtChans)));
    /* set rate (implicitly constrains period/buffer parameters) */
    CHECK(snd_pcm_hw_params_set_rate(data->pcmHandle, hp, Device->Frequency, 0));
    /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
    if(snd_pcm_hw_params_set_buffer_size_min(data->pcmHandle, hp, &bufferSizeInFrames) < 0)
    {
        TRACE("Buffer too large, using intermediate ring buffer\n");
        needring = AL_TRUE;
        CHECK(snd_pcm_hw_params_set_buffer_size_near(data->pcmHandle, hp, &bufferSizeInFrames));
    }
    /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
    CHECK(snd_pcm_hw_params_set_period_size_near(data->pcmHandle, hp, &periodSizeInFrames, NULL));
    /* install and prepare hardware configuration */
    CHECK(snd_pcm_hw_params(data->pcmHandle, hp));
    /* retrieve configuration info */
    CHECK(snd_pcm_hw_params_get_period_size(hp, &periodSizeInFrames, NULL));
#undef CHECK
    snd_pcm_hw_params_free(hp);
    hp = NULL;

    if(needring)
    {
        data->ring = CreateRingBuffer(FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType),
                                      Device->UpdateSize*Device->NumUpdates);
        if(!data->ring)
        {
            ERR("ring buffer create failed\n");
            goto error2;
        }

        data->size = snd_pcm_frames_to_bytes(data->pcmHandle, periodSizeInFrames);
        data->buffer = malloc(data->size);
        if(!data->buffer)
        {
            ERR("buffer malloc failed\n");
            goto error2;
        }
    }

    Device->DeviceName = strdup(deviceName);

    Device->ExtraData = data;
    return ALC_NO_ERROR;

error:
    ERR("%s failed: %s\n", funcerr, snd_strerror(err));
    if(hp) snd_pcm_hw_params_free(hp);

error2:
    free(data->buffer);
    DestroyRingBuffer(data->ring);
    snd_pcm_close(data->pcmHandle);
    free(data);

    Device->ExtraData = NULL;
    return ALC_INVALID_VALUE;
}
Example #20
0
static void *sound_play(void *args)
{
    char path[256];
    int samplerate;
    int err;
    snd_pcm_t *playback_handle;
    snd_pcm_hw_params_t *hw_params;
    FILE *fp;

    db_msg("prepare play sound...\n");
    if (script_fetch("hdmi", "sound_file", (int *)path, sizeof(path) / 4)) {
        db_warn("unknown sound file, use default\n");
        strcpy(path, "/dragonboard/data/test48000.pcm");
    }
    if (script_fetch("hdmi", "samplerate", &samplerate, 1)) {
        db_warn("unknown samplerate, use default #48000\n");
        samplerate = 48000;
    }
    db_msg("samplerate #%d\n", samplerate);

    err = snd_pcm_open(&playback_handle, "hw:1,0", SND_PCM_STREAM_PLAYBACK, 0);
    if (err < 0) {
        db_error("cannot open audio device (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_malloc(&hw_params);
    if (err < 0) {
        db_error("cannot allocate hardware parameter structure (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_any(playback_handle, hw_params);
    if (err < 0) {
        db_error("cannot initialize hardware parameter structure (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err < 0) {
        db_error("cannot allocate hardware parameter structure (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE);
    if (err < 0) {
        db_error("cannot allocate hardware parameter structure (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_set_rate(playback_handle, hw_params, samplerate, 0);
    if (err < 0) {
        db_error("cannot set sample rate (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2);
    if (err < 0) {
        db_error("cannot set channel count (%s), err = %d\n", snd_strerror(err), err);
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params(playback_handle, hw_params);
    if (err < 0) {
        db_error("cannot set parameters (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    snd_pcm_hw_params_free(hw_params);

    db_msg("open test pcm file: %s\n", path);
    fp = fopen(path, "r");
    if (fp == NULL) {
        db_error("cannot open test pcm file(%s)\n", strerror(errno));
        pthread_exit((void *)-1);
    }

    db_msg("play it...\n");
    while (1) {
        while (!feof(fp)) {
            if (sound_play_stop) {
                goto out;
            }

            err = fread(buf, 1, BUF_LEN, fp);
            if (err < 0) {
                db_warn("read test pcm failed(%s)\n", strerror(errno));
            }

            err = snd_pcm_writei(playback_handle, buf, BUF_LEN/4);
            if (err < 0) {
                err = xrun_recovery(playback_handle, err);
                if (err < 0) {
                    db_warn("write error: %s\n", snd_strerror(err));
                }
            }

            if (err == -EBADFD) {
                db_warn("PCM is not in the right state (SND_PCM_STATE_PREPARED or SND_PCM_STATE_RUNNING)\n");
            }
            if (err == -EPIPE) {
                db_warn("an underrun occurred\n");
            }
            if (err == -ESTRPIPE) {
                db_warn("a suspend event occurred (stream is suspended and waiting for an application recovery)\n");
            }

            if (feof(fp)) {
                fseek(fp, 0L, SEEK_SET);
            }
        }
    }

out:
    db_msg("play end...\n");
    fclose(fp);
    snd_pcm_close(playback_handle);
    pthread_exit(0);
}
int 
set_hwparams(snd_pcm_t *handle, int sampleRate, int channels, int bufferSize)
{
    snd_pcm_access_t access = SND_PCM_ACCESS_RW_INTERLEAVED;

    int ret, dir;

    snd_pcm_hw_params_t *hwparams;

    snd_pcm_hw_params_alloca(&hwparams);

    /* choose all parameters */
    ret = snd_pcm_hw_params_any(handle, hwparams);
    if (ret < 0) {
        fprintf(stderr, "Broken configuration for playback: "
	    "no configurations available: %s\n", snd_strerror(ret));
        return ret;
    }
    /* set hardware resampling */
    ret = snd_pcm_hw_params_set_rate_resample(handle, hwparams, resample);
    if (ret < 0) {
	fprintf(stderr, "Resampling setup failed for playback: %s\n", 
	    snd_strerror(ret));
        return ret;
    }

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

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

    /* set the count of channels */
    ret = snd_pcm_hw_params_set_channels(handle, hwparams, channels);
    if (ret < 0) {
        fprintf(stderr, 
	    "Channels count (%d) not available for playbacks: %s\n", 
	    channels, snd_strerror(ret));
        return ret;
    } 

    /* set the stream rate */
    int rate = sampleRate;

    ret = snd_pcm_hw_params_set_rate(handle, hwparams, rate, 0);
    if (ret < 0) {
        fprintf(stderr, "Rate %dHz not available for playback: %s\n", 
	    sampleRate, snd_strerror(ret));
        return ret;
    }

    if (rate != sampleRate) {
        fprintf(stderr, "Rate doesn't match (requested %dHz, get %dHz)\n", 
	    rate, ret);
        return -EINVAL;
    } 

    /* set the buffer frames */
    unsigned int buffer_frames = bufferSize / 2 / channels;  // bytes to frames

    ret = snd_pcm_hw_params_set_buffer_size(handle, hwparams, buffer_frames);
    if (ret < 0) {
        fprintf(stderr, "Unable to set buffer size %d for playback: %s\n", 
	    buffer_frames, snd_strerror(ret));
        return ret;
    }

    /* set the period time */
    dir = 0;
    ret = snd_pcm_hw_params_set_period_time_near(handle, hwparams, 
	&period_time, &dir);
    if (ret < 0) {
        fprintf(stderr, "Unable to set period time %d for playback: %s\n", 
	    period_time, snd_strerror(ret));
        return ret;
    }

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

    dump_hwparams(handle);
}
Example #22
0
FFTWidget::FFTWidget(QWidget *parent)
    : QWidget(parent)
{
    int err;
    snd_pcm_hw_params_t *hw_params;
    const char *dev_name = "hw:SDR";
    if ((err = snd_pcm_open(&capture_handle, dev_name, SND_PCM_STREAM_CAPTURE, 0)) < 0)
    {
        fprintf (stderr, "cannot open audio device %s (%s)\n",
                 dev_name,
                 snd_strerror (err));
        exit (1);
    }

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

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

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

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

    if ((err = snd_pcm_hw_params_set_rate(capture_handle, hw_params, 96000, 0)) < 0)
    {
        fprintf (stderr, "cannot set sample rate (%s)\n",
                 snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params_set_channels (capture_handle, hw_params, 2)) < 0)
    {
        fprintf (stderr, "cannot set channel count (%s)\n",
                 snd_strerror (err));
        exit (1);
    }

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

    snd_pcm_hw_params_free (hw_params);

    if ((err = snd_pcm_prepare (capture_handle)) < 0)
    {
        fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
                 snd_strerror (err));
        exit (1);
    }

    setRectWindow();

    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(processFFT()));
    timer->start(); // Zero-delay
    if((err = snd_pcm_start(capture_handle)) < 0)
    {
        fprintf (stderr, "cannot start audio interface (%s)\n",
                 snd_strerror (err));
        exit(1);
    }
}
Example #23
0
bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const
{
    // Set nearest to closest settings that do work.
    // See if what is in settings will work (return value).
    int err = 0;
    snd_pcm_t* handle;
    snd_pcm_hw_params_t *params;
    QString dev = device;

    // open()
    if(!dev.contains(QLatin1String("default"))) {
        int idx = snd_card_get_index(dev.toLocal8Bit().constData());
        dev = QString(QLatin1String("hw:%1,0")).arg(idx);
    }
    if(mode == QAudio::AudioOutput) {
        err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0);
    } else {
        err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0);
    }
    if(err < 0) {
        handle = 0;
        return false;
    }

    bool testChannel = false;
    bool testCodec = false;
    bool testFreq = false;
    bool testType = false;
    bool testSize = false;

    int  dir = 0;

    snd_pcm_nonblock( handle, 0 );
    snd_pcm_hw_params_alloca( &params );
    snd_pcm_hw_params_any( handle, params );

    // set the values!
    snd_pcm_hw_params_set_channels(handle,params,format.channels());
    snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir);
    switch(format.sampleSize()) {
        case 8:
            if(format.sampleType() == QAudioFormat::SignedInt)
                snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8);
            else if(format.sampleType() == QAudioFormat::UnSignedInt)
                snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8);
            break;
        case 16:
            if(format.sampleType() == QAudioFormat::SignedInt) {
                if(format.byteOrder() == QAudioFormat::LittleEndian)
                    snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
                else if(format.byteOrder() == QAudioFormat::BigEndian)
                    snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE);
            } else if(format.sampleType() == QAudioFormat::UnSignedInt) {
                if(format.byteOrder() == QAudioFormat::LittleEndian)
                    snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE);
                else if(format.byteOrder() == QAudioFormat::BigEndian)
                    snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE);
            }
            break;
        case 32:
            if(format.sampleType() == QAudioFormat::SignedInt) {
                if(format.byteOrder() == QAudioFormat::LittleEndian)
                    snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE);
                else if(format.byteOrder() == QAudioFormat::BigEndian)
                    snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE);
            } else if(format.sampleType() == QAudioFormat::UnSignedInt) {
                if(format.byteOrder() == QAudioFormat::LittleEndian)
                    snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE);
                else if(format.byteOrder() == QAudioFormat::BigEndian)
                    snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE);
            }
    }

    // For now, just accept only audio/pcm codec
    if(!format.codec().startsWith(QLatin1String("audio/pcm"))) {
        err=-1;
    } else
        testCodec = true;

    if(err>=0 && format.channels() != -1) {
        err = snd_pcm_hw_params_test_channels(handle,params,format.channels());
        if(err>=0)
            err = snd_pcm_hw_params_set_channels(handle,params,format.channels());
        if(err>=0)
            testChannel = true;
    }

    if(err>=0 && format.frequency() != -1) {
        err = snd_pcm_hw_params_test_rate(handle,params,format.frequency(),0);
        if(err>=0)
            err = snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir);
        if(err>=0)
            testFreq = true;
    }

    if((err>=0 && format.sampleSize() != -1) &&
            (format.sampleType() != QAudioFormat::Unknown)) {
        switch(format.sampleSize()) {
            case 8:
                if(format.sampleType() == QAudioFormat::SignedInt)
                    err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8);
                else if(format.sampleType() == QAudioFormat::UnSignedInt)
                    err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8);
                break;
            case 16:
                if(format.sampleType() == QAudioFormat::SignedInt) {
                    if(format.byteOrder() == QAudioFormat::LittleEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
                    else if(format.byteOrder() == QAudioFormat::BigEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE);
                } else if(format.sampleType() == QAudioFormat::UnSignedInt) {
                    if(format.byteOrder() == QAudioFormat::LittleEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE);
                    else if(format.byteOrder() == QAudioFormat::BigEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE);
                }
                break;
            case 32:
                if(format.sampleType() == QAudioFormat::SignedInt) {
                    if(format.byteOrder() == QAudioFormat::LittleEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE);
                    else if(format.byteOrder() == QAudioFormat::BigEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE);
                } else if(format.sampleType() == QAudioFormat::UnSignedInt) {
                    if(format.byteOrder() == QAudioFormat::LittleEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE);
                    else if(format.byteOrder() == QAudioFormat::BigEndian)
                        err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE);
                }
        }
        if(err>=0) {
            testSize = true;
            testType = true;
        }
    }
    if(err>=0)
        err = snd_pcm_hw_params(handle, params);

    if(err == 0) {
        // settings work
        // close()
        if(handle)
            snd_pcm_close(handle);
        return true;
    }
    if(handle)
        snd_pcm_close(handle);

    return false;
}
Example #24
0
/*----------------------------------------------------------------
 TIesrFA_ALSA_open

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


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

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

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

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

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

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

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


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

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


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


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



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

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

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

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

    /* Channel opened successfully */
    openSuccess = 1;


openExit:

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

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


    if( openSuccess )
        return TIesrFA_ALSAErrNone;

    return TIesrFA_ALSAErrFail;
}
Example #25
0
static snd_pcm_t *alsa_open(char *dev, int rate, int channels)
{
	snd_pcm_hw_params_t *hwp;
	snd_pcm_sw_params_t *swp;
	snd_pcm_t *h;
	int r;
	int dir;
	snd_pcm_uframes_t period_size_min;
	snd_pcm_uframes_t period_size_max;
	snd_pcm_uframes_t buffer_size_min;
	snd_pcm_uframes_t buffer_size_max;
	snd_pcm_uframes_t period_size;
	snd_pcm_uframes_t buffer_size;

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

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

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

	/* Configurue period */

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

	period_size = 1024;

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

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

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

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

	/* Configurue buffer size */

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

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

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

	r = snd_pcm_hw_params_get_buffer_size(hwp, &buffer_size);

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

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

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

	/*
	 * Software parameters
	 */

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

	r = snd_pcm_sw_params_set_avail_min(h, swp, period_size);

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

	snd_pcm_sw_params_set_start_threshold(h, swp, 0);

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

	r = snd_pcm_sw_params(h, swp);

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

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

	return h;
}
Example #26
0
static bool audio_capture_configure(uint32_t samplerate)
{
    assert(acapt_hdl != NULL);

	snd_pcm_hw_params_t *hw_params = NULL;
	snd_pcm_hw_params_alloca(&hw_params);

	int err = 0;

    /* set hardware params */
	if ((err = snd_pcm_hw_params_any(acapt_hdl, hw_params)) < 0) {
		fprintf(stderr, "ERROR: snd_pcm_hw_params_any() has failed - %s\n",
                                                            snd_strerror(err));
		return false;
	}

    /* interleaved samples */
	if ((err = snd_pcm_hw_params_set_access(acapt_hdl, hw_params,
                                        SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
		fprintf(stderr, "ERROR: snd_pcm_hw_params_set_access() has "
                                        "failed - %s\n", snd_strerror(err));
        return false;
	}

    /* 1 channel (mono) capture */
	if ((err = snd_pcm_hw_params_set_channels(acapt_hdl, hw_params, 1)) < 0) {
		fprintf(stderr, "ERROR: snd_pcm_hw_params_set_channels() has "
                                        "failed - %s\n", snd_strerror(err));
        return false;
	}

    /* 16 bit PCM samples */
	if ((err = snd_pcm_hw_params_set_format(acapt_hdl, hw_params,
                                                SND_PCM_FORMAT_S16_LE)) < 0) {
		fprintf(stderr, "ERROR: snd_pcm_hw_params_set_format() has "
                                        "failed - %s\n", snd_strerror(err));
        return false;
	}

    /* set samplerate */
	if ((err = snd_pcm_hw_params_set_rate(acapt_hdl, hw_params, samplerate, 0)) < 0) {
		fprintf(stderr, "ERROR: snd_pcm_hw_params_set_rate() has "
                                        "failed - %s\n", snd_strerror(err));
        return false;
	}

    /* apply hardware parameters */
	if ((err = snd_pcm_hw_params(acapt_hdl, hw_params)) < 0) {
		fprintf(stderr, "ERROR: snd_pcm_hw_params() has failed - %s\n\n",
                                                            snd_strerror(err));
        return false;
	}

    /* set software parameters */
	snd_pcm_sw_params_t *sw_params = NULL;
	snd_pcm_sw_params_alloca(&sw_params);

	if ((err = snd_pcm_sw_params_current(acapt_hdl, sw_params)) < 0) {
		fprintf(stderr, "ERROR: snd_pcm_sw_params_current() has failed - %s\n",
                                                            snd_strerror(err));
        return false;
	}

	if ((err = snd_pcm_sw_params_set_start_threshold(acapt_hdl,
                                                        sw_params, 0U)) < 0) {
		fprintf(stderr, "ERROR: snd_pcm_sw_params_set_start_threshold() has "
                                        "failed - %s\n", snd_strerror(err));
        return false;
	}

    /* apply software parameters */
	if ((err = snd_pcm_sw_params(acapt_hdl, sw_params)) < 0) {
		fprintf(stderr, "ERROR: snd_pcm_sw_params() has failed - %s\n",
                                                            snd_strerror(err));
        return false;
	}

    return true;
}
Example #27
0
bool WaveRecorder::init(uint32_t samples_per_sec,
                        uint32_t bits_per_sample,
                        uint32_t channels,
                        uint32_t frame_size)
{
    const char* pcm_device = "default";
    snd_pcm_format_t format;
    int err;

    _frame_size = frame_size;

    switch (bits_per_sample) {
    case 8:
        format = SND_PCM_FORMAT_S8;
        break;
    case 16:
        format = SND_PCM_FORMAT_S16_LE;
        break;
    default:
        return false;
    }

    if ((err = snd_pcm_open(&_pcm, pcm_device, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
        LOG_ERROR("cannot open audio record device %s %s", pcm_device, snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_malloc(&_hw_params)) < 0) {
        LOG_ERROR("cannot allocate hardware parameter structure %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_sw_params_malloc(&_sw_params)) < 0) {
        LOG_ERROR("cannot allocate software parameter structure %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_any(_pcm, _hw_params)) < 0) {
        LOG_ERROR("cannot initialize hardware parameter structure %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_set_rate_resample(_pcm, _hw_params, 1)) < 0) {
        LOG_ERROR("cannot set rate resample %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_set_access(_pcm, _hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
        LOG_ERROR("cannot set access type %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_set_rate(_pcm, _hw_params, samples_per_sec, 0)) < 0) {
        LOG_ERROR("cannot set sample rate %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_set_channels(_pcm, _hw_params, channels)) < 0) {
        LOG_ERROR("cannot set channel count %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_set_format(_pcm, _hw_params, format)) < 0) {
        LOG_ERROR("cannot set sample format %s", snd_strerror(err));
        return false;
    }

    int direction = 0;
    snd_pcm_uframes_t buffer_size = (samples_per_sec * 160 / 1000) / frame_size * frame_size;

    if ((err = snd_pcm_hw_params_set_buffer_size_near(_pcm, _hw_params, &buffer_size)) < 0) {
        LOG_ERROR("cannot set buffer size %s", snd_strerror(err));
        return false;
    }

    snd_pcm_uframes_t period_size = frame_size;
    if ((err = snd_pcm_hw_params_set_period_size_near(_pcm, _hw_params, &period_size,
                                                      &direction)) < 0) {
        LOG_ERROR("cannot set period size near %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params(_pcm, _hw_params)) < 0) {
        LOG_ERROR("cannot set parameters %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_sw_params_current(_pcm, _sw_params)) < 0) {
        LOG_ERROR("cannot get current sw parameters %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_sw_params_set_start_threshold(_pcm, _sw_params, frame_size)) < 0) {
        LOG_ERROR("cannot set start threshold %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_sw_params(_pcm, _sw_params)) < 0) {
        LOG_ERROR("cannot set sw parameters %s", snd_strerror(err));
        return false;
    }

    struct pollfd pfd;
    if ((err = snd_pcm_poll_descriptors(_pcm, &pfd, 1)) < 0) {
        LOG_ERROR("cannot get poll ID %s", snd_strerror(err));
        return false;
    }
    _event_trigger = new WaveRecorder::EventTrigger(*this, pfd.fd);
    _client.add_event_source(*_event_trigger);
    return true;
}
Example #28
0
File: main.c Project: texane/aspect
static int pcm_open(pcm_handle_t* pcm, const pcm_desc_t* desc)
{
  const snd_pcm_format_t fmt = SND_PCM_FORMAT_S16_LE;
  snd_pcm_stream_t stm;
  int err;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return 0;

 on_error_3:
  snd_pcm_sw_params_free(pcm->sw_params);
 on_error_2:
  snd_pcm_hw_params_free(pcm->hw_params);
 on_error_1:
  snd_pcm_close(pcm->pcm);
 on_error_0:
  return -1;
  
}
Example #29
0
static int capture(lua_State *lstate) {
	char *card;
	snd_pcm_sw_params_t *sparams;
	int ret, dir, i;
	snd_pcm_format_t f, format;
	unsigned int rate, buffer_time;
	if (rbuf == NULL) {
		rbuf = new_ringbuf(jack_sr, CHANNELS, BUFSECS,
					0.333, 0.667);
		}
	getstring(lstate, "card", &card);
	lua_pop(lstate, 1);
	for (i = 0; i < 20; i++) {
		ret = snd_pcm_open(&handle, card, SND_PCM_STREAM_CAPTURE, 0);
		if (ret < 0) {
			logmsg("can't open %s (%s)\n", card, snd_strerror(ret));
			}
		else {
			break;
			}
		}
	free(card);
	if (ret < 0) return 0;
	if (hparams != NULL) snd_pcm_hw_params_free(hparams);
	snd_pcm_hw_params_malloc(&hparams);
	snd_pcm_hw_params_any(handle, hparams);
	for (f = format = 0; f < SND_PCM_FORMAT_LAST; f++) {
		ret = snd_pcm_hw_params_test_format(handle, hparams, f);
		if (ret == 0) {
			logmsg("- %s\n", snd_pcm_format_name(f));
			format = f;
			}
		}
	ret = snd_pcm_hw_params_set_access(handle, hparams,
				SND_PCM_ACCESS_RW_INTERLEAVED);
	if (ret < 0) {
		logmsg("access %s\n", snd_strerror(ret));
		}
	ret = snd_pcm_hw_params_set_format(handle, hparams, format);
	logmsg("format: %s\n", snd_pcm_format_description(format));
	if (ret < 0) {
		logmsg("format error %s\n", snd_strerror(ret));
		}
	snd_pcm_hw_params_get_buffer_time_max(hparams, &buffer_time, 0);
	rate = jack_sr;
	ret = snd_pcm_hw_params_set_rate(handle, hparams, rate, 0);
logmsg("rate %d\n", rate);
	if (ret < 0) logmsg("rate error %s\n", snd_strerror(ret));
	snd_pcm_hw_params_set_channels(handle, hparams, CHANNELS);
	blocksize = BLOCKSIZE;
	snd_pcm_hw_params_set_period_size(handle, hparams, blocksize, 0);
logmsg("period %ld\n", blocksize);
	snd_pcm_hw_params_set_buffer_time_near(handle, hparams, &buffer_time, &dir);
logmsg("buffer time %u\n", buffer_time);
	if ((ret = snd_pcm_hw_params(handle, hparams)) < 0) {
		logmsg("can't set hardware: %s\n",
			snd_strerror(ret));
		return 0;
		}
	else logmsg("hardware configd\n");
	snd_pcm_sw_params_malloc(&sparams);
	snd_pcm_sw_params_current(handle, sparams);
	snd_pcm_sw_params_set_avail_min(handle, sparams, blocksize);
	snd_pcm_sw_params_set_start_threshold(handle, sparams, 0U);
	if ((ret = snd_pcm_sw_params(handle, sparams)) < 0) {
		logmsg("can't set software: %s\n",
			snd_strerror(ret));
		}
	else logmsg("software configd\n");
	snd_pcm_sw_params_free(sparams);
	pthread_create(&thread_id, NULL, dev_thread, NULL);
	return 0;
	}
bool QAlsaAudioDeviceInfo::testSettings(const QAudioFormat& format) const
{
    // Set nearest to closest settings that do work.
    // See if what is in settings will work (return value).
    int err = -1;
    snd_pcm_t* pcmHandle;
    snd_pcm_hw_params_t *params;
    QString dev;

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

        QString shortName = device.mid(device.indexOf(QLatin1String("="),0)+1);

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

    snd_pcm_stream_t stream = mode == QAudio::AudioOutput
                            ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE;

    if (snd_pcm_open(&pcmHandle, dev.toLocal8Bit().constData(), stream, 0) < 0)
        return false;

    snd_pcm_nonblock(pcmHandle, 0);
    snd_pcm_hw_params_alloca(&params);
    snd_pcm_hw_params_any(pcmHandle, params);

    // set the values!
    snd_pcm_hw_params_set_channels(pcmHandle, params, format.channelCount());
    snd_pcm_hw_params_set_rate(pcmHandle, params, format.sampleRate(), 0);

    snd_pcm_format_t pcmFormat = SND_PCM_FORMAT_UNKNOWN;
    switch (format.sampleSize()) {
    case 8:
        if (format.sampleType() == QAudioFormat::SignedInt)
            pcmFormat = SND_PCM_FORMAT_S8;
        else if (format.sampleType() == QAudioFormat::UnSignedInt)
            pcmFormat = SND_PCM_FORMAT_U8;
        break;
    case 16:
        if (format.sampleType() == QAudioFormat::SignedInt) {
            pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian
                      ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_S16_BE;
        } else if (format.sampleType() == QAudioFormat::UnSignedInt) {
            pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian
                      ? SND_PCM_FORMAT_U16_LE : SND_PCM_FORMAT_U16_BE;
        }
        break;
    case 32:
        if (format.sampleType() == QAudioFormat::SignedInt) {
            pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian
                      ? SND_PCM_FORMAT_S32_LE : SND_PCM_FORMAT_S32_BE;
        } else if (format.sampleType() == QAudioFormat::UnSignedInt) {
            pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian
                      ? SND_PCM_FORMAT_U32_LE : SND_PCM_FORMAT_U32_BE;
        } else if (format.sampleType() == QAudioFormat::Float) {
            pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian
                      ? SND_PCM_FORMAT_FLOAT_LE : SND_PCM_FORMAT_FLOAT_BE;
        }
    }

    if (pcmFormat != SND_PCM_FORMAT_UNKNOWN)
        err = snd_pcm_hw_params_set_format(pcmHandle, params, pcmFormat);

    // For now, just accept only audio/pcm codec
    if (!format.codec().startsWith(QLatin1String("audio/pcm")))
        err = -1;

    if (err >= 0 && format.channelCount() != -1) {
        err = snd_pcm_hw_params_test_channels(pcmHandle, params, format.channelCount());
        if (err >= 0)
            err = snd_pcm_hw_params_set_channels(pcmHandle, params, format.channelCount());
    }

    if (err >= 0 && format.sampleRate() != -1) {
        err = snd_pcm_hw_params_test_rate(pcmHandle, params, format.sampleRate(), 0);
        if (err >= 0)
            err = snd_pcm_hw_params_set_rate(pcmHandle, params, format.sampleRate(), 0);
    }

    if (err >= 0 && pcmFormat != SND_PCM_FORMAT_UNKNOWN)
        err = snd_pcm_hw_params_set_format(pcmHandle, params, pcmFormat);

    if (err >= 0)
        err = snd_pcm_hw_params(pcmHandle, params);

    snd_pcm_close(pcmHandle);

    return (err == 0);
}