static void audio_renderer_init() { int rc; decoder = opus_decoder_create(SAMPLE_RATE, CHANNEL_COUNT, &rc); snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; snd_pcm_uframes_t period_size = FRAME_SIZE * CHANNEL_COUNT * 2; snd_pcm_uframes_t buffer_size = 12 * period_size; unsigned int sampleRate = SAMPLE_RATE; /* Open PCM device for playback. */ CHECK_RETURN(snd_pcm_open(&handle, audio_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) /* Set hardware parameters */ CHECK_RETURN(snd_pcm_hw_params_malloc(&hw_params)); CHECK_RETURN(snd_pcm_hw_params_any(handle, hw_params)); CHECK_RETURN(snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)); CHECK_RETURN(snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE)); CHECK_RETURN(snd_pcm_hw_params_set_rate_near(handle, hw_params, &sampleRate, NULL)); CHECK_RETURN(snd_pcm_hw_params_set_channels(handle, hw_params, CHANNEL_COUNT)); CHECK_RETURN(snd_pcm_hw_params_set_buffer_size_near(handle, hw_params, &buffer_size)); CHECK_RETURN(snd_pcm_hw_params_set_period_size_near(handle, hw_params, &period_size, NULL)); CHECK_RETURN(snd_pcm_hw_params(handle, hw_params)); snd_pcm_hw_params_free(hw_params); /* Set software parameters */ CHECK_RETURN(snd_pcm_sw_params_malloc(&sw_params)); CHECK_RETURN(snd_pcm_sw_params_current(handle, sw_params)); CHECK_RETURN(snd_pcm_sw_params_set_start_threshold(handle, sw_params, buffer_size - period_size)); CHECK_RETURN(snd_pcm_sw_params_set_avail_min(handle, sw_params, period_size)); CHECK_RETURN(snd_pcm_sw_params(handle, sw_params)); snd_pcm_sw_params_free(sw_params); CHECK_RETURN(snd_pcm_prepare(handle)); }
static void pcm_close(pcm_handle_t* pcm) { free(pcm->buf); snd_pcm_hw_params_free(pcm->hw_params); snd_pcm_sw_params_free(pcm->sw_params); snd_pcm_close(pcm->pcm); }
static void alsa_set_sw_params(struct alsa_dev *dev, snd_pcm_t *handle, int period, int thres) { int ret; snd_pcm_sw_params_t *sw_params; ret = snd_pcm_sw_params_malloc(&sw_params); if (ret < 0) syslog_panic("Cannot allocate software parameters: %s\n", snd_strerror(ret)); ret = snd_pcm_sw_params_current(handle, sw_params); if (ret < 0) syslog_panic("Cannot initialize software parameters: %s\n", snd_strerror(ret)); ret = snd_pcm_sw_params_set_avail_min(handle, sw_params, period); if (ret < 0) syslog_panic("Cannot set minimum available count: %s\n", snd_strerror(ret)); if (thres) { ret = snd_pcm_sw_params_set_start_threshold(handle, sw_params, period); if (ret < 0) syslog_panic("Cannot set start mode: %s\n", snd_strerror(ret)); } ret = snd_pcm_sw_params(handle, sw_params); if (ret < 0) syslog_panic("Cannot set software parameters: %s\n", snd_strerror(ret)); snd_pcm_sw_params_free(sw_params); }
static av_cold int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap) { AlsaData *s = s1->priv_data; AVStream *st; int ret; enum CodecID codec_id; snd_pcm_sw_params_t *sw_params; st = av_new_stream(s1, 0); if (!st) { av_log(s1, AV_LOG_ERROR, "Cannot add stream\n"); return AVERROR(ENOMEM); } codec_id = s1->audio_codec_id; ret = ff_alsa_open(s1, SND_PCM_STREAM_CAPTURE, &s->sample_rate, s->channels, &codec_id); if (ret < 0) { return AVERROR(EIO); } if (snd_pcm_type(s->h) != SND_PCM_TYPE_HW) av_log(s1, AV_LOG_WARNING, "capture with some ALSA plugins, especially dsnoop, " "may hang.\n"); ret = snd_pcm_sw_params_malloc(&sw_params); if (ret < 0) { av_log(s1, AV_LOG_ERROR, "cannot allocate software parameters structure (%s)\n", snd_strerror(ret)); goto fail; } snd_pcm_sw_params_current(s->h, sw_params); snd_pcm_sw_params_set_tstamp_mode(s->h, sw_params, SND_PCM_TSTAMP_ENABLE); ret = snd_pcm_sw_params(s->h, sw_params); snd_pcm_sw_params_free(sw_params); if (ret < 0) { av_log(s1, AV_LOG_ERROR, "cannot install ALSA software parameters (%s)\n", snd_strerror(ret)); goto fail; } /* take real parameters */ st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = codec_id; st->codec->sample_rate = s->sample_rate; st->codec->channels = s->channels; av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ return 0; fail: snd_pcm_close(s->h); return AVERROR(EIO); }
static BOOL tsmf_alsa_set_format(ITSMFAudioDevice *audio, UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample) { int error; snd_pcm_uframes_t frames; snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio; if(!alsa->out_handle) return FALSE; snd_pcm_drop(alsa->out_handle); alsa->actual_rate = alsa->source_rate = sample_rate; alsa->actual_channels = alsa->source_channels = channels; alsa->bytes_per_sample = bits_per_sample / 8; error = snd_pcm_hw_params_malloc(&hw_params); if(error < 0) { WLog_ERR(TAG, "snd_pcm_hw_params_malloc failed"); return FALSE; } snd_pcm_hw_params_any(alsa->out_handle, hw_params); snd_pcm_hw_params_set_access(alsa->out_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(alsa->out_handle, hw_params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_rate_near(alsa->out_handle, hw_params, &alsa->actual_rate, NULL); snd_pcm_hw_params_set_channels_near(alsa->out_handle, hw_params, &alsa->actual_channels); frames = sample_rate; snd_pcm_hw_params_set_buffer_size_near(alsa->out_handle, hw_params, &frames); snd_pcm_hw_params(alsa->out_handle, hw_params); snd_pcm_hw_params_free(hw_params); error = snd_pcm_sw_params_malloc(&sw_params); if(error < 0) { WLog_ERR(TAG, "snd_pcm_sw_params_malloc"); return FALSE; } snd_pcm_sw_params_current(alsa->out_handle, sw_params); snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params, frames / 2); snd_pcm_sw_params(alsa->out_handle, sw_params); snd_pcm_sw_params_free(sw_params); snd_pcm_prepare(alsa->out_handle); DEBUG_TSMF("sample_rate %d channels %d bits_per_sample %d", sample_rate, channels, bits_per_sample); DEBUG_TSMF("hardware buffer %d frames", (int)frames); if((alsa->actual_rate != alsa->source_rate) || (alsa->actual_channels != alsa->source_channels)) { DEBUG_TSMF("actual rate %d / channel %d is different " "from source rate %d / channel %d, resampling required.", alsa->actual_rate, alsa->actual_channels, alsa->source_rate, alsa->source_channels); } return TRUE; }
/** * \brief Closes a ordinary pcm instance * \param pcm Ordinary pcm handle to close * \return 0 on success otherwise a negative error code */ int sndo_pcm_close(sndo_pcm_t *pcm) { int err; if (pcm->playback) err = snd_pcm_close(pcm->playback); if (pcm->capture) err = snd_pcm_close(pcm->capture); if (pcm->p_hw_params) snd_pcm_hw_params_free(pcm->p_hw_params); if (pcm->p_sw_params) snd_pcm_sw_params_free(pcm->p_sw_params); if (pcm->c_hw_params) snd_pcm_hw_params_free(pcm->c_hw_params); if (pcm->c_sw_params) snd_pcm_sw_params_free(pcm->c_sw_params); free(pcm); return 0; }
static int set_params(struct alsa_device_data * alsa_data) { snd_pcm_hw_params_t * hw_params; snd_pcm_sw_params_t * sw_params; int error; snd_pcm_uframes_t frames; snd_pcm_drop(alsa_data->out_handle); error = snd_pcm_hw_params_malloc(&hw_params); if (error < 0) { LLOGLN(0, ("set_params: snd_pcm_hw_params_malloc failed")); return 1; } snd_pcm_hw_params_any(alsa_data->out_handle, hw_params); snd_pcm_hw_params_set_access(alsa_data->out_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(alsa_data->out_handle, hw_params, alsa_data->format); snd_pcm_hw_params_set_rate_near(alsa_data->out_handle, hw_params, &alsa_data->actual_rate, NULL); snd_pcm_hw_params_set_channels_near(alsa_data->out_handle, hw_params, &alsa_data->actual_channels); frames = alsa_data->actual_rate * 4; snd_pcm_hw_params_set_buffer_size_near(alsa_data->out_handle, hw_params, &frames); snd_pcm_hw_params(alsa_data->out_handle, hw_params); snd_pcm_hw_params_free(hw_params); error = snd_pcm_sw_params_malloc(&sw_params); if (error < 0) { LLOGLN(0, ("set_params: snd_pcm_sw_params_malloc")); return 1; } snd_pcm_sw_params_current(alsa_data->out_handle, sw_params); snd_pcm_sw_params_set_start_threshold(alsa_data->out_handle, sw_params, frames / 2); snd_pcm_sw_params(alsa_data->out_handle, sw_params); snd_pcm_sw_params_free(sw_params); snd_pcm_prepare(alsa_data->out_handle); LLOGLN(10, ("set_params: hardware buffer %d frames, playback buffer %.2g seconds", (int)frames, (double)frames / 2.0 / (double)alsa_data->actual_rate)); if ((alsa_data->actual_rate != alsa_data->source_rate) || (alsa_data->actual_channels != alsa_data->source_channels)) { LLOGLN(0, ("set_params: actual rate %d / channel %d is different from source rate %d / channel %d, resampling required.", alsa_data->actual_rate, alsa_data->actual_channels, alsa_data->source_rate, alsa_data->source_channels)); } return 0; }
/****************************************************************************** * Sound_alsa_delete ******************************************************************************/ Int Sound_alsa_delete(Sound_Handle hSound) { if (hSound) { if (hSound->rcIn) { snd_pcm_close(hSound->rcIn); } if (hSound->rcOut) { snd_pcm_close(hSound->rcOut); } if (hSound->hwParamsIn) { /* Free the H/W param structure */ snd_pcm_hw_params_free(hSound->hwParamsIn); } if (hSound->swParamsIn) { /* Free the S/W param structure */ snd_pcm_sw_params_free(hSound->swParamsIn); } if (hSound->hwParamsOut) { /* Free the H/W param structure */ snd_pcm_hw_params_free(hSound->hwParamsOut); } if (hSound->swParamsOut) { /* Free the S/W param structure */ snd_pcm_sw_params_free(hSound->swParamsOut); } free(hSound); snd_config_update_free_global(); } return Dmai_EOK; }
void CASDeviceAlsa::Clear() { Stop(); if( m_poHandle ) { snd_pcm_close( m_poHandle ); m_poHandle = 0; } if( m_poHW ) snd_pcm_hw_params_free( m_poHW ); if( m_poSW ) snd_pcm_sw_params_free( m_poSW ); ClearBuffer(); }
static int laudio_alsa_set_start_threshold(snd_pcm_uframes_t threshold) { snd_pcm_sw_params_t *sw_params; int ret; ret = snd_pcm_sw_params_malloc(&sw_params); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not allocate sw params: %s\n", snd_strerror(ret)); goto out_fail; } ret = snd_pcm_sw_params_current(hdl, sw_params); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not retrieve current sw params: %s\n", snd_strerror(ret)); goto out_fail; } ret = snd_pcm_sw_params_set_start_threshold(hdl, sw_params, threshold); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not set start threshold: %s\n", snd_strerror(ret)); goto out_fail; } ret = snd_pcm_sw_params(hdl, sw_params); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Could not set sw params: %s\n", snd_strerror(ret)); goto out_fail; } return 0; out_fail: snd_pcm_sw_params_free(sw_params); return -1; }
AudioAlsa::~AudioAlsa() { stopProcessing(); if( m_handle != NULL ) { snd_pcm_close( m_handle ); } if( m_hwParams != NULL ) { snd_pcm_hw_params_free( m_hwParams ); } if( m_swParams != NULL ) { snd_pcm_sw_params_free( m_swParams ); } }
static void alsa_close (struct sound_device *sd) { struct alsa_params *p = (struct alsa_params *) sd->data; if (p) { if (p->hwparams) snd_pcm_hw_params_free (p->hwparams); if (p->swparams) snd_pcm_sw_params_free (p->swparams); if (p->handle) { snd_pcm_drain (p->handle); snd_pcm_close (p->handle); } free (p); } }
void WaveRecorder::cleanup() { if (_event_trigger) { _client.remove_event_source(*_event_trigger); delete _event_trigger; } if (_sw_params) { snd_pcm_sw_params_free(_sw_params); } if (_hw_params) { snd_pcm_hw_params_free(_hw_params); } if (_pcm) { snd_pcm_close(_pcm); } }
/* alsa_exit: * Shuts down ALSA driver. */ static void alsa_exit(int input) { if (input) return; _unix_bg_man->unregister_func(alsa_update); _AL_FREE(alsa_bufdata); alsa_bufdata = NULL; _mixer_exit(); if (alsa_mixer) snd_mixer_close(alsa_mixer); snd_pcm_close(pcm_handle); snd_pcm_hw_params_free(hwparams); snd_pcm_sw_params_free(swparams); }
void AlsaRenderer::SetupSwParams() { snd_pcm_sw_params_t* params; /* allocate a software parameters object */ snd_pcm_sw_params_malloc(¶ms); /* get the current swparams */ snd_pcm_sw_params_current(m_PcmHandle, params); /* round up to closest transfer boundary */ snd_pcm_sw_params_set_start_threshold(m_PcmHandle, params, 1); /* require a minimum of one full transfer in the buffer */ snd_pcm_sw_params_set_avail_min(m_PcmHandle, params, 1); snd_pcm_sw_params(m_PcmHandle, params); /* free */ snd_pcm_sw_params_free(params); }
void DAUDIO_Close(void* id, int isSource) { AlsaPcmInfo* info = (AlsaPcmInfo*) id; TRACE0("DAUDIO_Close\n"); if (info != NULL) { if (info->handle != NULL) { snd_pcm_close(info->handle); } if (info->hwParams) { snd_pcm_hw_params_free(info->hwParams); } if (info->swParams) { snd_pcm_sw_params_free(info->swParams); } #ifdef GET_POSITION_METHOD2 if (info->positionStatus) { snd_pcm_status_free(info->positionStatus); } #endif free(info); } }
static int set_swparams (GstAlsaSink * alsa) { int err; snd_pcm_sw_params_t *params; snd_pcm_sw_params_malloc (¶ms); /* get the current swparams */ CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config); /* start the transfer when the buffer is almost full: */ /* (buffer_size / avail_min) * avail_min */ CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params, (alsa->buffer_size / alsa->period_size) * alsa->period_size), start_threshold); /* allow the transfer when at least period_size samples can be processed */ CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params, alsa->period_size), set_avail); #if GST_CHECK_ALSA_VERSION(1,0,16) /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */ #else /* align all transfers to 1 sample */ CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align); #endif /* write the parameters to the playback device */ CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params); snd_pcm_sw_params_free (params); return 0; /* ERRORS */ no_config: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to determine current swparams for playback: %s", snd_strerror (err))); snd_pcm_sw_params_free (params); return err; } start_threshold: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set start threshold mode for playback: %s", snd_strerror (err))); snd_pcm_sw_params_free (params); return err; } set_avail: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set avail min for playback: %s", snd_strerror (err))); snd_pcm_sw_params_free (params); return err; } #if !GST_CHECK_ALSA_VERSION(1,0,16) set_align: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set transfer align for playback: %s", snd_strerror (err))); snd_pcm_sw_params_free (params); return err; } #endif set_sw_params: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set sw params for playback: %s", snd_strerror (err))); snd_pcm_sw_params_free (params); return err; } }
static void alsa_configure (struct sound_device *sd) { int val, err, dir; unsigned uval; struct alsa_params *p = (struct alsa_params *) sd->data; snd_pcm_uframes_t buffer_size; xassert (p->handle != 0); err = snd_pcm_hw_params_malloc (&p->hwparams); if (err < 0) alsa_sound_perror ("Could not allocate hardware parameter structure", err); err = snd_pcm_sw_params_malloc (&p->swparams); if (err < 0) alsa_sound_perror ("Could not allocate software parameter structure", err); err = snd_pcm_hw_params_any (p->handle, p->hwparams); if (err < 0) alsa_sound_perror ("Could not initialize hardware parameter structure", err); err = snd_pcm_hw_params_set_access (p->handle, p->hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) alsa_sound_perror ("Could not set access type", err); val = sd->format; err = snd_pcm_hw_params_set_format (p->handle, p->hwparams, val); if (err < 0) alsa_sound_perror ("Could not set sound format", err); uval = sd->sample_rate; err = snd_pcm_hw_params_set_rate_near (p->handle, p->hwparams, &uval, 0); if (err < 0) alsa_sound_perror ("Could not set sample rate", err); val = sd->channels; err = snd_pcm_hw_params_set_channels (p->handle, p->hwparams, val); if (err < 0) alsa_sound_perror ("Could not set channel count", err); err = snd_pcm_hw_params (p->handle, p->hwparams); if (err < 0) alsa_sound_perror ("Could not set parameters", err); err = snd_pcm_hw_params_get_period_size (p->hwparams, &p->period_size, &dir); if (err < 0) alsa_sound_perror ("Unable to get period size for playback", err); err = snd_pcm_hw_params_get_buffer_size (p->hwparams, &buffer_size); if (err < 0) alsa_sound_perror("Unable to get buffer size for playback", err); err = snd_pcm_sw_params_current (p->handle, p->swparams); if (err < 0) alsa_sound_perror ("Unable to determine current swparams for playback", err); /* Start the transfer when the buffer is almost full */ err = snd_pcm_sw_params_set_start_threshold (p->handle, p->swparams, (buffer_size / p->period_size) * p->period_size); if (err < 0) alsa_sound_perror ("Unable to set start threshold mode for playback", err); /* Allow the transfer when at least period_size samples can be processed */ err = snd_pcm_sw_params_set_avail_min (p->handle, p->swparams, p->period_size); if (err < 0) alsa_sound_perror ("Unable to set avail min for playback", err); err = snd_pcm_sw_params (p->handle, p->swparams); if (err < 0) alsa_sound_perror ("Unable to set sw params for playback\n", err); snd_pcm_hw_params_free (p->hwparams); p->hwparams = NULL; snd_pcm_sw_params_free (p->swparams); p->swparams = NULL; err = snd_pcm_prepare (p->handle); if (err < 0) alsa_sound_perror ("Could not prepare audio interface for use", err); if (sd->volume > 0) { int chn; snd_mixer_t *handle; snd_mixer_elem_t *e; const char *file = sd->file ? sd->file : DEFAULT_ALSA_SOUND_DEVICE; if (snd_mixer_open (&handle, 0) >= 0) { if (snd_mixer_attach (handle, file) >= 0 && snd_mixer_load (handle) >= 0 && snd_mixer_selem_register (handle, NULL, NULL) >= 0) for (e = snd_mixer_first_elem (handle); e; e = snd_mixer_elem_next (e)) { if (snd_mixer_selem_has_playback_volume (e)) { long pmin, pmax, vol; snd_mixer_selem_get_playback_volume_range (e, &pmin, &pmax); vol = pmin + (sd->volume * (pmax - pmin)) / 100; for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) snd_mixer_selem_set_playback_volume (e, chn, vol); } } snd_mixer_close(handle); } } }
static void *_msynth_thread_main(void *arg) { int i; int err; int sample; int processed; struct sampleclock sc = {0, 0, 0.0f, 0.0f}; msynth_frame fb = NULL; puts("synthread: started"); /* Begin initialization of ALSA */ /* snd_pcm_open(pcm_handle, device_name, stream_type, open_mode) */ err = snd_pcm_open(&pcm, config.device_name, SND_PCM_STREAM_PLAYBACK, 0); ALSERT("opening audio device"); /* First ALSA hardware settings */ /* Allocate HW params */ err = snd_pcm_hw_params_malloc(&hw_p); ALSERT("allocating hw params"); /* Get default HW parameters */ err = snd_pcm_hw_params_any(pcm, hw_p); ALSERT("requesting hw default params"); /* Disable software resampling */ err = snd_pcm_hw_params_set_rate_resample(pcm, hw_p, config.resample); ALSERT("disabling software resampling"); /* Configure sample rate */ if (config.srate != -1) srate = config.srate; else { /* Get maximum hardware samplerate */ err = snd_pcm_hw_params_get_rate_max(hw_p, &srate, &dir); ALSERT("requesting maximum hardware samplerate"); } /* Set sample rate * snd_pcm_hw_params_set_rate_near(pcn, hw_p, *rate, * 0 (== set exact rate)) */ err = snd_pcm_hw_params_set_rate_near(pcm, hw_p, &srate, 0); ALSERT("setting samplerate"); printf("synthread: Detected samplerate of %u\n", srate); /* RW interleaved access (means we will use the snd_pcm_writei function) */ err = snd_pcm_hw_params_set_access(pcm, hw_p, SND_PCM_ACCESS_RW_INTERLEAVED); ALSERT("setting access mode"); /* native-endian 16-bit signed sample format */ err = snd_pcm_hw_params_set_format(pcm, hw_p, SND_PCM_FORMAT_S16); ALSERT("setting sample format"); /* Switch to 2.0ch audio */ err = snd_pcm_hw_params_set_channels(pcm, hw_p, 2); ALSERT("switching to 2.0ch audio"); if (config.buffer_time != -1) { /* Set configured buffer time */ err = snd_pcm_hw_params_set_buffer_time_near(pcm, hw_p, &config.buffer_time, &dir); ALSERT("setting buffer time"); /* Fetch resulting size */ err = snd_pcm_hw_params_get_buffer_size(hw_p, &buffer_size); ALSERT("getting buffer size"); } else { /* Since we want the interactive synthesizer to be very responsive * select a minimum buffer size. */ err = snd_pcm_hw_params_set_buffer_size_first(pcm, hw_p, &buffer_size); ALSERT("setting buffer size"); } printf("synthread: Selected buffersize of %lu\n", buffer_size); printf("synthread: Response delay is approximately %.2f ms\n", (double)buffer_size / (double)srate * 1000.0); if (config.period_time != -1) { err = snd_pcm_hw_params_set_period_time_near(pcm, hw_p, &config.period_time, &dir); ALSERT("setting period time"); err = snd_pcm_hw_params_get_period_size(hw_p, &period_size, &dir); ALSERT("getting period size"); } else { /* Select a period time of half the buffer time * since this improves processing performance */ err = snd_pcm_hw_params_set_period_size_last(pcm, hw_p, &period_size, &dir); ALSERT("setting period size"); } if (dir) printf("synthread: Selected period size near %lu\n", period_size); else printf("synthread: Selected period size of %lu\n", period_size); /* write hw parameters to device */ err = snd_pcm_hw_params(pcm, hw_p); ALSERT("writing hw params"); /* Begin ALSA software side setup */ /* Allocate SW params */ err = snd_pcm_sw_params_malloc(&sw_p); ALSERT("allocating sw params"); /* Request software current settings */ err = snd_pcm_sw_params_current(pcm, sw_p); ALSERT("requesting current sw params"); /* Automatically start playing after the first period is written */ err = snd_pcm_sw_params_set_start_threshold(pcm, sw_p, period_size); ALSERT("settings start threshold"); /* XRUN when buffer is empty */ err = snd_pcm_sw_params_set_stop_threshold(pcm, sw_p, buffer_size * 2); ALSERT("setting stop threshold"); /* Block synthesizer when there is not at least period frames available */ err = snd_pcm_sw_params_set_avail_min(pcm, sw_p, period_size); ALSERT("setting minimum free frames"); /* Write software parameters */ err = snd_pcm_sw_params(pcm, sw_p); ALSERT("writing sw params"); printf("synthread: Audio system configured.\n"); /* Prepare device for playback */ err = snd_pcm_prepare(pcm); ALSERT("preparing device"); /* Allocate a period sized framebuffer * (yup an audio buffer is in ALSA speak indeed called a framebuffer) */ fb = malloc(sizeof(struct _msynth_frame) * period_size); if (!fb) { perror("malloc framebuffer failed"); exit(1); } /* Set sampleclock to 0 */ sc.samples = 0; sc.samplerate = srate; sc.cycle = 0.0f; sc.seconds = 0.0f; /* Initially the <root> variable describing the flow of sound within * the synthesizer is configured to be a NULL signal. (silence) */ /* Signal successful completion of initialization */ pthread_mutex_lock(&mutex); pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); /* -------------- Main loop --------------- */ while (!shutdown) { /* Only during generation we need the synth tree to be static */ synth_lock_graphs(); for (i = 0; i < period_size; i++) { /* Evaluate variables */ ssv_eval(sc); sample = (int)(32767.5 * ssv_get_var_eval("left") * volume); /* Clip samples */ if (sample > 32767) sample = 32767; if (sample < -32768) sample = -32768; fb[i].left = (short)sample; sample = (int)(32767.5 * ssv_get_var_eval("right") * volume); /* Clip samples */ if (sample > 32767) sample = 32767; if (sample < -32768) sample = -32768; fb[i].right = (short)sample; sc = sc_from_samples(sc.samplerate, sc.samples + 1); } synth_unlock_graphs(); /* Send audio to sound card */ processed = 0; while (processed != period_size) { err = snd_pcm_writei(pcm, fb + processed, period_size - processed); /* Retry on interruption by signal */ if (err == -EAGAIN) continue; /* Recover from XRUN/suspend */ if (err < 0) { err = synth_recover(err); ALSERT("sending audio"); continue; } /* Update processed samples */ processed += err; } } puts("synthread: shutting down"); /* Dump any statistics recorded */ if (recover_resumes) printf("synthread: Device was resumed %i times\n", recover_resumes); if (recover_xruns) printf("synthread: %i xrun recoveries were needed\n", recover_xruns); printf("synthread: processed %i samples\n", sc.samples); /* Wait for playback to complete */ err = snd_pcm_drain(pcm); ALSERT("draining device"); /* Shutdown PCM device */ err = snd_pcm_close(pcm); ALSERT("closing audio device"); /* Clean up parameters */ snd_pcm_hw_params_free(hw_p); snd_pcm_sw_params_free(sw_p); return NULL; }
static int palsa_init (void) { int err; // get and cache conf variables conf_alsa_resample = deadbeef->conf_get_int ("alsa.resample", 1); deadbeef->conf_get_str ("alsa_soundcard", "default", conf_alsa_soundcard, sizeof (conf_alsa_soundcard)); trace ("alsa_soundcard: %s\n", conf_alsa_soundcard); snd_pcm_sw_params_t *sw_params = NULL; state = OUTPUT_STATE_STOPPED; //const char *conf_alsa_soundcard = conf_get_str ("alsa_soundcard", "default"); if ((err = snd_pcm_open (&audio, conf_alsa_soundcard, SND_PCM_STREAM_PLAYBACK, 0))) { fprintf (stderr, "could not open audio device (%s)\n", snd_strerror (err)); return -1; } if (requested_fmt.samplerate != 0) { memcpy (&plugin.fmt, &requested_fmt, sizeof (ddb_waveformat_t)); } if (palsa_set_hw_params (&plugin.fmt) < 0) { goto open_error; } if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) { fprintf (stderr, "cannot allocate software parameters structure (%s)\n", snd_strerror (err)); goto open_error; } if ((err = snd_pcm_sw_params_current (audio, sw_params)) < 0) { fprintf (stderr, "cannot initialize software parameters structure (%s)\n", snd_strerror (err)); goto open_error; } snd_pcm_sw_params_set_start_threshold (audio, sw_params, buffer_size - period_size); if ((err = snd_pcm_sw_params_set_avail_min (audio, sw_params, period_size)) < 0) { fprintf (stderr, "cannot set minimum available count (%s)\n", snd_strerror (err)); goto open_error; } snd_pcm_uframes_t av; if ((err = snd_pcm_sw_params_get_avail_min (sw_params, &av)) < 0) { fprintf (stderr, "snd_pcm_sw_params_get_avail_min failed (%s)\n", snd_strerror (err)); goto open_error; } trace ("alsa avail_min: %d frames\n", (int)av); // if ((err = snd_pcm_sw_params_set_start_threshold (audio, sw_params, 0U)) < 0) { // trace ("cannot set start mode (%s)\n", // snd_strerror (err)); // goto open_error; // } if ((err = snd_pcm_sw_params (audio, sw_params)) < 0) { fprintf (stderr, "cannot set software parameters (%s)\n", snd_strerror (err)); goto open_error; } snd_pcm_sw_params_free (sw_params); sw_params = NULL; /* the interface will interrupt the kernel every N frames, and ALSA will wake up this program very soon after that. */ if ((err = snd_pcm_prepare (audio)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); goto open_error; } alsa_terminate = 0; alsa_tid = deadbeef->thread_start (palsa_thread, NULL); return 0; open_error: if (sw_params) { snd_pcm_sw_params_free (sw_params); } if (audio != NULL) { palsa_free (); } return -1; }
static void init_audio(const char* devname) { snd_pcm_hw_params_t* hwparams = 0; snd_pcm_sw_params_t* swparams = 0; snd_pcm_uframes_t bufsize = 0; unsigned int buftime = 1000000; unsigned int pertime = 50000; int dir = 0; int rc; if ((rc = snd_output_stdio_attach(&output, stderr, 0)) < 0) exit_snd_error(rc, "log output"); if ((rc = snd_pcm_open(&audio, devname, SND_PCM_STREAM_PLAYBACK, 0)) < 0) exit_snd_error(rc, "opening device"); if ((rc = snd_pcm_hw_params_malloc(&hwparams)) < 0) exit_snd_error(rc, "hardware parameters"); if ((rc = snd_pcm_hw_params_any(audio, hwparams)) < 0) exit_snd_error(rc, "hardware parameters"); if ((rc = snd_pcm_hw_params_set_rate_resample(audio, hwparams, 0)) < 0) exit_snd_error(rc, "hardware parameters"); if ((rc = snd_pcm_hw_params_set_access(audio, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) exit_snd_error(rc, "access type"); if ((rc = snd_pcm_hw_params_set_format(audio, hwparams, SND_PCM_FORMAT_S16)) < 0) exit_snd_error(rc, "sample format"); if ((rc = snd_pcm_hw_params_set_channels_near(audio, hwparams, &n_channels)) < 0) exit_snd_error(rc, "number of channels"); if ((rc = snd_pcm_hw_params_set_rate_near(audio, hwparams, &samplerate, &dir)) < 0) exit_snd_error(rc, "sample rate"); if ((rc = snd_pcm_hw_params_set_buffer_time_near(audio, hwparams, &buftime, &dir)) < 0) exit_snd_error(rc, "buffer time"); if ((rc = snd_pcm_hw_params_set_period_time_near(audio, hwparams, &pertime, &dir)) < 0) exit_snd_error(rc, "period time"); if ((rc = snd_pcm_hw_params(audio, hwparams)) < 0) exit_snd_error(rc, "applying hardware parameters"); if ((rc = snd_pcm_hw_params_get_buffer_size(hwparams, &bufsize)) < 0) exit_snd_error(rc, "buffer size"); if ((rc = snd_pcm_hw_params_get_period_size(hwparams, &periodsize, &dir)) < 0) exit_snd_error(rc, "period size"); snd_pcm_hw_params_free(hwparams); if ((rc = snd_pcm_sw_params_malloc(&swparams)) < 0) exit_snd_error(rc, "software parameters"); if ((rc = snd_pcm_sw_params_current(audio, swparams)) < 0) exit_snd_error(rc, "software parameters"); if ((rc = snd_pcm_sw_params_set_start_threshold(audio, swparams, bufsize / periodsize * periodsize)) < 0) exit_snd_error(rc, "start threshold"); if ((rc = snd_pcm_sw_params(audio, swparams)) < 0) exit_snd_error(rc, "applying software parameters"); snd_pcm_sw_params_free(swparams); if ((rc = snd_pcm_prepare(audio)) < 0) exit_snd_error(rc, "preparing device"); }
static snd_pcm_t * alsa_open (int channels, unsigned samplerate, int realtime) { const char * device = "default" ; snd_pcm_t *alsa_dev = NULL ; snd_pcm_hw_params_t *hw_params ; snd_pcm_uframes_t buffer_size ; snd_pcm_uframes_t alsa_period_size, alsa_buffer_frames ; snd_pcm_sw_params_t *sw_params ; int err ; if (realtime) { alsa_period_size = 256 ; alsa_buffer_frames = 3 * alsa_period_size ; } else { alsa_period_size = 1024 ; alsa_buffer_frames = 4 * alsa_period_size ; } ; if ((err = snd_pcm_open (&alsa_dev, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf (stderr, "cannot open audio device \"%s\" (%s)\n", device, snd_strerror (err)) ; goto catch_error ; } ; snd_pcm_nonblock (alsa_dev, 0) ; if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)) ; goto catch_error ; } ; if ((err = snd_pcm_hw_params_any (alsa_dev, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)) ; goto catch_error ; } ; if ((err = snd_pcm_hw_params_set_access (alsa_dev, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)) ; goto catch_error ; } ; if ((err = snd_pcm_hw_params_set_format (alsa_dev, hw_params, SND_PCM_FORMAT_FLOAT)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)) ; goto catch_error ; } ; if ((err = snd_pcm_hw_params_set_rate_near (alsa_dev, hw_params, &samplerate, 0)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)) ; goto catch_error ; } ; if ((err = snd_pcm_hw_params_set_channels (alsa_dev, hw_params, channels)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)) ; goto catch_error ; } ; if ((err = snd_pcm_hw_params_set_buffer_size_near (alsa_dev, hw_params, &alsa_buffer_frames)) < 0) { fprintf (stderr, "cannot set buffer size (%s)\n", snd_strerror (err)) ; goto catch_error ; } ; if ((err = snd_pcm_hw_params_set_period_size_near (alsa_dev, hw_params, &alsa_period_size, 0)) < 0) { fprintf (stderr, "cannot set period size (%s)\n", snd_strerror (err)) ; goto catch_error ; } ; if ((err = snd_pcm_hw_params (alsa_dev, hw_params)) < 0) { fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err)) ; goto catch_error ; } ; /* extra check: if we have only one period, this code won't work */ snd_pcm_hw_params_get_period_size (hw_params, &alsa_period_size, 0) ; snd_pcm_hw_params_get_buffer_size (hw_params, &buffer_size) ; if (alsa_period_size == buffer_size) { fprintf (stderr, "Can't use period equal to buffer size (%lu == %lu)", alsa_period_size, buffer_size) ; goto catch_error ; } ; snd_pcm_hw_params_free (hw_params) ; if ((err = snd_pcm_sw_params_malloc (&sw_params)) != 0) { fprintf (stderr, "%s: snd_pcm_sw_params_malloc: %s", __func__, snd_strerror (err)) ; goto catch_error ; } ; if ((err = snd_pcm_sw_params_current (alsa_dev, sw_params)) != 0) { fprintf (stderr, "%s: snd_pcm_sw_params_current: %s", __func__, snd_strerror (err)) ; goto catch_error ; } ; /* note: set start threshold to delay start until the ring buffer is full */ snd_pcm_sw_params_current (alsa_dev, sw_params) ; if ((err = snd_pcm_sw_params_set_start_threshold (alsa_dev, sw_params, buffer_size)) < 0) { fprintf (stderr, "cannot set start threshold (%s)\n", snd_strerror (err)) ; goto catch_error ; } ; if ((err = snd_pcm_sw_params (alsa_dev, sw_params)) != 0) { fprintf (stderr, "%s: snd_pcm_sw_params: %s", __func__, snd_strerror (err)) ; goto catch_error ; } ; snd_pcm_sw_params_free (sw_params) ; snd_pcm_reset (alsa_dev) ; catch_error : if (err < 0 && alsa_dev != NULL) { snd_pcm_close (alsa_dev) ; return NULL ; } ; return alsa_dev ; } /* alsa_open */
/*---------------------------------------------------------------- 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; }
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; }
static int set_swparams (GstAlsaSrc * alsa) { int err; snd_pcm_sw_params_t *params; snd_pcm_sw_params_malloc (¶ms); /* get the current swparams */ CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config); /* allow the transfer when at least period_size samples can be processed */ CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params, alsa->period_size), set_avail); /* start the transfer on first read */ CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params, 0), start_threshold); /* use monotonic timestamping */ CHECK (snd_pcm_sw_params_set_tstamp_mode (alsa->handle, params, SND_PCM_TSTAMP_MMAP), tstamp_mode); #if GST_CHECK_ALSA_VERSION(1,0,16) /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */ #else /* align all transfers to 1 sample */ CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align); #endif /* write the parameters to the recording device */ CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params); snd_pcm_sw_params_free (params); return 0; /* ERRORS */ no_config: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to determine current swparams for playback: %s", snd_strerror (err))); snd_pcm_sw_params_free (params); return err; } start_threshold: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set start threshold mode for playback: %s", snd_strerror (err))); snd_pcm_sw_params_free (params); return err; } set_avail: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set avail min for playback: %s", snd_strerror (err))); snd_pcm_sw_params_free (params); return err; } tstamp_mode: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set tstamp mode for playback: %s", snd_strerror (err))); snd_pcm_sw_params_free (params); return err; } #if !GST_CHECK_ALSA_VERSION(1,0,16) set_align: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set transfer align for playback: %s", snd_strerror (err))); snd_pcm_sw_params_free (params); return err; } #endif set_sw_params: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Unable to set sw params for playback: %s", snd_strerror (err))); snd_pcm_sw_params_free (params); return err; } }
status_t setSoftwareParams(alsa_handle_t *handle) { snd_pcm_sw_params_t * softwareParams; int err; snd_pcm_uframes_t bufferSize = 0; snd_pcm_uframes_t periodSize = 0; snd_pcm_uframes_t startThreshold, stopThreshold; if (snd_pcm_sw_params_malloc(&softwareParams) < 0) { LOG_ALWAYS_FATAL("Failed to allocate ALSA software parameters!"); return NO_INIT; } // Get the current software parameters err = snd_pcm_sw_params_current(handle->handle, softwareParams); if (err < 0) { LOGE("Unable to get software parameters: %s", snd_strerror(err)); goto done; } // Configure ALSA to start the transfer when the buffer is almost full. snd_pcm_get_params(handle->handle, &bufferSize, &periodSize); if (handle->devices & AudioSystem::DEVICE_OUT_ALL) { // For playback, configure ALSA to start the transfer when the // buffer is full. startThreshold = bufferSize - 1; stopThreshold = bufferSize; } else { // For recording, configure ALSA to start the transfer on the // first frame. startThreshold = 1; stopThreshold = bufferSize; } err = snd_pcm_sw_params_set_start_threshold(handle->handle, softwareParams, startThreshold); if (err < 0) { LOGE("Unable to set start threshold to %lu frames: %s", startThreshold, snd_strerror(err)); goto done; } err = snd_pcm_sw_params_set_stop_threshold(handle->handle, softwareParams, stopThreshold); if (err < 0) { LOGE("Unable to set stop threshold to %lu frames: %s", stopThreshold, snd_strerror(err)); goto done; } // Allow the transfer to start when at least periodSize samples can be // processed. err = snd_pcm_sw_params_set_avail_min(handle->handle, softwareParams, periodSize); if (err < 0) { LOGE("Unable to configure available minimum to %lu: %s", periodSize, snd_strerror(err)); goto done; } // Commit the software parameters back to the device. err = snd_pcm_sw_params(handle->handle, softwareParams); if (err < 0) LOGE("Unable to configure software parameters: %s", snd_strerror(err)); done: snd_pcm_sw_params_free(softwareParams); return err; }
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(¶ms)); 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; }
static ALCboolean alsa_reset_playback(ALCdevice *device) { alsa_data *data = (alsa_data*)device->ExtraData; snd_pcm_uframes_t periodSizeInFrames; unsigned int periodLen, bufferLen; snd_pcm_sw_params_t *sp = NULL; snd_pcm_hw_params_t *hp = NULL; snd_pcm_access_t access; snd_pcm_format_t format; unsigned int periods; unsigned int rate; const char *funcerr; int allowmmap; int err; 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; } allowmmap = GetConfigValueBool("alsa", "mmap", 1); periods = device->NumUpdates; periodLen = (ALuint64)device->UpdateSize * 1000000 / device->Frequency; bufferLen = periodLen * periods; rate = device->Frequency; 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 */ if(!allowmmap || snd_pcm_hw_params_set_access(data->pcmHandle, hp, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) { if(periods > 2) { periods--; bufferLen = periodLen * periods; } CHECK(snd_pcm_hw_params_set_access(data->pcmHandle, hp, SND_PCM_ACCESS_RW_INTERLEAVED)); } /* test and set format (implicitly sets sample bits) */ if(snd_pcm_hw_params_test_format(data->pcmHandle, hp, format) < 0) { static const struct { snd_pcm_format_t format; enum DevFmtType fmttype; } formatlist[] = { { SND_PCM_FORMAT_FLOAT, DevFmtFloat }, { SND_PCM_FORMAT_S32, DevFmtInt }, { SND_PCM_FORMAT_U32, DevFmtUInt }, { SND_PCM_FORMAT_S16, DevFmtShort }, { SND_PCM_FORMAT_U16, DevFmtUShort }, { SND_PCM_FORMAT_S8, DevFmtByte }, { SND_PCM_FORMAT_U8, DevFmtUByte }, }; size_t k; for(k = 0;k < COUNTOF(formatlist);k++) { format = formatlist[k].format; if(snd_pcm_hw_params_test_format(data->pcmHandle, hp, format) >= 0) { device->FmtType = formatlist[k].fmttype; break; } } } CHECK(snd_pcm_hw_params_set_format(data->pcmHandle, hp, format)); /* test and set channels (implicitly sets frame bits) */ if(snd_pcm_hw_params_test_channels(data->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans)) < 0) { static const enum DevFmtChannels channellist[] = { DevFmtStereo, DevFmtQuad, DevFmtX51, DevFmtX71, DevFmtMono, }; size_t k; for(k = 0;k < COUNTOF(channellist);k++) { if(snd_pcm_hw_params_test_channels(data->pcmHandle, hp, ChannelsFromDevFmt(channellist[k])) >= 0) { device->FmtChans = channellist[k]; break; } } } CHECK(snd_pcm_hw_params_set_channels(data->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans))); /* set rate (implicitly constrains period/buffer parameters) */ if(snd_pcm_hw_params_set_rate_resample(data->pcmHandle, hp, 0) < 0) ERR("Failed to disable ALSA resampler\n"); CHECK(snd_pcm_hw_params_set_rate_near(data->pcmHandle, hp, &rate, NULL)); /* set buffer time (implicitly constrains period/buffer parameters) */ CHECK(snd_pcm_hw_params_set_buffer_time_near(data->pcmHandle, hp, &bufferLen, NULL)); /* set period time (implicitly sets buffer size/bytes/time and period size/bytes) */ CHECK(snd_pcm_hw_params_set_period_time_near(data->pcmHandle, hp, &periodLen, NULL)); /* install and prepare hardware configuration */ CHECK(snd_pcm_hw_params(data->pcmHandle, hp)); /* retrieve configuration info */ CHECK(snd_pcm_hw_params_get_access(hp, &access)); CHECK(snd_pcm_hw_params_get_period_size(hp, &periodSizeInFrames, NULL)); CHECK(snd_pcm_hw_params_get_periods(hp, &periods, NULL)); snd_pcm_hw_params_free(hp); hp = NULL; snd_pcm_sw_params_malloc(&sp); CHECK(snd_pcm_sw_params_current(data->pcmHandle, sp)); CHECK(snd_pcm_sw_params_set_avail_min(data->pcmHandle, sp, periodSizeInFrames)); CHECK(snd_pcm_sw_params_set_stop_threshold(data->pcmHandle, sp, periodSizeInFrames*periods)); CHECK(snd_pcm_sw_params(data->pcmHandle, sp)); #undef CHECK snd_pcm_sw_params_free(sp); sp = NULL; /* Increase periods by one, since the temp buffer counts as an extra * period */ if(access == SND_PCM_ACCESS_RW_INTERLEAVED) device->NumUpdates = periods+1; else device->NumUpdates = periods; device->UpdateSize = periodSizeInFrames; device->Frequency = rate; SetDefaultChannelOrder(device); return ALC_TRUE; error: ERR("%s failed: %s\n", funcerr, snd_strerror(err)); if(hp) snd_pcm_hw_params_free(hp); if(sp) snd_pcm_sw_params_free(sp); return ALC_FALSE; }
static void rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa) { snd_pcm_hw_params_t* hw_params; snd_pcm_sw_params_t* sw_params; int error; snd_pcm_uframes_t frames; snd_pcm_uframes_t start_threshold; snd_pcm_drop(alsa->out_handle); error = snd_pcm_hw_params_malloc(&hw_params); if (error < 0) { DEBUG_WARN("snd_pcm_hw_params_malloc failed"); return; } snd_pcm_hw_params_any(alsa->out_handle, hw_params); snd_pcm_hw_params_set_access(alsa->out_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(alsa->out_handle, hw_params, alsa->format); snd_pcm_hw_params_set_rate_near(alsa->out_handle, hw_params, &alsa->actual_rate, NULL); snd_pcm_hw_params_set_channels_near(alsa->out_handle, hw_params, &alsa->actual_channels); if (alsa->latency < 0) frames = alsa->actual_rate * 4; /* Default to 4-second buffer */ else frames = alsa->latency * alsa->actual_rate * 2 / 1000; /* Double of the latency */ if (frames < alsa->actual_rate / 2) frames = alsa->actual_rate / 2; /* Minimum 0.5-second buffer */ snd_pcm_hw_params_set_buffer_size_near(alsa->out_handle, hw_params, &frames); snd_pcm_hw_params(alsa->out_handle, hw_params); snd_pcm_hw_params_free(hw_params); error = snd_pcm_sw_params_malloc(&sw_params); if (error < 0) { DEBUG_WARN("snd_pcm_sw_params_malloc failed"); return; } snd_pcm_sw_params_current(alsa->out_handle, sw_params); if (alsa->latency == 0) start_threshold = 0; else start_threshold = frames / 2; snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params, start_threshold); snd_pcm_sw_params(alsa->out_handle, sw_params); snd_pcm_sw_params_free(sw_params); snd_pcm_prepare(alsa->out_handle); DEBUG_SVC("hardware buffer %d frames, playback buffer %.2g seconds", (int)frames, (double)frames / 2.0 / (double)alsa->actual_rate); if ((alsa->actual_rate != alsa->source_rate) || (alsa->actual_channels != alsa->source_channels)) { DEBUG_SVC("actual rate %d / channel %d is different from source rate %d / channel %d, resampling required.", alsa->actual_rate, alsa->actual_channels, alsa->source_rate, alsa->source_channels); } }
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; }