|
|
1.1 ! root 1: #include "main.h" ! 2: #include "dialog.h" ! 3: #include "configuration.h" ! 4: #include "m68000.h" ! 5: #include "sysdeps.h" ! 6: #include "audio.h" ! 7: #include "dma.h" ! 8: #include "snd.h" ! 9: #include "host.h" ! 10: ! 11: #include <SDL.h> ! 12: ! 13: ! 14: /* Sound emulation SDL interface */ ! 15: static SDL_AudioDeviceID Audio_Input_Device; ! 16: static SDL_AudioDeviceID Audio_Output_Device; ! 17: ! 18: static bool bSoundOutputWorking = false; /* Is sound output OK */ ! 19: static bool bSoundInputWorking = false; /* Is sound input OK */ ! 20: static bool bSoundOutAlertShown = false; ! 21: static bool bSoundInAlertShown = false; ! 22: static bool bPlayingBuffer = false; /* Is playing buffer? */ ! 23: static bool bRecordingBuffer = false; /* Is recording buffer? */ ! 24: #define REC_BUFFER_SZ 16 /* Recording buffer size in power of two */ ! 25: static const Uint32 REC_BUFFER_MASK = (1<<REC_BUFFER_SZ) - 1; ! 26: static Uint8 recBuffer[1<<REC_BUFFER_SZ]; ! 27: static Uint32 recBufferWr = 0; ! 28: static Uint32 recBufferRd = 0; ! 29: static lock_t recBufferLock; ! 30: ! 31: void Audio_Output_Queue(Uint8* data, int len) { ! 32: int chunkSize = AUDIO_BUFFER_SAMPLES; ! 33: if (bSoundOutputWorking) { ! 34: while (len > 0) { ! 35: if (len < chunkSize) chunkSize = len; ! 36: SDL_QueueAudio(Audio_Output_Device, data, chunkSize); ! 37: data += chunkSize; ! 38: len -= chunkSize; ! 39: } ! 40: } ! 41: } ! 42: ! 43: Uint32 Audio_Output_Queue_Size() { ! 44: if (bSoundOutputWorking) { ! 45: return SDL_GetQueuedAudioSize(Audio_Output_Device) / 4; ! 46: } else { ! 47: return 0; ! 48: } ! 49: } ! 50: ! 51: /*-----------------------------------------------------------------------*/ ! 52: /** ! 53: * SDL audio callback functions - move sound between emulation and audio system. ! 54: * Note: These functions will run in a separate thread. ! 55: */ ! 56: ! 57: static void Audio_Input_CallBack(void *userdata, Uint8 *stream, int len) { ! 58: Log_Printf(LOG_WARN, "Audio_Input_CallBack %d", len); ! 59: if(len == 0) return; ! 60: Audio_Input_Lock(); ! 61: while(len--) { ! 62: recBuffer[recBufferWr++&REC_BUFFER_MASK] = *stream++; ! 63: } ! 64: recBufferWr &= REC_BUFFER_MASK; ! 65: recBufferWr &= ~1; /* Just to be sure */ ! 66: Audio_Input_Unlock(); ! 67: } ! 68: ! 69: void Audio_Input_Lock() { ! 70: host_lock(&recBufferLock); ! 71: } ! 72: ! 73: /* ! 74: * Initialize recording buffer with silence to compensate for time gap ! 75: * between Audio_Input_Enable and first call of Audio_Input_CallBack. ! 76: */ ! 77: #define AUDIO_RECBUF_INIT 0 /* 16000 byte = 1 second */ ! 78: ! 79: static void Audio_Input_InitBuf(void) { ! 80: recBufferRd = 0; ! 81: for (recBufferWr = 0; recBufferWr < AUDIO_RECBUF_INIT; recBufferWr++) { ! 82: recBuffer[recBufferWr] = 0; ! 83: } ! 84: } ! 85: ! 86: int Audio_Input_Read(void) { ! 87: Sint16 sample = 0; ! 88: ! 89: if (bSoundInputWorking) { ! 90: if ((recBufferRd&REC_BUFFER_MASK)==(recBufferWr&REC_BUFFER_MASK)) { ! 91: return -1; ! 92: } else { ! 93: sample = ((recBuffer[recBufferRd&REC_BUFFER_MASK]<<8)|recBuffer[(recBufferRd&REC_BUFFER_MASK)+1]); ! 94: recBufferRd += 2; ! 95: recBufferRd &= REC_BUFFER_MASK; ! 96: return snd_make_ulaw(sample); ! 97: } ! 98: } else { ! 99: return snd_make_ulaw(0); // silence ! 100: } ! 101: } ! 102: ! 103: void Audio_Input_Unlock() { ! 104: host_unlock(&recBufferLock); ! 105: } ! 106: ! 107: static bool check_audio(int requested, int granted, const char* attribute) { ! 108: if(requested != granted) ! 109: Log_Printf(LOG_WARN, "[Audio] %s mismatch. Requested:%d, granted:%d", attribute, requested, granted); ! 110: return requested == granted; ! 111: } ! 112: ! 113: /*-----------------------------------------------------------------------*/ ! 114: /** ! 115: * Initialize the audio subsystem. Return true if all OK. ! 116: */ ! 117: void Audio_Output_Init(void) ! 118: { ! 119: SDL_AudioSpec request; /* We fill in the desired SDL audio options here */ ! 120: SDL_AudioSpec granted; ! 121: ! 122: /* Init the SDL's audio subsystem: */ ! 123: if (SDL_WasInit(SDL_INIT_AUDIO) == 0) { ! 124: if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { ! 125: Log_Printf(LOG_WARN, "[Audio] Could not init audio output: %s\n", SDL_GetError()); ! 126: DlgAlert_Notice("Error: Can't open SDL audio subsystem."); ! 127: bSoundOutputWorking = false; ! 128: return; ! 129: } ! 130: } ! 131: ! 132: /* Set up SDL audio: */ ! 133: request.freq = AUDIO_OUT_FREQUENCY; /* 44,1 kHz */ ! 134: request.format = AUDIO_S16MSB; /* 16-Bit signed, big endian */ ! 135: request.channels = 2; /* stereo */ ! 136: request.callback = NULL; ! 137: request.userdata = NULL; ! 138: request.samples = AUDIO_BUFFER_SAMPLES; /* buffer size in samples */ ! 139: ! 140: Audio_Output_Device = SDL_OpenAudioDevice(NULL, 0, &request, &granted, 0); ! 141: if (Audio_Output_Device==0) /* Open audio device */ { ! 142: Log_Printf(LOG_WARN, "[Audio] Can't use audio: %s\n", SDL_GetError()); ! 143: if(!bSoundOutAlertShown) { ! 144: DlgAlert_Notice("Error: Can't open audio output device. No sound output."); ! 145: bSoundOutAlertShown = true; ! 146: } ! 147: bSoundOutputWorking = false; ! 148: return; ! 149: } ! 150: bSoundOutputWorking = true; ! 151: bSoundOutputWorking &= check_audio(request.freq, granted.freq, "freq"); ! 152: bSoundOutputWorking &= check_audio(request.format, granted.format, "format"); ! 153: bSoundOutputWorking &= check_audio(request.channels, granted.channels, "channels"); ! 154: bSoundOutputWorking &= check_audio(request.samples, granted.samples, "samples"); ! 155: ! 156: if(!(bSoundOutputWorking)) { ! 157: DlgAlert_Notice("Error: Can't open audio output device. No sound output."); ! 158: } ! 159: } ! 160: ! 161: void Audio_Input_Init(void) { ! 162: SDL_AudioSpec request; /* We fill in the desired SDL audio options here */ ! 163: SDL_AudioSpec granted; ! 164: ! 165: /* Init the SDL's audio subsystem: */ ! 166: if (SDL_WasInit(SDL_INIT_AUDIO) == 0) { ! 167: if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { ! 168: Log_Printf(LOG_WARN, "Could not init audio input: %s\n", SDL_GetError()); ! 169: DlgAlert_Notice("Error: Can't open SDL audio subsystem."); ! 170: bSoundInputWorking = false; ! 171: return; ! 172: } ! 173: } ! 174: ! 175: /* Set up SDL audio: */ ! 176: request.freq = AUDIO_IN_FREQUENCY; /* 8kHz */ ! 177: request.format = AUDIO_S16MSB; /* 16-Bit signed, big endian */ ! 178: request.channels = 1; /* mono */ ! 179: request.callback = Audio_Input_CallBack; ! 180: request.userdata = NULL; ! 181: request.samples = AUDIO_BUFFER_SAMPLES; /* buffer size in samples */ ! 182: ! 183: Audio_Input_Device = SDL_OpenAudioDevice(NULL, 1, &request, &granted, 0); /* Open audio device */ ! 184: ! 185: if (Audio_Input_Device==0){ ! 186: Log_Printf(LOG_WARN, "Can't use audio: %s\n", SDL_GetError()); ! 187: if(!bSoundInAlertShown) { ! 188: DlgAlert_Notice("Error: Can't open audio input device. No sound recording (will record silence instead)."); ! 189: bSoundInAlertShown = true; ! 190: } ! 191: bSoundInputWorking = false; ! 192: return; ! 193: } ! 194: ! 195: bSoundInputWorking = true; ! 196: bSoundInputWorking &= check_audio(request.freq, granted.freq, "freq"); ! 197: bSoundInputWorking &= check_audio(request.format, granted.format, "format"); ! 198: bSoundInputWorking &= check_audio(request.channels, granted.channels, "channels"); ! 199: bSoundInputWorking &= check_audio(request.samples, granted.samples, "samples"); ! 200: ! 201: if(!(bSoundInputWorking)) { ! 202: DlgAlert_Notice("Error: Can't open audio input device. No sound recording (will record silence instead)."); ! 203: } ! 204: } ! 205: ! 206: ! 207: /*-----------------------------------------------------------------------*/ ! 208: /** ! 209: * Free audio subsystem ! 210: */ ! 211: void Audio_Output_UnInit(void) { ! 212: if (bSoundOutputWorking) { ! 213: /* Stop */ ! 214: Audio_Output_Enable(false); ! 215: ! 216: SDL_CloseAudioDevice(Audio_Output_Device); ! 217: ! 218: bSoundOutputWorking = false; ! 219: } ! 220: } ! 221: ! 222: void Audio_Input_UnInit(void) { ! 223: if (bSoundInputWorking) { ! 224: /* Stop */ ! 225: Audio_Input_Enable(false); ! 226: ! 227: SDL_CloseAudioDevice(Audio_Input_Device); ! 228: ! 229: bSoundInputWorking = false; ! 230: } ! 231: } ! 232: ! 233: /*-----------------------------------------------------------------------*/ ! 234: /** ! 235: * Start/Stop sound buffer ! 236: */ ! 237: void Audio_Output_Enable(bool bEnable) { ! 238: if (bEnable && !bPlayingBuffer) { ! 239: /* Start playing */ ! 240: SDL_PauseAudioDevice(Audio_Output_Device, false); ! 241: bPlayingBuffer = true; ! 242: } ! 243: else if (!bEnable && bPlayingBuffer) { ! 244: /* Stop from playing */ ! 245: SDL_PauseAudioDevice(Audio_Output_Device, true); ! 246: bPlayingBuffer = false; ! 247: } ! 248: } ! 249: ! 250: void Audio_Input_Enable(bool bEnable) { ! 251: if (bEnable && !bRecordingBuffer) { ! 252: /* Start recording */ ! 253: Audio_Input_InitBuf(); ! 254: SDL_PauseAudioDevice(Audio_Input_Device, false); ! 255: bRecordingBuffer = true; ! 256: } ! 257: else if (!bEnable && bRecordingBuffer) { ! 258: /* Stop recording */ ! 259: SDL_PauseAudioDevice(Audio_Input_Device, true); ! 260: bRecordingBuffer = false; ! 261: } ! 262: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.