File: io.c

package info (click to toggle)
snd 3.4-4
  • links: PTS
  • area: main
  • in suites: potato
  • size: 5,148 kB
  • ctags: 12,594
  • sloc: ansic: 86,516; lisp: 3,480; sh: 1,507; makefile: 119
file content (1685 lines) | stat: -rw-r--r-- 53,098 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
/* IO handlers */
/*
 * --------------------------------
 * int mus_create_descriptors (void): initialize (allocate) various global arrays
 * int mus_read(int fd, int beg, int end, int chans, int **bufs)
 * int mus_write(int tfd, int beg, int end, int chans, int **bufs)
 * long mus_seek(int tfd, long offset, int origin)
 * int mus_open_read(char *arg) 
 * int mus_open_write(char *arg)
 * int mus_create(char *arg)
 * int mus_reopen_write(char *arg)
 * int mus_close(int fd)
 * int mus_probe_file(char *arg)
 * int mus_open_file_descriptors (int tfd, int df, int ds, int dl)
 * int mus_close_file_descriptors(int tfd)
 * see sndplay.c for a short example
 * --------------------------------
 */

#if defined(HAVE_CONFIG_H)
  #include "config.h"
#endif

#include <math.h>
#include <stdio.h>
#if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_FCNTL_H))
  #include <fcntl.h>
#endif
#include <signal.h>
#if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_LIMITS_H))
  #include <limits.h>
#endif
#include <errno.h>
#include <stdlib.h>

#if (defined(NEXT) || (defined(HAVE_LIBC_H) && (!defined(HAVE_UNISTD_H))))
  #include <libc.h>
#else
  #if (!(defined(_MSC_VER))) && (!(defined(MPW_C)))
    #include <unistd.h>
  #endif
#endif

#include <string.h>

#if (!defined(NEXT)) && (!defined(inline))
  #define inline
#endif

#if (defined(SIZEOF_INT) && (SIZEOF_INT != 4)) || (defined(INT_MAX) && (INT_MAX != 2147483647))
  #error sndlib C code assumes 32-bit ints
#endif

#if (defined(SIZEOF_LONG) && (SIZEOF_LONG < 4)) || (defined(LONG_MAX) && (LONG_MAX < 2147483647))
  #error sndlib C code assumes longs are at least 32 bits
#endif

#if (defined(SIZEOF_SHORT) && (SIZEOF_SHORT != 2)) || (defined(SHRT_MAX) && (SHRT_MAX != 32767))
  #error sndlib C code assumes 16-bit shorts
#endif

#if (defined(SIZEOF_CHAR) && (SIZEOF_CHAR != 1)) || (defined(CHAR_BIT) && (CHAR_BIT != 8))
  #error sndlib C code assumes 8-bit chars
#endif

#include "sndlib.h"

/* data translations for big/little endian machines -- the m_* forms are macros where possible for speed */

void mus_set_big_endian_int(unsigned char *j, int x)
{
  unsigned char *ox;
  ox=(unsigned char *)&x;
#ifdef SNDLIB_LITTLE_ENDIAN
  j[0]=ox[3]; j[1]=ox[2]; j[2]=ox[1]; j[3]=ox[0];
#else
  j[0]=ox[0]; j[1]=ox[1]; j[2]=ox[2]; j[3]=ox[3];
#endif
}

int mus_big_endian_int (unsigned char *inp)
{
  int o;
  unsigned char *outp;
  outp=(unsigned char *)&o;
#ifdef SNDLIB_LITTLE_ENDIAN
  outp[0]=inp[3]; outp[1]=inp[2]; outp[2]=inp[1]; outp[3]=inp[0];
#else
  outp[0]=inp[0]; outp[1]=inp[1]; outp[2]=inp[2]; outp[3]=inp[3];
#endif
  return(o);
}

void mus_set_little_endian_int(unsigned char *j, int x)
{
  unsigned char *ox;
  ox=(unsigned char *)&x;
#ifndef SNDLIB_LITTLE_ENDIAN
  j[0]=ox[3]; j[1]=ox[2]; j[2]=ox[1]; j[3]=ox[0];
#else
  j[0]=ox[0]; j[1]=ox[1]; j[2]=ox[2]; j[3]=ox[3];
#endif
}

int mus_little_endian_int (unsigned char *inp)
{
  int o;
  unsigned char *outp;
  outp=(unsigned char *)&o;
#ifndef SNDLIB_LITTLE_ENDIAN
  outp[0]=inp[3]; outp[1]=inp[2]; outp[2]=inp[1]; outp[3]=inp[0];
#else
  outp[0]=inp[0]; outp[1]=inp[1]; outp[2]=inp[2]; outp[3]=inp[3];
#endif
  return(o);
}

int mus_uninterpreted_int (unsigned char *inp)
{
  int o;
  unsigned char *outp;
  outp=(unsigned char *)&o;
  outp[0]=inp[0]; outp[1]=inp[1]; outp[2]=inp[2]; outp[3]=inp[3];
  return(o);
}

unsigned int mus_big_endian_unsigned_int (unsigned char *inp)
{
  unsigned int o;
  unsigned char *outp;
  outp=(unsigned char *)&o;
#ifdef SNDLIB_LITTLE_ENDIAN
  outp[0]=inp[3]; outp[1]=inp[2]; outp[2]=inp[1]; outp[3]=inp[0];
#else
  outp[0]=inp[0]; outp[1]=inp[1]; outp[2]=inp[2]; outp[3]=inp[3];
#endif
  return(o);
}

unsigned int mus_little_endian_unsigned_int (unsigned char *inp)
{
  unsigned int o;
  unsigned char *outp;
  outp=(unsigned char *)&o;
#ifndef SNDLIB_LITTLE_ENDIAN
  outp[0]=inp[3]; outp[1]=inp[2]; outp[2]=inp[1]; outp[3]=inp[0];
#else
  outp[0]=inp[0]; outp[1]=inp[1]; outp[2]=inp[2]; outp[3]=inp[3];
#endif
  return(o);
}


void mus_set_big_endian_float(unsigned char *j, float x)
{
  unsigned char *ox;
  ox=(unsigned char *)&x;
#ifdef SNDLIB_LITTLE_ENDIAN
  j[0]=ox[3]; j[1]=ox[2]; j[2]=ox[1]; j[3]=ox[0];
#else
  j[0]=ox[0]; j[1]=ox[1]; j[2]=ox[2]; j[3]=ox[3];
#endif
}

float mus_big_endian_float (unsigned char *inp)
{
  float o;
  unsigned char *outp;
  outp=(unsigned char *)&o;
#ifdef SNDLIB_LITTLE_ENDIAN
  outp[0]=inp[3]; outp[1]=inp[2]; outp[2]=inp[1]; outp[3]=inp[0];
#else
  outp[0]=inp[0]; outp[1]=inp[1]; outp[2]=inp[2]; outp[3]=inp[3];
#endif
  return(o);
}

void mus_set_little_endian_float(unsigned char *j, float x)
{
  unsigned char *ox;
  ox=(unsigned char *)&x;
#ifndef SNDLIB_LITTLE_ENDIAN
  j[0]=ox[3]; j[1]=ox[2]; j[2]=ox[1]; j[3]=ox[0];
#else
  j[0]=ox[0]; j[1]=ox[1]; j[2]=ox[2]; j[3]=ox[3];
#endif
}

float mus_little_endian_float (unsigned char *inp)
{
  float o;
  unsigned char *outp;
  outp=(unsigned char *)&o;
#ifndef SNDLIB_LITTLE_ENDIAN
  outp[0]=inp[3]; outp[1]=inp[2]; outp[2]=inp[1]; outp[3]=inp[0];
#else
  outp[0]=inp[0]; outp[1]=inp[1]; outp[2]=inp[2]; outp[3]=inp[3];
#endif
  return(o);
}

void mus_set_big_endian_short(unsigned char *j, short x)
{
  unsigned char *ox;
  ox=(unsigned char *)&x;
#ifdef SNDLIB_LITTLE_ENDIAN
  j[0]=ox[1]; j[1]=ox[0];
#else
  j[0]=ox[0]; j[1]=ox[1];
#endif
}

