static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams, int playback) { #ifndef ALSAAPI9 int err; snd_pcm_uframes_t ps,ops; snd_pcm_uframes_t bs,obs; /* get the current swparams */ err = snd_pcm_sw_params_current(handle, swparams); if (err < 0) { check_error(err,"Unable to determine current swparams for playback"); return err; } /* AUTOSTART: start the transfer on each write/commit ??? */ snd_pcm_sw_params_get_start_threshold(swparams, &obs); err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0U); if (err < 0) { check_error(err,"Unable to set start threshold mode"); return err; } snd_pcm_sw_params_get_start_threshold(swparams, &bs); #ifdef ALSAMM_DEBUG if(sys_verbose) post("sw_params: got start_thresh_hold= %d (was %d)",(int) bs,(int)obs); #endif /* AUTOSTOP: never stop the machine */ snd_pcm_sw_params_get_stop_threshold(swparams, &obs); err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, (snd_pcm_uframes_t)-1); if (err < 0) { check_error(err,"Unable to set stop threshold mode"); return err; } snd_pcm_sw_params_get_stop_threshold(swparams, &bs); #ifdef ALSAMM_DEBUG if(sys_verbose) post("sw_params: set stop_thresh_hold= %d (was %d)", (int) bs,(int)obs); #endif /* AUTOSILENCE: silence if overrun.... */ snd_pcm_sw_params_get_silence_threshold (swparams, &ops); if ((err = snd_pcm_sw_params_set_silence_threshold (handle, swparams, alsamm_period_size)) < 0) { check_error (err,"cannot set silence threshold for"); return -1; } snd_pcm_sw_params_get_silence_threshold (swparams, &ps); #ifdef ALSAMM_DEBUG if(sys_verbose) post("sw_params: set silence_threshold = %d (was %d)", (int) ps,(int)ops); #endif snd_pcm_sw_params_get_silence_size (swparams, &ops); if ((err = snd_pcm_sw_params_set_silence_size(handle, swparams, alsamm_period_size)) < 0) { check_error (err,"cannot set silence size for"); return -1; } snd_pcm_sw_params_get_silence_size (swparams, &ps); #ifdef ALSAMM_DEBUG if(sys_verbose) post("sw_params: set silence_size = %d (was %d)", (int) ps,(int)ops); #endif /* AVAIL: allow the transfer when at least period_size samples can be processed */ snd_pcm_sw_params_get_avail_min(swparams, &ops); err = snd_pcm_sw_params_set_avail_min(handle, swparams, alsamm_transfersize/2); if (err < 0) { check_error(err,"Unable to set avail min for"); return err; } snd_pcm_sw_params_get_avail_min(swparams, &ps); #ifdef ALSAMM_DEBUG if(sys_verbose) post("sw_params: set avail_min= %d (was %d)", (int) ps, (int) ops); #endif /* write the parameters to the playback device */ err = snd_pcm_sw_params(handle, swparams); if (err < 0) { check_error(err,"Unable to set sw params"); return err; } #ifdef ALSAMM_DEBUG if(sys_verbose) post("set sw finished"); #endif #else post("alsa: need version 1.0 or above for mmap operation"); #endif /* ALSAAPI9 */ return 0; }
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; }
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); }