Development:Tutorials:SetupAudio

From DingooWiki

Jump to: navigation, search

[edit] Using SDL

  1. Sample format is restricted to AUDIO_S16.
  2. Frequencies that works: 44100, 22050, 16000, 8000.

As normal no need it any special setting, a simple example:

  SDL_AudioSpec *desired, *obtained;
  desired = (SDL_AudioSpec *)malloc(sizeof(SDL_AudioSpec));
  obtained = (SDL_AudioSpec *)malloc(sizeof(SDL_AudioSpec));
 
  desired->freq = 44100;
  desired->format = AUDIO_S16;
  desired->channels = 2;
  desired->samples = audio_align_samples(desired->freq / 50);
 
  desired->callback = SoundUpdate;
  desired->userdata = NULL;
 
  if (SDL_OpenAudio(desired, obtained) < 0) {
     fprintf(stderr, "Could not open audio: %s\n", SDL_GetError());
     return 0;
  }
   
  free(desired);
 
  audio_spec = obtained;
    
  printf("SDL AUDIO - INIT AT: %i\n",audio_spec->size);

[edit] Using direct access to DSP

Global variables and includes:

[...]
#include <sys/ioctl.h>
#include <pthread.h>
#include <stdbool.h>
#include <sys/poll.h>
#include <sys/soundcard.h>
#include <sys/mman.h>

static pthread_t sound_thrd_loop_fill = (pthread_t)0;
static bool sound_running = false;
static bool sfx_thread_paused = true;

int sound_dev = -1;
int mixer_dev = -1;

int vol_left = 0, vol_right = 0;

audio_buf_info sound_buf_info;

int sound_fmt, sound_chans;
long sound_rate;

unsigned char *sound_buffer;
[...]

Need it fuctions:

int sound_set_volume() {
	if (vol_left < 0) vol_left = 0;
	if (vol_left > 100) vol_left = 100;
	if (vol_right < 0) vol_right = 0;
	if (vol_right > 100) vol_right = 100;
 
	int vol = ((vol_left << 8) | vol_right);
	return (ioctl(mixer_dev, MIXER_WRITE(SOUND_MIXER_VOLUME), &vol) == -1
		|| ioctl(mixer_dev, MIXER_WRITE(SOUND_MIXER_PCM), &vol) == -1) ? -1 : 0;
}
int sound_reset() {
	return ioctl(sound_dev, SNDCTL_DSP_RESET, 0);
}
int sound_set_format(int fmt) {
	if (fmt != AFMT_S16_LE) return -1; /* sorry, but this library depends on it */
 
	sound_reset();
 
	if (ioctl(sound_dev, SNDCTL_DSP_SETFMT, &fmt) == -1) return -1;
	if (ioctl(sound_dev, SNDCTL_DSP_GETOSPACE, &sound_buf_info) == -1) return -1;
 
	sound_fmt = fmt;
 
	return 0;
}
int sound_set_channels(int chans) {
	if (sound_chans == chans) return 0;

	sound_reset();

	if (ioctl(sound_dev, SNDCTL_DSP_CHANNELS, &chans) == -1) return -1;
	if (ioctl(sound_dev, SNDCTL_DSP_GETOSPACE, &sound_buf_info) == -1) return -1;
 
	sound_chans = chans;
 
	return 0;
}
int sound_set_rate(long rate) {
	if (sound_rate == rate) return 0;

	sound_reset();
	if (ioctl(sound_dev, SNDCTL_DSP_SPEED, &rate) == -1) return -1;
	if (ioctl(sound_dev, SNDCTL_DSP_GETOSPACE, &sound_buf_info) == -1) return -1;

 	sound_rate = rate;

 	return 0;
}
int sound_set_buffer_size(int max_frags, int size) {
	sound_reset();

	int frag = (max_frags << 16) | size;

	if (ioctl(sound_dev, SNDCTL_DSP_SETFRAGMENT, &frag) == -1) return -1;
	if (ioctl(sound_dev, SNDCTL_DSP_GETOSPACE, &sound_buf_info) == -1) return -1;

	return 0;
 }

 int sound_get_buffer_remaining() {
	audio_buf_info info;
	if (ioctl(sound_dev, SNDCTL_DSP_GETOSPACE, &info) == -1) return 0;
	return sound_buf_info.bytes - info.bytes;
 }

 int sound_set_nonblock() {
	return ioctl(sound_dev, SNDCTL_DSP_NONBLOCK, 0);
 }


Setup DSP Audio:

   if ((sound_dev = open("/dev/dsp", O_WRONLY)) == -1) goto error;
 
   if (sound_set_buffer_size(3, 15)) goto error; /* these values are based on several tests; not accurate */
 
   if (sound_set_format(AFMT_S16_LE) || sound_set_channels(2) || sound_set_rate(44100)) goto error; /* FIXME */
 
   sound_running = true;
   sfx_thread_paused = false;
 
   if (!sound_thrd_loop_fill && pthread_create(&sound_thrd_loop_fill, NULL, sound_loop_fill, NULL)) goto error;
 
   if ((mixer_dev = open("/dev/mixer", O_RDONLY)) == -1) goto error;

An audio thread example:

static void *sound_loop_fill(void *user_data) {

	while (sound_running) {

 		struct pollfd fds[1];

 		fds[0].fd = sound_dev;
		fds[0].events = POLLOUT;

		while (!poll(fds, sizeof(fds)/sizeof(fds[0]), 0)) usleep(1000);

		if (sfx_thread_paused) continue;
 		write(sound_dev, mySoundBuffer, 1024);
	}

	return NULL; 
}

Close Sound DSP and Mixer:

	sound_running = false;

	if (sound_thrd_loop_fill && pthread_join(sound_thrd_loop_fill, NULL)) return;
	sound_thrd_loop_fill = (pthread_t)0;

	if (sound_dev != -1 && (close(sound_dev) || ((sound_dev = -1) & 0))) return;

	if (mixer_dev != -1 && (close(mixer_dev) || ((mixer_dev = -1) & 0))) return;
Personal tools