Beispiel #1
0
snd_pcm_t *open_pcm(char *pcm_name) {

    snd_pcm_t *playback_handle;
    snd_pcm_hw_params_t *hw_params;
    snd_pcm_sw_params_t *sw_params;
            
    if (snd_pcm_open (&playback_handle, pcm_name, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
        fprintf (stderr, "cannot open audio device %s\n", pcm_name);
        exit (1);
    }
    snd_pcm_hw_params_alloca(&hw_params);
    snd_pcm_hw_params_any(playback_handle, hw_params);
    snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE);
    snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, 44100, 0);
    snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2);
    snd_pcm_hw_params_set_periods(playback_handle, hw_params, 2, 0);
    snd_pcm_hw_params_set_period_size(playback_handle, hw_params, BUFSIZE, 0);
    snd_pcm_hw_params(playback_handle, hw_params);
    snd_pcm_sw_params_alloca(&sw_params);
    snd_pcm_sw_params_current(playback_handle, sw_params);
    snd_pcm_sw_params_set_avail_min(playback_handle, sw_params, BUFSIZE);
    snd_pcm_sw_params(playback_handle, sw_params);
    return(playback_handle);
}
Beispiel #2
0
static void alsa_set_hw_params(struct alsa_dev *dev, snd_pcm_t *handle,
			       unsigned int rate, int channels, int period)
{
	int dir, ret;
	snd_pcm_uframes_t period_size;
	snd_pcm_uframes_t buffer_size;
	snd_pcm_hw_params_t *hw_params;

	ret = snd_pcm_hw_params_malloc(&hw_params);
	if (ret < 0)
		syslog_panic("Cannot allocate hardware parameters: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params_any(handle, hw_params);
	if (ret < 0)
		syslog_panic("Cannot initialize hardware parameters: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params_set_access(handle, hw_params,
					   SND_PCM_ACCESS_RW_INTERLEAVED);
	if (ret < 0)
		syslog_panic("Cannot set access type: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params_set_format(handle, hw_params,
					   SND_PCM_FORMAT_S16_LE);
	if (ret < 0)
		syslog_panic("Cannot set sample format: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params_set_rate_near(handle, hw_params, &rate, 0);
	if (ret < 0)
		syslog_panic("Cannot set sample rate: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params_set_channels(handle, hw_params, channels);
	if (ret < 0)
		syslog_panic("Cannot set channel number: %s\n",
			     snd_strerror(ret));
	period_size = period;
	dir = 0;
	ret = snd_pcm_hw_params_set_period_size_near(handle, hw_params,
						     &period_size, &dir);
	if (ret < 0)
		syslog_panic("Cannot set period size: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params_set_periods(handle, hw_params, PERIODS, 0);
	if (ret < 0)
		syslog_panic("Cannot set period number: %s\n",
			     snd_strerror(ret));
	buffer_size = period_size * PERIODS;
	dir = 0;
	ret = snd_pcm_hw_params_set_buffer_size_near(handle, hw_params,
						     &buffer_size);
	if (ret < 0)
		syslog_panic("Cannot set buffer size: %s\n",
			     snd_strerror(ret));
	ret = snd_pcm_hw_params(handle, hw_params);
	if (ret < 0)
		syslog_panic("Cannot set capture parameters: %s\n",
			     snd_strerror(ret));
	snd_pcm_hw_params_free(hw_params);
}
Beispiel #3
0
static int
setup_playback(void)
{
	int         err;
	snd_pcm_hw_params_t *pcm_params;

	if ((err = snd_pcm_hw_params_malloc(&pcm_params)) < 0 ||
		(err = snd_pcm_hw_params_any(pcm_handle, pcm_params)) < 0 ||
		(err = snd_pcm_hw_params_set_access(pcm_handle, pcm_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0 ||
		(err = snd_pcm_hw_params_set_format(pcm_handle, pcm_params, pcm_format)) < 0 ||
		(err = snd_pcm_hw_params_set_rate_near(pcm_handle, pcm_params, &pcm_hz, 0)) < 0 ||
		(err = snd_pcm_hw_params_set_channels(pcm_handle, pcm_params, 1)) < 0)
	{
		module_logger(&alsaSound, _L|LOG_USER | LOG_ERROR, _("params setup error: %s\n"),
			 snd_strerror(err));
		return 0;
	}

#if 0
	// ???
	pcm_samplesize = pcm_periodsize * pcm_periods / pcm_framesize;

	if ((err = snd_pcm_hw_params_set_periods(pcm_handle, pcm_params, pcm_periods, 0)) < 0 ||
		(err = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, pcm_params, &pcm_samplesize)) < 0) {
		module_logger(&alsaSound, _L|LOG_USER | LOG_ERROR, _("cannot set up period size: %s\n"),
			 snd_strerror(err));
		// continue
	}

	samplebuf = (s8 *) malloc(pcm_samplesize * pcm_framesize);
#else

	pcm_samplesize = pcm_periodsize;
	samplebuf = (s16 *) malloc(pcm_samplesize * sizeof(samplebuf[0]));
#endif

	if ((err = snd_pcm_hw_params(pcm_handle, pcm_params)) < 0) {
		module_logger(&alsaSound, _L|LOG_USER | LOG_ERROR, _("params setting error: %s\n"),
			 snd_strerror(err));
		return 0;
	}

	snd_pcm_hw_params_free(pcm_params);

	if ((err = snd_pcm_prepare(pcm_handle)) < 0) {
		module_logger(&alsaSound, _L|LOG_USER | LOG_ERROR, _("error preparing PCM handle\n"),
			 snd_strerror(err));
		return 0;
	}


	return 1;
}
Beispiel #4
0
int audio_drv_init(void)
{
	unsigned int rate = 44100;
	int err;
	snd_pcm_hw_params_t *hw_params;

	if ((err = snd_pcm_open(&playback_handle, "hw", 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_near(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, 4096, 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;
}
Beispiel #5
0
snd_pcm_t *open_pcm(char *pcm_name) {
    snd_pcm_t *playback_handle;
    snd_pcm_hw_params_t *hw_params;
    snd_pcm_sw_params_t *sw_params;
    if (snd_pcm_open (&playback_handle, pcm_name, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
        fprintf (stderr, "cannot open audio device %s\n", pcm_name);
      return NULL;//it seems greedy and wants exclusive control?!
    }
    snd_pcm_hw_params_alloca(&hw_params);
    snd_pcm_hw_params_any(playback_handle, hw_params);
    snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE);
    snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &rate, 0);
    snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2);
    snd_pcm_hw_params_set_periods(playback_handle, hw_params, 2, 0);
    snd_pcm_hw_params_set_period_size(playback_handle, hw_params, BUFSAMPS, 0);
    snd_pcm_hw_params(playback_handle, hw_params);
    snd_pcm_sw_params_alloca(&sw_params);
    snd_pcm_sw_params_current(playback_handle, sw_params);
    snd_pcm_sw_params_set_avail_min(playback_handle, sw_params, BUFSAMPS);
    snd_pcm_sw_params(playback_handle, sw_params);
    return(playback_handle);
}
Beispiel #6
0
/* ------- PCM INITS --------------------------------- */
static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params,int *chs)
{
#ifndef ALSAAPI9
  unsigned int rrate;
  int err, dir;
  int channels_allocated = 0;

  /* choose all parameters */
  err = snd_pcm_hw_params_any(handle, params);
  if (err < 0) {
    check_error(err,"Broken configuration: no configurations available");
    return err;
  }

  /* set the nointerleaved read/write format */
  err = snd_pcm_hw_params_set_access(handle, params,
                                     SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
  if (err >= 0) {
#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("Access type %s available","SND_PCM_ACCESS_MMAP_NONINTERLEAVED");
#endif
  }
  else{
    check_error(err,"No Accesstype SND_PCM_ACCESS_MMAP_NONINTERLEAVED");
    return err;
  }

  /* set the sample format */
  err = snd_pcm_hw_params_set_format(handle, params, ALSAMM_FORMAT);
  if (err < 0) {
    check_error(err,"Sample format not available for playback");
    return err;
  }

#ifdef ALSAMM_DEBUG
  if(sys_verbose)
    post("Setting format to %s",snd_pcm_format_name(ALSAMM_FORMAT));
#endif

  /* first check samplerate since channels numbers
     are samplerate dependent (double speed) */
  /* set the stream rate */

  rrate = alsamm_sr;

#ifdef ALSAMM_DEBUG
  if(sys_verbose)
    post("Samplerate request: %i Hz",rrate);
#endif

  dir=-1;
  err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, &dir);
  if (err < 0) {
    check_error(err,"Rate not available");
    return err;
  }

  if (rrate != alsamm_sr) {
    post("Warning: rate %iHz doesn't match requested %iHz", rrate,alsamm_sr);
    alsamm_sr = rrate;
  }
  else
    if(sys_verbose)
      post("Samplerate is set to %iHz",alsamm_sr);

  /* Info on channels */
  {
    int maxchs,minchs,channels = *chs;

    if((err = snd_pcm_hw_params_get_channels_max(params,
        (unsigned int *)&maxchs)) < 0){
      check_error(err,"Getting channels_max not available");
      return err;
    }
    if((err = snd_pcm_hw_params_get_channels_min(params,
        (unsigned int *)&minchs)) < 0){
      check_error(err,"Getting channels_min not available");
      return err;
    }

#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("Getting channels:min=%d, max= %d for request=%d",minchs,maxchs,channels);
#endif
    if(channels < 0)channels=maxchs;
    if(channels > maxchs)channels = maxchs;
    if(channels < minchs)channels = minchs;

    if(channels != *chs)
      post("requested channels=%d but used=%d",*chs,channels);

    *chs = channels;
#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("trying to use channels: %d",channels);
#endif
  }

  /* set the count of channels */
  err = snd_pcm_hw_params_set_channels(handle, params, *chs);
  if (err < 0) {
    check_error(err,"Channels count not available");
    return err;
  }

  /* testing for channels */
  if((err = snd_pcm_hw_params_get_channels(params,(unsigned int *)chs)) < 0)
    check_error(err,"Get channels not available");
#ifdef ALSAMM_DEBUG
  else
    if(sys_verbose)
      post("When setting channels count and got %d",*chs);
#endif

  /* if buffersize is set use this instead buffertime */
  if(alsamm_buffersize > 0){

#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("hw_params: ask for max buffersize of %d samples",
           (unsigned int) alsamm_buffersize );
#endif

    alsamm_buffer_size = alsamm_buffersize;

    err = snd_pcm_hw_params_set_buffer_size_near(handle, params,
        (unsigned long *)&alsamm_buffer_size);
    if (err < 0) {
      check_error(err,"Unable to set max buffer size");
      return err;
    }

  }
  else{
    if(alsamm_buffertime <= 0) /* should never happen, but use 20ms */
      alsamm_buffertime = 20000;

#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("hw_params: ask for max buffertime of %d ms",
           (unsigned int) (alsamm_buffertime*0.001) );
#endif

    err = snd_pcm_hw_params_set_buffer_time_near(handle, params,
        &alsamm_buffertime, &dir);
    if (err < 0) {
      check_error(err,"Unable to set max buffer time");
      return err;
    }
  }

  err = snd_pcm_hw_params_get_buffer_time(params,
    (unsigned int *)&alsamm_buffertime, &dir);
  if (err < 0) {
    check_error(err,"Unable to get buffer time");
    return err;
  }

#ifdef ALSAMM_DEBUG
  if(sys_verbose)
    post("hw_params: got buffertime to %f ms",
         (float) (alsamm_buffertime*0.001));
#endif

  err = snd_pcm_hw_params_get_buffer_size(params,
    (unsigned long *)&alsamm_buffer_size);
  if (err < 0) {
    check_error(err,"Unable to get buffer size");
    return err;
  }

#ifdef ALSAMM_DEBUG
  if(sys_verbose)
    post("hw_params: got  buffersize to %d samples",(int) alsamm_buffer_size);
#endif

  err = snd_pcm_hw_params_get_period_size(params,
    (unsigned long *)&alsamm_period_size, &dir);
  if (err > 0) {
    check_error(err,"Unable to get period size");
    return err;
  }

#ifdef ALSAMM_DEBUG
  if(sys_verbose)
    post("Got period size of %d", (int) alsamm_period_size);
#endif
  {
    unsigned int pmin,pmax;

    err = snd_pcm_hw_params_get_periods_min(params, &pmin, &dir);
    if (err > 0) {
      check_error(err,"Unable to get period size");
      return err;
    }
    err = snd_pcm_hw_params_get_periods_min(params, &pmax, &dir);
    if (err > 0) {
      check_error(err,"Unable to get period size");
      return err;
    }

    /* use maximum of periods */
    if( alsamm_periods <= 0)
      alsamm_periods = pmax;
    alsamm_periods = (alsamm_periods > pmax)?pmax:alsamm_periods;
    alsamm_periods = (alsamm_periods < pmin)?pmin:alsamm_periods;

    err = snd_pcm_hw_params_set_periods(handle, params, alsamm_periods, dir);
    if (err > 0) {
      check_error(err,"Unable to set periods");
      return err;
    }


    err = snd_pcm_hw_params_get_periods(params, &pmin, &dir);
    if (err > 0) {
      check_error(err,"Unable to get periods");
      return err;
    }
#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("Got periods of %d, where periodsmin=%d, periodsmax=%d",
           alsamm_periods,pmin,pmax);
#endif
  }

  /* write the parameters to device */
  err = snd_pcm_hw_params(handle, params);
  if (err < 0) {
    check_error(err,"Unable to set hw params");
    return err;
  }
#endif /* ALSAAPI9 */
  return 0;
}
    /**
     * Create and initialize Alsa audio output device with given parameters.
     *
     * @param Parameters - optional parameters
     * @throws AudioOutputException  if output device cannot be opened
     */
    AudioOutputDeviceAlsa::AudioOutputDeviceAlsa(std::map<String,DeviceCreationParameter*> Parameters) : AudioOutputDevice(Parameters), Thread(true, true, 1, 0) {
        pcm_handle           = NULL;
        stream               = SND_PCM_STREAM_PLAYBACK;
        this->uiAlsaChannels = ((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt();
        this->uiSamplerate   = ((DeviceCreationParameterInt*)Parameters["SAMPLERATE"])->ValueAsInt();
        this->FragmentSize   = ((DeviceCreationParameterInt*)Parameters["FRAGMENTSIZE"])->ValueAsInt();
        uint Fragments       = ((DeviceCreationParameterInt*)Parameters["FRAGMENTS"])->ValueAsInt();
        String Card          = ((DeviceCreationParameterString*)Parameters["CARD"])->ValueAsString();

        dmsg(2,("Checking if hw parameters supported...\n"));
        if (HardwareParametersSupported(Card, uiAlsaChannels, uiSamplerate, Fragments, FragmentSize)) {
            pcm_name = "hw:" + Card;
        }
        else {
            fprintf(stderr, "Warning: your soundcard doesn't support chosen hardware parameters; ");
            fprintf(stderr, "trying to compensate support lack with plughw...");
            fflush(stdout);
            pcm_name = "plughw:" + Card;
        }
        dmsg(2,("HW check completed.\n"));

        int err;

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

        /* 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.c_str(), stream, 0)) < 0) {
            throw AudioOutputException(String("Error opening PCM device ") + pcm_name + ": " + snd_strerror(err));
        }

        if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
            throw AudioOutputException(String("Error, cannot initialize hardware parameter structure: ") + snd_strerror(err));
        }

        /* Set access type. This can be either    */
        /* SND_PCM_ACCESS_RW_INTERLEAVED or       */
        /* SND_PCM_ACCESS_RW_NONINTERLEAVED.      */
        if ((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
            throw AudioOutputException(String("Error snd_pcm_hw_params_set_access: ") + snd_strerror(err));
        }

        /* Set sample format */
        #if WORDS_BIGENDIAN
        if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE)) < 0)
        #else // little endian
        if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0)
        #endif
        {
            throw AudioOutputException(String("Error setting sample format: ") + snd_strerror(err));
        }

        int dir = 0;

        /* Set sample rate. If the exact rate is not supported */
        /* by the hardware, use nearest possible rate.         */
        #if ALSA_MAJOR > 0
        if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &uiSamplerate, &dir)) < 0)
        #else
        if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, uiSamplerate, &dir)) < 0)
        #endif
        {
            throw AudioOutputException(String("Error setting sample rate: ") + snd_strerror(err));
        }

        if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, uiAlsaChannels)) < 0) {
            throw AudioOutputException(String("Error setting number of channels: ") + snd_strerror(err));
        }

        /* Set number of periods. Periods used to be called fragments. */
        if ((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, Fragments, dir)) < 0) {
            throw AudioOutputException(String("Error setting number of ") + ToString(Fragments) + " periods: " + snd_strerror(err));
        }

        /* Set buffer size (in frames). The resulting latency is given by */
        /* latency = periodsize * periods / (rate * bytes_per_frame)     */
        if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (FragmentSize * Fragments))) < 0) {
            throw AudioOutputException(String("Error setting buffersize: ") + snd_strerror(err));
        }

        /* Apply HW parameter settings to */
        /* PCM device and prepare device  */
        if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
            throw AudioOutputException(String("Error setting HW params: ") + snd_strerror(err));
        }

        if (snd_pcm_sw_params_malloc(&swparams) != 0) {
            throw AudioOutputException(String("Error in snd_pcm_sw_params_malloc: ") + snd_strerror(err));
        }

        if (snd_pcm_sw_params_current(pcm_handle, swparams) != 0) {
            throw AudioOutputException(String("Error in snd_pcm_sw_params_current: ") + snd_strerror(err));
        }

        if (snd_pcm_sw_params_set_stop_threshold(pcm_handle, swparams, 0xffffffff) != 0) {
            throw AudioOutputException(String("Error in snd_pcm_sw_params_set_stop_threshold: ") + snd_strerror(err));
        }

        if (snd_pcm_sw_params(pcm_handle, swparams) != 0) {
            throw AudioOutputException(String("Error in snd_pcm_sw_params: ") + snd_strerror(err));
        }

        if ((err = snd_pcm_prepare(pcm_handle)) < 0) {
            throw AudioOutputException(String("Error snd_pcm_prepare: ") + snd_strerror(err));
        }

        // allocate Alsa output buffer
        pAlsaOutputBuffer = new int16_t[uiAlsaChannels * FragmentSize];

        // create audio channels for this audio device to which the sampler engines can write to
        for (int i = 0; i < uiAlsaChannels; i++) this->Channels.push_back(new AudioChannel(i, FragmentSize));

	if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) {
		Play();
	}
    }
