Example #1
0
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;
}
Example #2
0
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();
}
Example #3
0
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;
}