static int pcmout_sdl_init(sfx_pcm_device_t *self) { SDL_AudioSpec a; if (SDL_Init(SDL_INIT_AUDIO|SDL_INIT_NOPARACHUTE) != 0) { fprintf (stderr, "[SND:SDL] Error while initialising: %s\n", SDL_GetError()); return -1; } a.freq = 44100; /* FIXME */ #ifdef WORDS_BIGENDIAN a.format = AUDIO_S16MSB; /* FIXME */ #else a.format = AUDIO_S16LSB; /* FIXME */ #endif a.channels = 2; /* FIXME */ a.samples = 2048; /* FIXME */ a.callback = timer_sdl_internal_callback; a.userdata = NULL; if (SDL_OpenAudio (&a, NULL) < 0) { fprintf (stderr, "[SND:SDL] Error while opening audio: %s\n", SDL_GetError()); return SFX_ERROR; } buf_size = a.samples; rate = a.freq; self->buf_size = a.samples << 1; /* Looks like they're using double size */ self->conf.rate = a.freq; self->conf.stereo = a.channels > 1; self->conf.format = SFX_PCM_FORMAT_S16_NATIVE; frame_size = SFX_PCM_FRAME_SIZE(self->conf); sfx_audbuf_init(&audio_buffer, self->conf); SDL_PauseAudio (0); return SFX_OK; }
static int pcmout_alsa_init(sfx_pcm_device_t *self) { unsigned int rrate; int err, dir; snd_pcm_hw_params_t *hwparams; snd_pcm_sw_params_t *swparams; pthread_attr_t attr; snd_pcm_hw_params_alloca(&hwparams); snd_pcm_sw_params_alloca(&swparams); err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0); if (err < 0) { sciprintf("[SND:ALSA] Playback open error: %s\n", snd_strerror(err)); return SFX_ERROR; } err = snd_pcm_hw_params_any(handle, hwparams); if (err < 0) { sciprintf("[SND:ALSA] Broken configuration for playback: no configurations available: %s\n", snd_strerror(err)); return SFX_ERROR; } err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { sciprintf("[SND:ALSA] Access type not available for playback: %s\n", snd_strerror(err)); return SFX_ERROR; } err = snd_pcm_hw_params_set_format(handle, hwparams, format); if (err < 0) { sciprintf("[SND:ALSA] Sample format not available for playback: %s\n", snd_strerror(err)); return SFX_ERROR; } err = snd_pcm_hw_params_set_channels(handle, hwparams, channels); if (err < 0) { sciprintf("[SND:ALSA] Channels count (%i) not available for playback: %s\n", channels, snd_strerror(err)); return SFX_ERROR; } rrate = rate; err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rrate, 0); if (err < 0) { sciprintf("[SND:ALSA] Rate %iHz not available for playback: %s\n", rate, snd_strerror(err)); return SFX_ERROR; } if (rrate != rate) { sciprintf("[SND:ALSA] Rate doesn't match (requested %iHz, get %iHz)\n", rate, err); return SFX_ERROR; } err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir); if (err < 0) { sciprintf("[SND:ALSA] Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err)); return SFX_ERROR; } err = snd_pcm_hw_params_get_buffer_size(hwparams, (snd_pcm_uframes_t*)&buffer_size); if (err < 0) { sciprintf("[SND:ALSA] Unable to get buffer size for playback: %s\n", snd_strerror(err)); return SFX_ERROR; } err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir); if (err < 0) { sciprintf("[SND:ALSA] Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err)); return SFX_ERROR; } err = snd_pcm_hw_params_get_period_size(hwparams, (snd_pcm_uframes_t*)&period_size, &dir); if (err < 0) { sciprintf("[SND:ALSA] Unable to get period size for playback: %s\n", snd_strerror(err)); return SFX_ERROR; } if (period_size >= buffer_size) { sciprintf("[SND:ALSA] Period size %i matches or exceeds buffer size %i\n", period_size, buffer_size); return SFX_ERROR; } err = snd_pcm_hw_params(handle, hwparams); if (err < 0) { sciprintf("[SND:ALSA] Unable to set hw params for playback: %s\n", snd_strerror(err)); return SFX_ERROR; } err = snd_pcm_sw_params_current(handle, swparams); if (err < 0) { sciprintf("[SND:ALSA] Unable to determine current swparams for playback: %s\n", snd_strerror(err)); return SFX_ERROR; } err = snd_pcm_sw_params_set_start_threshold(handle, swparams, buffer_size); if (err < 0) { sciprintf("[SND:ALSA] Unable to set start threshold mode for playback: %s\n", snd_strerror(err)); return SFX_ERROR; } err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_size); if (err < 0) { sciprintf("[SND:ALSA] Unable to set avail min for playback: %s\n", snd_strerror(err)); return SFX_ERROR; } err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1); if (err < 0) { sciprintf("[SND:ALSA] Unable to set transfer align for playback: %s\n", snd_strerror(err)); return SFX_ERROR; } err = snd_pcm_sw_params(handle, swparams); if (err < 0) { sciprintf("[SND:ALSA] Unable to set sw params for playback: %s\n", snd_strerror(err)); return SFX_ERROR; } self->buf_size = buffer_size; self->conf.rate = rate; self->conf.stereo = channels > 1; self->conf.format = SFX_PCM_FORMAT_S16_NATIVE; frame_size = SFX_PCM_FRAME_SIZE(self->conf); sfx_audbuf_init(&audio_buffer, self->conf); if (pthread_mutex_init(&mutex, NULL) != 0) { sciprintf("[SND:ALSA] Failed to create mutex\n"); return SFX_ERROR; } run_thread = 1; if (pthread_create(&thread, NULL, alsa_thread, self) != 0) { sciprintf("[SND:ALSA] Failed to create thread\n"); return SFX_ERROR; } return SFX_OK; }