short mus_big_endian_short (unsigned char *inp)
{
  short o;
  unsigned char *outp;
  outp=(unsigned char *)&o;
#ifdef SNDLIB_LITTLE_ENDIAN
  outp[0]=inp[1]; outp[1]=inp[0];
#else
  outp[0]=inp[0]; outp[1]=inp[1];
#endif
  return(o);
}

void mus_set_little_endian_short(unsigned char *j, short x)
{
  unsigned char *ox;
  ox=(unsigned char *)&x;
#ifndef SNDLIB_LITTLE_ENDIAN
  j[0]=ox[1]; j[1]=ox[0];
#else
  j[0]=ox[0]; j[1]=ox[1];
#endif
}

short mus_little_endian_short (unsigned char *inp)
{
  short o;
  unsigned char *outp;
  outp=(unsigned char *)&o;
#ifndef SNDLIB_LITTLE_ENDIAN
  outp[0]=inp[1]; outp[1]=inp[0];
#else
  outp[0]=inp[0]; outp[1]=inp[1];
#endif
  return(o);
}

void mus_set_big_endian_unsigned_short(unsigned char *j, unsigned short x)
{
  unsigned char *ox;
  ox=(unsigned char *)&x;
#ifdef SNDLIB_LITTLE_ENDIAN
  j[0]=ox[1]; j[1]=ox[0];
#else
  j[0]=ox[0]; j[1]=ox[1];
#endif
}

unsigned short mus_big_endian_unsigned_short (unsigned char *inp)
{
  unsigned short o;
  unsigned char *outp;
  outp=(unsigned char *)&o;
#ifdef SNDLIB_LITTLE_ENDIAN
  outp[0]=inp[1]; outp[1]=inp[0];
#else
  outp[0]=inp[0]; outp[1]=inp[1];
#endif
  return(o);
}

void mus_set_little_endian_unsigned_short(unsigned char *j, unsigned short x)
{
  unsigned char *ox;
  ox=(unsigned char *)&x;
#ifndef SNDLIB_LITTLE_ENDIAN
  j[0]=ox[1]; j[1]=ox[0];
#else
  j[0]=ox[0]; j[1]=ox[1];
#endif
}

unsigned short mus_little_endian_unsigned_short (unsigned char *inp)
{
  unsigned short o;
  unsigned char *outp;
  outp=(unsigned char *)&o;
#ifndef SNDLIB_LITTLE_ENDIAN
  outp[0]=inp[1]; outp[1]=inp[0];
#else
  outp[0]=inp[0]; outp[1]=inp[1];
#endif
  return(o);
}

double mus_little_endian_double (unsigned char *inp)
{
  double o;
#ifndef SNDLIB_LITTLE_ENDIAN
  int i;
#endif
  unsigned char *outp;
  outp=(unsigned char *)&o;
#ifndef SNDLIB_LITTLE_ENDIAN
  for (i=0;i<8;i++) outp[i]=inp[i];
#else
  outp[0]=inp[7]; outp[1]=inp[6]; outp[2]=inp[5]; outp[3]=inp[4]; outp[4]=inp[3]; outp[5]=inp[2]; outp[6]=inp[1]; outp[7]=inp[0];
#endif
  return(o);
}

double mus_big_endian_double (unsigned char *inp)
{
  double o;
#ifdef SNDLIB_LITTLE_ENDIAN
  int i;
#endif
  unsigned char *outp;
  outp=(unsigned char *)&o;
#ifndef SNDLIB_LITTLE_ENDIAN
  outp[0]=inp[7]; outp[1]=inp[6]; outp[2]=inp[5]; outp[3]=inp[4]; outp[4]=inp[3]; outp[5]=inp[2]; outp[6]=inp[1]; outp[7]=inp[0];
#else
  for (i=0;i<8;i++) outp[i]=inp[i];
#endif
  return(o);
}

void mus_set_big_endian_double(unsigned char *j, double x)
{
#ifdef SNDLIB_LITTLE_ENDIAN
  int i;
#endif
  unsigned char *ox;
  ox=(unsigned char *)&x;
#ifndef SNDLIB_LITTLE_ENDIAN
  j[0]=ox[7]; j[1]=ox[6]; j[2]=ox[5]; j[3]=ox[4]; j[4]=ox[3]; j[5]=ox[2]; j[6]=ox[1]; j[7]=ox[0];
#else
  for (i=0;i<8;i++) j[i]=ox[i];
#endif
}

void mus_set_little_endian_double(unsigned char *j, double x)
{
#ifndef SNDLIB_LITTLE_ENDIAN
  int i;
#endif
  unsigned char *ox;
  ox=(unsigned char *)&x;
#ifndef SNDLIB_LITTLE_ENDIAN
  for (i=0;i<8;i++) j[i]=ox[i];
#else
  j[0]=ox[7]; j[1]=ox[6]; j[2]=ox[5]; j[3]=ox[4]; j[4]=ox[3]; j[5]=ox[2]; j[6]=ox[1]; j[7]=ox[0];
#endif
}

/* Vax float translation taken from Mosaic libdtm/vaxcvt.c */
static float from_vax_float(unsigned char *inp)
{
  unsigned char exp;
  unsigned char c0, c1, c2, c3;
  float o;
  unsigned char *outp;
  outp=(unsigned char *)&o;
  c0 = inp[0]; c1 = inp[1]; c2 = inp[2]; c3 = inp[3];
  exp = (c1 << 1) | (c0 >> 7);             /* extract exponent */
  if (!exp && !c1) return(0.0);            /* zero value */
  else if (exp>2) {                        /* normal value */
    outp[0] = c1 - 1;                      /* subtracts 2 from exponent */
    outp[1] = c0;                          /* copy mantissa, LSB of exponent */
    outp[2] = c3;
    outp[3] = c2;}
  else if (exp) {                          /* denormalized number */
    unsigned int shft;
    outp[0] = c1 & 0x80;                   /* keep sign, zero exponent */
    shft = 3 - exp;
    /* shift original mant by 1 or 2 to get denormalized mant */
    /* prefix mantissa with '1'b or '01'b as appropriate */
    outp[1] = ((c0 & 0x7f) >> shft) | (0x10 << exp);
    outp[2] = (c0 << (8-shft)) | (c3 >> shft);
    outp[3] = (c3 << (8-shft)) | (c2 >> shft);}
  else {                                   /* sign=1 -> infinity or NaN */
    outp[0] = 0xff;                        /* set exp to 255 */
    outp[1] = c0 | 0x80;                   /* LSB of exp = 1 */
    outp[2] = c3;
    outp[3] = c2;}
  return(o);
}

#if USE_BYTESWAP
  #include <byteswap.h>
  /* in fully optimized code, the byteswap macros are about 15% faster than the calls used here */
#endif

#ifdef SNDLIB_LITTLE_ENDIAN

#if USE_BYTESWAP
  #define m_big_endian_short(n)                   ((short)(bswap_16((*((unsigned short *)n)))))
  #define m_big_endian_int(n)                     ((int)(bswap_32((*((unsigned int *)n)))))
#else
  #define m_big_endian_short(n)                   (mus_big_endian_short(n))
  #define m_big_endian_int(n)                     (mus_big_endian_int(n))
#endif
  #define m_big_endian_float(n)                   (mus_big_endian_float(n))
  #define m_big_endian_double(n)                  (mus_big_endian_double(n))
  #define m_big_endian_unsigned_short(n)          (mus_big_endian_unsigned_short(n))

  #define m_little_endian_short(n)                (*((short *)n))
  #define m_little_endian_int(n)                  (*((int *)n))
  #define m_little_endian_float(n)                (*((float *)n))
  #define m_little_endian_double(n)               (*((double *)n))
  #define m_little_endian_unsigned_short(n)       (*((unsigned short *)n))

  #define m_set_big_endian_short(n,x)             mus_set_big_endian_short(n,x)
  #define m_set_big_endian_int(n,x)               mus_set_big_endian_int(n,x)
  #define m_set_big_endian_float(n,x)             mus_set_big_endian_float(n,x)
  #define m_set_big_endian_double(n,x)            mus_set_big_endian_double(n,x)
  #define m_set_big_endian_unsigned_short(n,x)    mus_set_big_endian_unsigned_short(n,x)

  #define m_set_little_endian_short(n,x)          (*((short *)n)) = x
  #define m_set_little_endian_int(n,x)            (*((int *)n)) = x
  #define m_set_little_endian_float(n,x)          (*((float *)n)) = x
  #define m_set_little_endian_double(n,x)         (*((double *)n)) = x
  #define m_set_little_endian_unsigned_short(n,x) (*((unsigned short *)n)) = x

