|
|
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();
1.1.1.3 ! root 61: while(len--) {
! 62: recBuffer[recBufferWr++&REC_BUFFER_MASK] = *stream++;
! 63: }
1.1.1.2 root 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:
1.1.1.3 ! root 79: static void Audio_Input_InitBuf(void) {
1.1.1.2 root 80: recBufferRd = 0;
81: for (recBufferWr = 0; recBufferWr < AUDIO_RECBUF_INIT; recBufferWr++) {
82: recBuffer[recBufferWr] = 0;
83: }
84: }
85:
1.1.1.3 ! root 86: int Audio_Input_Read(void) {
1.1.1.2 root 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;
1.1 root 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: */
1.1.1.2 root 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());
1.1 root 126: DlgAlert_Notice("Error: Can't open SDL audio subsystem.");
127: bSoundOutputWorking = false;
128: return;
129: }
130: }
131:
132: /* Set up SDL audio: */
1.1.1.2 root 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;
1.1 root 137: request.userdata = NULL;
1.1.1.2 root 138: request.samples = AUDIO_BUFFER_SAMPLES; /* buffer size in samples */
1.1 root 139:
140: Audio_Output_Device = SDL_OpenAudioDevice(NULL, 0, &request, &granted, 0);
1.1.1.2 root 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: }
1.1 root 147: bSoundOutputWorking = false;
148: return;
149: }
150: bSoundOutputWorking = true;
1.1.1.2 root 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: }
1.1 root 159: }
160:
1.1.1.2 root 161: void Audio_Input_Init(void) {
1.1 root 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: */
1.1.1.2 root 166: if (SDL_WasInit(SDL_INIT_AUDIO) == 0) {
167: if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
1.1 root 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: */
1.1.1.2 root 176: request.freq = AUDIO_IN_FREQUENCY; /* 8kHz */
177: request.format = AUDIO_S16MSB; /* 16-Bit signed, big endian */
178: request.channels = 1; /* mono */
1.1 root 179: request.callback = Audio_Input_CallBack;
180: request.userdata = NULL;
1.1.1.2 root 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 */
1.1 root 184:
1.1.1.2 root 185: if (Audio_Input_Device==0){
1.1 root 186: Log_Printf(LOG_WARN, "Can't use audio: %s\n", SDL_GetError());
1.1.1.2 root 187: if(!bSoundInAlertShown) {
188: DlgAlert_Notice("Error: Can't open audio input device. No sound recording (will record silence instead).");
189: bSoundInAlertShown = true;
190: }
1.1 root 191: bSoundInputWorking = false;
192: return;
193: }
194:
195: bSoundInputWorking = true;
1.1.1.2 root 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: }
1.1 root 204: }
205:
206:
207: /*-----------------------------------------------------------------------*/
208: /**
209: * Free audio subsystem
210: */
1.1.1.2 root 211: void Audio_Output_UnInit(void) {
212: if (bSoundOutputWorking) {
1.1 root 213: /* Stop */
214: Audio_Output_Enable(false);
215:
216: SDL_CloseAudioDevice(Audio_Output_Device);
217:
218: bSoundOutputWorking = false;
219: }
220: }
221:
1.1.1.2 root 222: void Audio_Input_UnInit(void) {
223: if (bSoundInputWorking) {
1.1 root 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: */
1.1.1.2 root 237: void Audio_Output_Enable(bool bEnable) {
238: if (bEnable && !bPlayingBuffer) {
1.1 root 239: /* Start playing */
240: SDL_PauseAudioDevice(Audio_Output_Device, false);
241: bPlayingBuffer = true;
242: }
1.1.1.2 root 243: else if (!bEnable && bPlayingBuffer) {
1.1 root 244: /* Stop from playing */
245: SDL_PauseAudioDevice(Audio_Output_Device, true);
246: bPlayingBuffer = false;
247: }
248: }
249:
1.1.1.2 root 250: void Audio_Input_Enable(bool bEnable) {
251: if (bEnable && !bRecordingBuffer) {
252: /* Start recording */
253: Audio_Input_InitBuf();
1.1 root 254: SDL_PauseAudioDevice(Audio_Input_Device, false);
255: bRecordingBuffer = true;
256: }
1.1.1.2 root 257: else if (!bEnable && bRecordingBuffer) {
258: /* Stop recording */
1.1 root 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.