0
|
1 /*
|
|
2 * PWP Generic Beep (PWPbeep) engine for digital audio.
|
|
3 *
|
|
4 */
|
|
5
|
|
6 #include "config.h"
|
|
7
|
|
8 #ifdef DRIVE_GB
|
|
9
|
|
10 #include <stdio.h>
|
|
11 #include <stdlib.h>
|
|
12 #include <string.h>
|
|
13 #include <math.h>
|
|
14
|
|
15 #include "pwplib.h"
|
|
16
|
|
17 struct {
|
|
18 struct {
|
|
19 int wvlgt;
|
|
20 int wvleft;
|
|
21 int wvphase;
|
|
22 int wvlgt1;
|
|
23 }ch[3];
|
|
24 int freq;
|
|
25 }pwpgb;
|
|
26
|
|
27 void gb_sound(int chan,int freq,int volume,int ratio)
|
|
28 {
|
|
29 if(volume&&freq){
|
|
30 int wvlgt=
|
|
31 ((double)(pwpgb.freq*12)/pow(1.059465,freq/256.0));
|
|
32
|
|
33 if(ratio<1)ratio=1;else if(ratio>255)ratio=255;
|
|
34
|
|
35 pwpgb.ch[chan].wvlgt=(wvlgt*ratio)>>7;
|
|
36 pwpgb.ch[chan].wvlgt1=2*pwpgb.ch[chan].wvlgt-wvlgt;
|
|
37
|
|
38 pwpgb.ch[chan].wvleft=pwpgb.ch[chan].wvlgt/(chan+2);
|
|
39 pwpgb.ch[chan].wvphase=volume;
|
|
40 }else{
|
|
41 pwpgb.ch[chan].wvphase=0;
|
|
42 pwpgb.ch[chan].wvleft=pwpgb.ch[chan].wvlgt=32123;
|
|
43 }
|
|
44 }
|
|
45
|
|
46 void gb_init(int freq)
|
|
47 {
|
|
48 pwpgb.freq=freq;
|
|
49 {int i=0;for(;i<3;i++)gb_sound(i,0,0,0);}
|
|
50 }
|
|
51
|
35
|
52 static void gb_gen1chan(char*d,int l,int freq)
|
0
|
53 {
|
|
54 int ph=128*256;
|
|
55 while(l--){
|
|
56 *d++=64+((ph>>8)&0x80);
|
|
57 ph+=freq;
|
|
58 }
|
|
59 }
|
|
60
|
|
61 #define CH pwpgb.ch
|
|
62
|
35
|
63 static void gb_beepemu(char*d,int l)
|
0
|
64 {
|
|
65 static int pf=0;
|
|
66 int
|
|
67 fq0=CH[0].wvlgt,
|
|
68 fq1=CH[1].wvlgt,
|
|
69 fq2=CH[2].wvlgt,fq;
|
|
70 if(CH[0].wvphase==0)fq0=32768;
|
|
71 if(CH[1].wvphase==0)fq1=32768;
|
|
72 if(CH[2].wvphase==0)fq2=32768;
|
|
73
|
|
74 if(fq0>fq1){int tmp=fq0;fq0=fq1;fq1=tmp;}
|
|
75 if(fq0>fq2){int tmp=fq0;fq0=fq2;fq2=tmp;}
|
|
76 if(fq1>fq2){int tmp=fq1;fq1=fq2;fq2=tmp;}
|
|
77
|
|
78 if(pf&1){
|
|
79 if(pf&2)fq=fq1;else fq=fq2;
|
|
80 if(!fq)fq=fq0;
|
|
81 }else{
|
|
82 fq=fq0;
|
|
83 if(fq==32768){fq=fq1;
|
|
84 if(fq==32768)fq=fq2;}
|
|
85 }
|
|
86 if(fq==32768)memset(d,128,l);else
|
|
87 {
|
|
88 fq=(65536*256)/fq;
|
|
89 gb_gen1chan(d,l,fq);
|
|
90 }
|
|
91 pf++;
|
|
92 }
|
|
93
|
|
94 void gb_genwave(char*d,int l)
|
|
95 {
|
|
96 int remain=0;
|
|
97
|
|
98 l<<=8;
|
|
99 while(l)
|
|
100 {
|
|
101 int min=CH[0].wvleft,w,sum;
|
|
102 w=CH[1].wvleft;if(w<min)min=w;
|
|
103 w=CH[2].wvleft;if(w<min)min=w;
|
|
104
|
|
105 sum=CH[0].wvphase+CH[1].wvphase+CH[2].wvphase+128;
|
|
106 if(sum<0)sum=0;else if(sum>255)sum=255;
|
|
107
|
|
108 if(min>l)min=l; l-=min;
|
|
109 memset(d,sum,(min+remain)>>8);
|
|
110 d+=((min+remain)>>8);
|
|
111 remain=(min+remain)&255;
|
|
112
|
|
113 {int i=0;
|
|
114 for(;i<3;i++){
|
|
115 w=CH[i].wvleft-=min;
|
|
116 if(!w)
|
|
117 {
|
|
118 CH[i].wvleft=CH[i].wvlgt1;
|
|
119 CH[i].wvlgt1=CH[i].wvlgt;
|
|
120 CH[i].wvlgt=CH[i].wvleft;
|
|
121 CH[i].wvphase=0-CH[i].wvphase;
|
|
122 }
|
|
123 }
|
|
124 }
|
|
125 }
|
|
126 }
|
|
127
|
|
128 /* my_memset, ... */
|
|
129
|
|
130 /*
|
|
131 gb_genwave_opt(char*buf,int endptr)
|
|
132 {
|
|
133 #define SETTILL(a) \
|
|
134 {int bord=w##a,rs;if(bord>endptr)goto last;\
|
|
135 rs=sum;if(rs&~0xff){if(rs<0)rs=0;else rs=255;}\
|
|
136 memset(buf+(ptr>>8),rs,2+((bord-ptr)>>8));ptr=bord;\
|
|
137 CH[a].wvphase=0-CH[a].wvphase;\
|
|
138 sum+=(CH[a].wvphase)<<1;\
|
|
139 w##a=ptr+CH[a].wvlgt;}
|
|
140 #define HANDLE(s0,s1,s2) \
|
|
141 {SETTILL(s0); \
|
|
142 if(w##s0<=w##s1)goto w##s0##w##s1##w##s2;else \
|
|
143 if(w##s0<=w##s2)goto w##s1##w##s0##w##s2;else \
|
|
144 goto w##s1##w##s2##w##s0;}
|
|
145
|
|
146 int ptr=0,sum=CH[0].wvphase+
|
|
147 CH[1].wvphase+
|
|
148 CH[2].wvphase;
|
|
149
|
|
150 int w0=CH[0].wvleft,
|
|
151 w1=CH[1].wvleft,
|
|
152 w2=CH[2].wvleft;
|
|
153
|
|
154 endptr<<=8;
|
|
155
|
|
156 w1w2w0:HANDLE(1,2,0);
|
|
157 w2w1w0:HANDLE(2,1,0);
|
|
158 w0w2w1:HANDLE(0,2,1);
|
|
159 w2w0w1:HANDLE(2,0,1);
|
|
160 w0w1w2:HANDLE(0,1,2);
|
|
161 w1w0w2:HANDLE(1,0,2);
|
|
162
|
|
163 last:
|
|
164 {int rs=sum;
|
|
165 if(rs&~0xff){if(rs<0)rs=0;else rs=255;}
|
|
166 memset(buf+(ptr>>8),rs,(endptr-ptr)>>8);}
|
|
167
|
|
168 CH[0].wvleft=w0-endptr;
|
|
169 CH[1].wvleft=w1-endptr;
|
|
170 CH[2].wvleft=w2-endptr;
|
|
171
|
|
172 #undef SETTILL
|
|
173 }
|
|
174 */
|
|
175
|
|
176 #if (0)
|
|
177 gb_genwave_opt(char*buf,int endptr)
|
|
178 {
|
|
179 int ptr=0,sum=CH[0].wvphase+
|
|
180 CH[1].wvphase+
|
|
181 CH[2].wvphase;
|
|
182
|
|
183 #define w0 CH[0].wvleft
|
|
184 #define w1 CH[1].wvleft
|
|
185 #define w2 CH[2].wvleft
|
|
186
|
|
187 /* volatile int w0=CH[0].wvleft,
|
|
188 w1=CH[1].wvleft,
|
|
189 w2=CH[2].wvleft;*/
|
|
190
|
|
191 endptr<<=8;
|
|
192
|
|
193 #define SETTILL(a) \
|
|
194 {int bord=w##a,rs;if(bord>endptr)goto last;\
|
|
195 rs=sum;if(rs&~0xff){if(rs<0)rs=0;else rs=255;}\
|
|
196 memset(buf+(ptr>>8),rs,2+((bord-(ptr&~0xff))>>8));ptr=bord;\
|
|
197 CH[a].wvphase=0-CH[a].wvphase;\
|
|
198 sum+=(CH[a].wvphase)<<1;\
|
|
199 w##a=ptr+CH[a].wvlgt;}
|
|
200
|
|
201 if(w0<=w1){
|
|
202 if(w1<=w2)goto w0w1w2;else
|
|
203 if(w2<=w0)goto w2w0w1;else
|
|
204 goto w0w2w1;
|
|
205 }else{
|
|
206 if(w0<=w2)goto w1w0w2;else
|
|
207 if(w2<=w1)goto w2w1w0; //.. else w1w2w0 (next)
|
|
208 }
|
|
209
|
|
210 w1w2w0:
|
|
211 SETTILL(1);
|
|
212 if(w1<=w2)goto w1w2w0;else
|
|
213 if(w1<=w0)goto w2w1w0;else //.. if(w1>w0)goto w2w0w1;
|
|
214 goto w2w0w1;
|
|
215 w2w1w0:
|
|
216 SETTILL(2);
|
|
217 if(w2<=w1)goto w2w1w0;else
|
|
218 if(w2<=w0)goto w1w2w0;else
|
|
219 goto w1w0w2;
|
|
220
|
|
221 w0w2w1:
|
|
222 SETTILL(0);
|
|
223 if(w0<=w2)goto w0w2w1;else
|
|
224 if(w0<=w1)goto w2w0w1;else //.. if(w0>w1)goto w2w1w0;
|
|
225 goto w2w1w0;
|
|
226 w2w0w1:
|
|
227 SETTILL(2);
|
|
228 if(w2<=w0)goto w2w0w1;else
|
|
229 if(w2<=w1)goto w0w2w1;else
|
|
230 goto w0w1w2; //.. not reqd
|
|
231
|
|
232 w0w1w2:
|
|
233 SETTILL(0);
|
|
234 if(w0<=w1)goto w0w1w2;else
|
|
235 if(w0<=w2)goto w1w0w2;else //.. if(w0>w2)goto w1w2w0;
|
|
236 goto w1w2w0;
|
|
237
|
|
238 w1w0w2:
|
|
239 SETTILL(1);
|
|
240 if(w1<=w0)goto w1w0w2;else
|
|
241 if(w1<=w2)goto w0w1w2;else
|
|
242 goto w0w2w1;
|
|
243
|
|
244 last:
|
|
245 {int rs=sum;
|
|
246 if(rs&~0xff){if(rs<0)rs=0;else rs=255;}
|
|
247 memset(buf+(ptr>>8),rs,2+((endptr-ptr)>>8));}
|
|
248
|
|
249 CH[0].wvleft=w0-endptr;
|
|
250 CH[1].wvleft=w1-endptr;
|
|
251 CH[2].wvleft=w2-endptr;
|
|
252
|
|
253 #undef SETTILL
|
|
254 }
|
|
255 #endif
|
|
256
|
|
257 #endif
|