#else

  #ifndef SUN
    #define m_big_endian_short(n)                   (*((short *)n))
    #define m_big_endian_int(n)                     (*((int *)n))
    #define m_big_endian_float(n)                   (*((float *)n))
    #define m_big_endian_double(n)                  (*((double *)n))
    #define m_big_endian_unsigned_short(n)          (*((unsigned short *)n))

    #define m_set_big_endian_short(n,x)             (*((short *)n)) = x
    #define m_set_big_endian_int(n,x)               (*((int *)n)) = x
    #define m_set_big_endian_float(n,x)             (*((float *)n)) = x
    #define m_set_big_endian_double(n,x)            (*((double *)n)) = x
    #define m_set_big_endian_unsigned_short(n,x)    (*((unsigned short *)n)) = x
  #else
    #define m_big_endian_short(n)                   (mus_big_endian_short(n))
    #define m_big_endian_int(n)                     (mus_big_endian_int(n))
    #define m_big_endian_float(n)                   (mus_big_endian_float(n))
    #define m_big_endian_double(n)                  (mus_big_endian_double(n))
    #define m_big_endian_unsigned_short(n)          (mus_big_endian_unsigned_short(n))

    #define m_set_big_endian_short(n,x)             mus_set_big_endian_short(n,x)
    #define m_set_big_endian_int(n,x)               mus_set_big_endian_int(n,x)
    #define m_set_big_endian_float(n,x)             mus_set_big_endian_float(n,x)
    #define m_set_big_endian_double(n,x)            mus_set_big_endian_double(n,x)
    #define m_set_big_endian_unsigned_short(n,x)    mus_set_big_endian_unsigned_short(n,x)
  #endif

#if USE_BYTESWAP
  #define m_little_endian_short(n)                  ((short)(bswap_16((*((unsigned short *)n)))))
  #define m_little_endian_int(n)                    ((int)(bswap_32((*((unsigned int *)n)))))
#else
  #define m_little_endian_short(n)                  (mus_little_endian_short(n))
  #define m_little_endian_int(n)                    (mus_little_endian_int(n))
#endif
  #define m_little_endian_float(n)                  (mus_little_endian_float(n))
  #define m_little_endian_double(n)                 (mus_little_endian_double(n))
  #define m_little_endian_unsigned_short(n)         (mus_little_endian_unsigned_short(n))

  #define m_set_little_endian_short(n,x)            mus_set_little_endian_short(n,x)
  #define m_set_little_endian_int(n,x)              mus_set_little_endian_int(n,x)
  #define m_set_little_endian_float(n,x)            mus_set_little_endian_float(n,x)
  #define m_set_little_endian_double(n,x)           mus_set_little_endian_double(n,x)
  #define m_set_little_endian_unsigned_short(n,x)   mus_set_little_endian_unsigned_short(n,x)

#endif


/* ---------------- file descriptors ----------------
 *
 * I'm using unbuffered IO here because it is faster on the machines I normally use,
 * and I'm normally doing very large reads/writes (that is, the stuff is self-buffered).
 *
 *   machine                     read/write:              fread/fwrite:             arithmetic: 
 *                               256   512   8192  65536  same sizes                tbl   bigfft sffts
 *
 * NeXT 68040 (32MB):            11575 10514 10256  9943  11951 11923 12358 12259   10478 108122 26622
 * NeXT Turbo (16MB):             8329  7760  6933  6833   9216  8742  9416  9238    7825 121591 19495
 * HP 90MHz Pentium NextStep:    11970 10069  9840  9920  11930 11209 11399 11540    1930  46389  4019
 * Mac 8500 120 MHz PPC MacOS:   21733 15416  5000  2916   9566  9550  9733  9850    <died in memory manager>
 * Mac G3 266 MHz PPC MacOS:      4866  3216  1850  1366   2400  2400  2366  2450     550  12233   700
 * MkLinux G3 266 MHz:             580   462   390   419    640   631   552   500     485  11364   770
 * LinuxPPC G3 266 MHz:            456   385   366   397    489   467   467   487     397  11808   763
 * Mac clone 120 MHz PPC BeOS:    1567   885   725  3392   1015  1000  1114  1161    1092  37212  1167
 * SGI R4600 132 MHz Indy (32MB): 2412  1619   959  1045   1172  1174  1111  1126    1224  30825  3490
 * SGI R5000 150 MHz Indy (32MB): 1067   846   684   737    847   817   734   791     885  25878  1591
 * SGI R5000 180 MHz O2 (64MB):   1359   788   431   446   1919  1944  1891  1885     828  24658  1390
 * Sun Ultra5 270 MHz (128 MB):    981   880   796   827    965  1029   922   903     445  26791   691
 * HP 200 MHz Pentium Linux:       576   492   456   482    615   613   599   592     695  14851   882
 * Asus 266 MHz Pentium II Linux:  475   426   404   406    466   455   467   465     490  13170   595
 * ditto W95:                     1320   660   600   550   2470  2470  2470  2470     990  17410  1540
 * Dell XPSD300 Pentium II Linux:  393   350   325   332    376   369   397   372     414   8793   576
 * 450MHz PC Linux:                263   227   208   217    268   263   274   270     275   6224   506
 *
 * the first 8 numbers are comparing read/write fread/fwrite at various buffer sizes -- CLM uses 65536.
 * the last 3 numbers are comparing table lookup, a huge fft, and a bunch of small ffts.
 * In normal CLM usage, small instruments and mixes are IO bound, so these differences can matter.
 * The reason to use 65536 rather than 8192 is that it allows us to forgo IO completely in
 * many cases -- the output buffer can collect many notes before flushing, etc.
 */

#if defined(SGI) || defined(LINUX) || defined(UW2) || defined(SCO5)
  #define FILE_DESCRIPTORS 400
  #define BASE_FILE_DESCRIPTORS 200
#else
  #define FILE_DESCRIPTORS 128
  #define BASE_FILE_DESCRIPTORS 64
#endif

static int io_descriptors_ok = 0;
static int *io_data_format,*io_bytes_per_sample,*io_data_location,*io_files,*io_data_clipped,*io_chans,*io_header_type;
static int io_files_ready = 0;
static int max_descriptor = 0;

static int rt_ap_out;   /* address of RT audio ports, if any */

#ifdef CLM
void set_rt_audio_p (int rt)
{
  rt_ap_out = rt;
}
#endif

int mus_create_descriptors (void)
{
  if (!io_descriptors_ok)
    {
      io_descriptors_ok = 1;
      max_descriptor = 0;
      io_data_format = (int *)CALLOC(FILE_DESCRIPTORS,sizeof(int));
      io_bytes_per_sample = (int *)CALLOC(FILE_DESCRIPTORS,sizeof(int));
      io_data_clipped = (int *)CALLOC(FILE_DESCRIPTORS,sizeof(int));
      io_header_type = (int *)CALLOC(FILE_DESCRIPTORS,sizeof(int));
      io_chans = (int *)CALLOC(FILE_DESCRIPTORS,sizeof(int));
      io_data_location = (int *)CALLOC(FILE_DESCRIPTORS,sizeof(int));
      io_files = (int *)CALLOC(BASE_FILE_DESCRIPTORS,sizeof(int));
      if ((io_data_format == NULL) || (io_bytes_per_sample == NULL) || (io_data_location == NULL) || (io_files == NULL) ||
	  (io_data_clipped == NULL) || (io_header_type == NULL))
	{
	  mus_error(MUS_MEMORY_ALLOCATION_FAILED,"file descriptor buffer allocation trouble");
	  return(-1);
	}
    }
  return(0);
}

