1 /* aylet 0.4, a .AY music file player.
2 * Copyright (C) 2001-2004 Russell Marks and Ian Collier. See main.c for licence.
3 *
4 * drv-oss.c - OSS sound code, partly due to Matan Ziv-Av.
5 */
6
7 #ifdef DRIVER_OSS
8
9 #include <sys/ioctl.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <sys/soundcard.h>
14 #include "sound.h"
15
16 #include "driver.h"
17
18
19 /* using (4) 256 byte frags for 8kHz, scale up for higher */
20 #define BASE_SOUND_FRAG_PWR 8
21
22
23 /* returns non-zero on success, and adjusts freq/stereo args to reflect
24 * what we've actually got.
25 */
driver_init(int * freqptr,int * stereoptr)26 int driver_init(int *freqptr,int *stereoptr)
27 {
28 int frag,tmp;
29
30 if(play_to_stdout)
31 {
32 soundfd=1;
33 return(1);
34 }
35
36 if((soundfd=open("/dev/dsp",O_WRONLY))<0)
37 return(0);
38
39 tmp=AFMT_S16_NE;
40 if(!sixteenbit || ioctl(soundfd,SNDCTL_DSP_SETFMT,&tmp)==-1)
41 {
42 /* try 8-bit - may be a 8-bit-only device */
43 tmp=AFMT_U8;
44 if((ioctl(soundfd,SNDCTL_DSP_SETFMT,&tmp))==-1)
45 {
46 close(soundfd);
47 return(0);
48 }
49
50 sixteenbit=0;
51 }
52
53 tmp=(*stereoptr)?1:0;
54 if(ioctl(soundfd,SNDCTL_DSP_STEREO,&tmp)<0)
55 {
56 /* if it failed, make sure the opposite is ok */
57 tmp=(*stereoptr)?0:1;
58 if(ioctl(soundfd,SNDCTL_DSP_STEREO,&tmp)<0)
59 {
60 close(soundfd);
61 return(0);
62 }
63 *stereoptr=tmp;
64 }
65
66 frag=(0x40000|BASE_SOUND_FRAG_PWR);
67
68 if(ioctl(soundfd,SNDCTL_DSP_SPEED,freqptr)<0)
69 {
70 close(soundfd);
71 return(0);
72 }
73
74 if(*freqptr>8250) frag++;
75 if(*freqptr>16500) frag++;
76 if(*freqptr>33000) frag++;
77 if(*stereoptr) frag++;
78 if(sixteenbit) frag++;
79
80 if(ioctl(soundfd,SNDCTL_DSP_SETFRAGMENT,&frag)<0)
81 {
82 close(soundfd);
83 return(0);
84 }
85
86 return(1); /* success */
87 }
88
89
driver_end(void)90 void driver_end(void)
91 {
92 if(soundfd>1)
93 close(soundfd);
94 }
95
96
driver_frame(signed short * data,int len)97 void driver_frame(signed short *data,int len)
98 {
99 static unsigned char buf8[4096];
100 unsigned char *data8=(unsigned char *)data;
101 int ret=0,ofs=0;
102
103 len<<=1; /* now in bytes */
104
105 if(!sixteenbit)
106 {
107 signed short *src;
108 unsigned char *dst;
109 int f;
110
111 src=data; dst=buf8;
112 len>>=1;
113 for(f=0;f<len;f++)
114 *dst++=128+(int)((*src++)/256);
115
116 data8=buf8;
117 }
118
119 while(len)
120 {
121 ret=write(soundfd,data8+ofs,len);
122 if(ret>0)
123 ofs+=ret,len-=ret;
124 }
125 }
126
127 #endif /* DRIVER_OSS */
128