db: Override cycle multiplier for Colin McRae PAL
[pcsx_rearmed.git] / plugins / dfsound / oss.c
CommitLineData
ef79bbde
P
1/***************************************************************************
2 oss.c - description
3 -------------------
4 begin : Wed May 15 2002
5 copyright : (C) 2002 by Pete Bernert
6 email : BlackDove@addcom.de
7 ***************************************************************************/
8/***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. See also the license.txt file for *
14 * additional informations. *
15 * *
16 ***************************************************************************/
17
07c13dfd 18#include <stdio.h>
650adfd2 19#include <string.h>
07c13dfd 20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <sys/ioctl.h>
24#include <unistd.h>
25#include <sys/soundcard.h>
26#include "out.h"
ef79bbde
P
27
28////////////////////////////////////////////////////////////////////////
29// oss globals
30////////////////////////////////////////////////////////////////////////
31
32#define OSS_MODE_STEREO 1
33#define OSS_MODE_MONO 0
34
35#define OSS_SPEED_44100 44100
36
e541b8e0 37#define FRAGMENT_SHIFT 12
38#define FRAGMENT_SIZE (1 << FRAGMENT_SHIFT)
39
ef79bbde
P
40static int oss_audio_fd = -1;
41extern int errno;
42
43////////////////////////////////////////////////////////////////////////
44// SETUP SOUND
45////////////////////////////////////////////////////////////////////////
46
07c13dfd 47static int oss_init(void)
ef79bbde
P
48{
49 int pspeed=44100;
50 int pstereo;
51 int format;
ef79bbde
P
52 int myfrag;
53 int oss_speed, oss_stereo;
54
97ea4077 55 pstereo = OSS_MODE_STEREO;
ef79bbde
P
56 oss_speed = pspeed;
57 oss_stereo = pstereo;
58
59 if((oss_audio_fd=open("/dev/dsp",O_WRONLY,0))==-1)
60 {
07c13dfd 61 printf("OSS device not available\n");
62 return -1;
ef79bbde
P
63 }
64
65 if(ioctl(oss_audio_fd,SNDCTL_DSP_RESET,0)==-1)
66 {
67 printf("Sound reset failed\n");
07c13dfd 68 return -1;
ef79bbde
P
69 }
70
71 // we use 64 fragments with 1024 bytes each
17ed0d69 72 // rearmed: now using 10*4096 for better latency
ef79bbde 73
e541b8e0 74 myfrag = (10<<16) | FRAGMENT_SHIFT;
ef79bbde
P
75
76 if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFRAGMENT,&myfrag)==-1)
77 {
78 printf("Sound set fragment failed!\n");
07c13dfd 79 return -1;
ef79bbde
P
80 }
81
82 format = AFMT_S16_NE;
83
84 if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFMT,&format) == -1)
85 {
86 printf("Sound format not supported!\n");
07c13dfd 87 return -1;
ef79bbde
P
88 }
89
90 if(format!=AFMT_S16_NE)
91 {
92 printf("Sound format not supported!\n");
07c13dfd 93 return -1;
ef79bbde
P
94 }
95
97ea4077 96 if(ioctl(oss_audio_fd,SNDCTL_DSP_STEREO,&oss_stereo)==-1 || !oss_stereo)
ef79bbde
P
97 {
98 printf("Stereo mode not supported!\n");
07c13dfd 99 return -1;
ef79bbde
P
100 }
101
ef79bbde
P
102 if(ioctl(oss_audio_fd,SNDCTL_DSP_SPEED,&oss_speed)==-1)
103 {
104 printf("Sound frequency not supported\n");
07c13dfd 105 return -1;
ef79bbde
P
106 }
107
108 if(oss_speed!=pspeed)
109 {
110 printf("Sound frequency not supported\n");
07c13dfd 111 return -1;
ef79bbde 112 }
07c13dfd 113
114 return 0;
ef79bbde
P
115}
116
117////////////////////////////////////////////////////////////////////////
118// REMOVE SOUND
119////////////////////////////////////////////////////////////////////////
120
07c13dfd 121static void oss_finish(void)
ef79bbde
P
122{
123 if(oss_audio_fd != -1 )
124 {
125 close(oss_audio_fd);
126 oss_audio_fd = -1;
127 }
128}
129
130////////////////////////////////////////////////////////////////////////
07c13dfd 131// GET BUFFERED STATUS
ef79bbde
P
132////////////////////////////////////////////////////////////////////////
133
07c13dfd 134static int oss_busy(void)
ef79bbde
P
135{
136 audio_buf_info info;
137 unsigned long l;
138
f8edb5bc 139 if(oss_audio_fd == -1) return 1;
ef79bbde
P
140 if(ioctl(oss_audio_fd,SNDCTL_DSP_GETOSPACE,&info)==-1)
141 l=0;
142 else
143 {
144 if(info.fragments<(info.fragstotal>>1)) // can we write in at least the half of fragments?
f8edb5bc 145 l=1; // -> no? wait
ef79bbde
P
146 else l=0; // -> else go on
147 }
148
149 return l;
150}
151
152////////////////////////////////////////////////////////////////////////
153// FEED SOUND DATA
154////////////////////////////////////////////////////////////////////////
155
07c13dfd 156static void oss_feed(void *buf, int bytes)
ef79bbde 157{
650adfd2 158 audio_buf_info info;
159 char sbuf[4096];
160
ef79bbde 161 if(oss_audio_fd == -1) return;
650adfd2 162 if(ioctl(oss_audio_fd,SNDCTL_DSP_GETOSPACE,&info)==0)
163 {
e541b8e0 164 // for fast forward
165 if(bytes > info.fragments * FRAGMENT_SIZE)
166 bytes = info.fragments * FRAGMENT_SIZE;
167 if(bytes == 0)
168 return;
169
650adfd2 170 if(info.fragments==info.fragstotal)
171 {
172 memset(sbuf, 0, sizeof(sbuf));
173 write(oss_audio_fd, sbuf, sizeof(sbuf));
174 write(oss_audio_fd, sbuf, sizeof(sbuf));
e541b8e0 175 write(oss_audio_fd, sbuf, sizeof(sbuf));
650adfd2 176 }
177 }
178
07c13dfd 179 write(oss_audio_fd, buf, bytes);
180}
181
182void out_register_oss(struct out_driver *drv)
183{
184 drv->name = "oss";
185 drv->init = oss_init;
186 drv->finish = oss_finish;
187 drv->busy = oss_busy;
188 drv->feed = oss_feed;
ef79bbde 189}