static int convert_fd(int n)
{
  if (n<BASE_FILE_DESCRIPTORS)
    return(n);
  else
    {
      int i;
      for (i=0;i<BASE_FILE_DESCRIPTORS;i++)
	{
	  if (io_files[i] == n) return(i+BASE_FILE_DESCRIPTORS);
	}
      return(-1);
    }
}

static int open_mus_file (int tfd)
{
  int fd;
  if (tfd < BASE_FILE_DESCRIPTORS) return(tfd);
  if (io_files_ready == 0)
    {
      for (fd=0;fd<BASE_FILE_DESCRIPTORS;fd++) io_files[fd]=-1;
      io_files_ready = 1;
    }
  for (fd=0;fd<BASE_FILE_DESCRIPTORS;fd++)
    {
      if (io_files[fd] == -1)
	{
	  io_files[fd] = tfd;
	  return(fd+BASE_FILE_DESCRIPTORS);
	}
    }
  return(-1);
}

int mus_open_file_descriptors (int tfd, int format, int size, int location)
{ /* transfers header info from functions in header.c back to us for reads here and in merge.c */
  int fd;
  if (!io_descriptors_ok) return(-1);
  fd = open_mus_file(tfd);
  if (fd == -1) return(-1);
  io_data_format[fd] = format;
  io_bytes_per_sample[fd] = size;
  io_data_location[fd] = location;
  io_data_clipped[fd] = 0;
  io_header_type[fd] = 0;
  io_chans[fd] = 1;
  if (fd > max_descriptor) max_descriptor = fd;
  return(0);
}

int mus_set_file_descriptors (int tfd, int format, int size, int location, int chans, int type)
{
  /* new form to make sound.c handlers cleaner, 4-Sep-99 */
  int fd;
  if (!io_descriptors_ok) return(-1);
  fd = open_mus_file(tfd);
  if (fd == -1) return(-1);
  io_data_format[fd] = format;
  io_bytes_per_sample[fd] = size;
  io_data_location[fd] = location;
  io_header_type[fd] = type;
  io_data_clipped[fd] = 0;
  io_chans[fd] = chans;
  if (fd > max_descriptor) max_descriptor = fd;
  return(0);
}

int mus_close_file_descriptors(int tfd)
{
  int fd;
  if (!io_descriptors_ok) return(0); /* not necessarily an error -- c-close before with-sound etc */
  fd = convert_fd(tfd);
  if (fd >= 0)
    {
      if (fd >= BASE_FILE_DESCRIPTORS)
	io_files[fd-BASE_FILE_DESCRIPTORS] = -1;
      io_data_format[fd]=SNDLIB_NO_SND;
      io_header_type[fd] = 0;
      io_data_clipped[fd] = 0;
      io_chans[fd] = 0;
      return(0);
    }
  return(-1);
}

int mus_cleanup_file_descriptors(void)
{
  /* error cleanup -- try to find C-opened files that are invisible to lisp and close them */
  int fd,lim;
  if (!io_descriptors_ok) return(0);
  lim = BASE_FILE_DESCRIPTORS-1;
  if (max_descriptor < lim) lim = max_descriptor;
  for (fd=0;fd<=lim;fd++)
    if (io_data_format[fd] != SNDLIB_NO_SND) mus_close(fd);
  if ((io_files_ready) && (max_descriptor > BASE_FILE_DESCRIPTORS))
    {
      lim = max_descriptor - BASE_FILE_DESCRIPTORS;
      if (lim >= BASE_FILE_DESCRIPTORS) lim = BASE_FILE_DESCRIPTORS - 1;
      for (fd=0;fd<=lim;fd++)
	if (io_files[fd] != -1)
	  mus_close(io_files[fd]);
    }
  return(0);
}

int mus_set_data_clipped (int tfd, int clipped)
{
  int fd;
  if (!io_descriptors_ok) return(0);
  fd = convert_fd(tfd);
  if (fd < 0) return(-1);
  io_data_clipped[fd] = clipped;
  return(0);
}

int mus_set_header_type (int tfd, int type)
{
  int fd;
  if (!io_descriptors_ok) return(0);
  fd = convert_fd(tfd);
  if (fd < 0) return(-1);
  io_header_type[fd] = type;
  return(0);
}

int mus_get_header_type(int tfd)
{
  int fd;
  if (!io_descriptors_ok) return(0);
  fd = convert_fd(tfd);
  if (fd < 0) return(-1);
  return(io_header_type[fd]);
}

int mus_set_chans (int tfd, int chans)
{
  int fd;
  if (!io_descriptors_ok) return(0);
  fd = convert_fd(tfd);
  if (fd < 0) return(-1);
  io_chans[fd] = chans;
  return(0);
}


/* ---------------- open, creat, close ---------------- */

int mus_open_read(char *arg) 
{
#ifdef MACOS
  return(open (arg, O_RDONLY));
#else
  int fd;
  #ifdef WINDOZE
    fd = open (arg, O_RDONLY | O_BINARY);
  #else
    fd = open (arg, O_RDONLY, 0);
  #endif
  return(fd);
#endif
}

int mus_probe_file(char *arg) 
{
  int fd;
#ifdef MACOS
  fd = (open (arg, O_RDONLY));
#else
  #ifdef WINDOZE
    fd = open (arg, O_RDONLY | O_BINARY);
  #else
    #ifdef O_NONBLOCK
      fd = open(arg,O_RDONLY,O_NONBLOCK);
    #else
      fd = open(arg,O_RDONLY,0);
    #endif
  #endif
#endif
  if (fd == -1) return(0);
  close(fd);
  return(1);
}

int mus_open_write(char *arg)
{
  int fd;
#ifdef MACOS
  if ((fd = open(arg,O_RDWR)) == -1)
  #ifdef MPW_C
    fd = creat(arg);
  #else
    fd = creat(arg, 0);
  #endif
  else
    lseek(fd,0L,SEEK_END);
#else
  #ifdef WINDOZE
    if ((fd = open(arg,O_RDWR | O_BINARY)) == -1)
  #else
    if ((fd = open(arg,O_RDWR,0)) == -1)
  #endif
      {
        fd = creat(arg,0666);  /* equivalent to the new open(arg,O_RDWR | O_CREAT | O_TRUNC, 0666) */
      }
    else
      lseek(fd,0L,SEEK_END);
#endif
  return(fd);
}

int mus_create(char *arg)
{
#ifdef MACOS
  #ifdef MPW_C
    return(creat(arg));
  #else
    return(creat(arg,0));
  #endif
#else
  int fd;
  fd = creat(arg,0666);
  return(fd);
#endif
}

int mus_reopen_write(char *arg)
{
#ifdef MACOS
  return(open(arg,O_RDWR));
#else
  int fd;
  #ifdef WINDOZE
    fd = open(arg,O_RDWR | O_BINARY);
  #else
    fd = open(arg,O_RDWR,0);
  #endif
  return(fd);
#endif
}

int mus_close(int fd)
{
  mus_close_file_descriptors(fd);
  return(close(fd));
}



/* ---------------- seek ---------------- */

long mus_seek(int tfd, long offset, int origin)
{
  int fd,siz; /* siz = datum size in bytes */
  long loc,true_loc,header_end;
  if (!io_descriptors_ok) {mus_error(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED,"mus_seek: file descriptors not initialized!"); return(-1);}
  if ((tfd == SNDLIB_DAC_CHANNEL) || (tfd == SNDLIB_DAC_REVERB)) return(0);
  fd = convert_fd(tfd);
  if (fd < 0) return(-1);
  if (io_data_format[fd] == SNDLIB_NO_SND) 
    {
      mus_error(MUS_NOT_A_SOUND_FILE,"mus_seek: invalid stream: %d (%d, %d, %d)",fd,tfd,(int)offset,origin);
      return(-1);
    }
  siz = io_bytes_per_sample[fd];
  if ((siz == 2) || (origin != 0))
    return(lseek(tfd,offset,origin));
  else
    {
      header_end = io_data_location[fd];
      loc = offset - header_end;
      switch (siz)
	{
	case 1: 
	  true_loc = lseek(tfd,header_end+(loc>>1),origin);
	  /* now pretend we're still in 16-bit land and return where we "actually" are in that region */
	  /* that is, loc (in bytes) = how many (2-byte) samples into the file we want to go, return what we got */
	  return(header_end + ((true_loc - header_end)<<1));
	  break;
	case 3:
	  true_loc = lseek(tfd,header_end+loc+(loc>>1),origin);
	  return(true_loc + ((true_loc - header_end)>>1));
	  break;
	case 4:
	  true_loc = lseek(tfd,header_end+(loc<<1),origin);
	  return(header_end + ((true_loc - header_end)>>1));
	  break;
	case 8:
	  true_loc = lseek(tfd,header_end+(loc<<2),origin);
	  return(header_end + ((true_loc - header_end)>>2));
	  break;
	}
    }
  return(-1);
}

