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