185571bc7Sbellard /* 2*1d14ffa9Sbellard * QEMU SDL audio driver 385571bc7Sbellard * 4*1d14ffa9Sbellard * Copyright (c) 2004-2005 Vassili Karpov (malc) 585571bc7Sbellard * 685571bc7Sbellard * Permission is hereby granted, free of charge, to any person obtaining a copy 785571bc7Sbellard * of this software and associated documentation files (the "Software"), to deal 885571bc7Sbellard * in the Software without restriction, including without limitation the rights 985571bc7Sbellard * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1085571bc7Sbellard * copies of the Software, and to permit persons to whom the Software is 1185571bc7Sbellard * furnished to do so, subject to the following conditions: 1285571bc7Sbellard * 1385571bc7Sbellard * The above copyright notice and this permission notice shall be included in 1485571bc7Sbellard * all copies or substantial portions of the Software. 1585571bc7Sbellard * 1685571bc7Sbellard * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1785571bc7Sbellard * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1885571bc7Sbellard * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1985571bc7Sbellard * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2085571bc7Sbellard * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2185571bc7Sbellard * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 2285571bc7Sbellard * THE SOFTWARE. 2385571bc7Sbellard */ 249f059ecaSbellard #include <SDL.h> 259f059ecaSbellard #include <SDL_thread.h> 2685571bc7Sbellard #include "vl.h" 2785571bc7Sbellard 28*1d14ffa9Sbellard #define AUDIO_CAP "sdl" 29*1d14ffa9Sbellard #include "audio_int.h" 30fb065187Sbellard 31*1d14ffa9Sbellard typedef struct SDLVoiceOut { 32*1d14ffa9Sbellard HWVoiceOut hw; 33*1d14ffa9Sbellard int live; 34*1d14ffa9Sbellard int rpos; 35*1d14ffa9Sbellard int decr; 36*1d14ffa9Sbellard } SDLVoiceOut; 3785571bc7Sbellard 3885571bc7Sbellard static struct { 3985571bc7Sbellard int nb_samples; 4085571bc7Sbellard } conf = { 4185571bc7Sbellard 1024 4285571bc7Sbellard }; 4385571bc7Sbellard 4485571bc7Sbellard struct SDLAudioState { 4585571bc7Sbellard int exit; 4685571bc7Sbellard SDL_mutex *mutex; 4785571bc7Sbellard SDL_sem *sem; 4885571bc7Sbellard int initialized; 4985571bc7Sbellard } glob_sdl; 5085571bc7Sbellard typedef struct SDLAudioState SDLAudioState; 5185571bc7Sbellard 52*1d14ffa9Sbellard static void GCC_FMT_ATTR (1, 2) sdl_logerr (const char *fmt, ...) 5385571bc7Sbellard { 54*1d14ffa9Sbellard va_list ap; 55*1d14ffa9Sbellard 56*1d14ffa9Sbellard va_start (ap, fmt); 57*1d14ffa9Sbellard AUD_vlog (AUDIO_CAP, fmt, ap); 58*1d14ffa9Sbellard va_end (ap); 59*1d14ffa9Sbellard 60*1d14ffa9Sbellard AUD_log (AUDIO_CAP, "Reason: %s\n", SDL_GetError ()); 6185571bc7Sbellard } 6285571bc7Sbellard 63*1d14ffa9Sbellard static int sdl_lock (SDLAudioState *s, const char *forfn) 6485571bc7Sbellard { 6585571bc7Sbellard if (SDL_LockMutex (s->mutex)) { 66*1d14ffa9Sbellard sdl_logerr ("SDL_LockMutex for %s failed\n", forfn); 6785571bc7Sbellard return -1; 6885571bc7Sbellard } 6985571bc7Sbellard return 0; 7085571bc7Sbellard } 7185571bc7Sbellard 72*1d14ffa9Sbellard static int sdl_unlock (SDLAudioState *s, const char *forfn) 7385571bc7Sbellard { 7485571bc7Sbellard if (SDL_UnlockMutex (s->mutex)) { 75*1d14ffa9Sbellard sdl_logerr ("SDL_UnlockMutex for %s failed\n", forfn); 7685571bc7Sbellard return -1; 7785571bc7Sbellard } 7885571bc7Sbellard return 0; 7985571bc7Sbellard } 8085571bc7Sbellard 81*1d14ffa9Sbellard static int sdl_post (SDLAudioState *s, const char *forfn) 8285571bc7Sbellard { 8385571bc7Sbellard if (SDL_SemPost (s->sem)) { 84*1d14ffa9Sbellard sdl_logerr ("SDL_SemPost for %s failed\n", forfn); 8585571bc7Sbellard return -1; 8685571bc7Sbellard } 8785571bc7Sbellard return 0; 8885571bc7Sbellard } 8985571bc7Sbellard 90*1d14ffa9Sbellard static int sdl_wait (SDLAudioState *s, const char *forfn) 9185571bc7Sbellard { 9285571bc7Sbellard if (SDL_SemWait (s->sem)) { 93*1d14ffa9Sbellard sdl_logerr ("SDL_SemWait for %s failed\n", forfn); 9485571bc7Sbellard return -1; 9585571bc7Sbellard } 9685571bc7Sbellard return 0; 9785571bc7Sbellard } 9885571bc7Sbellard 99*1d14ffa9Sbellard static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn) 10085571bc7Sbellard { 101*1d14ffa9Sbellard if (sdl_unlock (s, forfn)) { 10285571bc7Sbellard return -1; 10385571bc7Sbellard } 10485571bc7Sbellard 105*1d14ffa9Sbellard return sdl_post (s, forfn); 10685571bc7Sbellard } 10785571bc7Sbellard 108*1d14ffa9Sbellard static int aud_to_sdlfmt (audfmt_e fmt, int *shift) 10985571bc7Sbellard { 110*1d14ffa9Sbellard switch (fmt) { 111*1d14ffa9Sbellard case AUD_FMT_S8: 11285571bc7Sbellard *shift = 0; 113*1d14ffa9Sbellard return AUDIO_S8; 114*1d14ffa9Sbellard 115*1d14ffa9Sbellard case AUD_FMT_U8: 116*1d14ffa9Sbellard *shift = 0; 117*1d14ffa9Sbellard return AUDIO_U8; 118*1d14ffa9Sbellard 119*1d14ffa9Sbellard case AUD_FMT_S16: 120*1d14ffa9Sbellard *shift = 1; 121*1d14ffa9Sbellard return AUDIO_S16LSB; 122*1d14ffa9Sbellard 123*1d14ffa9Sbellard case AUD_FMT_U16: 124*1d14ffa9Sbellard *shift = 1; 125*1d14ffa9Sbellard return AUDIO_U16LSB; 126*1d14ffa9Sbellard 12785571bc7Sbellard default: 128*1d14ffa9Sbellard dolog ("Internal logic error: Bad audio format %d\n", fmt); 129*1d14ffa9Sbellard #ifdef DEBUG_AUDIO 130*1d14ffa9Sbellard abort (); 131*1d14ffa9Sbellard #endif 132*1d14ffa9Sbellard return AUDIO_U8; 13385571bc7Sbellard } 13485571bc7Sbellard } 13585571bc7Sbellard 136*1d14ffa9Sbellard static int sdl_to_audfmt (int sdlfmt, audfmt_e *fmt, int *endianess) 13785571bc7Sbellard { 138*1d14ffa9Sbellard switch (sdlfmt) { 139*1d14ffa9Sbellard case AUDIO_S8: 140*1d14ffa9Sbellard *endianess = 0; 141*1d14ffa9Sbellard *fmt = AUD_FMT_S8; 142*1d14ffa9Sbellard break; 143*1d14ffa9Sbellard 144*1d14ffa9Sbellard case AUDIO_U8: 145*1d14ffa9Sbellard *endianess = 0; 146*1d14ffa9Sbellard *fmt = AUD_FMT_U8; 147*1d14ffa9Sbellard break; 148*1d14ffa9Sbellard 149*1d14ffa9Sbellard case AUDIO_S16LSB: 150*1d14ffa9Sbellard *endianess = 0; 151*1d14ffa9Sbellard *fmt = AUD_FMT_S16; 152*1d14ffa9Sbellard break; 153*1d14ffa9Sbellard 154*1d14ffa9Sbellard case AUDIO_U16LSB: 155*1d14ffa9Sbellard *endianess = 0; 156*1d14ffa9Sbellard *fmt = AUD_FMT_U16; 157*1d14ffa9Sbellard break; 158*1d14ffa9Sbellard 159*1d14ffa9Sbellard case AUDIO_S16MSB: 160*1d14ffa9Sbellard *endianess = 1; 161*1d14ffa9Sbellard *fmt = AUD_FMT_S16; 162*1d14ffa9Sbellard break; 163*1d14ffa9Sbellard 164*1d14ffa9Sbellard case AUDIO_U16MSB: 165*1d14ffa9Sbellard *endianess = 1; 166*1d14ffa9Sbellard *fmt = AUD_FMT_U16; 167*1d14ffa9Sbellard break; 168*1d14ffa9Sbellard 16985571bc7Sbellard default: 170*1d14ffa9Sbellard dolog ("Unrecognized SDL audio format %d\n", sdlfmt); 171*1d14ffa9Sbellard return -1; 17285571bc7Sbellard } 173*1d14ffa9Sbellard 174*1d14ffa9Sbellard return 0; 17585571bc7Sbellard } 17685571bc7Sbellard 17785571bc7Sbellard static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt) 17885571bc7Sbellard { 17985571bc7Sbellard int status; 18085571bc7Sbellard 18185571bc7Sbellard status = SDL_OpenAudio (req, obt); 18285571bc7Sbellard if (status) { 183*1d14ffa9Sbellard sdl_logerr ("SDL_OpenAudio failed\n"); 18485571bc7Sbellard } 18585571bc7Sbellard return status; 18685571bc7Sbellard } 18785571bc7Sbellard 18885571bc7Sbellard static void sdl_close (SDLAudioState *s) 18985571bc7Sbellard { 19085571bc7Sbellard if (s->initialized) { 191*1d14ffa9Sbellard sdl_lock (s, "sdl_close"); 19285571bc7Sbellard s->exit = 1; 193*1d14ffa9Sbellard sdl_unlock_and_post (s, "sdl_close"); 19485571bc7Sbellard SDL_PauseAudio (1); 19585571bc7Sbellard SDL_CloseAudio (); 19685571bc7Sbellard s->initialized = 0; 19785571bc7Sbellard } 19885571bc7Sbellard } 19985571bc7Sbellard 20085571bc7Sbellard static void sdl_callback (void *opaque, Uint8 *buf, int len) 20185571bc7Sbellard { 202*1d14ffa9Sbellard SDLVoiceOut *sdl = opaque; 20385571bc7Sbellard SDLAudioState *s = &glob_sdl; 204*1d14ffa9Sbellard HWVoiceOut *hw = &sdl->hw; 205*1d14ffa9Sbellard int samples = len >> hw->info.shift; 20685571bc7Sbellard 20785571bc7Sbellard if (s->exit) { 20885571bc7Sbellard return; 20985571bc7Sbellard } 21085571bc7Sbellard 21185571bc7Sbellard while (samples) { 212*1d14ffa9Sbellard int to_mix, decr; 21385571bc7Sbellard 21485571bc7Sbellard /* dolog ("in callback samples=%d\n", samples); */ 215*1d14ffa9Sbellard sdl_wait (s, "sdl_callback"); 21685571bc7Sbellard if (s->exit) { 21785571bc7Sbellard return; 21885571bc7Sbellard } 21985571bc7Sbellard 220*1d14ffa9Sbellard if (sdl_lock (s, "sdl_callback")) { 221*1d14ffa9Sbellard return; 222*1d14ffa9Sbellard } 223*1d14ffa9Sbellard 224*1d14ffa9Sbellard if (audio_bug (AUDIO_FUNC, sdl->live < 0 || sdl->live > hw->samples)) { 225*1d14ffa9Sbellard dolog ("sdl->live=%d hw->samples=%d\n", 226*1d14ffa9Sbellard sdl->live, hw->samples); 227*1d14ffa9Sbellard return; 228*1d14ffa9Sbellard } 229*1d14ffa9Sbellard 230*1d14ffa9Sbellard if (!sdl->live) { 23185571bc7Sbellard goto again; 232*1d14ffa9Sbellard } 23385571bc7Sbellard 23485571bc7Sbellard /* dolog ("in callback live=%d\n", live); */ 235*1d14ffa9Sbellard to_mix = audio_MIN (samples, sdl->live); 23685571bc7Sbellard decr = to_mix; 23785571bc7Sbellard while (to_mix) { 23885571bc7Sbellard int chunk = audio_MIN (to_mix, hw->samples - hw->rpos); 23985571bc7Sbellard st_sample_t *src = hw->mix_buf + hw->rpos; 24085571bc7Sbellard 24185571bc7Sbellard /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */ 24285571bc7Sbellard hw->clip (buf, src, chunk); 243*1d14ffa9Sbellard mixeng_clear (src, chunk); 244*1d14ffa9Sbellard sdl->rpos = (sdl->rpos + chunk) % hw->samples; 24585571bc7Sbellard to_mix -= chunk; 246*1d14ffa9Sbellard buf += chunk << hw->info.shift; 24785571bc7Sbellard } 24885571bc7Sbellard samples -= decr; 249*1d14ffa9Sbellard sdl->live -= decr; 250*1d14ffa9Sbellard sdl->decr += decr; 25185571bc7Sbellard 25285571bc7Sbellard again: 253*1d14ffa9Sbellard if (sdl_unlock (s, "sdl_callback")) { 254*1d14ffa9Sbellard return; 255*1d14ffa9Sbellard } 25685571bc7Sbellard } 25785571bc7Sbellard /* dolog ("done len=%d\n", len); */ 25885571bc7Sbellard } 25985571bc7Sbellard 260*1d14ffa9Sbellard static int sdl_write_out (SWVoiceOut *sw, void *buf, int len) 26185571bc7Sbellard { 262*1d14ffa9Sbellard return audio_pcm_sw_write (sw, buf, len); 263*1d14ffa9Sbellard } 264*1d14ffa9Sbellard 265*1d14ffa9Sbellard static int sdl_run_out (HWVoiceOut *hw) 266*1d14ffa9Sbellard { 267*1d14ffa9Sbellard int decr, live; 268*1d14ffa9Sbellard SDLVoiceOut *sdl = (SDLVoiceOut *) hw; 269*1d14ffa9Sbellard SDLAudioState *s = &glob_sdl; 270*1d14ffa9Sbellard 271*1d14ffa9Sbellard if (sdl_lock (s, "sdl_callback")) { 272*1d14ffa9Sbellard return 0; 273*1d14ffa9Sbellard } 274*1d14ffa9Sbellard 275*1d14ffa9Sbellard live = audio_pcm_hw_get_live_out (hw); 276*1d14ffa9Sbellard 277*1d14ffa9Sbellard if (sdl->decr > live) { 278*1d14ffa9Sbellard ldebug ("sdl->decr %d live %d sdl->live %d\n", 279*1d14ffa9Sbellard sdl->decr, 280*1d14ffa9Sbellard live, 281*1d14ffa9Sbellard sdl->live); 282*1d14ffa9Sbellard } 283*1d14ffa9Sbellard 284*1d14ffa9Sbellard decr = audio_MIN (sdl->decr, live); 285*1d14ffa9Sbellard sdl->decr -= decr; 286*1d14ffa9Sbellard 287*1d14ffa9Sbellard sdl->live = live - decr; 288*1d14ffa9Sbellard hw->rpos = sdl->rpos; 289*1d14ffa9Sbellard 290*1d14ffa9Sbellard if (sdl->live > 0) { 291*1d14ffa9Sbellard sdl_unlock_and_post (s, "sdl_callback"); 292*1d14ffa9Sbellard } 293*1d14ffa9Sbellard else { 294*1d14ffa9Sbellard sdl_unlock (s, "sdl_callback"); 295*1d14ffa9Sbellard } 296*1d14ffa9Sbellard return decr; 297*1d14ffa9Sbellard } 298*1d14ffa9Sbellard 299*1d14ffa9Sbellard static void sdl_fini_out (HWVoiceOut *hw) 300*1d14ffa9Sbellard { 301*1d14ffa9Sbellard (void) hw; 302*1d14ffa9Sbellard 30385571bc7Sbellard sdl_close (&glob_sdl); 30485571bc7Sbellard } 30585571bc7Sbellard 306*1d14ffa9Sbellard static int sdl_init_out (HWVoiceOut *hw, int freq, int nchannels, audfmt_e fmt) 30785571bc7Sbellard { 308*1d14ffa9Sbellard SDLVoiceOut *sdl = (SDLVoiceOut *) hw; 30985571bc7Sbellard SDLAudioState *s = &glob_sdl; 31085571bc7Sbellard SDL_AudioSpec req, obt; 31185571bc7Sbellard int shift; 312*1d14ffa9Sbellard int endianess; 313*1d14ffa9Sbellard int err; 314*1d14ffa9Sbellard audfmt_e effective_fmt; 31585571bc7Sbellard 31685571bc7Sbellard if (nchannels != 2) { 317*1d14ffa9Sbellard dolog ("Can not init DAC. Bogus channel count %d\n", nchannels); 31885571bc7Sbellard return -1; 31985571bc7Sbellard } 32085571bc7Sbellard 32185571bc7Sbellard req.freq = freq; 322*1d14ffa9Sbellard req.format = aud_to_sdlfmt (fmt, &shift); 32385571bc7Sbellard req.channels = nchannels; 32485571bc7Sbellard req.samples = conf.nb_samples; 32585571bc7Sbellard shift <<= nchannels == 2; 32685571bc7Sbellard 32785571bc7Sbellard req.callback = sdl_callback; 32885571bc7Sbellard req.userdata = sdl; 32985571bc7Sbellard 330*1d14ffa9Sbellard if (sdl_open (&req, &obt)) { 33185571bc7Sbellard return -1; 332*1d14ffa9Sbellard } 33385571bc7Sbellard 334*1d14ffa9Sbellard err = sdl_to_audfmt (obt.format, &effective_fmt, &endianess); 335*1d14ffa9Sbellard if (err) { 336*1d14ffa9Sbellard sdl_close (s); 337*1d14ffa9Sbellard return -1; 338*1d14ffa9Sbellard } 339*1d14ffa9Sbellard 340*1d14ffa9Sbellard audio_pcm_init_info ( 341*1d14ffa9Sbellard &hw->info, 342*1d14ffa9Sbellard obt.freq, 343*1d14ffa9Sbellard obt.channels, 344*1d14ffa9Sbellard effective_fmt, 345*1d14ffa9Sbellard audio_need_to_swap_endian (endianess) 346*1d14ffa9Sbellard ); 34785571bc7Sbellard hw->bufsize = obt.samples << shift; 34885571bc7Sbellard 34985571bc7Sbellard s->initialized = 1; 35085571bc7Sbellard s->exit = 0; 35185571bc7Sbellard SDL_PauseAudio (0); 35285571bc7Sbellard return 0; 35385571bc7Sbellard } 35485571bc7Sbellard 355*1d14ffa9Sbellard static int sdl_ctl_out (HWVoiceOut *hw, int cmd, ...) 35685571bc7Sbellard { 35785571bc7Sbellard (void) hw; 35885571bc7Sbellard 35985571bc7Sbellard switch (cmd) { 36085571bc7Sbellard case VOICE_ENABLE: 36185571bc7Sbellard SDL_PauseAudio (0); 36285571bc7Sbellard break; 36385571bc7Sbellard 36485571bc7Sbellard case VOICE_DISABLE: 36585571bc7Sbellard SDL_PauseAudio (1); 36685571bc7Sbellard break; 36785571bc7Sbellard } 36885571bc7Sbellard return 0; 36985571bc7Sbellard } 37085571bc7Sbellard 37185571bc7Sbellard static void *sdl_audio_init (void) 37285571bc7Sbellard { 37385571bc7Sbellard SDLAudioState *s = &glob_sdl; 37485571bc7Sbellard 37585571bc7Sbellard if (SDL_InitSubSystem (SDL_INIT_AUDIO)) { 376*1d14ffa9Sbellard sdl_logerr ("SDL failed to initialize audio subsystem\n"); 37785571bc7Sbellard return NULL; 37885571bc7Sbellard } 37985571bc7Sbellard 38085571bc7Sbellard s->mutex = SDL_CreateMutex (); 38185571bc7Sbellard if (!s->mutex) { 382*1d14ffa9Sbellard sdl_logerr ("Failed to create SDL mutex\n"); 38385571bc7Sbellard SDL_QuitSubSystem (SDL_INIT_AUDIO); 38485571bc7Sbellard return NULL; 38585571bc7Sbellard } 38685571bc7Sbellard 38785571bc7Sbellard s->sem = SDL_CreateSemaphore (0); 38885571bc7Sbellard if (!s->sem) { 389*1d14ffa9Sbellard sdl_logerr ("Failed to create SDL semaphore\n"); 39085571bc7Sbellard SDL_DestroyMutex (s->mutex); 39185571bc7Sbellard SDL_QuitSubSystem (SDL_INIT_AUDIO); 39285571bc7Sbellard return NULL; 39385571bc7Sbellard } 39485571bc7Sbellard 39585571bc7Sbellard return s; 39685571bc7Sbellard } 39785571bc7Sbellard 39885571bc7Sbellard static void sdl_audio_fini (void *opaque) 39985571bc7Sbellard { 40085571bc7Sbellard SDLAudioState *s = opaque; 40185571bc7Sbellard sdl_close (s); 40285571bc7Sbellard SDL_DestroySemaphore (s->sem); 40385571bc7Sbellard SDL_DestroyMutex (s->mutex); 40485571bc7Sbellard SDL_QuitSubSystem (SDL_INIT_AUDIO); 40585571bc7Sbellard } 40685571bc7Sbellard 407*1d14ffa9Sbellard static struct audio_option sdl_options[] = { 408*1d14ffa9Sbellard {"SAMPLES", AUD_OPT_INT, &conf.nb_samples, 409*1d14ffa9Sbellard "Size of SDL buffer in samples", NULL, 0}, 410*1d14ffa9Sbellard {NULL, 0, NULL, NULL, NULL, 0} 41185571bc7Sbellard }; 41285571bc7Sbellard 413*1d14ffa9Sbellard static struct audio_pcm_ops sdl_pcm_ops = { 414*1d14ffa9Sbellard sdl_init_out, 415*1d14ffa9Sbellard sdl_fini_out, 416*1d14ffa9Sbellard sdl_run_out, 417*1d14ffa9Sbellard sdl_write_out, 418*1d14ffa9Sbellard sdl_ctl_out, 419*1d14ffa9Sbellard 420*1d14ffa9Sbellard NULL, 421*1d14ffa9Sbellard NULL, 422*1d14ffa9Sbellard NULL, 423*1d14ffa9Sbellard NULL, 424*1d14ffa9Sbellard NULL 425*1d14ffa9Sbellard }; 426*1d14ffa9Sbellard 427*1d14ffa9Sbellard struct audio_driver sdl_audio_driver = { 428*1d14ffa9Sbellard INIT_FIELD (name = ) "sdl", 429*1d14ffa9Sbellard INIT_FIELD (descr = ) "SDL http://www.libsdl.org", 430*1d14ffa9Sbellard INIT_FIELD (options = ) sdl_options, 431*1d14ffa9Sbellard INIT_FIELD (init = ) sdl_audio_init, 432*1d14ffa9Sbellard INIT_FIELD (fini = ) sdl_audio_fini, 433*1d14ffa9Sbellard INIT_FIELD (pcm_ops = ) &sdl_pcm_ops, 434*1d14ffa9Sbellard INIT_FIELD (can_be_default = ) 1, 435*1d14ffa9Sbellard INIT_FIELD (max_voices_out = ) 1, 436*1d14ffa9Sbellard INIT_FIELD (max_voices_in = ) 0, 437*1d14ffa9Sbellard INIT_FIELD (voice_size_out = ) sizeof (SDLVoiceOut), 438*1d14ffa9Sbellard INIT_FIELD (voice_size_in = ) 0 43985571bc7Sbellard }; 440