ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/audio.cpp
Revision: 1.2
Committed: 1999-10-20T15:13:52Z (25 years ago) by cebix
Branch: MAIN
CVS Tags: snapshot-21101999, snapshot-22121999, release-0_8-1, snapshot-02111999
Changes since 1.1: +29 -13 lines
Log Message:
- renamed main_volume to speaker_volume and dac_volume to main_volume
  (same for mute)
- added defines for headphone volume/mute

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * audio.cpp - Audio support
3     *
4     * Basilisk II (C) 1997-1999 Christian Bauer
5     * Portions (C) 1997-1999 Marc Hellwig
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20     */
21    
22     /*
23     * SEE ALSO
24     * Inside Macintosh: Sound, chapter 5 "Sound Components"
25     */
26    
27     #include "sysdeps.h"
28     #include "cpu_emulation.h"
29     #include "macos_util.h"
30     #include "emul_op.h"
31     #include "main.h"
32     #include "audio.h"
33     #include "audio_defs.h"
34    
35     #define DEBUG 0
36     #include "debug.h"
37    
38    
39     // Global variables
40     struct audio_status AudioStatus; // Current audio status (sample rate etc.)
41     bool audio_open = false; // Flag: audio is initialized and ready
42     int audio_frames_per_block; // Number of audio frames per block
43     uint32 audio_component_flags; // Component feature flags
44     uint32 audio_data = 0; // Mac address of global data area
45     static int open_count = 0; // Open/close nesting count
46    
47     bool AudioAvailable = false; // Flag: audio output available (from the software point of view)
48    
49    
50     /*
51     * Get audio info
52     */
53    
54     static int32 AudioGetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
55     {
56     D(bug(" AudioGetInfo %c%c%c%c, infoPtr %08lx, source ID %08lx\n", selector >> 24, (selector >> 16) & 0xff, (selector >> 8) & 0xff, selector & 0xff, infoPtr, sourceID));
57     M68kRegisters r;
58     int i;
59    
60     switch (selector) {
61     case siSampleSize:
62     WriteMacInt16(infoPtr, AudioStatus.sample_size);
63     break;
64    
65     case siSampleSizeAvailable: {
66     r.d[0] = audio_num_sample_sizes * 2;
67     Execute68kTrap(0xa122, &r); // NewHandle()
68     uint32 h = r.a[0];
69     if (h == 0)
70     return memFullErr;
71     WriteMacInt16(infoPtr + sil_count, audio_num_sample_sizes);
72     WriteMacInt32(infoPtr + sil_infoHandle, h);
73     uint32 sp = ReadMacInt32(h);
74     for (i=0; i<audio_num_sample_sizes; i++)
75     WriteMacInt16(sp + i*2, audio_sample_sizes[i]);
76     break;
77     }
78    
79     case siNumberChannels:
80     WriteMacInt16(infoPtr, AudioStatus.channels);
81     break;
82    
83     case siChannelAvailable: {
84     r.d[0] = audio_num_channel_counts * 2;
85     Execute68kTrap(0xa122, &r); // NewHandle()
86     uint32 h = r.a[0];
87     if (h == 0)
88     return memFullErr;
89     WriteMacInt16(infoPtr + sil_count, audio_num_channel_counts);
90     WriteMacInt32(infoPtr + sil_infoHandle, h);
91     uint32 sp = ReadMacInt32(h);
92     for (i=0; i<audio_num_channel_counts; i++)
93     WriteMacInt16(sp + i*2, audio_channel_counts[i]);
94     break;
95     }
96    
97     case siSampleRate:
98     WriteMacInt32(infoPtr, AudioStatus.sample_rate);
99     break;
100    
101     case siSampleRateAvailable: {
102     r.d[0] = audio_num_sample_rates * 4;
103     Execute68kTrap(0xa122, &r); // NewHandle()
104     uint32 h = r.a[0];
105     if (h == 0)
106     return memFullErr;
107     WriteMacInt16(infoPtr + sil_count, audio_num_sample_rates);
108     WriteMacInt32(infoPtr + sil_infoHandle, h);
109     uint32 lp = ReadMacInt32(h);
110     for (i=0; i<audio_num_sample_rates; i++)
111     WriteMacInt32(lp + i*4, audio_sample_rates[i]);
112     break;
113     }
114    
115     case siSpeakerMute:
116 cebix 1.2 WriteMacInt16(infoPtr, audio_get_speaker_mute());
117 cebix 1.1 break;
118    
119     case siSpeakerVolume:
120 cebix 1.2 WriteMacInt32(infoPtr, audio_get_speaker_volume());
121     break;
122    
123     case siHeadphoneMute:
124     WriteMacInt16(infoPtr, 0);
125     break;
126    
127     case siHeadphoneVolume:
128     WriteMacInt32(infoPtr, 0x01000100);
129     break;
130    
131     case siHeadphoneVolumeSteps:
132     WriteMacInt16(infoPtr, 13);
133 cebix 1.1 break;
134    
135     case siHardwareMute:
136 cebix 1.2 WriteMacInt16(infoPtr, audio_get_main_mute());
137 cebix 1.1 break;
138    
139     case siHardwareVolume:
140 cebix 1.2 WriteMacInt32(infoPtr, audio_get_main_volume());
141     break;
142    
143     case siHardwareVolumeSteps:
144     WriteMacInt16(infoPtr, 13);
145 cebix 1.1 break;
146    
147     case siHardwareBusy:
148     WriteMacInt16(infoPtr, AudioStatus.num_sources != 0);
149     break;
150    
151     default: // Delegate to Apple Mixer
152     if (AudioStatus.mixer == 0)
153     return badComponentSelector;
154     M68kRegisters r;
155     r.a[0] = infoPtr;
156     r.d[0] = selector;
157     r.a[1] = sourceID;
158     r.a[2] = AudioStatus.mixer;
159     Execute68k(audio_data + adatGetInfo, &r);
160     D(bug(" delegated to Apple Mixer, returns %08lx\n", r.d[0]));
161     return r.d[0];
162     }
163     return noErr;
164     }
165    
166    
167     /*
168     * Set audio info
169     */
170    
171     static int32 AudioSetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
172     {
173     D(bug(" AudioSetInfo %c%c%c%c, infoPtr %08lx, source ID %08lx\n", selector >> 24, (selector >> 16) & 0xff, (selector >> 8) & 0xff, selector & 0xff, infoPtr, sourceID));
174     M68kRegisters r;
175     int i;
176    
177     switch (selector) {
178     case siSampleSize:
179     D(bug(" set sample size %08lx\n", infoPtr));
180     if (AudioStatus.num_sources)
181     return siDeviceBusyErr;
182     for (i=0; i<audio_num_sample_sizes; i++)
183     if (audio_sample_sizes[i] == infoPtr) {
184     audio_set_sample_size(i);
185     return noErr;
186     }
187     return siInvalidSampleSize;
188    
189     case siSampleRate:
190     D(bug(" set sample rate %08lx\n", infoPtr));
191     if (AudioStatus.num_sources)
192     return siDeviceBusyErr;
193     for (i=0; i<audio_num_sample_rates; i++)
194     if (audio_sample_rates[i] == infoPtr) {
195     audio_set_sample_rate(i);
196     return noErr;
197     }
198     return siInvalidSampleRate;
199    
200     case siNumberChannels:
201     D(bug(" set number of channels %08lx\n", infoPtr));
202     if (AudioStatus.num_sources)
203     return siDeviceBusyErr;
204     for (i=0; i<audio_num_channel_counts; i++)
205     if (audio_channel_counts[i] == infoPtr) {
206     audio_set_channels(i);
207     return noErr;
208     }
209     return badChannel;
210    
211     case siSpeakerMute:
212 cebix 1.2 audio_set_speaker_mute((uint16)infoPtr);
213 cebix 1.1 break;
214    
215     case siSpeakerVolume:
216     D(bug(" set speaker volume %08lx\n", infoPtr));
217 cebix 1.2 audio_set_speaker_volume(infoPtr);
218     break;
219    
220     case siHeadphoneMute:
221     case siHeadphoneVolume:
222 cebix 1.1 break;
223    
224     case siHardwareMute:
225 cebix 1.2 audio_set_main_mute((uint16)infoPtr);
226 cebix 1.1 break;
227    
228     case siHardwareVolume:
229     D(bug(" set hardware volume %08lx\n", infoPtr));
230 cebix 1.2 audio_set_main_volume(infoPtr);
231 cebix 1.1 break;
232    
233     default: // Delegate to Apple Mixer
234     if (AudioStatus.mixer == 0)
235     return badComponentSelector;
236     r.a[0] = infoPtr;
237     r.d[0] = selector;
238     r.a[1] = sourceID;
239     r.a[2] = AudioStatus.mixer;
240     Execute68k(audio_data + adatSetInfo, &r);
241     D(bug(" delegated to Apple Mixer, returns %08lx\n", r.d[0]));
242     return r.d[0];
243     }
244     return noErr;
245     }
246    
247    
248     /*
249     * Sound output component dispatch
250     */
251    
252     int32 AudioDispatch(uint32 params, uint32 globals)
253     {
254     D(bug("AudioDispatch params %08lx (size %d), what %d\n", params, ReadMacInt8(params + cp_paramSize), (int16)ReadMacInt16(params + cp_what)));
255     M68kRegisters r;
256     uint32 p = params + cp_params;
257    
258     switch ((int16)ReadMacInt16(params + cp_what)) {
259     // Basic component functions
260     case kComponentOpenSelect:
261     if (audio_data == 0) {
262    
263     // Allocate global data area
264     r.d[0] = SIZEOF_adat;
265     Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
266     if (r.a[0] == 0)
267     return memFullErr;
268     audio_data = r.a[0];
269     D(bug(" global data at %08lx\n", audio_data));
270    
271     // Put in 68k routines
272     int p = audio_data + adatDelegateCall;
273     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
274     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
275     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
276     WriteMacInt16(p, 0x7024); p += 2; // moveq #$24,d0
277     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
278     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
279     WriteMacInt16(p, M68K_RTS); p += 2; // rts
280     if (p - audio_data != adatOpenMixer)
281     goto adat_error;
282     WriteMacInt16(p, 0x558f); p += 2; // subq.l #2,sp
283     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
284     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
285     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
286     WriteMacInt16(p, 0x203c); p += 2; // move.l #$06140018,d0
287     WriteMacInt32(p, 0x06140018); p+= 4;
288     WriteMacInt16(p, 0xa800); p += 2; // SoundDispatch
289     WriteMacInt16(p, 0x301f); p += 2; // move.w (sp)+,d0
290     WriteMacInt16(p, 0x48c0); p += 2; // ext.l d0
291     WriteMacInt16(p, M68K_RTS); p += 2; // rts
292     if (p - audio_data != adatCloseMixer)
293     goto adat_error;
294     WriteMacInt16(p, 0x558f); p += 2; // subq.l #2,sp
295     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
296     WriteMacInt16(p, 0x203c); p += 2; // move.l #$02180018,d0
297     WriteMacInt32(p, 0x02180018); p+= 4;
298     WriteMacInt16(p, 0xa800); p += 2; // SoundDispatch
299     WriteMacInt16(p, 0x301f); p += 2; // move.w (sp)+,d0
300     WriteMacInt16(p, 0x48c0); p += 2; // ext.l d0
301     WriteMacInt16(p, M68K_RTS); p += 2; // rts
302     if (p - audio_data != adatGetInfo)
303     goto adat_error;
304     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
305     WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
306     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
307     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
308     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
309     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0103,-(sp)
310     WriteMacInt32(p, 0x000c0103); p+= 4;
311     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
312     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
313     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
314     WriteMacInt16(p, M68K_RTS); p += 2; // rts
315     if (p - audio_data != adatSetInfo)
316     goto adat_error;
317     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
318     WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
319     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
320     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
321     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
322     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0104,-(sp)
323     WriteMacInt32(p, 0x000c0104); p+= 4;
324     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
325     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
326     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
327     WriteMacInt16(p, M68K_RTS); p += 2; // rts
328     if (p - audio_data != adatPlaySourceBuffer)
329     goto adat_error;
330     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
331     WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
332     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
333     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
334     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
335     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0108,-(sp)
336     WriteMacInt32(p, 0x000c0108); p+= 4;
337     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
338     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
339     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
340     WriteMacInt16(p, M68K_RTS); p += 2; // rts
341     if (p - audio_data != adatGetSourceData)
342     goto adat_error;
343     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
344     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
345     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
346     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$00040004,-(sp)
347     WriteMacInt32(p, 0x00040004); p+= 4;
348     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
349     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
350     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
351     WriteMacInt16(p, M68K_RTS); p += 2; // rts
352     if (p - audio_data != adatData)
353     goto adat_error;
354     }
355     AudioAvailable = true;
356     if (open_count == 0)
357     audio_enter_stream();
358     open_count++;
359     return noErr;
360    
361     adat_error: printf("FATAL: audio component data block initialization error\n");
362     QuitEmulator();
363     return openErr;
364    
365     case kComponentCanDoSelect:
366     case kComponentRegisterSelect:
367     return noErr;
368    
369     case kComponentVersionSelect:
370 cebix 1.2 return 0x00010003;
371 cebix 1.1
372     case kComponentCloseSelect:
373     open_count--;
374     if (open_count == 0) {
375     if (AudioStatus.mixer) {
376     // Close Apple Mixer
377     r.a[0] = AudioStatus.mixer;
378     Execute68k(audio_data + adatCloseMixer, &r);
379     AudioStatus.mixer = 0;
380     return r.d[0];
381     }
382     AudioStatus.num_sources = 0;
383     audio_exit_stream();
384     }
385     return noErr;
386    
387     // Sound component functions
388     case kSoundComponentInitOutputDeviceSelect:
389     D(bug(" InitOutputDevice\n"));
390     if (!audio_open)
391     return noHardwareErr;
392     if (AudioStatus.mixer)
393     return noErr;
394    
395     // Init sound component data
396     WriteMacInt32(audio_data + adatData + scd_flags, 0);
397     WriteMacInt32(audio_data + adatData + scd_format, AudioStatus.sample_size == 16 ? 'twos' : 'raw ');
398     WriteMacInt16(audio_data + adatData + scd_numChannels, AudioStatus.channels);
399     WriteMacInt16(audio_data + adatData + scd_sampleSize, AudioStatus.sample_size);
400     WriteMacInt32(audio_data + adatData + scd_sampleRate, AudioStatus.sample_rate);
401     WriteMacInt32(audio_data + adatData + scd_sampleCount, audio_frames_per_block);
402     WriteMacInt32(audio_data + adatData + scd_buffer, 0);
403     WriteMacInt32(audio_data + adatData + scd_reserved, 0);
404     WriteMacInt32(audio_data + adatStreamInfo, 0);
405    
406     // Open Apple Mixer
407     r.a[0] = audio_data + adatMixer;
408     r.d[0] = 0;
409     r.a[1] = audio_data + adatData;
410     Execute68k(audio_data + adatOpenMixer, &r);
411     AudioStatus.mixer = ReadMacInt32(audio_data + adatMixer);
412     D(bug(" OpenMixer() returns %08lx, mixer %08lx\n", r.d[0], AudioStatus.mixer));
413     return r.d[0];
414    
415     case kSoundComponentAddSourceSelect:
416     D(bug(" AddSource\n"));
417     AudioStatus.num_sources++;
418     goto delegate;
419    
420     case kSoundComponentRemoveSourceSelect:
421     D(bug(" RemoveSource\n"));
422     AudioStatus.num_sources--;
423     goto delegate;
424    
425     case kSoundComponentStopSourceSelect:
426     D(bug(" StopSource\n"));
427     goto delegate;
428    
429     case kSoundComponentPauseSourceSelect:
430     D(bug(" PauseSource\n"));
431     delegate: // Delegate call to Apple Mixer
432     D(bug(" delegating call to Apple Mixer\n"));
433     r.a[0] = AudioStatus.mixer;
434     r.a[1] = params;
435     Execute68k(audio_data + adatDelegateCall, &r);
436     D(bug(" returns %08lx\n", r.d[0]));
437     return r.d[0];
438    
439     case kSoundComponentStartSourceSelect:
440     D(bug(" StartSource\n"));
441     return noErr;
442    
443     case kSoundComponentGetInfoSelect:
444     return AudioGetInfo(ReadMacInt32(p), ReadMacInt32(p + 4), ReadMacInt32(p + 8));
445    
446     case kSoundComponentSetInfoSelect:
447     return AudioSetInfo(ReadMacInt32(p), ReadMacInt32(p + 4), ReadMacInt32(p + 8));
448    
449     case kSoundComponentPlaySourceBufferSelect:
450     D(bug(" PlaySourceBuffer\n"));
451     r.d[0] = ReadMacInt32(p);
452     r.a[0] = ReadMacInt32(p + 4);
453     r.a[1] = ReadMacInt32(p + 8);
454     r.a[2] = AudioStatus.mixer;
455     Execute68k(audio_data + adatPlaySourceBuffer, &r);
456     D(bug(" returns %08lx\n", r.d[0]));
457     return r.d[0];
458    
459     default:
460     return badComponentSelector;
461     }
462     }