summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/s_audio_oss.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/s_audio_oss.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/s_audio_oss.c843
1 files changed, 0 insertions, 843 deletions
diff --git a/apps/plugins/pdbox/PDa/src/s_audio_oss.c b/apps/plugins/pdbox/PDa/src/s_audio_oss.c
index efb15d1bc1..de11f66243 100644
--- a/apps/plugins/pdbox/PDa/src/s_audio_oss.c
+++ b/apps/plugins/pdbox/PDa/src/s_audio_oss.c
@@ -842,847 +842,4 @@ void oss_getdevs(char *indevlist, int *nindevs,
842} 842}
843 843
844#endif 844#endif
845/* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler,
846* Winfried Ritsch, Karl MacMillan, and others.
847* For information on usage and redistribution, and for a DISCLAIMER OF ALL
848* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
849
850/* this file inputs and outputs audio using the OSS API available on linux. */
851
852#ifdef USEAPI_OSS
853
854#include <linux/soundcard.h>
855
856#include "m_pd.h"
857#include "s_stuff.h"
858#include <errno.h>
859#include <stdio.h>
860#include <unistd.h>
861#include <stdlib.h>
862#include <string.h>
863#include <sys/types.h>
864#include <sys/time.h>
865#include <sys/stat.h>
866#include <sys/ioctl.h>
867#include <fcntl.h>
868#include <sched.h>
869#include <sys/mman.h>
870
871
872/* Defines */
873#define DEBUG(x) x
874#define DEBUG2(x) {x;}
875
876#define OSS_MAXCHPERDEV 32 /* max channels per OSS device */
877#define OSS_MAXDEV 4 /* maximum number of input or output devices */
878#define OSS_DEFFRAGSIZE 256 /* default log fragment size (frames) */
879#define OSS_DEFAUDIOBUF 40000 /* default audiobuffer, microseconds */
880#define OSS_DEFAULTCH 2
881#define RME_DEFAULTCH 8 /* need this even if RME undefined */
882typedef int16_t t_oss_int16;
883typedef int32_t t_oss_int32;
884#define OSS_MAXSAMPLEWIDTH sizeof(t_oss_int32)
885#define OSS_BYTESPERCHAN(width) (DEFDACBLKSIZE * (width))
886#define OSS_XFERSAMPS(chans) (DEFDACBLKSIZE* (chans))
887#define OSS_XFERSIZE(chans, width) (DEFDACBLKSIZE * (chans) * (width))
888
889/* GLOBALS */
890static int linux_meters; /* true if we're metering */
891static float linux_inmax; /* max input amplitude */
892static float linux_outmax; /* max output amplitude */
893static int linux_fragsize = 0; /* for block mode; block size (sample frames) */
894
895/* our device handles */
896
897typedef struct _oss_dev
898{
899 int d_fd;
900 unsigned int d_space; /* bytes available for writing/reading */
901 int d_bufsize; /* total buffer size in blocks for this device */
902 int d_dropcount; /* # of buffers to drop for resync (output only) */
903 unsigned int d_nchannels; /* number of channels for this device */
904 unsigned int d_bytespersamp; /* bytes per sample (2 for 16 bit, 4 for 32) */
905} t_oss_dev;
906
907static t_oss_dev linux_dacs[OSS_MAXDEV];
908static t_oss_dev linux_adcs[OSS_MAXDEV];
909static int linux_noutdevs = 0;
910static int linux_nindevs = 0;
911
912 /* exported variables */
913float sys_dacsr;
914t_sample *sys_soundout;
915t_sample *sys_soundin;
916
917 /* OSS-specific private variables */
918static int oss_blockmode = 1; /* flag to use "blockmode" */
919static int oss_32bit = 0; /* allow 23 bit transfers in OSS */
920static char ossdsp[] = "/dev/dsp%d";
921
922 /* don't assume we can turn all 31 bits when doing float-to-fix;
923 otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */
924#define FMAX 0x7ffff000
925#define CLIP32(x) (((x)>FMAX)?FMAX:((x) < -FMAX)?-FMAX:(x))
926
927
928/* ------------- private routines for all APIS ------------------- */
929
930static void linux_flush_all_underflows_to_zero(void)
931{
932/*
933 TODO: Implement similar thing for linux (GGeiger)
934
935 One day we will figure this out, I hope, because it
936 costs CPU time dearly on Intel - LT
937 */
938 /* union fpc_csr f;
939 f.fc_word = get_fpc_csr();
940 f.fc_struct.flush = 1;
941 set_fpc_csr(f.fc_word);
942 */
943}
944
945static int oss_ndev = 0;
946
947 /* find out how many OSS devices we have. Since this has to
948 open the devices to find out if they're there, we have
949 to be called before audio is actually started up. So we
950 cache the results, which in effect are the number of available
951 devices. */
952void oss_init(void)
953{
954 int fd, i;
955 static int countedthem = 0;
956 if (countedthem)
957 return;
958 for (i = 0; i < 10; i++)
959 {
960 char devname[100];
961 if (i == 0)
962 strcpy(devname, "/dev/dsp");
963 else sprintf(devname, "/dev/dsp%d", i);
964 if ( (fd = open(devname, O_WRONLY|O_NONBLOCK)) != -1)
965 {
966 oss_ndev++;
967 close(fd);
968 }
969 else break;
970 }
971 countedthem = 1;
972}
973
974
975void oss_set32bit( void)
976{
977 oss_32bit = 1;
978}
979
980
981typedef struct _multidev {
982 int fd;
983 int channels;
984 int format;
985} t_multidev;
986
987int oss_reset(int fd) {
988 int err;
989 if ((err = ioctl(fd,SNDCTL_DSP_RESET)) < 0)
990 error("OSS: Could not reset");
991 return err;
992}
993
994 /* The AFMT_S32_BLOCKED format is not defined in standard linux kernels
995 but is proposed by Guenter Geiger to support extending OSS to handle
996 32 bit sample. This is user in Geiger's OSS driver for RME Hammerfall.
997 I'm not clear why this isn't called AFMT_S32_[SLN]E... */
998
999#ifndef AFMT_S32_BLOCKED
1000#define AFMT_S32_BLOCKED 0x0000400
1001#endif
1002
1003void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize)
1004{ /* IOhannes */
1005 int orig, param, nblk, fd = dev->d_fd, wantformat;
1006 int nchannels = dev->d_nchannels;
1007 int advwas = sys_schedadvance;
1008
1009 audio_buf_info ainfo;
1010
1011 /* IOhannes :
1012 * pd is very likely to crash if different formats are used on
1013 multiple soundcards
1014 */
1015
1016 /* set resolution - first try 4 byte samples */
1017 if (oss_32bit && (ioctl(fd,SNDCTL_DSP_GETFMTS,&param) >= 0) &&
1018 (param & AFMT_S32_BLOCKED))
1019 {
1020 wantformat = AFMT_S32_BLOCKED;
1021 dev->d_bytespersamp = 4;
1022 }
1023 else
1024 {
1025 wantformat = AFMT_S16_NE;
1026 dev->d_bytespersamp = 2;
1027 }
1028 param = wantformat;
1029
1030 if (sys_verbose)
1031 post("bytes per sample = %d", dev->d_bytespersamp);
1032 if (ioctl(fd, SNDCTL_DSP_SETFMT, &param) == -1)
1033 fprintf(stderr,"OSS: Could not set DSP format\n");
1034 else if (wantformat != param)
1035 fprintf(stderr,"OSS: DSP format: wanted %d, got %d\n",
1036 wantformat, param);
1037
1038 /* sample rate */
1039 orig = param = srate;
1040 if (ioctl(fd, SNDCTL_DSP_SPEED, &param) == -1)
1041 fprintf(stderr,"OSS: Could not set sampling rate for device\n");
1042 else if( orig != param )
1043 fprintf(stderr,"OSS: sampling rate: wanted %d, got %d\n",
1044 orig, param );
1045
1046 if (oss_blockmode && !skipblocksize)
1047 {
1048 int fragbytes, logfragsize, nfragment;
1049 /* setting fragment count and size. */
1050 if (!linux_fragsize)
1051 {
1052 linux_fragsize = OSS_DEFFRAGSIZE;
1053 while (linux_fragsize > DEFDACBLKSIZE
1054 && linux_fragsize * 4 > sys_advance_samples)
1055 linux_fragsize = linux_fragsize/2;
1056 }
1057
1058 /* post("adv_samples %d", sys_advance_samples); */
1059 nfragment = (sys_schedadvance * (44100. * 1.e-6)) / linux_fragsize;
1060
1061 fragbytes = linux_fragsize * (dev->d_bytespersamp * nchannels);
1062 logfragsize = ilog2(fragbytes);
1063
1064 if (fragbytes != (1 << logfragsize))
1065 post("warning: OSS takes only power of 2 blocksize; using %d",
1066 (1 << logfragsize)/(dev->d_bytespersamp * nchannels));
1067 if (sys_verbose)
1068 post("setting nfrags = %d, fragsize %d\n", nfragment, fragbytes);
1069
1070 param = orig = (nfragment<<16) + logfragsize;
1071 if (ioctl(fd,SNDCTL_DSP_SETFRAGMENT, &param) == -1)
1072 error("OSS: Could not set or read fragment size\n");
1073 if (param != orig)
1074 {
1075 nfragment = ((param >> 16) & 0xffff);
1076 logfragsize = (param & 0xffff);
1077 post("warning: actual fragments %d, blocksize %d",
1078 nfragment, (1 << logfragsize));
1079 }
1080 if (sys_verbose)
1081 post("audiobuffer set to %d msec", (int)(0.001 * sys_schedadvance));
1082 }
1083 if (dac)
1084 {
1085 /* use "free space" to learn the buffer size. Normally you
1086 should set this to your own desired value; but this seems not
1087 to be implemented uniformly across different sound cards. LATER
1088 we should figure out what to do if the requested scheduler advance
1089 is greater than this buffer size; for now, we just print something
1090 out. */
1091
1092 int defect;
1093 if (ioctl(fd, SOUND_PCM_GETOSPACE,&ainfo) < 0)
1094 fprintf(stderr,"OSS: ioctl on output device failed");
1095 dev->d_bufsize = ainfo.bytes;
1096
1097 defect = sys_advance_samples * (dev->d_bytespersamp * nchannels)
1098 - dev->d_bufsize - OSS_XFERSIZE(nchannels, dev->d_bytespersamp);
1099 if (defect > 0)
1100 {
1101 if (sys_verbose || defect > (dev->d_bufsize >> 2))
1102 fprintf(stderr,
1103 "OSS: requested audio buffer size %d limited to %d\n",
1104 sys_advance_samples * (dev->d_bytespersamp * nchannels),
1105 dev->d_bufsize);
1106 sys_advance_samples =
1107 (dev->d_bufsize - OSS_XFERSAMPS(nchannels)) /
1108 (dev->d_bytespersamp *nchannels);
1109 }
1110 }
1111}
1112
1113static int oss_setchannels(int fd, int wantchannels, char *devname)
1114{ /* IOhannes */
1115 int param = wantchannels;
1116 845
1117 while (param>1) {
1118 int save = param;
1119 if (ioctl(fd, SNDCTL_DSP_CHANNELS, &param) == -1) {
1120 error("OSS: SNDCTL_DSP_CHANNELS failed %s",devname);
1121 } else {
1122 if (param == save) return (param);
1123 }
1124 param=save-1;
1125 }
1126
1127 return (0);
1128}
1129
1130#define O_AUDIOFLAG 0 /* O_NDELAY */
1131
1132int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
1133 int noutdev, int *outdev, int nchout, int *chout, int rate)
1134{ /* IOhannes */
1135 int capabilities = 0;
1136 int inchannels = 0, outchannels = 0;
1137 char devname[20];
1138 int n, i, fd;
1139 char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
1140 int num_devs = 0;
1141 int wantmore=0;
1142 int spread = 0;
1143 audio_buf_info ainfo;
1144
1145 linux_nindevs = linux_noutdevs = 0;
1146
1147
1148 /* mark input devices unopened */
1149 for (i = 0; i < OSS_MAXDEV; i++)
1150 linux_adcs[i].d_fd = -1;
1151
1152 /* open output devices */
1153 wantmore=0;
1154 if (noutdev < 0 || nindev < 0)
1155 bug("linux_open_audio");
1156
1157 for (n = 0; n < noutdev; n++)
1158 {
1159 int gotchans, j, inindex = -1;
1160 int thisdevice = (outdev[n] >= 0 ? outdev[n] : n-1);
1161 int wantchannels = (nchout>n) ? chout[n] : wantmore;
1162 fd = -1;
1163 if (!wantchannels)
1164 goto end_out_loop;
1165
1166 if (thisdevice > 1)
1167 sprintf(devname, "/dev/dsp%d", thisdevice-1);
1168 else sprintf(devname, "/dev/dsp");
1169
1170 /* search for input request for same device. Succeed only
1171 if the number of channels matches. */
1172 for (j = 0; j < nindev; j++)
1173 if (indev[j] == thisdevice && chin[j] == wantchannels)
1174 inindex = j;
1175
1176 /* if the same device is requested for input and output,
1177 try to open it read/write */
1178 if (inindex >= 0)
1179 {
1180 sys_setalarm(1000000);
1181 if ((fd = open(devname, O_RDWR | O_AUDIOFLAG)) == -1)
1182 {
1183 post("%s (read/write): %s", devname, strerror(errno));
1184 post("(now will try write-only...)");
1185 }
1186 else
1187 {
1188 if (sys_verbose)
1189 post("opened %s for reading and writing\n", devname);
1190 linux_adcs[inindex].d_fd = fd;
1191 }
1192 }
1193 /* if that didn't happen or if it failed, try write-only */
1194 if (fd == -1)
1195 {
1196 sys_setalarm(1000000);
1197 if ((fd = open(devname, O_WRONLY | O_AUDIOFLAG)) == -1)
1198 {
1199 post("%s (writeonly): %s",
1200 devname, strerror(errno));
1201 break;
1202 }
1203 if (sys_verbose)
1204 post("opened %s for writing only\n", devname);
1205 }
1206 if (ioctl(fd, SNDCTL_DSP_GETCAPS, &capabilities) == -1)
1207 error("OSS: SNDCTL_DSP_GETCAPS failed %s", devname);
1208
1209 gotchans = oss_setchannels(fd,
1210 (wantchannels>OSS_MAXCHPERDEV)?OSS_MAXCHPERDEV:wantchannels,
1211 devname);
1212
1213 if (sys_verbose)
1214 post("opened audio output on %s; got %d channels",
1215 devname, gotchans);
1216
1217 if (gotchans < 2)
1218 {
1219 /* can't even do stereo? just give up. */
1220 close(fd);
1221 }
1222 else
1223 {
1224 linux_dacs[linux_noutdevs].d_nchannels = gotchans;
1225 linux_dacs[linux_noutdevs].d_fd = fd;
1226 oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0);
1227
1228 linux_noutdevs++;
1229 outchannels += gotchans;
1230 if (inindex >= 0)
1231 {
1232 linux_adcs[inindex].d_nchannels = gotchans;
1233 chin[inindex] = gotchans;
1234 }
1235 }
1236 /* LATER think about spreading large numbers of channels over
1237 various dsp's and vice-versa */
1238 wantmore = wantchannels - gotchans;
1239 end_out_loop: ;
1240 }
1241
1242 /* open input devices */
1243 wantmore = 0;
1244 for (n = 0; n < nindev; n++)
1245 {
1246 int gotchans=0;
1247 int thisdevice = (indev[n] >= 0 ? indev[n] : n-1);
1248 int wantchannels = (nchin>n)?chin[n]:wantmore;
1249 int alreadyopened = 0;
1250 if (!wantchannels)
1251 goto end_in_loop;
1252
1253 if (thisdevice > 1)
1254 sprintf(devname, "/dev/dsp%d", thisdevice - 1);
1255 else sprintf(devname, "/dev/dsp");
1256
1257 sys_setalarm(1000000);
1258
1259 /* perhaps it's already open from the above? */
1260 if (linux_dacs[n].d_fd >= 0)
1261 {
1262 fd = linux_dacs[n].d_fd;
1263 alreadyopened = 1;
1264 }
1265 else
1266 {
1267 /* otherwise try to open it here. */
1268 if ((fd = open(devname, O_RDONLY | O_AUDIOFLAG)) == -1)
1269 {
1270 post("%s (readonly): %s", devname, strerror(errno));
1271 goto end_in_loop;
1272 }
1273 if (sys_verbose)
1274 post("opened %s for reading only\n", devname);
1275 }
1276 linux_adcs[linux_nindevs].d_fd = fd;
1277 gotchans = oss_setchannels(fd,
1278 (wantchannels>OSS_MAXCHPERDEV)?OSS_MAXCHPERDEV:wantchannels,
1279 devname);
1280 if (sys_verbose)
1281 post("opened audio input device %s; got %d channels",
1282 devname, gotchans);
1283
1284 if (gotchans < 1)
1285 {
1286 close(fd);
1287 goto end_in_loop;
1288 }
1289
1290 linux_adcs[linux_nindevs].d_nchannels = gotchans;
1291
1292 oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened);
1293
1294 inchannels += gotchans;
1295 linux_nindevs++;
1296
1297 wantmore = wantchannels-gotchans;
1298 /* LATER think about spreading large numbers of channels over
1299 various dsp's and vice-versa */
1300 end_in_loop: ;
1301 }
1302
1303 /* We have to do a read to start the engine. This is
1304 necessary because sys_send_dacs waits until the input
1305 buffer is filled and only reads on a filled buffer.
1306 This is good, because it's a way to make sure that we
1307 will not block. But I wonder why we only have to read
1308 from one of the devices and not all of them??? */
1309
1310 if (linux_nindevs)
1311 {
1312 if (sys_verbose)
1313 fprintf(stderr,("OSS: issuing first ADC 'read' ... "));
1314 read(linux_adcs[0].d_fd, buf,
1315 linux_adcs[0].d_bytespersamp *
1316 linux_adcs[0].d_nchannels * DEFDACBLKSIZE);
1317 if (sys_verbose)
1318 fprintf(stderr, "...done.\n");
1319 }
1320 sys_setalarm(0);
1321 return (0);
1322}
1323
1324void oss_close_audio( void)
1325{
1326 int i;
1327 for (i=0;i<linux_nindevs;i++)
1328 close(linux_adcs[i].d_fd);
1329
1330 for (i=0;i<linux_noutdevs;i++)
1331 close(linux_dacs[i].d_fd);
1332
1333 linux_nindevs = linux_noutdevs = 0;
1334}
1335
1336static int linux_dacs_write(int fd,void* buf,long bytes)
1337{
1338 return write(fd, buf, bytes);
1339}
1340
1341static int linux_adcs_read(int fd,void* buf,long bytes)
1342{
1343 return read(fd, buf, bytes);
1344}
1345
1346 /* query audio devices for "available" data size. */
1347static void oss_calcspace(void)
1348{
1349 int dev;
1350 audio_buf_info ainfo;
1351 for (dev=0; dev < linux_noutdevs; dev++)
1352 {
1353 if (ioctl(linux_dacs[dev].d_fd, SOUND_PCM_GETOSPACE, &ainfo) < 0)
1354 fprintf(stderr,"OSS: ioctl on output device %d failed",dev);
1355 linux_dacs[dev].d_space = ainfo.bytes;
1356 }
1357
1358 for (dev = 0; dev < linux_nindevs; dev++)
1359 {
1360 if (ioctl(linux_adcs[dev].d_fd, SOUND_PCM_GETISPACE,&ainfo) < 0)
1361 fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
1362 dev, linux_adcs[dev].d_fd);
1363 linux_adcs[dev].d_space = ainfo.bytes;
1364 }
1365}
1366
1367void linux_audiostatus(void)
1368{
1369 int dev;
1370 if (!oss_blockmode)
1371 {
1372 oss_calcspace();
1373 for (dev=0; dev < linux_noutdevs; dev++)
1374 fprintf(stderr, "dac %d space %d\n", dev, linux_dacs[dev].d_space);
1375
1376 for (dev = 0; dev < linux_nindevs; dev++)
1377 fprintf(stderr, "adc %d space %d\n", dev, linux_adcs[dev].d_space);
1378
1379 }
1380}
1381
1382/* this call resyncs audio output and input which will cause discontinuities
1383in audio output and/or input. */
1384
1385static void oss_doresync( void)
1386{
1387 int dev, zeroed = 0, wantsize;
1388 char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
1389 audio_buf_info ainfo;
1390
1391 /* 1. if any input devices are ahead (have more than 1 buffer stored),
1392 drop one or more buffers worth */
1393 for (dev = 0; dev < linux_nindevs; dev++)
1394 {
1395 if (linux_adcs[dev].d_space == 0)
1396 {
1397 linux_adcs_read(linux_adcs[dev].d_fd, buf,
1398 OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
1399 linux_adcs[dev].d_bytespersamp));
1400 }
1401 else while (linux_adcs[dev].d_space >
1402 OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
1403 linux_adcs[dev].d_bytespersamp))
1404 {
1405 linux_adcs_read(linux_adcs[dev].d_fd, buf,
1406 OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
1407 linux_adcs[dev].d_bytespersamp));
1408 if (ioctl(linux_adcs[dev].d_fd, SOUND_PCM_GETISPACE, &ainfo) < 0)
1409 {
1410 fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
1411 dev, linux_adcs[dev].d_fd);
1412 break;
1413 }
1414 linux_adcs[dev].d_space = ainfo.bytes;
1415 }
1416 }
1417
1418 /* 2. if any output devices are behind, feed them zeros to catch them
1419 up */
1420 for (dev = 0; dev < linux_noutdevs; dev++)
1421 {
1422 while (linux_dacs[dev].d_space > linux_dacs[dev].d_bufsize -
1423 sys_advance_samples * (linux_dacs[dev].d_nchannels *
1424 linux_dacs[dev].d_bytespersamp))
1425 {
1426 if (!zeroed)
1427 {
1428 unsigned int i;
1429 for (i = 0; i < OSS_XFERSAMPS(linux_dacs[dev].d_nchannels);
1430 i++)
1431 buf[i] = 0;
1432 zeroed = 1;
1433 }
1434 linux_dacs_write(linux_dacs[dev].d_fd, buf,
1435 OSS_XFERSIZE(linux_dacs[dev].d_nchannels,
1436 linux_dacs[dev].d_bytespersamp));
1437 if (ioctl(linux_dacs[dev].d_fd, SOUND_PCM_GETOSPACE, &ainfo) < 0)
1438 {
1439 fprintf(stderr, "OSS: ioctl on output device %d, fd %d failed",
1440 dev, linux_dacs[dev].d_fd);
1441 break;
1442 }
1443 linux_dacs[dev].d_space = ainfo.bytes;
1444 }
1445 }
1446 /* 3. if any DAC devices are too far ahead, plan to drop the
1447 number of frames which will let the others catch up. */
1448 for (dev = 0; dev < linux_noutdevs; dev++)
1449 {
1450 if (linux_dacs[dev].d_space > linux_dacs[dev].d_bufsize -
1451 (sys_advance_samples - 1) * linux_dacs[dev].d_nchannels *
1452 linux_dacs[dev].d_bytespersamp)
1453 {
1454 linux_dacs[dev].d_dropcount = sys_advance_samples - 1 -
1455 (linux_dacs[dev].d_space - linux_dacs[dev].d_bufsize) /
1456 (linux_dacs[dev].d_nchannels *
1457 linux_dacs[dev].d_bytespersamp) ;
1458 }
1459 else linux_dacs[dev].d_dropcount = 0;
1460 }
1461}
1462
1463int oss_send_dacs(void)
1464{
1465 t_sample *fp1, *fp2;
1466 long fill;
1467 int i, j, dev, rtnval = SENDDACS_YES;
1468 char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
1469 t_oss_int16 *sp;
1470 t_oss_int32 *lp;
1471 /* the maximum number of samples we should have in the ADC buffer */
1472 int idle = 0;
1473 int thischan;
1474 t_time timeref, timenow;
1475
1476 if (!linux_nindevs && !linux_noutdevs)
1477 return (SENDDACS_NO);
1478
1479 if (!oss_blockmode)
1480 {
1481 /* determine whether we're idle. This is true if either (1)
1482 some input device has less than one buffer to read or (2) some
1483 output device has fewer than (sys_advance_samples) blocks buffered
1484 already. */
1485 oss_calcspace();
1486
1487 for (dev=0; dev < linux_noutdevs; dev++)
1488 if (linux_dacs[dev].d_dropcount ||
1489 (linux_dacs[dev].d_bufsize - linux_dacs[dev].d_space >
1490 sys_advance_samples * linux_dacs[dev].d_bytespersamp *
1491 linux_dacs[dev].d_nchannels))
1492 idle = 1;
1493 for (dev=0; dev < linux_nindevs; dev++)
1494 if (linux_adcs[dev].d_space <
1495 OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
1496 linux_adcs[dev].d_bytespersamp))
1497 idle = 1;
1498 }
1499
1500 if (idle && !oss_blockmode)
1501 {
1502 /* sometimes---rarely---when the ADC available-byte-count is
1503 zero, it's genuine, but usually it's because we're so
1504 late that the ADC has overrun its entire kernel buffer. We
1505 distinguish between the two by waiting 2 msec and asking again.
1506 There should be an error flag we could check instead; look for this
1507 someday... */
1508 for (dev = 0;dev < linux_nindevs; dev++)
1509 if (linux_adcs[dev].d_space == 0)
1510 {
1511 audio_buf_info ainfo;
1512 sys_microsleep(2000);
1513 oss_calcspace();
1514 if (linux_adcs[dev].d_space != 0) continue;
1515
1516 /* here's the bad case. Give up and resync. */
1517 sys_log_error(ERR_DATALATE);
1518 oss_doresync();
1519 return (SENDDACS_NO);
1520 }
1521 /* check for slippage between devices, either because
1522 data got lost in the driver from a previous late condition, or
1523 because the devices aren't synced. When we're idle, no
1524 input device should have more than one buffer readable and
1525 no output device should have less than sys_advance_samples-1
1526 */
1527
1528 for (dev=0; dev < linux_noutdevs; dev++)
1529 if (!linux_dacs[dev].d_dropcount &&
1530 (linux_dacs[dev].d_bufsize - linux_dacs[dev].d_space <
1531 (sys_advance_samples - 2) *
1532 (linux_dacs[dev].d_bytespersamp *
1533 linux_dacs[dev].d_nchannels)))
1534 goto badsync;
1535 for (dev=0; dev < linux_nindevs; dev++)
1536 if (linux_adcs[dev].d_space > 3 *
1537 OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
1538 linux_adcs[dev].d_bytespersamp))
1539 goto badsync;
1540
1541 /* return zero to tell the scheduler we're idle. */
1542 return (SENDDACS_NO);
1543 badsync:
1544 sys_log_error(ERR_RESYNC);
1545 oss_doresync();
1546 return (SENDDACS_NO);
1547
1548 }
1549
1550
1551 /* do output */
1552
1553 timeref = sys_getrealtime();
1554 for (dev=0, thischan = 0; dev < linux_noutdevs; dev++)
1555 {
1556 int nchannels = linux_dacs[dev].d_nchannels;
1557 if (linux_dacs[dev].d_dropcount)
1558 linux_dacs[dev].d_dropcount--;
1559 else
1560 {
1561 if (linux_dacs[dev].d_bytespersamp == 4)
1562 {
1563 for (i = DEFDACBLKSIZE * nchannels, fp1 = sys_soundout +
1564 DEFDACBLKSIZE*thischan,
1565 lp = (t_oss_int32 *)buf; i--; fp1++, lp++)
1566 {
1567 t_sample f = SCALE32(*fp1);
1568 *lp = (f >= 2147483647 ? 2147483647 :
1569 (f < -2147483647 ? -2147483647 : f));
1570 }
1571 }
1572 else
1573 {
1574 for (i = DEFDACBLKSIZE, fp1 = sys_soundout +
1575 DEFDACBLKSIZE*thischan,
1576 sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels)
1577 {
1578 for (j=0, fp2 = fp1; j<nchannels; j++, fp2 += DEFDACBLKSIZE)
1579 {
1580 int s = SCALE16(*fp2);
1581 if (s > 32767) s = 32767;
1582 else if (s < -32767) s = -32767;
1583 sp[j] = s;
1584 }
1585 }
1586 }
1587
1588
1589#if 0
1590#define PR_S "%8d"
1591 {
1592 int nm = 64;
1593 int* sp1 = buf;
1594 post("dac:");
1595 while (nm > 0)
1596 {
1597 post(PR_S PR_S PR_S PR_S PR_S PR_S PR_S PR_S,
1598 sp1[0], sp1[1], sp1[2], sp1[3], sp1[4], sp1[5], sp1[6], sp1[7]);
1599 nm -= 8;
1600 sp1 += 8;
1601 }
1602 }
1603#endif
1604 linux_dacs_write(linux_dacs[dev].d_fd, buf,
1605 OSS_XFERSIZE(nchannels, linux_dacs[dev].d_bytespersamp));
1606
1607#if 0
1608 if ((timenow = sys_getrealtime()) - timeref > 200)
1609 {
1610 post("dacslept %d",sys_getrealtime() - timeref);
1611 if (!oss_blockmode)
1612 sys_log_error(ERR_DACSLEPT);
1613 else rtnval = SENDDACS_SLEPT;
1614 }
1615#endif
1616 timeref = timenow;
1617 }
1618 thischan += nchannels;
1619 }
1620 memset(sys_soundout, 0,
1621 sys_outchannels * (sizeof(float) * DEFDACBLKSIZE));
1622
1623 /* do input */
1624
1625 for (dev = 0, thischan = 0; dev < linux_nindevs; dev++)
1626 {
1627 int nchannels = linux_adcs[dev].d_nchannels;
1628 linux_adcs_read(linux_adcs[dev].d_fd, buf,
1629 OSS_XFERSIZE(nchannels, linux_adcs[dev].d_bytespersamp));
1630
1631#if 0
1632 if ((timenow = sys_getrealtime()) - timeref > 200)
1633 {
1634 if (!oss_blockmode)
1635 sys_log_error(ERR_ADCSLEPT);
1636 else
1637 rtnval = SENDDACS_SLEPT;
1638 }
1639#endif
1640 timeref = timenow;
1641
1642 if (linux_adcs[dev].d_bytespersamp == 4)
1643 {
1644 for (i = DEFDACBLKSIZE*nchannels,
1645 fp1 = sys_soundin + thischan*DEFDACBLKSIZE,
1646 lp = (t_oss_int32 *)buf; i--; fp1++, lp++)
1647 {
1648 *fp1 = ((t_sample)(*lp))*(t_sample)(1./2147483648.);
1649 }
1650 }
1651 else
1652 {
1653 for (i = DEFDACBLKSIZE,fp1 = sys_soundin + thischan*DEFDACBLKSIZE,
1654 sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels)
1655 {
1656 for (j=0;j<sys_inchannels;j++)
1657 fp1[j*DEFDACBLKSIZE] = INVSCALE16(sp[j]);
1658 }
1659 }
1660 thischan += nchannels;
1661 }
1662 if (thischan != sys_inchannels)
1663 bug("inchannels");
1664 return (rtnval);
1665}
1666
1667void oss_listdevs( void)
1668{
1669 post("device listing not implemented in OSS yet\n");
1670}
1671
1672void oss_getdevs(char *indevlist, int *nindevs,
1673 char *outdevlist, int *noutdevs, int *canmulti,
1674 int maxndev, int devdescsize)
1675{
1676 int i, ndev;
1677 *canmulti = 2; /* supports multiple devices */
1678 if ((ndev = oss_ndev) > maxndev)
1679 ndev = maxndev;
1680 for (i = 0; i < ndev; i++)
1681 {
1682 sprintf(indevlist + i * devdescsize, "OSS device #%d", i+1);
1683 sprintf(outdevlist + i * devdescsize, "OSS device #%d", i+1);
1684 }
1685 *nindevs = *noutdevs = ndev;
1686}
1687
1688#endif