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 void mix_subscribe(sfx_pcm_mixer_t *self, sfx_pcm_feed_t *feed) { sfx_pcm_feed_state_t *fs; ACQUIRE_LOCK(); if (!self->feeds) { self->feeds_allocd = 2; self->feeds = (sfx_pcm_feed_state_t*)sci_malloc(sizeof(sfx_pcm_feed_state_t) * self->feeds_allocd); } else if (self->feeds_allocd == self->feeds_nr) { self->feeds_allocd += 2; self->feeds = (sfx_pcm_feed_state_t*)sci_realloc(self->feeds, sizeof(sfx_pcm_feed_state_t) * self->feeds_allocd); } fs = self->feeds + self->feeds_nr++; fs->feed = feed; feed->frame_size = SFX_PCM_FRAME_SIZE(feed->conf); /* fs->buf_size = (self->dev->buf_size * (feed->conf.rate + self->dev->conf.rate - 1)) / self->dev->conf.rate; */ /* For the sake of people without 64 bit CPUs: */ fs->buf_size = 2 + /* Additional safety */ (self->dev->buf_size * (1 + (feed->conf.rate / self->dev->conf.rate))); fprintf(stderr, " ---> %d/%d/%d/%d = %d\n", self->dev->buf_size, feed->conf.rate, self->dev->conf.rate, feed->frame_size, fs->buf_size); fs->buf = (byte*)sci_malloc(fs->buf_size * feed->frame_size); fprintf(stderr, " ---> --> %d for %p at %p\n", fs->buf_size * feed->frame_size, (void *)fs, (void *)fs->buf); {int i; for (i = 0; i < fs->buf_size * feed->frame_size; i++) fs->buf[i] = 0xa5; } fs->scount = urat(0, 1); fs->spd = urat(feed->conf.rate, self->dev->conf.rate); fs->scount.den = fs->spd.den; fs->ch_old.left = 0; fs->ch_old.right = 0; fs->ch_new.left = 0; fs->ch_new.right = 0; fs->mode = SFX_PCM_FEED_MODE_ALIVE; /* If the feed can't provide us with timestamps, we don't need to wait for it to do so */ fs->pending_review = (feed->get_timestamp)? 1 : 0; fs->frame_bufstart = 0; #ifdef DEBUG sciprintf("[soft-mixer] Subscribed %s-%x (%d Hz, %d/%x) at %d+%d/%d, buffer size %d\n", feed->debug_name, feed->debug_nr, feed->conf.rate, feed->conf.stereo, feed->conf.format, fs->spd.val, fs->spd.nom, fs->spd.den, fs->buf_size); #endif RELEASE_LOCK(); }
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; }