ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/AmigaOS/audio_amiga.cpp
Revision: 1.4
Committed: 1999-10-21T22:39:56Z (24 years, 8 months ago) by cebix
Branch: MAIN
Changes since 1.3: +8 -0 lines
Log Message:
- ExtFS works under AmigaOS
- fixed erroneous __regargs attributes in prefs_editor_amiga.cpp
  and audio_amiga.cpp for GCC

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * audio_amiga.cpp - Audio support, AmigaOS implementation using AHI
3     *
4     * Basilisk II (C) 1997-1999 Christian Bauer
5     *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include "sysdeps.h"
22    
23     #include <exec/types.h>
24     #include <exec/memory.h>
25     #include <devices/ahi.h>
26     #include <proto/exec.h>
27     #include <proto/ahi.h>
28    
29     #include "cpu_emulation.h"
30     #include "main.h"
31     #include "prefs.h"
32     #include "user_strings.h"
33     #include "audio.h"
34     #include "audio_defs.h"
35    
36     #define DEBUG 0
37     #include "debug.h"
38    
39    
40     // Supported sample rates, sizes and channels
41     int audio_num_sample_rates = 1;
42     uint32 audio_sample_rates[] = {22050 << 16};
43     int audio_num_sample_sizes = 1;
44     uint16 audio_sample_sizes[] = {16};
45     int audio_num_channel_counts = 1;
46     uint16 audio_channel_counts[] = {2};
47    
48    
49     // Global variables
50     static ULONG ahi_id = AHI_DEFAULT_ID; // AHI audio ID
51     static struct AHIAudioCtrl *ahi_ctrl = NULL;
52     static struct AHISampleInfo sample[2]; // Two sample infos for double-buffering
53     static struct Hook sf_hook;
54     static int play_buf = 0; // Number of currently played buffer
55     static long sound_buffer_size; // Size of one audio buffer in bytes
56     static int audio_block_fetched = 0; // Number of audio blocks fetched by interrupt routine
57    
58    
59     // Prototypes
60 cebix 1.4 #ifdef __GNUC__
61     static __saveds __attribute__((regparm(3))) ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/);
62     #else
63 cebix 1.2 static __saveds __regargs ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/);
64 cebix 1.4 #endif
65 cebix 1.1
66    
67     /*
68     * Initialization
69     */
70    
71     void AudioInit(void)
72     {
73     sample[0].ahisi_Address = sample[1].ahisi_Address = NULL;
74    
75     // Init audio status and feature flags
76     AudioStatus.sample_rate = audio_sample_rates[0];
77     AudioStatus.sample_size = audio_sample_sizes[0];
78     AudioStatus.channels = audio_channel_counts[0];
79     AudioStatus.mixer = 0;
80     AudioStatus.num_sources = 0;
81     audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
82    
83     // Sound disabled in prefs? Then do nothing
84     if (PrefsFindBool("nosound"))
85     return;
86    
87     // AHI available?
88     if (AHIBase == NULL) {
89     WarningAlert(GetString(STR_NO_AHI_WARN));
90     return;
91     }
92    
93     // Initialize callback hook
94     sf_hook.h_Entry = (HOOKFUNC)audio_callback;
95    
96     // Read "sound" preferences
97     const char *str = PrefsFindString("sound");
98     if (str)
99     sscanf(str, "ahi/%08lx", &ahi_id);
100    
101     // Open audio control structure
102     if ((ahi_ctrl = AHI_AllocAudio(
103     AHIA_AudioID, ahi_id,
104     AHIA_MixFreq, AudioStatus.sample_rate >> 16,
105     AHIA_Channels, 1,
106     AHIA_Sounds, 2,
107     AHIA_SoundFunc, (ULONG)&sf_hook,
108     TAG_END)) == NULL) {
109     WarningAlert(GetString(STR_NO_AHI_CTRL_WARN));
110     return;
111     }
112    
113     // 2048 frames per block
114     audio_frames_per_block = 2048;
115     sound_buffer_size = (AudioStatus.sample_size >> 3) * AudioStatus.channels * audio_frames_per_block;
116    
117     // Prepare SampleInfos and load sounds (two sounds for double buffering)
118     sample[0].ahisi_Type = AudioStatus.sample_size == 16 ? AHIST_S16S : AHIST_S8S;
119     sample[0].ahisi_Length = audio_frames_per_block;
120     sample[0].ahisi_Address = AllocVec(sound_buffer_size, MEMF_PUBLIC | MEMF_CLEAR);
121     sample[1].ahisi_Type = AudioStatus.sample_size == 16 ? AHIST_S16S : AHIST_S8S;
122     sample[1].ahisi_Length = audio_frames_per_block;
123     sample[1].ahisi_Address = AllocVec(sound_buffer_size, MEMF_PUBLIC | MEMF_CLEAR);
124     if (sample[0].ahisi_Address == NULL || sample[1].ahisi_Address == NULL)
125     return;
126     AHI_LoadSound(0, AHIST_DYNAMICSAMPLE, &sample[0], ahi_ctrl);
127     AHI_LoadSound(1, AHIST_DYNAMICSAMPLE, &sample[1], ahi_ctrl);
128    
129     // Set parameters
130     play_buf = 0;
131     AHI_SetVol(0, 0x10000, 0x8000, ahi_ctrl, AHISF_IMM);
132     AHI_SetFreq(0, AudioStatus.sample_rate >> 16, ahi_ctrl, AHISF_IMM);
133     AHI_SetSound(0, play_buf, 0, 0, ahi_ctrl, AHISF_IMM);
134    
135     // Everything OK
136     audio_open = true;
137     }
138    
139    
140     /*
141     * Deinitialization
142     */
143    
144     void AudioExit(void)
145     {
146     // Free everything
147     if (ahi_ctrl != NULL) {
148     AHI_ControlAudio(ahi_ctrl, AHIC_Play, FALSE, TAG_END);
149     AHI_FreeAudio(ahi_ctrl);
150     }
151    
152     FreeVec(sample[0].ahisi_Address);
153     FreeVec(sample[1].ahisi_Address);
154     }
155    
156    
157     /*
158     * First source added, start audio stream
159     */
160    
161     void audio_enter_stream()
162     {
163     AHI_ControlAudio(ahi_ctrl, AHIC_Play, TRUE, TAG_END);
164     }
165    
166    
167     /*
168     * Last source removed, stop audio stream
169     */
170    
171     void audio_exit_stream()
172     {
173     AHI_ControlAudio(ahi_ctrl, AHIC_Play, FALSE, TAG_END);
174     }
175    
176    
177     /*
178     * AHI sound callback, request next buffer
179     */
180    
181 cebix 1.4 #ifdef __GNUC__
182     static __saveds __attribute__((regparm(3))) ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/)
183     #else
184 cebix 1.2 static __saveds __regargs ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/)
185 cebix 1.4 #endif
186 cebix 1.1 {
187     play_buf ^= 1;
188    
189     // New buffer available?
190     if (audio_block_fetched) {
191     audio_block_fetched--;
192    
193     // Get size of audio data
194     uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
195     if (apple_stream_info) {
196     int work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels;
197     D(bug("stream: work_size %d\n", work_size));
198     if (work_size > sound_buffer_size)
199     work_size = sound_buffer_size;
200    
201     // Put data into AHI buffer (convert 8-bit data unsigned->signed)
202     if (AudioStatus.sample_size == 16)
203     memcpy(sample[play_buf].ahisi_Address, Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)), work_size);
204     else {
205     uint32 *p = (uint32 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer));
206     uint32 *q = (uint32 *)sample[play_buf].ahisi_Address;
207     int r = work_size >> 2;
208     while (r--)
209     *q++ = *p++ ^ 0x80808080;
210     }
211     if (work_size != sound_buffer_size)
212     memset((uint8 *)sample[play_buf].ahisi_Address + work_size, 0, sound_buffer_size - work_size);
213     }
214    
215     } else
216     memset(sample[play_buf].ahisi_Address, 0, sound_buffer_size);
217    
218     // Play next buffer
219     AHI_SetSound(0, play_buf, 0, 0, ahi_ctrl, 0);
220    
221     // Trigger audio interrupt to get new buffer
222     if (AudioStatus.num_sources) {
223     D(bug("stream: triggering irq\n"));
224     SetInterruptFlag(INTFLAG_AUDIO);
225     TriggerInterrupt();
226     }
227     return 0;
228     }
229    
230    
231     /*
232     * MacOS audio interrupt, read next data block
233     */
234    
235     void AudioInterrupt(void)
236     {
237     D(bug("AudioInterrupt\n"));
238    
239     // Get data from apple mixer
240     if (AudioStatus.mixer) {
241     M68kRegisters r;
242     r.a[0] = audio_data + adatStreamInfo;
243     r.a[1] = AudioStatus.mixer;
244     Execute68k(audio_data + adatGetSourceData, &r);
245     D(bug(" GetSourceData() returns %08lx\n", r.d[0]));
246     } else
247     WriteMacInt32(audio_data + adatStreamInfo, 0);
248    
249     // Signal stream function
250     audio_block_fetched++;
251     D(bug("AudioInterrupt done\n"));
252     }
253    
254    
255     /*
256     * Set sampling parameters
257     * "index" is an index into the audio_sample_rates[] etc. arrays
258     * It is guaranteed that AudioStatus.num_sources == 0
259     */
260    
261     void audio_set_sample_rate(int index)
262     {
263     }
264    
265     void audio_set_sample_size(int index)
266     {
267     }
268    
269     void audio_set_channels(int index)
270     {
271     }
272    
273    
274     /*
275     * Get/set volume controls (volume values received/returned have the left channel
276     * volume in the upper 16 bits and the right channel volume in the lower 16 bits;
277     * both volumes are 8.8 fixed point values with 0x0100 meaning "maximum volume"))
278     */
279    
280     bool audio_get_main_mute(void)
281     {
282     return false;
283     }
284    
285     uint32 audio_get_main_volume(void)
286     {
287     return 0x01000100;
288     }
289    
290 cebix 1.3 bool audio_get_speaker_mute(void)
291 cebix 1.1 {
292     return false;
293     }
294    
295 cebix 1.3 uint32 audio_get_speaker_volume(void)
296 cebix 1.1 {
297     return 0x01000100;
298     }
299    
300     void audio_set_main_mute(bool mute)
301     {
302     }
303    
304     void audio_set_main_volume(uint32 vol)
305     {
306     }
307    
308 cebix 1.3 void audio_set_speaker_mute(bool mute)
309 cebix 1.1 {
310     }
311    
312 cebix 1.3 void audio_set_speaker_volume(uint32 vol)
313 cebix 1.1 {
314     }