int mus_seek_frame(int tfd, int frame)
{
  int fd;
  if (!io_descriptors_ok) {mus_error(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED,"mus_seek_frame: file descriptors not initialized!"); return(-1);}
  if ((tfd == SNDLIB_DAC_CHANNEL) || (tfd == SNDLIB_DAC_REVERB)) return(0);
  fd = convert_fd(tfd);
  if (fd < 0) return(-1);
  if (io_data_format[fd] == SNDLIB_NO_SND) 
    {
      mus_error(MUS_NOT_A_SOUND_FILE,"mus_seek_frame: invalid stream: %d (%d, %d)",fd,tfd,frame);
      return(-1);
    }
  return(lseek(tfd,io_data_location[fd] + (io_chans[fd] * frame * io_bytes_per_sample[fd]),SEEK_SET));
}



/* ---------------- mulaw/alaw conversions ----------------
 *
 *      x : input signal with max value 32767
 *     mu : compression parameter (mu=255 used for telephony)
 *     y = (32767/log(1+mu))*log(1+mu*abs(x)/32767)*sign(x); -- this isn't right -- typo?
 */

/* from sox g711.c */

#define	SIGN_BIT	(0x80)		/* Sign bit for a A-law byte. */
#define	QUANT_MASK	(0xf)		/* Quantization field mask. */
#define	NSEGS		(8)		/* Number of A-law segments. */
#define	SEG_SHIFT	(4)		/* Left shift for segment number. */
#define	SEG_MASK	(0x70)		/* Segment field mask. */

static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF,  0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};

static int search(int val, short *table, int size)
{
  int i;
  for (i = 0; i < size; i++) {if (val <= *table++) return (i);}
  return (size);
}

static unsigned char to_alaw(int pcm_val)
{
  int mask,seg;
  unsigned char	aval;
  if (pcm_val >= 0) {mask = 0xD5;} else {mask = 0x55; pcm_val = -pcm_val - 8;}
  seg = search(pcm_val, seg_end, 8);
  if (seg >= 8)	return (0x7F ^ mask);
  else 
    {
      aval = seg << SEG_SHIFT;
      if (seg < 2) aval |= (pcm_val >> 4) & QUANT_MASK; else aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
      return (aval ^ mask);
    }
}

static const int alaw[256] = {
 -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, 
 -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, 
 -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, 
 -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, 
 -344, -328, -376, -360, -280, -264, -312, -296, -472, -456, -504, -488, -408, -392, -440, -424, 
 -88, -72, -120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136, -184, -168, 
 -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, 
 -688, -656, -752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816, -784, -880, -848, 
 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 
 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 
 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 
 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 
 344, 328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 
 88, 72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 
 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 
 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848
};

#if 0
static int from_alaw(unsigned char a_val)
{
  int t,seg;
  a_val ^= 0x55;
  t = (a_val & QUANT_MASK) << 4;
  seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
  switch (seg) 
    {
    case 0: t += 8; break;
    case 1: t += 0x108; break;
  default:  t += 0x108; t <<= seg - 1;
    }
  return((a_val & SIGN_BIT) ? t : -t);
}
#endif 

#define	BIAS		(0x84)		/* Bias for linear code. */

static unsigned char to_mulaw(int pcm_val)
{
  int mask;
  int seg;
  unsigned char	uval;
  if (pcm_val < 0) {pcm_val = BIAS - pcm_val; mask = 0x7F;} else {pcm_val += BIAS; mask = 0xFF;}
  seg = search(pcm_val, seg_end, 8);
  if (seg >= 8) return (0x7F ^ mask);
  else 
    {
      uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF);
      return (uval ^ mask);
    }
}

/* generated by SNDiMulaw on a NeXT -- see /usr/include/sound/mulaw.h */
static const int mulaw[256] = {
  -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, -23932, -22908, -21884, -20860, 
  -19836, -18812, -17788, -16764, -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, 
  -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, -7932, -7676, -7420, -7164, -6908, 
  -6652, -6396, -6140, -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, -3900, -3772, -3644, 
  -3516, -3388, -3260, -3132, -3004, -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, -1884, 
  -1820, -1756, -1692, -1628, -1564, -1500, -1436, -1372, -1308, -1244, -1180, -1116, -1052, -988, 
  -924, -876, -844, -812, -780, -748, -716, -684, -652, -620, -588, -556, -524, -492, -460, -428, 
  -396, -372, -356, -340, -324, -308, -292, -276, -260, -244, -228, -212, -196, -180, -164, -148, 
  -132, -120, -112, -104, -96, -88, -80, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0, 32124, 31100, 
  30076, 29052, 28028, 27004, 25980, 24956, 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, 
  15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, 11900, 11388, 10876, 10364, 9852, 9340, 
  8828, 8316, 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, 5884, 5628, 5372, 5116, 4860, 4604, 
  4348, 4092, 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, 2876, 2748, 2620, 2492, 2364, 2236, 
  2108, 1980, 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, 1372, 1308, 1244, 1180, 1116, 1052, 
  988, 924, 876, 844, 812, 780, 748, 716, 684, 652, 620, 588, 556, 524, 492, 460, 428, 396, 372, 
  356, 340, 324, 308, 292, 276, 260, 244, 228, 212, 196, 180, 164, 148, 132, 120, 112, 104, 96, 
  88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0};

#if 0
/* in case it's ever needed, here's the mulaw to linear converter from g711.c -- identical to table above */
static int from_mulaw(unsigned char u_val)
{
  int t;
  u_val = ~u_val;
  t = ((u_val & QUANT_MASK) << 3) + BIAS;
  t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
  return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
}
#endif

/* ---------------- read/write buffer allocation ---------------- */

#if LONG_INT_P
static int **long_int_p_table = NULL;
static int long_int_p_table_size = 0;

int *delist_ptr(int arr) {return(long_int_p_table[arr]);}

int list_ptr(int *arr) 
{
  int i,loc;
  loc = -1;
  for (i=0;i<long_int_p_table_size;i++) 
    {
      if (long_int_p_table[i] == NULL)
	{
	  loc = i;
	  break;
	}
    }
  if (loc == -1)
    {
      loc = long_int_p_table_size;
      long_int_p_table_size+=16;
      if (long_int_p_table)
	{
	  long_int_p_table = (int **)REALLOC(long_int_p_table,long_int_p_table_size * sizeof(int *));
	  for (i=loc;i<long_int_p_table_size;i++) long_int_p_table[i] = NULL;
	}
      else
	long_int_p_table = (int **)CALLOC(long_int_p_table_size,sizeof(int *));
    }
  long_int_p_table[loc] = arr;
  return(loc);
}

void freearray(int ip_1) 
{
  int *ip; 
  ip = delist_ptr(ip_1); 
  if (ip) FREE(ip); 
  long_int_p_table[ip_1] = NULL;
}
#else
void freearray(int *ip) {if (ip) FREE(ip);}
#endif

#define BUFLIM (64*1024)
static char *charbuf;
static int char_ok = -1;

static void check_charbuf (void)
{
  if (char_ok == -1)
    {
      charbuf = (char *)CALLOC(BUFLIM,sizeof(char)); 
      if (charbuf == NULL) mus_error(MUS_MEMORY_ALLOCATION_FAILED,"IO buffer allocation trouble");
    }
  char_ok = 0;
}

