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