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