static int checked_write(int fd, char *buf, int chars)
{
#ifdef CLM
#ifndef MACOS
  long lisp_call(int index);
#endif
#endif
  int bytes,cfd;
  if (fd == SNDLIB_DAC_CHANNEL)
    {
      write_audio(rt_ap_out,buf,chars);
    }
  else
    {
      bytes=write(fd,buf,chars);
      if (bytes != chars) 
	{
	  if (!io_descriptors_ok) {mus_error(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED,"checked_write: file descriptors not initialized!"); return(-1);}
	  cfd = convert_fd(fd);
	  if (cfd < 0) return(-1);
	  if (io_data_format[cfd] == SNDLIB_NO_SND) mus_error(MUS_FILE_CLOSED,"checked_write called on closed file");
#if LONG_INT_P
	  mus_error(MUS_WRITE_ERROR,"IO write error (%s): %d of %d bytes written for %d from %d (%d %d %d)\n",
		    strerror(errno),
		    bytes,chars,fd,cfd,io_bytes_per_sample[cfd],io_data_format[cfd],io_data_location[cfd]);
#else
  #ifndef MACOS
	  mus_error(MUS_WRITE_ERROR,"IO write error (%s): %d of %d bytes written for %d from %d (%d %d %d %d)\n",
		    strerror(errno),
		    bytes,chars,fd,cfd,(int)buf,io_bytes_per_sample[cfd],io_data_format[cfd],io_data_location[cfd]);
  #else
	  mus_error(MUS_WRITE_ERROR,"IO write error: %d of %d bytes written for %d from %d (%d %d %d %d)\n",
		    bytes,chars,fd,cfd,(int)buf,io_bytes_per_sample[cfd],io_data_format[cfd],io_data_location[cfd]);
  #endif
#endif
	  return(-1);
	}
    }
  return(0);
}



/* ---------------- read ---------------- */

/* normally we assume a 16-bit fractional part, but sometimes user want 24-bits */
static int shift_24_choice = 0;
#ifdef CLM
int get_shift_24_choice(void) {return(shift_24_choice);}
void set_shift_24_choice(int choice) {shift_24_choice = choice;}
#endif

int mus_read_any(int tfd, int beg, int chans, int nints, int **bufs, int *cm)
{
  int fd;
  int bytes,j,lim,siz,total,leftover,total_read,k,loc,oldloc,siz_chans,buflim;
  unsigned char *jchar;
  int *buffer;
  if (!io_descriptors_ok) {mus_error(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED,"mus_read: file descriptors not initialized!"); return(-1);}
  if (nints <= 0) return(0);
  check_charbuf();
  fd = convert_fd(tfd);
  if (fd < 0) return(-1);
  if (io_data_format[fd] == SNDLIB_NO_SND) {mus_error(MUS_FILE_CLOSED,"read_any called on closed file"); return(-1);}
  siz = io_bytes_per_sample[fd];
  siz_chans = siz*chans;
  leftover = (nints*siz_chans);
  k = (BUFLIM) % siz_chans;
  if (k != 0) /* for example, 3 channel output of 1-byte (mulaw) samples will need a mod 3 buffer */
    buflim = (BUFLIM) - k;
  else buflim = BUFLIM;
  total_read = 0;
  loc = beg;
  while (leftover > 0)
    {
      bytes = leftover;
      if (bytes > buflim) {leftover = (bytes-buflim); bytes = buflim;} else leftover = 0;
      total = read(tfd,charbuf,bytes); 
      if (total <= 0) 
	{
	  /* zero out trailing section (some callers don't check the returned value) -- this added 9-May-99 */
	  lim = beg+nints;
	  if (loc < lim)
	    {
	      for (k=0;k<chans;k++)
		{
		  if ((cm == NULL) || (cm[k]))
		    {
		      for (j=loc;j<lim;j++) 
			bufs[k][j] = 0;
		    }
		}
	    }
	  return(total_read);
	}
      lim = (int) (total / siz_chans);  /* this divide must be exact (hence the buflim calc above) */
      total_read += lim;
      oldloc = loc;

      for (k=0;k<chans;k++)
	{
	  if ((cm == NULL) || (cm[k]))
	    {
	      buffer = (int *)(bufs[k]);
	      if (buffer)
		{
		  loc = oldloc;
		  jchar = (unsigned char *)charbuf;
		  jchar += (k*siz);
		  switch (io_data_format[fd])
		    {
		    case SNDLIB_16_LINEAR:               
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = (int)m_big_endian_short(jchar); 
		      break;
		    case SNDLIB_16_LINEAR_LITTLE_ENDIAN: 
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = (int)m_little_endian_short(jchar); 
		      break;
		    case SNDLIB_32_LINEAR:              
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = m_big_endian_int(jchar); 
		      break;
		    case SNDLIB_32_LINEAR_LITTLE_ENDIAN: 
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = m_little_endian_int(jchar); 
		      break;
		    case SNDLIB_8_MULAW:  	              
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = mulaw[*jchar]; 
		      break;
		    case SNDLIB_8_ALAW:                  
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = alaw[*jchar]; 
		      break;
		    case SNDLIB_8_LINEAR:                
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = (int)(((signed char)(*jchar)) << 8); 
		      break;
		    case SNDLIB_8_UNSIGNED:     	      
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = (int) ((((int)(*jchar))-128) << 8); 
		      break;
		    case SNDLIB_32_FLOAT:
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = (int) (SNDLIB_SNDFIX*(m_big_endian_float(jchar)));
		      break;
		    case SNDLIB_64_DOUBLE:   
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = (int) (SNDLIB_SNDFIX*(m_big_endian_double(jchar)));
		      break;
		    case SNDLIB_32_FLOAT_LITTLE_ENDIAN:    
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = (int) (SNDLIB_SNDFIX*(m_little_endian_float(jchar)));
		      break;
		    case SNDLIB_64_DOUBLE_LITTLE_ENDIAN:   
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = (int) (SNDLIB_SNDFIX*(m_little_endian_double(jchar)));
		      break;
		    case SNDLIB_16_UNSIGNED:   
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = ((int)(m_big_endian_unsigned_short(jchar)) - 32768);
		      break;
		    case SNDLIB_16_UNSIGNED_LITTLE_ENDIAN:   
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = ((int)(m_little_endian_unsigned_short(jchar)) - 32768);
		      break;
		    case SNDLIB_32_VAX_FLOAT:   
		      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) buffer[loc] = (int)from_vax_float(jchar);
		      break;
		    case SNDLIB_24_LINEAR:
		      if (shift_24_choice == 0)
			{
			  for (j=0;j<lim;j++,loc++,jchar+=siz_chans)
			    buffer[loc] = (int)(((jchar[0]<<24)+(jchar[1]<<16))>>16);
			}
		      else
			{
			  for (j=0;j<lim;j++,loc++,jchar+=siz_chans)
			    buffer[loc] = (int)(((jchar[0]<<24)+(jchar[1]<<16)+(jchar[2]<<8))>>8);
			}
		      break;
		    case SNDLIB_24_LINEAR_LITTLE_ENDIAN:   
		      if (shift_24_choice == 0)
			{
			  for (j=0;j<lim;j++,loc++,jchar+=siz_chans)
			    buffer[loc] = (int)(((jchar[2]<<24)+(jchar[1]<<16))>>16);
			}
		      else
			{
			  for (j=0;j<lim;j++,loc++,jchar+=siz_chans)
			    buffer[loc] = (int)(((jchar[2]<<24)+(jchar[1]<<16)+(jchar[0]<<8))>>8);
			}
		      break;
		    }
		}
	    }
	}
    }
  return(total_read);
}

int mus_read(int fd, int beg, int end, int chans, int **bufs)
{
  int num,rtn,i,k;
  int *buffer;
  num=(end-beg+1);
  rtn=mus_read_any(fd,beg,chans,num,bufs,NULL);
  if (rtn == -1) return(-1);
  if (rtn<num) 
    {
      for (k=0;k<chans;k++)
	{
	  buffer=(int *)(bufs[k]);
	  for (i=rtn+beg;i<=end;i++)
	    {
	      buffer[i]=0;
	    }
	}
    }
  return(num);
}

