summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/s_audio_mmio.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/s_audio_mmio.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/s_audio_mmio.c793
1 files changed, 0 insertions, 793 deletions
diff --git a/apps/plugins/pdbox/PDa/src/s_audio_mmio.c b/apps/plugins/pdbox/PDa/src/s_audio_mmio.c
index 44bbae855b..4a4a8f7354 100644
--- a/apps/plugins/pdbox/PDa/src/s_audio_mmio.c
+++ b/apps/plugins/pdbox/PDa/src/s_audio_mmio.c
@@ -792,797 +792,4 @@ void mmio_getdevs(char *indevlist, int *nindevs,
792 sprintf(outdevlist + i * devdescsize, (wRtn ? "???" : wocap.szPname)); 792 sprintf(outdevlist + i * devdescsize, (wRtn ? "???" : wocap.szPname));
793 } 793 }
794} 794}
795/* Copyright (c) 1997-1999 Miller Puckette.
796* For information on usage and redistribution, and for a DISCLAIMER OF ALL
797* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
798
799/* modified 2/98 by Winfried Ritsch to deal with up to 4 synchronized
800"wave" devices, which is how ADAT boards appear to the WAVE API. */
801
802#include "m_pd.h"
803#include "s_stuff.h"
804#include <stdio.h>
805
806#include <windows.h>
807
808#include <MMSYSTEM.H>
809
810/* ------------------------- audio -------------------------- */
811
812static void nt_close_midiin(void);
813static void nt_noresync( void);
814
815static void postflags(void);
816
817#define NAPORTS 16 /* wini hack for multiple ADDA devices */
818#define CHANNELS_PER_DEVICE 2
819#define DEFAULTCHANS 2
820#define DEFAULTSRATE 44100
821#define SAMPSIZE 2
822
823int nt_realdacblksize;
824#define DEFREALDACBLKSIZE (4 * DEFDACBLKSIZE) /* larger underlying bufsize */
825
826#define MAXBUFFER 100 /* number of buffers in use at maximum advance */
827#define DEFBUFFER 30 /* default is about 30x6 = 180 msec! */
828static int nt_naudiobuffer = DEFBUFFER;
829float sys_dacsr = DEFAULTSRATE;
830
831static int nt_whichapi = API_MMIO;
832static int nt_meters; /* true if we're metering */
833static float nt_inmax; /* max input amplitude */
834static float nt_outmax; /* max output amplitude */
835static int nt_nwavein, nt_nwaveout; /* number of WAVE devices in and out */
836
837typedef struct _sbuf
838{
839 HANDLE hData;
840 HPSTR lpData; // pointer to waveform data memory
841 HANDLE hWaveHdr;
842 WAVEHDR *lpWaveHdr; // pointer to header structure
843} t_sbuf;
844
845t_sbuf ntsnd_outvec[NAPORTS][MAXBUFFER]; /* circular buffer array */
846HWAVEOUT ntsnd_outdev[NAPORTS]; /* output device */
847static int ntsnd_outphase[NAPORTS]; /* index of next buffer to send */
848
849t_sbuf ntsnd_invec[NAPORTS][MAXBUFFER]; /* circular buffer array */
850HWAVEIN ntsnd_indev[NAPORTS]; /* input device */
851static int ntsnd_inphase[NAPORTS]; /* index of next buffer to read */
852
853static void nt_waveinerror(char *s, int err)
854{
855 char t[256];
856 waveInGetErrorText(err, t, 256);
857 fprintf(stderr, s, t);
858}
859
860static void nt_waveouterror(char *s, int err)
861{
862 char t[256];
863 waveOutGetErrorText(err, t, 256);
864 fprintf(stderr, s, t);
865}
866
867static void wave_prep(t_sbuf *bp, int setdone)
868{
869 WAVEHDR *wh;
870 short *sp;
871 int i;
872 /*
873 * Allocate and lock memory for the waveform data. The memory
874 * for waveform data must be globally allocated with
875 * GMEM_MOVEABLE and GMEM_SHARE flags.
876 */
877
878 if (!(bp->hData =
879 GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
880 (DWORD) (CHANNELS_PER_DEVICE * SAMPSIZE * nt_realdacblksize))))
881 printf("alloc 1 failed\n");
882
883 if (!(bp->lpData =
884 (HPSTR) GlobalLock(bp->hData)))
885 printf("lock 1 failed\n");
886
887 /* Allocate and lock memory for the header. */
888
889 if (!(bp->hWaveHdr =
890 GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (DWORD) sizeof(WAVEHDR))))
891 printf("alloc 2 failed\n");
892
893 if (!(wh = bp->lpWaveHdr =
894 (WAVEHDR *) GlobalLock(bp->hWaveHdr)))
895 printf("lock 2 failed\n");
896
897 for (i = CHANNELS_PER_DEVICE * nt_realdacblksize,
898 sp = (short *)bp->lpData; i--; )
899 *sp++ = 0;
900
901 wh->lpData = bp->lpData;
902 wh->dwBufferLength = (CHANNELS_PER_DEVICE * SAMPSIZE * nt_realdacblksize);
903 wh->dwFlags = 0;
904 wh->dwLoops = 0L;
905 wh->lpNext = 0;
906 wh->reserved = 0;
907 /* optionally (for writing) set DONE flag as if we had queued them */
908 if (setdone)
909 wh->dwFlags = WHDR_DONE;
910}
911
912static UINT nt_whichdac = WAVE_MAPPER, nt_whichadc = WAVE_MAPPER;
913
914int mmio_do_open_audio(void)
915{
916 PCMWAVEFORMAT form;
917 int i, j;
918 UINT mmresult;
919 int nad, nda;
920 static int naudioprepped = 0, nindevsprepped = 0, noutdevsprepped = 0;
921 if (sys_verbose)
922 post("%d devices in, %d devices out",
923 nt_nwavein, nt_nwaveout);
924
925 form.wf.wFormatTag = WAVE_FORMAT_PCM;
926 form.wf.nChannels = CHANNELS_PER_DEVICE;
927 form.wf.nSamplesPerSec = sys_dacsr;
928 form.wf.nAvgBytesPerSec = sys_dacsr * (CHANNELS_PER_DEVICE * SAMPSIZE);
929 form.wf.nBlockAlign = CHANNELS_PER_DEVICE * SAMPSIZE;
930 form.wBitsPerSample = 8 * SAMPSIZE;
931
932 if (nt_nwavein <= 1 && nt_nwaveout <= 1)
933 nt_noresync();
934
935 if (nindevsprepped < nt_nwavein)
936 {
937 for (i = nindevsprepped; i < nt_nwavein; i++)
938 for (j = 0; j < naudioprepped; j++)
939 wave_prep(&ntsnd_invec[i][j], 0);
940 nindevsprepped = nt_nwavein;
941 }
942 if (noutdevsprepped < nt_nwaveout)
943 {
944 for (i = noutdevsprepped; i < nt_nwaveout; i++)
945 for (j = 0; j < naudioprepped; j++)
946 wave_prep(&ntsnd_outvec[i][j], 1);
947 noutdevsprepped = nt_nwaveout;
948 }
949 if (naudioprepped < nt_naudiobuffer)
950 {
951 for (j = naudioprepped; j < nt_naudiobuffer; j++)
952 {
953 for (i = 0; i < nt_nwavein; i++)
954 wave_prep(&ntsnd_invec[i][j], 0);
955 for (i = 0; i < nt_nwaveout; i++)
956 wave_prep(&ntsnd_outvec[i][j], 1);
957 }
958 naudioprepped = nt_naudiobuffer;
959 }
960 for (nad=0; nad < nt_nwavein; nad++)
961 {
962 /* Open waveform device(s), sucessively numbered, for input */
963
964 mmresult = waveInOpen(&ntsnd_indev[nad], nt_whichadc+nad,
965 (WAVEFORMATEX *)(&form), 0L, 0L, CALLBACK_NULL);
966
967 if (sys_verbose)
968 printf("opened adc device %d with return %d\n",
969 nt_whichadc+nad,mmresult);
970
971 if (mmresult != MMSYSERR_NOERROR)
972 {
973 nt_waveinerror("waveInOpen: %s\n", mmresult);
974 nt_nwavein = nad; /* nt_nwavein = 0 wini */
975 }
976 else
977 {
978 for (i = 0; i < nt_naudiobuffer; i++)
979 {
980 mmresult = waveInPrepareHeader(ntsnd_indev[nad],
981 ntsnd_invec[nad][i].lpWaveHdr, sizeof(WAVEHDR));
982 if (mmresult != MMSYSERR_NOERROR)
983 nt_waveinerror("waveinprepareheader: %s\n", mmresult);
984 mmresult = waveInAddBuffer(ntsnd_indev[nad],
985 ntsnd_invec[nad][i].lpWaveHdr, sizeof(WAVEHDR));
986 if (mmresult != MMSYSERR_NOERROR)
987 nt_waveinerror("waveInAddBuffer: %s\n", mmresult);
988 }
989 }
990 }
991 /* quickly start them all together */
992 for (nad = 0; nad < nt_nwavein; nad++)
993 waveInStart(ntsnd_indev[nad]);
994
995 for (nda = 0; nda < nt_nwaveout; nda++)
996 {
997 /* Open a waveform device for output in sucessiv device numbering*/
998 mmresult = waveOutOpen(&ntsnd_outdev[nda], nt_whichdac + nda,
999 (WAVEFORMATEX *)(&form), 0L, 0L, CALLBACK_NULL);
1000
1001 if (sys_verbose)
1002 fprintf(stderr,"opened dac device %d, with return %d\n",
1003 nt_whichdac +nda, mmresult);
1004
1005 if (mmresult != MMSYSERR_NOERROR)
1006 {
1007 fprintf(stderr,"Wave out open device %d + %d\n",nt_whichdac,nda);
1008 nt_waveouterror("waveOutOpen device: %s\n", mmresult);
1009 nt_nwaveout = nda;
1010 }
1011 }
1012
1013 return (0);
1014}
1015
1016void mmio_close_audio( void)
1017{
1018 int errcode;
1019 int nda, nad;
1020 if (sys_verbose)
1021 post("closing audio...");
1022
1023 for (nda=0; nda < nt_nwaveout; nda++) /*if (nt_nwaveout) wini */
1024 {
1025 errcode = waveOutReset(ntsnd_outdev[nda]);
1026 if (errcode != MMSYSERR_NOERROR)
1027 printf("error resetting output %d: %d\n", nda, errcode);
1028 errcode = waveOutClose(ntsnd_outdev[nda]);
1029 if (errcode != MMSYSERR_NOERROR)
1030 printf("error closing output %d: %d\n",nda , errcode);
1031 }
1032 nt_nwaveout = 0;
1033
1034 for(nad=0; nad < nt_nwavein;nad++) /* if (nt_nwavein) wini */
1035 {
1036 errcode = waveInReset(ntsnd_indev[nad]);
1037 if (errcode != MMSYSERR_NOERROR)
1038 printf("error resetting input: %d\n", errcode);
1039 errcode = waveInClose(ntsnd_indev[nad]);
1040 if (errcode != MMSYSERR_NOERROR)
1041 printf("error closing input: %d\n", errcode);
1042 }
1043 nt_nwavein = 0;
1044}
1045
1046
1047#define ADCJITTER 10 /* We tolerate X buffers of jitter by default */
1048#define DACJITTER 10
1049
1050static int nt_adcjitterbufsallowed = ADCJITTER;
1051static int nt_dacjitterbufsallowed = DACJITTER;
1052
1053 /* ------------- MIDI time stamping from audio clock ------------ */
1054
1055#ifdef MIDI_TIMESTAMP
1056
1057static double nt_hibuftime;
1058static double initsystime = -1;
1059
1060 /* call this whenever we reset audio */
1061static void nt_resetmidisync(void)
1062{
1063 initsystime = clock_getsystime();
1064 nt_hibuftime = sys_getrealtime();
1065}
1066
1067 /* call this whenever we're idled waiting for audio to be ready.
1068 The routine maintains a high and low water point for the difference
1069 between real and DAC time. */
1070
1071static void nt_midisync(void)
1072{
1073 double jittersec, diff;
1074
1075 if (initsystime == -1) nt_resetmidisync();
1076 jittersec = (nt_dacjitterbufsallowed > nt_adcjitterbufsallowed ?
1077 nt_dacjitterbufsallowed : nt_adcjitterbufsallowed)
1078 * nt_realdacblksize / sys_getsr();
1079 diff = sys_getrealtime() - 0.001 * clock_gettimesince(initsystime);
1080 if (diff > nt_hibuftime) nt_hibuftime = diff;
1081 if (diff < nt_hibuftime - jittersec)
1082 {
1083 post("jitter excess %d %f", dac, diff);
1084 nt_resetmidisync();
1085 }
1086}
1087
1088static double nt_midigettimefor(LARGE_INTEGER timestamp)
1089{
1090 /* this is broken now... used to work when "timestamp" was derived from
1091 QueryPerformanceCounter() instead of the gates approved
1092 timeGetSystemTime() call in the MIDI callback routine below. */
1093 return (nt_tixtotime(timestamp) - nt_hibuftime);
1094}
1095#endif /* MIDI_TIMESTAMP */
1096
1097
1098static int nt_fill = 0;
1099#define WRAPFWD(x) ((x) >= nt_naudiobuffer ? (x) - nt_naudiobuffer: (x))
1100#define WRAPBACK(x) ((x) < 0 ? (x) + nt_naudiobuffer: (x))
1101#define MAXRESYNC 500
1102
1103#if 0 /* this is used for debugging */
1104static void nt_printaudiostatus(void)
1105{
1106 int nad, nda;
1107 for (nad = 0; nad < nt_nwavein; nad++)
1108 {
1109 int phase = ntsnd_inphase[nad];
1110 int phase2 = phase, phase3 = WRAPFWD(phase2), count, ntrans = 0;
1111 int firstphasedone = -1, firstphasebusy = -1;
1112 for (count = 0; count < nt_naudiobuffer; count++)
1113 {
1114 int donethis =
1115 (ntsnd_invec[nad][phase2].lpWaveHdr->dwFlags & WHDR_DONE);
1116 int donenext =
1117 (ntsnd_invec[nad][phase3].lpWaveHdr->dwFlags & WHDR_DONE);
1118 if (donethis && !donenext)
1119 {
1120 if (firstphasebusy >= 0) goto multipleadc;
1121 firstphasebusy = count;
1122 }
1123 if (!donethis && donenext)
1124 {
1125 if (firstphasedone >= 0) goto multipleadc;
1126 firstphasedone = count;
1127 }
1128 phase2 = phase3;
1129 phase3 = WRAPFWD(phase2 + 1);
1130 }
1131 post("nad %d phase %d busy %d done %d", nad, phase, firstphasebusy,
1132 firstphasedone);
1133 continue;
1134 multipleadc:
1135 startpost("nad %d phase %d: oops:", nad, phase);
1136 for (count = 0; count < nt_naudiobuffer; count++)
1137 {
1138 char buf[80];
1139 sprintf(buf, " %d",
1140 (ntsnd_invec[nad][count].lpWaveHdr->dwFlags & WHDR_DONE));
1141 poststring(buf);
1142 }
1143 endpost();
1144 }
1145 for (nda = 0; nda < nt_nwaveout; nda++)
1146 {
1147 int phase = ntsnd_outphase[nad];
1148 int phase2 = phase, phase3 = WRAPFWD(phase2), count, ntrans = 0;
1149 int firstphasedone = -1, firstphasebusy = -1;
1150 for (count = 0; count < nt_naudiobuffer; count++)
1151 {
1152 int donethis =
1153 (ntsnd_outvec[nda][phase2].lpWaveHdr->dwFlags & WHDR_DONE);
1154 int donenext =
1155 (ntsnd_outvec[nda][phase3].lpWaveHdr->dwFlags & WHDR_DONE);
1156 if (donethis && !donenext)
1157 {
1158 if (firstphasebusy >= 0) goto multipledac;
1159 firstphasebusy = count;
1160 }
1161 if (!donethis && donenext)
1162 {
1163 if (firstphasedone >= 0) goto multipledac;
1164 firstphasedone = count;
1165 }
1166 phase2 = phase3;
1167 phase3 = WRAPFWD(phase2 + 1);
1168 }
1169 if (firstphasebusy < 0) post("nda %d phase %d all %d",
1170 nda, phase, (ntsnd_outvec[nad][0].lpWaveHdr->dwFlags & WHDR_DONE));
1171 else post("nda %d phase %d busy %d done %d", nda, phase, firstphasebusy,
1172 firstphasedone);
1173 continue;
1174 multipledac:
1175 startpost("nda %d phase %d: oops:", nda, phase);
1176 for (count = 0; count < nt_naudiobuffer; count++)
1177 {
1178 char buf[80];
1179 sprintf(buf, " %d",
1180 (ntsnd_outvec[nad][count].lpWaveHdr->dwFlags & WHDR_DONE));
1181 poststring(buf);
1182 }
1183 endpost();
1184 }
1185}
1186#endif /* 0 */
1187
1188/* this is a hack to avoid ever resyncing audio pointers in case for whatever
1189reason the sync testing below gives false positives. */
1190
1191static int nt_resync_cancelled;
1192 795
1193static void nt_noresync( void)
1194{
1195 nt_resync_cancelled = 1;
1196}
1197
1198static void nt_resyncaudio(void)
1199{
1200 UINT mmresult;
1201 int nad, nda, count;
1202 if (nt_resync_cancelled)
1203 return;
1204 /* for each open input device, eat all buffers which are marked
1205 ready. The next one will thus be "busy". */
1206 post("resyncing audio");
1207 for (nad = 0; nad < nt_nwavein; nad++)
1208 {
1209 int phase = ntsnd_inphase[nad];
1210 for (count = 0; count < MAXRESYNC; count++)
1211 {
1212 WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
1213 if (!(inwavehdr->dwFlags & WHDR_DONE)) break;
1214 if (inwavehdr->dwFlags & WHDR_PREPARED)
1215 waveInUnprepareHeader(ntsnd_indev[nad],
1216 inwavehdr, sizeof(WAVEHDR));
1217 inwavehdr->dwFlags = 0L;
1218 waveInPrepareHeader(ntsnd_indev[nad], inwavehdr, sizeof(WAVEHDR));
1219 mmresult = waveInAddBuffer(ntsnd_indev[nad], inwavehdr,
1220 sizeof(WAVEHDR));
1221 if (mmresult != MMSYSERR_NOERROR)
1222 nt_waveinerror("waveInAddBuffer: %s\n", mmresult);
1223 ntsnd_inphase[nad] = phase = WRAPFWD(phase + 1);
1224 }
1225 if (count == MAXRESYNC) post("resync error 1");
1226 }
1227 /* Each output buffer which is "ready" is filled with zeros and
1228 queued. */
1229 for (nda = 0; nda < nt_nwaveout; nda++)
1230 {
1231 int phase = ntsnd_outphase[nda];
1232 for (count = 0; count < MAXRESYNC; count++)
1233 {
1234 WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
1235 if (!(outwavehdr->dwFlags & WHDR_DONE)) break;
1236 if (outwavehdr->dwFlags & WHDR_PREPARED)
1237 waveOutUnprepareHeader(ntsnd_outdev[nda],
1238 outwavehdr, sizeof(WAVEHDR));
1239 outwavehdr->dwFlags = 0L;
1240 memset((char *)(ntsnd_outvec[nda][phase].lpData),
1241 0, (CHANNELS_PER_DEVICE * SAMPSIZE * nt_realdacblksize));
1242 waveOutPrepareHeader(ntsnd_outdev[nda], outwavehdr,
1243 sizeof(WAVEHDR));
1244 mmresult = waveOutWrite(ntsnd_outdev[nda], outwavehdr,
1245 sizeof(WAVEHDR));
1246 if (mmresult != MMSYSERR_NOERROR)
1247 nt_waveouterror("waveOutAddBuffer: %s\n", mmresult);
1248 ntsnd_outphase[nda] = phase = WRAPFWD(phase + 1);
1249 }
1250 if (count == MAXRESYNC) post("resync error 2");
1251 }
1252
1253#ifdef MIDI_TIMESTAMP
1254 nt_resetmidisync();
1255#endif
1256
1257}
1258
1259#define LATE 0
1260#define RESYNC 1
1261#define NOTHING 2
1262static int nt_errorcount;
1263static int nt_resynccount;
1264static double nt_nextreporttime = -1;
1265
1266void nt_logerror(int which)
1267{
1268#if 0
1269 post("error %d %d", count, which);
1270 if (which < NOTHING) nt_errorcount++;
1271 if (which == RESYNC) nt_resynccount++;
1272 if (sys_getrealtime() > nt_nextreporttime)
1273 {
1274 post("%d audio I/O error%s", nt_errorcount,
1275 (nt_errorcount > 1 ? "s" : ""));
1276 if (nt_resynccount) post("DAC/ADC sync error");
1277 nt_errorcount = nt_resynccount = 0;
1278 nt_nextreporttime = sys_getrealtime() - 5;
1279 }
1280#endif
1281}
1282
1283/* system buffer with t_sample types for one tick */
1284t_sample *sys_soundout;
1285t_sample *sys_soundin;
1286float sys_dacsr;
1287
1288int mmio_send_dacs(void)
1289{
1290 HMMIO hmmio;
1291 UINT mmresult;
1292 HANDLE hFormat;
1293 int i, j;
1294 short *sp1, *sp2;
1295 float *fp1, *fp2;
1296 int nextfill, doxfer = 0;
1297 int nda, nad;
1298 if (!nt_nwavein && !nt_nwaveout) return (0);
1299
1300
1301 if (nt_meters)
1302 {
1303 int i, n;
1304 float maxsamp;
1305 for (i = 0, n = 2 * nt_nwavein * DEFDACBLKSIZE, maxsamp = nt_inmax;
1306 i < n; i++)
1307 {
1308 float f = sys_soundin[i];
1309 if (f > maxsamp) maxsamp = f;
1310 else if (-f > maxsamp) maxsamp = -f;
1311 }
1312 nt_inmax = maxsamp;
1313 for (i = 0, n = 2 * nt_nwaveout * DEFDACBLKSIZE, maxsamp = nt_outmax;
1314 i < n; i++)
1315 {
1316 float f = sys_soundout[i];
1317 if (f > maxsamp) maxsamp = f;
1318 else if (-f > maxsamp) maxsamp = -f;
1319 }
1320 nt_outmax = maxsamp;
1321 }
1322
1323 /* the "fill pointer" nt_fill controls where in the next
1324 I/O buffers we will write and/or read. If it's zero, we
1325 first check whether the buffers are marked "done". */
1326
1327 if (!nt_fill)
1328 {
1329 for (nad = 0; nad < nt_nwavein; nad++)
1330 {
1331 int phase = ntsnd_inphase[nad];
1332 WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
1333 if (!(inwavehdr->dwFlags & WHDR_DONE)) goto idle;
1334 }
1335 for (nda = 0; nda < nt_nwaveout; nda++)
1336 {
1337 int phase = ntsnd_outphase[nda];
1338 WAVEHDR *outwavehdr =
1339 ntsnd_outvec[nda][phase].lpWaveHdr;
1340 if (!(outwavehdr->dwFlags & WHDR_DONE)) goto idle;
1341 }
1342 for (nad = 0; nad < nt_nwavein; nad++)
1343 {
1344 int phase = ntsnd_inphase[nad];
1345 WAVEHDR *inwavehdr =
1346 ntsnd_invec[nad][phase].lpWaveHdr;
1347 if (inwavehdr->dwFlags & WHDR_PREPARED)
1348 waveInUnprepareHeader(ntsnd_indev[nad],
1349 inwavehdr, sizeof(WAVEHDR));
1350 }
1351 for (nda = 0; nda < nt_nwaveout; nda++)
1352 {
1353 int phase = ntsnd_outphase[nda];
1354 WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
1355 if (outwavehdr->dwFlags & WHDR_PREPARED)
1356 waveOutUnprepareHeader(ntsnd_outdev[nda],
1357 outwavehdr, sizeof(WAVEHDR));
1358 }
1359 }
1360
1361 /* Convert audio output to fixed-point and put it in the output
1362 buffer. */
1363 for (nda = 0, fp1 = sys_soundout; nda < nt_nwaveout; nda++)
1364 {
1365 int phase = ntsnd_outphase[nda];
1366
1367 for (i = 0, sp1 = (short *)(ntsnd_outvec[nda][phase].lpData) +
1368 CHANNELS_PER_DEVICE * nt_fill;
1369 i < 2; i++, fp1 += DEFDACBLKSIZE, sp1++)
1370 {
1371 for (j = 0, fp2 = fp1, sp2 = sp1; j < DEFDACBLKSIZE;
1372 j++, fp2++, sp2 += CHANNELS_PER_DEVICE)
1373 {
1374 int x1 = 32767.f * *fp2;
1375 if (x1 > 32767) x1 = 32767;
1376 else if (x1 < -32767) x1 = -32767;
1377 *sp2 = x1;
1378 }
1379 }
1380 }
1381 memset(sys_soundout, 0,
1382 (DEFDACBLKSIZE *sizeof(t_sample)*CHANNELS_PER_DEVICE)*nt_nwaveout);
1383
1384 /* vice versa for the input buffer */
1385
1386 for (nad = 0, fp1 = sys_soundin; nad < nt_nwavein; nad++)
1387 {
1388 int phase = ntsnd_inphase[nad];
1389
1390 for (i = 0, sp1 = (short *)(ntsnd_invec[nad][phase].lpData) +
1391 CHANNELS_PER_DEVICE * nt_fill;
1392 i < 2; i++, fp1 += DEFDACBLKSIZE, sp1++)
1393 {
1394 for (j = 0, fp2 = fp1, sp2 = sp1; j < DEFDACBLKSIZE;
1395 j++, fp2++, sp2 += CHANNELS_PER_DEVICE)
1396 {
1397 *fp2 = ((float)(1./32767.)) * (float)(*sp2);
1398 }
1399 }
1400 }
1401
1402 nt_fill = nt_fill + DEFDACBLKSIZE;
1403 if (nt_fill == nt_realdacblksize)
1404 {
1405 nt_fill = 0;
1406
1407 for (nad = 0; nad < nt_nwavein; nad++)
1408 {
1409 int phase = ntsnd_inphase[nad];
1410 HWAVEIN device = ntsnd_indev[nad];
1411 WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
1412 waveInPrepareHeader(device, inwavehdr, sizeof(WAVEHDR));
1413 mmresult = waveInAddBuffer(device, inwavehdr, sizeof(WAVEHDR));
1414 if (mmresult != MMSYSERR_NOERROR)
1415 nt_waveinerror("waveInAddBuffer: %s\n", mmresult);
1416 ntsnd_inphase[nad] = WRAPFWD(phase + 1);
1417 }
1418 for (nda = 0; nda < nt_nwaveout; nda++)
1419 {
1420 int phase = ntsnd_outphase[nda];
1421 HWAVEOUT device = ntsnd_outdev[nda];
1422 WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
1423 waveOutPrepareHeader(device, outwavehdr, sizeof(WAVEHDR));
1424 mmresult = waveOutWrite(device, outwavehdr, sizeof(WAVEHDR));
1425 if (mmresult != MMSYSERR_NOERROR)
1426 nt_waveouterror("waveOutWrite: %s\n", mmresult);
1427 ntsnd_outphase[nda] = WRAPFWD(phase + 1);
1428 }
1429
1430 /* check for DAC underflow or ADC overflow. */
1431 for (nad = 0; nad < nt_nwavein; nad++)
1432 {
1433 int phase = WRAPBACK(ntsnd_inphase[nad] - 2);
1434 WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
1435 if (inwavehdr->dwFlags & WHDR_DONE) goto late;
1436 }
1437 for (nda = 0; nda < nt_nwaveout; nda++)
1438 {
1439 int phase = WRAPBACK(ntsnd_outphase[nda] - 2);
1440 WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
1441 if (outwavehdr->dwFlags & WHDR_DONE) goto late;
1442 }
1443 }
1444 return (1);
1445
1446late:
1447
1448 nt_logerror(LATE);
1449 nt_resyncaudio();
1450 return (1);
1451
1452idle:
1453
1454 /* If more than nt_adcjitterbufsallowed ADC buffers are ready
1455 on any input device, resynchronize */
1456
1457 for (nad = 0; nad < nt_nwavein; nad++)
1458 {
1459 int phase = ntsnd_inphase[nad];
1460 WAVEHDR *inwavehdr =
1461 ntsnd_invec[nad]
1462 [WRAPFWD(phase + nt_adcjitterbufsallowed)].lpWaveHdr;
1463 if (inwavehdr->dwFlags & WHDR_DONE)
1464 {
1465 nt_resyncaudio();
1466 return (0);
1467 }
1468 }
1469
1470 /* test dac sync the same way */
1471 for (nda = 0; nda < nt_nwaveout; nda++)
1472 {
1473 int phase = ntsnd_outphase[nda];
1474 WAVEHDR *outwavehdr =
1475 ntsnd_outvec[nda]
1476 [WRAPFWD(phase + nt_dacjitterbufsallowed)].lpWaveHdr;
1477 if (outwavehdr->dwFlags & WHDR_DONE)
1478 {
1479 nt_resyncaudio();
1480 return (0);
1481 }
1482 }
1483#ifdef MIDI_TIMESTAMP
1484 nt_midisync();
1485#endif
1486 return (0);
1487}
1488
1489/* ------------------- public routines -------------------------- */
1490
1491void mmio_open_audio(int naudioindev, int *audioindev,
1492 int nchindev, int *chindev, int naudiooutdev, int *audiooutdev,
1493 int nchoutdev, int *choutdev, int rate) /* IOhannes */
1494{
1495 int nbuf;
1496
1497 nt_realdacblksize = (sys_blocksize ? sys_blocksize : DEFREALDACBLKSIZE);
1498 nbuf = sys_advance_samples/nt_realdacblksize;
1499 if (nbuf >= MAXBUFFER)
1500 {
1501 fprintf(stderr, "pd: audio buffering maxed out to %d\n",
1502 (int)(MAXBUFFER * ((nt_realdacblksize * 1000.)/44100.)));
1503 nbuf = MAXBUFFER;
1504 }
1505 else if (nbuf < 4) nbuf = 4;
1506 fprintf(stderr, "%d audio buffers\n", nbuf);
1507 nt_naudiobuffer = nbuf;
1508 if (nt_adcjitterbufsallowed > nbuf - 2)
1509 nt_adcjitterbufsallowed = nbuf - 2;
1510 if (nt_dacjitterbufsallowed > nbuf - 2)
1511 nt_dacjitterbufsallowed = nbuf - 2;
1512
1513 nt_nwavein = sys_inchannels / 2;
1514 nt_nwaveout = sys_outchannels / 2;
1515 nt_whichadc = (naudioindev < 1 ?
1516 (nt_nwavein > 1 ? WAVE_MAPPER : -1) : audioindev[0]);
1517 nt_whichdac = (naudiooutdev < 1 ?
1518 (nt_nwaveout > 1 ? WAVE_MAPPER : -1) : audiooutdev[0]);
1519 if (naudiooutdev > 1 || naudioindev > 1)
1520 post("separate audio device choice not supported; using sequential devices.");
1521 mmio_do_open_audio();
1522}
1523
1524
1525void mmio_reportidle(void)
1526{
1527}
1528
1529#if 0
1530/* list the audio and MIDI device names */
1531void mmio_listdevs(void)
1532{
1533 UINT wRtn, ndevices;
1534 unsigned int i;
1535
1536 ndevices = waveInGetNumDevs();
1537 for (i = 0; i < ndevices; i++)
1538 {
1539 WAVEINCAPS wicap;
1540 wRtn = waveInGetDevCaps(i, (LPWAVEINCAPS) &wicap,
1541 sizeof(wicap));
1542 if (wRtn) nt_waveinerror("waveInGetDevCaps: %s\n", wRtn);
1543 else fprintf(stderr,
1544 "audio input device #%d: %s\n", i+1, wicap.szPname);
1545 }
1546
1547 ndevices = waveOutGetNumDevs();
1548 for (i = 0; i < ndevices; i++)
1549 {
1550 WAVEOUTCAPS wocap;
1551 wRtn = waveOutGetDevCaps(i, (LPWAVEOUTCAPS) &wocap,
1552 sizeof(wocap));
1553 if (wRtn) nt_waveouterror("waveOutGetDevCaps: %s\n", wRtn);
1554 else fprintf(stderr,
1555 "audio output device #%d: %s\n", i+1, wocap.szPname);
1556 }
1557}
1558#endif
1559
1560void mmio_getdevs(char *indevlist, int *nindevs,
1561 char *outdevlist, int *noutdevs, int *canmulti,
1562 int maxndev, int devdescsize)
1563{
1564 int wRtn, ndev, i;
1565
1566 *canmulti = 2; /* supports multiple devices */
1567 ndev = waveInGetNumDevs();
1568 if (ndev > maxndev)
1569 ndev = maxndev;
1570 *nindevs = ndev;
1571 for (i = 0; i < ndev; i++)
1572 {
1573 WAVEINCAPS wicap;
1574 wRtn = waveInGetDevCaps(i, (LPWAVEINCAPS) &wicap, sizeof(wicap));
1575 sprintf(indevlist + i * devdescsize, (wRtn ? "???" : wicap.szPname));
1576 }
1577
1578 ndev = waveOutGetNumDevs();
1579 if (ndev > maxndev)
1580 ndev = maxndev;
1581 *noutdevs = ndev;
1582 for (i = 0; i < ndev; i++)
1583 {
1584 WAVEOUTCAPS wocap;
1585 wRtn = waveOutGetDevCaps(i, (LPWAVEOUTCAPS) &wocap, sizeof(wocap));
1586 sprintf(outdevlist + i * devdescsize, (wRtn ? "???" : wocap.szPname));
1587 }
1588}