Beispiel #8
0
int AlsaIO::Initialize(uint Channels, uint Samplerate, uint Fragments, uint FragmentSize, String Card) {
    this->uiChannels           = Channels;
    this->uiSamplerate         = Samplerate;
    this->uiMaxSamplesPerCycle = FragmentSize;
    this->bInterleaved         = true;

    if (HardwareParametersSupported(Channels, Samplerate, Fragments, FragmentSize)) {
        pcm_name = "hw:" + Card;
    }
    else {
        printf("Warning: your soundcard doesn't support chosen hardware parameters; ");
        printf("trying to compensate support lack with plughw...");
        fflush(stdout);
        pcm_name = "plughw:" + Card;
    }

    int err;

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

    /* 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.c_str(), stream, 0)) < 0) {
        fprintf(stderr, "Error opening PCM device %s: %s\n", pcm_name.c_str(), snd_strerror(err));
        return -1;
    }

    if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
        fprintf(stderr, "Error, cannot initialize hardware parameter structure: %s.\n", snd_strerror(err));
        return -1;
    }

    /* Set access type. This can be either    */
    /* SND_PCM_ACCESS_RW_INTERLEAVED or       */
    /* SND_PCM_ACCESS_RW_NONINTERLEAVED.      */
    if ((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
        fprintf(stderr, "Error snd_pcm_hw_params_set_access: %s.\n", snd_strerror(err));
        return -1;
    }

    /* Set sample format */
    #if WORDS_BIGENDIAN
    if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE)) < 0) {
    #else // little endian
    if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0) {
    #endif
        fprintf(stderr, "Error setting sample format. : %s\n", snd_strerror(err));
        return -1;
    }

    int dir = 0;

    /* Set sample rate. If the exact rate is not supported */
    /* by the hardware, use nearest possible rate.         */
    #if ALSA_MAJOR > 0
    if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &Samplerate, &dir)) < 0) {
    #else
    if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, Samplerate, &dir)) < 0) {
    #endif
        fprintf(stderr, "Error setting sample rate. : %s\n", snd_strerror(err));
        return -1;
    }

    if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, Channels)) < 0) {
        fprintf(stderr, "Error setting number of channels. : %s\n", 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, Fragments, dir)) < 0) {
        fprintf(stderr, "Error setting number of periods. : %s\n", snd_strerror(err));
        return -1;
    }

    /* Set buffer size (in frames). The resulting latency is given by */
    /* latency = periodsize * periods / (rate * bytes_per_frame)     */
    if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (FragmentSize * Fragments))) < 0) {
        fprintf(stderr, "Error setting buffersize. : %s\n", 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) {
        fprintf(stderr, "Error setting HW params. : %s\n", snd_strerror(err));
        return -1;
    }

    if (snd_pcm_sw_params_malloc(&swparams) != 0) {
        fprintf(stderr, "Error in snd_pcm_sw_params_malloc. : %s\n", snd_strerror(err));
        return -1;
    }

    if (snd_pcm_sw_params_current(pcm_handle, swparams) != 0) {
        fprintf(stderr, "Error in snd_pcm_sw_params_current. : %s\n", snd_strerror(err));
        return -1;
    }

    if (snd_pcm_sw_params_set_stop_threshold(pcm_handle, swparams, 0xffffffff) != 0) {
        fprintf(stderr, "Error in snd_pcm_sw_params_set_stop_threshold. : %s\n", snd_strerror(err));
        return -1;
    }

    if (snd_pcm_sw_params(pcm_handle, swparams) != 0) {
        fprintf(stderr, "Error in snd_pcm_sw_params. : %s\n", snd_strerror(err));
        return -1;
    }

    if ((err = snd_pcm_prepare(pcm_handle)) < 0) {
        fprintf(stderr, "Error snd_pcm_prepare : %s\n", snd_strerror(err));
        return -1;
    }

    // allocate the audio output buffer
    pOutputBuffer = new int16_t[Channels * FragmentSize];
    
    this->bInitialized = true;

    return 0;
}

