1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * Support for Amiga audio.device sound
5 *
6 * Copyright 1996, 1997, 1998 Samuel Devulder, Holger Jakob (AHI).
7 * Copyright 2004-2007 Richard Drummond
8 */
9
10 #include "sysconfig.h"
11 #include "sysdeps.h"
12
13 #include "options.h"
14 #include "gensound.h"
15 #include "sounddep/sound.h"
16
17 #include <exec/memory_uae.h>
18 #include <graphics/gfxbase.h>
19
20 struct MsgPort *AHImp = NULL;
21 struct AHIRequest *AHIio[2] = {NULL, NULL};
22 struct AHIRequest *linkio = NULL;
23
24
25 unsigned char *buffers[2];
26 uae_u16 *paula_sndbuffer;
27 uae_u16 *paula_sndbufpt;
28 int paula_sndbufsize;
29 int bufidx;
30
31 unsigned int have_sound;
32 int clockval;
33 int period;
34
35
36
setup_sound(void)37 int setup_sound (void)
38 {
39 sound_available = 1;
40 return 1;
41 }
42
open_AHI(void)43 static BOOL open_AHI (void)
44 {
45 if ((AHImp = CreateMsgPort())) {
46 if ((AHIio[0] = (struct AHIRequest *)
47 CreateIORequest (AHImp, sizeof (struct AHIRequest)))) {
48 AHIio[0]->ahir_Version = 4;
49
50 if (!OpenDevice (AHINAME, 0, (struct IORequest *)AHIio[0], 0)) {
51 if ((AHIio[1] = malloc (sizeof(struct AHIRequest)))) {
52 memcpy (AHIio[1], AHIio[0], sizeof(struct AHIRequest));
53 return TRUE;
54 }
55 }
56 }
57 }
58 return FALSE;
59 }
60
close_AHI(void)61 static void close_AHI (void)
62 {
63 if (!CheckIO ((struct IORequest *)AHIio[0]))
64 WaitIO ((struct IORequest *)AHIio[0]);
65
66 if (linkio) { /* Only if the second request was started */
67 if (!CheckIO ((struct IORequest *) AHIio[1]))
68 WaitIO ((struct IORequest *) AHIio[1]);
69 }
70 CloseDevice ((struct IORequest *) AHIio[0]);
71 DeleteIORequest ((void*) AHIio[0]);
72 xfree (AHIio[1]);
73 DeleteMsgPort ((void*)AHImp);
74 AHIio[0] = NULL;
75 AHIio[1] = NULL;
76 linkio = NULL;
77 }
78
get_clockval(void)79 static int get_clockval (void)
80 {
81 struct GfxBase *GB;
82 int clk = 0;
83
84 GB = (void*) OpenLibrary ("graphics.library", 0L);
85
86 if (GB) {
87 if (GB->DisplayFlags & PAL)
88 clk = 3546895; /* PAL clock */
89 else
90 clk = 3579545; /* NTSC clock */
91 CloseLibrary ((void *) GB);
92 }
93 return clk;
94 }
95
init_sound(void)96 int init_sound (void)
97 {
98 /* too complex ? No it is only the allocation of a single channel ! */
99 /* it would have been far less painfull if AmigaOS provided a */
100 /* SOUND: device handler */
101 int rate;
102
103 atexit (close_sound); /* if only amiga os had resource tracking */
104
105 /* determine the clock */
106 clockval = get_clockval ();
107 if (clockval == 0)
108 goto fail;
109
110 /* check freq */
111 if (!currprefs.sound_freq)
112 currprefs.sound_freq = 22000;
113 if (clockval / currprefs.sound_freq < 80/*124*/ || clockval/currprefs.sound_freq > 65535) {
114 write_log ("Can't use sound with desired frequency %d Hz\n", currprefs.sound_freq);
115 changed_prefs.sound_freq = currprefs.sound_freq = 22000;
116 }
117 rate = currprefs.sound_freq;
118 period = (uae_u16)(clockval / rate);
119
120 if (!open_AHI ())
121 goto fail;
122
123 /* calculate buffer size */
124 paula_sndbufsize = rate * currprefs.sound_latency * 2 * (currprefs.sound_stereo ? 2 : 1) / 1000;
125 paula_sndbufsize = (paula_sndbufsize + 1) & ~1;
126
127 /* get the buffers */
128 buffers[0] = (void*) AllocMem (paula_sndbufsize,MEMF_PUBLIC | MEMF_CLEAR);
129 buffers[1] = (void*) AllocMem (paula_sndbufsize,MEMF_PUBLIC | MEMF_CLEAR);
130 if (!buffers[0] || !buffers[1])
131 goto fail;
132
133 bufidx = 0;
134 paula_sndbuffer = paula_sndbufpt = (uae_u16*) buffers[bufidx];
135
136 sample_handler = currprefs.sound_stereo ? sample16s_handler : sample16_handler;
137
138 have_sound = 1;
139 obtainedfreq = rate;
140
141 write_log ("Sound driver found and configured for %s "
142 "at %d Hz, buffer is %d bytes.\n",
143 currprefs.sound_stereo ? "stereo" : "mono",
144 rate, paula_sndbufsize);
145
146 sound_available = 1;
147 return 1;
148 fail:
149 sound_available = 0;
150 return 0;
151 }
152
close_sound(void)153 void close_sound (void)
154 {
155 close_AHI ();
156
157 if (buffers[0]) {
158 FreeMem ((APTR) buffers[0], paula_sndbufsize);
159 buffers[0] = 0;
160 }
161 if (buffers[1]) {
162 FreeMem ((APTR) buffers[1], paula_sndbufsize);
163 buffers[1] = 0;
164 }
165 if (sound_available) {
166 sound_available = 0;
167 }
168 }
169
pause_sound(void)170 void pause_sound (void)
171 {
172 }
173
resume_sound(void)174 void resume_sound (void)
175 {
176 }
177
reset_sound(void)178 void reset_sound (void)
179 {
180 }
181
sound_volume(int dir)182 void sound_volume (int dir)
183 {
184 }
185
186 /*
187 * Handle audio specific cfgfile options
188 */
audio_default_options(struct uae_prefs * p)189 void audio_default_options (struct uae_prefs *p)
190 {
191 }
192
audio_save_options(FILE * f,const struct uae_prefs * p)193 void audio_save_options (FILE *f, const struct uae_prefs *p)
194 {
195 }
196
audio_parse_option(struct uae_prefs * p,const char * option,const char * value)197 int audio_parse_option (struct uae_prefs *p, const char *option, const char *value)
198 {
199 return 0;
200 }
201