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 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; }
AudioAlsa::AudioAlsa( bool & _success_ful, Mixer* _mixer ) : AudioDevice( tLimit<ch_cnt_t>( ConfigManager::inst()->value( "audioalsa", "channels" ).toInt(), DEFAULT_CHANNELS, SURROUND_CHANNELS ), _mixer ), m_handle( NULL ), m_hwParams( NULL ), m_swParams( NULL ), m_convertEndian( false ) { _success_ful = false; int err; if( ( err = snd_pcm_open( &m_handle, probeDevice().toLatin1().constData(), SND_PCM_STREAM_PLAYBACK, 0 ) ) < 0 ) { printf( "Playback open error: %s\n", snd_strerror( err ) ); return; } snd_pcm_hw_params_malloc( &m_hwParams ); snd_pcm_sw_params_malloc( &m_swParams ); if( ( err = setHWParams( channels(), SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 ) { printf( "Setting of hwparams failed: %s\n", snd_strerror( err ) ); return; } if( ( err = setSWParams() ) < 0 ) { printf( "Setting of swparams failed: %s\n", snd_strerror( err ) ); return; } // set FD_CLOEXEC flag for all file descriptors so forked processes // do not inherit them struct pollfd * ufds; int count = snd_pcm_poll_descriptors_count( m_handle ); ufds = new pollfd[count]; snd_pcm_poll_descriptors( m_handle, ufds, count ); for( int i = 0; i < qMax( 3, count ); ++i ) { const int fd = ( i >= count ) ? ufds[0].fd+i : ufds[i].fd; int oldflags = fcntl( fd, F_GETFD, 0 ); if( oldflags < 0 ) continue; oldflags |= FD_CLOEXEC; fcntl( fd, F_SETFD, oldflags ); } delete[] ufds; _success_ful = true; }
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; }
static void * alsa_new (void) { guint i; gint err; alsa_driver *d = g_new(alsa_driver, 1); d->device = g_strdup("hw:0,0"); d->bits = 8; d->stereo = 0; d->buffer_size = 14; d->playrate = 44100; d->minfreq_old = 0; d->maxfreq_old = 0; d->address_old = 0; d->bufsize_old = 0; d->num_periods = 1; d->can8 = TRUE; d->can16 = TRUE; d->canmono = TRUE; d->canstereo = TRUE; d->signedness8 = FALSE; d->signedness16 = TRUE; d->persizemin = 256; d->persizemax = 8192; for(i = 0; i < NUM_FORMATS; i++) { d->devcap[i].minfreq = 22050; d->devcap[i].maxfreq = 44100; d->devcap[i].minbufsize = 512; d->devcap[i].maxbufsize = 16384; } d->soundfd = 0; d->sndbuf = NULL; d->polltag = NULL; d->pfd = NULL; d->verbose = FALSE; d->hwtest = TRUE; if((err = snd_output_stdio_attach(&(d->output), stdout,0)) < 0) { alsa_error(N_("Error attaching sound output"), err); return NULL; } snd_pcm_hw_params_malloc(&(d->hwparams)); snd_pcm_sw_params_malloc(&(d->swparams)); alsa_make_config_widgets(d); return d; }
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; }
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); }
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 */
/** * 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(); } }
/** * This method prepares ALSA system for 22050hz signed 16bits Little Endian * playback. */ void SoundThread::initAlsa() { int err; ostringstream oss; /* Get a handle on the PCM device. */ if ((err = snd_pcm_open (&playback_handle, deviceName, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { oss << "cannot open audio device : " << deviceName << snd_strerror(err) << endl; throw oss.str(); } /* Allocate snd_pcm_hw_params_t structure. */ if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { oss << "cannot allocate hardware parameter structure : " << snd_strerror (err) << endl; throw oss.str(); } /* Retrieve current parameters. */ if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) { oss << "cannot initialize hardware parameter structure : " << snd_strerror (err) << endl; throw oss.str(); } /* Set Sample are NON Interleaved (mono !) */ if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED)) < 0) { oss << "cannot set access type : " << snd_strerror (err) << endl; throw oss.str(); } /* Set Sample format: Signed 16bit little endian. */ if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { oss << "cannot set sample format : " << snd_strerror (err) << endl; throw oss.str(); } /* Set the Sample rate. */ if ((err = snd_pcm_hw_params_set_rate (playback_handle, hw_params, 22050, 0)) < 0) { oss << "cannot set sample rate : " << snd_strerror (err) << endl; throw oss.str(); } /* Set Channel number (MONO). */ if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 1)) < 0) { oss << "cannot set channel count : " << snd_strerror (err) << endl; throw oss.str(); } if ((err = snd_pcm_hw_params_set_buffer_size(playback_handle, hw_params, 2048)) < 0) { oss << "cannot set channel buffer size : " << snd_strerror (err) << endl; throw oss.str(); } /* Apply these parameters. */ if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) { oss << "cannot apply parameters : " << snd_strerror (err) << endl; throw oss.str(); } snd_pcm_uframes_t bufferSize; snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize ); //cout << "initAlsa: Buffer size = " << bufferSize << " frames." << endl; /* Free memoray allocated for snd_pcm_hw_params_t */ snd_pcm_hw_params_free (hw_params); /* tell ALSA to wake us up whenever 4096 or more frames of playback data can be delivered. Also, tell ALSA that we'll start the device ourselves. */ /* Allocate snd_pcm_sw_params_t structure. */ if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) { oss << "cannot allocate software parameters structure : " << snd_strerror (err) << endl; throw oss.str(); } /* Get the current software configuration*/ if ((err = snd_pcm_sw_params_current (playback_handle, sw_params)) < 0) { oss << "cannot initialize software parameters structure : " << snd_strerror (err) << endl; throw oss.str(); } /* Set the wake up point to 2048 (92.9 ms). The minimum data available before asking*/ /* for new ones. */ if ((err = snd_pcm_sw_params_set_avail_min (playback_handle, sw_params, 2048U)) < 0) { oss << "cannot set minimum available count : " << snd_strerror (err) << endl; throw oss.str(); } /* Set when ALSA starts to play. */ if ((err = snd_pcm_sw_params_set_start_threshold (playback_handle, sw_params, 1024U)) < 0) { oss << "cannot set start mode : " << snd_strerror (err) << endl; throw oss.str(); } /* Apply parameters. */ if ((err = snd_pcm_sw_params (playback_handle, sw_params)) < 0) { oss << "cannot apply software parameters : " << snd_strerror (err) << endl; throw oss.str(); } /* the interface will interrupt the kernel every 4096 frames, and ALSA will wake up this program very soon after that. */ if ((err = snd_pcm_prepare (playback_handle)) < 0) { oss << "cannot prepare audio interface for use : " << snd_strerror (err) << endl; throw oss.str(); } }
main (int argc, char *argv[]) { snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; snd_pcm_sframes_t frames_to_deliver; int nfds; int err; struct pollfd *pfds; if ((err = snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf (stderr, "cannot open audio device %s (%s)\n", argv[1], snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, 44100, 0)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 2)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) { fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err)); exit (1); } snd_pcm_hw_params_free (hw_params); if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) { fprintf (stderr, "cannot allocate software parameters structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_sw_params_current (playback_handle, sw_params)) < 0) { fprintf (stderr, "cannot initialize software parameters structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_sw_params_set_avail_min (playback_handle, sw_params, 4096)) < 0) { fprintf (stderr, "cannot set minimum available count (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_sw_params_set_start_threshold (playback_handle, sw_params, 0U)) < 0) { fprintf (stderr, "cannot set start mode (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_sw_params (playback_handle, sw_params)) < 0) { fprintf (stderr, "cannot set software parameters (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_prepare (playback_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); exit (1); } while (1) { if ((err = snd_pcm_wait (playback_handle, 1000)) < 0) { fprintf (stderr, "poll failed (%s)\n", strerror (errno)); break; } if ((frames_to_deliver = snd_pcm_avail_update (playback_handle)) < 0) { if (frames_to_deliver == -EPIPE) { fprintf (stderr, "an xrun occured\n"); break; } else { fprintf (stderr, "unknown ALSA avail update return value (%d)\n", frames_to_deliver); break; } } frames_to_deliver = frames_to_deliver > 4096 ? 4096 : frames_to_deliver; if (playback_callback (frames_to_deliver) != frames_to_deliver) { fprintf (stderr, "playback callback failed\n"); break; } } snd_pcm_close (playback_handle); exit (0); }
void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource, int encoding, float sampleRate, int sampleSizeInBits, int frameSize, int channels, int isSigned, int isBigEndian, int bufferSizeInBytes) { snd_pcm_format_mask_t* formatMask; snd_pcm_format_t format; int dir; int ret = 0; AlsaPcmInfo* info = NULL; /* snd_pcm_uframes_t is 64 bit on 64-bit systems */ snd_pcm_uframes_t alsaPeriodSize = 0; snd_pcm_uframes_t alsaBufferSizeInFrames = 0; TRACE0("> DAUDIO_Open\n"); #ifdef USE_TRACE // for using ALSA debug dump methods if (ALSA_OUTPUT == NULL) { snd_output_stdio_attach(&ALSA_OUTPUT, stdout, 0); } #endif info = (AlsaPcmInfo*) malloc(sizeof(AlsaPcmInfo)); if (!info) { ERROR0("Out of memory\n"); return NULL; } memset(info, 0, sizeof(AlsaPcmInfo)); ret = openPCMfromDeviceID(deviceID, &(info->handle), isSource, FALSE /* do open device*/); if (ret == 0) { // set to blocking mode snd_pcm_nonblock(info->handle, 0); ret = snd_pcm_hw_params_malloc(&(info->hwParams)); if (ret != 0) { ERROR1(" snd_pcm_hw_params_malloc returned error %d\n", ret); } else { ret = -1; if (getAlsaFormatFromFormat(&format, frameSize / channels, sampleSizeInBits, isSigned, isBigEndian, encoding)) { if (setHWParams(info, sampleRate, channels, bufferSizeInBytes / frameSize, format)) { info->frameSize = frameSize; #ifdef ALSA_PCM_NEW_HW_PARAMS_API ret = snd_pcm_hw_params_get_period_size(info->hwParams, &alsaPeriodSize, &dir); info->periodSize = (int) alsaPeriodSize; if (ret < 0) { ERROR1("ERROR: snd_pcm_hw_params_get_period: %s\n", snd_strerror(ret)); } snd_pcm_hw_params_get_periods(info->hwParams, &(info->periods), &dir); snd_pcm_hw_params_get_buffer_size(info->hwParams, &alsaBufferSizeInFrames); info->bufferSizeInBytes = (int) alsaBufferSizeInFrames * frameSize; #else info->periodSize = snd_pcm_hw_params_get_period_size(info->hwParams, &dir); info->periods = snd_pcm_hw_params_get_periods(info->hwParams, &dir); info->bufferSizeInBytes = snd_pcm_hw_params_get_buffer_size(info->hwParams) * frameSize; ret = 0; #endif TRACE3(" DAUDIO_Open: period size = %d frames, periods = %d. Buffer size: %d bytes.\n", (int) info->periodSize, info->periods, info->bufferSizeInBytes); } } } if (ret == 0) { // set software parameters ret = snd_pcm_sw_params_malloc(&(info->swParams)); if (ret != 0) { ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret); } else { if (!setSWParams(info)) { ret = -1; } } } if (ret == 0) { // prepare device ret = snd_pcm_prepare(info->handle); if (ret < 0) { ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret)); } } #ifdef GET_POSITION_METHOD2 if (ret == 0) { ret = snd_pcm_status_malloc(&(info->positionStatus)); if (ret != 0) { ERROR1("ERROR in snd_pcm_status_malloc: %s\n", snd_strerror(ret)); } } #endif } if (ret != 0) { DAUDIO_Close((void*) info, isSource); info = NULL; } else { // set to non-blocking mode snd_pcm_nonblock(info->handle, 1); TRACE1("< DAUDIO_Open: Opened device successfully. Handle=%p\n", (void*) info->handle); } return (void*) info; }
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; }
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); } }
/** * \brief Opens a ordinary pcm instance * \param ppcm Returned ordinary pcm handle * \param playback_name ASCII identifier of the ordinary pcm handle (playback) * \param capture_name ASCII identifier of the ordinary pcm handle (capture) * \param lconf Local configuration (might be NULL - use global configuration) * \return 0 on success otherwise a negative error code */ int sndo_pcm_open(sndo_pcm_t **ppcm, const char *playback_name, const char *capture_name, struct alisp_cfg *lconf) { int err = 0; sndo_pcm_t *pcm; assert(ppcm); assert(playback_name || capture_name); *ppcm = NULL; pcm = calloc(1, sizeof(sndo_pcm_t)); if (pcm == NULL) return -ENOMEM; if (playback_name) { err = snd_pcm_hw_params_malloc(&pcm->p_hw_params); if (err < 0) goto __end; err = snd_pcm_sw_params_malloc(&pcm->p_sw_params); } if (capture_name) { err = snd_pcm_hw_params_malloc(&pcm->c_hw_params); if (err < 0) goto __end; err = snd_pcm_sw_params_malloc(&pcm->p_sw_params); } if (err < 0) goto __end; if (lconf) { if (playback_name) { err = snd_pcm_open_lconf(&pcm->playback, playback_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK, NULL); if (err < 0) goto __end; } if (capture_name) { err = snd_pcm_open_lconf(&pcm->capture, playback_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK, NULL); if (err < 0) goto __end; } } else { if (playback_name) { err = snd_pcm_open(&pcm->playback, playback_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (err < 0) goto __end; } if (capture_name) { err = snd_pcm_open(&pcm->capture, playback_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); if (err < 0) goto __end; } } if (pcm->playback && pcm->capture) { err = snd_pcm_link(pcm->playback, pcm->capture); if (err < 0) goto __end; pcm->master = pcm->playback; } __end: if (err < 0) sndo_pcm_close(pcm); return err; }
bool WaveRecorder::init(uint32_t samples_per_sec, uint32_t bits_per_sample, uint32_t channels, uint32_t frame_size) { const char* pcm_device = "default"; snd_pcm_format_t format; int err; _frame_size = frame_size; switch (bits_per_sample) { case 8: format = SND_PCM_FORMAT_S8; break; case 16: format = SND_PCM_FORMAT_S16_LE; break; default: return false; } if ((err = snd_pcm_open(&_pcm, pcm_device, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { LOG_ERROR("cannot open audio record device %s %s", pcm_device, snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_malloc(&_hw_params)) < 0) { LOG_ERROR("cannot allocate hardware parameter structure %s", snd_strerror(err)); return false; } if ((err = snd_pcm_sw_params_malloc(&_sw_params)) < 0) { LOG_ERROR("cannot allocate software parameter structure %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_any(_pcm, _hw_params)) < 0) { LOG_ERROR("cannot initialize hardware parameter structure %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_set_rate_resample(_pcm, _hw_params, 1)) < 0) { LOG_ERROR("cannot set rate resample %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_set_access(_pcm, _hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { LOG_ERROR("cannot set access type %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_set_rate(_pcm, _hw_params, samples_per_sec, 0)) < 0) { LOG_ERROR("cannot set sample rate %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_set_channels(_pcm, _hw_params, channels)) < 0) { LOG_ERROR("cannot set channel count %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params_set_format(_pcm, _hw_params, format)) < 0) { LOG_ERROR("cannot set sample format %s", snd_strerror(err)); return false; } int direction = 0; snd_pcm_uframes_t buffer_size = (samples_per_sec * 160 / 1000) / frame_size * frame_size; if ((err = snd_pcm_hw_params_set_buffer_size_near(_pcm, _hw_params, &buffer_size)) < 0) { LOG_ERROR("cannot set buffer size %s", snd_strerror(err)); return false; } snd_pcm_uframes_t period_size = frame_size; if ((err = snd_pcm_hw_params_set_period_size_near(_pcm, _hw_params, &period_size, &direction)) < 0) { LOG_ERROR("cannot set period size near %s", snd_strerror(err)); return false; } if ((err = snd_pcm_hw_params(_pcm, _hw_params)) < 0) { LOG_ERROR("cannot set parameters %s", snd_strerror(err)); return false; } if ((err = snd_pcm_sw_params_current(_pcm, _sw_params)) < 0) { LOG_ERROR("cannot get current sw parameters %s", snd_strerror(err)); return false; } if ((err = snd_pcm_sw_params_set_start_threshold(_pcm, _sw_params, frame_size)) < 0) { LOG_ERROR("cannot set start threshold %s", snd_strerror(err)); return false; } if ((err = snd_pcm_sw_params(_pcm, _sw_params)) < 0) { LOG_ERROR("cannot set sw parameters %s", snd_strerror(err)); return false; } struct pollfd pfd; if ((err = snd_pcm_poll_descriptors(_pcm, &pfd, 1)) < 0) { LOG_ERROR("cannot get poll ID %s", snd_strerror(err)); return false; } _event_trigger = new WaveRecorder::EventTrigger(*this, pfd.fd); _client.add_event_source(*_event_trigger); return true; }
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_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 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 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 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; }
void audio_init() { unsigned int buffer_time = 50000; const char* device; int err; if(audio_initialised) return; audio_initialised = 1; device = getenv("ALSA_DEVICE"); if(!device) device = "default"; if(0 > (err = snd_pcm_open(&playback_handle, device, SND_PCM_STREAM_PLAYBACK, 0/*SND_PCM_NONBLOCK*/))) errx(EXIT_FAILURE, "Audio: Cannot open device %s: %s", device, snd_strerror(err)); if(0 > (err = snd_pcm_sw_params_malloc(&sw_params))) errx(EXIT_FAILURE, "Audio: Could not allocate software parameter structure: %s", snd_strerror(err)); if(0 > (err = snd_pcm_hw_params_malloc(&hw_params))) errx(EXIT_FAILURE, "Audio: Could not allocate hardware parameter structure: %s", snd_strerror(err)); if(0 > (err = snd_pcm_hw_params_any(playback_handle, hw_params))) errx(EXIT_FAILURE, "Audio: Could not initializa hardware parameters: %s", snd_strerror(err)); if(0 > (err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED))) errx(EXIT_FAILURE, "Audio: Could not set access type: %s", snd_strerror(err)); if(0 > (err = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16))) errx(EXIT_FAILURE, "Audio: Could not set sample format to signed 16 bit " "native endian: %s", snd_strerror(err)); if(0 > (err = snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &rate, 0))) errx(EXIT_FAILURE, "Audio: Could not set sample rate %uHz: %s", rate, snd_strerror(err)); if(0 > (err = snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2))) errx(EXIT_FAILURE, "Audio: Could not set channel count to %u: %s", 2, snd_strerror(err)); snd_pcm_hw_params_set_buffer_time_near(playback_handle, hw_params, &buffer_time, 0); if(0 > (err = snd_pcm_hw_params(playback_handle, hw_params))) errx(EXIT_FAILURE, "Audio: Could not set hardware parameters: %s", snd_strerror(err)); fprintf(stderr, "Buffer time is %.3f seconds\n", buffer_time / 1.0e6); if(0 > (err = snd_pcm_sw_params_current(playback_handle, sw_params))) errx(EXIT_FAILURE, "Audio: Could not initialise software parameters: %s", snd_strerror(err)); snd_pcm_sw_params_set_start_threshold(playback_handle, sw_params, 0); snd_pcm_sw_params_set_avail_min(playback_handle, sw_params, 1024); snd_pcm_uframes_t min; snd_pcm_sw_params_get_avail_min(sw_params, &min); fprintf(stderr, "Minimum %u\n", (unsigned) min); if(0 > (err = snd_pcm_sw_params(playback_handle, sw_params))) errx(EXIT_FAILURE, "Audio: Could not set software parameters: %s", snd_strerror(err)); buffer_size = snd_pcm_avail_update(playback_handle); }
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; }
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; }