/**
 *  Checks if sound card supports the chosen parameters.
 *
 *  @returns  true if hardware supports it
 */
bool AlsaIO::HardwareParametersSupported(uint channels, int samplerate, uint numfragments, uint fragmentsize) {
    pcm_name = "hw:0,0";
    if (snd_pcm_open(&pcm_handle, pcm_name.c_str(), stream, 0) < 0) return false;
    snd_pcm_hw_params_alloca(&hwparams);
    if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
        snd_pcm_close(pcm_handle);
        return false;
    }
    if (snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
        snd_pcm_close(pcm_handle);
        return false;
    }
    #if WORDS_BIGENDIAN
    if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE) < 0) {
    #else // little endian
    if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) {
    #endif
        snd_pcm_close(pcm_handle);
        return false;
    }
    int dir = 0;
    if (snd_pcm_hw_params_test_rate(pcm_handle, hwparams, samplerate, dir) < 0) {
        snd_pcm_close(pcm_handle);
        return false;
    }
    if (snd_pcm_hw_params_test_channels(pcm_handle, hwparams, channels) < 0) {
        snd_pcm_close(pcm_handle);
        return false;
    }
    if (snd_pcm_hw_params_test_periods(pcm_handle, hwparams, numfragments, dir) < 0) {
        snd_pcm_close(pcm_handle);
        return false;
    }
    if (snd_pcm_hw_params_test_buffer_size(pcm_handle, hwparams, (fragmentsize * numfragments)) < 0) {
        snd_pcm_close(pcm_handle);
        return false;
    }

    snd_pcm_close(pcm_handle);
    return true;
}