int mus_read_chans(int fd, int beg, int end, int chans, int **bufs, int *cm)
{
  /* an optimization of mus_read -- just reads the desired channels */
  int num,rtn,i,k;
  int *buffer;
  num=(end-beg+1);
  rtn=mus_read_any(fd,beg,chans,num,bufs,cm);
  if (rtn == -1) return(-1);
  if (rtn<num) 
    {
      for (k=0;k<chans;k++)
	{
	  if ((cm == NULL) || (cm[k]))
	    {
	      buffer=(int *)(bufs[k]);
	      for (i=rtn+beg;i<=end;i++)
		{
		  buffer[i]=0;
		}
	    }
	}
    }
  return(num);
}


/* ---------------- write ---------------- */

#ifdef WINDOZE
  #undef min
#endif

#define min(x,y)  ((x) < (y) ? (x) : (y))

int mus_write_zeros(int tfd, int num)
{
  int i,lim,curnum,fd,err;
  if (tfd == -1) return(-1);
  if (tfd == SNDLIB_DAC_REVERB) return(0);
  if (!io_descriptors_ok) {mus_error(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED,"mus_write: file descriptors not initialized!"); return(-1);}
  check_charbuf();
  fd = convert_fd(tfd);
  if (fd < 0) return(-1);
  if (io_data_format[fd] == SNDLIB_NO_SND) {mus_error(MUS_FILE_CLOSED,"write_zeros called on closed file"); return(-1);}
  lim = num*(io_bytes_per_sample[fd]);
  curnum=min(lim,BUFLIM);
  for (i=0;i<curnum;i++) charbuf[i]=0;
  while (curnum>0)
    {
      err = checked_write(tfd,charbuf,curnum);
      if (err == -1) return(-1);
      lim -= (BUFLIM);
      curnum=min(lim,BUFLIM);
    }
  return(num);
}


#ifdef CLM
void mus_write_float(int fd, float val) {write(fd,(char *)(&val),4);}

#if defined(ACL4) && defined(ALPHA)
/* in this case, the array passed from lisp is a list of table indices */
void mus_write_1(int tfd, int beg, int end, int chans, int *buflist)
{
  int i;
  int **bufs;
  bufs = (int **)CALLOC(chans,sizeof(int *));
  for (i=0;i<chans;i++) bufs[i] = delist_ptr(buflist[i]);
  mus_write(tfd,beg,end,chans,bufs);
  FREE(bufs);
}
void mus_read_1(int fd, int beg, int end, int chans, int *buflist)
{
  int i;
  int **bufs;
  bufs = (int **)CALLOC(chans,sizeof(int *));
  for (i=0;i<chans;i++) bufs[i] = delist_ptr(buflist[i]);
  mus_read(fd,beg,end,chans,bufs);
  FREE(bufs);
}
#endif
#endif

int mus_write(int tfd, int beg, int end, int chans, int **bufs)
{
  int fd,err;
  int bytes,j,k,lim,siz,leftover,loc,bk,oldloc,buflim,siz_chans,cliploc;
  unsigned char *jchar;
  int *buffer;
  if (tfd == -1) return(-1);
  if (tfd == SNDLIB_DAC_REVERB) return(0);
  if (!io_descriptors_ok) {mus_error(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED,"mus_write: file descriptors not initialized!"); return(-1);}
  check_charbuf();
  fd = convert_fd(tfd);
  if (fd < 0) return(-1);
  if (io_data_format[fd] == SNDLIB_NO_SND) {mus_error(MUS_FILE_CLOSED,"write called on closed file"); return(-1);}
  siz = io_bytes_per_sample[fd];
  lim=(end-beg+1);
  siz_chans = siz*chans;
  leftover = lim*siz_chans;
  k = (BUFLIM) % siz_chans;
  if (k != 0) 
    buflim = (BUFLIM) - k;
  else buflim = BUFLIM;
  loc = beg;
  while (leftover > 0)
    {
      bytes = leftover;
      if (bytes > buflim) {leftover = (bytes-buflim); bytes = buflim;} else leftover = 0;
      lim = (int)(bytes/siz_chans); /* see note above */
      oldloc = loc;

      for (k=0;k<chans;k++)
	{
	  loc = oldloc;
	  buffer = (int *)(bufs[k]);
	  if (io_data_clipped[fd])
	    {
	      cliploc = oldloc;
	      for (j=0;j<lim;j++,cliploc++)
		{
		  if (buffer[cliploc] > 32767)
		    buffer[cliploc] = 32767;
		  else
		    if (buffer[cliploc] < -32768)
		      buffer[cliploc] = -32768;
		}
	    }
	  jchar = (unsigned char *)charbuf;
	  jchar += (k*siz);
	  switch (io_data_format[fd])
	    {
	    case SNDLIB_16_LINEAR: 
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) m_set_big_endian_short(jchar,(short)(buffer[loc]));
	      break;
	    case SNDLIB_16_LINEAR_LITTLE_ENDIAN:   
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) m_set_little_endian_short(jchar,(short)(buffer[loc]));
	      break;
	    case SNDLIB_32_LINEAR:   
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) m_set_big_endian_int(jchar,buffer[loc]);
	      break;
	    case SNDLIB_32_LINEAR_LITTLE_ENDIAN:   
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) m_set_little_endian_int(jchar,buffer[loc]);
	      break;
	    case SNDLIB_8_MULAW:     
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) (*jchar) = to_mulaw(buffer[loc]);
	      break;
	    case SNDLIB_8_ALAW:      
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) (*jchar) = to_alaw(buffer[loc]);
	      break;
	    case SNDLIB_8_LINEAR:    
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) (*((signed char *)jchar)) = ((buffer[loc])>>8);
	      break;
	    case SNDLIB_8_UNSIGNED:  
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) (*jchar) = ((buffer[loc])>>8)+128;
	      break;
	    case SNDLIB_32_FLOAT:    
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) m_set_big_endian_float(jchar,(SNDLIB_SNDFLT * (buffer[loc])));
	      break;
	    case SNDLIB_32_FLOAT_LITTLE_ENDIAN:    
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) m_set_little_endian_float(jchar,(SNDLIB_SNDFLT * (buffer[loc])));
	      break;
	    case SNDLIB_64_DOUBLE:
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) m_set_big_endian_double(jchar,(SNDLIB_SNDFLT * (buffer[loc])));
	      break;
	    case SNDLIB_64_DOUBLE_LITTLE_ENDIAN:   
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) m_set_little_endian_double(jchar,(SNDLIB_SNDFLT * (buffer[loc])));
	      break;
	    case SNDLIB_16_UNSIGNED: 
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) m_set_big_endian_unsigned_short(jchar,(short)(buffer[loc] + 32768));
	      break;
	    case SNDLIB_16_UNSIGNED_LITTLE_ENDIAN: 
	      for (j=0;j<lim;j++,loc++,jchar+=siz_chans) m_set_little_endian_unsigned_short(jchar,(short)(buffer[loc] + 32768));
	      break;
	    case SNDLIB_24_LINEAR:   
	      bk=(k*3);
	      if (shift_24_choice == 0)
		{
		  for (j=0;j<lim;j++,loc++,bk+=(chans*3)) 
		    {
		      charbuf[bk]=((buffer[loc])>>8); 
		      charbuf[bk+1]=((buffer[loc])&0xFF); 
		      charbuf[bk+2]=0;	
		    }
		}
	      else
		{
		  for (j=0;j<lim;j++,loc++,bk+=(chans*3)) 
		    {
		      charbuf[bk]=((buffer[loc])>>16); 
		      charbuf[bk+1]=((buffer[loc])>>8); 
		      charbuf[bk+2]=((buffer[loc])&0xFF); 
		    }
		}
	      break;
	    case SNDLIB_24_LINEAR_LITTLE_ENDIAN:   
	      bk=(k*3);
	      if (shift_24_choice == 0)
		{
		  for (j=0;j<lim;j++,loc++,bk+=(chans*3))
		    {
		      charbuf[bk+2]=((buffer[loc])>>8); 
		      charbuf[bk+1]=((buffer[loc])&0xFF); 
		      charbuf[bk]=0;    
		    }
		}
	      else
		{
		  for (j=0;j<lim;j++,loc++,bk+=(chans*3))
		    {
		      charbuf[bk+2]=((buffer[loc])>>16); 
		      charbuf[bk+1]=((buffer[loc])>>8); 
		      charbuf[bk]=((buffer[loc])&0xFF); 
		    }
		}
	      break;
	    }
	}
      err = checked_write(tfd,charbuf,bytes);
      if (err == -1) return(-1);
    }
  return(0);
}

