822ce5132e44bde867133af2c7d199cc066f72cf
15 typedef struct Chan Chan
;
16 typedef struct DSP DSP
;
28 int channels
; /* number of channels (2 for stereo) */
29 int freq
; /* frequency of sound stream */
31 int rfreq
; /* frequency of /dev/audio */
33 uchar
*buf
; /* resampling */
37 vlong time
; /* time point of the last sample in device buffer */
39 ulong written
; /* number of bytes written to dsp */
40 ulong written2
; /* same as written, will be reset on every GETOPTR ioctl */
46 DSP
*dsp
= (DSP
*)file
;
48 trace("dsp: closedsp");
56 polldsp(Ufile
*, void *)
62 readdsp(Ufile
*, void *, int, vlong
)
64 return 0; /* not implemented */
68 resample(Chan
*c
, uchar
*src
, uchar
*dst
, int sstep
, int dstep
, ulong delta
, ulong count
)
80 val
= sp
[0] | (sp
[1] << 8);
81 val
= (val
& 0x7FFF) - (val
& 0x8000);
84 last
= sp
[0] | (sp
[1] << 8);
85 last
= (last
& 0x7FFF) - (last
& 0x8000);
87 out
= last
+ (((val
- last
) * (phase
& 0xFFFF)) >> 16);
96 c
->phase
= phase
& 0xFFFF;
98 c
->phase
= phase
- (count
<< 16);
100 return (dp
- dst
) / dstep
;
104 convertout(DSP
*dsp
, uchar
*buf
, int len
, uchar
**out
)
109 /* no conversion required? */
110 if(dsp
->freq
== dsp
->rfreq
&& dsp
->channels
== CHANNELS
){
116 * delta is the number of input samples to
117 * produce one output sample. scaled by 16 bit to
118 * get fractional part.
120 delta
= ((ulong
)dsp
->freq
<< 16) / dsp
->rfreq
;
121 count
= len
/ (2 * dsp
->channels
);
124 * get maximum required size of output bufer. this is not exact!
125 * number of output samples depends on phase!
127 ret
= (((count
<< 16) + delta
-1) / delta
) * 2*CHANNELS
;
130 dsp
->buf
= kmalloc(ret
);
133 for(ch
=0; ch
< CHANNELS
; ch
++)
134 ret
= resample(dsp
->chan
+ ch
,
135 buf
+ 2*(ch
% dsp
->channels
),
143 return ret
* 2*CHANNELS
;
147 writedsp(Ufile
*file
, void *buf
, int len
, vlong
)
149 DSP
*dsp
= (DSP
*)file
;
154 if((ret
= convertout(dsp
, buf
, len
, &out
)) <= 0)
157 if((ret
= write(dsp
->fd
, out
, ret
)) < 0)
166 diff
= (dsp
->time
- now
) / 1000000;
170 dsp
->time
+= ((1000000000LL) * ret
/ (dsp
->rfreq
* 2*CHANNELS
));
172 dsp
->written2
+= len
;
183 ioctldsp(Ufile
*file
, int cmd
, void *arg
)
185 DSP
*dsp
= (DSP
*)file
;
193 trace("dsp: unknown ioctl %lux %p", (ulong
)cmd
, arg
);
198 trace("dsp: SNDCTL_DSP_SETFRAGMENT(%lux)", *(ulong
*)arg
);
202 trace("dsp: SNDCTL_DSP_GETBLKSIZE");
203 *((int*)arg
) = FRAGSIZE
;
207 trace("dsp: SNDCTL_DSP_GETIPTR");
212 trace("dsp: SNDCTL_DSP_GETOPTR");
213 ((int*)arg
)[0] = dsp
->written
; // Total # of bytes processed
214 ((int*)arg
)[1] = dsp
->written2
/ FRAGSIZE
; // # of fragment transitions since last time
216 ((int*)arg
)[2] = 0; // Current DMA pointer value
220 trace("dsp: SNDCTL_DSG_GETISPACE");
224 trace("dsp: SNDCTL_DSP_GETOSPACE");
225 i
= (2 * dsp
->channels
) * ((dsp
->freq
*DELAY
)/1000);
226 ((int*)arg
)[1] = i
/ FRAGSIZE
; // fragstot
227 ((int*)arg
)[2] = FRAGSIZE
; // fragsize
230 i
-= ((2 * dsp
->channels
) * (((dsp
->time
- now
) * (vlong
)dsp
->freq
) / 1000000000));
234 ((int*)arg
)[0] = i
/ FRAGSIZE
; // available fragment count
235 ((int*)arg
)[3] = i
; // available space in bytes
239 trace("dsp: SNDCTL_DSP_GETFMTS(%d)", *(int*)arg
);
240 *(int*)arg
= AFMT_S16_LE
;
244 trace("dsp: SNDCTL_DSP_GETCAPS");
249 trace("dsp: SNDCTL_DSP_SETFMT(%d)", *(int*)arg
);
250 *(int*)arg
= AFMT_S16_LE
;
254 trace("dsp: SOUND_PCM_WRITE_CHANNELS(%d)", *(int*)arg
);
255 dsp
->channels
= *(int*)arg
;
259 trace("dsp: SNDCTL_DSP_STEREO(%d)", *(int*)arg
);
265 trace("dsp: SNDCTL_DSP_SPEED(%d)", *(int*)arg
);
266 dsp
->freq
= *(int*)arg
;
267 for(i
=0; i
<CHANNELS
; i
++){
268 dsp
->chan
[i
].phase
= 0;
269 dsp
->chan
[i
].last
= 0;
274 trace("dsp: SNDCTL_DSP_RESET");
278 trace("dsp: SNDCTL_DSP_SYNC");
292 if((fd
= open("/dev/volume", OREAD
)) < 0)
294 if((n
= read(fd
, buf
, sizeof(buf
)-1)) > 0){
298 if(p
= strstr(buf
, "speed out "))
305 int opendsp(char *path
, int mode
, int, Ufile
**pf
)
311 if(strcmp(path
, "/dev/dsp")==0 || strcmp(path
, "/dev/dsp0")==0){
312 if((fd
= open("/dev/audio", OWRITE
)) < 0)
315 freq
= getaudiofreq();
316 dsp
= mallocz(sizeof(DSP
), 1);
321 dsp
->path
= kstrdup(path
);
324 dsp
->channels
= CHANNELS
;
334 fstatdsp(Ufile
*f
, Ustat
*s
)
336 s
->mode
= 0666 | S_IFCHR
;
337 s
->uid
= current
->uid
;
338 s
->gid
= current
->gid
;
339 s
->ino
= hashpath(f
->path
);
345 statdsp(char *path
, int , Ustat
*s
)
347 if(strcmp(path
, "/dev/dsp")==0 || strcmp(path
, "/dev/dsp0")==0){
348 s
->mode
= 0666 | S_IFCHR
;
349 s
->uid
= current
->uid
;
350 s
->gid
= current
->gid
;
351 s
->ino
= hashpath(path
);
371 void dspdevinit(void)
373 devtab
[DSPDEV
] = &dspdev
;
375 fsmount(&dspdev
, "/dev/dsp");
376 fsmount(&dspdev
, "/dev/dsp0");