void AlsaIO::Activate() {
    this->StartThread();
}

int AlsaIO::Main() {
    if (!pEngine) {
        fprintf(stderr, "AlsaIO: No Sampler Engine assigned, exiting.\n");
        exit(EXIT_FAILURE);
    }
    if (!bInitialized) {
        fprintf(stderr, "AlsaIO: Not yet intitialized, exiting.\n");
        exit(EXIT_FAILURE);
    }

    while (true) {

        // let the engine render audio for the current audio fragment
        pEngine->RenderAudio(uiMaxSamplesPerCycle);


        // check clipping in the audio sum, convert to sample_type
        // (from 32bit to 16bit sample) and copy to output buffer
        float sample_point; uint o = 0;
        for (uint s = 0; s < uiMaxSamplesPerCycle; s++) {
            for (uint c = 0; c < uiChannels; c++) {
                sample_point = pEngine->GetAudioSumBuffer(c)[s] * pEngine->Volume;
                if (sample_point < -32768.0) sample_point = -32768.0;
                if (sample_point >  32767.0) sample_point =  32767.0;
                this->pOutputBuffer[o++] = (int32_t) sample_point;
            }
        }


        // output sound
        int res = Output();
        if (res < 0) {
            fprintf(stderr, "AlsaIO: Audio output error, exiting.\n");
            exit(EXIT_FAILURE);
        }
    }
}

/**
 *  Will be called after every audio fragment cycle, to output the audio data
 *  of the current fragment to the soundcard.
 *
 *  @returns  0 on success
 */
int AlsaIO::Output() {
    int err = snd_pcm_writei(pcm_handle, pOutputBuffer, uiMaxSamplesPerCycle);
    if (err < 0) {
        fprintf(stderr, "Error snd_pcm_writei failed. : %s\n", snd_strerror(err));
        return -1;
    }
    return 0;
}

void AlsaIO::Close() {
    if (bInitialized) {
        //dmsg(0,("Stopping Alsa Thread..."));
        //StopThread();  //FIXME: commented out due to a bug in thread.cpp (StopThread() doesn't return at all)
        //dmsg(0,("OK\n"));
        if (pcm_handle) {
            //FIXME: currently commented out due to segfault
            //snd_pcm_close(pcm_handle);
            pcm_handle = NULL;
        }
        if (pOutputBuffer) {
            //FIXME: currently commented out due to segfault
            //delete[] pOutputBuffer;
            pOutputBuffer = NULL;
        }
        bInitialized = false;
    }
}

void* AlsaIO::GetInterleavedOutputBuffer() {
    return pOutputBuffer;
}

