|
|
1.1 ! root 1: /* ! 2: * UAE - The Un*x Amiga Emulator ! 3: * ! 4: * Support for Linux/USS sound ! 5: * ! 6: * Copyright 1997 Bernd Schmidt ! 7: */ ! 8: ! 9: #include "sysconfig.h" ! 10: #include "sysdeps.h" ! 11: ! 12: #include "config.h" ! 13: #include "options.h" ! 14: #include "memory.h" ! 15: #include "events.h" ! 16: #include "custom.h" ! 17: #include "gensound.h" ! 18: #include "sounddep/sound.h" ! 19: #include "threaddep/thread.h" ! 20: #include "SDL_audio.h" ! 21: ! 22: int sound_fd; ! 23: static int have_sound = 0; ! 24: static unsigned long formats; ! 25: ! 26: uae_u16 sndbuffer[44100]; ! 27: uae_u16 *sndbufpt; ! 28: int sndbufsize; ! 29: static SDL_AudioSpec spec; ! 30: ! 31: static smp_comm_pipe to_sound_pipe; ! 32: static uae_sem_t data_available_sem, callback_done_sem, sound_init_sem; ! 33: ! 34: static int in_callback, closing_sound; ! 35: ! 36: static void sound_callback (void *userdata, Uint8 *stream, int len) ! 37: { ! 38: if (closing_sound) ! 39: return; ! 40: in_callback = 1; ! 41: /* Wait for data to finish. */ ! 42: uae_sem_wait (&data_available_sem); ! 43: if (! closing_sound) { ! 44: memcpy (stream, sndbuffer, sndbufsize); ! 45: /* Notify writer that we're done. */ ! 46: uae_sem_post (&callback_done_sem); ! 47: } ! 48: in_callback = 0; ! 49: } ! 50: ! 51: void finish_sound_buffer (void) ! 52: { ! 53: uae_sem_post (&data_available_sem); ! 54: uae_sem_wait (&callback_done_sem); ! 55: } ! 56: ! 57: /* Try to determine whether sound is available. This is only for GUI purposes. */ ! 58: int setup_sound (void) ! 59: { ! 60: int size = currprefs.sound_maxbsiz; ! 61: ! 62: spec.freq = currprefs.sound_freq; ! 63: spec.format = AUDIO_S16; ! 64: spec.channels = currprefs.stereo ? 2 : 1; ! 65: size >>= spec.channels - 1; ! 66: size >>= 1; ! 67: while (size & (size - 1)) ! 68: size &= size - 1; ! 69: if (size < 512) ! 70: size = 512; ! 71: spec.samples = size; ! 72: spec.callback = sound_callback; ! 73: spec.userdata = 0; ! 74: ! 75: if (SDL_OpenAudio (&spec, NULL) < 0) { ! 76: write_log (stderr, "Couldn't open audio: %s\n", SDL_GetError()); ! 77: return 0; ! 78: } ! 79: sound_available = 1; ! 80: SDL_CloseAudio (); ! 81: return 1; ! 82: } ! 83: ! 84: static int open_sound (void) ! 85: { ! 86: int size = currprefs.sound_maxbsiz; ! 87: ! 88: spec.freq = currprefs.sound_freq; ! 89: spec.format = currprefs.sound_bits == 8 ? AUDIO_U8 : AUDIO_S16; ! 90: spec.channels = currprefs.stereo ? 2 : 1; ! 91: /* Always interpret buffer size as number of samples, not as actual ! 92: buffer size. Of course, since 8192 is the default, we'll have to ! 93: scale that to a sane value (assuming that otherwise 16 bits and ! 94: stereo would have been enabled and we'd have done the shift by ! 95: two anyway). */ ! 96: size >>= 2; ! 97: while (size & (size - 1)) ! 98: size &= size - 1; ! 99: if (size < 512) ! 100: size = 512; ! 101: spec.samples = size; ! 102: spec.callback = sound_callback; ! 103: spec.userdata = 0; ! 104: ! 105: if (SDL_OpenAudio (&spec, NULL) < 0) { ! 106: write_log (stderr, "Couldn't open audio: %s\n", SDL_GetError()); ! 107: return 0; ! 108: } ! 109: have_sound = 1; ! 110: ! 111: scaled_sample_evtime = (unsigned long)maxhpos * maxvpos * vblank_hz * CYCLE_UNIT / spec.freq; ! 112: scaled_sample_evtime_ok = 1; ! 113: ! 114: if (spec.format == AUDIO_S16) { ! 115: init_sound_table16 (); ! 116: sample_handler = currprefs.stereo ? sample16s_handler : sample16_handler; ! 117: } else { ! 118: init_sound_table8 (); ! 119: sample_handler = currprefs.stereo ? sample8s_handler : sample8_handler; ! 120: } ! 121: sound_available = 1; ! 122: write_log ("SDL sound driver found and configured for %d bits at %d Hz, buffer is %d samples\n", ! 123: currprefs.sound_bits, spec.freq, spec.samples); ! 124: sndbufpt = sndbuffer; ! 125: sndbufsize = size * currprefs.sound_bits / 8 * spec.channels; ! 126: return 1; ! 127: } ! 128: ! 129: static void *sound_thread (void *dummy) ! 130: { ! 131: for (;;) { ! 132: int cmd = read_comm_pipe_int_blocking (&to_sound_pipe); ! 133: int n; ! 134: ! 135: switch (cmd) { ! 136: case 0: ! 137: open_sound (); ! 138: uae_sem_post (&sound_init_sem); ! 139: break; ! 140: case 1: ! 141: uae_sem_post (&sound_init_sem); ! 142: return 0; ! 143: } ! 144: } ! 145: } ! 146: ! 147: /* We need a thread for this, since communication between finish_sound_buffer ! 148: and the callback works through semaphores. In theory, this is unnecessary, ! 149: since SDL uses a sound thread internally, and the callback runs in its ! 150: context. But we don't want to depend on SDL's internals too much. */ ! 151: static void init_sound_thread (void) ! 152: { ! 153: uae_thread_id tid; ! 154: ! 155: init_comm_pipe (&to_sound_pipe, 20, 1); ! 156: uae_sem_init (&data_available_sem, 0, 0); ! 157: uae_sem_init (&callback_done_sem, 0, 0); ! 158: uae_sem_init (&sound_init_sem, 0, 0); ! 159: uae_start_thread (sound_thread, NULL, &tid); ! 160: } ! 161: ! 162: void close_sound (void) ! 163: { ! 164: if (! have_sound) ! 165: return; ! 166: ! 167: SDL_PauseAudio (1); ! 168: if (in_callback) { ! 169: closing_sound = 1; ! 170: uae_sem_post (&data_available_sem); ! 171: } ! 172: write_comm_pipe_int (&to_sound_pipe, 1, 1); ! 173: uae_sem_wait (&sound_init_sem); ! 174: SDL_CloseAudio (); ! 175: uae_sem_destroy (&data_available_sem); ! 176: uae_sem_destroy (&sound_init_sem); ! 177: uae_sem_destroy (&callback_done_sem); ! 178: have_sound = 0; ! 179: } ! 180: ! 181: int init_sound (void) ! 182: { ! 183: in_callback = 0; ! 184: closing_sound = 0; ! 185: ! 186: init_sound_thread (); ! 187: write_comm_pipe_int (&to_sound_pipe, 0, 1); ! 188: uae_sem_wait (&sound_init_sem); ! 189: SDL_PauseAudio (0); ! 190: ! 191: return have_sound; ! 192: } ! 193: ! 194: void pause_sound (void) ! 195: { ! 196: SDL_PauseAudio (1); ! 197: } ! 198: ! 199: void resume_sound (void) ! 200: { ! 201: SDL_PauseAudio (0); ! 202: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.