channel-switch: use sys/ioctl.h instead of stropts.h
[rofl0r-MacGeiger.git] / audio-backend.c
blob391a89799c215876c4f7e9d42324549d01effc86
1 #define AUDIO_BACKEND_AO 1
2 #define AUDIO_BACKEND_SDL 2
3 #define AUDIO_BACKEND_NOP 3
5 #ifndef AUDIO_BACKEND
6 #define AUDIO_BACKEND AUDIO_BACKEND_AO
7 #endif
9 #if AUDIO_BACKEND == AUDIO_BACKEND_AO
10 #pragma RcB2 LINK "-lao"
11 #elif AUDIO_BACKEND == AUDIO_BACKEND_SDL
12 #pragma RcB2 LINK "-lSDL_sound" "-lSDL"
13 #endif
15 #include <unistd.h>
17 #if AUDIO_BACKEND == AUDIO_BACKEND_NOP
19 struct NopAudio {
20 int dummy;
23 #define audio_init(X) do {} while(0)
24 #define audio_write(X, Y, Z) do {} while(0)
25 #define audio_close(X) do {} while(0)
27 #define AudioCTX NopAudio
29 #elif AUDIO_BACKEND == AUDIO_BACKEND_SDL
31 #include <pthread.h>
32 #include <SDL/SDL.h>
33 #include <SDL/SDL_audio.h>
35 struct SdlWriter {
36 pthread_mutex_t cb_lock;
37 char* buffer;
38 size_t buffer_used;
39 size_t buffer_size;
40 SDL_AudioSpec fmt;
43 #define alock() pthread_mutex_lock(&self->cb_lock)
44 #define aunlock() pthread_mutex_unlock(&self->cb_lock)
46 static void sdl_callback(void *user, Uint8 *stream, int len) {
47 struct SdlWriter *self = user;
48 do {
49 alock();
50 if((size_t) len <= self->buffer_used) {
51 memcpy(stream, self->buffer, len);
52 size_t diff = self->buffer_used - len;
53 memmove(self->buffer, (char*)self->buffer + len, diff);
54 self->buffer_used = diff;
55 aunlock();
56 return;
57 } else {
58 aunlock();
59 usleep(1000);
62 } while(1);
65 int SdlWriter_write(struct SdlWriter *self, void* buffer, size_t bufsize) {
66 do {
67 alock();
68 if(self->buffer_used + bufsize > self->buffer_size) {
69 aunlock();
70 usleep(1000);
71 } else {
72 memcpy((char*)self->buffer + self->buffer_used, buffer, bufsize);
73 self->buffer_used += bufsize;
74 aunlock();
75 break;
77 } while(1);
78 return 1;
81 #undef alock
82 #undef aunlock
84 #define NUM_CHANNELS 2
85 int SdlWriter_init(struct SdlWriter *self) {
86 SDL_Init(SDL_INIT_AUDIO);
87 SDL_AudioSpec obtained;
88 self->fmt.freq = 11025; //44100;
89 self->fmt.format = AUDIO_U8; //AUDIO_S16;
90 self->fmt.channels = 1; //NUM_CHANNELS;
91 self->fmt.samples = 768; //COREMIXER_MAX_BUFFER;
92 self->fmt.callback = sdl_callback;
93 self->fmt.userdata = self;
94 pthread_mutex_init(&self->cb_lock, 0);
95 if(SDL_OpenAudio(&self->fmt, &obtained) < 0) {
96 printf("sdl_openaudio: %s\n", SDL_GetError());
97 return 0;
99 size_t max = obtained.samples > self->fmt.samples ? obtained.samples : self->fmt.samples;
100 self->fmt = obtained;
101 /* the buffer must be twice as big as the biggest number of samples processed/consumed */
102 self->buffer_size = max * sizeof(int16_t) * NUM_CHANNELS * 2;
103 if(!(self->buffer = malloc(self->buffer_size))) return 0;
104 self->buffer_used = 0;
105 SDL_PauseAudio(0);
106 return 1;
109 int SdlWriter_close(struct SdlWriter *self) {
110 SDL_CloseAudio();
111 free(self->buffer);
112 self->buffer = 0;
113 self->buffer_size = 0;
114 pthread_mutex_destroy(&self->cb_lock);
115 SDL_QuitSubSystem(SDL_INIT_AUDIO);
116 return 1;
119 #define audio_init(X) SdlWriter_init(X)
120 #define audio_write(X, Y, Z) SdlWriter_write(X, Y, Z)
121 #define audio_close(X) SdlWriter_close(X)
123 #define AudioCTX SdlWriter
125 #elif AUDIO_BACKEND == AUDIO_BACKEND_AO
127 #include <ao/ao.h>
129 struct AoWriter {
130 ao_device *device;
131 ao_sample_format format;
132 int aodriver;
135 int AoWriter_init(struct AoWriter *self) {
136 ao_initialize();
137 memset(self, 0, sizeof(*self));
138 self->format.bits = 8;
139 self->format.channels = 1;
140 self->format.rate = 11025;
141 self->format.byte_format = AO_FMT_LITTLE;
142 self->aodriver = ao_default_driver_id();
143 self->device = ao_open_live(self->aodriver, &self->format, NULL);
144 return self->device != NULL;
147 int AoWriter_write(struct AoWriter *self, void* buffer, size_t bufsize) {
148 return ao_play(self->device, buffer, bufsize);
151 int AoWriter_close(struct AoWriter *self) {
152 return ao_close(self->device);
155 #define audio_init(X) AoWriter_init(X)
156 #define audio_write(X, Y, Z) AoWriter_write(X, Y, Z)
157 #define audio_close(X) AoWriter_close(X)
159 #define AudioCTX AoWriter
162 #else
163 #error unknown AUDIO_BACKEND
164 #endif