|
|
1.1.1.4 ! root 1: /* 1.1 root 2: * UAE - The Un*x Amiga Emulator 1.1.1.4 ! root 3: * 1.1 root 4: * Support for Linux/USS sound 1.1.1.4 ! root 5: * 1.1 root 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; 1.1.1.3 root 64: spec.channels = currprefs.sound_stereo ? 2 : 1; 1.1 root 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; 1.1.1.3 root 90: spec.channels = currprefs.sound_stereo ? 2 : 1; 1.1 root 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). */ 1.1.1.3 root 96: size >>= spec.channels - 1; 97: size >>= currprefs.sound_bits == 8 ? 0 : 1; 1.1 root 98: while (size & (size - 1)) 99: size &= size - 1; 100: if (size < 512) 101: size = 512; 102: spec.samples = size; 103: spec.callback = sound_callback; 104: spec.userdata = 0; 105: 106: if (SDL_OpenAudio (&spec, NULL) < 0) { 107: write_log (stderr, "Couldn't open audio: %s\n", SDL_GetError()); 108: return 0; 109: } 110: have_sound = 1; 111: 1.1.1.2 root 112: scaled_sample_evtime = (unsigned long)MAXHPOS_PAL * MAXVPOS_PAL * VBLANK_HZ_PAL * CYCLE_UNIT / spec.freq; 1.1 root 113: scaled_sample_evtime_ok = 1; 114: 115: if (spec.format == AUDIO_S16) { 116: init_sound_table16 (); 1.1.1.3 root 117: sample_handler = currprefs.sound_stereo ? sample16s_handler : sample16_handler; 1.1 root 118: } else { 119: init_sound_table8 (); 1.1.1.3 root 120: sample_handler = currprefs.sound_stereo ? sample8s_handler : sample8_handler; 1.1 root 121: } 122: sound_available = 1; 123: write_log ("SDL sound driver found and configured for %d bits at %d Hz, buffer is %d samples\n", 124: currprefs.sound_bits, spec.freq, spec.samples); 125: sndbufpt = sndbuffer; 126: sndbufsize = size * currprefs.sound_bits / 8 * spec.channels; 127: return 1; 128: } 129: 130: static void *sound_thread (void *dummy) 131: { 132: for (;;) { 133: int cmd = read_comm_pipe_int_blocking (&to_sound_pipe); 134: int n; 135: 136: switch (cmd) { 137: case 0: 138: open_sound (); 139: uae_sem_post (&sound_init_sem); 140: break; 141: case 1: 142: uae_sem_post (&sound_init_sem); 143: return 0; 144: } 145: } 146: } 147: 148: /* We need a thread for this, since communication between finish_sound_buffer 149: and the callback works through semaphores. In theory, this is unnecessary, 150: since SDL uses a sound thread internally, and the callback runs in its 151: context. But we don't want to depend on SDL's internals too much. */ 152: static void init_sound_thread (void) 153: { 154: uae_thread_id tid; 155: 156: init_comm_pipe (&to_sound_pipe, 20, 1); 157: uae_sem_init (&data_available_sem, 0, 0); 158: uae_sem_init (&callback_done_sem, 0, 0); 159: uae_sem_init (&sound_init_sem, 0, 0); 160: uae_start_thread (sound_thread, NULL, &tid); 161: } 162: 163: void close_sound (void) 164: { 165: if (! have_sound) 166: return; 167: 168: SDL_PauseAudio (1); 169: if (in_callback) { 170: closing_sound = 1; 171: uae_sem_post (&data_available_sem); 172: } 173: write_comm_pipe_int (&to_sound_pipe, 1, 1); 174: uae_sem_wait (&sound_init_sem); 175: SDL_CloseAudio (); 176: uae_sem_destroy (&data_available_sem); 177: uae_sem_destroy (&sound_init_sem); 178: uae_sem_destroy (&callback_done_sem); 179: have_sound = 0; 180: } 181: 182: int init_sound (void) 183: { 184: in_callback = 0; 185: closing_sound = 0; 186: 187: init_sound_thread (); 188: write_comm_pipe_int (&to_sound_pipe, 0, 1); 189: uae_sem_wait (&sound_init_sem); 190: SDL_PauseAudio (0); 191: 192: return have_sound; 193: } 194: 195: void pause_sound (void) 196: { 197: SDL_PauseAudio (1); 198: } 199: 200: void resume_sound (void) 201: { 202: SDL_PauseAudio (0); 203: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.