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 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885
|
<html>
<head><title>Snd Customization and Extension</title></head>
<body bgcolor="#ffffff">
<a name="extsndcontents"></a>
<h1>Snd Customization and Extension</h1>
<dl>
<dt><a href="#sndconstants">Constants</a>
<dt><a href="#sndvariables">Variables</a>
<dt><a href="#sndfunctions">Functions</a>
<dt><a href="#sndhooks">Hooks</a>
<dt><a href="#scanning">Scanning Data</a>
<dt><a href="#writing">Writing Sound Files</a>
<dt><a href="#sndsndlib">Sndlib</a>
<dt><a href="#sndinitfile">The initialization file</a>
<dt><a href="#sndexamples">Examples</a>
<dt><a href="#sndresources">Snd resources</a>
<dt><a href="#sndswitches">Snd invocation flags</a>
<dt><a href="#snddynamic">Runtime modules, plug-ins, external programs</a>
<dd><a href="#dynamic">Dynamically loaded modules</a>
<dd><a href="#plugins">Plug-ins</a>
<dd><a href="#programs">External Programs</a>
<dt><a href="#sndaswidget">Snd as a Widget</a>
<dt><a href="#sndwithclm">Snd and the CLM module</a>
<dt><a href="#sndwithmotif">Snd and Motif</a>
</dl>
<h2>Introduction</h2>
<a name="lisplistener"></a>
<p>Nearly everything in Snd can be set in an initialization
file, loaded at any time from a <a href="snd.html#savedstate">saved state</a> file,
specified via inter-process communciation
from any other program, invoked via M-x in the minibuffer,
imbedded in a keyboard macro, or dealt with from the
lisp listener panel. The syntax used is
lisp; if the Guile library is loaded, the
underlying language is actually Scheme,
these entities are fully incorporated into lisp, and all of them
can be used in arbitrarily complicated functions.
I've tried to bring out to lisp nearly every portion
of Snd, both the signal-processing functions, and
much of the user interface. You can, for example,
add your own menu choices, editing operations,
or graphing alternatives. These extensions can
be loaded at any time. If the listener is active
(whether its pane is open or not) any forms typed
to the M-X prompt will be copied to the listener,
providing a history of the interactions. To activate
the listener without opening it (to conserve screen
space or whatever), use the function <a href="#activatelistener">activate-listener</a>.
</p>
<p>Currently, if the listener is active, and some sound
is selected, any characters typed while in the sound
graph which it can't handle are passed to the
listener; to exit the listener without using the
mouse, type C-g.</p>
<p>In Guile versions 1.3.4 or later, remember to
<code>(use-modules (ice-9 debug))</code> if you
want to get backtrace information from the error handler.</p>
<p>In the following, optional arguments are in italics,
functions available only if Guile is loaded are bold face.
Channels are numbered from 0. If a channel argument
is omitted, the currently active channel is used,
if any; otherwise channel 0. Each sound has an
associated "index" used to refer to it in all the
functions. This somewhat arbitrary number is more
or less related to the sound's position in the
display of sounds. If the index is omitted, the
currently active sound is used; if none, the
top sound (or leftmost if you're using the
horizontal panes).
</p>
<hr>
<h2><a name="sndconstants">Constants</a></h2>
<pre>
<font size="2">
Sndlib (see <a href="sndlib.html#sndlibguile">sndlib.html</a> for a complete list):
<a name="nextsoundfile">next-sound-file</a> aiff-sound-file riff-sound-file
nist-sound-file raw-sound-file ircam-sound-file
<a name="snd16linear">snd-16-linear</a> snd-8-mulaw snd-8-linear snd-32-linear-little-endian
snd-32-linear snd-8-alaw snd-8-unsigned snd-32-float-little-endian
snd-64-double snd-24-linear snd-32-float snd-16-linear-little-endian
FFT style (the Transform Options Display choice):
normal-fft sonogram spectrogram
Transform type:
<a name="fouriertransform">fourier-transform</a> wavelet-transform hankel-transform chebyshev-transform legendre-transform
autocorrelation walsh-transform hadamard-transform
<a name="fftwindowchoices"></a>FFT Window type:
rectangular-window hanning-window welch-window parzen-window
bartlett-window hamming-window blackman2-window blackman3-window
blackman4-window exponential-window riemann-window kaiser-window
cauchy-window poisson-window gaussian-window tukey-window
Zoom Focus style:
focus-left focus-right focus-active focus-middle
X-axis Label:
x-in-seconds x-in-samples x-to-one
Speed Control style:
speed-as-float speed-as-ratio speed-as-semitone
Channel Combination style;
<a name="channelstyleconstants">channels-separate</a> channels-combined channels-superimposed
Envelope Editor target:
amplitude-env spectrum-env srate-env
Graph Line style:
<a name="graphlines">graph-lines</a> graph-dots graph-filled graph-lollipops
graph-dots-and-lines
Keyboard action choices:
<a name="cursorchoices">cursor-in-view</a> cursor-on-left cursor-on-right cursor-in-middle
cursor-update-display cursor-no-action cursor-claim-selection keyboard-no-action
</font></pre><hr>
<h2><a name="sndvariables">Variables</a></h2>
<p>These variables are accessed as though each were a function
of no arguments, and set using a function with "set-" prepended
to the variable name. For example, auto-resize's current
value can be accessed via (auto-resize), and set to a
new value via (set-auto-resize #t). (I can't use normal
Scheme variables here because set! would not affect the
user-interface that reflects the variable; I need the
"set-" forms anyway, so making everything a function
makes for less confusion, I hope). Many of the variables
are switches that can take either the C-style boolean values 0 and 1,
or the Scheme-style #f and #t (the variables reside in C, but
Scheme values are translated to C values automatically).
</p>
<pre>
<font size="2">
<a name="askbeforeoverwrite">ask-before-overwrite</a> #f (Save-as): ask before <a href="snd.html#overwrite">overwriting</a> an existing file
<a name="audiooutputdevice">audio-output-device</a> <i>sndlib-default-device</i> Audio output device (for the play button)
<a name="autoresize">auto-resize</a> #t should Snd window resize upon open/close (see <a href="#Xautoresize">AutoResize</a>)
<a name="autoupdate">auto-update</a> #f should Snd <a href="snd.html#updatefile">update</a> a file automatically.
<b><a name="basiccolor">basic-color</a></b> ivory2 main Snd color.
<a name="channelstyle">channel-style</a> <i>channels-separate</i>
The default state of the '<a href="snd.html#unitebutton">unite</a>' button in multi-channel files.
Other values are <i>channels-combined</i> and <i>channels-superimposed</i>.
<a name="colorcutoff">color-cutoff</a> 0.003 In spectra, sets the lowest data value that will be colored.
<a name="colorinverted">color-inverted</a> #t The 'invert' button in the <a href="snd.html#colorbrowser">color</a> dialog, negated (hunh?!).
<a name="colorscale">color-scale</a> 0.5 The darkness setting in the <a href="snd.html#colorbrowser">color</a> dialog, divided by 100.
<a name="colormap">colormap</a> 0 Colormap choice for various displays (see the Color Editor).
This should be an integer between -1 and 15. The maps (from 0 to 15) are:
gray, hsv, hot, cool, bone, copper, pink, jet, prism, autumn, winter, spring,
summer, colorcube, flag, and lines. -1 means black and white.
<a name="corruptiontime">corruption-time</a> 60 Time (seconds) between background checks for changed file on disk (see <a href="#autoupdate">auto-update</a>).
If less than 0.0, this background process is turned off.
<b><a name="cursorcolor">cursor-color</a></b> red cursor color.
<a name="dacsize">dac-size</a> 256 Audio output buffer size (not always meaningful).
<b><a name="datacolor">data-color</a></b> black color of data in unselected graph.
<a name="defaultamp">default-amp</a> 1.0 These 'default' settings refer to the value given the control
panel widgets when a sound is opened. <i>default-amp</i> is the
amplitude setting. See <a href="#sndamp">amp</a>).
<a name="defaultcontrast">default-contrast</a> 0.0 Initial contrast value.
<a name="defaultcontrastamp">default-contrast-amp</a> 1.0 Initial contrast scaler (see <a href="#sndcontrastamp">contrast-amp</a>).
<a name="defaultcontrasting">default-contrasting</a> #f Initial contrast button value (<a href="#sndcontrasting">contrasting</a>).
<a name="defaultexpand">default-expand</a> 1.0 Initial expand value (<a href="#sndexpand">expand</a>).
<a name="defaultexpandhop">default-expand-hop</a> 0.05 Initial expand hop value (<a href="#sndexpandhop">expand-hop</a>).
<a name="defaultexpandlength">default-expand-length</a> 0.15 Initial expand segment length (<a href="#sndexpandlength">expand-length</a>).
<a name="defaultexpandramp">default-expand-ramp</a> 0.4 Initial expand ramp length (<a href="#sndexpandramp">expand-ramp</a>).
<a name="defaultexpanding">default-expanding</a> #f Initial value of expand button (<a href="#sndexpanding">expanding</a>).
<a name="defaultfilterorder">default-filter-order</a> 20 Initial control panel filter order (<a href="#sndfilterorder">filter-order</a>).
<a name="defaultfiltering">default-filtering</a> #f Initial filter button value (<a href="#sndfiltering">filtering</a>).
<a name="defaultoutputtype">default-output-type</a> <i>next-sound-file</i>
The default header type when a new or temporary file is created (<a href="snd.html#Xdefaultoutputtype">defaultOutputType</a> resource).
<a name="defaultreverbfeedback">default-reverb-feedback</a> 1.09 Initial reverb feedback coefficient (<a href="#sndreverbfeedback">reverb-feedback</a>).
<a name="defaultreverblength">default-reverb-length</a> 1.0 Initial reverb delay length scaler (<a href="#sndreverblength">reverb-length</a>).
This scales the length of all the delay lines used in the reverberator,
so higher numbers give longer initial delays and a more cavernous
effect. In the control panel it is the scaler labelled "len:".
<a name="defaultreverblowpass">default-reverb-lowpass</a> 0.7 Initial reverb lowpass coefficient (<a href="#sndreverblowpass">reverb-lowpass</a>).
<a name="defaultreverbscale">default-reverb-scale</a> 0.0 Initial value of the reverb volume scaler (<a href="#sndreverbscale">reverb-scale</a>).
<a name="defaultreverbing">default-reverbing</a> #f Initial reverb button value (<a href="#sndreverbing">reverbing</a>).
<a name="defaultspeed">default-speed</a> 1.0 Initial speed (srate) scaler value (<a href="#sndspeed">speed</a>).
<a name="dotsize">dot-size</a> 1 Size in pixels of dots when graphing with dots (see also examp.scm auto-dot function).
<a name="edithistorywidth">edit-history-width</a> 1 width (pixels) of edit history portion of channel pane.
<a name="envedbase">enved-base</a> 1.0 <a href="snd.html#editenvelope">Envelope editor</a> exponential base value
<a name="envedclipping">enved-clipping</a> #f <a href="snd.html#editenvelope">Envelope editor</a> 'clip' button
If clipping, the motion of the mouse is restricted to the current graph bounds.
<a name="enveddBing">enved-dBing</a> #f <a href="snd.html#editenvelope">Envelope editor</a> 'dB' button
<a name="envedexping">enved-exping</a> #f <a href="snd.html#editenvelope">Envelope editor</a> 'exp' and 'lin' buttons
If exping, the connecting segments use exponential curves rather than straight lines.
<a name="envedpower">enved-power</a> 3.0 <a href="snd.html#editenvelope">Envelope editor</a> base scale range (9.0^power).
<a name="envedtarget">enved-target</a> <i>amplitude-env</i>
Determines how the envelope is applied to the current data
This chooses one of the 'amp', 'flt', and 'src' buttons in the <a href="snd.html#editenvelope">Envelope editor</a>.
The other (named constant) choices are <i>srate-env</i> and <i>spectrum-env</i>.
<b><a name="envedwaveformcolor">enved-waveform-color</a></b> blue color of waveform displayed in envelope editor.
<a name="envedwaving">enved-waving</a> #f <a href="snd.html#editenvelope">Envelope editor</a> 'wave' button
The wave shown is the time domain display, even when filtering.
<a name="epsfile">eps-file</a> "snd.eps" Name of the Postscript file produced by the <a href="snd.html#printfile">File Print</a> option.
See also the <a href="#epsresource">epsFile</a> resource.
<a name="fftbeta">fft-beta</a> 0.0 The fft data <a href="snd.html#Xfftbeta">window parameter</a>, if relevant. If any of the FFT
variables is set to a new value, call <a href="#sndupdateffts">update-ffts</a> to see the effect.
<a name="fftlogfrequency">fft-log-frequency</a> #f If #t, the spectrum frequency axis is logarithmic, not linear.
<a name="fftlogmagnitude">fft-log-magnitude</a> #f If #t, the spectrum magnitude axis is in decibels.
<a name="lfftsize">fft-size</a> 256 FFT size.
<a name="lfftstyle">fft-style</a> <i>normal-fft</i>
The other choices are <i>sonogram</i> and <i>spectrogram</i>.
<a name="lfftwindow">fft-window</a> <i>blackman2-window</i>
FFT data window. See the long list <a href="#fftwindowchoices">above</a> for other choices.
<a name="filterenvorder">filter-env-order</a> 40 The order of the Envelope editor's FIR filter.
<b><a name="filterwaveformcolor">filter-waveform-color</a></b> blue color of control panel filter waveform.
<a name="fitdataonopen">fit-data-on-open</a> #f If #t, the initial time-domain display of a sound shows
its entire duration, with the Y-axis set to show its maxamp.
<b><a name="graphcolor">graph-color</a></b> white background color of unselected graph.
<b><a name="graphcursor">graph-cursor</a></b> XC_crosshair (34) cursor displayed following mouse in graph
The cursors are declared in /usr/X11R6/include/X11/cursorfont.h or some such file.
<a name="graphstyle">graph-style</a> <i>graph-lines</i>
The other choices are <i>graph-dots</i>, <i>graph-filled</i> etc.
<b><a name="highlightcolor">highlight-color</a></b> ivory1 highlighting color.
<a name="initialx0">initial-x0</a> 0.0 Initial time domain window left bound (seconds).
<a name="initialx1">initial-x1</a> 0.1 Same, but on the right; actual x1 is the lesser of this and the sound's duration
<a name="initialy0">initial-y0</a> -1.0 Initial window y axis minimum.
<a name="initialy1">initial-y1</a> 1.0 Same, but maximum.
<a name="linesize">line-size</a> 128 Number of samples considered to be a 'line' (<a href="snd.html#cn">C-n</a> and <a href="snd.html#cp">C-p</a> commands).
<b><a name="listenercolor">listener-color</a></b> aliceblue background color of lisp listener.
<b><a name="listenerprompt">listener-prompt</a></b> ">" lisp listener prompt (a one-character string).
<b><a name="markcolor">mark-color</a></b> red color of mark indicator.
<a name="maxfftpeaks">max-fft-peaks</a> 100 Max number of fft peaks reported.
<a name="maxfftsize">max-fft-size</a> 0 In convolve-with, max size of in-memory fft (0 = limited only by malloc).
<a name="maxregions">max-regions</a> 16 Size of region stack.
<a name="memosound">memo-sound</a> #f When a sound file is opened, Snd looks for a file with the same name but with an appended
".scm" extension. If such a file is found, it is loaded automatically. The variable
<b>memo-sound</b> is set to the newly opened sound's index. This supports the "snd-memo"
feature in CLM, but can be used independently of CLM to store marks, selections, or whatever
that you want associated with a particular sound.
<a name="mindb">min-dB</a> -60.0 Sets the minimum dB value displayed in various graphs.
<a name="mixampscaler">mix-amp-scaler</a> 1.0 Multiplier on amp scales in mix consoles (see <a href="snd.html#mix-amp-scaler">mix consoles</a>).
<b><a name="mixcolor">mix-color</a></b> lightgreen color of mixer consoles.
<b><a name="mixfocuscolor">mix-focus-color</a></b> green color of selected mix consoles.
<a name="mixspeedscaler">mix-speed-scaler</a> 1.0 Multiplier on speed scales in mix consoles (<a href="snd.html#mix-speed-scaler">mix consoles</a>).
<a name="mixtemposcaler">mix-tempo-scaler</a> 1.0 Multiplier on tempo scales in group consoles.
<b><a name="mixwaveformcolor">mix-waveform-color</a></b> darkgray color of mix waveform.
<a name="mixwaveformheight">mix-waveform-height</a> 20 Max height (pixels) of mix waveforms (see <a href="#showmixwaveforms">show-mix-waveforms</a>).
<a name="mixergroupmax-out-chans">mixer-group-max-out-chans</a> 4 Maximum number of output scalers in mix console.
<a name="mixergroups">mixer-groups</a> 6 Number of mixer <a href="snd.html#groups">groups</a> available.
<a name="mixersavestatefile">mixer-save-state-file</a> ".snd-mixer" Name of file for save mixer state.
<a name="movies">movies</a> #t If #t, the mix graphs are updated constantly as the mouse drags the mix console.
<a name="normalizefft">normalize-fft</a> #t If #t, spectral data is normalized to 1.0 before display.
If #f, you get the raw data values, which can reflect amplitude changes. Snd tries
to choose a y axis limit that makes successive displays move smoothly.
<a name="normalizeonopen">normalize-on-open</a> #t When a new sound is added to the Snd window, the resultant
set of graphs can start to dangle off the bottom or end of the screen.
If <i>normalize-on-open</i> is #t, Snd tries to do something reasonable in this case.
<b><a name="positioncolor">position-color</a></b> ivory3 position slider color
<a name="prefixarg">prefix-arg</a> 0 This is the keyboard <a href="snd.html#kcu">C-u</a> style argument (named current-prefix-arg in Emacs).
<a name="previousfilessort">previous-files-sort</a> 0 Sort choice in files dialog (0=unsorted, 1=name, etc).
<a name="printlength">print-length</a> 12 In the listener, print-out of lists and vectors that are longer
than <i>print-length</i> is truncated.
<b><a name="pushedbuttoncolor">pushed-button-color</a></b> lightsteelblue1 color of pushed button.
<a name="rawchans">raw-chans</a> 1 The "raw-" variables refer to sound data interpretation choices made
when a sound is opened that appears to be headerless.
<i>raw-chans</i> sets the default number of channels.
<a name="rawformat">raw-format</a> <i>16-linear</i>
The default data format in a headerless sound. Other possibilities
are given <a href="#snd16linear">above</a>, or you can use the <a href="sndlib.html">Sndlib</a> macros directly.
<a name="rawsrate">raw-srate</a> 44100 The default headerless sound sampling rate.
<a name="rawtype">raw-type</a> <i>next-sound-file</i>
The default headerless file header type (for subsequent saves and so on).
Snd only writes NeXT/Sun, AIFF, RIFF ('wave'), IRCAM, or raw files; the
corresponding <a href="sndlib.html">Sndlib</a> macros are given <a href="#nextsoundfile">above</a>.
<a name="recorderautoload">recorder-autoload</a> #f The '<a href="snd.html#Xautoload">autoload</a>' button in the recorder dialog.
<a name="recorderbuffersize">recorder-buffer-size</a> 4096 The size of the recorder input buffer (there's a trade-off
between responsiveness and clicks in some cases).
<a name="recorderfile">recorder-file</a> nil Default recorder output file name.
<a name="recorderinformat">recorder-in-format</a> 16-bit linear
Incoming data format for the recorder. It's not currently safe to mess with this.
It defaults to the host byte order.
<a name="recordermaxduration">recorder-max-duration</a> 1000000.0 Recorder max output file length.
<a name="recorderoutchans">recorder-out-chans</a> 2 Recorder output file channels.
<a name="recorderoutformat">recorder-out-format</a> same as <a href="#recorderinformat">recorder-in-format</a>
<a name="recordersrate">recorder-srate</a> 22050 Recorder sampling rate.
<a name="recordertrigger">recorder-trigger</a> 0.0 Recorder auto-trigger value.
<a name="reverbdecay">reverb-decay</a> 1.0 The length (seconds) of the reverberation after the sound has finished.
The sound-local (<a href="snd.html#controls">control panel</a>) version of this is <a href="#sndreverblength">reverb-length</a>.
<a name="savestateonexit">save-state-on-exit</a> #f If #t, Snd saves its current state in <a href="#lsavestatefile">save-state-file</a>.
<a name="lsavestatefile">save-state-file</a> "saved-snd.scm" The default <a href="snd.html#savedstate">saved state</a> file name.
<b><a name="selecteddatacolor">selected-data-color</a></b> black color of data in currently selected graph.
<b><a name="selectedgraphcolor">selected-graph-color</a></b> white background color of currently selected graph.
<b><a name="selectioncolor">selection-color</a></b> lightsteelblue1 color of selected portion of graph.
<a name="showaxes">show-axes</a> #t If #t, display x and y axes. This is the 'Show axes' View menu option.
<i><a name="showedithistory">show-edit-history</a></i> #f (Motif 1 only) If #t, include edit history window in channel pane.
<a name="showfftpeaks">show-fft-peaks</a> #f If #t, fft peak information is included in the fft display.
(This is the 'peaks' button in the <a href="snd.html#viewfft">Transform</a> options dialog).
<a name="setshowmarks"></a><a name="showmarks">show-marks</a> #t If #t, marks are displayed. This is the '<a href="snd.html#marks">Show marks</a>' View menu option.
<a name="showmixconsoles">show-mix-consoles</a> #t If #t, mix consoles are displayed. This is the '<a href="snd.html#consoles">Show consoles</a>' View menu option.
<a name="showmixwaveforms">show-mix-waveforms</a> #t If #t, mixer console displays the waveform of the sound being mixed.
<a name="lshowselectiontransform">show-selection-transform</a> #f If #t, display the transform of the current active selection, if any.
<a name="showusagestats">show-usage-stats</a> #f If #t, show approximate memory and disk space usage of current edit trees.
<a name="setshowyzero"></a><a name="showyzero">show-y-zero</a> #f If #t, the y=0 axis is displayed. This is the '<a href="snd.html#viewy0">Show Y=0</a>' View menu option.
<a name="sincwidth">sinc-width</a> 10 Width (in samples) of the sampling rate conversion sinc interpolation.
The higher this number, the better the src low-pass filter, but the slower src runs.
If you use too low a setting, you can sometimes hear high frequency "whistles" leaking through.
To hear these on purpose, make a sine wave at (say) 55 Hz, then (src-sound '(0 3 1 1)) with sinc-width at 4.
<a name="spectrocutoff">spectro-cutoff</a> 1.0 The amount of the frequency domain to include in the spectrum display.
This number changes as you drag the frequency axis, for example. This is the
slider labelled '% of spectrum' in the View Orientation dialog.
<a name="spectrohop">spectro-hop</a> 4 The distance (samples) moved between successive spectrogram traces.
This is the slider labelled 'hop' in the Orientation dialog.
<a name="spectroxangle">spectro-x-angle</a> 90.0 Default spectrogram x-axis viewing angle.
<a name="spectroxscale">spectro-x-scale</a> 1.0 Default scaler (stretch) along the spectrogram x axis.
<a name="spectroyangle">spectro-y-angle</a> 0.0 Same for y-axis.
<a name="spectroyscale">spectro-y-scale</a> 1.0 Same for y-axis.
<a name="spectrozangle">spectro-z-angle</a> -2.0 Same for z-axis
<a name="spectrozscale">spectro-z-scale</a> 0.1 Same for z-axis. For all of these variables, the easiest way to
see what they refer to is to run the Orientation dialog with a spectrogram displayed.
<a name="lspeedstyle">speed-style</a> <i>speed-as-float</i>
In the control panel, the 'speed' control can be interpreted as a continuum
(<i>speed-as-float</i>), as a just-intonation ratio of relatively small integers
(<i>speed-as-ratio</i>) or as a step in a microtonal scale (<i>speed-as-semitone</i>).
The default is 12 tones to the octave. See the Speed style Options menu option.
<a name="speedtones">speed-tones</a> 12 The number of tones per octave in the <i>speed-as-semitone</i> speed style.
<a name="tempdir">temp-dir</a> nil Name of directory for temporary files. nil usually means "/var/tmp".
<b><a name="textfocuscolor">text-focus-color</a></b> white color of text field when it has focus.
<a name="ltransformtype">transform-type</a> <i>fourier-transform</i>
The spectrum transform type. Other types are given <a href="#fouriertransform">above</a>.
<a name="trapsegfault">trap-segfault</a> #t If #t, try to catch segfaults and continue anyway.
<a name="userawdefaults">use-raw-defaults</a> #f If #t, the "raw-" variables' values are used automatically
when a headerless file is encountered. If #f, Snd fires up the
raw file dialog to find out how to interpret the data.
<a name="verbosecursor">verbose-cursor</a> #f If #t, the cursor's position and other information is
constantly displayed in the minibuffer. This is the View menu's Verbose cursor option.
<a name="vufont">vu-font</a> nil The "vu-" variables refer to the VU meters in the recorder.
<i>vu-font</i> is the font used to label the meters. It is normally "courier".
<a name="vufontsize">vu-font-size</a> 1.0 This sets the recorder VU meter label font size.
<a name="vusize">vu-size</a> 1.0 This sets the overall size of the recorder VU meters.
<a name="wavelettype">wavelet-type</a> 0 If <i><a href="#ltransformtype">transform-type</a></i> is <i>wavelet-transform</i>, <i>wavelet-type</i> selects which
wavelet is used. The list of available wavelets is in the Transform Dialog.
There are currently 20 choices, so this variable goes from 0 to 19.
<a name="wavo">wavo</a> #f If #t, the time domain waveform is displayed as a '<a href="snd.html#wavogram">wavogram</a>'.
<a name="wavohop">wavo-hop</a> 3 This sets the distance upward between wavogram traces; that is,
the smaller this number, the more traces can be displayed.
<a name="wavotrace">wavo-trace</a> 64 This sets the length (samples) of each wavogram trace.
<a name="windowheight">window-height</a> 0 The current Snd window height in pixels.
<a name="windowwidth">window-width</a> 0 The current Snd window width in pixels.
<a name="windowx">window-x</a> -1 The current Snd window left side in pixels.
<a name="windowy">window-y</a> -1 The current Snd window upper side in pixels (X numbering starts at 0 at the top).
<a name="xaxisstyle">x-axis-style</a> <i>x-in-seconds</i>
The x axis labelling of the time domain waveform can be in seconds
(<i>x-in-seconds</i>), in samples (<i>x-in-samples</i>), or expressed
as a percentage of the overall duration (useful in envelope definitions).
The latter is <i>x-to-one</i>. This is the View menu 'X-axis units' option.
<a name="xmax">xmax</a> 0.0 Sets the x axis maximum (truncates the display if the sound is longer).
That is, you can display anything below <i>xmax</i> normally, but
Snd refuses to go past that point. Not sure why you'd want this...
The default of 0.0 turns off this feature.
<a name="xmin">xmin</a> 0.0 Sets the x axis minimum.
<a name="ymax">ymax</a> 1.0 Sets the y axis maximum (useful to narrow the range of slider action).
<a name="ymin">ymin</a> 1.0 Sets the y axis minimum.
<a name="zeropad">zero-pad</a> 0 fft zero pad size as a multiple of the fft size; (set-zero-pad 1) gives you
half data, half zeros.
<b><a name="zoomcolor">zoom-color</a></b> ivory4 zoom slider color.
<a name="setzoomfocusstyle"></a><a name="zoomfocusstyle">zoom-focus-style</a> <i>focus-active</i>
This determines what a zoom action focuses (centers) on. See <a href="snd.html#zoomoption">Zoom options</a>.
</font></pre><hr>
<h2><a name="sndfunctions">Functions</a></h2>
<p>These functions give lisp access to most of Snd's data structures and functions.
In the argument lists
below, <i>snd</i> as an argument refers to the sound's index, and defaults to the currently
selected sound. Similarly, <i>chn</i> is the channel number, starting from 0, and defaults
to the currently selected channel. So if there's only one sound active, and it has only
one channel, (cursor) (cursor 0), and (cursor 0 0) all refer to the same
thing.</p>
<pre>
<font size="2">
<a name="abort">abort</a> () drop into gdb
<b><a name="sndabort">abort?</a></b> () check for C-g to interrupt on-going computation (and let other UI events through).
<a name="activatelistener">activate-listener</a> () make listener active, even if not open.
<a name="sndactivesounds">active-sounds</a> () return number of currently active (displayed) sounds.
<a name="sndaddmark">add-mark</a> (sample <i>snd chn</i>) add mark at <i>sample</i>, returning mark id.
<a name="addsoundfileextension">add-sound-file-extension</a> (ext) add <i>ext</i> to the list of sound file extensions.
<b><a name="sndaddtomainmenu">add-to-main-menu</a></b> (menu-label) add new top-level menu named <i>menu-label</i>, return menu index.
(add-to-main-menu "Tools") -> 5
see examples in examp.scm.
<b><a name="sndaddtomenu">add-to-menu</a></b> (top-menu menu-label callback)
add menu <i>menu-label</i> to top-level menu whose index is
<i>top-menu</i> with the lisp callback string <i>callback</i>. The built-in
Snd menus are numbered from 0 ('File') to 4 ('Help'). see also <a href="#sndremovefrommenu">remove-from-menu</a>.
(<font color="#ff0000">add-to-menu</font> 5 "Denoise" "(report-in-minibuffer \"denoise\")")
<a name="sndamp">amp</a> (<i>snd</i>) return current amp (control panel slider) value.
<a name="sndappendtominibuffer">append-to-minibuffer</a> (msg <i>snd</i>) append <i>msg</i> to whatever is in <i>snd</i>'s minibuffer.
<a name="sndaudiooutputs">audio-outputs</a> (speakers headphones line-out) (Sun only) set which output devices are active.
<a name="sndautocorrelate">autocorrelate</a> (data) return (in place) autocorrelation of <i>data</i>
<a name="sndbackwardgraph">backward-graph</a> (<i>count</i>) move back (up or left) <i>count</i> graphs (C-x C-o).
<a name="sndbackwardmark">backward-mark</a> (<i>count</i>) move back <i>count</i> marks (C-j).
<a name="sndbackwardmix">backward-mix</a> (<i>count</i>) move back <i>count</i> mix consoles (C-x C-j).
<a name="sndbackwardsample">backward-sample</a> (<i>count</i>) move back <i>count</i> samples (C-b), return new cursor position.
<a name="sndbindkey">bind-key</a> (key state code <i>ignore-prefix</i>)
Cause <i>key</i> (an integer) with modifiers <i>state</i> to evaluate <i>code</i>.
as in the hook functions: (bind-key (char->integer #\a) 4 "(snd-print \"hi\"))")
The modifier state is a combination of shift: 1, control: 4, meta: 8, so this call
causes C-a to print "hi" in the lisp listener. The value returned should
be one of the <a href="#cursorchoices">cursor choices</a> telling Snd what action (if any) to take after
evaluating <i>code</i>. If <i>ignore-prefix</i> is #t, Snd does not repeat the key based
on the prefix argument (<a href="snd.html#kcu">C-u</a>) -- in this case, the <i>code</i> can examine <a href="#prefixarg">prefix-arg</a> if desired.
See examp.scm for several examples. (<i>code</i> can be a scheme function if Guile is loaded).
<b><a name="bomb">bomb</a></b> (<i>snd on</i>) display bomb icon in <i>snd's</i> minibuffer. If <i>on</i> (default #t) is #f, the bomb is erased.
<a name="callapply">call-apply</a> (<i>snd</i>) equivalent to pushing <i>snd</i>'s 'apply' button.
This can be used in conjunction with the various control panel variables:
(define expnd (lambda (amt) (set-expanding #t) (set-expand amt) (<font color="#ff0000">call-apply</font>))).
<b><a name="callplug">call-plug</a></b> (plug) invoke the plug as an editing operation.
<b><a name="callplugselection">call-plug-selection</a></b> (plug) invoke the plug as an editing operation over current selection.
<b><a name="sndchangemenulabel">change-menu-label</a></b> (top-menu old-label new-label)
<a name="sndchannels">channels</a> (<i>snd</i>) return number of channels in <i>snd</i>.
<a name="sndchans">chans</a> (<i>snd</i>) same as <i>channels</i> (the forgetful programmer's friend).
<a name="sndclearaudioinputs">clear-audio-inputs</a>() in Linux/OSS, try to reduce soundcard background racket.
<a name="sndclm">clm?</a> () return 1 if clm is loaded.
<a name="sndclose">close-sound</a> (<i>snd</i>) close <i>snd</i> (same as File menu Close).
<b><a name="sndclosesoundfile">close-sound-file</a></b> (fd bytes) close file updating header to report <i>bytes</i> bytes of data. (See <a href="#sndopensoundfile">open-sound-file</a>).
<b><a name="colorp">color?</a></b> (obj) return #t if <i>obj</i> is a color object (see <a href="#makecolor">make-color</a>).
<a name="sndcolordialog">color-dialog</a> () fire up the Color dialog.
<a name="sndcomment">comment</a> (<i>snd</i>) return <i>snd</i>'s comment, if any.
<a name="sndcontrast">contrast</a> (<i>snd</i>) return current <a href="snd.html#contrast">contrast</a> (control panel slider) value.
<a name="sndcontrastamp">contrast-amp</a> (<i>snd</i>) return <i>snd</i>'s <a href="snd.html#contrast">contrast-amp</a> (control panel variable).
<a name="sndcontrasting">contrasting</a> (<i>snd</i>) return #t if <i>snd</i> has <a href="snd.html#contrast">contrast</a> turned on (control panel)
<b><a name="sndconvolve">convolve-arrays</a></b> (rl1 rl2) convolve vectors <i>rl1</i> with <i>rl2</i>. Result returned in rl1.
rl1 should be large enough to hold the full convolution result.
As a special dispensation for forgetful users, if rl1 is a file
name and rl2 is not a vector, <i>convolve-with</i> is called instead.
<a name="sndconvolvewith">convolve-with</a> (file <i>amp snd chn</i>)
convolve <i>snd</i>'s channel <i>chn</i> (or the currently sync'd data)
with the data in the sound file <i>file</i>. If your machine is short on memory,
set <a href="#maxfftsize">max-fft-size</a> first. <i>amp</i> is the resultant peak amplitude
(leave <i>amp</i> unset, or set it to #f to get the unnormalized result).
<b>Convolve-with</b> in conjunction with <b>mix</b> can provide high-quality reverb:
(define conrev
(lambda (impulse amp)
(<font color="#ff0000">convolve-with</font> impulse amp)
(save-sound-as "reverb.snd") ;this extra step so mix console scalers set reverb amount
(revert-sound)
(<font color="#ff0000">mix</font> "reverb.snd")))
<a name="sndconvolveselectionwith">convolve-selection-with</a> (file <i>amp</i>)
convolve the current selection with <i>file</i>.
<a name="lcountmatches">count-matches</a> (expr <i>sample snd chn</i>)
return how many samples satisfy the expression <i>expr</i>. <i>expr</i>
can be either a C expression (a string), or a Scheme function of one argument.
For example, (count-matches "y>.1") returns the number of samples
greater than .1. <i>sample</i> determines where to start the search.
The same thing in Scheme is: (count-matches (lambda (y) (> (or y 0.0) .1)))
<a name="sndcursor">cursor</a> (<i>snd chn</i>) return cursor location (samples) of channel <i>chn</i> of <i>snd</i>.
<a name="sndcursorfollowsplay">cursor-follows-play</a> (<i>snd</i>) return #t if cursor is following along in the sound as it plays.
<a name="sndcut">cut</a> () cut the current selection (a no-op if no active selection).
<a name="snddataformat">data-format</a> (<i>snd</i>) return <i>snd</i>'s data <a href="#snd16linear">format</a> (<a href="sndlib.html">sndlib</a>).
<a name="snddatalocation">data-location</a> (<i>snd</i>) return <i>snd</i>'s data location (bytes).
<a name="snddeletemark">delete-mark</a> (<i>id snd chn</i>) delete mark <i>id</i> in <i>snd</i>'s channel <i>chn</i> (- C-m).
<a name="snddeletemarks">delete-marks</a> (<i>snd chn</i>) delete all marks in <i>snd</i>'s channel <i>chn</i>
<a name="snddeleteregion">delete-region</a> (<i>reg</i>) delete region number <i>reg</i> (which defaults to 0). This removes the
region from the region stack; it doesn't edit the corresponding file(s).
<a name="snddeletesample">delete-sample</a> (samp <i>snd chn</i>) delete sample <i>samp</i> in <i>snd</i>'s channel <i>chn</i>.
<a name="snddeletesamples">delete-samples</a> (samp samps <i>snd chn</i>) delete <i>samps</i> samples starting at sample <i>samp</i>.
<b><a name="describeplug">describe-plug</a></b> (plug) describe <i>plug</i>
<a name="dismissalldialogs">dismiss-all-dialogs</a> () deactivate all dialogs.
<a name="sndeditheaderdialog">edit-header-dialog</a>() fire up Edit Header dialog.
<b><a name="sndedits">edits</a></b> (<i>snd chn</i>) return a vector with number of undo-able edits and redo-able edits.
<a name="sndenv">env-sound</a> (envelope <i>samp samps env-base snd chn</i>)
apply (in amplitude) <i>envelope</i> to <i>snd</i>'s channel <i>chn</i> starting
at sample <i>samp</i> for <i>samps</i> samples with connecting segments
based on <i>env-base</i>. <i>env-base</i> defaults to 1.0 (line segments).
<i>samp</i> defaults to 0. <i>samps</i> defaults to the full duration.
<i>envelope</i> is a list or vector containing the breakpoint values (as in CLM).
(env-sound '(0 0 1 1 2 0))
<a name="sndenvselection">env-selection</a> (envelope <i>env-base snd chn</i>)
apply <i>envelope</i> to the currently selected portion of <i>snd</i>'s channel <i>chn</i>.
<a name="sndenveddialog">enved-dialog</a> () fire up the Envelope editor dialog.
<a name="sndexit">exit</a> () exit Snd.
<a name="sndexpand">expand</a> (<i>snd</i>) return current <a href="snd.html#expand">expansion</a> amount (control panel).
<a name="sndexpandhop">expand-hop</a> (<i>snd</i>) return <i>snd</i>'s <a href="snd.html#expand">expansion</a> hop amount (seconds).
<a name="sndexpandlength">expand-length</a> (<i>snd</i>) return <i>snd</i>'s <a href="snd.html#expand">expansion</a> segment length (seconds).
<a name="sndexpandramp">expand-ramp</a> (<i>snd</i>) return <i>snd</i>'s <a href="snd.html#expand">expansion</a> ramp amount (between 0 and .5).
This affects the smoothness of the grain overlaps -- .001 is a rattling effect.
<a name="sndexpanding">expanding</a> (<i>snd</i>) return #t if <i>snd</i>'s expand button is on.
<b><a name="sndfft">fft</a></b> (rl im <i>sgn</i>) perform an FFT on <i>rl</i> and <i>im</i> (the real and imaginary parts
of the input data. <i>sgn</i> is 1 for an FFT, -1 for an inverse FFT; it defaults to 1.
<a name="sndffting">ffting</a> (<i>snd chn</i>) return #t if <i>snd</i>'s channel <i>chn</i> is displaying a spectrum (the 'f' button).
<a name="sndfiledialog">file-dialog</a> () fire up the <a href="snd.html#prevfiles">list</a> of current and previous files (not the file browser).
<a name="sndfilename">file-name</a> (<i>snd</i>) <i>snd</i>'s complete file name.
<a name="sndfilterenv">filter-env</a> (<i>snd</i>) <i>snd</i>'s <a href="snd.html#filter">filter</a> envelope (control panel).
<a name="sndfilterdbing">filter-dBing</a> (<i>snd</i>) <i>snd</i>'s <a href="snd.html#filter">filter</a> dB button state (control panel).
<a name="sndfilterorder">filter-order</a> (<i>snd</i>) <i>snd</i>'s <a href="snd.html#filter">filter</a> order (control panel).
<a name="sndfilter">filter-sound</a> (env order <i>snd chn</i>)
apply an FIR filter of order <i>order</i> and frequency response <i>env</i>
to <i>snd</i>'s channel <i>chn</i>.
<a name="sndfiltering">filtering</a> (<i>snd</i>) return #t if <i>snd</i> is filtering (control panel filter button).
<a name="sndfilterselection">filter-selection</a> (env order) apply an FIR filter of order <i>order</i> and frequency response <i>env</i>
to the current selection.
<a name="lfind">find</a> (c-expr <i>sample snd chn</i>)
find the sample that satisfies the C expression (a string) <i>c-expr</i>.
For example, (find "y>.1") looks for a sample greater than .1,
returning the sample number if one is found. <i>sample</i>
determines where to start the search. <i>c-expr</i> can also be a Scheme function.
<a name="sndfindmark">find-mark</a> (samp <i>snd chn</i>) return identifier of mark at sample <i>samp</i> or #f if none found.
This identifier is used in calls such as <a href="#sndmarksample">mark-sample</a>. Since marks
can move around during editing, a unique 'tag' is needed to refer to a particular mark.
<i>samp</i> can also be a string; in this case <i>find-mark</i> looks for a mark of that name.
<a name="sndfindsound">find-sound</a> (filename) returns the index of <i>filename</i> (used as <i>snd</i> throughout).
return #f if no sound is found that matches <i>filename</i>.
<b><a name="finishprogressreport">finish-progress-report</a></b> (<i>snd</i>) see <a href="#progressreport">progress-report</a>.
<a name="sndforwardgraph">forward-graph</a> (<i>count</i>) move forward (down or right) <i>count</i> graphs (C-x C-o).
<a name="sndforwardmark">forward-mark</a> (<i>count</i>) move forward <i>count</i> marks (C-j).
<a name="sndforwardmix">forward-mix</a> (<i>count</i>) move forward <i>count</i> mix consoles (C-x C-j).
<a name="sndforwardsample">forward-sample</a> (<i>count</i>) move forward <i>count</i> samples (C-f), return new cursor position.
<a name="sndframes">frames</a> (<i>snd chn</i>) return <i>chn</i>'s current length in samples.
<b><a name="sndgraph">graph</a></b> (data <i>xlabel x0 x1 y0 y1 snd chn</i>)
Display a graph of <i>data</i> in a separate display per channel. The x axis
is labelled <i>xlabel</i>, the x axis units go from x0 to x1 (default 0 to 1.0),
the y axis goes from y0 to y1 (default fits the data), and the display is
associated with channel <i>chn</i> in <i>snd</i>. <i>data</i> should be a vector.
(graph #(0 .1 .2 .3 .4 .3 .2 .1 0) "roof")
<a name="sndgraphing">graphing</a> (<i>snd chn</i>) return #t if graph data is being displayed.
<a name="sndgraph2ps">graph->ps</a> () create Postscript description of current display (see <a href="#epsfile">eps-file</a>).
<a name="sndgroupamp">group-amp</a> (<i>group chan</i>) return <i><a href="snd.html#groups">group</a></i>'s <i>chan</i>-th output amplitude.
<a name="sndgroupbeg">group-beg</a> (<i>group</i>) return <i><a href="snd.html#groups">group</a></i>'s begin time.
<a name="sndgroupdialog">group-dialog</a> () fire up the Groups browser.
<a name="sndgroupend">group-end</a> (<i>group</i>) return <i><a href="snd.html#groups">group</a></i>'s end time.
<a name="sndgroupok">group-ok?</a> (group) return #t if <i>group</i> is active (i.e. has a member mix).
<a name="sndgroupspeed">group-speed</a> (<i>group</i>) return <i><a href="snd.html#groups">group</a></i>'s speed.
<a name="sndgrouptempo">group-tempo</a> (<i>group</i>) return <i><a href="snd.html#groups">group</a></i>'s tempo.
<a name="sndgroups">groups</a> () return how many groups are currently active.
<a name="sndguile">guile?</a> () return 1 if guile is loaded. If you're running on a system where
several Snd's are running, some without Guile, and you want to include Guile-isms in
your initialization file, precede such code with (if (guile?)...)
<a name="sndheadertype">header-type</a> (<i>snd</i>) return (type . name)
<a name="sndhelpdialog">help-dialog</a> (subject help) fire up the help dialog with title <i>subject</i> and body <i>help</i>.
(help-dialog "xyzzy" "are we having fun?")
<a name="sndhidelistener">hide-listener</a> () close the lisp listener pane.
<b><a name="gin">in</a></b> (ms code) <i>ms</i> milliseconds from now, evaluate <i>code</i>, a string containing Scheme code, or a Scheme function (see examp.scm).
The <a name="autosave">auto-save</a> implementation in examp.scm uses <b>in</b>.
<a name="sndinsertfile">insert-sound</a> (file <i>in_chan snd chn</i>)
insert channel <i>in_chan</i> of <i>file</i> at the cursor in <i>snd</i>'s channel <i>chn</i>.
<a name="sndinsertregion">insert-region</a> (<i>beg reg snd chn</i>) insert region <i>reg</i> at sample <i>beg</i> in <i>snd</i>'s channel <i>chn</i>.
<a name="sndinsertsample">insert-sample</a> (samp value <i>snd chn</i>)
insert sample <i>value</i> at sample <i>samp</i> in <i>snd</i>'s channel <i>chn</i>.
<b><a name="sndinsertsamples">insert-samples</a></b> (samp samps data <i>snd chn</i>)
insert <i>samps</i> samples of <i>data</i> starting at sample <i>samp</i> in <i>snd</i>'s channel <i>chn</i>.
<i>data</i> can be a filename; Snd assumes any such file is temporary; it will be
deleted when no longer needed.
<a name="sndkey">key</a> (key state) execute the keyboard command <i>key</i> with modifier keys <i>state</i>.
shift: 1, control: 4, meta: 8 (see /usr/include/X11/X.h ControlMask et al).
<a name="sndleftsample">left-sample</a> (<i>snd chn</i>) return the position in samples of the left edge of the time domain
waveform for <i>snd</i>'s channel <i>chn</i>.
<b><a name="sndlist2vct">list->vct</a></b> (lst) return vct object with elements of list <i>lst</i>
<b><a name="loadcolormap">load-colormap</a></b> (colors) use colors in <i>colors</i> (a vector) as current colormap.
This is still kludgey, but the following shows how to use it:
(load "rgb.scm")
(define hi (make-vector 512)) ;use 64 if not using big colormaps
(do ((i 0 (+ i 4))) ((>= i 512))
(vector-set! hi i red) (vector-set! hi (+ i 1) blue)
(vector-set! hi (+ i 2) green) (vector-set! hi (+ i 3) black))
(<font color="#ff0000">load-colormap</font> hi)
<b><a name="makecolor">make-color</a></b> (r g b) return a color value using the red/green/blue values r/g/b -- each of these
is a float running from 0.0 to 1.0. (make-color 1.0 0.0 0.0) returns red.
<a name="sndmakeregion">make-region</a> (beg end <i>snd chn</i>)
create a new region spanning samples <i>beg</i> to <i>end</i> in <i>snd</i>'s channel <i>chn</i>.
<b><a name="makevct">make-vct</a></b> (len) create vct struct of size <i>len</i>.
<b><a name="mapacrossallchans">map-across-all-chans</a></b> (func <i>start end edname</i>) apply func to all open channels in parallel (see <a href="#scanning">Scanning Data</a>).
<b><a name="mapacrosschans">map-across-chans</a></b> (func <i>start end edname</i>) apply func to currently syncd channels in parallel
<b><a name="mapacrosssoundchans">map-across-sound-chans</a></b> (func <i>start end edname snd</i>) apply func to sound's channels in parallel
<b><a name="mapallchans">map-all-chans</a></b> (func <i>start end edname</i>) apply func to all open channels
<b><a name="mapchan">map-chan</a></b> (func <i>start end edname snd chn</i>) apply func to samples in current channel (see <a href="#scanning">Scanning Data</a>).
<b><a name="mapchans">map-chans</a></b> (func <i>start end edname</i>) apply func to currently syncd channels
<b><a name="mapsoundchan">map-sound-chans</a></b> (func <i>start end edname snd</i>) apply func to current sound's channels
<a name="sndmarkname">mark-name</a> (<i>id snd chn</i>) return name of mark <i>id</i>.
<a name="sndmarksample">mark-sample</a> (<i>id snd chn</i>) return position of mark <i>id</i>.
<a name="sndmarks">marks</a> (<i>snd chn</i>) return number of marks in <i>snd</i>'s channel <i>chn</i>.
<a name="sndmaxsounds">max-sounds</a> () return current size of sound array (grows as required, may contain holes).
<a name="sndmaxamp">maxamp</a> (<i>snd chn</i>) return max amp of <i>snd</i>'s channel <i>chn</i>.
<a name="sndmix">mix</a> (file <i>samp in_chan snd chn</i>)
mix <i>file</i>'s channel <i>in_chan</i> starting at <i>samp</i> in <i>snd</i>'s channel <i>chn</i>.
if only the <i>file</i> argument is given, this is equivalent to the File menu's Mix option.
<a name="sndmixamp">mix-amp</a> (<i>mix chan</i>) return amplitude of <i>mix</i>'s channel <i>chan</i>.
<a name="sndmixanchor">mix-anchor</a> (<i>mix</i>) return anchor position (within the mix) of <i>mix</i>.
<a name="sndmixgroups">mix-groups</a> (<i>mix</i>) return a bit-wise indication of the groups <i>mix</i> is participating in.
That is, group 0 is bit 0, etc. If <i>mix</i> is in groups 3 and 4, this returns 24.
<a name="sndmixlength">mix-length</a> (<i>mix</i>) return length in samples of <i>mix</i>.
<a name="sndmixposition">mix-position</a> (<i>mix</i>) return position (sample number) of <i>mix</i>.
<a name="sndmixregion">mix-region</a> (<i>samp scaler reg snd chn</i>)
Mix in region <i>reg</i> at sample <i>samp</i> (defaulting to the cursor sample),
scaled by <i>scaler</i> (defaults to 1.0) in <i>snd</i>'s channel <i>chn</i>.
<a name="sndmixspeed">mix-speed</a> (<i>mix</i>) return speed of <i>mix</i>.
<a name="sndmixstate">mix-state</a> (<i>mix</i>) return console state of <i>mix</i> (0=open, 1=title bar, 2=name[0]).
<a name="sndnew">new-sound</a> (name <i>header-type data-format srate chans</i>)
create a new (empty) sound named <i>name</i>. If the <i>type</i> and other
arguments are not specified, the raw file dialog is posted to get the
needed values which default to the current <a href="#rawtype">raw-type</a> and related settings.
<a name="sndnormalizeview">normalize-view</a> () normalize Snd display as in View menu <a href="snd.html#viewnormalize">Normalize</a> option.
<a name="sndok">ok?</a> (<i>snd</i>) return #t if <i>snd</i> (an index) is active.
<b><a name="sndrawopen">open-raw-sound</a></b> (name chans srate format) open <i>name</i> as a raw (no header) sound in the layout specified.
<a name="sndopen">open-sound</a> (name) open <i>name</i> as in File menu Open option.
<b><a name="sndopensoundfile">open-sound-file</a></b> (<i>name chans srate comment</i>)
Open (create) a sound file <i>name</i> (defaults to "test.snd" or "test.wav"). It is assumed
that the data will be floats in the native format (written by the caller interleaving channels),
and that the file will be closed by <a href="#sndclosesoundfile">close-sound-file</a>.
One simple way to write the data is to call <a href="#vct2soundfile">vct->sound-file</a>.
<a name="sndopenalternate">open-alternate-sound</a>(name) close the currently selected file, if any, and open <i>name</i>.
<a name="sndorientationdialog">orientation-dialog</a>() fire up the <a href="snd.html#orientationbrowser">Orientation</a> dialog.
<a name="overridedataformat">override-data-format</a>(format <i>snd</i>)force data format (ignore header)
<a name="overridedatalocation">override-data-location</a>(loc <i>snd</i>) force data location (ignore header)
<a name="overridedatasize">override-data-size</a>(samps <i>snd</i>) force data size (ignore header)
<a name="sndpeaks">peaks</a> (<i>file snd chn</i>) display fft peak information. If <i>file</i> is not null, write the information
to that file, else post it in a help window (where it can be selected and
pasted elsewhere). This function follows the state of the various 'sync'
buttons, given <i>snd</i> and <i>chn</i>.
<a name="sndplay">play</a> (<i>samp snd chn</i>) play <i>snd</i>'s channel <i>chn</i> starting from sample <i>samp</i>.
<a name="sndplayandwait">play-and-wait</a> (<i>samp snd chn</i>) play <i>snd</i>'s channel <i>chn</i> starting from sample <i>samp</i> and wait for it to finish.
<a name="sndplayregion">play-region</a> (<i>reg</i>) play region <i>reg</i>.
<a name="sndpreloaddirectory">preload-directory</a> (dir) preload sound files from directory <i>dir</i> (see -<a href="snd.html#minusp">p</a>).
<a name="sndpreloadfile">preload-file</a> (file) preload <i>file</i> (see View menu's <a href="snd.html#prevfiles">View Files</a> option).
<b><a name="progressreport">progress-report</a></b> (pct <i>name current-channel channels snd</i>)
The functions <i>start-progress-report</i>, <i>progress-report</i>, and <i>finish-progress-report</i>
handle the animated hour-glass icon used to amuse the idle user while some long
computation is allegedly in progress. The <i>pct</i> argument is a float between
0.0 and 1.0 which indicates how far along we are in the computation (there are
actually only 15 or 20 separate icons, so there's no point in calling this more
often than that). start-progress-report posts the initial icon, and finish-progress-report
removes it. If the icons are not available, a message is posted in <i>snd's</i> minibuffer
using <i>name</i> and so on to identify itself.
<a name="sndprotectregion">protect-region</a> (reg protect) protect/unprotect region <i>reg</i> from deletion in the <a href="snd.html#regionbrowser">region browser</a>.
<a name="sndreadonly">read-only</a> (<i>snd</i>) return #t if <i>snd</i> is read-only, #f otherwise.
<a name="sndrecorderdialog">recorder-dialog</a> () fire up <a href="snd.html#recordfile">recorder</a> window.
<a name="sndrecordergain">recorder-gain</a> (gain) return recorder input (soundcard-audio) gain <i>gain</i>.
<a name="sndrecorderinamp">recorder-in-amp</a> (in out) return recorder input channel <i>in</i> to output channel <i>out</i> amplitude.
<a name="sndrecorderoutamp">recorder-out-amp</a> (out) return recorder file output channel <i>out</i> amplitude.
<a name="sndredo">redo</a> (<i>edits snd chn</i>) redo <i>edits</i> edits (default is 1) in <i>snd</i>'s channel <i>chn</i>.
<a name="sndregionchans">region-chans</a> (<i>reg</i>) return number of channels in region <i>reg</i>.
<a name="sndregiondialog">region-dialog</a> () fire up <a href="snd.html#regionbrowser">region browser</a> (a no-op if no regions).
<a name="sndregionlength">region-length</a> (<i>reg</i>) return number of samples (per channel) in region <i>reg</i>.
<a name="sndregionmaxamp">region-maxamp</a> (<i>reg</i>) return maximum amplitude of region <i>reg</i>.
<a name="sndregionsample">region-sample</a> (<i>samp reg chn</i>) return value of sample <i>samp</i> in region <i>reg</i> in <i>snd</i>'s channel <i>chn</i>.
<b><a name="sndregionsamples">region-samples</a></b> (<i>samp samps reg chn</i>)
return vector of <i>samps</i> samples starting at <i>samp</i> in region <i>reg</i>'s channel <i>chn</i>.
<b><a name="sndregionsamples2vct">region-samples->vct</a></b> (<i>samp samps reg chn</i>)
return vct struct of <i>samps</i> samples starting at <i>samp</i> in region <i>reg</i>'s channel <i>chn</i>.
<a name="sndregionsrate">region-srate</a> (<i>reg</i>) return original (nominal) sampling rate of region <i>reg</i>.
<a name="sndregions">regions</a> () return number of regions in the region stack.
<b><a name="sndremovefrommenu">remove-from-menu</a></b> (top-menu menu-label)
remove menu <i>menu-label</i> from the top top-level menu whose index is <i>top-menu</i>.
<a name="sndreportinminibuffer">report-in-minibuffer</a> (msg <i>snd</i>) post <i>msg</i> in <i>snd</i>'s minibuffer.
<a name="sndcontrolpanelrestore">restore-control-panel</a> (<i>snd</i>) same as pushing the control panel '<a href="snd.html#savcontrols">r</a>' button.
<a name="sndreverbfeedback">reverb-feedback</a> (<i>snd</i>) return <i>snd</i>'s reverb feedback coefficient.
<a name="sndreverblength">reverb-length</a> (<i>snd</i>) return <a href="snd.html#reverb">reverb</a> delay line length scaler (control panel).
<a name="sndreverblowpass">reverb-lowpass</a> (<i>snd</i>) return reverb low pass filter coefficient.
<a name="sndreverbscale">reverb-scale</a> (<i>snd</i>) return <a href="snd.html#reverb">reverb</a> amount (control panel).
<a name="sndreverbing">reverbing</a> (<i>snd</i>) return #t if <i>snd</i>'s reverb button is on.
<a name="sndreverseselection">reverse-selection</a> () reverse data delineated by current selection.
<a name="sndreverse">reverse-sound</a> (<i>snd chn</i>) reverse data.
<a name="sndrevert">revert-sound</a> (<i>snd</i>) revert <i>snd</i> to saved state (undo all edits).
<a name="sndrightsample">right-sample</a> (<i>snd chn</i>) return position (samples) of right edge of time domain waveform.
<a name="sndsample">sample</a> (samp <i>snd chn</i>) return value of sample <i>samp</i> in <i>snd</i>'s channel <i>chn</i>.
<b><a name="sndsamples">samples</a></b> (<i>samp samps snd chn</i>)
return vector of <i>samps</i> samples starting at <i>samp</i> in <i>snd</i>'s channel <i>chn</i>.
<i>samp</i> defaults to 0. <i>samps</i> defaults to frames - samp.
<b><a name="samples2vct">samples->vct</a></b> (<i>samp samps snd chn</i>)
return vct struct with same data as in <b>samples</b> call above.
<a name="sndcontrolpanelsave">save-control-panel</a>(<i>snd</i>) same as pushing the control panel '<a href="snd.html#savcontrols">s</a>' button.
<b><a name="sndsaveedithistory">save-edit-history</a></b> (filename <i>snd chn</i>) save current edit list(s) in <i>filename</i>.
If <i>chn</i> is omitted, all <i>snd</i>'s channels are saved; if <i>snd</i> is omitted,
all edit list are saved. If the underlying files are not subsequently
changed, you can load this file to restore the current edit list state.
Returns #t if successful (file opened ok); #f is something went wrong.
<a name="sndsaveenvelopes">save-envelopes</a> (filename) save envelope editor contents in <i>filename</i>.
<a name="sndsavemacros">save-macros</a> () save <a href="snd.html#kbdmacros">keyboard macros</a> in Snd's init file (.snd).
<a name="sndsavemarks">save-marks</a> (<i>snd</i>) save <i>snd</i>'s marks, writing a file <name>.marks.
<a name="sndsaveoptions">save-options</a> (filename) save options in <i>filename</i>.
<a name="sndsaveregion">save-region</a> (reg filename <i>format</i>)
save region <i>reg</i> in <i>filename</i> in data format <i>format</i> (default snd-16-linear).
<a name="sndsaveselection">save-selection</a> (file <i>header-type data-format srate comment</i>)
save the currently selected data in <i>file</i>.
<a name="sndsave">save-sound</a> (<i>snd</i>) save <i>snd</i>; same as File menu's Save option.
<a name="sndsaveas">save-sound-as</a> (filename <i>snd header-type data-format srate</i>)
save <i>snd</i> as <i>filename</i> (same as File Save as option).
<a name="sndsavestate">save-state</a> (filename) save current state of Snd in <i>filename</i>.
<a name="sndscaleby">scale-by</a> (<i>scalers snd chn</i>)
<a href="snd.html#scaling">scale</a> amplitude of <i>snd</i> by <i>scalers</i>. Unlike most of these functions,
scale-by follows the 'sync' buttons and affects all currently sync'd channels.
<i>scalers</i> can be either a float or a vector of floats. In the latter case,
the values are used one by one, applying each as scale-by moves through the channels.
If 'sync' is off, channel <i>chn</i> is scaled (defaults to the currently selected channel).
<a name="sndscaleselectionby">scale-selection-by</a>(<i>scalers</i>) <a href="snd.html#scaling">scale</a> the current selection by <i>scalers</i> which can be either a float, or a vector of floats.
<a name="sndscaleselectionto">scale-selection-to</a>(<i>scalers</i>) <a href="snd.html#scaling">normalize</a> the current selection to <i>scalers</i> which can be either a float, or a vector of floats.
<a name="sndscaleto">scale-to</a> (<i>scalers snd chn</i>) <a href="snd.html#scaling">normalize</a> <i>snd</i> to <i>scalers</i>.
<b><a name="scanacrossallchans">scan-across-all-chans</a></b> (func <i>start end</i>) apply func to all open channels in parallel (see <a href="#scanning">Scanning Data</a>).
<b><a name="scanacrosschans">scan-across-chans</a></b> (func <i>start end</i>) apply func to currently syncd channels in parallel
<b><a name="scanacrosssoundchans">scan-across-sound-chans</a></b> (func <i>start end snd</i>) apply func to sound's channels in parallel
<b><a name="scanallchans">scan-all-chans</a></b> (func <i>start end</i>) apply func to all open channels
<b><a name="scanchan">scan-chan</a></b> (func <i>start end snd chn</i>) apply func to samples in current channel (see <a href="#scanning">Scanning Data</a>).
<b><a name="scanchans">scan-chans</a></b> (func <i>start end</i>) apply func to currently syncd channels
<b><a name="scansoundchan">scan-sound-chans</a></b> (func <i>start end snd</i>) apply func to current sound's channels
<a name="sndselectall">select-all</a> (<i>snd chn</i>) create a new region spanning all samples in <i>snd</i>'s channel <i>chn</i>.
<a name="sndselectchannel">select-channel</a> (<i>chn</i>) select channel <i>chn</i>.
<a name="sndselectregion">select-region</a> (<i>reg</i>) select region <i>reg</i> (i.e make it region 0).
<a name="sndselectsound">select-sound</a> (<i>snd</i>) select sound <i>snd</i>.
<a name="sndselectedchannel">selected-channel</a> (<i>snd</i>) return selected channel in <i>snd</i>.
<a name="sndselectedsound">selected-sound</a> () return selected sound (index).
<a name="selectionbeg">selection-beg</a> () return selection begin sample number.
<a name="selectionlength">selection-length</a> () return selection frames.
<b><a name="selectionmember">selection-member</a></b> (<i>snd chn</i>) return #t if snd's chn is member of active selection.
<b><a name="selectiontotemp">selection-to-temp</a></b> (<i>type format</i>) write out selected data as a temp file (see <a href="#programs">external programs</a>).
<b><a name="selectiontotemps">selection-to-temps</a></b>(<i>type format</i>) write out selected data as temp files (see <a href="#programs">external programs</a>).
;; The notation "(default #t)" below means the default value of the boolean argument
;; is #t; normally the default value of the associated boolean itself is #f. This
;; means that the command (set-contrasting) turns on contrasting, rather than
;; turning it off (doesn't that make more sense?).
<a name="sndsetamp">set-amp</a> (amp <i>snd</i>) set <i>snd</i>'s amp to <i>amp</i> (control panel).
<a name="sndsetcontrast">set-contrast</a> (contrast <i>snd</i>) set <i>snd</i>'s contrast amount to <i>contrast</i> (control panel).
<a name="sndsetcontrastamp">set-contrast-amp</a> (contrast-amp <i>snd</i>) set <i>snd</i>'s <i>contrast-amp</i> (control panel).
<a name="sndsetcontrasting">set-contrasting</a> (<i>contrasting snd</i>) set <i>snd</i>'s contrast button to <i>contrasting</i> (default #t).
<a name="sndsetcursor">set-cursor</a> (samp <i>snd chn</i>) place <i>snd</i>'s channel <i>chn</i>'s cursor at <i>samp</i>.
<a name="sndsetcursorfollowsplay">set-cursor-follows-play</a> (<i>cursor-follows snd</i>)
if #t, the cursor runs alongside the waveform as the sound if played (default #t).
<a name="sndsetexpand">set-expand</a> (expand-amount <i>snd</i>) set <i>snd</i>'s expansion amount to <i>expand-amount</i>.
<a name="sndsetexpandhop">set-expand-hop</a> (expand-hop <i>snd</i>) set <i>snd</i>'s expand-hop to <i>expand-hop</i>. This is the amount the
expander moves forward in the output on each segment. If hop > length,
you get a series of individual (isolated) grains.
<a name="sndsetexpandlength">set-expand-length</a> (expand-length <i>snd</i>) set <i>snd</i>'s expand-length (segment length) to <i>expand-length</i>.
This is the length (seconds) of each grain.
<a name="sndsetexpandramp">set-expand-ramp</a> (expand-ramp <i>snd</i>) set <i>snd</i>'s expand-ramp (ramp time) to <i>expand-ramp</i>.
<a name="sndsetexpanding">set-expanding</a> (<i>contrasting snd</i>) set <i>snd</i>'s expand button (default #t).
<a name="sndsetffting">set-ffting</a> (<i>on snd chn</i>) set <i>snd</i>'s channel <i>chn</i>'s 'f' button (default #t).
<a name="sndsetfilterdbing">set-filter-dBing</a> (dB <i>snd</i>) set <i>snd</i>'s filter dB button state.
<a name="sndsetfilterorder">set-filter-order</a> (filter-order <i>snd</i>) set <i>snd</i>'s filter-order.
<a name="sndsetfilterenv">set-filter-env</a> (filter-env <i>snd</i>) set <i>snd</i>'s filter frequency response envelope (a list).
<a name="sndsetfiltering">set-filtering</a> (filtering <i>snd</i>) set <i>snd</i>'s filter button (default #t).
<a name="sndsetgraphing">set-graphing</a> (<i>on snd chn</i>) if #t (1), <i>snd</i>'s channel <i>chn</i>'s displays any lisp-generated
graphics data (see <a href="#graphhook">graph-hook</a> and <a href="#sndgraph">graph</a>).
<a name="sndsetgroupamp">set-group-amp</a> (group chan amp) set <i>group</i>'s channel <i>chan</i> amplitude to <i>amp</i>.
<a name="sndsetgroupbeg">set-group-beg</a> (group beg) set <i>group</i>'s begin time to <i>beg</i> (moves all associated mixes).
<a name="sndsetgroupend">set-group-end</a> (group end) set <i>group</i>'s end time to <i>end</i> (moves all mixes to accomodate).
<a name="sndsetgroupspeed">set-group-speed</a> (group speed) set <i>group</i>'s speed to <i>speed</i>.
<a name="sndsetgrouptempo">set-group-tempo</a> (group tempo) set <i>group</i>'s tempo to <i>tempo</i>.
<a name="sndsetjustsounds">set-just-sounds</a> (<i>just-sounds</i>) set just-sounds button in file browser (default #t).
<a name="sndsetleftsample">set-left-sample</a> (samp <i>snd chn</i>) set <i>snd</i>'s <i>chn</i>'s left sample (the window bound) to <i>samp</i>.
<a name="sndsetmarkname">set-mark-name</a> (id name <i>snd chn</i>) set mark <i>id</i>'s name to <i>name</i> (in <i>snd</i>'s channel <i>chn</i>).
<a name="sndsetmarksample">set-mark-sample</a> (id sample <i>snd chn</i>) set mark <i>id</i>'s position to <i>sample</i> (in <i>snd</i>'s channel <i>chn</i>).
<b><a name="sndsetmenusensitive">set-menu-sensitive</a></b>(top-menu label sensitive)
<a name="sndsetmixamp">set-mix-amp</a> (mix chan amp) set <i>mix</i> channel <i>chan</i>'s amplitude to <i>amp</i>.
<a name="sndsetmixanchor">set-mix-anchor</a> (mix anchor) set <i>mix</i>'s anchor to <i>anchor</i>.
<a name="sndsetmixgroups">set-mix-groups</a> (mix groups) set <i>mix</i>'s associated groups (bit-wise) to <i>groups</i>.
<a name="sndsetmixlength">set-mix-length</a> (mix length) set <i>mix</i>'s length (samples) -- this can be dangerous!
<a name="sndsetmixposition">set-mix-position</a> (mix samp) set <i>mix</i>'s position (begin time in samples).
<a name="sndsetmixspeed">set-mix-speed</a> (mix speed) set <i>mix</i>'s speed.
<a name="sndsetmixstate">set-mix-state</a> (mix state) set <i>mix</i>'e title/console display state (0=open, 1=title, 2=name[0]).
<a name="sndsetreadonly">set-read-only</a> (<i>read-only snd</i>) set <i>snd</i>'s write-protection to be <i>read-only</i> (default #t).
<a name="sndsetrecordergain">set-recorder-gain</a>(gain amp) set recorder's hardware gain <i>gain</i> to <i>amp</i>.
<a name="sndsetrecorderinamp">set-recorder-in-amp</a>(in out amp) set recorder's input <i>in</i> to output <i>out</i> amp to <i>amp</i>.
<a name="sndsetrecorderoutamp">set-recorder-out-amp</a>(out amp) set recorder's file output channel <i>out</i> to <i>amp</i>.
<a name="sndsetreverbfeedback">set-reverb-feedback</a>(feedback <i>snd</i>) set <i>snd</i>'s reverb feedback coefficient to <i>feedback</i>.
<a name="sndsetreverblength">set-reverb-length</a>(length <i>snd</i>) set <i>snd</i>'s reverb delay line length scaler to <i>length</i>.
<a name="sndsetreverblowpass">set-reverb-lowpass</a>(lowpass <i>snd</i>) set <i>snd</i>'s lowpass coefficient to <i>lowpass</i>.
<a name="sndsetreverbscale">set-reverb-scale</a>(scale <i>snd</i>) set <i>snd</i>'s reverb amount to <i>scale</i>.
<a name="sndsetreverbing">set-reverbing</a> (<i>on snd</i>) set <i>snd</i>'s reverb button (default #t).
<a name="sndsetrightsample">set-right-sample</a> (samp <i>snd chn</i>) set <i>snd</i>'s channel <i>chn</i>'s right sample position to <i>samp</i>.
<a name="sndsetsample">set-sample</a> (samp value <i>snd chn</i>) set <i>snd</i>'s channel <i>chn</i>'s sample <i>samp</i> to <i>value</i>.
<b><a name="sndsetsamples">set-samples</a></b> (samp samps data <i>snd chn</i>) set <i>snd</i>'s channel <i>chn</i>'s samples satrting from
sample <i>samp</i> for <i>samps</i> samples to the values in <i>data</i>.
<font size="1">(If <i>samp</i> is beyond the end of the file, the file is first zero-padded to reach it).</font>
<i>data</i> can be a filename; Snd assumes any such file is temporary; it will be
deleted when no longer needed.
<a name="sndsetshowingcontrols">set-showing-controls</a> (<i>showing snd</i>) open or close the control panel (default #t).
<a name="sndsetspeed">set-speed</a> (speed <i>snd</i>) set <i>snd</i>'s speed to <i>speed</i> (control panel).
<a name="sndsetsquelchupdate">set-squelch-update</a>(<i>val snd chn</i>) if val is not #f, turn off graphics updates else turn them on.
<a name="sndsetsyncing">set-syncing</a> (<i>syncing snd</i>) set <i>snd</i>'s 'sync' button (default 1).
<a name="sndsetuniting">set-uniting</a> (<i>style snd</i>) set <i>snd</i>'s 'unite' button (default channels-combined).
<a name="sndsetwaving">set-waving</a> (<i>on snd chn</i>) set <i>snd</i>'s channel <i>chn</i>'s 'w' button (default #t).
<a name="sndsetxbounds">set-x-bounds</a> (x0 x1 <i>snd chn</i>) set the display window x axis bounds to x0 and x1 (seconds).
<a name="sndsetybounds">set-y-bounds</a> (<i>y0 y1 snd chn</i>) set the display window y axis bounds to y0 and y1. If y1 is
omitted, it is set from y0; if y0 is also omitted, the y axis bounds
are set to reflect the channel's current max amp.
<a name="sndshortfilename">short-file-name</a> (<i>snd</i>) return the brief (no directory) form of <i>snd</i>'s filename.
<a name="sndshowingcontrols">showing-controls</a> (<i>snd</i>) return #t if <i>snd</i>'s control panel is open.
<a name="sndshowlistener">show-listener</a> () open the lisp listener pane.
<a name="sndsmoothselection">smooth-selection</a> () apply a smoothing function to the current selection.
<a name="sndsmooth">smooth</a> (beg num <i>snd chn</i>) apply a smoothing function to the indicated data.
<a name="sndprint">snd-print</a> (str) display <i>str</i> in lisp listener, return <i>str</i>. (This is intended
as a debugging aid -- there's still nothing like a lowly print statement).
<b><a name="sndspectrum">snd-spectrum</a></b> (data window length <i>linear</i>)
return spectrum of <i>data</i> (type vct) using fft-window <i>win</i>.
length of data (and fft) is <i>length</i>.
<b><a name="soundtotemp">sound-to-temp</a></b> (<i>type format</i>) write out sync'd edit state as a temp file (see <a href="#programs">external programs</a>).
<b><a name="soundtotemps">sound-to-temps</a></b> (<i>type format</i>) write out sync'd edit state as temp files (see <a href="#programs">external programs</a>).
<a name="sndspeed">speed</a> (<i>snd</i>) return current <a href="snd.html#speed">speed</a> (control panel).
<a name="squelchupdate">squelch-update</a> (<i>snd chn</i>) return #t graphic updates are currently squelched (turned off).
<a name="sndsrate">srate</a> (<i>snd</i>) return <i>snd</i>'s sampling rate.
<a name="sndsrc">src-sound</a> (num-or-env <i>base</i>) sampling rate conversion using 'warped sinc interpolation'. The
argument <i>num-or-env</i> can be either a number or an envelope. In
the latter case, <i>base</i> sets the segment base (default is 1.0 = linear).
A value greater than 1.0 causes the sound to be transposed up.
A value less than 0.0 causes the sound to be reversed.
<a name="sndsrcselection">src-selection</a> (num-or-env <i>base</i>) same as <i>src</i> but applied to current selection.
<b><a name="startprogressreport">start-progress-report</a></b> (<i>snd</i>) see <a href="#progressreport">progress-report</a>.
<a name="sndstop">stop-playing</a> (<i>snd</i>) if <i>snd</i> is playing, stop.
<a name="sndsyncing">syncing</a> (<i>snd</i>) return <i>snd</i>'s 'sync' value (an integer, 0=off)
<b><a name="sndtempfilenames">temp-filenames</a></b> (data) return vector of temp file names (see <a href="#programs">external programs</a>).
<b><a name="temptoselection">temp-to-selection</a></b> (data name origin) read selected data from temp file (see <a href="#programs">external programs</a>).
<b><a name="tempstoselection">temps-to-selection</a></b>(data names origin) read selected data from temp files (see <a href="#programs">external programs</a>).
<b><a name="temptosound">temp-to-sound</a></b> (data name origin) read sync'd edit state from temp file (see <a href="#programs">external programs</a>).
<b><a name="tempstosound">temps-to-sound</a></b> (data names origin) read sync'd edit state from temp files (see <a href="#programs">external programs</a>).
<a name="sndtransformdialog">transform-dialog</a> () fire up the Transform window (Option menu's Transform Options choice).
<b><a name="sndtransformsample">transform-sample</a></b> (<i>bin slice snd chn</i>)
return the current value of the transform (if any) in <i>bin</i> and (if a
sonogram or spectrogram) <i>slice</i> in <i>snd</i>'s channel <i>chn</i>.
<b><a name="sndtransformsamples">transform-samples</a></b> (<i>snd chn</i>) return the transform data currently in <i>snd</i>'s channel <i>chn</i>.
<b><a name="transformsamples2vct">transform-samples->vct</a></b> (<i>snd chn</i>) return vct struct with the transform data currently in <i>snd</i>'s channel <i>chn</i>.
<a name="sndunbindkey">unbind-key</a> (key state) cause <i>key</i> with modifiers <i>state</i> to be a no-op.
<a name="sndundo">undo</a> (<i>edits snd chn</i>) undo <i>edits</i> edits (default 1) in <i>snd</i>'s channel <i>chn</i>.
<a name="snduniting">uniting</a> (<i>snd</i>) 0 if channels are not superimposed or combined ('unite' button is off).
<a name="sndupdate">update-sound</a> () update the currently selected file.
<a name="sndupdatefft">update-fft</a> (<i>snd chn</i>) recalculate <i>chn's</i> fft.
<a name="sndupdategraph">update-graph</a> (<i>snd chn</i>) redisplay <i>chn's</i> graph(s).
<a name="sndversion">version</a> () return Snd version (a string).
<b><a name="vctp">vct?</a></b> (vobj) return #t if <i>vobj</i> is a vct struct.
<b><a name="vctadd">vct-add!</a></b> (vobj1 vobj2) vobj1[i] += vobj2[i], returns vobj1.
<b><a name="vctcopy">vct-copy</a></b> (obj) return a copy of <i>obj</i>.
<b><a name="vctfill">vct-fill!</a></b> (vobj val) vobj[i] = val, returns vobj.
<b><a name="vctlength">vct-length</a></b> (vobj) return length of data array in vobj.
<b><a name="vctmultiply">vct-multiply!</a></b> (vobj1 vobj2) vobj1[i] *= vobj2[i], returns vobj1.
<b><a name="vctoffset">vct-offset!</a></b> (vobj val) vobj[i] += val, returns vobj.
<b><a name="vctref">vct-ref</a></b> (vobj pos) return value in vobj's data at location pos.
<b><a name="vctscale">vct-scale!</a></b> (vobj scl) vobj[i] *= scl, returns vobj.
<b><a name="vctset">vct-set!</a></b> (vobj pos val) set vobj's data at location pos to val.
<b><a name="vct2samples">vct->samples</a></b> (samp samps data <i>snd chn</i>) synonym for <a href="#sndsetsamples">set-samples</a>.
<b><a name="vct2soundfile">vct->sound-file</a></b> (fd vobj vals) write <i>vals</i> floats from <i>vobj</i> to <i>fd</i>.
<a name="sndview">view</a> (filename) open <i>filename</i> read-only.
<a name="sndwaving">waving</a> (<i>snd chn</i>) return the state of <i>snd</i>'s channel <i>chn</i>'s 'w' button.
<a name="sndxbounds">x-bounds</a> (<i>snd chn</i>) return (x0 . x1) -- current x axis time domain bounds in seconds.
<a name="sndxmhtml">XmHTML?</a> () return 1 if XmHTML is loaded.
<a name="sndybounds">y-bounds</a> (<i>snd chn</i>) return (y0 . y1) -- current y axis bounds.
<a name="sndyesornop">yes-or-no-p</a> (ques) modal error dialog, returns #t if user clicks "ok", otherwise #f.
<a name="ldefvar">defvar</a> (var val) same as (define var val) except that the envelope editor keeps track
of <i>var</i> thereafter and treats lists as envelopes. (<i>defvar</i> is a macro).
I'm using <i>defvar</i> here rather than some more perspicuous name like def-envelope
so that Snd and CLM can share envelope files.
<b><a name="savedefvar">update-var</a></b> (var-name) tell the envelope editor that some variable's value has changed
(once the envelope dialog is running it won't otherwise notice these
changes). <i>var-name</i> in this case is the name of the variable (a string).
<a name="lload">load</a> (file) load <i>file</i> (containing lisp code -- this is Scheme's load function if Guile is loaded).
<b>string-length</b> (str) length of <i>str</i>
</font></pre><hr>
<h2><a name="sndhooks">Hooks</a></h2>
<p>The hooks provide
a way to customize various situations that arise through user-interface
manipulations. Each is a list of functions to be called or #f.
See the <a href="#sndexamples">Examples</a> section and the file examp.scm for examples.
If there is more than one function attached to a hook, some of the hooks effectively
'or' the functions together (marked <b>or</b> below), others 'progn' the list (marked <b>progn</b>);
that is, to use less garish jargon,
some run through the list of functions, and if any function returns #t, the
hook immediately returns #t (ignoring the remaining functions), whereas in the other
case, the result returned by the hook is the result of the last function in the list.</p>
<pre>
<font size="2">
<a name="openhook">open-hook</a> (filename) called each time a file is opened (before the actual open). (<b>or</b>)
If it returns #t, the file is not opened.
<a name="closehook">close-hook</a> (snd) called each time a file is closed (before the close takes effect). (<b>or</b>)
If it returns #t, the file is not closed.
<a name="ffthook">fft-hook</a> (snd chn scaler) called just after an FFT (or spectrum) is calculated. (<b>progn</b>)
<a name="graphhook">graph-hook</a> (snd chn y0 y1) called each time a graph is updated or redisplayed. (<b>progn</b>)
If it returns #t, the display is not updated.
<a name="exithook">exit-hook</a> () called upon exit. (<b>or</b>)
If it returns #t, Snd does not exit.
<a name="starthook">start-hook</a> (filename) called upon start-up. (<b>or</b>)
If it returns #t, snd exits immediately.
<a name="mousepresshook">mouse-press-hook</a> (snd chn button state x y) called upon mouse button press within lisp graph. (<b>progn</b>)
<a name="mousereleasehook">mouse-release-hook</a> (snd chn button state x y) called upon mouse button release within lisp graph. (<b>progn</b>)
<a name="mousedraghook">mouse-drag-hook</a> (snd chn button state x y) called upon mouse motion (with button pressed) within lisp graph. (<b>progn</b>)
<a name="keypresshook">key-press-hook</a> (snd chn key state) called upon key press while mouse is in lisp graph. (<b>or</b>)
If it returns #t, the key press is not passed on to the main handler.
<a name="startplayinghook">start-playing-hook</a> (filename) called when a play request is triggered. (<b>or</b>)
If it returns #t, snd does not play.
<a name="stopplayinghook">stop-playing-hook</a> (snd) called when a sound finishes playing. (<b>or</b>)
<a name="markclickhook">mark-click-hook</a> (id) called when a mark is clicked, return #t to squelch normal message. (<b>progn</b>)
(add-hook! mark-click-hook
(lambda (n)
(help-dialog "Mark Help" (number->string (mark-sample n)))
#t))
</font></pre>
<p>To add a function to a hook, use add-hook!. To remove it, use remove-hook!. To clear a hook, use reset-hook!. (These are
functions supplied by Guile, and presumably someday they'll document them).
</p>
<hr>
<h2><a name="scanning">Scanning Data</a></h2>
<p>Sound files can be enormous, far larger than available memory, so vector access to
sample data (as in <a href="#sndsetsamples">set-samples</a>) is not always very useful.
(Each set-sample call is treated as a separate edit by Snd, but we would normally
want the entire operation to be handled as one edit).
In addition, the collection of available channels of data in the editor can present
a complicated access problem. The 14 scanning and mapping functions provide what
I hope is a straightforward answer to these problems. The "scan" functions do
not change any data; they simply run through data presenting it to the caller.
The "map" functions can change data, if they wish; the entire mapping call
becomes one large editing operation from the editor's point of view.
There are four ways to get at the editor's data: one channel, a sound's
channels, all currently open channels, and all currently sync'd channels.
There are two ways to march through this collection of channels: in series
(that is, one channel at a time), and in parallel (all channels at once);
the former is the default, and for the latter, I use the word "across".
So map-chan maps a function over a single channel; map-chans affects
the currently syncd channels (in series); map-across-chans affects the
same set of channels, but they are presented to the caller's function
as an array, each element of the array being a channel's sample at the
current location in the map; map-all-chans affects all currently open
channels; and finally, map-sound-chans affects all of a sound's channels,
independent of the 'sync' button. The 'scan' functions behave similarly.
In each case, an optional subsequence of the data can be requested via
'start' and 'end' points. If beg is #f, it defaults to 0; if end is #f,
it defaults to the end of the channel.
</p>
<pre>
<font size="2">
<b>map-across-all-chans</b> (func <i>start end edname</i>) apply func to all open channels in parallel
<b>map-across-chans</b> (func <i>start end edname</i>) apply func to currently syncd channels in parallel
<b>map-across-sound-chans</b> (func <i>start end edname snd</i>) apply func to sound's channels in parallel
<b>map-all-chans</b> (func <i>start end edname</i>) apply func to all open channels
<b>map-chan</b> (func <i>start end edname snd chn</i>) apply func to samples in current channel
<b>map-chans</b> (func <i>start end edname</i>) apply func to currently syncd channels
<b>map-sound-chans</b> (func <i>start end edname snd</i>) apply func to current sound's channels
<b>scan-across-all-chans</b> (func <i>start end</i>) apply func to all open channels in parallel
<b>scan-across-chans</b> (func <i>start end</i>) apply func to currently syncd channels in parallel
<b>scan-across-sound-chans</b> (func <i>start end snd</i>) apply func to sound's channels in parallel
<b>scan-all-chans</b> (func <i>start end</i>) apply func to all open channels
<b>scan-chan</b> (func <i>start end snd chn</i>) apply func to samples in current channel
<b>scan-chans</b> (func <i>start end</i>) apply func to currently syncd channels
<b>scan-sound-chans</b> (func <i>start end snd</i>) apply func to current sound's channels
</font></pre>
<p>In the case of the scanning operations, the function passed as the first argument takes
either the current sample (when scanning in series), or two arguments, the current
array of samples, and the array's length (when scanning in parallel). If the function
returns something other than #f, the scan is stopped and (in the series case) a list is returned to
the caller containing the non-#f value returned, the current sample position of the
scan, the current channel number, and the current sound index; in the parallel case, the current
sample position is returned. If the scan reaches
the end of its data without ever getting a value other than #f from its function,
it calls the function once more, passing #f as the first argument, and returns
whatever the function returns. So, for example, the following call scans the
current channel from sample 0 to the end looking for any sample greater than
.1:</p>
<pre>
<font size="2">
>(scan-chan (lambda (y) (> (or y 0.0) .1)))
(#t 4423 0 0)
</font></pre>
<p>In this case, we found such a sample at position 4423 of the first channel of the
sound whose index is 0. The '(or y 0.0)' form protects the '>' operation against
the #f passed in the case of failure. Here's an example of scanning across all channels,
returning the maximum sample value found:</p>
<pre>
<font size="2">
(define data-max
(lambda ()
(let ((maxval 0.0))
(lambda (data len)
(if data
(do ((i 0 (1+ i)))
((= i len) #f)
(let ((curval (abs (vector-ref data i))))
(if (> curval maxval) (set! maxval curval))))
maxval)))))
>(scan-across-all-chans (data-max))
0.492675779232
>(define every-sample?
(lambda (proc)
(let ((baddy (scan-chan (lambda (y) (if y (not (proc y)) #f)))))
(if baddy (set-cursor (cadr baddy)))
(not baddy))))
>(every-sample? (lambda (y) (< y .5)))
#t
</font></pre>
The function 'data-max' returns a closure that includes the function
we'll actually apply to the data (the inner lambda with the 'data'
and 'len' arguments), and the variable that tracks the
maxamp through the current call on 'scan-across-all-chans'.
We include the extra layer of 'lambda' so that a subsequent
call on '(data-max)' will start with a newly zeroed version
of 'maxval'.<p>
<p>The mapping operations are slightly more complicated because they
can edit the data. The fourth argument <i>edname</i> is the
name of the editing operation that will be reported by the
edit history mechanism. If none is given, it will default to
the name of the calling map function (which has little
to do with the actual edit). The other arguments to the mapping
calls are the same as corresponding scanning calls. The function
passed (and applied to the data) also takes the same arguments;
its return value is interpreted differently however. The applied
function can return #f, which means that the data passed in is
deleted (replaced by nothing), or a number which replaces the
current sample (in the parallel case this is an array of numbers),
or #t which halts the mapping operation, leaving trailing samples
unaffected, or a list, vct object, or vector of numbers (in the parallel case,
an embedded array as an element of the outer array); in this
case, the numbers are spliced into the edited version, effectively
replacing the current sample with any number of samples. At the
end of the map, the same function is called again with the first
argument #f, and any returned values are spliced in. This sounds
more complicated than it is! Basically, a map in series receives
each sample and returns either #f (no corresponding output), a number
(the new output), or a list of numbers; a map in parallel does the
same for each sample in the array passed to it.
If every value returned for a given channel is #f, the data is not edited.
This makes it possible to run through all current channels in parallel,
changing only one channel (or a subset of them).
</p>
<pre>
<font size="2">
>(map-chan (lambda (y) (if y (+ y .2) 'done)))
done
>(map-chan (lambda (y) (if y (cos y) )) #f #f "(cos y)")
#<unspecified>
>(map-chan (lambda (y) (if (and y (> y .1)) (list .1 .2 .3) y)))
#f
(define swap-channels
(lambda ()
(if (= (channels) 2)
(map-across-sound-chans
(lambda (data chans)
(if data
(let ((chan0-sample (vector-ref data 0)))
(vector-set! data 0 (vector-ref data 1))
(vector-set! data 1 chan0-sample)
data)
#f))
#f #f "swap-channels")
(string-append (short-file-name) " is not stereo!"))))
</font></pre>
<p>The edit history may show multiple entries for a given map application;
it may have to delete the old samples before
inserting the new samples. This means that you may have to repeat 'undo'
once or twice to get back to the state before the map operation. I'll
fix this someday...
Here's a slightly more involved example;
we define a function that finds silences and replaces them with
something:<p>
<pre>
<font size="2">
(define map-silence
(lambda (silence replacement)
(let ((sum-of-squares 0.0)
(buffer (make-vector 128 0.0))
(position 0)
(current-sample 0)
(chan-samples (frames)))
(lambda (y)
(if y
(let ((old-y (vector-ref buffer position)))
(set! sum-of-squares (- (+ sum-of-squares (* y y)) (* old-y old-y)))
(vector-set! buffer position y)
(set! position (1+ position))
(if (= position 128) (set! position 0))
(set! current-sample (1+ current-sample))
(if (> sum-of-squares silence)
(if (= current-sample chan-samples)
;; at end return trailing samples as long as it looks like sound
(let ((temp-buffer make-vector 128 0.0))
(do ((i 0 (1+ i)))
((= i 128) temp-buffer)
(let ((final-y (vector-ref buffer position)))
(vector-set! temp-buffer i (if (> sum-of-squares silence) final-y replacement))
(set! sum-of-squares (- sum-of-squares (* final-y final-y)))
(set! position (1+ position))
(if (= position 128) (set! position 0)))))
old-y)
replacement))
#f)))))
(map-chan (map-silence .01 0.0)) ; squelch background noise
(map-chan (map-silence .001 #f)) ; remove silences altogether
</font></pre>
<p>In case it isn't obvious, we're using <i>buffer</i> to hold a running
portion of the sound, and <i>sum-of-squares</i> to hold the sum of the squares
of all the samples in that portion. When the portion's sum falls below
the argument <i>silence</i>, we replace the current sample with <i>replacement</i>.
At the end, we flush out all the remaining samples awaiting output in <i>buffer</i>.</p>
<hr>
<h2><a name="writing">Writing Sound Files</a></h2>
<p>As with the mapping functions,
it is sometimes inconvenient to handle the entire current sound in one array, and the undo/redo
lists are easier to use if each actual edit is just one listed edit in Snd. If the mapping
functions don't provide the kind of access you want, you can also write sound files, then
tell Snd that the data in the file consitutes the new data in the sound currently being
edited.</p>
<pre>
<b>open-sound-file</b> (name chans srate comment) ; returns fd
<b>vct->sound-file</b> (fd vct vals) ; writes vals floats to fd
<b>close-sound-file</b> (fd vals)
</pre>
After opening the file, loop through the data calling samples->vct, deal with the
vct data as desired, write the samples to the file via vct->sound-file, then
when finished, close-sound-file. If the new data is to replace the old,
call set-samples with the new sound file's name; otherwise call insert-samples.
<hr>
<h2><a name="sndsndlib">Sndlib</a></h2>
<p>Most of the underlying sound library (<a href="sndlib.html">Sndlib</a>)
functions are available.
These return -1 if the file can't be found or some other error occurs.</p>
<pre>
<font size="2">
<a name="soundsamples">sound-samples</a> (filename) samples of sound according to header (can be incorrect)
<a name="soundframes">sound-frames</a> (filename) frames of sound according to header (can be incorrect)
<a name="soundduration">sound-duration</a> (filename) duration of sound in seconds
<a name="sounddatumsize">sound-datum-size</a> (filename) bytes per sample
<a name="sounddatalocation">sound-data-location</a> (filename) location of first sample (bytes)
<a name="soundchans">sound-chans</a> (filename) number of channels (samples are interleaved)
<a name="soundsrate">sound-srate</a> (filename) sampling rate
<a name="soundheadertype">sound-header-type</a> (filename) header type (e.g. <i>aiff-sound-file</i>)
<a name="sounddataformat">sound-data-format</a>(filename) data format (e.g. <i>16-linear</i>)
<a name="soundlength">sound-length</a> (filename) true file length (bytes)
<a name="soundtypespecifier">sound-type-specifier</a> (filename) original header type identifier
<a name="soundtypename">sound-type-name</a> (type) e.g. "AIFF"
<a name="soundformatname">sound-format-name</a> (format) e.g. "16-bit big endian linear"
<a name="soundcomment">sound-comment</a> (filename) header comment, if any
<a name="bytespersample">sound-bytes-per-sample</a> (format) bytes per sample
<a name="audioerror">audio-error</a> () returns error code indicated by preceding audio call
<a name="audioerror-name">audio-error-name</a>(err) string decription of error code
<a name="describeaudiostate">describe-audio</a> () describe audio hardware state (in help window)
<a name="setossbuffers">set-oss-buffers</a> (num size) in Linux (OSS) sets the number and size of the OSS "fragments"
</font></pre><hr>
<h2><a name="sndinitfile">The initialization file</a></h2>
<p>
When Snd starts up, it looks for an "initialization file", normally named "~/.snd". This optional file is
supposed to be just like emacs' .emacs file, containing any customizations or
extensions that you want loaded whenever Snd starts up. For example, say we
want the Snd window to start out 800x500, want to predefine an envelope named
"env1", and want the file selection box to
default to showing just sound files. We make ~/.snd and put in it:</p>
<pre>
(set-window-width 800)
(set-window-height 500)
(defvar env1 '(0 0 1 1 2 0))
(set-just-sounds 1)
</pre>
<p>
In addition, we could add our own analysis functions or whatever. In more
complex situations, you may want an initialization file particular to a given
machine, and global across users; in that case, the macro SND_CONF gives the
name of this global initialization file. At ccrma, it's "/etc/snd.conf". The
global file is read before the user's local file; both can, of course, be
absent. To override reading the global init file when Snd is invoked, include the switch -noglob.
To override the local init file, use -noinit. To set the global file name in
a makefile include (for example) -DSND_CONF='"/home/bil/cl/sndconf"' in CFLAGS.
</p>
<p>As a more extended example, here is my initialization file (or, I wish it
were this neat; the actual file is
more full of junk than my garage):</p>
<pre>
<font size="2">
(use-modules (ice-9 popen) (ice-9 debug))
(set-window-width 500)
(set-window-height 300)
(set-window-y 50)
(set-window-x 300)
(defvar env1 '(0 1 1 2 2 1))
(set-show-mix-waveforms #t)
(define shell
(lambda (cmd)
(let* ((str "")
(fil (open-pipe cmd "r")))
(do ((val (read-char fil) (read-char fil)))
((eof-object? val))
(set! str (string-append str (string val))))
(close-pipe fil)
str)))
(define beige (make-color 0.96 0.96 0.86))
(define blue (make-color 0 0 1))
(set-selected-graph-color beige)
(set-selected-data-color blue)
</font></pre><hr>
<h2><a name="sndexamples">Examples</a></h2>
<p>These examples are simplified to make the exposition cleaner; see examp.scm for more robust versions.
examp.scm also has examples that add and remove menu items, set variables via the special "F" keys,
perform correlation on the current data,
make a system call from the listener, and so on. The following function computes the rms amplitude of a region:</p>
<pre>
<font size="2">
(define region-rms
(lambda (n)
(let* ((data (<a href="#sndregionsamples">region-samples</a> 0 0 n))
(len (vector-length data))
(sum 0.0))
(do ((i 0 (1+ i))) ((= i len) (sqrt (/ sum len)))
(set! sum (+ sum (* (vector-ref data i) (vector-ref data i))))))))
</font></pre>
<p>To get the data currently displayed in the time domain window:</p>
<pre>
<font size="2">
(define <a name="windowsamples">window-samples</a>
(lambda ()
(let ((wl (<a href="#sndleftsample">left-sample</a>))
(wr (<a href="#sndrightsample">right-sample</a>)))
(<a href="#sndsamples">samples</a> wl (+ 1 (- wr wl))))))
</font></pre>
<p>Now we can use <i>window-samples</i> and <i>graph-hook</i>
to show a running graph of the
time domain energy:</p>
<pre>
<font size="2">
(define <a name="displayenergy">display-energy</a>
(lambda ()
(let* ((data (window-samples))
(len (vector-length data)))
(do ((i 0 (1+ i))) ((= i len))
(vector-set! data i (* (vector-ref data i) (vector-ref data i))))
(<a href="#sndgraph">graph</a> data))))
(set! <a href="#graphhook">graph-hook</a> "(display-energy)")
</font></pre>
<p>As the time domain window is moved, the lisp window automatically
updates itself. The same thing can show the spectral energy
(via <i>transform-samples</i>). Unfortunately, vector access and floating-point multiplies are
slow in Guile, so in a case like this, it will speed up
redisplay by at least an order of magnitude to use the 'vct'
functions. The functions graph, fft, insert-samples, and set-samples know about the vct
structure also, so we can rewrite display-energy:</p>
<pre>
<font size="2">
(define display-energy
(lambda (snd chn y0 y1)
(let* ((ls (left-sample snd chn))
(rs (right-sample snd chn))
(data (samples->vct ls (+ 1 (- rs ls)) snd chn))
(len (vc-length data))
(sr (srate snd)))
(vct-multiply! data data)
(graph data "energy" (/ ls sr) (/ rs sr) 0.0 (* y1 y1) snd chn))))
</font></pre>
<p>See examp.scm for more examples of using the vct structure.
Say we want Snd to refuse to exit if there are unsaved edits.</p>
<pre>
<font size="2">
(define <a name="unsavededits">unsaved-edits?</a>
(lambda (ind)
(and (< ind (max-sounds))
(or (and (ok? ind)
(> (vector-ref (edits ind) 0) 0)
(report-in-minibuffer "there are unsaved edits")
#t)
(unsaved-edits? (+ ind 1))))))
(add-hook! exit-hook (lambda () (report-in-minibuffer "") (unsaved-edits? 0)))
</font></pre>
<p>Here's somewhat brute-force code to play a sound a given number of times:</p>
<pre>
<font size="2">
(define plays 0)
(define pl1
(lambda (snd)
(if (= plays 0)
(remove-hook! stop-playing-hook pl1)
(begin
(set! plays (- plays 1))
(play 0 snd)))))
(define (pl n)
(set! plays (- n 1))
(add-hook! stop-playing-hook pl1)
(play))
(bind-key (char->integer #\p) 0 (lambda () (pl (max 1 (prefix-arg)))) #t)
</font></pre>
<p>Say we are so annoyed by the X/Motif file browser that we want
Snd to exit back to the shell if its file argument is not
found (this code obviously has to be in the init file):</p>
<pre>
<font size="2">
(define no-startup-file?
(lambda (ind file)
(if (= ind (max-sounds))
(begin
(write (string-append "can't open " file) (current-error-port))
(newline (current-error-port))
#t)
(if (ok? ind)
#f
(no-startup-file? (+ ind 1) file)))))
(add-hook! start-hook (lambda (file) (if (> (string-length file) 0) (no-startup-file? 0 file) #f)))
</font></pre>
<p>And just for completeness, here's an example of using the fft-hook.
Since fft's in Snd are asynchronous and interruptible, there are
times when the function <i>transform-samples</i> returns
nil (the fft in question is still in progress, for example).</p>
<pre>
<font size="2">
(define fft-peak
(lambda (snd chn scale)
(if (and (ffting) (= (fft-style) normal-fft))
(let ((samps (transform-samples snd chn)))
(if samps
(let* ((len (vector-length samps))
(mx (vector-ref samps 0))
(peak (do ((i 1 (+ i 1))) ((= i len) (/ (* 2 mx) (fft-size)))
(let ((val (abs (vector-ref samps i))))
(if (> val mx) (set! mx val))))))
(report-in-minibuffer (number->string peak) snd)))))
#f))
(add-hook! fft-hook fft-peak)
</font></pre>
<p>The following function uses the sndlib functions to mimic the 'info' popup menu option (see examp.scm for a version that uses format):</p>
<pre>
<font size="2">
<a name="sndinfo"></a>
(define info
(lambda (file)
(string-append
file
": chans: " (number->string (<a href="#soundchans">sound-chans</a> file))
", srate: " (number->string (<a href="#soundsrate">sound-srate</a> file))
", " (<a href="#soundtypename">sound-type-name</a> (<a href="#soundheadertype">sound-header-type</a> file))
", " (<a href="#soundformatname">sound-format-name</a> (<a href="#sounddataformat">sound-data-format</a> file))
", len: " (number->string
(/ (<a href="#soundsamples">sound-samples</a> file)
(* (<a href="#soundchans">sound-chans</a> file) (<a href="#soundsrate">sound-srate</a> file)))))))
</font></pre>
<img src="energy.gif" alt="picture of examp.scm in action">
<br><br>
<!-- I(plug-ins):O(call-plug-selection)(callplugselection) --><!-- I(plug-ins):A(snddynamic) --><!-- I(plug-ins):L(call-plug)(callplug) -->
<!-- I(open file):L(open-sound)(sndopen) -->
<!-- I(close file):L(close-sound)(sndclose) -->
<!-- I(save file):L(save-sound)(sndsave) -->
<!-- I(save file as):L(save-sound-as)(sndsaveas) -->
<!-- I(change format):L(save-sound-as)(sndsaveas) -->
<!-- I(revert file):L(revert-sound)(sndrevert) -->
<!-- I(open file read-only):L(view-sound)(sndview) -->
<!-- I(create new file):L(new-sound)(sndnew) -->
<!-- I(print file):L(graph->ps)(sndgraph2ps) -->
<!-- I(exit Snd):L(exit)(sndexit) -->
<!-- I(undo edit):L(undo)(sndundo) -->
<!-- I(redo edit):L(redo)(sndredo) -->
<!-- I(cut selection):L(cut)(sndcut) -->
<!-- I(insert selection):L(insert-region)(sndinsertregion) -->
<!-- I(play file):L(play, stop)(sndplay) -->
<!-- I(show marks):L(set-show-marks)(setshowmarks) -->
<!-- I(y=0 line):L(set-show-y-zero)(setshowyzero) -->
<!-- I(dots or lines):L(graph-style)(graphstyle) -->
<!-- I(combine channels):L(channel-style)(channelstyle) -->
<!-- I(normalize display):L(normalize-view)(sndnormalizeview) -->
<!-- I(control panel):L(set-showing-controls)(sndsetshowingcontrols) -->
<!-- I(fft peaks):L(show-fft-peaks)(showfftpeaks) -->
<!-- I(fft peaks):O(peaks)(sndpeaks) -->
<!-- I(fft/sono/spectrogram):L(fft-style)(lfftstyle) -->
<!-- I(zoom focus):L(set-zoom-focus-style)(setzoomfocusstyle) -->
<!-- I(fft in dB):L(fft-log-magnitude)(fftlogmagnitude) -->
<!-- I(fft log freq):L(fft-log-frequency)(fftlogfrequency) -->
<!-- I(axis fits data):L(fit-data-on-open)(fitdataonopen) --><!-- I(axis fits data):O(set-y-bounds)(sndsetybounds) -->
<!-- I(axis fits data):A(fitdataonopen) -->
<!-- I(select sound):L(select-sound)(sndselectsound) -->
<!-- I(multichannel ops):L(syncing)(sndsyncing) -->
<!-- I(save control state):L(control-panel-save)(sndcontrolpanelsave) -->
<!-- I(amp env):L(env-sound)(sndenv) -->
<!-- I(filter):L(filter-env)(sndfilterenv) -->
<!-- I(filter):M(Edit: Edit Env)(editenvelope) -->
<!-- I(axis bounds):L([xy]-bounds)(sndxbounds) -->
<!-- I(max amp):L(maxamp)(sndmaxamp) -->
<!-- I(max amp):A(sndmaxamp) -->
<!-- I(define mark):L(add-mark)(sndaddmark) -->
<!-- I(preload directory):L(preload-directory)(sndpreloaddirectory) -->
<!-- I(color):L(color-dialog)(sndcolordialog) -->
<!-- I(color):O(color-scale,color-cutoff)(colorscale) -->
<!-- I(orientation):L(orientation-dialog)(sndorientationdialog) -->
<!-- I(file lists):L(file-dialog)(sndfiledialog) -->
<!-- I(define selection):L(make-region)(sndmakeregion) -->
<!-- I(delete samples):L(delete-samples)(snddeletesamples) -->
<!-- I(temp directory):L(temp-dir)(tempdir) -->
<!-- I(continue session):L(load)(lload) -->
<!-- I(fft window):L(fft-window)(lfftwindow) -->
<!-- I(fft size):L(fft-size)(lfftsize) -->
<!-- I(fft window parameter):L(fft-beta)(fftbeta) -->
<!-- I(move cursor ahead):L(forward-sample)(sndforwardsample) -->
<!-- I(move cursor back):L(backward-sample)(sndbackwardsample) -->
<!-- I(file formats):L(raw-format)(rawformat) -->
<!-- I(insert zeros):L(insert-samples)(sndinsertsamples) -->
<!-- I(change samples):L(set-samples)(sndsetsamples) -->
<!-- I(srate conversion):L(src-sound)(sndsrc) --><!-- I(srate conversion):M(Edit: Edit Env)(editenvelope) -->
<!-- I(srate conversion):O(src-selection)(sndsrcselection) --><!-- I(srate conversion):A(sndsrc) -->
<!-- I(resample):L(src-sound)(sndsrc) --><!-- I(resample):M(Edit: Edit Env)(editenvelope) --><!-- I(resample):A(sndsrc) -->
<!-- I(resample):O(src-selection)(sndsrcselection) --><!-- I(reverse samples):A(sndreverse) -->
<!-- I(reverse samples):L(reverse-sound)(sndreverse) --><!-- I(reverse samples):O(reverse-selection)(sndreverseselection) -->
<!-- I(filter samples):L(filter-sound)(sndfilter) --><!-- I(filter samples):M(Edit: Edit Env)(editenvelope) -->
<!-- I(filter samples):O(filter-selection)(sndfilterselection) --><!-- I(filter samples):A(sndfilter) -->
<!-- I(save marks):L(save-marks)(sndsavemarks) -->
<!-- I(show edit list):L(show-edit-history)(showedithistory) -->
<!-- I(show freq domain):L(ffting)(sndffting) -->
<!-- I(show time domain):L(waving)(sndwaving) -->
<!-- I(keyboard macros):L(key)(sndkey) -->
<!-- I(delete mark):L(delete-mark)(snddeletemark) --> <!-- I(delete mark):O(delete-marks)(snddeletemarks) -->
<!-- I(sonogram):L(fft-style)(lfftstyle) -->
<!-- I(spectrogram):L(fft-style)(lfftstyle) -->
<!-- I(X axis units):L(x-axis-style)(xaxisstyle) -->
<!-- I(speed units):L(speed-style)(lspeedstyle) -->
<!-- I(fft normalization):L(normalize-fft)(normalizefft) -->
<!-- I(fft normalization):A(normalizefft) -->
<!-- I(speed units):O(speed-tones)(speedtones) -->
<!-- I(change srate):L(src-sound)(sndsrc) -->
<!-- I(edit env):L(enved-dialog)(sndenveddialog) -->
<!-- I(edit header):L(edit-header-dialog)(sndeditheaderdialog) -->
<!-- I(insert file):L(insert-sound)(sndinsertfile) -->
<!-- I(mix file):L(mix)(sndmix) -->
<!-- I(move mixed file):L(set-mix-position)(sndsetmixposition) -->
<!-- I(move to mark):L(forward-mark)(sndforwardmark) -->
<!-- I(move to mix):L(forward-mix)(sndforwardmix) -->
<!-- I(play selection):L(play-region)(sndplayregion) -->
<!-- I(update file):L(update)(sndupdate) -->
<!-- I(view envs):L(enved-dialog)(sndenveddialog) -->
<!-- I(play channel):L(play)(sndplay) -->
<!-- I(mix selection):L(mix-region)(sndmixregion) -->
<!-- I(interrupt Snd):L(stop)(sndstop) -->
<!-- I(move window back):L(set-left-sample)(sndsetleftsample) -->
<!-- I(move window ahead):L(set-right-sample)(sndsetrightsample) -->
<!-- I(numeric arguments):L(prefix-arg)(prefixarg) -->
<!-- I(change tempo):L(set-expand)(sndsetexpand) -->
<!-- I(wavelets):L(wavelet-type)(wavelettype) -->
<!-- I(save macros):L(save-macros)(sndsavemacros) -->
<!-- I(save selection):L(save-region)(sndsaveregion) --><!-- I(save selection):O(save-selection)(sndsaveselection) -->
<!-- I(examine regions):L(region-dialog)(sndregiondialog) -->
<!-- I(zoom window):L(set-x-bounds)(sndsetxbounds) -->
<!-- I(save options):L(save-options)(sndsaveoptions) -->
<!-- I(describe audio):A(describeaudiostate) --><!-- I(describe audio):L(describe-audio)(describeaudiostate) -->
<!-- I(abort command):L(abort?)(sndabort) -->
<!-- I(count matches):L(count-matches)(lcountmatches) --><!-- I(count matches):A(lcountmatches) -->
<!-- I(convolution):L(convolve)(sndconvolve) --><!-- I(convolution):A(sndconvolve) --><!-- I(convolution):O(convolve-with)(sndconvolvewith) -->
<!-- I(auto-save):A(autosave) --><!-- I(auto-save):O(examp.scm) -->
<!-- I(reverberate file):L(convolve-with)(sndconvolvewith) -->
<!-- I(record sound):L(recorder-dialog)(sndrecorderdialog) -->
<!-- I(describe file):L(info)(sndinfo) -->
<!-- I(change pitch):L(src-sound)(sndsrc) -->
<!-- I(change colors):L(make-color)(aboutcolors) --><!-- I(change colors):A(aboutcolors) --><!-- I(change colors):O(resources)(sndresources) -->
<hr>
<h2><a name="sndresources">Snd resources</a></h2>
<p>There are a few X-style resources that Snd explicity looks for (see Snd.ad):</p>
<pre>
initFile "~/.snd"
<a name="epsresource">epsFile</a> "snd.eps"
overwriteCheck 0
groups 6
autoResize 1
groupOutChans 4
horizontalPanes 0
buttonFont -*-times-medium-r-*-*-14-*-*-*-*-*-iso8859-1
boldbuttonFont -*-times-bold-r-*-*-14-*-*-*-*-*-iso8859-1
axisLabelFont -*-times-medium-r-normal-*-20-*-*-*-*-*-iso8859-1
axisNumbersFont -*-courier-medium-r-normal-*-14-*-*-*-*-*-iso8859-1
helpTextFont 9x15
listenerFont default
useSchemes none
highlightcolor ivory1
basiccolor ivory2
positioncolor ivory3
zoomcolor ivory4
cursorcolor red
selectioncolor lightsteelblue1
mixcolor lightgreen
mixfocuscolor green2
listenercolor aliceblue
envedwaveformcolor blue
filterwaveformcolor blue
mixwaveformcolor darkgray
graphcolor white
selectedgraphcolor white
datacolor black
selecteddatacolor black
markcolor red
pushedbuttoncolor lightsteelblue1
sashcolor lightgreen
</pre>
<p>If you have the XmHTML widget loaded, the following
resources are also available:</p>
<pre>
htmlDir "." ! also the variable html-dir
htmlWidth 600
htmlHeight 400
htmlFontSizeList "14,10,24,24,18,14,12"
htmlFixedFontSizeList "14,10"
</pre>
<p>You can experiment with other choices by
using the -xrm command line argument:</p>
<pre>
snd -xrm '*Highlightcolor: Red' oboe.snd
snd -xrm '*AxisNumbersFont: 6x10' oboe.snd
snd -xrm '*overwriteCheck: 1' oboe.snd
snd -xrm '*useSchemes: all' -xrm '*scheme: Pacific'
snd -xrm '*fontList: 9x15' oboe.snd
snd -xrm '*listenerFont: 6x10' oboe.snd
snd -xrm '*mixwaveformcolor: red' oboe.snd -notebook
snd oboe.snd pistol.snd -xrm '*graphcolor: beige' -xrm '*selecteddatacolor: red'
snd oboe.snd -title hiho -display hummer.hiho:0.0 -xrm '*chn-graph*backgroundPixmap: text.xpm'
</pre>
<p>The color names can be found in <a href="rgb.scm">rgb.scm</a>.
If you use SGI color schemes (the useSchemes resource), most of the color resources mentioned above are ignored
(the cursor and selection colors are never ignored). If color schemes are available
they're listed in /usr/lib/X11/schemes, probably -- it's unfortunate that
there is the language Scheme used by Guile, and the notion of an SGI color scheme -- there is
no connection between the two. The last example sets the window title to "hiho", rather than
"snd", displays the window on the machine hummer.hiho (presumably accessible over the net),
and tiles the graph backgrounds with the contents of text.xpm. To get the -geometry argument
to work, set the autoResize resource to 0:</p>
<pre>
snd oboe.snd -geometry 800x200 -xrm '*autoResize: 0'
</pre>
<p>
The <a name="Xautoresize"><i>AutoResize</i></a> resource determines how Snd acts when files
are added or removed from its overall display. The default (1)
causes Snd to expand or contract the main window's size to accomodate
the sounds (many people find this distracting); if <i>autoResize</i> is 0, the outer window size remains the
same, and the sounds try to fit as best they can. See also
the variable <a href="#autoresize">auto-resize</a>.
If <i>overwriteCheck</i> is 1, Snd asks before overwriting existing files.
The resource
<i>groupOutChans</i> sets the number of output channels in a mixer
group. Until the groups are created (upon invoking the mixer),
this number grows as needed to reflect the maximum number of
channels seen in any file read by Snd. The <a name="horizontalpanes"><i>horizontalPanes</i></a> resource
is equivalent to the -h flag; if 1, sounds are layed out
horizontally rather than vertically; if 2, you get a notebook
widget holding the sounds; if 3, the sounds are enclosed in
a scrolling widget. These special cases are not as fully
supported as the default vertical layout.</p>
<p><a name="aboutcolors"></a>The various colors are:</p>
<pre>
basiccolor default background color everywhere; basic-color
cursorcolor color of the cursor; cursor-color
datacolor unselected data color; data-color
envedwaveformcolor color of envelope editor waveform; enved-waveform-color
filterwaveformcolor color of control panel filter waveform; filter-waveform-color
graphcolor unselected channels' graph background; graph-color
highlightcolor highlighting here and there; highlight-color
listenercolor background color of the listener; listener-color
markcolor color of the mark indicator; mark-color
mixcolor used for mixer console titles; mix-color
mixfocuscolor mix within current group indicator; mix-focus-color
mixwaveformcolor color of mix waveform data; mix-waveform-color
positioncolor color of position sliders; position-color
pushedbuttoncolor color of pushed button; pushed-button-color
sashcolor color of paned window sash handles
selecteddatacolor color of the data in selected channel; selected-data-color
selectedgraphcolor background of selected channel's graph; selected-graph-color
selectioncolor color of an active selection; selection-color
textfocuscolor color of text field with focus; text-focus-color
zoomcolor color of zoom sliders; zoom-color
</pre>
<p>
Each of these colors can be set in Guile using the second name given above ("basic-color").
Colors are defined by calling <a href="#makecolor">make-color</a> with the three red/green/blue values,
each a float between 0.0 and 1.0. <code>(set-basic-color (make-color 1.0 0.0 0.0))</code> sets
the overall background color of Snd to red. <a href="rgb.scm">rgb.scm</a> defines all the standard X11 color names
(you probably don't want to load the whole thing; just use the names as needed).
</p>
<p>There are several other resources that set various widget sizes: zoomSliderWidth,
positionSliderWidth, toggleSize, sashSize, sashIndent, channelSashSize, channelSashIndent, and
envedPointSize. And several more color resources: whitecolor (list background),
blackcolor (recorder VU meter text), redcolor (buttons, VU clipping, etc),
greencolor (a few buttons),
yellowcolor (a few envelope editor buttons), lightbluecolor (the recorder), and lighterbluecolor (the fft option panel).
</p>
<!-- I(print file):O(epsFile resource)(epsresource) -->
<hr>
<h2><a name="sndswitches">Snd invocation flags</a></h2>
<p>The following flags are recognized by Snd (leaving aside all
the usual X-related flags like -xrm).</p>
<pre>
-h -horizontal layout sounds as horizontal panes
-v -vertical layout sounds vertically (the default)
-notebook layout sounds in a notebook widget (Motif 2.0 or later)
-scroller layout sounds vertically in a scroller widget
-separate layout sounds each in a separate window (lisp listener in main window)
--help print some help, version info, and exit
--version print version info
-noglob don't read SND_CONF, if any
-noinit don't read ~/.snd, if any
-p -preload <dir> preload sound files in directory <dir> (for example, snd -p .)
-l -load <file> load guile (scheme) code in <file> (for example, snd -l test.scm)
<file> -s <4 args> set initial graph window bounds
-e -eval expr evaluate expr
</pre>
<p>
The -e switch evaluates its argument as though it had been passed to M-X. The
initialization file, if any, is loaded first, then the arguments are processed
in order. For example</p>
<pre>
snd -e "(set-data-color (make-color 1 0 0))" oboe.snd
</pre>
<p>reads ~/.snd, if any, then sets the (unselected) data color to red, then opens oboe.snd.<p>
<pre>
./snd -eval '(begin (display (+ 1 2)) (exit))'
</pre>
<p>prints "3" and exits.</p>
<hr>
<h2><a name="snddynamic">Runtime modules, plug-ins, external programs</a></h2>
<p>It is possible to load your own C code into Snd at run-time, either
as a simple dynamically loaded module, or as a "plug-in"; you can
also use any external program from within Snd as an editing function.
</p>
<h3><a name="dynamic">Dynamically loaded modules</a></h3>
<p>You can import shared object files into Snd at any time.
You need to build Snd
with -lguile (that is, load it with the guile shared library, not libguile.a);
if the loader can't find libguile.so.2 (or whatever), add its directory to
your LD_LIBRARY_PATH; for example, if
it's on /usr/local/lib, <code>setenv LD_LIBRARY_PATH /usr/local/lib</code>.
Next add Guile wrappers to your C code:</p>
<pre>
<font size="2">
/* cscm.c */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <guile/gh.h>
int hiho (int a)
{ /* this is the function we want to call from Snd */
return(1+a);
}
SCM hiho_wrapper(SCM a)
{ /* this tells Guile how to interpret the arguments and return value of hiho */
return(gh_int2scm(hiho(gh_scm2int(a))));
}
void init_hiho()
{ /* this declares hiho within Guile calling the wrapper which calls the C function hiho */
gh_new_procedure1_0("hiho",hiho_wrapper);
}
</font></pre>
<p>
Next compile
your code into a shared object (this example is for Linux):
<pre>
cc -c cscm.c
ld -shared -o cscm.so cscm.o -lguile
</pre>
<p>Now go to Snd's lisp listener and,</p>
<pre>
(define lib (<font color="#0000ff">dynamic-link</font> "/home/bil/cl/cscm.so"))
(<font color="#0000ff">dynamic-call</font> "init_hiho" lib)
(hiho 3)
</pre>
<p>The function we actually want loaded into Guile here is "hiho".
We define a wrapper for it to handle the translation between
Guile (Scheme) variable types and C ("hiho_wrapper"), and
a procedure to define hiho in Guile ("init_hiho"). Once loaded
("dynamic-link"), we can call the initialization function
("dynamic-call"), and thereafter treat "hiho" as though
it had been defined in Guile/Snd to begin with. After both the
dynamic-link and dynamic-lib calls, the listener will
print "#<unspecified>" or something equally obscure to indicate
in its own peculiar way that all went well. M-x (hiho 4) will
print 5 in the minibuffer.
</p>
<p>Simple dynamically loaded modules like this, however, do
not have any better access to the editing aspects of Snd than
the equivalent Guile (Scheme) code. Perhaps the main reason
to work at this level is to speed up code that manipulates
large vectors:</p>
<pre>
<font size="2">
/* cscm.c */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <guile/gh.h>
typedef struct {int length; float *data;} vct;
SCM hiho (SCM data)
{ /* this is the function we want to call from Snd --
* it will return the sum of the squares of the samples */
int i;
float sum = 0.0;
vct *v = (vct *)gh_cdr(data);
for (i=0;i<v->length;i++) sum += (v->data[i] * v->data[i]);
return(gh_double2scm(sum));
}
void init_hiho() {gh_new_procedure1_0("hiho",hiho);}
</font></pre>
<p>Now in Snd, we'd call this with something like:</p>
<pre>
(hiho (samples->vct 0 200))
</pre>
<p>However, our function can't be interrupted, or applied to
a selection, or follow the sync buttons, and so on.
To make your editing function
act like any of the predefined Snd functions, tie it into Snd
as a "plug-in" (I got this terminology from Gimp).</p>
<hr>
<h3><a name="plugins">Plug-ins</a></h3>
<p>A plug-in is C code loadable at run-time (a shared object normally).
It contains a set of functions that implement the desired operation
and tell Snd how to handle it. A very brief example follows.</p>
<pre>
<font size="2">
/* scale.c */
#include "snd.h"
/* snd plug-ins are described in "snd-plugins.h" */
static int sample_ready = 0, current_sample = 0;
static int send_sample(int *new_value)
{
/* called by Snd when it wants the next sample of the new data */
if (sample_ready)
{
(*new_value) = current_sample;
sample_ready = 0;
return(PLUG_OK);
}
else return(PLUG_NO_DATA);
}
static int receive_sample(int value, int last_value)
{
/* called by Snd on each sample of the current data (the data being edited) */
/* last_value will be true only if this is the last sample of data in the current channel */
/* these values are 32-bit integers normally between -32768 and 32767 */
sample_ready = 1;
current_sample = value * 2; /* this is our scaling operation */
return(PLUG_OK);
}
static snd_plug *plug = NULL;
SCM snd_scale(void)
{
if (plug == NULL)
{
plug = (snd_plug *)calloc(1,sizeof(snd_plug));
/* we don't need any fanciness here, so several fields are null */
plug->init = NULL;
plug->quit = NULL;
plug->start_channel = NULL;
plug->end_channel = NULL;
plug->read_sample = receive_sample;
plug->write_sample = send_sample;
plug->name = "scale";
plug->documentation = "scales by 2";
plug->edit_name = "(snd-scale)";
<font color="#0000ff">scm_sysintern</font>("scale-plug",gh_ulong2scm((unsigned long)plug));
/* this tells Guile about the new plug -- we'll refer to it by the name "scale-plug" in Guile */
}
gh_eval_str("(<font color="#ff0000">call-plug</font> scale-plug)");
/* this actually calls the plug-in function from within Snd */
return(SCM_BOOL_F);
}
void init_snd_scale(void)
{
/* define "snd-scale" in Guile as a function of no arguments that calls snd_scale */
gh_new_procedure("snd-scale",snd_scale,0,0,0);
}
/* end of scale.c */
</font></pre>
<p>Now we need to compile and load this code, load it into Snd, and declare snd_scale:</p>
<pre>
cc scale.c -c -DHAVE_GUILE -o scale.o
ld -shared scale.o -o scale.so
</pre>
<p>Then in Snd (this could obviously be in your Snd initialization file):</p>
<pre>
(define lib (dynamic-link "/space/home/bil/cl/scale.so"))
(dynamic-call "init_snd_scale" lib)
</pre>
<p>If all went well, we've loaded our module and Snd can now call it
via M-x (snd-scale). Another more elaborate example is anoi.c, a denoiser by
Matti Koskinen, included in the Snd distribution.</p>
<p>The Guile functions that relate to plug-ins are:</p>
<pre>
<b>call-plug</b> (plug) invoke the plug as an editing operation.
<b>call-plug-selection</b> (plug) invoke the plug as an editing operation over current selection.
<b>describe-plug</b> (plug) describe plug
</pre>
<pre>
When a plug-in edit operation is invoked in Snd:
plug->init is called with a pointer to the global Snd state
if it returns PLUG_OK, we continue, else we print some message and exit the edit
plug->edit_name is saved as the edit-history's reference to the current operation
the 'sync' buttons are checked to collect the set of channels affected
a loop begins through the set of channels, one channel at a time
at any time, the operation may be aborted (by the user),
thereby setting state->stopped_explicitly to true
plug->start_channel is called with the current channel
if it returns PLUG_OK we continue, else we abort the
current edit and try to return to the pre-edit state
a loop begins through the current samples of the current channel
for each sample,
plug->read_sample is called with the current sample
and a flag indicating the end of the channel's data
if it returns PLUG_OK we continue, else we try to back out
plug->write_sample is called until it returns PLUG_NO_DATA
each returned sample (if any) is saved as the edited form of the current channel's data
for each new sample, write_sample should return PLUG_OK
if it returns PLUG_ERROR or PLUG_STOP, we abort the edit and try to back out
when this channel's data is done,
plug->end_channel is called with the channel
if it returns PLUG_OK, the channel is considered edited, and its edit history is updated
when all the channels have been edited,
plug->quit is called with the global state
</pre>
<p>If any of the functions is null, it is ignored (as though it had simply returned PLUG_OK).
If PLUG_ERROR is returned, Snd prints plug->error as its error message if it isn't null.
The guile functions call-plug, call-plug-selection, and describe-plug take the plug argument.
snd-plugins.h has a variety of macros to get information about the current channel and whatnot.
You can also call any of the Snd functions from your module via gh_eval_str:</p>
<pre>
gh_eval_str("(recorder-dialog)");
gh_eval_str("(open-sound \"oboe.snd\")");
srate = gh_scm2int(gh_eval_str("(srate)"));
</pre>
See also Matti Koskinen's <a href="http://www.sci.fi/~mjkoskin/snd-plugins.tar.gz">plugin package</a>)
and the echo plug-in below.</p>
<hr>
<h3><a name="programs">External Programs</a></h3>
<p>Any external program that knows about sound files can be used to perform editing operations
from Snd. You thereby get Snd's display, analysis, header and format conversion, and edit-tree support,
and can concentrate on the actual sound effect you're developing.
The original
impetus for Snd came from CLM, a large lisp-listener based program
which normally runs
without a graphical
user interface, and without any simple way to move around
in what Snd calls the edit history. Since interprocess
communication proved problematic in this case,
the communication path was simplified to
consist of little more than shared files, with CLM treated
as a batch program.
A nice side-effect of this is that any other program can fit
the same mold.</p>
<p>
For example, say we have a sound processing CLM instrument we like; it takes
two sound file names as its arguments, reading the first and writing the second.
In Snd we write the current edited state to a temporary file, start CLM, call the instrument
passing it the input and output filenames, then pass its output back
to Snd. Snd then replaces the current data with the data our instrument wrote, as if it had incorporated that
instrument as an editing operation from the beginning.</p>
<p>There are two choices as to what is being edited: either the full sound, or the current active selection
of it. And two choices as to how this data should be presented to the external program:
either as one, possibly multi-channel file, or as a set of mono files. So we have eight
functions (four to write, then four to read), as well as one function to get the
current temporary file names (as written by Snd, to be read by the external program):</p>
<pre>
<b>sound-to-temp</b> (<i>type format</i>) write out sync'd edit state as a temp file
<b>sound-to-temps</b> (<i>type format</i>) write out sync'd edit state as temp files
<b>selection-to-temp</b> (<i>type format</i>) write out selected data as a temp file
<b>selection-to-temps</b>(<i>type format</i>) write out selected data as temp files
<b>temp-filenames</b> (data) return vector of temp file names
<b>temp-to-selection</b> (data name origin) read selected data from temp file
<b>temps-to-selection</b>(data names origin) read selected data from temp files
<b>temp-to-sound</b> (data name origin) read sync'd edit state from temp file
<b>temps-to-sound</b> (data names origin) read sync'd edit state from temp files
</pre>
<p>Everything else is handled by scheme code. The <i>type</i> and <i>format</i>
arguments default to the currently selected sound's header type and data format,
but if your external program can only read a particular kind of file or data,
you can specify them here. The external program should not delete either input
or output files, and should not overwrite existing output files (Snd handles this
bookkeeping).
</p>
<h4><a name="stk">STK</a></h4>
<p><b><a href="www-ccrma.stanford.edu/CCRMA/Software/STK/">STK</a></b>
is a synthesis toolkit developed by Perry Cook and Gary Scavone.
Like many such programs, it reads a score file and produces an output file. We'll use it here
to replace the current sound with a clarinet tone:</p>
<pre><font size="2">
(define stk
(lambda ()
(let* ((str "")
(data (<font color="#ff0000">sound-to-temp</font>))
(fil (<font color="0000ff">open-pipe</font> "syntmono Clarinet -s /tmp/test < scores/hiho.ski" "r")))
(do ((val (read-char fil) (read-char fil)))
((eof-object? val))
(set! str (string-append str (string val))))
(<font color="#0000ff">close-pipe</font> fil)
(<font color="#ff0000">temp-to-sound</font> data "/tmp/test.snd" "(STK clarinet)")
str)))
</font></pre>
<p>hiho.ski is:</p>
<pre><font size="2">
NoteOn 0.000000 1 60 127.000000
NoteOff 0.126032 1 60 63.500000
</font></pre>
<p>The basic sequence is: <b>sound-to-temp</b> writes out the current (possibly edited)
state of the selected sound(s) in Snd as a temp file. <b>sound-to-temp</b> returns
an opaque object which we will later pass to <b>temp-to-sound</b> to complete the
edit. But first, we open a pipe, call STK as a batch job, and read in whatever
it prints out (so we can see how the call went). Then we call <b>temp-to-sound</b>
passing it the object mentioned earlier, the new filename (the data written by STK
that will replace the current data in Snd), and the associated edit-history reference
to the operation. In brief:</p>
<pre>
[sound | selection]-to-[temp | temps]
call external program on the data and write new data
[temp | temps]-to-[sound | selection]
</pre>
<p>But this function can't safely be called twice because it always writes
"test.snd", and it isn't very useful as an editing operation because it
completely ignores the current Snd data. The next steps are to write
our data using safe temporary filenames, and read the current data
using <b>temp-filenames</b>. We'll also apply this to the current
selection, rather than the full file. Since I don't know enough
about STK to get it to read an input file, I'll use Sox for the
next examples.</p>
<h4><a name="sox">Sox</a></h4>
<p>Sox is a widely available and well-known program for sound format conversions
and various sound effects. In this case, we'll read and write NeXT files, and
use Sox's copy "effect".</p>
<pre><font size="2">
(define sox
(lambda ()
(let ((data (<font color="#ff0000">selection-to-temp</font>)))
(if data
(let* ((str "")
(input-names (<font color="#ff0000">temp-filenames</font> data))
(output-name (string-append (<font color="#0000ff">tmpnam</font>) ".snd"))
(cmd (string-append
"sox -t .au \""
(<font color="#0000ff">vector-ref</font> input-names 0)
"\" -t .au \""
output-name
"\" copy"))
(fil (open-pipe cmd "r")))
(do ((val (read-char fil) (read-char fil)))
((eof-object? val))
(set! str (string-append str (string val))))
(close-pipe fil)
(<font color="#ff0000">temp-to-selection</font> data output-name "(sox copy)")
str)
(report-in-minibuffer "no current selection")))))
</font></pre>
<p>We use the Guile built-in function <i>tmpnam</i> to get an output
file name that doesn't collide with any existing file;
We then read the incoming filename that Snd wrote (<i>temp-filenames</i>),
and pass that to Sox. This is a very complicated no-op,
since Sox in this case merely copies its input to its output.
We're assuming NeXT/Sun files (the
"-t .au" business), and
we're blithely ignored the possibility that we might be
editing any number of sounds, each with any number of channels. To deal with
the latter, we need to notice how many mono files have been passed to us (in the
case of <i>sound-to-temps</i>), or our external program needs to be able
to handle a file with arbitrarily many channels (<i>sound-to-temp</i>).
In the next example, we'll loop through the mono files, processing each
in turn. We'll also start packaging up the boilerplate a bit.</p>
<pre><font size="2">
(define execute-and-wait
(lambda (cmd)
(let ((str "")
(fil (open-pipe cmd "r")))
(do ((val (read-char fil) (read-char fil)))
((eof-object? val))
(set! str (string-append str (string val))))
(close-pipe fil)
str)))
(define loop-through-files
(lambda (description make-cmd)
(let* ((data (<font color="#ff0000">sound-to-temps</font>))
(input-names (temp-filenames data))
(files (vector-length input-names))
(output-names (make-vector files "")))
(do ((i 0 (1+ i)))
((= i files))
(vector-set! output-names i (string-append (tmpnam) ".snd"))
(execute-and-wait (make-cmd (vector-ref input-names i) (vector-ref output-names i))))
(<font color="#ff0000">temps-to-sound</font> data output-names description))))
(define sox-1
(lambda ()
(loop-through-files
"(sox copy)"
(lambda (in out)
(string-append "sox -t .au \"" in "\" -t .au \"" out "\" copy")))))
</font></pre>
<p>Now our <i>sox</i> function can handle any number of files or
channels that might be sync'd together in Snd. In case it's not
obvious, the function <i>loop-through-files</i> takes as its second argument
a function of two arguments, and calls it on each file as we march
through the input file list, passing it the input and output file
names as arguments. It (<i>make-cmd</i>) puts together the actual
call on sox that we were making earlier. An equivalent using cp is:</p>
<pre><font size="2">
(define copyfile
(lambda ()
(loop-through-files
"(cp)"
(lambda (in out)
(string-append "cp " in " " out)))))
</font></pre>
<p>But we're still assuming NeXT/Sun format files, and we're throwing away the string
we so laboriously created. A more friendly function would display its progress.
</p>
<h4><a name="clm">CLM</a></h4>
<p>Reading, mixing, and writing sound files are no problem in CLM, but
it's unusual to run it as a batch program.
Assume for the moment we have loaded the CLM instruments we want (v.ins and jcrev.ins),
and have saved the image using ACL 5.0 in Linux. The CLM image is
invoked in this case with <code>lisp -I clm.dxl</code>. ACL provides
a way (<i>-e</i>) to evaluate lisp code from the command line, so
we'll use that along with the <i>exit</i> function to turn CLM
into a batch program. For example, we can reverberate the current data:</p>
<pre><font size="2">
(define reverb
(lambda (reverb-amount)
(loop-through-files
(string-append "(reverb " (number->string reverb-amount) ")")
(lambda (in out)
(string-append
"lisp -I clm.dxl "
"-e '(progn (restart-clm) "
" (with-sound (:play nil :output \"" out "\" :reverb jc-reverb) "
" (mix \"" in "\") "
" (mix \"" in "\" :output *reverb* :amplitude " (number->string reverb-amount) "))"
" (exit))'")))))
</font></pre>
<p>This is a call on CLM's <i>with-sound</i> with a reverberator
and two calls on <i>mix</i>, one for the direct signal, the
other for the reverb input. The with-sound form is wrapped up
in a progn that calls <i>restart-clm</i> (to make sure all dynamically
allocated entities are setup properly), the with-sound itself,
then <i>exit</i> to leave lisp (the latter is needed since we're
waiting for EOF in the <i>execute-and-wait</i> function).
The <i>reverb</i> function's argument sets the amount of
reverb, and we save that value in the edit-history descriptor.
Now, in Snd, <code>M-x (reverb .1)</code> reverbs the current
data and extends the edit-history list with the string "(reverb .1)".
This example also shows how to mix something into the current
data. For example, to add an fm-violin note starting at the
current cursor:
</p>
<pre><font size="2">
(define fm-violin
(lambda (dur frq amp)
(let* ((beg (/ (<font color="#ff0000">cursor</font>) (srate)))
(fmv-call (string-append "(fm-violin "
(number->string beg) " "
(number->string dur) " "
(number->string frq) " "
(number->string amp) ")")))
(loop-through-files
fmv-call
(lambda (in out)
(string-append
"lisp -I clm.dxl "
"-e '(progn (restart-clm) "
" (with-sound (:play nil :output \"" out "\") "
" (mix \"" in "\") "
fmv-call
" ) (exit))'"))))))
</font></pre>
<p>But if anything goes wrong, the whole process gets hung, since Lisp
drops into its error handler, and Snd is waiting for the Lisp job to
exit -- we have to go to a shell and kill the Lisp subjob!
So let's check for C-g in Snd, and send the subjob output to
Guile's "current-output-port" (whatever that is):</p>
<pre><font size="2">
(define read-or-run
(lambda (fil)
(let ((val (<font color="#0000ff">peek-char</font> fil)))
(or (and val (read-char fil))
(<font color="#ff0000">abort?</font>)
(read-or-run fil)))))
(define execute-and-wait
(lambda (cmd)
(let ((fil (open-pipe cmd "r")))
(do ((val (read-or-run fil) (read-or-run fil)))
((or (eq? val #t) (eof-object? val))
(eq? val #t))
(<font color="#0000ff">write-char</font> val (<font color="#0000ff">current-output-port</font>)))
(close-pipe fil))))
(define loop-through-files
(lambda (description make-cmd)
(let* ((data (sound-to-temps))
(input-names (temp-filenames data))
(files (vector-length input-names))
(output-names (make-vector files ""))
(stopped #f))
(do ((i 0 (1+ i)))
((or stopped (= i files)))
(vector-set! output-names i (string-append (tmpnam) ".snd"))
(set! stopped (execute-and-wait (make-cmd (vector-ref input-names i) (vector-ref output-names i)))))
(temps-to-sound data output-names description))))
</font></pre>
<p>If this is too ugly, we could probably use append-to-minibuffer instead
of write-char. In Clisp, use the -x switch without the exit function call.
Also, place the expression to be evaluated in double quotes, rather than
ACL's single quotes.
</p>
<hr>
<h2><a name="sndaswidget">Snd as a Widget</a></h2>
<p>To include the entire Snd editor as a widget in some other program,
first compile it with -DSND_AS_WIDGET. Then load it into your program,
using the procedure <b>snd_as_widget</b> to fire it up. The program
saw.c included with Snd is a very brief example.</p>
<pre>
void snd_as_widget(int argc, char **argv, XtAppContext app, Widget parent, Arg *caller_args, int caller_argn)
</pre>
<p>starts up the Snd editor in the widget <i>parent</i>, passing the outer Snd
form widget the arguments <i>caller_args</i> and <i>caller_argn</i>. The
enclosing application context is <i>app</i>. <i>parent</i> needs to
be realized at the time of the call, since Snd uses it to set up graphics
contexts and so on. <i>argc</i> and <i>argv</i> can be passed to
simulate a shell invocation of Snd. Remember that in this case, the
first string argument is expected to be the application name, and is
ignored by Snd.</p>
<hr>
<h2><a name="sndwithclm">Snd and the CLM module</a></h2>
<p>The files clm.c, clm.h, and clm2scm.c implement CLM (a Common Lisp Music V implementation
described in clm.html, available in clm-2.tar.gz at ccrma-ftp) as a Guile-loadable module.
You can have them loaded into Snd by including the <i>--with-clm</i> switch when running configure,
or by using -DWITH_MUS_MODULE with CLM_O_FILES in your makefile (see makefile.clm for an
example). Or, the CLM module can be loaded at any time as a shared library. In Linux, the
command sequence is something like:</p>
<pre>
cc clm.c -c -O2 -DHAVE_GUILE -DHAVE_SNDLIB -DLINUX
cc clm2scm.c -c -O2 -DHAVE_GUILE -DHAVE_SNDLIB -DLINUX
setenv LD_LIBRARY_PATH /usr/local/lib:.
ld io.o audio.o headers.o sound.o clm.o vct.o clm2scm.o -o clm.so -lc -lm -shared
</pre>
<p>This creates the shared library clm.so, and sets the LD_LIBRARY_PATH environment
variable to include the current directory (the "." at the end); now we start Snd,
and in the lisp listener:</p>
<pre>
(define clmlib (dynamic-link "clm.so"))
(dynamic-call "init_mus2scm_module" clmlib)
</pre>
You can see what a generator does, or a group of generators, by running them in the
lisp listener, and using the graph and spectrum functions. For example, say we have
these declarations in ~/.snd:
</p>
<pre>
(define data-size 1024)
(define data (make-vct data-size))
(define run
(lambda (fun)
(do ((i 0 (1+ i)))
((= i data-size))
(vct-set! data i (fun)))
(graph data)))
(define runf
(lambda (fun)
(do ((i 0 (1+ i)))
((= i data-size))
(vct-set! data i (fun)))
(graph (spectrum data blackman2-window data-size #t))))
</pre>
<p>Now we can open the listener, and type:<p>
<pre>
(define hi (make-oscil))
(run (lambda () (oscil hi)))
(define ho (make-oscil))
(runf (lambda () (oscil hi (* .5 (oscil ho)))))
</pre>
<p>Obviously, any CLM instrument or function can be used in this way
to edit sounds, and so on. Say we want an echo effect:</p>
<pre>
(define echo
(lambda (scaler secs)
(let ((del (make-delay (round (* secs (srate))))))
(lambda (inval)
(if inval
(+ inval (delay del (* scaler (+ (tap del) inval))))))))))
</pre>
<p>For readers who are new to Scheme, <i>echo</i> is a function
of two arguments, <i>scaler</i> and <i>secs</i>. Scaler sets
how loud subsequent echos are, and secs sets how far apart they
are in seconds. <i>echo</i> uses the <i>secs</i> argument to create
a delay line (<i>make-delay</i>) using the current sound's
sampling rate to turn the <i>secs</i> parameter into samples.
<i>echo</i> then returns a "closure", that is, a function with
associated variables (in this case <i>del</i> and <i>scaler</i>);
the returned function (the second <i>lambda</i>) takes
one argument (<i>inval</i>) and returns the result of passing
that value to the delay with scaling. The upshot of all this is that
we can use:</p>
<pre>
(map-chan (echo .5 .75) 0 44100)
</pre>
<p>to take the current active channel and
return 44100 samples of echos, each echo half the amplitude
of the previous, and spaced by .75 seconds. <i>map-chan</i>'s
first argument is a function of one argument, the current sample;
when we pass it <i>(echo ...)</i>, it evaluates the echo call,
which returns the function that actually runs the delay line,
producing the echo.
The CLM (common lisp) version might be something like:</p>
<pre>
(definstrument echo (beg dur scaler secs file)
(let ((del (make-delay (round (* secs *srate*))))
(inf (open-input file))
(j 0))
(run
(loop for i from beg below (+ beg dur) do
(let ((inval (ina j inf)))
(outa i (+ inval (delay del (* scaler (+ (tap del) inval)))))
(incf j))))
(close-input inf)))
;;; (with-sound () (echo 0 60000 .5 1.0 "pistol.snd"))
</pre>
I hope someday to make it possible to use this form directly
in Snd, but for now it needs to be translated.
Unfortunately, the interpreted Scheme version of the echo
effect is pretty slow; it is very handy for experimenting, but
when we have the effect we want, it can be bothersome to have to
wait while it plows through a long file. To optimize it in Snd,
we'll use exactly the
same code (the CLM-style delay line), but translate it to
C, loading the resultant module into Snd as described above under
<a href="#dynamic">dynamically loaded modules</a>. Here is our
module (echo.c):</p>
<pre>
<font size="2">
#include "snd.h"
#include "clm.h"
static int sample_ready = 0, current_sample = 0;
static mus_any *del = NULL;
static float echo_scaler,echo_secs,echo_duration;
static int trailing_samps = 0;
static chan_info *echo_cp;
static int send_sample(int *new_value)
{
if (sample_ready)
{
(*new_value) = current_sample;
sample_ready = 0;
return(PLUG_OK);
}
else
{
if (trailing_samps > 0)
{
(*new_value) = (int)mus_delay(del,echo_scaler * mus_tap(del,0.0),0.0);
trailing_samps--;
return(PLUG_OK);
}
}
return(PLUG_NO_DATA);
}
static int receive_sample(int value, int last_value)
{
sample_ready = 1;
current_sample = (int)(value + mus_delay(del,(float)((value + mus_tap(del,0.0)) * echo_scaler),0.0));
if (last_value)
{
trailing_samps = (echo_duration * SND_PLUGIN_SRATE(echo_cp)) - SND_PLUGIN_SAMPLES(echo_cp);
if (trailing_samps < 0) trailing_samps = 0;
}
return(PLUG_OK);
}
static int init_channel(chan_info *cp)
{
int samples;
if (del) mus_free(del); /* might be cleaner to put this in the end_channel method */
samples = (int)(echo_secs * SND_PLUGIN_SRATE(cp));
del = mus_make_delay(samples,NULL,samples);
trailing_samps = 0;
echo_cp = cp;
return(PLUG_OK);
}
static snd_plug *plug = NULL;
SCM echo(SCM scaler, SCM secs, SCM duration)
{
echo_scaler = (float)gh_scm2double(scaler);
echo_secs = (float)gh_scm2double(secs);
echo_duration = (float)gh_scm2double(duration);
if (plug == NULL)
{
plug = (snd_plug *)calloc(1,sizeof(snd_plug));
plug->init = NULL;
plug->quit = NULL;
plug->start_channel = init_channel;
plug->end_channel = NULL;
plug->read_sample = receive_sample;
plug->write_sample = send_sample;
plug->name = "echo";
plug->documentation = "echos";
plug->edit_name = "(echo)";
scm_sysintern("echo-plug",gh_ulong2scm((unsigned long)plug));
}
gh_eval_str("(call-plug echo-plug)");
return(SCM_BOOL_F);
}
void init_echo(void)
{
gh_new_procedure("echo",echo,3,0,0);
}
</font></pre>
<p>Most of this is boiler-plate that can be quickly copied and
pasted. Once we have echo.c, we need to create the associated
shared library. In Linux, this would be something like:</p>
<pre>
setenv LD_LIBRARY_PATH /usr/local/lib:/space/home/bil/cl
ld -shared clm.o io.o headers.o audio.o sound.o -o sndlib.so
cc echo.c -c -DHAVE_GUILE -DWITH_MUS_MODULE -DHAVE_SNDLIB
ld echo.o -shared -o echo.so sndlib.so -lc -lm
</pre>
<p>Now in Snd:</p>
<pre>
(define echolib (dynamic-link "echo.so"))
(dynamic-call "init_echo" echolib)
(echo .75 .5 3.0)
</pre>
<p>which is about 10 times as fast as the interpreted version. The <i>trailing_samps</i>
business allows our plug-in function to return more samples than were in the original.
(In more complex cases, such as the fm-violin in examp.scm, translation to C gives us
a speed up of about a factor of 40 -- exactly equivalent to using the run macro in CLM).
</p>
<h3>CLM functions</h3>
<p>See <a href="clm.html">clm.html</a> for full details. Optional args are in italics.</p>
<pre>
<font size="2">
<a href="clm.html#all-pass">all-pass</a> (gen input <i>pm</i>) all-pass filter
<a href="clm.html#all-pass?">all-pass?</a> (gen) #t if gen is all-pass filter
<a href="clm.html#amplitude-modulate">amplitude-modulate</a> (carrier in1 in2) amplitude modulation
<a href="clm.html#array-interp">array-interp</a> (arr x) interpolated array lookup
<a href="clm.html#array->file">array->file</a> (filename vct len srate channels)
write the contents of <i>vct</i> to the newly created sound file <i>filename</i>, giving
the new file <i>channels</i> channels (data assumed to be interleaved in <i>vct</i>),
sampling rate <i>srate</i>, and <i>len</i> samples (not frames).
<a href="clm.html#asymmetric-fm">asymmetric-fm</a> (gen index <i>fm</i>) asymmetric-fm generator
<a href="clm.html#asymmetric-fm?">asymmetric-fm?</a> (gen) #t if gen is asymmetric-fm generator
<a href="clm.html#buffer->frame">buffer->frame</a> (gen <i>frame</i> buffer generator returning frame
<a href="clm.html#buffer->sample">buffer->sample</a> (gen) buffer generator returning sample
<a href="clm.html#buffer-empty?">buffer-empty?</a> (gen) #t if buffer has no data
<a href="clm.html#buffer?">buffer?</a> (gen) #t if gen is buffer generator
<a href="clm.html#clear-array">clear-array</a> (arr) set all elements of arr to 0.0
<a href="clm.html#comb">comb</a> (gen input <i>pm</i>) comb filter
<a href="clm.html#comb?">comb?</a> (gen) #t if gen is comb filter
<a href="clm.html#contrast-enhancement">contrast-enhancement</a>(input (<i>index</i> 1.0)) a kind of phase modulation or companding
<a href="clm.html#convolution">convolution</a> (sig1 sig2 n) convolve sig1 with sig2 (size n), returning new sig1
<a href="clm.html#convolve">convolve</a> (gen <i>input-function</i>) convolve generator
<a href="clm.html#convolve?">convolve?</a> (gen) #t if gen is convolve generator
<a href="clm.html#db->linear">db->linear</a> (db) translate dB value to linear
<a href="clm.html#degrees->radians">degrees->radians</a> (deg) translate degrees to radians
<a href="clm.html#delay">delay</a> (gen input <i>pm</i>) delay line
<b>delay</b> is a built-in syntactic form (or whatever they call it) in Scheme,
but I don't think this is a case where I care! The name <b>%delay</b> is bound
to the original meaning of <b>delay</b> in case you need to use it.
<a href="clm.html#delay?">delay?</a> (gen) #t if gen is delay line
<a href="clm.html#dot-product">dot-product</a> (sig1 sig2) return dot-product of sig1 with sig2
<a href="clm.html#env">env</a> (gen) envelope generator
<a href="clm.html#env-interp">env-interp</a> (x env (<i>base</i> 1.0)) return value of env at x
<a href="clm.html#env?">env?</a> (gen) #t if gen is env (from make-env)
<a href="clm.html#fft">mus-fft</a> (rl im n sign) fft of rl and im (sign = -1 for ifft), result in rl
<a href="clm.html#file->array">file->array</a> (filename chan start len vct)
load <i>len</i> samples of <i>filename</i> into <i>vct</i> starting at frame <i>start</i> in channel <i>chan</i>.
<a href="clm.html#file->frame">file->frame</a> (gen loc <i>frame</i>) return frame from file at loc
<a href="clm.html#file->frame?">file->frame?</a> (gen) #t if gen is file->frame generator
<a href="clm.html#file->sample">file->sample</a> (gen loc <i>(chan 0)</i>) return sample from file at loc
<a href="clm.html#file->sample?">file->sample?</a> (gen) #t if gen is file->sample generator
<a href="clm.html#filter">filter</a> (gen input) filter
<a href="clm.html#filter?">filter?</a> (gen) #t if gen is filter
<a href="clm.html#fir-filter">fir-filter</a> (gen input) FIR filter
<a href="clm.html#fir-filter?">fir-filter?</a> (gen) #t if gen is fir filter
<a href="clm.html#formant">formant</a> (gen input) formant generator
<a href="clm.html#formant?">formant?</a> (gen) #t if gen is formant generator
<a href="clm.html#frame*">frame*</a> (fr1 fr2 <i>outfr</i>) element-wise multiply
<a href="clm.html#frame+">frame+</a> (fr1 fr2 <i>outfr</i>) element-wise add
<a href="clm.html#frame->buffer">frame->buffer</a> (buf frame) add frame to buffer
<a href="clm.html#frame->file">frame->file</a> (gen loc frame) write (add) frame to file at loc
<a href="clm.html#frame->file?">frame->file?</a> (gen) #t if gen is frame->file generator
<a href="clm.html#frame->frame">frame->frame</a> (mixer frame <i>outfr</i>) pass frame through mixer
<a href="clm.html#frame-ref">frame-ref</a> (frame chan) return frame[chan]
<a href="clm.html#frame->sample">frame->sample</a> (frmix frame) pass frame through frame or mixer to produce sample
<a href="clm.html#frame-set!">frame-set!</a> (frame chan val) frame[chan]=val
<a href="clm.html#frame?">frame?</a> (gen) #t if gen is frame object
<a href="clm.html#granulate">granulate</a> (gen <i>input-function</i>) granular synthesis generator
<a href="clm.html#granulate?">granulate?</a> (gen) #t if gen is granulate generator
<a href="clm.html#hz->radians">hz->radians</a> (freq) translate freq to radians/sample
<a href="clm.html#iir-filter">iir-filter</a> (gen input) IIR filter
<a href="clm.html#iir-filter?">iir-filter?</a> (gen) #t if gen is iir-filter
<a href="clm.html#in-any">in-any</a> (loc <i>chan</i> <i>stream</i>) return sample in stream at loc and chan
<a href="clm.html#in-hz">in-hz</a> (freq) translate freq to radians/sample
<a href="clm.html#ina">ina</a> (loc <i>stream</i>) return sample in stream at loc, chan 0
<a href="clm.html#inb">inb</a> (loc <i>stream</i>) return sample in stream at loc, chan 1
<a href="clm.html#linear->db">linear->db</a> (val) translate linear val to dB
<a href="clm.html#locsig">locsig</a> (gen loc input) place input in output channels at loc
<a href="clm.html#locsig-ref">locsig-ref</a> (gen chan) locsig-scaler[chan]
<a href="clm.html#locsig-reverb-ref">locsig-reverb-ref</a> (gen chan) locsig-reverb-scaler[chan]
<a href="clm.html#locsig-set!">locsig-set!</a> (gen chan val) locsig-scaler[chan] = val
<a href="clm.html#locsig-reverb-set!">locsig-reverb-set!</a> (gen chan val) locsig-reverb-scaler[chan] = val
<a href="clm.html#locsig?">locsig?</a> (gen) #t if gen is locsig generator
;; all the make function arguments are <a href="clm.html#optional-key">optional-key</a> args
<a href="clm.html#make-all-pass">make-all-pass</a> (feedback feedforward size max-size initial-contents initial-element)
<a href="clm.html#make-asymmetric-fm">make-asymmetric-fm</a> (frequency initial-phase r ratio)
<a href="clm.html#make-buffer">make-buffer</a> (size fill-time)
<a href="clm.html#make-comb">make-comb</a> (scaler size max-size initial-contents initial-element)
<a href="clm.html#make-convolve">make-convolve</a> (input filter fft-size filter-size)
<a href="clm.html#make-delay">make-delay</a> (size initial-contents initial-element max-size)
<a href="clm.html#make-env">make-env</a> (envelope scaler duration offset base end start)
<a href="clm.html#make-fft-window">make-fft-window</a> (type size)
<a href="clm.html#make-file->frame">make-file->frame</a> (name)
<a href="clm.html#make-file->sample">make-file->sample</a> (name)
<a href="clm.html#make-filter">make-filter</a> (order xcoeffs ycoeffs)
<a href="clm.html#make-fir-filter">make-fir-filter</a> (order xcoeffs)
<a href="clm.html#make-formant">make-formant</a> (radius frequency gain)
<a href="clm.html#make-frame">make-frame</a> (chans &rest vals)
<a href="clm.html#make-frame->file">make-frame->file</a> (name chans)
<a href="clm.html#make-granulate">make-granulate</a> (input expansion length scaler hop ramp jitter max-size)
<a href="clm.html#make-iir-filter">make-iir-filter</a> (order ycoeffs)
<a href="clm.html#make-locsig">make-locsig</a> (degree distance reverb output revout channels)
<a href="clm.html#make-mixer">make-mixer</a> (chans &rest vals)
<a href="clm.html#make-notch">make-notch</a> (scaler size max-size initial-contents initial-element)
<a href="clm.html#make-one-pole">make-one-pole</a> (a0 b1)
<a href="clm.html#make-one-zero">make-one-zero</a> (a0 a1)
<a href="clm.html#make-oscil">make-oscil</a> (frequency initial-phase)
<a href="clm.html#make-ppolar">make-ppolar</a> (radius frequency)
<a href="clm.html#make-pulse-train">make-pulse-train</a> (frequency amplitude initial-phase)
<a href="clm.html#make-rand">make-rand</a> (frequency amplitude)
<a href="clm.html#make-rand-interp">make-rand-interp</a> (frequency amplitude)
<a href="clm.html#make-readin">make-readin</a> (file channel start)
<a href="clm.html#make-sample->file">make-sample->file</a> (name chans)
<a href="clm.html#make-sawtooth-wave">make-sawtooth-wave</a> (frequency amplitude initial-phase)
<a href="clm.html#make-sine-summation">make-sine-summation</a> (frequency initial-phase n a ratio)
<a href="clm.html#make-square-wave">make-square-wave</a> (frequency amplitude initial-phase)
<a href="clm.html#make-src">make-src</a> (input srate width)
<a href="clm.html#make-sum-of-cosines">make-sum-of-cosines</a> (frequency initial-phase cosines)
<a href="clm.html#make-table-lookup">make-table-lookup</a> (frequency initial-phase wave)
<a href="clm.html#make-triangle-wave">make-triangle-wave</a> (frequency amplitude initial-phase)
<a href="clm.html#make-two-pole">make-two-pole</a> (a0 b1 b2)
<a href="clm.html#make-two-zero">make-two-zero</a> (a0 a1 a2)
<a href="clm.html#make-wave-train">make-wave-train</a> (frequency initial-phase wave)
<a href="clm.html#make-waveshape">make-waveshape</a> (frequency partials)
<a href="clm.html#make-zpolar">make-zpolar</a> (radius frequency)
<a href="clm.html#mixer*">mixer*</a> (mix1 mix2 <i>outmx</i>) matrix multiply of mix1 and mix2
<a href="clm.html#mixer-ref">mixer-ref</a> (mix in out) mix-scaler[in,out]
<a href="clm.html#mixer-set!">mixer-set!</a> (mix in out val) mix-scaler[in,out] = val
<a href="clm.html#mixer?">mixer?</a> (gen) #t if gen is mixer object
<a href="clm.html#multiply-arrays">multiply-arrays</a> (arr1 arr2) arr1[i] *= arr2[i]
;; the "mus-" functions are generic functions, to set use mus-set-var as in mus-set-frequency
<a href="clm.html#mus-a0">mus-a0</a> (gen) a0 field (simple filters)
<a href="clm.html#mus-a1">mus-a1</a> (gen) a1 field (simple filters)
<a href="clm.html#mus-a2">mus-a2</a> (gen) a2 field (simple filters)
<a href="clm.html#mus-array-print-length">mus-array-print-length</a> () how many array elements to print in mus_describe
<a href="clm.html#mus-b1">mus-b1</a> (gen) b1 field (simple filters)
<a href="clm.html#mus-b2">mus-b2</a> (gen) b2 field (simple filters)
<a href="clm.html#mus-channel">mus-channel</a> (gen) channel of gen
<a href="clm.html#mus-channels">mus-channels</a> (gen) channels of gen
<a href="clm.html#mus-cosines">mus-cosines</a> (gen) cosines of sum-of-cosines gen
<a href="clm.html#mus-data">mus-data</a> (gen) data array of gen
<a href="clm.html#mus-feedback">mus-feedback</a> (gen) feedback term of gen (simple filters)
<a href="clm.html#mus-feedforward">mus-feedforward</a> (gen) feedforward term of gen (all-pass)
<a href="clm.html#mus-formant-radius">mus-formant-radius</a> (gen) formant radius
<a href="clm.html#mus-frequency">mus-frequency</a> (gen) frequency of gen (Hz)
<a href="clm.html#mus-hop">mus-hop</a> (gen) hop amount of gen (granulate)
<a href="clm.html#mus-increment">mus-increment</a> (gen) increment of gen (src, readin, granulate)
<a href="clm.html#mus-input?">mus-input?</a> (gen) #t if gen is input source
<a href="clm.html#mus-length">mus-length</a> (gen) length of gen
<a href="clm.html#mus-location">mus-location</a> (gen) location (read point) of gen
<a href="clm.html#mus-mix">mus-mix</a> (outfile infile <i>(outloc 0) frames (inloc 0) mixer envs</i>)
mix <i>infile</i> into <i>outfile</i> starting at <i>outloc</i> in <i>outfile</i> and <i>inloc</i> in <i>infile</i>
mixing <i>frames</i> frames of <i>infile</i>. <i>frames</i> defaults to the length of <i>infile</i>. If <i>mixer</i>,
use it to scale the various channels; if <i>envs</i> (an array of envelope generators), use
it in conjunction with <i>mixer</i> to scale/envelope all the various ins and outs.
<a href="clm.html#mus-order">mus-order</a> (gen) order of gen (filters)
<a href="clm.html#mus-output?">mus-output?</a> (gen) #t if gen is output generator
<a href="clm.html#mus-phase">mus-phase</a> (gen) phase of gen (radians)
<a href="clm.html#mus-ramp">mus-ramp</a> (gen) ramp time of gen (granulate)
<a href="clm.html#mus-random">mus-random</a> (val) random numbers bewteen -val and val
<a href="clm.html#mus-scaler">mus-scaler</a> (gen) scaler of gen
<a href="clm.html#mus-set-rand-seed">mus-set-rand-seed</a> (val) set random number generator seed to val
<a href="clm.html#mus-set-srate">mus-set-srate</a> (val) set sampling rate to val
<a href="clm.html#mus-srate">mus-srate</a> () current sampling rate
<a href="clm.html#mus-xcoeffs">mus-xcoeffs</a> (gen) feedforward (FIR) coeffs of filter
<a href="clm.html#mus-ycoeffs">mus-ycoeffs</a> (gen) feedback (IIR) coeefs of filter
<a href="clm.html#notch">notch</a> (gen input <i>pm</i>) notch filter
<a href="clm.html#notch?">notch?</a> (gen) #t if gen is notch filter
<a href="clm.html#one-pole">one-pole</a> (gen input) one-pole filter
<a href="clm.html#one-pole?">one-pole?</a> (gen) #t if gen is one-pole filter
<a href="clm.html#one-zero">one-zero</a> (gen input) one-zero filter
<a href="clm.html#one-zero?">one-zero?</a> (gen) #t if gen is one-zero filter
<a href="clm.html#oscil">oscil</a> (gen <i>fm pm</i>) sine wave generator
<a href="clm.html#oscil?">oscil?</a> (gen) #t if gen is oscil generator
<a href="clm.html#out-any">out-any</a> (loc samp chan <i>stream</i>) write (add) samp to stream at loc in channel chan
<a href="clm.html#outa">outa</a> (loc samp <i>stream</i>) write (add) samp to stream at loc in chan 0
<a href="clm.html#outb">outb</a> (loc samp <i>stream</i>) write (add) samp to stream at loc in chan 1
<a href="clm.html#outc">outc</a> (loc samp <i>stream</i>) write (add) samp to stream at loc in chan 2
<a href="clm.html#outd">outd</a> (loc samp <i>stream</i>) write (add) samp to stream at loc in chan 3
<a href="clm.html#partials->polynomial">partials->polynomial</a>(partials <i>kind</i>) create waveshaping polynomial from partials
<a href="clm.html#partials->wave">partials->wave</a> (synth-data table <i>norm</i>) load table from synth-data
<a href="clm.html#partials->waveshape">partials->waveshape</a> (partials <i>norm size</i>) create waveshaping table from partials
<a href="clm.html#phase-partials->wave">phase-partials->wave</a>(synth-data table <i>norm</i>) load table from synth-data
<a href="clm.html#phase-partials->waveshape">phase-partials->waveshape</a>(partials phases <i>size</i>) create waveshaping table from partials
<a href="clm.html#polynomial">polynomial</a> (coeffs x) evaluate polynomial at x
<a href="clm.html#pulse-train">pulse-train</a> (gen <i>fm</i>) pulse-train generator
<a href="clm.html#pulse-train?">pulse-train?</a> (gen) #t if gen is pulse-train generator
<a href="clm.html#radians->degrees">radians->degrees</a> (rads) convert radians to degrees
<a href="clm.html#radians->hz">radians->hz</a> (rads) convert radians/sample to Hz
<a href="clm.html#rand">rand</a> (gen <i>fm</i>) random number generator
<a href="clm.html#rand-interp">rand-interp</a> (gen <i>fm</i>) interpolating random number generator
<a href="clm.html#rand-interp?">rand-interp?</a> (gen) #t if gen is interpolating random number generator
<a href="clm.html#rand?">rand?</a> (gen) #t if gen is random number generator
<a href="clm.html#readin">readin</a> (gen) read one value from associated input stream
<a href="clm.html#readin?">readin?</a> (gen) #t if gen is readin generator
<a href="clm.html#rectangular->polar">rectangular->polar</a> (rl im) translate from rectangular to polar coordinates
<a href="clm.html#restart-env">restart-env</a> (env) return to start of env
<a href="clm.html#ring-modulate">ring-modulate</a> (sig1 sig2) sig1 * sig2 (element-wise)
<a href="clm.html#sample->buffer">sample->buffer</a> (buf samp) store samp in buffer
<a href="clm.html#sample->file">sample->file</a> (gen loc chan val) store val in file at loc in channel chan
<a href="clm.html#sample->file?">sample->file?</a> (gen) #t if gen is sample->file generator
<a href="clm.html#sample->frame">sample->frame</a> (frmix samp <i>outfr</i>) convert samp to frame
<a href="clm.html#sawtooth-wave">sawtooth-wave</a> (gen <i>fm</i>) sawtooth-wave generator
<a href="clm.html#sawtooth-wave?">sawtooth-wave?</a> (gen) #t if gen is sawtooth-wave generator
<a href="clm.html#sine-summation">sine-summation</a> (gen <i>fm</i>) sine-summation generator
<a href="clm.html#sine-summation?">sine-summation?</a> (gen) #t if gen is sine-summation generator
<a href="clm.html#spectrum">spectrum</a> (rl im win type) produce spectrum of data in rl
<a href="clm.html#square-wave">square-wave</a> (gen <i>fm</i>) square-wave generator
<a href="clm.html#square-wave?">square-wave?</a> (gen) #t if gen is square-wave generator
<a href="clm.html#src">src</a> (gen <i>fm input-function</i>) sample rate converter
<a href="clm.html#src?">src?</a> (gen) #t if gen is sample-rate converter
<a href="clm.html#sum-of-cosines">sum-of-cosines</a> (gen <i>fm</i>) sum-of-cosines (pulse-train) generator
<a href="clm.html#sum-of-cosines?">sum-of-cosines?</a> (gen) #t if gen is sum-of-cosines generator
<a href="clm.html#table-lookup">table-lookup</a> (gen <i>fm</i>) table-lookup generator
<a href="clm.html#table-lookup?">table-lookup?</a> (gen) #t if gen is table-lookup generator
<a href="clm.html#tap">tap</a> (gen <i>pm</i>) delay line tap
<a href="clm.html#triangle-wave">triangle-wave</a> (gen <i>fm</i>) triangle-wave generator
<a href="clm.html#triangle-wave?">triangle-wave?</a> (gen) #t if gen is triangle-wave generator
<a href="clm.html#two-pole">two-pole</a> (gen input) two-pole filter
<a href="clm.html#two-pole?">two-pole?</a> (gen) #t if gen is two-pole filter
<a href="clm.html#two-zero">two-zero</a> (gen input) two-zero filter
<a href="clm.html#two-zero?">two-zero?</a> (gen) #t if gen is two-zero filter
<a href="clm.html#wave-train">wave-train</a> (gen <i>fm</i>) wave-train generator
<a href="clm.html#wave-train?">wave-train?</a> (gen) #t if gen is wave-train generator
<a href="clm.html#waveshape">waveshape</a> (gen <i>index fm</i>) waveshaping generator
<a href="clm.html#waveshape?">waveshape?</a> (gen) #t if gen is waveshape generator
</font></pre>
<p>Here are a few more examples, taken from examp.scm:</p>
<pre>
<font size="2">
(define comb-filter
(lambda (scaler size)
(let ((cmb (make-comb scaler size)))
(lambda (x) (if x (comb cmb x))))))
; (map-chan (comb-filter .8 32))
;;; by using filters at harmonically related sizes, we can get chords:
(define comb-chord
(lambda (scaler size amp)
(let ((c1 (make-comb scaler size))
(c2 (make-comb scaler (* size .75)))
(c3 (make-comb scaler (* size 1.2))))
(lambda (x) (if x (* amp (+ (comb c1 x) (comb c2 x) (comb c3 x))))))))
; (map-chan (comb-chord .95 60 .3))
;;; or change the comb length via an envelope:
(define max-envelope
(lambda (e mx)
(if (null? e)
mx
(max-envelope (cddr e) (max mx (abs (cadr e)))))))
(define zcomb
(lambda (scaler size pm)
(let ((cmb (make-comb scaler size :max-size (+ size 1 (max-envelope pm 0))))
(penv (make-env :envelope pm :end (frames))))
(lambda (x) (if x (comb cmb x (env penv)))))))
; (map-chan (zcomb .8 32 '(0 0 1 10)))
;;; to impose several formants, just add them in parallel:
(define formants
(lambda (r1 f1 r2 f2 r3 f3)
(let ((fr1 (make-formant r1 f1))
(fr2 (make-formant r2 f2))
(fr3 (make-formant r3 f3)))
(lambda (x)
(if x (+ (formant fr1 x)
(formant fr2 x)
(formant fr3 x)))))))
; (map-chan (formants .01 900 .02 1800 .01 2700))
;;; to get a moving formant:
(define moving-formant
(lambda (radius move)
(let ((frm (make-formant radius (cadr move)))
(menv (make-env :envelope move :end (frames))))
(lambda (x)
(if x
(let ((val (formant frm x)))
(mus-set-frequency frm (env menv))
val))))))
; (map-chan (moving-formant .01 '(0 1200 1 2400)))
;;; various "Forbidden Planet" sound effects:
(define fp
(lambda (sr osamp osfrq)
(let* ((os (make-oscil osfrq))
(sr (make-src :srate sr))
(len (frames))
(inctr 0)
(out-data (make-vct len)))
(do ((i 0 (1+ i)))
((= i len))
(vct-set! out-data i
(src sr (* osamp (oscil os))
(lambda (dir)
(let ((val (sample inctr)))
(set! inctr (+ inctr dir))
val)))))
(vct->samples 0 len out-data))))
; (fp 1.0 .3 20)
;;; -------- shift pitch keeping duration constant
;;;
;;; both src and granulate take a function argument to get input whenever it is needed.
;;; in this case, src calls granulate which reads the currently selected file.
(define expsrc
(lambda (rate)
(let* ((gr (make-granulate :expansion rate))
(sr (make-src :srate rate))
(inctr 0))
(lambda (inval)
(if inval
(src sr 0.0
(lambda (dir)
(granulate gr
(lambda (dir)
(let ((val (sample inctr)))
(set! inctr (+ inctr dir))
val))))))))))
</font></pre>
<p>Geez, I haven't had this much fun in a long time! Check out examp.scm for more.</p>
<hr>
<h2><a name="sndwithmotif">Snd and Motif</a></h2>
<p>It is possible to add your own user-interface elements controlling your plug-ins.
As a very simple example, let's add a dialog window with a slider to the scale plug-in
given above.</p>
<pre>
<font size="2">
/* scale.c, includes dialog-window with slider to set scale value */
#include "snd.h"
static int sample_ready = 0, current_sample = 0;
static Widget scale_dialog = NULL; /* this will hold our slider */
static float current_scaler = 1.0;
static void Help_Scale_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
fprintf(stderr,"move the slider to affect the volume");
}
static void Dismiss_Scale_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
XtUnmanageChild(scale_dialog);
}
static void Scale_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
XmScaleCallbackStruct *cb = (XmScaleCallbackStruct *)callData;
current_scaler = (float)(cb->value/100.0);
}
static int create_scale_dialog(snd_state *ss)
{
Arg args[32];
int n,i;
XmString xhelp,xdismiss,titlestr;
Widget mainform,scale;
if (!scale_dialog)
{
xdismiss = XmStringCreate("Dismiss",XmFONTLIST_DEFAULT_TAG);
xhelp = XmStringCreate("Help",XmFONTLIST_DEFAULT_TAG);
titlestr = XmStringCreate("Scaling Plug-in",XmFONTLIST_DEFAULT_TAG);
n=0;
XtSetArg(args[n],XmNcancelLabelString,xdismiss); n++;
XtSetArg(args[n],XmNhelpLabelString,xhelp); n++;
XtSetArg(args[n],XmNautoUnmanage,FALSE); n++;
XtSetArg(args[n],XmNdialogTitle,titlestr); n++;
XtSetArg(args[n],XmNresizePolicy,XmRESIZE_GROW); n++;
XtSetArg(args[n],XmNnoResize,FALSE); n++;
XtSetArg(args[n],XmNtransient,FALSE); n++;
scale_dialog = XmCreateTemplateDialog(ss->sgx->mainshell,"Scaling Plug-in",args,n);
XtAddCallback(scale_dialog,XmNcancelCallback,Dismiss_Scale_Callback,ss);
XtAddCallback(scale_dialog,XmNhelpCallback,Help_Scale_Callback,ss);
XmStringFree(xhelp);
XmStringFree(xdismiss);
XmStringFree(titlestr);
n=0;
XtSetArg(args[n],XmNleftAttachment,XmATTACH_FORM); n++;
XtSetArg(args[n],XmNrightAttachment,XmATTACH_FORM); n++;
XtSetArg(args[n],XmNtopAttachment,XmATTACH_FORM); n++;
XtSetArg(args[n],XmNbottomAttachment,XmATTACH_WIDGET); n++;
XtSetArg(args[n],XmNbottomWidget,XmMessageBoxGetChild(scale_dialog,XmDIALOG_SEPARATOR)); n++;
mainform = XtCreateManagedWidget("formd",xmFormWidgetClass,scale_dialog,args,n);
n=0;
XtSetArg(args[n],XmNorientation,XmHORIZONTAL); n++;
XtSetArg(args[n],XmNshowValue,TRUE); n++;
XtSetArg(args[n],XmNvalue,100); n++;
XtSetArg(args[n],XmNmaximum,500); n++;
XtSetArg(args[n],XmNdecimalPoints,2); n++;
scale = XtCreateManagedWidget("",xmScaleWidgetClass,mainform,args,n);
XtAddCallback(scale,XmNvalueChangedCallback,Scale_Callback,ss);
XtAddCallback(scale,XmNdragCallback,Scale_Callback,ss);
}
XtManageChild(scale_dialog);
return(PLUG_OK);
}
/* the rest is as before except that we add create_scale_dialog to the plug-in struct */
static int send_sample(int *new_value)
{
if (sample_ready)
{
(*new_value) = current_sample;
sample_ready = 0;
return(PLUG_OK);
}
else return(PLUG_NO_DATA);
}
static int receive_sample(int value, int last_value)
{
sample_ready = 1;
current_sample = value * current_scaler; /* this is our scaling operation */
return(PLUG_OK);
}
static snd_plug *plug = NULL;
SCM snd_scale(void)
{
if (plug == NULL)
{
plug = (snd_plug *)calloc(1,sizeof(snd_plug));
plug->init = create_scale_dialog;
plug->quit = NULL;
plug->start_channel = NULL;
plug->end_channel = NULL;
plug->read_sample = receive_sample;
plug->write_sample = send_sample;
plug->name = "scale";
plug->documentation = "scales by 2";
plug->edit_name = "(snd-scale)";
scm_sysintern("scale-plug",gh_ulong2scm((unsigned long)plug));
}
gh_eval_str("(call-plug scale-plug)");
return(SCM_BOOL_F);
}
void init_snd_scale(void)
{
gh_new_procedure("snd-scale",snd_scale,0,0,0);
}
/* end of scale.c */
</font></pre>
</body></html>
|