void* AlsaIO::GetChannelOutputBufer(uint Channel) {
    fprintf(stderr, "AlsaIO::GetChannelOutputBufer(): Only interleaved access allowed so far, exiting.\n");
    exit(EXIT_FAILURE);
    // just to avoid compiler warnings
    return NULL;
}
Beispiel #9
0
static void* sound_thread(void* context)
{
    struct SPU* c = (struct SPU*)context;
    int div;
    snd_pcm_t* snd;
    snd_pcm_hw_params_t* hwp;
    int rate = c->sampling;
    int periods = 3;
    snd_pcm_hw_params_alloca(&hwp);
    if (snd_pcm_open(&snd, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0) {
        return NULL;
    }
    if (snd_pcm_hw_params_any(snd, hwp) < 0) {
        return NULL;
    }
    div = c->bit / 8;
    switch (c->bit) {
        case 8:
            if (snd_pcm_hw_params_set_format(snd, hwp, SND_PCM_FORMAT_U8) < 0) {
                return NULL;
            }
            break;
        case 16:
            if (snd_pcm_hw_params_set_format(snd, hwp, SND_PCM_FORMAT_S16_LE) < 0) {
                return NULL;
            }
            break;
        case 24:
            if (snd_pcm_hw_params_set_format(snd, hwp, SND_PCM_FORMAT_S24_LE) < 0) {
                return NULL;
            }
            break;
        case 32:
            if (snd_pcm_hw_params_set_format(snd, hwp, SND_PCM_FORMAT_S32_LE) < 0) {
                return NULL;
            }
            break;
        default:
            return NULL;
    }
    if (snd_pcm_hw_params_set_rate_near(snd, hwp, &rate, 0) < 0) {
        return NULL;
    }
    if (rate != SAMPLE_RATE) {
        return NULL;
    }
    if (snd_pcm_hw_params_set_channels(snd, hwp, c->ch) < 0) {
        return NULL;
    }
    if (snd_pcm_hw_params_set_periods(snd, hwp, periods, 0) < 0) {
        return NULL;
    }
    if (snd_pcm_hw_params_set_buffer_size(snd, hwp, (periods * c->size) / 4) < 0) {
        return NULL;
    }
    if (snd_pcm_hw_params(snd, hwp) < 0) {
        return NULL;
    }
    while (c->alive) {
        c->callback(c->buffer, c->size);
        while (c->alive) {
            if (snd_pcm_writei(snd, c->buffer, c->size / div) < 0) {
                snd_pcm_prepare(snd);
            } else {
                break;
            }
        }
    }
    snd_pcm_drain(snd);
    snd_pcm_close(snd);
    return NULL;
}
Beispiel #10
0
    void PCMThread::init()
    {
        snd_pcm_t* pcm_handle;
        snd_pcm_hw_params_t* hwparams;
        snd_pcm_uframes_t buffersize_return;
        unsigned int tmp;
        int err;

        std::unique_ptr<PCMHandle> spPCMHandle {new PCMHandle {spSettings_->pcmName_, SND_PCM_STREAM_CAPTURE}};
        QObject::connect (spPCMHandle.get(), &PCMThread::PCMHandle::sigDebug, this, &PCMThread::slotDebug);

        snd_pcm_hw_params_alloca (&hwparams);

        if ( (err = snd_pcm_hw_params_any (*spPCMHandle, hwparams)) < 0)
            throw std::runtime_error (snd_strerror (err));

        if ( (err = snd_pcm_hw_params_set_access (*spPCMHandle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
            throw std::runtime_error (snd_strerror (err));

        if ( (err = snd_pcm_hw_params_set_format (*spPCMHandle, hwparams, SND_PCM_FORMAT_FLOAT)) < 0)
            throw std::runtime_error (snd_strerror (err));

        tmp = spSettings_->rate_;

        if ( (err = snd_pcm_hw_params_set_rate_near (*spPCMHandle, hwparams, &tmp, 0)) < 0)
            throw std::runtime_error (snd_strerror (err));

        tmp = spSettings_->channels_;

        if ( (err = snd_pcm_hw_params_set_channels (*spPCMHandle, hwparams, tmp)) < 0)
            throw std::runtime_error (snd_strerror (err));

        tmp = spSettings_->periods_;

        if ( (err = snd_pcm_hw_params_set_periods (*spPCMHandle, hwparams, tmp, 0)) < 0)
            throw std::runtime_error (snd_strerror (err));

        buffersize_return = spSettings_->periodSize_ * spSettings_->periods_;

        if ( (err = snd_pcm_hw_params_set_buffer_size_near (*spPCMHandle, hwparams, &buffersize_return)) < 0)
            throw std::runtime_error (snd_strerror (err));

        if (buffersize_return != static_cast<snd_pcm_uframes_t> (spSettings_->periodSize_ * spSettings_->periods_))
        {
            DebugHelper dbgHelper;
            dbgHelper << "Period size " << spSettings_->periodSize_ << " not available, using " << 
                            buffersize_return / spSettings_->periods_;
            emit sigDebug (dbgHelper.string());
            periodSize_ = buffersize_return / spSettings_->periods_;
        }
        else
        {
            periodSize_ = spSettings_->periodSize_;
        }

        if ( (err = snd_pcm_hw_params (*spPCMHandle, hwparams)) < 0)
            throw std::runtime_error (snd_strerror (err));

        spPCMHandle_ = std::move (spPCMHandle);
        emit sigDebug ("Initialized : " + QString::fromStdString (spSettings_->pcmName_));
    }
Beispiel #11
0
static void Wav_handler(Instance *pi, void *data)
{
  ALSAio_private *priv = (ALSAio_private *)pi;
  Wav_buffer *wav_in = data;
  int state;
  int dir = 0;
  int rc;
  //int i;
  snd_pcm_sframes_t n;

  if (!priv->c.enable) {
    return;
  }

  if (!priv->c.rate) {
    /* Set rate. */
    char channels[32];
    char rate[32];
    sprintf(rate, "%d", wav_in->params.rate);
    set_rate(pi, rate);

    /* Set channels. */
    sprintf(channels, "%d", wav_in->params.channels);
    set_channels(pi, channels);

    /* Set format */
    snd_pcm_format_t format = ALSAio_bps_to_snd_fmt(wav_in->params.bits_per_sample);
    if (format != SND_PCM_FORMAT_UNKNOWN) {
      priv->c.format = format;
      rc = snd_pcm_hw_params_set_format(priv->c.handle, priv->c.hwparams, priv->c.format);
      if (rc < 0) {
        fprintf(stderr, "*** %s: snd_pcm_hw_params_set_format %s: %s\n", __func__,
                s(priv->c.device), snd_strerror(rc));
      }
    }
  }

  state = snd_pcm_state(priv->c.handle);
  dpf("%s: state(1)=%s\n", __func__, ALSAio_state_to_string(state));

  if (state == SND_PCM_STATE_OPEN || state == SND_PCM_STATE_SETUP) {
    /* One time playback setup. */

    /* FIXME: Why does 64 work on NVidia CK804 with "snd_intel8x0"
       driver, but not 32, 128, 2048?  How to find out what will
       work? */
    snd_pcm_uframes_t frames =  priv->c.frames_per_io;

    fprintf(stderr, "%s: state=%s\n", __func__, ALSAio_state_to_string(state));

    rc = snd_pcm_hw_params_set_period_size_near(priv->c.handle, priv->c.hwparams, &frames, &dir);
    fprintf(stderr, "set_period_size_near returns %d (frames=%d)\n", rc, (int)frames);

    int periods = 4;

    rc = snd_pcm_hw_params_set_periods(priv->c.handle, priv->c.hwparams, periods, 0);
    if (rc < 0) {
      fprintf(stderr, "*** snd_pcm_hw_params_set_periods %s: %s\n", s(priv->c.device), snd_strerror(rc));
    }

    rc = snd_pcm_hw_params(priv->c.handle, priv->c.hwparams);
    if (rc < 0) {
      fprintf(stderr, "*** snd_pcm_hw_params %s: %s\n", s(priv->c.device), snd_strerror(rc));
    }

    state = snd_pcm_state(priv->c.handle);
    fprintf(stderr, "%s: state=%s\n", __func__, ALSAio_state_to_string(state));

    rc = snd_pcm_prepare(priv->c.handle);
    state = snd_pcm_state(priv->c.handle);
    fprintf(stderr, "%s: state=%s\n", __func__, ALSAio_state_to_string(state));
  }

  dpf("%s: state(2)=%s\n", __func__, ALSAio_state_to_string(state));

  int out_frames = wav_in->data_length / (priv->c.channels * priv->c.format_bytes);
  int frames_written = 0;
  while (1) {
    n = snd_pcm_writei(priv->c.handle, (uint8_t*)wav_in->data + (frames_written * (priv->c.channels * priv->c.format_bytes)),
                       out_frames);
    if (n > 0) {
      out_frames -= n;
      frames_written += n;
    }
    else {
      break;
    }
  }

  if (n < 0) {
    fprintf(stderr, "*** snd_pcm_writei %s: %s\n", s(priv->c.device), snd_strerror((int)n));
    fprintf(stderr, "*** attempting snd_pcm_prepare() to correct...\n");
    snd_pcm_prepare(priv->c.handle);
  }

  if (wav_in->no_feedback == 0  /* The default is 0, set to 1 if "filler" code below is called. */
      && pi->outputs[OUTPUT_FEEDBACK].destination) {
    Feedback_buffer *fb = Feedback_buffer_new();
    fb->seq = wav_in->seq;
    PostData(fb, pi->outputs[OUTPUT_FEEDBACK].destination);
  }

  Wav_buffer_release(&wav_in);
}
Beispiel #12
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;
}
AlsaDevice *alsa_device_open(char *device_name, unsigned int rate, int channels, int period)
{
   int dir;
   int err;
   snd_pcm_hw_params_t *hw_params;
   snd_pcm_sw_params_t *sw_params;
   snd_pcm_uframes_t period_size = period;
   snd_pcm_uframes_t buffer_size = PERIODS*period;
   static snd_output_t *jcd_out;
   AlsaDevice *dev = malloc(sizeof(*dev));
   if (!dev)
      return NULL;
   dev->device_name = malloc(1+strlen(device_name));
   if (!dev->device_name)
   {
      free(dev);
      return NULL;
   }
   strcpy(dev->device_name, device_name);
   dev->channels = channels;
   dev->period = period;
   err = snd_output_stdio_attach(&jcd_out, stdout, 0);
   
   if ((err = snd_pcm_open (&dev->capture_handle, dev->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
      fprintf (stderr, "cannot open audio device %s (%s)\n",
               dev->device_name,
               snd_strerror (err));
      assert(0);
   }

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

   dev->read_fd = malloc(dev->readN*sizeof(*dev->read_fd));
   /*printf ("descriptors: %d %d\n", dev->readN, dev->writeN);*/
   if (snd_pcm_poll_descriptors(dev->capture_handle, dev->read_fd, dev->readN) != dev->readN)
   {
      fprintf (stderr, "cannot obtain capture file descriptors (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   dev->write_fd = malloc(dev->writeN*sizeof(*dev->read_fd));
   if (snd_pcm_poll_descriptors(dev->playback_handle, dev->write_fd, dev->writeN) != dev->writeN)
   {
      fprintf (stderr, "cannot obtain playback file descriptors (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   return dev;
}
Beispiel #14
0
int main(void)
{
    /* Handle for the PCM device */
     snd_pcm_t *pcm_handle = NULL;

    /* 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 ot the device.
     */
    char * pcm_name;

    /* Init pcm_name. Of course, later you
     * will make this configurable; 
     */
    pcm_name = strdup("plughw:0,0");

    /* 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(snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0){
        fprintf(stderr, "Error opening PCM device %s\n", pcm_name);
        return (-1);
    }

    /* Init hwparams with full configuration space */
    if(snd_pcm_hw_params_any(pcm_handle, hwparams) < 0){
        fprintf(stderr, "Can not configure this PCM device.\n");
        return (-1);
    }

    int rate = 44100; /* Sample rate */
    int exact_rate;   /* Sample rate returned by snd_pcm_hw_params_set_rate_near */
    int dir;          /* exact_rate == rate --> dir = 0 */
                      /* exact_rate < rate  --> dir = -1 */
                      /* exact_rate > rate  --> dir = 1 */
    int periods = 2;  /* Number of periods */
    snd_pcm_uframes_t periodsize = 8192; /* Periodsize (bytes) */

    /* Set access type. This can be either
     * SND_PCM_ACCESS_RW_INTERLEAVED or 
     * SND_PCM_ACCESS_MMAP_NONINTERLEAVED.
     * There are also access types for MMAPed
     * access, but this is beyond the scope
     * of this introduction.
     */
    if(snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0){
        fprintf(stderr, "Error setting access.\n");
        return (-1);
    }
    
    /* Set sample format */
    if(snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0){
        fprintf(stderr, "Error setting format.\n");
        return (-1);
    }

    /* Set sample rate. If the exact rate is not supported by the hardware, use nearest possbile rate. */
    exact_rate = rate;
    if(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, 0) < 0){
        fprintf(stderr, "Error setting rate.\n");
        return (-1);
    }
    if(rate != exact_rate){
        fprintf(stderr, "The rate %d HZ is not supported by your hardware.\n ==> Using %d HZ instead.\n", rate, exact_rate);
    }

    /* Set number of channels */
    if(snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2) < 0){
        fprintf(stderr, "Error setting channels. \n");
        return (-1);
    }

    /* Set number of periods. Periods used to be called fragments. */
    if(snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0){
        fprintf(stderr, "Error setting periods.\n");
        return (-1);
    }

    /* Set buffer size (in frames). The resulting latency is given by 
     * latency = periodsize * periods / (rate * bytes_per_frame)
     */
    if(snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (periodsize * periods) >> 2) < 0){
        fprintf(stderr, "Error setting buffersize.\n");
        return (-1);
    }

    /* Apply HW parameter settins to 
     * PCM device and prepare device
     */
    if(snd_pcm_hw_params(pcm_handle, hwparams) < 0){
        fprintf(stderr, "Error setting HW params. \n");
        return (-1);
    }

#if 0
    /* Write num_frames frames from buffer data to
     * the PCM device pointed to by pcm_handle.
     * Returns the number of frames actually written. 
     */
    snd_pcm_sframes_t snd_pcm_writei(pcm_handle, data, num_frames);
#endif
#if 0
    /*Write num_frames frames from buffer data to 
     * the PCM device pointed to by pcm_handle.
     * Returns the number of frames actually written.
     */
    snd_pcm_sframes_t snd_pcm_writen(pcm_handle, data, num_frames);
#endif

    unsigned char *data;
    int pcmreturn, l1, l2;
    short s1, s2;
    int frames;
    int num_frames = 1024;

    data = (unsigned char *)malloc(periodsize);
    frames = periodsize >> 2;
    for(l1 = 0; l1 < 100; l1++){
        for(l2 = 0; l2 < num_frames; l2++){
            s1 = (l2 % 128) * 100 - 5000;
            s2 = (l2 % 256) * 100 - 5000;
            data[4*l2] = (unsigned char)s1;
            data[4*l2+1] = s1 >> 8;
            data[4*l2+2] = (unsigned char)s2;
            data[4*l2+3] = s2 >> 8;
        }
        while((pcmreturn = snd_pcm_writei(pcm_handle, data, frames)) < 0){
            snd_pcm_prepare(pcm_handle);
            fprintf(stderr, "<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>");
        }
    }


    /* Stop PCM device and drop pending frames */
    snd_pcm_drop(pcm_handle);

    /* Stop PCM device after pending frames have been played */
    snd_pcm_drain(pcm_handle);

    return 0;
}
Beispiel #15
0
int main(int argc, char *argv[])
{
	int err;
	struct sniffer_state sts;

	sts.pcm_name = strdup("plughw:0,0");
	sts.stream = SND_PCM_STREAM_PLAYBACK;
	sts.format = SND_PCM_FORMAT_A_LAW;
	sts.rate = 8000;
//	sts.exact_rate;
	sts.periods = 2;
	sts.buffer_time = 25000;
	sts.period_time = 12500;

	snd_pcm_hw_params_alloca(&sts.hwparams);

	if (snd_pcm_open(&sts.pcm, sts.pcm_name, sts.stream, 0) < 0) {
		fprintf(stderr, "Error opening PCM device %s\n", sts.pcm_name);
		return(-1);
	}

	if (snd_pcm_hw_params_any(sts.pcm, sts.hwparams) < 0) {
		fprintf(stderr, "Can not configure this PCM device.\n");
		return(-1);
	}

	if (snd_pcm_hw_params_set_access(sts.pcm, sts.hwparams,
			SND_PCM_ACCESS_MMAP_NONINTERLEAVED) < 0) {
		fprintf(stderr, "Error setting access.\n");
		return(-1);
	}

	if (snd_pcm_hw_params_set_format(sts.pcm, sts.hwparams,
			sts.format) < 0) {
		fprintf(stderr, "Error setting format.\n");
		return(-1);
	}

	sts.exact_rate = sts.rate;
	if (snd_pcm_hw_params_set_rate_near(sts.pcm, sts.hwparams,
			&sts.exact_rate, 0) < 0) {
		fprintf(stderr, "Error setting rate.\n");
		return(-1);
	}

printf("rate: %d\n", sts.exact_rate);

	if (sts.rate != sts.exact_rate) {
		fprintf(stderr, "The rate %d Hz is not supported by your hardware.\n"
			"==> Using %d Hz instead.\n", sts.rate, sts.exact_rate);
	}

	if (snd_pcm_hw_params_set_channels(sts.pcm, sts.hwparams, 1) < 0) {
		fprintf(stderr, "Error setting channels.\n");
		return(-1);
	}

	if (snd_pcm_hw_params_set_periods(sts.pcm, sts.hwparams, sts.periods, 0) < 0) {
		fprintf(stderr, "Error setting periods.\n");
		return(-1);
	}

	if (snd_pcm_hw_params_set_buffer_time_near(sts.pcm, sts.hwparams,
			&sts.buffer_time, &sts.dir) < 0) {
		fprintf(stderr, "Error setting buffersize.\n");
		return(-1);
	}

printf("buffer_time set to %d\n", sts.buffer_time);

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

printf("period_size = %d\n", (int)sts.period_size);

	if (snd_pcm_hw_params(sts.pcm, sts.hwparams) < 0) {
		fprintf(stderr, "Error setting HW params.\n");
		return(-1);
	}

	setvbuf(stdout, (char *)NULL, _IONBF, 0);

	int router_control_fd = open("/dev/visdn/router-control", O_RDWR);
	if (router_control_fd < 0) {
		perror("Unable to open router-control");
		return 1;
	}

	int fd;
	fd = open("/dev/visdn/streamport", O_RDWR);
	if (fd < 0) {
		perror("cannot open /dev/visdn/streamport");
		return 1;
	}

	struct vsp_ctl vsp_ctl;
	if (ioctl(fd, VISDN_SP_GET_NODEID, (caddr_t)&vsp_ctl) < 0) {
		perror("ioctl(VISDN_SP_GET_NODEID)");
		return 1;
	}

	char node_id[80];
	snprintf(node_id, sizeof(node_id), "/sys/%s", vsp_ctl.node_id);

	struct visdn_connect vc;
	memset(&vc, 0, sizeof(vc));
	strncpy(vc.from_endpoint, argv[1],
				sizeof(vc.from_endpoint));
	strncpy(vc.to_endpoint, node_id,
				sizeof(vc.to_endpoint));

printf("Connect: %s => %s\n", vc.from_endpoint, vc.to_endpoint);

	if (ioctl(router_control_fd, VISDN_IOC_CONNECT, (caddr_t) &vc) < 0) {
		perror("ioctl(VISDN_CONNECT, br=>sp)");
		return 1;
	}

	int pipeline_id = vc.pipeline_id;

	memset(&vc, 0, sizeof(vc));
	vc.pipeline_id = pipeline_id;
	if (ioctl(router_control_fd, VISDN_IOC_PIPELINE_OPEN,
						(caddr_t)&vc) < 0) {
		perror("ioctl(VISDN_PIPELINE_OPEN, br=>sp)");
		return 1;
	}

	memset(&vc, 0, sizeof(vc));
	vc.pipeline_id = pipeline_id;
	if (ioctl(router_control_fd, VISDN_IOC_PIPELINE_START,
						(caddr_t)&vc) < 0) {
		perror("ioctl(VISDN_PIPELINE_START, br=>sp)");
		return 1;
	}






	//double phase = 0;
	const snd_pcm_channel_area_t *my_areas;
	snd_pcm_uframes_t offset, frames, size;
	snd_pcm_sframes_t avail, commitres;
	snd_pcm_state_t state;
	int first = 1;

	while (1) {
		state = snd_pcm_state(sts.pcm);

		if (state == SND_PCM_STATE_XRUN) {
			err = xrun_recovery(sts.pcm, -EPIPE);
			if (err < 0) {
				printf("XRUN recovery failed: %s\n", snd_strerror(err));
				return err;
			}
			first = 1;
		} else if (state == SND_PCM_STATE_SUSPENDED) {
			err = xrun_recovery(sts.pcm, -ESTRPIPE);
			if (err < 0) {
				printf("SUSPEND recovery failed: %s\n", snd_strerror(err));
				return err;
			}
		}

		avail = snd_pcm_avail_update(sts.pcm);
		if (avail < 0) {
			err = xrun_recovery(sts.pcm, avail);
			if (err < 0) {
				printf("avail update failed: %s\n", snd_strerror(err));
				return err;
			}
			first = 1;
			continue;
		}

		if (avail < sts.period_size) {
			if (first) {
				first = 0;
				err = snd_pcm_start(sts.pcm);
				if (err < 0) {
					printf("Start error: %s\n", snd_strerror(err));
					exit(EXIT_FAILURE);
				}
			} else {
				err = snd_pcm_wait(sts.pcm, -1);
				if (err < 0) {
					if ((err = xrun_recovery(sts.pcm, err)) < 0) {
						printf("snd_pcm_wait error: %s\n", snd_strerror(err));
						exit(EXIT_FAILURE);
					}
					first = 1;
				}
			}
			continue;
		}

		size = sts.period_size;
		while (size > 0) {
			frames = size;
			err = snd_pcm_mmap_begin(sts.pcm, &my_areas, &offset, &frames);
			if (err < 0) {
				if ((err = xrun_recovery(sts.pcm, err)) < 0) {
					printf("MMAP begin avail error: %s\n", snd_strerror(err));
					exit(EXIT_FAILURE);
				}

				first = 1;
			}

			int r = read(fd, my_areas[0].addr + offset, frames);
			printf("%d %d %d: ", (int)offset, (int)frames, r);

			int i;
			for (i=0; i<r; i++)
				printf("%02x", *(__u8 *)(my_areas[0].addr + i));

			printf("\n");

			commitres = snd_pcm_mmap_commit(sts.pcm, offset, frames);
			if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
				if ((err = xrun_recovery(sts.pcm, commitres >= 0 ? -EPIPE : commitres)) < 0) {
					printf("MMAP commit error: %s\n", snd_strerror(err));
					exit(EXIT_FAILURE);
				}
				first = 1;
			}
			size -= frames;
		}
	}

	return 0;
}
int set_hwparams(snd_pcm_t *handle,
                        snd_pcm_hw_params_t *params,
                        snd_pcm_access_t access)
{
        unsigned int rrate;
        int err, dir;

	printf("set_hwparams\n");
        /* choose all parameters */
        err = snd_pcm_hw_params_any(handle, params);
        if (err < 0) {
                printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
                return err;
        }
        /* set the interleaved read/write format */
        err = snd_pcm_hw_params_set_access(handle, params, access);
        if (err < 0) {
                printf("Access type not available for playback: %s\n", snd_strerror(err));
                return err;
        }
        /* set the sample format */
        err = snd_pcm_hw_params_set_format(handle, params, format);
        if (err < 0) {
                printf("Sample format not available for playback: %s\n", snd_strerror(err));
                return err;
        }
        /* set the count of channels */
        err = snd_pcm_hw_params_set_channels(handle, params, channels);
        if (err < 0) {
                printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err));
                return err;
        }
        /* set the stream rate */
        rrate = rate;
        err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
        if (err < 0) {
                printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
                return err;
        }
        if (rrate != rate) {
                printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
                return -EINVAL;
        }
	dir = 0;
        err = snd_pcm_hw_params_set_period_size_near(handle, params, &period_size, &dir);
        if (err < 0) {
                printf("Unable to set period size %i for playback: %s\n", (int)period_size, snd_strerror(err));
                return err;
        }
        err = snd_pcm_hw_params_set_periods(handle, params, periods, 0);
        if (err < 0) {
                printf("Unable to set periods %i for playback: %s\n", periods, snd_strerror(err));
                return err;
        }
        /* write the parameters to device */
        err = snd_pcm_hw_params(handle, params);
        if (err < 0) {
                printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
                return err;
        }

        err = snd_pcm_hw_params_get_periods(params, &periods, &dir);
        if (err < 0) {
                printf("Unable to get periods for playback: %s\n", snd_strerror(err));
                return err;
        }
        err = snd_pcm_hw_params_get_period_size(params, &period_size, &dir);
        if (err < 0) {
                printf("Unable to get period size for playback: %s\n", snd_strerror(err));
                return err;
        }
        return 0;
}
Beispiel #17
0
int audioStreamer_ALSA::Open(char *devname, int is_write, int srate, int nch, int bps, int fragsize, int nfrags, int dosleep)
{
	m_sleep=dosleep;

        /* Playback stream */
        snd_pcm_stream_t stream = is_write?SND_PCM_STREAM_PLAYBACK:SND_PCM_STREAM_CAPTURE;

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

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

    	if (snd_pcm_open(&pcm_handle, devname, stream, 0) < 0) 
	{
 		fprintf(stderr, "Error opening PCM device %s\n", devname);
	        return(-1);
    	}

        /* Init hwparams with full configuration space */
        if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) 
	{
		fprintf(stderr, "Can not configure this PCM device.\n");
		return(-1);
        }

	if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) 
	{
		fprintf(stderr, "Error setting access.\n");
		return(-1);
        }
	  
    	/* Set sample format */
	m_bps=bps==32?32:bps==24?24:16;
    	if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, 
				bps==32?SND_PCM_FORMAT_S32_LE:bps==24?SND_PCM_FORMAT_S24_3LE:SND_PCM_FORMAT_S16_LE) < 0) {
		fprintf(stderr, "Error setting format.\n");
		fprintf(stderr, "Try -bps 16, -bps 24, or -bps 32\n");
		return(-1);
	}

  int dir=0;          /* exact_rate == rate --> dir = 0 */
                          /* exact_rate < rate  --> dir = -1 */
                          /* exact_rate > rate  --> dir = 1 */
	unsigned int usrate=srate;

        /* Set sample rate. If the exact rate is not supported */
        /* by the hardware, use nearest possible rate.         */ 
	m_srate=srate;
  int exact_rate = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &usrate, &dir);
	if (dir != 0) 
	{
		fprintf(stderr, "The rate %d Hz is not supported by your hardware. Using %d Hz instead.\n", srate, exact_rate);
  		m_srate=exact_rate;
      	}

       	/* Set number of channels */
        if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, nch) < 0) 
	{
		fprintf(stderr, "Error setting channels.\n");
		fprintf(stderr, "Try -nch 1 or -nch 2\n");
		return(-1);
        }
	m_nch=nch;
	
	int periods=m_nfrags=(is_write?nfrags:nfrags*3);
	int periodsize=fragsize;

	/* Set number of periods. Periods used to be called fragments. */ 
	if (snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0) 
	{
		fprintf(stderr, "Error setting periods.\n");
		fprintf(stderr, "Try -nbufs 2 through -nbufs 16\n");
		return(-1);
	}

    	/* Set buffer size (in frames). The resulting latency is given by */
    	/* latency = periodsize * periods / (rate * bytes_per_frame)     */
    	if (snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, m_bufsize = (periodsize * periods)/(m_nch * m_bps/8)) < 0) 
	{
		fprintf(stderr, "Error setting buffersize.\n");
		fprintf(stderr, "Try -bufsize 256 through -bufsize 2048\n");
		return(-1);
	}

     	/* Apply HW parameter settings to */
        /* PCM device and prepare device  */
        if (snd_pcm_hw_params(pcm_handle, hwparams) < 0) 
	{
		fprintf(stderr, "Error setting HW params.\n");
		return(-1);
	}

	return 0;
}
Beispiel #18
0
/* Initialise audio devices. */
int digi_init()
{
 int err, tmp;
 char *device = "plughw:0,0";
 snd_pcm_hw_params_t *params;
 pthread_attr_t attr;
 pthread_mutexattr_t mutexattr;

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

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

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

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

 /* Start the mixer thread */

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

 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

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

 digi_initialised = 1;
 return 0;
}
Beispiel #19
0
input_module_t *alsa_open_module(module_param_t *params)
{
    input_module_t *mod = calloc(1, sizeof(input_module_t));
    im_alsa_state *s;
    module_param_t *current;
    char *device = "plughw:0,0"; /* default device */
    int format = AFMT_S16_LE;
    int channels, rate;
    int use_metadata = 1; /* Default to on */
    unsigned int buffered_time;

    snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;
    snd_pcm_hw_params_t *hwparams;

    int err;

    mod->type = ICES_INPUT_PCM;
    mod->subtype = INPUT_PCM_LE_16;
    mod->getdata = alsa_read;
    mod->handle_event = event_handler;
    mod->metadata_update = metadata_update;

    mod->internal = calloc(1, sizeof(im_alsa_state));
    s = mod->internal;

    s->fd = NULL; /* Set it to something invalid, for now */
    s->rate = 44100; /* Defaults */
    s->channels = 2; 

    thread_mutex_create(&s->metadatalock);

    current = params;

    while(current)
    {
        if(!strcmp(current->name, "rate"))
            s->rate = atoi(current->value);
        else if(!strcmp(current->name, "channels"))
            s->channels = atoi(current->value);
        else if(!strcmp(current->name, "device"))
            device = current->value;
        else if(!strcmp(current->name, "metadata"))
            use_metadata = atoi(current->value);
        else if(!strcmp(current->name, "metadatafilename"))
            ices_config->metadata_filename = current->value;
        else
            LOG_WARN1("Unknown parameter %s for alsa module", current->name);

        current = current->next;
    }

    snd_pcm_hw_params_alloca(&hwparams);

    if ((err = snd_pcm_open(&s->fd, device, stream, 0)) < 0)
    {
        LOG_ERROR2("Failed to open audio device %s: %s", device, snd_strerror(err));
        goto fail;
    }

    if ((err = snd_pcm_hw_params_any(s->fd, hwparams)) < 0)
    {
        LOG_ERROR1("Failed to initialize hwparams: %s", snd_strerror(err));
        goto fail;
    }
    if ((err = snd_pcm_hw_params_set_access(s->fd, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
    {
        LOG_ERROR1("Error setting access: %s", snd_strerror(err));
        goto fail;
    }
    if ((err = snd_pcm_hw_params_set_format(s->fd, hwparams, SND_PCM_FORMAT_S16_LE)) < 0)
    {
        LOG_ERROR1("Couldn't set sample format to SND_PCM_FORMAT_S16_LE: %s", snd_strerror(err));
        goto fail;
    }
    if ((err = snd_pcm_hw_params_set_rate_near(s->fd, hwparams, &s->rate, 0)) < 0)
    {
        LOG_ERROR1("Error setting rate: %s", snd_strerror(err));
        goto fail;
    }
    if ((err = snd_pcm_hw_params_set_channels(s->fd, hwparams, s->channels)) < 0)
    {
        LOG_ERROR1("Error setting channels: %s", snd_strerror(err));
        goto fail;
    }
    if ((err = snd_pcm_hw_params_set_periods(s->fd, hwparams, 2, 0)) < 0)
    {
        LOG_ERROR1("Error setting periods: %s", snd_strerror(err));
        goto fail;
    }
    buffered_time = 500000;
    if ((err = snd_pcm_hw_params_set_buffer_time_near(s->fd, hwparams, &buffered_time, 0)) < 0)
    {
        LOG_ERROR1("Error setting buffersize: %s", snd_strerror(err));
        goto fail;
    }
    if ((err = snd_pcm_hw_params(s->fd, hwparams)) < 0)
    {
        LOG_ERROR1("Error setting HW params: %s", snd_strerror(err));
        goto fail;
    }

    /* We're done, and we didn't fail! */
    LOG_INFO3("Opened audio device %s at %d channel(s), %d Hz", 
            device, s->channels, s->rate);

    if(use_metadata)
    {
        if(ices_config->metadata_filename)
            thread_create("im_alsa-metadata", metadata_thread_signal, mod, 1);
        else
            thread_create("im_alsa-metadata", metadata_thread_stdin, mod, 1);
        LOG_INFO0("Started metadata update thread");
    }

    return mod;

fail:
    close_module(mod); /* safe, this checks for valid contents */
    return NULL;
}
Beispiel #20
0
main(int argc, char **argv){
    snd_pcm_t *handle;
    snd_pcm_hw_params_t *params;
    snd_pcm_uframes_t frames;
    //the libsamplerate stuff
    SRC_DATA datastr;//holds the data(inpu and output),input frames used, output frames generated 
    SRC_STATE *statestr;//holds the state
    int error;
    //the lbsndfile stuff, one keeps the header the other the data
    SF_INFO sfinf;//has all the info like total frames,samplerate, channels, mode
    SNDFILE *input = NULL;
    //buffers used in computation to pass to the playback function
    float *buffin = NULL;//float into the converter
    float *filein = NULL;
    float *flangebuffout = NULL;//float to traverse the array for getting flange effects
    float *flangebase = NULL;//float to fix the array for initialising the flange effects
    float *buffout = NULL;//float out of the converter
    short *final = NULL;//final array to write to snd card

    float fldelmax = 256;
    float flfreq = 1;
    float flgain = .5;
    int fltime = 0;


    int pcm, readcount, pcmrc, blah;//pcm is used for error checking the alsa stuff, pcmrc is used in the main loop
    float *eofin;//to point to the end of the file's raw data
    int tmp;//used to hold information that is printed in stdio
    int i = 0;//index for initialising the output DAC
   // float fldelmax, flgain, flfreq;
    // pointer for the file input
    if (argc != 3){
        printf("Usage requires music file and src ratio, please try again\n\n");
        return 0;
    }
    char *inputname = argv[1];
    //int *filein = argv[1];

    input = sf_open(inputname, SFM_READ, &sfinf);
    if (input == NULL){
        printf("could not open file sorry \n\n");
        return 0;
    }
    fprintf(stderr, "Channels : %d\n", sfinf.channels);
    fprintf(stderr, "Sample rate; %d\n", sfinf.samplerate);
    fprintf(stderr, "Sections: %d\n", sfinf.sections);
    fprintf(stderr, "Format: %d\n", sfinf.format);
   // fprintf(stderr, "Frame Count: %d\n", sfinf.frames);
    //fprintf(stderr, "size: %d\n", sizeof(short));
   //open sndcard
   if ((filein = malloc(sizeof(float)*sfinf.channels*sfinf.frames)) == NULL)
   {
       printf("MAN YOU OUT OF MEM");
       return 0;
   }
   blah = sf_readf_float(input, filein, sfinf.frames);
   buffin = filein;
   eofin = filein + (sfinf.frames)*sfinf.channels;




    if (pcm =snd_pcm_open(&handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0)< 0){
        printf("Error: CANNOT OPEN PCM DEVICE\n");
    }

    //allocate default parameters
    snd_pcm_hw_params_alloca(&params);
    snd_pcm_hw_params_any(handle, params);
    //set parameters
    if (pcm = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED)< 0){
        printf("Cannot set interleaved mode\n");
    }

    if (pcm = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE)< 0){
        printf("CANNOT SET FORMAT\n");
    }
    if (pcm = snd_pcm_hw_params_set_channels(handle, params, sfinf.channels)< 0){
        printf("CANNOT SET CHANNELS \n");
    }
    if (pcm = snd_pcm_hw_params_set_rate(handle, params, sfinf.samplerate, 0)< 0){
        printf("CANNOT SET SAMPLERATES \n");
    }
    if (pcm = snd_pcm_hw_params_set_periods(handle, params,1024, 0) < 0){
        printf("CANNOT SET PERIOD TO 128");
    }

    //write parameters
    if (pcm = snd_pcm_hw_params(handle, params)< 0){
        printf("CANNOT SET HARDWARE PARAMETERS\n");
    }
    printf("PCm NAME: %s\n", snd_pcm_name(handle));
    printf("PCM state: %s \n", snd_pcm_state_name(snd_pcm_state(handle)));
    snd_pcm_hw_params_get_channels(params, &tmp);
    printf("channels: %i\n", tmp);
    snd_pcm_hw_params_get_rate(params, &tmp, 0);
    printf("rate: %d \n", tmp);
    //find size of period on hardware
    snd_pcm_hw_params_get_period_size(params, &frames, 0);
    fprintf(stderr, "# frames in a period: %d\n", frames);
  
    //buffers on buffers (buffout for float output from sample rate conversion), (final for short array to write to pcm) and flangebse for the flanger stuff
    
    buffout = malloc(frames*sfinf.channels * sizeof(float));//frames
    final = malloc(frames*sfinf.channels * sizeof(short));//frames