int mus_float_sound(char *charbuf, int samps, int charbuf_format, float *buffer)
{
  /* translate whatever is in charbuf to 32-bit floats still interleaved */
  int j,siz;
  unsigned char *jchar;
  siz = mus_format2bytes(charbuf_format);
  jchar = (unsigned char *)charbuf;
  switch (charbuf_format)
    {
    case SNDLIB_16_LINEAR:   
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)(m_big_endian_short(jchar)); 
      break;
    case SNDLIB_16_LINEAR_LITTLE_ENDIAN:   
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)(m_little_endian_short(jchar)); 
      break;
    case SNDLIB_32_LINEAR:   
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)(m_big_endian_int(jchar));
      break;
    case SNDLIB_32_LINEAR_LITTLE_ENDIAN:   
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)(m_little_endian_int(jchar));
      break;
    case SNDLIB_8_MULAW:
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)(mulaw[*jchar]);
      break;
    case SNDLIB_8_ALAW:      
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)(alaw[*jchar]);
      break;
    case SNDLIB_8_LINEAR:
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)((int)((*((signed char *)jchar)) << 8));
      break;
    case SNDLIB_8_UNSIGNED:  
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)((int) ((((int)(*jchar))-128) << 8));
      break;
    case SNDLIB_24_LINEAR:
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)((int)(((jchar[0]<<24)+(jchar[1]<<16))>>16));
      break;
    case SNDLIB_24_LINEAR_LITTLE_ENDIAN:   
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)((int)(((jchar[2]<<24)+(jchar[1]<<16))>>16));
      break;
    case SNDLIB_32_FLOAT:
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = m_big_endian_float(jchar);
      break;
    case SNDLIB_64_DOUBLE:   
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)(m_big_endian_double(jchar));
      break;
    case SNDLIB_32_FLOAT_LITTLE_ENDIAN:    
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = m_little_endian_float(jchar);
      break;
    case SNDLIB_64_DOUBLE_LITTLE_ENDIAN:   
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)(m_little_endian_double(jchar));
      break;
    case SNDLIB_16_UNSIGNED:   
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)(((int)(m_big_endian_unsigned_short(jchar)) - 32768));
      break;
    case SNDLIB_32_VAX_FLOAT:   
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)((int)from_vax_float(jchar));
      break;
    case SNDLIB_16_UNSIGNED_LITTLE_ENDIAN:   
      for (j=0;j<samps;j++,jchar+=siz) buffer[j] = (float)((int)(m_little_endian_unsigned_short(jchar)) - 32768);
      break;
    default: return(-1); break;
    }
  return(0);
}

#ifdef CLM

/* originally part of clmnet.c, but requires endian handlers and is easier to deal with on the Mac if it's in this file */
int net_mix(int fd, int loc, char *buf1, char *buf2, int bytes)
{
#if defined(SNDLIB_LITTLE_ENDIAN) || defined(SUN)
  unsigned char*b1,*b2;
#else
  short *dat1,*dat2;
#endif  
  int i,lim,rtn;
  lim = bytes>>1;
  lseek(fd,loc,SEEK_SET);
  rtn = read(fd,buf1,bytes);
  if (rtn < bytes)
    {
      for (i=rtn;i<bytes;i++) buf1[i]=buf2[i];
      lim = rtn>>1;
    }
  lseek(fd,loc,SEEK_SET);
#if defined(SNDLIB_LITTLE_ENDIAN) || defined(SUN)
  /* all intermediate results are written as big-endian shorts (NeXT output) */
  b1 = (unsigned char *)buf1;
  b2 = (unsigned char *)buf2;
  for (i=0;i<lim;i++,b1+=2,b2+=2) mus_set_big_endian_short(b1,(short)(mus_big_endian_short(b1) + mus_big_endian_short(b2)));
#else
  dat1 = (short *)buf1;
  dat2 = (short *)buf2;
  for (i=0;i<lim;i++) dat1[i] += dat2[i];
#endif
  write(fd,buf1,bytes);
  return(0);
}
#endif

int mus_unshort_sound(short *in_buf, int samps, int new_format, char *out_buf)
{
  int j,siz;
  unsigned char *jchar;
  siz = mus_format2bytes(new_format);
  jchar = (unsigned char *)out_buf;
  switch (new_format)
    {
    case SNDLIB_16_LINEAR:   
      for (j=0;j<samps;j++,jchar+=siz) m_set_big_endian_short(jchar,in_buf[j]);
      break;
    case SNDLIB_16_LINEAR_LITTLE_ENDIAN:   
      for (j=0;j<samps;j++,jchar+=siz) m_set_little_endian_short(jchar,in_buf[j]);
      break;
    case SNDLIB_32_LINEAR:   
      for (j=0;j<samps;j++,jchar+=siz) m_set_big_endian_int(jchar,(int)in_buf[j]);
      break;
    case SNDLIB_32_LINEAR_LITTLE_ENDIAN:   
      for (j=0;j<samps;j++,jchar+=siz) m_set_little_endian_int(jchar,(int)in_buf[j]);
      break;
    case SNDLIB_8_MULAW:     
      for (j=0;j<samps;j++,jchar+=siz) (*jchar) = to_mulaw(in_buf[j]);
      break;
    case SNDLIB_8_ALAW:      
      for (j=0;j<samps;j++,jchar+=siz) (*jchar) = to_alaw(in_buf[j]);
      break;
    case SNDLIB_8_LINEAR:    
      for (j=0;j<samps;j++,jchar+=siz) (*((signed char *)jchar)) = ((in_buf[j])>>8);
      break;
    case SNDLIB_8_UNSIGNED:  
      for (j=0;j<samps;j++,jchar+=siz) (*jchar) = ((in_buf[j])>>8)+128;
      break;
    case SNDLIB_32_FLOAT:    
      for (j=0;j<samps;j++,jchar+=siz) m_set_big_endian_float(jchar,(SNDLIB_SNDFLT * (in_buf[j])));
      break;
    case SNDLIB_32_FLOAT_LITTLE_ENDIAN:    
      for (j=0;j<samps;j++,jchar+=siz) m_set_little_endian_float(jchar,(SNDLIB_SNDFLT * (in_buf[j])));
      break;
    default: return(0); break;
    }
  return(samps*siz);
}

#ifdef CLM
void reset_io_c(void) 
{
  io_descriptors_ok = 0; 
  io_files_ready = 0;
  char_ok = -1;
#if LONG_INT_P
  long_int_p_table = NULL;
  long_int_p_table_size = 0;
#endif
}
#endif


static char file_name_buf[SNDLIB_MAX_FILE_NAME];

char *mus_complete_filename(char *tok)
{
  /* fill out under-specified library pathnames and check for the damned '//' business (SGI file selection box uses this) */
  /* what about "../" and "./" ? these work, but perhaps we should handle them explicitly) */
  int i,j,len;
  if ((tok) && (*tok)) len = strlen(tok); else len = 0;
  j = 0;
  for (i=0;i<len-1;i++)
    {
      if ((tok[i] == '/') && (tok[i+1] == '/')) j=i+1;
    }
  if (j > 0)
    {
      for (i=0;j<len;i++,j++) tok[i] = tok[j];
      tok[i]='\0';
    }
#ifdef MACOS
  strcpy(file_name_buf,tok);
#else
  if (tok[0] != '/')
    {
      file_name_buf[0] = '\0';
      if (tok[0] == '~')
	{
	  strcpy(file_name_buf,getenv("HOME"));
	  strcat(file_name_buf,++tok);
	}
      else
	{
  #if (!defined(NEXT)) || defined(HAVE_GETCWD)
	  getcwd(file_name_buf,SNDLIB_MAX_FILE_NAME);
  #else
	  getwd(file_name_buf);
  #endif
	  strcat(file_name_buf,"/");
	  strcat(file_name_buf,tok);
	}
    }
  else strcpy(file_name_buf,tok);
#endif
  return(file_name_buf);
}