/usr/include/liquid/liquid.h is in libliquid-dev 1.3.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 | /*
* Copyright (c) 2007 - 2016 Joseph Gaeddert
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __LIQUID_H__
#define __LIQUID_H__
#ifdef __cplusplus
extern "C" {
# define LIQUID_USE_COMPLEX_H 0
#else
# define LIQUID_USE_COMPLEX_H 1
#endif // __cplusplus
// common headers
#include <inttypes.h>
//
// Make sure the version and version number macros weren't defined by
// some prevoiusly included header file.
//
#ifdef LIQUID_VERSION
# undef LIQUID_VERSION
#endif
#ifdef LIQUID_VERSION_NUMBER
# undef LIQUID_VERSION_NUMBER
#endif
//
// Compile-time version numbers
//
// LIQUID_VERSION = "X.Y.Z"
// LIQUID_VERSION_NUMBER = (X*1000000 + Y*1000 + Z)
//
#define LIQUID_VERSION "1.2.0"
#define LIQUID_VERSION_NUMBER 1002000
//
// Run-time library version numbers
//
extern const char liquid_version[];
const char * liquid_libversion(void);
int liquid_libversion_number(void);
// run-time library validation
#define LIQUID_VALIDATE_LIBVERSION \
if (LIQUID_VERSION_NUMBER != liquid_libversion_number()) { \
fprintf(stderr,"%s:%u: ", __FILE__,__LINE__); \
fprintf(stderr,"error: invalid liquid runtime library\n"); \
exit(1); \
} \
#define LIQUID_CONCAT(prefix, name) prefix ## name
#define LIQUID_VALIDATE_INPUT
/*
* Compile-time complex data type definitions
*
* Default: use the C99 complex data type, otherwise
* define complex type compatible with the C++ complex standard,
* otherwise resort to defining binary compatible array.
*/
#if LIQUID_USE_COMPLEX_H==1
# include <complex.h>
# define LIQUID_DEFINE_COMPLEX(R,C) typedef R _Complex C
#elif defined _GLIBCXX_COMPLEX || defined _LIBCPP_COMPLEX
# define LIQUID_DEFINE_COMPLEX(R,C) typedef std::complex<R> C
#else
# define LIQUID_DEFINE_COMPLEX(R,C) typedef struct {R real; R imag;} C;
#endif
//# define LIQUID_DEFINE_COMPLEX(R,C) typedef R C[2]
LIQUID_DEFINE_COMPLEX(float, liquid_float_complex);
LIQUID_DEFINE_COMPLEX(double, liquid_double_complex);
//
// MODULE : agc (automatic gain control)
//
#define AGC_MANGLE_CRCF(name) LIQUID_CONCAT(agc_crcf, name)
#define AGC_MANGLE_RRRF(name) LIQUID_CONCAT(agc_rrrf, name)
// large macro
// AGC : name-mangling macro
// T : primitive data type
// TC : input/output data type
#define LIQUID_AGC_DEFINE_API(AGC,T,TC) \
typedef struct AGC(_s) * AGC(); \
\
/* create automatic gain control object */ \
AGC() AGC(_create)(void); \
\
/* destroy object, freeing all internally-allocated memory */ \
void AGC(_destroy)(AGC() _q); \
\
/* print object properties to stdout */ \
void AGC(_print)(AGC() _q); \
\
/* reset object's internal state */ \
void AGC(_reset)(AGC() _q); \
\
/* execute automatic gain control on an single input sample */ \
/* _q : automatic gain control object */ \
/* _x : input sample */ \
/* _y : output sample */ \
void AGC(_execute)(AGC() _q, \
TC _x, \
TC * _y); \
\
/* execute automatic gain control on block of samples */ \
/* _q : automatic gain control object */ \
/* _x : input data array, [size: _n x 1] */ \
/* _n : number of input, output samples */ \
/* _y : output data array, [size: _n x 1] */ \
void AGC(_execute_block)(AGC() _q, \
TC * _x, \
unsigned int _n, \
TC * _y); \
\
/* lock/unlock gain control */ \
void AGC(_lock)( AGC() _q); \
void AGC(_unlock)(AGC() _q); \
\
/* get/set loop filter bandwidth; attack/release time */ \
float AGC(_get_bandwidth)(AGC() _q); \
void AGC(_set_bandwidth)(AGC() _q, float _bt); \
\
/* get/set signal level (linear) relative to unity energy */ \
float AGC(_get_signal_level)(AGC() _q); \
void AGC(_set_signal_level)(AGC() _q, float _signal_level); \
\
/* get/set signal level (dB) relative to unity energy */ \
float AGC(_get_rssi)(AGC() _q); \
void AGC(_set_rssi)(AGC() _q, float _rssi); \
\
/* get/set gain value (linear) relative to unity energy */ \
float AGC(_get_gain)(AGC() _q); \
void AGC(_set_gain)(AGC() _q, float _gain); \
\
/* initialize internal gain on input array */ \
/* _q : automatic gain control object */ \
/* _x : input data array, [size: _n x 1] */ \
/* _n : number of input, output samples */ \
void AGC(_init)(AGC() _q, \
TC * _x, \
unsigned int _n); \
// Define agc APIs
LIQUID_AGC_DEFINE_API(AGC_MANGLE_CRCF, float, liquid_float_complex)
LIQUID_AGC_DEFINE_API(AGC_MANGLE_RRRF, float, float)
//
// MODULE : audio
//
// CVSD: continuously variable slope delta
typedef struct cvsd_s * cvsd;
// create cvsd object
// _num_bits : number of adjacent bits to observe (4 recommended)
// _zeta : slope adjustment multiplier (1.5 recommended)
// _alpha : pre-/post-emphasis filter coefficient (0.9 recommended)
// NOTE: _alpha must be in [0,1]
cvsd cvsd_create(unsigned int _num_bits,
float _zeta,
float _alpha);
// destroy cvsd object
void cvsd_destroy(cvsd _q);
// print cvsd object parameters
void cvsd_print(cvsd _q);
// encode/decode single sample
unsigned char cvsd_encode(cvsd _q, float _audio_sample);
float cvsd_decode(cvsd _q, unsigned char _bit);
// encode/decode 8 samples at a time
void cvsd_encode8(cvsd _q, float * _audio, unsigned char * _data);
void cvsd_decode8(cvsd _q, unsigned char _data, float * _audio);
//
// MODULE : buffer
//
// circular buffer
#define CBUFFER_MANGLE_FLOAT(name) LIQUID_CONCAT(cbufferf, name)
#define CBUFFER_MANGLE_CFLOAT(name) LIQUID_CONCAT(cbuffercf, name)
// large macro
// CBUFFER : name-mangling macro
// T : data type
#define LIQUID_CBUFFER_DEFINE_API(CBUFFER,T) \
typedef struct CBUFFER(_s) * CBUFFER(); \
\
/* create circular buffer object of a particular size */ \
CBUFFER() CBUFFER(_create)(unsigned int _max_size); \
\
/* create circular buffer object of a particular size and */ \
/* specify the maximum number of elements that can be read */ \
/* at any given time. */ \
CBUFFER() CBUFFER(_create_max)(unsigned int _max_size, \
unsigned int _max_read); \
\
/* destroy cbuffer object, freeing all internal memory */ \
void CBUFFER(_destroy)(CBUFFER() _q); \
\
/* print cbuffer object properties */ \
void CBUFFER(_print)(CBUFFER() _q); \
\
/* print cbuffer object properties and internal state */ \
void CBUFFER(_debug_print)(CBUFFER() _q); \
\
/* clear internal buffer */ \
void CBUFFER(_reset)(CBUFFER() _q); \
\
/* get the number of elements currently in the buffer */ \
unsigned int CBUFFER(_size)(CBUFFER() _q); \
\
/* get the maximum number of elements the buffer can hold */ \
unsigned int CBUFFER(_max_size)(CBUFFER() _q); \
\
/* get the maximum number of elements you may read at once */ \
unsigned int CBUFFER(_max_read)(CBUFFER() _q); \
\
/* get the number of available slots (max_size - size) */ \
unsigned int CBUFFER(_space_available)(CBUFFER() _q); \
\
/* is buffer full? */ \
int CBUFFER(_is_full)(CBUFFER() _q); \
\
/* write a single sample into the buffer */ \
/* _q : circular buffer object */ \
/* _v : input sample */ \
void CBUFFER(_push)(CBUFFER() _q, \
T _v); \
\
/* write samples to the buffer */ \
/* _q : circular buffer object */ \
/* _v : output array */ \
/* _n : number of samples to write */ \
void CBUFFER(_write)(CBUFFER() _q, \
T * _v, \
unsigned int _n); \
\
/* remove and return a single element from the buffer */ \
/* _q : circular buffer object */ \
/* _v : pointer to sample output */ \
void CBUFFER(_pop)(CBUFFER() _q, \
T * _v); \
\
/* read buffer contents */ \
/* _q : circular buffer object */ \
/* _num_requested : number of elements requested */ \
/* _v : output pointer */ \
/* _nr : number of elements referenced by _v */ \
void CBUFFER(_read)(CBUFFER() _q, \
unsigned int _num_requested, \
T ** _v, \
unsigned int * _num_read); \
\
/* release _n samples from the buffer */ \
void CBUFFER(_release)(CBUFFER() _q, \
unsigned int _n); \
// Define buffer APIs
LIQUID_CBUFFER_DEFINE_API(CBUFFER_MANGLE_FLOAT, float)
LIQUID_CBUFFER_DEFINE_API(CBUFFER_MANGLE_CFLOAT, liquid_float_complex)
// Windowing functions
#define WINDOW_MANGLE_FLOAT(name) LIQUID_CONCAT(windowf, name)
#define WINDOW_MANGLE_CFLOAT(name) LIQUID_CONCAT(windowcf, name)
// large macro
// WINDOW : name-mangling macro
// T : data type
#define LIQUID_WINDOW_DEFINE_API(WINDOW,T) \
\
typedef struct WINDOW(_s) * WINDOW(); \
\
/* create window buffer object of length _n */ \
WINDOW() WINDOW(_create)(unsigned int _n); \
\
/* recreate window buffer object with new length */ \
/* _q : old window object */ \
/* _n : new window length */ \
WINDOW() WINDOW(_recreate)(WINDOW() _q, unsigned int _n); \
\
/* destroy window object, freeing all internally memory */ \
void WINDOW(_destroy)(WINDOW() _q); \
\
/* print window object to stdout */ \
void WINDOW(_print)(WINDOW() _q); \
\
/* print window object to stdout (with extra information) */ \
void WINDOW(_debug_print)(WINDOW() _q); \
\
/* reset window object (initialize to zeros) */ \
void WINDOW(_reset)(WINDOW() _q); \
\
/* read window buffer contents */ \
/* _q : window object */ \
/* _v : output pointer (set to internal array) */ \
void WINDOW(_read)(WINDOW() _q, T ** _v); \
\
/* index single element in buffer at a particular index */ \
/* _q : window object */ \
/* _i : index of element to read */ \
/* _v : output value pointer */ \
void WINDOW(_index)(WINDOW() _q, \
unsigned int _i, \
T * _v); \
\
/* push single element onto window buffer */ \
/* _q : window object */ \
/* _v : single input element */ \
void WINDOW(_push)(WINDOW() _q, \
T _v); \
\
/* write array of elements onto window buffer */ \
/* _q : window object */ \
/* _v : input array of values to write */ \
/* _n : number of input values to write */ \
void WINDOW(_write)(WINDOW() _q, \
T * _v, \
unsigned int _n); \
// Define window APIs
LIQUID_WINDOW_DEFINE_API(WINDOW_MANGLE_FLOAT, float)
LIQUID_WINDOW_DEFINE_API(WINDOW_MANGLE_CFLOAT, liquid_float_complex)
//LIQUID_WINDOW_DEFINE_API(WINDOW_MANGLE_UINT, unsigned int)
// wdelay functions : windowed-delay
// Implements an efficient z^-k delay with minimal memory
#define WDELAY_MANGLE_FLOAT(name) LIQUID_CONCAT(wdelayf, name)
#define WDELAY_MANGLE_CFLOAT(name) LIQUID_CONCAT(wdelaycf, name)
#define WDELAY_MANGLE_UINT(name) LIQUID_CONCAT(wdelayui, name)
// large macro
// WDELAY : name-mangling macro
// T : data type
#define LIQUID_WDELAY_DEFINE_API(WDELAY,T) \
typedef struct WDELAY(_s) * WDELAY(); \
\
/* create delay buffer object with '_delay' samples */ \
WDELAY() WDELAY(_create)(unsigned int _delay); \
\
/* re-create delay buffer object with '_delay' samples */ \
/* _q : old delay buffer object */ \
/* _delay : delay for new object */ \
WDELAY() WDELAY(_recreate)(WDELAY() _q, \
unsigned int _delay); \
\
/* destroy delay buffer object, freeing internal memory */ \
void WDELAY(_destroy)(WDELAY() _q); \
\
/* print delay buffer object's state to stdout */ \
void WDELAY(_print)(WDELAY() _q); \
\
/* clear/reset state of object */ \
void WDELAY(_reset)(WDELAY() _q); \
\
/* read delayed sample from delay buffer object */ \
/* _q : delay buffer object */ \
/* _v : value of delayed element */ \
void WDELAY(_read)(WDELAY() _q, \
T * _v); \
\
/* push new sample into delay buffer object */ \
/* _q : delay buffer object */ \
/* _v : new value to be added to buffer */ \
void WDELAY(_push)(WDELAY() _q, \
T _v); \
// Define wdelay APIs
LIQUID_WDELAY_DEFINE_API(WDELAY_MANGLE_FLOAT, float)
LIQUID_WDELAY_DEFINE_API(WDELAY_MANGLE_CFLOAT, liquid_float_complex)
//LIQUID_WDELAY_DEFINE_API(WDELAY_MANGLE_UINT, unsigned int)
//
// MODULE : channel
//
#define CHANNEL_MANGLE_CCCF(name) LIQUID_CONCAT(channel_cccf,name)
// large macro
// CHANNEL : name-mangling macro
// TO : output data type
// TC : coefficients data type
// TI : input data type
#define LIQUID_CHANNEL_DEFINE_API(CHANNEL,TO,TC,TI) \
\
typedef struct CHANNEL(_s) * CHANNEL(); \
\
/* create channel object with default parameters */ \
CHANNEL() CHANNEL(_create)(void); \
\
/* destroy channel object, freeing all internal memory */ \
void CHANNEL(_destroy)(CHANNEL() _q); \
\
/* print channel object internals to standard output */ \
void CHANNEL(_print)(CHANNEL() _q); \
\
/* apply additive white Gausss noise impairment */ \
/* _q : channel object */ \
/* _noise_floor_dB : noise floor power spectral density */ \
/* _SNR_dB : signal-to-noise ratio [dB] */ \
void CHANNEL(_add_awgn)(CHANNEL() _q, \
float _noise_floor_dB, \
float _SNRdB); \
\
/* apply carrier offset impairment */ \
/* _q : channel object */ \
/* _frequency : carrier frequency offse [radians/sample */ \
/* _phase : carrier phase offset [radians] */ \
void CHANNEL(_add_carrier_offset)(CHANNEL() _q, \
float _frequency, \
float _phase); \
\
/* apply multi-path channel impairment */ \
/* _q : channel object */ \
/* _h : channel coefficients (NULL for random) */ \
/* _h_len : number of channel coefficients */ \
void CHANNEL(_add_multipath)(CHANNEL() _q, \
TC * _h, \
unsigned int _h_len); \
\
/* apply slowly-varying shadowing impairment */ \
/* _q : channel object */ \
/* _sigma : std. deviation for log-normal shadowing */ \
/* _fd : Doppler frequency, _fd in (0,0.5) */ \
void CHANNEL(_add_shadowing)(CHANNEL() _q, \
float _sigma, \
float _fd); \
\
/* apply channel impairments on single input sample */ \
/* _q : channel object */ \
/* _x : input sample */ \
/* _y : pointer to output sample */ \
void CHANNEL(_execute)(CHANNEL() _q, \
TI _x, \
TO * _y); \
\
/* apply channel impairments on block of samples */ \
/* _q : channel object */ \
/* _x : input array [size: _n x 1] */ \
/* _n : input array length */ \
/* _y : output array [size: _n x 1] */ \
void CHANNEL(_execute_block)(CHANNEL() _q, \
TI * _x, \
unsigned int _n, \
TO * _y); \
LIQUID_CHANNEL_DEFINE_API(CHANNEL_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// time-varying multi-path channel
//
#define TVMPCH_MANGLE_CCCF(name) LIQUID_CONCAT(tvmpch_cccf,name)
// large macro
// TVMPCH : name-mangling macro
// TO : output data type
// TC : coefficients data type
// TI : input data type
#define LIQUID_TVMPCH_DEFINE_API(TVMPCH,TO,TC,TI) \
\
typedef struct TVMPCH(_s) * TVMPCH(); \
\
/* create channel object with default parameters */ \
/* create time-varying multi-path channel emulator object */ \
/* _n : number of coefficients, _n > 0 */ \
/* _std : standard deviation */ \
/* _tau : coherence time */ \
TVMPCH() TVMPCH(_create)(unsigned int _n, \
float _std, \
float _tau); \
\
/* destroy channel object, freeing all internal memory */ \
void TVMPCH(_destroy)(TVMPCH() _q); \
\
/* reset object */ \
void TVMPCH(_reset)(TVMPCH() _q); \
\
/* print channel object internals to standard output */ \
void TVMPCH(_print)(TVMPCH() _q); \
\
/* push sample into emulator */ \
/* _q : channel object */ \
/* _x : input sample */ \
void TVMPCH(_push)(TVMPCH() _q, \
TI _x); \
\
/* compute output sample */ \
/* _q : channel object */ \
/* _y : output sample */ \
void TVMPCH(_execute)(TVMPCH() _q, \
TO * _y); \
\
/* apply channel impairments on a block of samples */ \
/* _q : channel object */ \
/* _x : input array [size: _nx x 1] */ \
/* _nx : input array length */ \
/* _y : output array */ \
void TVMPCH(_execute_block)(TVMPCH() _q, \
TI * _x, \
unsigned int _nx, \
TO * _y); \
LIQUID_TVMPCH_DEFINE_API(TVMPCH_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// MODULE : dotprod (vector dot product)
//
#define DOTPROD_MANGLE_RRRF(name) LIQUID_CONCAT(dotprod_rrrf,name)
#define DOTPROD_MANGLE_CCCF(name) LIQUID_CONCAT(dotprod_cccf,name)
#define DOTPROD_MANGLE_CRCF(name) LIQUID_CONCAT(dotprod_crcf,name)
// large macro
// DOTPROD : name-mangling macro
// TO : output data type
// TC : coefficients data type
// TI : input data type
#define LIQUID_DOTPROD_DEFINE_API(DOTPROD,TO,TC,TI) \
\
/* run dot product without creating object [unrolled loop] */ \
/* _v : coefficients array [size: _n x 1] */ \
/* _x : input array [size: _n x 1] */ \
/* _n : dotprod length, _n > 0 */ \
/* _y : output sample pointer */ \
void DOTPROD(_run)( TC *_v, TI *_x, unsigned int _n, TO *_y); \
void DOTPROD(_run4)(TC *_v, TI *_x, unsigned int _n, TO *_y); \
\
typedef struct DOTPROD(_s) * DOTPROD(); \
\
/* create dot product object */ \
/* _v : coefficients array [size: _n x 1] */ \
/* _n : dotprod length, _n > 0 */ \
DOTPROD() DOTPROD(_create)(TC * _v, \
unsigned int _n); \
\
/* re-create dot product object */ \
/* _q : old dotprod object */ \
/* _v : coefficients array [size: _n x 1] */ \
/* _n : dotprod length, _n > 0 */ \
DOTPROD() DOTPROD(_recreate)(DOTPROD() _q, \
TC * _v, \
unsigned int _n); \
\
/* destroy dotprod object, freeing all internal memory */ \
void DOTPROD(_destroy)(DOTPROD() _q); \
\
/* print dotprod object internals to standard output */ \
void DOTPROD(_print)(DOTPROD() _q); \
\
/* execute dot product */ \
/* _q : dotprod object */ \
/* _x : input array [size: _n x 1] */ \
/* _y : output sample pointer */ \
void DOTPROD(_execute)(DOTPROD() _q, \
TI * _x, \
TO * _y); \
LIQUID_DOTPROD_DEFINE_API(DOTPROD_MANGLE_RRRF,
float,
float,
float)
LIQUID_DOTPROD_DEFINE_API(DOTPROD_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
LIQUID_DOTPROD_DEFINE_API(DOTPROD_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
//
// sum squared methods
//
float liquid_sumsqf(float * _v,
unsigned int _n);
float liquid_sumsqcf(liquid_float_complex * _v,
unsigned int _n);
//
// MODULE : equalization
//
// least mean-squares (LMS)
#define EQLMS_MANGLE_RRRF(name) LIQUID_CONCAT(eqlms_rrrf,name)
#define EQLMS_MANGLE_CCCF(name) LIQUID_CONCAT(eqlms_cccf,name)
// large macro
// EQLMS : name-mangling macro
// T : data type
#define LIQUID_EQLMS_DEFINE_API(EQLMS,T) \
typedef struct EQLMS(_s) * EQLMS(); \
\
/* create LMS EQ initialized with external coefficients */ \
/* _h : filter coefficients (NULL for {1,0,0...}) */ \
/* _h_len : filter length */ \
EQLMS() EQLMS(_create)(T * _h, \
unsigned int _h_len); \
\
/* create LMS EQ initialized with square-root Nyquist */ \
/* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \
/* _k : samples/symbol */ \
/* _m : filter delay (symbols) */ \
/* _beta : rolloff factor (0 < beta <= 1) */ \
/* _dt : fractional sample delay */ \
EQLMS() EQLMS(_create_rnyquist)(int _type, \
unsigned int _k, \
unsigned int _m, \
float _beta, \
float _dt); \
\
/* create LMS EQ initialized with low-pass filter */ \
/* _h_len : filter length */ \
/* _fc : filter cut-off, _fc in (0,0.5] */ \
EQLMS() EQLMS(_create_lowpass)(unsigned int _h_len, \
float _fc); \
\
/* re-create EQ initialized with external coefficients */ \
/* _q : equalizer object */ \
/* _h : filter coefficients (NULL for {1,0,0...}) */ \
/* _h_len : filter length */ \
EQLMS() EQLMS(_recreate)(EQLMS() _q, \
T * _h, \
unsigned int _h_len); \
\
/* destroy equalizer object, freeing all internal memory */ \
void EQLMS(_destroy)(EQLMS() _q); \
\
/* reset equalizer object, clearing internal state */ \
void EQLMS(_reset)(EQLMS() _q); \
\
/* print equalizer internal state */ \
void EQLMS(_print)(EQLMS() _q); \
\
/* get/set equalizer learning rate */ \
float EQLMS(_get_bw)(EQLMS() _q); \
void EQLMS(_set_bw)(EQLMS() _q, \
float _lambda); \
\
/* push sample into equalizer internal buffer */ \
void EQLMS(_push)(EQLMS() _q, \
T _x); \
\
/* push sample into equalizer internal buffer as block */ \
/* _q : equalizer object */ \
/* _x : input sample array */ \
/* _n : input sample array length */ \
void EQLMS(_push_block)(EQLMS() _q, \
T * _x, \
unsigned int _n); \
\
/* execute internal dot product and return result */ \
/* _q : equalizer object */ \
/* _y : output sample */ \
void EQLMS(_execute)(EQLMS() _q, \
T * _y); \
\
/* execute equalizer with block of samples using constant */ \
/* modulus algorithm, operating on a decimation rate of _k */ \
/* samples. */ \
/* _q : equalizer object */ \
/* _k : down-sampling rate */ \
/* _x : input sample array [size: _n x 1] */ \
/* _n : input sample array length */ \
/* _y : output sample array [size: _n x 1] */ \
void EQLMS(_execute_block)(EQLMS() _q, \
unsigned int _k, \
T * _x, \
unsigned int _n, \
T * _y); \
\
/* step through one cycle of equalizer training */ \
/* _q : equalizer object */ \
/* _d : desired output */ \
/* _d_hat : actual output */ \
void EQLMS(_step)(EQLMS() _q, \
T _d, \
T _d_hat); \
\
/* step through one cycle of equalizer training (blind) */ \
/* _q : equalizer object */ \
/* _d_hat : actual output */ \
void EQLMS(_step_blind)(EQLMS() _q, \
T _d_hat); \
\
/* get equalizer's internal coefficients */ \
/* _q : equalizer object */ \
/* _w : weights [size: _p x 1] */ \
void EQLMS(_get_weights)(EQLMS() _q, \
T * _w); \
\
/* train equalizer object on group of samples */ \
/* _q : equalizer object */ \
/* _w : input/output weights [size: _p x 1] */ \
/* _x : received sample vector [size: _n x 1] */ \
/* _d : desired output vector [size: _n x 1] */ \
/* _n : input, output vector length */ \
void EQLMS(_train)(EQLMS() _q, \
T * _w, \
T * _x, \
T * _d, \
unsigned int _n); \
LIQUID_EQLMS_DEFINE_API(EQLMS_MANGLE_RRRF, float);
LIQUID_EQLMS_DEFINE_API(EQLMS_MANGLE_CCCF, liquid_float_complex);
// recursive least-squares (RLS)
#define EQRLS_MANGLE_RRRF(name) LIQUID_CONCAT(eqrls_rrrf,name)
#define EQRLS_MANGLE_CCCF(name) LIQUID_CONCAT(eqrls_cccf,name)
// large macro
// EQRLS : name-mangling macro
// T : data type
#define LIQUID_EQRLS_DEFINE_API(EQRLS,T) \
typedef struct EQRLS(_s) * EQRLS(); \
\
/* create RLS EQ initialized with external coefficients */ \
/* _h : filter coefficients (NULL for {1,0,0...}) */ \
/* _p : filter length */ \
EQRLS() EQRLS(_create)(T * _h, \
unsigned int _p); \
\
/* re-create RLS EQ initialized with external coefficients */ \
/* _q : initial equalizer object */ \
/* _h : filter coefficients (NULL for {1,0,0...}) */ \
/* _p : filter length */ \
EQRLS() EQRLS(_recreate)(EQRLS() _q, \
T * _h, \
unsigned int _p); \
\
/* destroy equalizer object, freeing all internal memory */ \
void EQRLS(_destroy)(EQRLS() _q); \
\
/* print equalizer internal state */ \
void EQRLS(_print)(EQRLS() _q); \
\
/* reset equalizer object, clearing internal state */ \
void EQRLS(_reset)(EQRLS() _q); \
\
/* get/set equalizer learning rate */ \
float EQRLS(_get_bw)(EQRLS() _q); \
void EQRLS(_set_bw)(EQRLS() _q, \
float _mu); \
\
/* push sample into equalizer internal buffer */ \
void EQRLS(_push)(EQRLS() _q, T _x); \
\
/* execute internal dot product and return result */ \
/* _q : equalizer object */ \
/* _y : output sample */ \
void EQRLS(_execute)(EQRLS() _q, T * _y); \
\
/* step through one cycle of equalizer training */ \
/* _q : equalizer object */ \
/* _d : desired output */ \
/* _d_hat : actual output */ \
void EQRLS(_step)(EQRLS() _q, T _d, T _d_hat); \
\
/* retrieve internal filter coefficients */ \
/* _q : equalizer object */ \
/* _w : weights [size: _p x 1] */ \
void EQRLS(_get_weights)(EQRLS() _q, \
T * _w); \
\
/* train equalizer object on group of samples */ \
/* _q : equalizer object */ \
/* _w : input/output weights [size: _p x 1] */ \
/* _x : received sample vector [size: _n x 1] */ \
/* _d : desired output vector [size: _n x 1] */ \
/* _n : input, output vector length */ \
void EQRLS(_train)(EQRLS() _q, \
T * _w, \
T * _x, \
T * _d, \
unsigned int _n);
LIQUID_EQRLS_DEFINE_API(EQRLS_MANGLE_RRRF, float);
LIQUID_EQRLS_DEFINE_API(EQRLS_MANGLE_CCCF, liquid_float_complex);
//
// MODULE : fec (forward error-correction)
//
// soft bit values
#define LIQUID_SOFTBIT_0 (0)
#define LIQUID_SOFTBIT_1 (255)
#define LIQUID_SOFTBIT_ERASURE (127)
// available CRC schemes
#define LIQUID_CRC_NUM_SCHEMES 7
typedef enum {
LIQUID_CRC_UNKNOWN=0, // unknown/unavailable CRC scheme
LIQUID_CRC_NONE, // no error-detection
LIQUID_CRC_CHECKSUM, // 8-bit checksum
LIQUID_CRC_8, // 8-bit CRC
LIQUID_CRC_16, // 16-bit CRC
LIQUID_CRC_24, // 24-bit CRC
LIQUID_CRC_32 // 32-bit CRC
} crc_scheme;
// pretty names for crc schemes
extern const char * crc_scheme_str[LIQUID_CRC_NUM_SCHEMES][2];
// Print compact list of existing and available CRC schemes
void liquid_print_crc_schemes();
// returns crc_scheme based on input string
crc_scheme liquid_getopt_str2crc(const char * _str);
// get length of CRC (bytes)
unsigned int crc_get_length(crc_scheme _scheme);
// generate error-detection key
// _scheme : error-detection scheme
// _msg : input data message, [size: _n x 1]
// _n : input data message size
unsigned int crc_generate_key(crc_scheme _scheme,
unsigned char * _msg,
unsigned int _n);
// generate error-detection key and append to end of message
// _scheme : error-detection scheme (resulting in 'p' bytes)
// _msg : input data message, [size: _n+p x 1]
// _n : input data message size (excluding key at end)
void crc_append_key(crc_scheme _scheme,
unsigned char * _msg,
unsigned int _n);
// validate message using error-detection key
// _scheme : error-detection scheme
// _msg : input data message, [size: _n x 1]
// _n : input data message size
// _key : error-detection key
int crc_validate_message(crc_scheme _scheme,
unsigned char * _msg,
unsigned int _n,
unsigned int _key);
// check message with key appended to end of array
// _scheme : error-detection scheme (resulting in 'p' bytes)
// _msg : input data message, [size: _n+p x 1]
// _n : input data message size (excluding key at end)
int crc_check_key(crc_scheme _scheme,
unsigned char * _msg,
unsigned int _n);
// get size of key (bytes)
unsigned int crc_sizeof_key(crc_scheme _scheme);
// available FEC schemes
#define LIQUID_FEC_NUM_SCHEMES 28
typedef enum {
LIQUID_FEC_UNKNOWN=0, // unknown/unsupported scheme
LIQUID_FEC_NONE, // no error-correction
LIQUID_FEC_REP3, // simple repeat code, r1/3
LIQUID_FEC_REP5, // simple repeat code, r1/5
LIQUID_FEC_HAMMING74, // Hamming (7,4) block code, r1/2 (really 4/7)
LIQUID_FEC_HAMMING84, // Hamming (7,4) with extra parity bit, r1/2
LIQUID_FEC_HAMMING128, // Hamming (12,8) block code, r2/3
LIQUID_FEC_GOLAY2412, // Golay (24,12) block code, r1/2
LIQUID_FEC_SECDED2216, // SEC-DED (22,16) block code, r8/11
LIQUID_FEC_SECDED3932, // SEC-DED (39,32) block code
LIQUID_FEC_SECDED7264, // SEC-DED (72,64) block code, r8/9
// codecs not defined internally (see http://www.ka9q.net/code/fec/)
LIQUID_FEC_CONV_V27, // r1/2, K=7, dfree=10
LIQUID_FEC_CONV_V29, // r1/2, K=9, dfree=12
LIQUID_FEC_CONV_V39, // r1/3, K=9, dfree=18
LIQUID_FEC_CONV_V615, // r1/6, K=15, dfree<=57 (Heller 1968)
// punctured (perforated) codes
LIQUID_FEC_CONV_V27P23, // r2/3, K=7, dfree=6
LIQUID_FEC_CONV_V27P34, // r3/4, K=7, dfree=5
LIQUID_FEC_CONV_V27P45, // r4/5, K=7, dfree=4
LIQUID_FEC_CONV_V27P56, // r5/6, K=7, dfree=4
LIQUID_FEC_CONV_V27P67, // r6/7, K=7, dfree=3
LIQUID_FEC_CONV_V27P78, // r7/8, K=7, dfree=3
LIQUID_FEC_CONV_V29P23, // r2/3, K=9, dfree=7
LIQUID_FEC_CONV_V29P34, // r3/4, K=9, dfree=6
LIQUID_FEC_CONV_V29P45, // r4/5, K=9, dfree=5
LIQUID_FEC_CONV_V29P56, // r5/6, K=9, dfree=5
LIQUID_FEC_CONV_V29P67, // r6/7, K=9, dfree=4
LIQUID_FEC_CONV_V29P78, // r7/8, K=9, dfree=4
// Reed-Solomon codes
LIQUID_FEC_RS_M8 // m=8, n=255, k=223
} fec_scheme;
// pretty names for fec schemes
extern const char * fec_scheme_str[LIQUID_FEC_NUM_SCHEMES][2];
// Print compact list of existing and available FEC schemes
void liquid_print_fec_schemes();
// returns fec_scheme based on input string
fec_scheme liquid_getopt_str2fec(const char * _str);
// fec object (pointer to fec structure)
typedef struct fec_s * fec;
// return the encoded message length using a particular error-
// correction scheme (object-independent method)
// _scheme : forward error-correction scheme
// _msg_len : raw, uncoded message length
unsigned int fec_get_enc_msg_length(fec_scheme _scheme,
unsigned int _msg_len);
// get the theoretical rate of a particular forward error-
// correction scheme (object-independent method)
float fec_get_rate(fec_scheme _scheme);
// create a fec object of a particular scheme
// _scheme : error-correction scheme
// _opts : (ignored)
fec fec_create(fec_scheme _scheme,
void *_opts);
// recreate fec object
// _q : old fec object
// _scheme : new error-correction scheme
// _opts : (ignored)
fec fec_recreate(fec _q,
fec_scheme _scheme,
void *_opts);
// destroy fec object
void fec_destroy(fec _q);
// print fec object internals
void fec_print(fec _q);
// encode a block of data using a fec scheme
// _q : fec object
// _dec_msg_len : decoded message length
// _msg_dec : decoded message
// _msg_enc : encoded message
void fec_encode(fec _q,
unsigned int _dec_msg_len,
unsigned char * _msg_dec,
unsigned char * _msg_enc);
// decode a block of data using a fec scheme
// _q : fec object
// _dec_msg_len : decoded message length
// _msg_enc : encoded message
// _msg_dec : decoded message
void fec_decode(fec _q,
unsigned int _dec_msg_len,
unsigned char * _msg_enc,
unsigned char * _msg_dec);
// decode a block of data using a fec scheme (soft decision)
// _q : fec object
// _dec_msg_len : decoded message length
// _msg_enc : encoded message (soft bits)
// _msg_dec : decoded message
void fec_decode_soft(fec _q,
unsigned int _dec_msg_len,
unsigned char * _msg_enc,
unsigned char * _msg_dec);
//
// Packetizer
//
// computes the number of encoded bytes after packetizing
//
// _n : number of uncoded input bytes
// _crc : error-detecting scheme
// _fec0 : inner forward error-correction code
// _fec1 : outer forward error-correction code
unsigned int packetizer_compute_enc_msg_len(unsigned int _n,
int _crc,
int _fec0,
int _fec1);
// computes the number of decoded bytes before packetizing
//
// _k : number of encoded bytes
// _crc : error-detecting scheme
// _fec0 : inner forward error-correction code
// _fec1 : outer forward error-correction code
unsigned int packetizer_compute_dec_msg_len(unsigned int _k,
int _crc,
int _fec0,
int _fec1);
typedef struct packetizer_s * packetizer;
// create packetizer object
//
// _n : number of uncoded input bytes
// _crc : error-detecting scheme
// _fec0 : inner forward error-correction code
// _fec1 : outer forward error-correction code
packetizer packetizer_create(unsigned int _dec_msg_len,
int _crc,
int _fec0,
int _fec1);
// re-create packetizer object
//
// _p : initialz packetizer object
// _n : number of uncoded input bytes
// _crc : error-detecting scheme
// _fec0 : inner forward error-correction code
// _fec1 : outer forward error-correction code
packetizer packetizer_recreate(packetizer _p,
unsigned int _dec_msg_len,
int _crc,
int _fec0,
int _fec1);
// destroy packetizer object
void packetizer_destroy(packetizer _p);
// print packetizer object internals
void packetizer_print(packetizer _p);
// access methods
unsigned int packetizer_get_dec_msg_len(packetizer _p);
unsigned int packetizer_get_enc_msg_len(packetizer _p);
crc_scheme packetizer_get_crc (packetizer _p);
fec_scheme packetizer_get_fec0 (packetizer _p);
fec_scheme packetizer_get_fec1 (packetizer _p);
// Execute the packetizer on an input message
//
// _p : packetizer object
// _msg : input message (uncoded bytes)
// _pkt : encoded output message
void packetizer_encode(packetizer _p,
const unsigned char * _msg,
unsigned char * _pkt);
// Execute the packetizer to decode an input message, return validity
// check of resulting data
//
// _p : packetizer object
// _pkt : input message (coded bytes)
// _msg : decoded output message
int packetizer_decode(packetizer _p,
const unsigned char * _pkt,
unsigned char * _msg);
// Execute the packetizer to decode an input message, return validity
// check of resulting data
//
// _p : packetizer object
// _pkt : input message (coded soft bits)
// _msg : decoded output message
int packetizer_decode_soft(packetizer _p,
const unsigned char * _pkt,
unsigned char * _msg);
//
// interleaver
//
typedef struct interleaver_s * interleaver;
// create interleaver
// _n : number of bytes
interleaver interleaver_create(unsigned int _n);
// destroy interleaver object
void interleaver_destroy(interleaver _q);
// print interleaver object internals
void interleaver_print(interleaver _q);
// set depth (number of internal iterations)
// _q : interleaver object
// _depth : depth
void interleaver_set_depth(interleaver _q,
unsigned int _depth);
// execute forward interleaver (encoder)
// _q : interleaver object
// _msg_dec : decoded (un-interleaved) message
// _msg_enc : encoded (interleaved) message
void interleaver_encode(interleaver _q,
unsigned char * _msg_dec,
unsigned char * _msg_enc);
// execute forward interleaver (encoder) on soft bits
// _q : interleaver object
// _msg_dec : decoded (un-interleaved) message
// _msg_enc : encoded (interleaved) message
void interleaver_encode_soft(interleaver _q,
unsigned char * _msg_dec,
unsigned char * _msg_enc);
// execute reverse interleaver (decoder)
// _q : interleaver object
// _msg_enc : encoded (interleaved) message
// _msg_dec : decoded (un-interleaved) message
void interleaver_decode(interleaver _q,
unsigned char * _msg_enc,
unsigned char * _msg_dec);
// execute reverse interleaver (decoder) on soft bits
// _q : interleaver object
// _msg_enc : encoded (interleaved) message
// _msg_dec : decoded (un-interleaved) message
void interleaver_decode_soft(interleaver _q,
unsigned char * _msg_enc,
unsigned char * _msg_dec);
//
// MODULE : fft (fast Fourier transform)
//
// type of transform
typedef enum {
LIQUID_FFT_UNKNOWN = 0, // unknown transform type
// regular complex one-dimensional transforms
LIQUID_FFT_FORWARD = +1, // complex one-dimensional FFT
LIQUID_FFT_BACKWARD = -1, // complex one-dimensional inverse FFT
// discrete cosine transforms
LIQUID_FFT_REDFT00 = 10, // real one-dimensional DCT-I
LIQUID_FFT_REDFT10 = 11, // real one-dimensional DCT-II
LIQUID_FFT_REDFT01 = 12, // real one-dimensional DCT-III
LIQUID_FFT_REDFT11 = 13, // real one-dimensional DCT-IV
// discrete sine transforms
LIQUID_FFT_RODFT00 = 20, // real one-dimensional DST-I
LIQUID_FFT_RODFT10 = 21, // real one-dimensional DST-II
LIQUID_FFT_RODFT01 = 22, // real one-dimensional DST-III
LIQUID_FFT_RODFT11 = 23, // real one-dimensional DST-IV
// modified discrete cosine transform
LIQUID_FFT_MDCT = 30, // MDCT
LIQUID_FFT_IMDCT = 31, // IMDCT
} liquid_fft_type;
#define LIQUID_FFT_MANGLE_FLOAT(name) LIQUID_CONCAT(fft,name)
// Macro : FFT
// FFT : name-mangling macro
// T : primitive data type
// TC : primitive data type (complex)
#define LIQUID_FFT_DEFINE_API(FFT,T,TC) \
\
typedef struct FFT(plan_s) * FFT(plan); \
\
/* create regular complex one-dimensional transform */ \
/* _n : transform size */ \
/* _x : pointer to input array [size: _n x 1] */ \
/* _y : pointer to output array [size: _n x 1] */ \
/* _dir : direction (e.g. LIQUID_FFT_FORWARD) */ \
/* _flags : options, optimization */ \
FFT(plan) FFT(_create_plan)(unsigned int _n, \
TC * _x, \
TC * _y, \
int _dir, \
int _flags); \
\
/* create real-to-real transform */ \
/* _n : transform size */ \
/* _x : pointer to input array [size: _n x 1] */ \
/* _y : pointer to output array [size: _n x 1] */ \
/* _type : transform type (e.g. LIQUID_FFT_REDFT00) */ \
/* _flags : options, optimization */ \
FFT(plan) FFT(_create_plan_r2r_1d)(unsigned int _n, \
T * _x, \
T * _y, \
int _type, \
int _flags); \
\
/* destroy transform */ \
void FFT(_destroy_plan)(FFT(plan) _p); \
\
/* print transform plan and internal strategy */ \
void FFT(_print_plan)(FFT(plan) _p); \
\
/* run the transform */ \
void FFT(_execute)(FFT(plan) _p); \
\
/* object-independent methods */ \
\
/* perform n-point FFT allocating plan internally */ \
/* _nfft : fft size */ \
/* _x : input array [size: _nfft x 1] */ \
/* _y : output array [size: _nfft x 1] */ \
/* _dir : fft direction: LIQUID_FFT_{FORWARD,BACKWARD} */ \
/* _flags : fft flags */ \
void FFT(_run)(unsigned int _n, \
TC * _x, \
TC * _y, \
int _dir, \
int _flags); \
\
/* perform n-point real FFT allocating plan internally */ \
/* _nfft : fft size */ \
/* _x : input array [size: _nfft x 1] */ \
/* _y : output array [size: _nfft x 1] */ \
/* _type : fft type, e.g. LIQUID_FFT_REDFT10 */ \
/* _flags : fft flags */ \
void FFT(_r2r_1d_run)(unsigned int _n, \
T * _x, \
T * _y, \
int _type, \
int _flags); \
\
/* perform _n-point fft shift */ \
void FFT(_shift)(TC * _x, \
unsigned int _n); \
LIQUID_FFT_DEFINE_API(LIQUID_FFT_MANGLE_FLOAT,float,liquid_float_complex)
// antiquated fft methods
// FFT(plan) FFT(_create_plan_mdct)(unsigned int _n,
// T * _x,
// T * _y,
// int _kind,
// int _flags);
//
// spectral periodogram
//
#define LIQUID_SPGRAM_MANGLE_CFLOAT(name) LIQUID_CONCAT(spgramcf,name)
#define LIQUID_SPGRAM_MANGLE_FLOAT(name) LIQUID_CONCAT(spgramf, name)
// Macro : SPGRAM
// SPGRAM : name-mangling macro
// T : primitive data type
// TC : primitive data type (complex)
// TI : primitive data type (input)
#define LIQUID_SPGRAM_DEFINE_API(SPGRAM,T,TC,TI) \
\
typedef struct SPGRAM(_s) * SPGRAM(); \
\
/* create spgram object */ \
/* _nfft : FFT size */ \
/* _window : window [size: _window_len x 1] */ \
/* _window_len : window length, _window_len in [1,_nfft] */ \
/* _delay : delay between transforms, _delay > 0 */ \
SPGRAM() SPGRAM(_create)(unsigned int _nfft, \
int _wtype, \
unsigned int _window_len, \
unsigned int _delay); \
\
/* create default spgram object (Kaiser-Bessel window) */ \
SPGRAM() SPGRAM(_create_default)(unsigned int _nfft); \
\
/* destroy spgram object */ \
void SPGRAM(_destroy)(SPGRAM() _q); \
\
/* resets the internal state of the spgram object */ \
void SPGRAM(_reset)(SPGRAM() _q); \
\
/* print internal state of the spgram object */ \
void SPGRAM(_print)(SPGRAM() _q); \
\
/* set methods */ \
int SPGRAM(_set_alpha)(SPGRAM() _q, float _alpha); \
\
/* access methods */ \
unsigned int SPGRAM(_get_nfft) (SPGRAM() _q); \
unsigned int SPGRAM(_get_window_len) (SPGRAM() _q); \
unsigned int SPGRAM(_get_delay) (SPGRAM() _q); \
uint64_t SPGRAM(_get_num_samples) (SPGRAM() _q); \
uint64_t SPGRAM(_get_num_samples_total) (SPGRAM() _q); \
uint64_t SPGRAM(_get_num_transforms) (SPGRAM() _q); \
uint64_t SPGRAM(_get_num_transforms_total)(SPGRAM() _q); \
float SPGRAM(_get_alpha) (SPGRAM() _q); \
\
/* push a single sample into the spgram object */ \
/* _q : spgram object */ \
/* _x : input sample */ \
void SPGRAM(_push)(SPGRAM() _q, \
TI _x); \
\
/* write a block of samples to the spgram object */ \
/* _q : spgram object */ \
/* _x : input buffer [size: _n x 1] */ \
/* _n : input buffer length */ \
void SPGRAM(_write)(SPGRAM() _q, \
TI * _x, \
unsigned int _n); \
\
/* compute spectral periodogram output (fft-shifted values */ \
/* in dB) from current buffer contents */ \
/* _q : spgram object */ \
/* _X : output spectrum (dB) [size: _nfft x 1] */ \
void SPGRAM(_get_psd)(SPGRAM() _q, \
T * _X); \
\
/* export gnuplot file */ \
/* _q : spgram object */ \
/* _filename : input buffer [size: _n x 1] */ \
int SPGRAM(_export_gnuplot)(SPGRAM() _q, \
const char * _filename); \
\
/* object-independent methods */ \
\
/* estimate spectrum on input signal */ \
/* _nfft : FFT size */ \
/* _x : input signal [size: _n x 1] */ \
/* _n : input signal length */ \
/* _psd : output spectrum, [size: _nfft x 1] */ \
void SPGRAM(_estimate_psd)(unsigned int _nfft, \
TI * _x, \
unsigned int _n, \
T * _psd); \
LIQUID_SPGRAM_DEFINE_API(LIQUID_SPGRAM_MANGLE_CFLOAT,
float,
liquid_float_complex,
liquid_float_complex)
LIQUID_SPGRAM_DEFINE_API(LIQUID_SPGRAM_MANGLE_FLOAT,
float,
liquid_float_complex,
float)
//
// asgram : ascii spectral periodogram
//
#define LIQUID_ASGRAM_MANGLE_CFLOAT(name) LIQUID_CONCAT(asgramcf,name)
#define LIQUID_ASGRAM_MANGLE_FLOAT(name) LIQUID_CONCAT(asgramf, name)
// Macro : ASGRAM
// ASGRAM : name-mangling macro
// T : primitive data type
// TC : primitive data type (complex)
// TI : primitive data type (input)
#define LIQUID_ASGRAM_DEFINE_API(ASGRAM,T,TC,TI) \
\
typedef struct ASGRAM(_s) * ASGRAM(); \
\
/* create asgram object with size _nfft */ \
ASGRAM() ASGRAM(_create)(unsigned int _nfft); \
\
/* destroy asgram object */ \
void ASGRAM(_destroy)(ASGRAM() _q); \
\
/* resets the internal state of the asgram object */ \
void ASGRAM(_reset)(ASGRAM() _q); \
\
/* set scale and offset for spectrogram */ \
/* _q : asgram object */ \
/* _offset : signal offset level [dB] */ \
/* _scale : signal scale [dB] */ \
void ASGRAM(_set_scale)(ASGRAM() _q, \
float _offset, \
float _scale); \
\
/* push a single sample into the asgram object */ \
/* _q : asgram object */ \
/* _x : input sample */ \
void ASGRAM(_push)(ASGRAM() _q, \
TI _x); \
\
/* write a block of samples to the asgram object */ \
/* _q : asgram object */ \
/* _x : input buffer [size: _n x 1] */ \
/* _n : input buffer length */ \
void ASGRAM(_write)(ASGRAM() _q, \
TI * _x, \
unsigned int _n); \
\
/* compute spectral periodogram output from current buffer */ \
/* contents */ \
/* _q : spgram object */ \
/* _ascii : output ASCII string [size: _nfft x 1] */ \
/* _peakval : peak power spectral density value [dB] */ \
/* _peakfreq : peak power spectral density frequency */ \
void ASGRAM(_execute)(ASGRAM() _q, \
char * _ascii, \
float * _peakval, \
float * _peakfreq); \
\
/* compute spectral periodogram output from current buffer */ \
/* contents and print standard format to stdout */ \
void ASGRAM(_print)(ASGRAM() _q); \
LIQUID_ASGRAM_DEFINE_API(LIQUID_ASGRAM_MANGLE_CFLOAT,
float,
liquid_float_complex,
liquid_float_complex)
LIQUID_ASGRAM_DEFINE_API(LIQUID_ASGRAM_MANGLE_FLOAT,
float,
liquid_float_complex,
float)
//
// MODULE : filter
//
//
// firdes: finite impulse response filter design
//
// prototypes
typedef enum {
LIQUID_FIRFILT_UNKNOWN=0, // unknown filter type
// Nyquist filter prototypes
LIQUID_FIRFILT_KAISER, // Nyquist Kaiser filter
LIQUID_FIRFILT_PM, // Parks-McClellan filter
LIQUID_FIRFILT_RCOS, // raised-cosine filter
LIQUID_FIRFILT_FEXP, // flipped exponential
LIQUID_FIRFILT_FSECH, // flipped hyperbolic secant
LIQUID_FIRFILT_FARCSECH, // flipped arc-hyperbolic secant
// root-Nyquist filter prototypes
LIQUID_FIRFILT_ARKAISER, // root-Nyquist Kaiser (approximate optimum)
LIQUID_FIRFILT_RKAISER, // root-Nyquist Kaiser (true optimum)
LIQUID_FIRFILT_RRC, // root raised-cosine
LIQUID_FIRFILT_hM3, // harris-Moerder-3 filter
LIQUID_FIRFILT_GMSKTX, // GMSK transmit filter
LIQUID_FIRFILT_GMSKRX, // GMSK receive filter
LIQUID_FIRFILT_RFEXP, // flipped exponential
LIQUID_FIRFILT_RFSECH, // flipped hyperbolic secant
LIQUID_FIRFILT_RFARCSECH, // flipped arc-hyperbolic secant
} liquid_firfilt_type;
// Design (root-)Nyquist filter from prototype
// _type : filter type (e.g. LIQUID_FIRFILT_RRC)
// _k : samples/symbol, _k > 1
// _m : symbol delay, _m > 0
// _beta : excess bandwidth factor, _beta in [0,1)
// _dt : fractional sample delay, _dt in [-1,1]
// _h : output coefficient buffer (length: 2*_k*_m+1)
void liquid_firdes_prototype(liquid_firfilt_type _type,
unsigned int _k,
unsigned int _m,
float _beta,
float _dt,
float * _h);
// returns filter type based on input string
int liquid_getopt_str2firfilt(const char * _str);
// estimate required filter length given
// _df : transition bandwidth (0 < _b < 0.5)
// _As : stop-band attenuation [dB], _As > 0
unsigned int estimate_req_filter_len(float _df,
float _As);
// estimate filter stop-band attenuation given
// _df : transition bandwidth (0 < _b < 0.5)
// _N : filter length
float estimate_req_filter_As(float _df,
unsigned int _N);
// estimate filter transition bandwidth given
// _As : stop-band attenuation [dB], _As > 0
// _N : filter length
float estimate_req_filter_df(float _As,
unsigned int _N);
// returns the Kaiser window beta factor give the filter's target
// stop-band attenuation (As) [Vaidyanathan:1993]
// _As : target filter's stop-band attenuation [dB], _As > 0
float kaiser_beta_As(float _As);
// Design FIR filter using Parks-McClellan algorithm
// band type specifier
typedef enum {
LIQUID_FIRDESPM_BANDPASS=0, // regular band-pass filter
LIQUID_FIRDESPM_DIFFERENTIATOR, // differentiating filter
LIQUID_FIRDESPM_HILBERT // Hilbert transform
} liquid_firdespm_btype;
// weighting type specifier
typedef enum {
LIQUID_FIRDESPM_FLATWEIGHT=0, // flat weighting
LIQUID_FIRDESPM_EXPWEIGHT, // exponential weighting
LIQUID_FIRDESPM_LINWEIGHT, // linear weighting
} liquid_firdespm_wtype;
// run filter design (full life cycle of object)
// _h_len : length of filter (number of taps)
// _num_bands : number of frequency bands
// _bands : band edges, f in [0,0.5], [size: _num_bands x 2]
// _des : desired response [size: _num_bands x 1]
// _weights : response weighting [size: _num_bands x 1]
// _wtype : weight types (e.g. LIQUID_FIRDESPM_FLATWEIGHT) [size: _num_bands x 1]
// _btype : band type (e.g. LIQUID_FIRDESPM_BANDPASS)
// _h : output coefficients array [size: _h_len x 1]
void firdespm_run(unsigned int _h_len,
unsigned int _num_bands,
float * _bands,
float * _des,
float * _weights,
liquid_firdespm_wtype * _wtype,
liquid_firdespm_btype _btype,
float * _h);
// structured object
typedef struct firdespm_s * firdespm;
// create firdespm object
// _h_len : length of filter (number of taps)
// _num_bands : number of frequency bands
// _bands : band edges, f in [0,0.5], [size: _num_bands x 2]
// _des : desired response [size: _num_bands x 1]
// _weights : response weighting [size: _num_bands x 1]
// _wtype : weight types (e.g. LIQUID_FIRDESPM_FLATWEIGHT) [size: _num_bands x 1]
// _btype : band type (e.g. LIQUID_FIRDESPM_BANDPASS)
firdespm firdespm_create(unsigned int _h_len,
unsigned int _num_bands,
float * _bands,
float * _des,
float * _weights,
liquid_firdespm_wtype * _wtype,
liquid_firdespm_btype _btype);
// destroy firdespm object
void firdespm_destroy(firdespm _q);
// print firdespm object internals
void firdespm_print(firdespm _q);
// execute filter design, storing result in _h
void firdespm_execute(firdespm _q, float * _h);
// Design FIR using kaiser window
// _n : filter length, _n > 0
// _fc : cutoff frequency, 0 < _fc < 0.5
// _As : stop-band attenuation [dB], _As > 0
// _mu : fractional sample offset, -0.5 < _mu < 0.5
// _h : output coefficient buffer, [size: _n x 1]
void liquid_firdes_kaiser(unsigned int _n,
float _fc,
float _As,
float _mu,
float *_h);
// Design FIR doppler filter
// _n : filter length
// _fd : normalized doppler frequency (0 < _fd < 0.5)
// _K : Rice fading factor (K >= 0)
// _theta : LoS component angle of arrival
// _h : output coefficient buffer
void liquid_firdes_doppler(unsigned int _n,
float _fd,
float _K,
float _theta,
float * _h);
// Design Nyquist raised-cosine filter
// _k : samples/symbol
// _m : symbol delay
// _beta : rolloff factor (0 < beta <= 1)
// _dt : fractional sample delay
// _h : output coefficient buffer (length: 2*k*m+1)
void liquid_firdes_rcos(unsigned int _k,
unsigned int _m,
float _beta,
float _dt,
float * _h);
// Design root-Nyquist raised-cosine filter
void liquid_firdes_rrcos(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
// Design root-Nyquist Kaiser filter
void liquid_firdes_rkaiser(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
// Design (approximate) root-Nyquist Kaiser filter
void liquid_firdes_arkaiser(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
// Design root-Nyquist harris-Moerder filter
void liquid_firdes_hM3(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
// Design GMSK transmit and receive filters
void liquid_firdes_gmsktx(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
void liquid_firdes_gmskrx(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
// Design flipped exponential Nyquist/root-Nyquist filters
void liquid_firdes_fexp( unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
void liquid_firdes_rfexp(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
// Design flipped hyperbolic secand Nyquist/root-Nyquist filters
void liquid_firdes_fsech( unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
void liquid_firdes_rfsech(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
// Design flipped arc-hyperbolic secand Nyquist/root-Nyquist filters
void liquid_firdes_farcsech( unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
void liquid_firdes_rfarcsech(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
// Compute group delay for an FIR filter
// _h : filter coefficients array
// _n : filter length
// _fc : frequency at which delay is evaluated (-0.5 < _fc < 0.5)
float fir_group_delay(float * _h,
unsigned int _n,
float _fc);
// Compute group delay for an IIR filter
// _b : filter numerator coefficients
// _nb : filter numerator length
// _a : filter denominator coefficients
// _na : filter denominator length
// _fc : frequency at which delay is evaluated (-0.5 < _fc < 0.5)
float iir_group_delay(float * _b,
unsigned int _nb,
float * _a,
unsigned int _na,
float _fc);
// liquid_filter_autocorr()
//
// Compute auto-correlation of filter at a specific lag.
//
// _h : filter coefficients [size: _h_len x 1]
// _h_len : filter length
// _lag : auto-correlation lag (samples)
float liquid_filter_autocorr(float * _h,
unsigned int _h_len,
int _lag);
// liquid_filter_crosscorr()
//
// Compute cross-correlation of two filters at a specific lag.
//
// _h : filter coefficients [size: _h_len]
// _h_len : filter length
// _g : filter coefficients [size: _g_len]
// _g_len : filter length
// _lag : cross-correlation lag (samples)
float liquid_filter_crosscorr(float * _h,
unsigned int _h_len,
float * _g,
unsigned int _g_len,
int _lag);
// liquid_filter_isi()
//
// Compute inter-symbol interference (ISI)--both RMS and
// maximum--for the filter _h.
//
// _h : filter coefficients [size: 2*_k*_m+1 x 1]
// _k : filter over-sampling rate (samples/symbol)
// _m : filter delay (symbols)
// _rms : output root mean-squared ISI
// _max : maximum ISI
void liquid_filter_isi(float * _h,
unsigned int _k,
unsigned int _m,
float * _rms,
float * _max);
// Compute relative out-of-band energy
//
// _h : filter coefficients [size: _h_len x 1]
// _h_len : filter length
// _fc : analysis cut-off frequency
// _nfft : fft size
float liquid_filter_energy(float * _h,
unsigned int _h_len,
float _fc,
unsigned int _nfft);
//
// IIR filter design
//
// IIR filter design filter type
typedef enum {
LIQUID_IIRDES_BUTTER=0,
LIQUID_IIRDES_CHEBY1,
LIQUID_IIRDES_CHEBY2,
LIQUID_IIRDES_ELLIP,
LIQUID_IIRDES_BESSEL
} liquid_iirdes_filtertype;
// IIR filter design band type
typedef enum {
LIQUID_IIRDES_LOWPASS=0,
LIQUID_IIRDES_HIGHPASS,
LIQUID_IIRDES_BANDPASS,
LIQUID_IIRDES_BANDSTOP
} liquid_iirdes_bandtype;
// IIR filter design coefficients format
typedef enum {
LIQUID_IIRDES_SOS=0,
LIQUID_IIRDES_TF
} liquid_iirdes_format;
// IIR filter design template
// _ftype : filter type (e.g. LIQUID_IIRDES_BUTTER)
// _btype : band type (e.g. LIQUID_IIRDES_BANDPASS)
// _format : coefficients format (e.g. LIQUID_IIRDES_SOS)
// _n : filter order
// _fc : low-pass prototype cut-off frequency
// _f0 : center frequency (band-pass, band-stop)
// _Ap : pass-band ripple in dB
// _As : stop-band ripple in dB
// _B : numerator
// _A : denominator
void liquid_iirdes(liquid_iirdes_filtertype _ftype,
liquid_iirdes_bandtype _btype,
liquid_iirdes_format _format,
unsigned int _n,
float _fc,
float _f0,
float _Ap,
float _As,
float * _B,
float * _A);
// compute analog zeros, poles, gain for specific filter types
void butter_azpkf(unsigned int _n,
liquid_float_complex * _za,
liquid_float_complex * _pa,
liquid_float_complex * _ka);
void cheby1_azpkf(unsigned int _n,
float _ep,
liquid_float_complex * _z,
liquid_float_complex * _p,
liquid_float_complex * _k);
void cheby2_azpkf(unsigned int _n,
float _es,
liquid_float_complex * _z,
liquid_float_complex * _p,
liquid_float_complex * _k);
void ellip_azpkf(unsigned int _n,
float _ep,
float _es,
liquid_float_complex * _z,
liquid_float_complex * _p,
liquid_float_complex * _k);
void bessel_azpkf(unsigned int _n,
liquid_float_complex * _z,
liquid_float_complex * _p,
liquid_float_complex * _k);
// compute frequency pre-warping factor
float iirdes_freqprewarp(liquid_iirdes_bandtype _btype,
float _fc,
float _f0);
// convert analog z/p/k form to discrete z/p/k form (bilinear z-transform)
// _za : analog zeros [length: _nza]
// _nza : number of analog zeros
// _pa : analog poles [length: _npa]
// _npa : number of analog poles
// _m : frequency pre-warping factor
// _zd : output digital zeros [length: _npa]
// _pd : output digital poles [length: _npa]
// _kd : output digital gain (should actually be real-valued)
void bilinear_zpkf(liquid_float_complex * _za,
unsigned int _nza,
liquid_float_complex * _pa,
unsigned int _npa,
liquid_float_complex _ka,
float _m,
liquid_float_complex * _zd,
liquid_float_complex * _pd,
liquid_float_complex * _kd);
// digital z/p/k low-pass to high-pass
// _zd : digital zeros (low-pass prototype), [length: _n]
// _pd : digital poles (low-pass prototype), [length: _n]
// _n : low-pass filter order
// _zdt : output digital zeros transformed [length: _n]
// _pdt : output digital poles transformed [length: _n]
void iirdes_dzpk_lp2hp(liquid_float_complex * _zd,
liquid_float_complex * _pd,
unsigned int _n,
liquid_float_complex * _zdt,
liquid_float_complex * _pdt);
// digital z/p/k low-pass to band-pass
// _zd : digital zeros (low-pass prototype), [length: _n]
// _pd : digital poles (low-pass prototype), [length: _n]
// _n : low-pass filter order
// _f0 : center frequency
// _zdt : output digital zeros transformed [length: 2*_n]
// _pdt : output digital poles transformed [length: 2*_n]
void iirdes_dzpk_lp2bp(liquid_float_complex * _zd,
liquid_float_complex * _pd,
unsigned int _n,
float _f0,
liquid_float_complex * _zdt,
liquid_float_complex * _pdt);
// convert discrete z/p/k form to transfer function
// _zd : digital zeros [length: _n]
// _pd : digital poles [length: _n]
// _n : filter order
// _kd : digital gain
// _b : output numerator [length: _n+1]
// _a : output denominator [length: _n+1]
void iirdes_dzpk2tff(liquid_float_complex * _zd,
liquid_float_complex * _pd,
unsigned int _n,
liquid_float_complex _kd,
float * _b,
float * _a);
// convert discrete z/p/k form to second-order sections
// _zd : digital zeros [length: _n]
// _pd : digital poles [length: _n]
// _n : filter order
// _kd : digital gain
// _B : output numerator [size: 3 x L+r]
// _A : output denominator [size: 3 x L+r]
// where r = _n%2, L = (_n-r)/2
void iirdes_dzpk2sosf(liquid_float_complex * _zd,
liquid_float_complex * _pd,
unsigned int _n,
liquid_float_complex _kd,
float * _B,
float * _A);
// additional IIR filter design templates
// design 2nd-order IIR filter (active lag)
// 1 + t2 * s
// F(s) = ------------
// 1 + t1 * s
//
// _w : filter bandwidth
// _zeta : damping factor (1/sqrt(2) suggested)
// _K : loop gain (1000 suggested)
// _b : output feed-forward coefficients [size: 3 x 1]
// _a : output feed-back coefficients [size: 3 x 1]
void iirdes_pll_active_lag(float _w,
float _zeta,
float _K,
float * _b,
float * _a);
// design 2nd-order IIR filter (active PI)
// 1 + t2 * s
// F(s) = ------------
// t1 * s
//
// _w : filter bandwidth
// _zeta : damping factor (1/sqrt(2) suggested)
// _K : loop gain (1000 suggested)
// _b : output feed-forward coefficients [size: 3 x 1]
// _a : output feed-back coefficients [size: 3 x 1]
void iirdes_pll_active_PI(float _w,
float _zeta,
float _K,
float * _b,
float * _a);
// checks stability of iir filter
// _b : feed-forward coefficients [size: _n x 1]
// _a : feed-back coefficients [size: _n x 1]
// _n : number of coefficients
int iirdes_isstable(float * _b,
float * _a,
unsigned int _n);
//
// linear prediction
//
// compute the linear prediction coefficients for an input signal _x
// _x : input signal [size: _n x 1]
// _n : input signal length
// _p : prediction filter order
// _a : prediction filter [size: _p+1 x 1]
// _e : prediction error variance [size: _p+1 x 1]
void liquid_lpc(float * _x,
unsigned int _n,
unsigned int _p,
float * _a,
float * _g);
// solve the Yule-Walker equations using Levinson-Durbin recursion
// for _symmetric_ autocorrelation
// _r : autocorrelation array [size: _p+1 x 1]
// _p : filter order
// _a : output coefficients [size: _p+1 x 1]
// _e : error variance [size: _p+1 x 1]
//
// NOTES:
// By definition _a[0] = 1.0
void liquid_levinson(float * _r,
unsigned int _p,
float * _a,
float * _e);
//
// auto-correlator (delay cross-correlation)
//
#define AUTOCORR_MANGLE_CCCF(name) LIQUID_CONCAT(autocorr_cccf,name)
#define AUTOCORR_MANGLE_RRRF(name) LIQUID_CONCAT(autocorr_rrrf,name)
// Macro:
// AUTOCORR : name-mangling macro
// TO : output data type
// TC : coefficients data type
// TI : input data type
#define LIQUID_AUTOCORR_DEFINE_API(AUTOCORR,TO,TC,TI) \
\
typedef struct AUTOCORR(_s) * AUTOCORR(); \
\
/* create auto-correlator object */ \
/* _window_size : size of the correlator window */ \
/* _delay : correlator delay [samples] */ \
AUTOCORR() AUTOCORR(_create)(unsigned int _window_size, \
unsigned int _delay); \
\
/* destroy auto-correlator object, freeing internal memory */ \
void AUTOCORR(_destroy)(AUTOCORR() _q); \
\
/* reset auto-correlator object's internals */ \
void AUTOCORR(_reset)(AUTOCORR() _q); \
\
/* print auto-correlator parameters to stdout */ \
void AUTOCORR(_print)(AUTOCORR() _q); \
\
/* push sample into auto-correlator object */ \
void AUTOCORR(_push)(AUTOCORR() _q, \
TI _x); \
\
/* compute single auto-correlation output */ \
void AUTOCORR(_execute)(AUTOCORR() _q, \
TO * _rxx); \
\
/* compute auto-correlation on block of samples; the input */ \
/* and output arrays may have the same pointer */ \
/* _q : auto-correlation object */ \
/* _x : input array [size: _n x 1] */ \
/* _n : number of input, output samples */ \
/* _rxx : input array [size: _n x 1] */ \
void AUTOCORR(_execute_block)(AUTOCORR() _q, \
TI * _x, \
unsigned int _n, \
TO * _rxx); \
\
/* return sum of squares of buffered samples */ \
float AUTOCORR(_get_energy)(AUTOCORR() _q); \
LIQUID_AUTOCORR_DEFINE_API(AUTOCORR_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
LIQUID_AUTOCORR_DEFINE_API(AUTOCORR_MANGLE_RRRF,
float,
float,
float)
//
// Finite impulse response filter
//
#define FIRFILT_MANGLE_RRRF(name) LIQUID_CONCAT(firfilt_rrrf,name)
#define FIRFILT_MANGLE_CRCF(name) LIQUID_CONCAT(firfilt_crcf,name)
#define FIRFILT_MANGLE_CCCF(name) LIQUID_CONCAT(firfilt_cccf,name)
// Macro:
// FIRFILT : name-mangling macro
// TO : output data type
// TC : coefficients data type
// TI : input data type
#define LIQUID_FIRFILT_DEFINE_API(FIRFILT,TO,TC,TI) \
typedef struct FIRFILT(_s) * FIRFILT(); \
\
FIRFILT() FIRFILT(_create)(TC * _h, unsigned int _n); \
\
/* create using Kaiser-Bessel windowed sinc method */ \
/* _n : filter length, _n > 0 */ \
/* _fc : filter cut-off frequency 0 < _fc < 0.5 */ \
/* _As : filter stop-band attenuation [dB], _As > 0 */ \
/* _mu : fractional sample offset, -0.5 < _mu < 0.5 */ \
FIRFILT() FIRFILT(_create_kaiser)(unsigned int _n, \
float _fc, \
float _As, \
float _mu); \
\
/* create from square-root Nyquist prototype */ \
/* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \
/* _k : nominal samples/symbol, _k > 1 */ \
/* _m : filter delay [symbols], _m > 0 */ \
/* _beta : rolloff factor, 0 < beta <= 1 */ \
/* _mu : fractional sample offset,-0.5 < _mu < 0.5 */ \
FIRFILT() FIRFILT(_create_rnyquist)(int _type, \
unsigned int _k, \
unsigned int _m, \
float _beta, \
float _mu); \
\
/* create rectangular filter prototype */ \
FIRFILT() FIRFILT(_create_rect)(unsigned int _n); \
\
/* re-create filter */ \
/* _q : original filter object */ \
/* _h : pointer to filter coefficients [size: _n x 1] */ \
/* _n : filter length, _n > 0 */ \
FIRFILT() FIRFILT(_recreate)(FIRFILT() _q, \
TC * _h, \
unsigned int _n); \
\
/* destroy filter object and free all internal memory */ \
void FIRFILT(_destroy)(FIRFILT() _q); \
\
/* reset filter object's internal buffer */ \
void FIRFILT(_reset)(FIRFILT() _q); \
\
/* print filter object information */ \
void FIRFILT(_print)(FIRFILT() _q); \
\
/* set output scaling for filter */ \
void FIRFILT(_set_scale)(FIRFILT() _q, \
TC _scale); \
\
/* push sample into filter object's internal buffer */ \
/* _q : filter object */ \
/* _x : single input sample */ \
void FIRFILT(_push)(FIRFILT() _q, \
TI _x); \
\
/* execute the filter on internal buffer and coefficients */ \
/* _q : filter object */ \
/* _y : pointer to single output sample */ \
void FIRFILT(_execute)(FIRFILT() _q, \
TO * _y); \
\
/* execute the filter on a block of input samples; the */ \
/* input and output buffers may be the same */ \
/* _q : filter object */ \
/* _x : pointer to input array [size: _n x 1] */ \
/* _n : number of input, output samples */ \
/* _y : pointer to output array [size: _n x 1] */ \
void FIRFILT(_execute_block)(FIRFILT() _q, \
TI * _x, \
unsigned int _n, \
TO * _y); \
\
/* return length of filter object */ \
unsigned int FIRFILT(_get_length)(FIRFILT() _q); \
\
/* compute complex frequency response of filter object */ \
/* _q : filter object */ \
/* _fc : frequency to evaluate */ \
/* _H : pointer to output complex frequency response */ \
void FIRFILT(_freqresponse)(FIRFILT() _q, \
float _fc, \
liquid_float_complex * _H); \
\
/* compute and return group delay of filter object */ \
/* _q : filter object */ \
/* _fc : frequency to evaluate */ \
float FIRFILT(_groupdelay)(FIRFILT() _q, \
float _fc); \
LIQUID_FIRFILT_DEFINE_API(FIRFILT_MANGLE_RRRF,
float,
float,
float)
LIQUID_FIRFILT_DEFINE_API(FIRFILT_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_FIRFILT_DEFINE_API(FIRFILT_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// FIR Hilbert transform
// 2:1 real-to-complex decimator
// 1:2 complex-to-real interpolator
//
#define FIRHILB_MANGLE_FLOAT(name) LIQUID_CONCAT(firhilbf, name)
//#define FIRHILB_MANGLE_DOUBLE(name) LIQUID_CONCAT(firhilb, name)
// NOTES:
// Although firhilb is a placeholder for both decimation and
// interpolation, separate objects should be used for each task.
#define LIQUID_FIRHILB_DEFINE_API(FIRHILB,T,TC) \
typedef struct FIRHILB(_s) * FIRHILB(); \
\
/* create finite impulse reponse Hilbert transform */ \
/* _m : filter semi-length, delay is 2*m+1 */ \
/* _As : filter stop-band attenuation [dB] */ \
FIRHILB() FIRHILB(_create)(unsigned int _m, \
float _As); \
\
/* destroy finite impulse reponse Hilbert transform */ \
void FIRHILB(_destroy)(FIRHILB() _q); \
\
/* print firhilb object internals to stdout */ \
void FIRHILB(_print)(FIRHILB() _q); \
\
/* reset firhilb object internal state */ \
void FIRHILB(_reset)(FIRHILB() _q); \
\
/* execute Hilbert transform (real to complex) */ \
/* _q : Hilbert transform object */ \
/* _x : real-valued input sample */ \
/* _y : complex-valued output sample */ \
void FIRHILB(_r2c_execute)(FIRHILB() _q, \
T _x, \
TC * _y); \
\
/* execute Hilbert transform (complex to real) */ \
/* _q : Hilbert transform object */ \
/* _x : complex-valued input sample */ \
/* _y : real-valued output sample */ \
void FIRHILB(_c2r_execute)(FIRHILB() _q, \
TC _x, \
T * _y); \
\
/* execute Hilbert transform decimator (real to complex) */ \
/* _q : Hilbert transform object */ \
/* _x : real-valued input array [size: 2 x 1] */ \
/* _y : complex-valued output sample */ \
void FIRHILB(_decim_execute)(FIRHILB() _q, \
T * _x, \
TC * _y); \
\
/* execute Hilbert transform decimator (real to complex) on */ \
/* a block of samples */ \
/* _q : Hilbert transform object */ \
/* _x : real-valued input array [size: 2*_n x 1] */ \
/* _n : number of *output* samples */ \
/* _y : complex-valued output array [size: _n x 1] */ \
void FIRHILB(_decim_execute_block)(FIRHILB() _q, \
T * _x, \
unsigned int _n, \
TC * _y); \
\
/* execute Hilbert transform interpolator (real to complex) */ \
/* _q : Hilbert transform object */ \
/* _x : complex-valued input sample */ \
/* _y : real-valued output array [size: 2 x 1] */ \
void FIRHILB(_interp_execute)(FIRHILB() _q, \
TC _x, \
T * _y); \
\
/* execute Hilbert transform interpolator (complex to real) */ \
/* on a block of samples */ \
/* _q : Hilbert transform object */ \
/* _x : complex-valued input array [size: _n x 1] */ \
/* _n : number of *input* samples */ \
/* _y : real-valued output array [size: 2*_n x 1] */ \
void FIRHILB(_interp_execute_block)(FIRHILB() _q, \
TC * _x, \
unsigned int _n, \
T * _y); \
LIQUID_FIRHILB_DEFINE_API(FIRHILB_MANGLE_FLOAT, float, liquid_float_complex)
//LIQUID_FIRHILB_DEFINE_API(FIRHILB_MANGLE_DOUBLE, double, liquid_double_complex)
//
// FFT-based finite impulse response filter
//
#define FFTFILT_MANGLE_RRRF(name) LIQUID_CONCAT(fftfilt_rrrf,name)
#define FFTFILT_MANGLE_CRCF(name) LIQUID_CONCAT(fftfilt_crcf,name)
#define FFTFILT_MANGLE_CCCF(name) LIQUID_CONCAT(fftfilt_cccf,name)
// Macro:
// FFTFILT : name-mangling macro
// TO : output data type
// TC : coefficients data type
// TI : input data type
#define LIQUID_FFTFILT_DEFINE_API(FFTFILT,TO,TC,TI) \
typedef struct FFTFILT(_s) * FFTFILT(); \
\
/* create FFT-based FIR filter using external coefficients */ \
/* _h : filter coefficients [size: _h_len x 1] */ \
/* _h_len : filter length, _h_len > 0 */ \
/* _n : block size = nfft/2, at least _h_len-1 */ \
FFTFILT() FFTFILT(_create)(TC * _h, \
unsigned int _h_len, \
unsigned int _n); \
\
/* destroy filter object and free all internal memory */ \
void FFTFILT(_destroy)(FFTFILT() _q); \
\
/* reset filter object's internal buffer */ \
void FFTFILT(_reset)(FFTFILT() _q); \
\
/* print filter object information */ \
void FFTFILT(_print)(FFTFILT() _q); \
\
/* set output scaling for filter */ \
void FFTFILT(_set_scale)(FFTFILT() _q, \
TC _scale); \
\
/* execute the filter on internal buffer and coefficients */ \
/* _q : filter object */ \
/* _x : pointer to input data array [size: _n x 1] */ \
/* _y : pointer to output data array [size: _n x 1] */ \
void FFTFILT(_execute)(FFTFILT() _q, \
TI * _x, \
TO * _y); \
\
/* return length of filter object's internal coefficients */ \
unsigned int FFTFILT(_get_length)(FFTFILT() _q); \
LIQUID_FFTFILT_DEFINE_API(FFTFILT_MANGLE_RRRF,
float,
float,
float)
LIQUID_FFTFILT_DEFINE_API(FFTFILT_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_FFTFILT_DEFINE_API(FFTFILT_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// Infinite impulse response filter
//
#define IIRFILT_MANGLE_RRRF(name) LIQUID_CONCAT(iirfilt_rrrf,name)
#define IIRFILT_MANGLE_CRCF(name) LIQUID_CONCAT(iirfilt_crcf,name)
#define IIRFILT_MANGLE_CCCF(name) LIQUID_CONCAT(iirfilt_cccf,name)
// Macro:
// IIRFILT : name-mangling macro
// TO : output data type
// TC : coefficients data type
// TI : input data type
#define LIQUID_IIRFILT_DEFINE_API(IIRFILT,TO,TC,TI) \
\
typedef struct IIRFILT(_s) * IIRFILT(); \
\
/* create infinite impulse reponse filter */ \
/* _b : feed-forward coefficients [size: _nb x 1] */ \
/* _nb : number of feed-forward coefficients */ \
/* _a : feed-back coefficients [size: _na x 1] */ \
/* _na : number of feed-back coefficients */ \
IIRFILT() IIRFILT(_create)(TC * _b, \
unsigned int _nb, \
TC * _a, \
unsigned int _na); \
\
/* create IIR filter using 2nd-order secitons */ \
/* _B : feed-forward coefficients [size: _nsos x 3] */ \
/* _A : feed-back coefficients [size: _nsos x 3] */ \
IIRFILT() IIRFILT(_create_sos)(TC * _B, \
TC * _A, \
unsigned int _nsos); \
\
/* create IIR filter from design template */ \
/* _ftype : filter type (e.g. LIQUID_IIRDES_BUTTER) */ \
/* _btype : band type (e.g. LIQUID_IIRDES_BANDPASS) */ \
/* _format : coefficients format (e.g. LIQUID_IIRDES_SOS) */ \
/* _n : filter order */ \
/* _fc : low-pass prototype cut-off frequency */ \
/* _f0 : center frequency (band-pass, band-stop) */ \
/* _Ap : pass-band ripple in dB */ \
/* _As : stop-band ripple in dB */ \
IIRFILT() IIRFILT(_create_prototype)( \
liquid_iirdes_filtertype _ftype, \
liquid_iirdes_bandtype _btype, \
liquid_iirdes_format _format, \
unsigned int _order, \
float _fc, \
float _f0, \
float _Ap, \
float _As); \
\
/* create simplified low-pass Butterworth IIR filter */ \
/* _n : filter order */ \
/* _fc : low-pass prototype cut-off frequency */ \
IIRFILT() IIRFILT(_create_lowpass)( \
unsigned int _order, \
float _fc); \
\
/* create 8th-order integrator filter */ \
IIRFILT() IIRFILT(_create_integrator)(); \
\
/* create 8th-order differentiator filter */ \
IIRFILT() IIRFILT(_create_differentiator)(); \
\
/* create simple DC-blocking filter */ \
IIRFILT() IIRFILT(_create_dc_blocker)(float _alpha); \
\
/* create phase-locked loop iirfilt object */ \
/* _w : filter bandwidth */ \
/* _zeta : damping factor (1/sqrt(2) suggested) */ \
/* _K : loop gain (1000 suggested) */ \
IIRFILT() IIRFILT(_create_pll)(float _w, \
float _zeta, \
float _K); \
\
/* destroy iirfilt object, freeing all internal memory */ \
void IIRFILT(_destroy)(IIRFILT() _q); \
\
/* print iirfilt object properties to stdout */ \
void IIRFILT(_print)(IIRFILT() _q); \
\
/* clear/reset iirfilt object internals */ \
void IIRFILT(_reset)(IIRFILT() _q); \
\
/* compute filter output */ \
/* _q : iirfilt object */ \
/* _x : input sample */ \
/* _y : output sample pointer */ \
void IIRFILT(_execute)(IIRFILT() _q, \
TI _x, \
TO * _y); \
\
/* execute the filter on a block of input samples; the */ \
/* input and output buffers may be the same */ \
/* _q : filter object */ \
/* _x : pointer to input array [size: _n x 1] */ \
/* _n : number of input, output samples */ \
/* _y : pointer to output array [size: _n x 1] */ \
void IIRFILT(_execute_block)(IIRFILT() _q, \
TI * _x, \
unsigned int _n, \
TO * _y); \
\
/* return iirfilt object's filter length (order + 1) */ \
unsigned int IIRFILT(_get_length)(IIRFILT() _q); \
\
/* compute complex frequency response of filter object */ \
/* _q : filter object */ \
/* _fc : frequency to evaluate */ \
/* _H : pointer to output complex frequency response */ \
void IIRFILT(_freqresponse)(IIRFILT() _q, \
float _fc, \
liquid_float_complex * _H); \
\
/* compute and return group delay of filter object */ \
/* _q : filter object */ \
/* _fc : frequency to evaluate */ \
float IIRFILT(_groupdelay)(IIRFILT() _q, float _fc); \
LIQUID_IIRFILT_DEFINE_API(IIRFILT_MANGLE_RRRF,
float,
float,
float)
LIQUID_IIRFILT_DEFINE_API(IIRFILT_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_IIRFILT_DEFINE_API(IIRFILT_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// FIR Polyphase filter bank
//
#define FIRPFB_MANGLE_RRRF(name) LIQUID_CONCAT(firpfb_rrrf,name)
#define FIRPFB_MANGLE_CRCF(name) LIQUID_CONCAT(firpfb_crcf,name)
#define FIRPFB_MANGLE_CCCF(name) LIQUID_CONCAT(firpfb_cccf,name)
// Macro:
// FIRPFB : name-mangling macro
// TO : output data type
// TC : coefficients data type
// TI : input data type
#define LIQUID_FIRPFB_DEFINE_API(FIRPFB,TO,TC,TI) \
\
typedef struct FIRPFB(_s) * FIRPFB(); \
\
/* create firpfb from external coefficients */ \
/* _M : number of filters in the bank */ \
/* _h : coefficients [size: _M*_h_len x 1] */ \
/* _h_len : filter delay (symbols) */ \
FIRPFB() FIRPFB(_create)(unsigned int _M, \
TC * _h, \
unsigned int _h_len); \
\
/* create firpfb from external coefficients */ \
/* _M : number of filters in the bank */ \
/* _m : filter semi-length [samples] */ \
/* _fc : filter cut-off frequency 0 < _fc < 0.5 */ \
/* _As : filter stop-band suppression [dB] */ \
FIRPFB() FIRPFB(_create_kaiser)(unsigned int _M, \
unsigned int _m, \
float _fc, \
float _As); \
\
/* create firpfb from square-root Nyquist prototype */ \
/* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \
/* _npfb : number of filters in the bank */ \
/* _k : nominal samples/symbol */ \
/* _m : filter delay (symbols) */ \
/* _beta : rolloff factor (0 < beta <= 1) */ \
FIRPFB() FIRPFB(_create_rnyquist)(int _type, \
unsigned int _npfb, \
unsigned int _k, \
unsigned int _m, \
float _beta); \
\
/* create from square-root derivative Nyquist prototype */ \
/* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \
/* _npfb : number of filters in the bank */ \
/* _k : nominal samples/symbol */ \
/* _m : filter delay (symbols) */ \
/* _beta : rolloff factor (0 < beta <= 1) */ \
FIRPFB() FIRPFB(_create_drnyquist)(int _type, \
unsigned int _npfb, \
unsigned int _k, \
unsigned int _m, \
float _beta); \
\
/* re-create filterbank object */ \
/* _q : original firpfb object */ \
/* _M : number of filters in the bank */ \
/* _h : coefficients [size: _M x _h_len] */ \
/* _h_len : length of each filter */ \
FIRPFB() FIRPFB(_recreate)(FIRPFB() _q, \
unsigned int _M, \
TC * _h, \
unsigned int _h_len); \
\
/* destroy firpfb object, freeing all internal memory */ \
void FIRPFB(_destroy)(FIRPFB() _q); \
\
/* print firpfb object's parameters */ \
void FIRPFB(_print)(FIRPFB() _q); \
\
/* set output scaling for filter */ \
void FIRPFB(_set_scale)(FIRPFB() _q, \
TC _g); \
\
/* clear/reset firpfb object internal state */ \
void FIRPFB(_reset)(FIRPFB() _q); \
\
/* push sample into firpfb internal buffer */ \
void FIRPFB(_push)(FIRPFB() _q, TI _x); \
\
/* execute the filter on internal buffer and coefficients */ \
/* _q : firpfb object */ \
/* _i : index of filter to use */ \
/* _y : pointer to output sample */ \
void FIRPFB(_execute)(FIRPFB() _q, \
unsigned int _i, \
TO * _y); \
\
/* execute the filter on a block of input samples; the */ \
/* input and output buffers may be the same */ \
/* _q : firpfb object */ \
/* _i : index of filter to use */ \
/* _x : pointer to input array [size: _n x 1] */ \
/* _n : number of input, output samples */ \
/* _y : pointer to output array [size: _n x 1] */ \
void FIRPFB(_execute_block)(FIRPFB() _q, \
unsigned int _i, \
TI * _x, \
unsigned int _n, \
TO * _y); \
LIQUID_FIRPFB_DEFINE_API(FIRPFB_MANGLE_RRRF,
float,
float,
float)
LIQUID_FIRPFB_DEFINE_API(FIRPFB_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_FIRPFB_DEFINE_API(FIRPFB_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// Interpolators
//
// firinterp : finite impulse response interpolator
#define FIRINTERP_MANGLE_RRRF(name) LIQUID_CONCAT(firinterp_rrrf,name)
#define FIRINTERP_MANGLE_CRCF(name) LIQUID_CONCAT(firinterp_crcf,name)
#define FIRINTERP_MANGLE_CCCF(name) LIQUID_CONCAT(firinterp_cccf,name)
#define LIQUID_FIRINTERP_DEFINE_API(FIRINTERP,TO,TC,TI) \
\
typedef struct FIRINTERP(_s) * FIRINTERP(); \
\
/* create interpolator from external coefficients */ \
/* _M : interpolation factor */ \
/* _h : filter coefficients [size: _h_len x 1] */ \
/* _h_len : filter length */ \
FIRINTERP() FIRINTERP(_create)(unsigned int _M, \
TC * _h, \
unsigned int _h_len); \
\
/* create interpolator from Kaiser prototype */ \
/* _M : interpolation factor */ \
/* _m : filter delay (symbols) */ \
/* _As : stop-band attenuation [dB] */ \
FIRINTERP() FIRINTERP(_create_kaiser)(unsigned int _M, \
unsigned int _m, \
float _As); \
\
/* create prorotype (root-)Nyquist interpolator */ \
/* _type : filter type (e.g. LIQUID_FIRFILT_RCOS) */ \
/* _k : samples/symbol, _k > 1 */ \
/* _m : filter delay (symbols), _m > 0 */ \
/* _beta : excess bandwidth factor, _beta < 1 */ \
/* _dt : fractional sample delay, _dt in (-1, 1) */ \
FIRINTERP() FIRINTERP(_create_prototype)(int _type, \
unsigned int _k, \
unsigned int _m, \
float _beta, \
float _dt); \
\
/* destroy firinterp object, freeing all internal memory */ \
void FIRINTERP(_destroy)(FIRINTERP() _q); \
\
/* print firinterp object's internal properties to stdout */ \
void FIRINTERP(_print)(FIRINTERP() _q); \
\
/* reset internal state */ \
void FIRINTERP(_reset)(FIRINTERP() _q); \
\
/* execute interpolation on single input sample */ \
/* _q : firinterp object */ \
/* _x : input sample */ \
/* _y : output sample array [size: _M x 1] */ \
void FIRINTERP(_execute)(FIRINTERP() _q, \
TI _x, \
TO * _y); \
\
/* execute interpolation on block of input samples */ \
/* _q : firinterp object */ \
/* _x : input array [size: _n x 1] */ \
/* _n : size of input array */ \
/* _y : output sample array [size: _M*_n x 1] */ \
void FIRINTERP(_execute_block)(FIRINTERP() _q, \
TI * _x, \
unsigned int _n, \
TO * _y); \
LIQUID_FIRINTERP_DEFINE_API(FIRINTERP_MANGLE_RRRF,
float,
float,
float)
LIQUID_FIRINTERP_DEFINE_API(FIRINTERP_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_FIRINTERP_DEFINE_API(FIRINTERP_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
// iirinterp : infinite impulse response interpolator
#define IIRINTERP_MANGLE_RRRF(name) LIQUID_CONCAT(iirinterp_rrrf,name)
#define IIRINTERP_MANGLE_CRCF(name) LIQUID_CONCAT(iirinterp_crcf,name)
#define IIRINTERP_MANGLE_CCCF(name) LIQUID_CONCAT(iirinterp_cccf,name)
#define LIQUID_IIRINTERP_DEFINE_API(IIRINTERP,TO,TC,TI) \
typedef struct IIRINTERP(_s) * IIRINTERP(); \
\
/* create interpolator from external coefficients */ \
/* _M : interpolation factor */ \
/* _b : feed-back coefficients [size: _nb x 1] */ \
/* _nb : feed-back coefficients length */ \
/* _a : feed-forward coefficients [size: _na x 1] */ \
/* _na : feed-forward coefficients length */ \
IIRINTERP() IIRINTERP(_create)(unsigned int _M, \
TC * _b, \
unsigned int _nb, \
TC * _a, \
unsigned int _na); \
\
/* create decimator with default Butterworth prototype */ \
/* _M : decimation factor */ \
/* _order : filter order */ \
IIRINTERP() IIRINTERP(_create_default)(unsigned int _M, \
unsigned int _order); \
\
/* create interpolator from prototype */ \
/* _M : interpolation factor */ \
IIRINTERP() IIRINTERP(_create_prototype)( \
unsigned int _M, \
liquid_iirdes_filtertype _ftype, \
liquid_iirdes_bandtype _btype, \
liquid_iirdes_format _format, \
unsigned int _order, \
float _fc, \
float _f0, \
float _Ap, \
float _As); \
\
/* destroy interpolator object and free internal memory */ \
void IIRINTERP(_destroy)(IIRINTERP() _q); \
\
/* print interpolator object internals */ \
void IIRINTERP(_print)(IIRINTERP() _q); \
\
/* reset interpolator object */ \
void IIRINTERP(_reset)(IIRINTERP() _q); \
\
/* execute interpolation on single input sample */ \
/* _q : iirinterp object */ \
/* _x : input sample */ \
/* _y : output sample array [size: _M x 1] */ \
void IIRINTERP(_execute)(IIRINTERP() _q, \
TI _x, \
TO * _y); \
\
/* execute interpolation on block of input samples */ \
/* _q : iirinterp object */ \
/* _x : input array [size: _n x 1] */ \
/* _n : size of input array */ \
/* _y : output sample array [size: _M*_n x 1] */ \
void IIRINTERP(_execute_block)(IIRINTERP() _q, \
TI * _x, \
unsigned int _n, \
TO * _y); \
\
/* get system group delay at frequency _fc */ \
float IIRINTERP(_groupdelay)(IIRINTERP() _q, float _fc); \
LIQUID_IIRINTERP_DEFINE_API(IIRINTERP_MANGLE_RRRF,
float,
float,
float)
LIQUID_IIRINTERP_DEFINE_API(IIRINTERP_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_IIRINTERP_DEFINE_API(IIRINTERP_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// Decimators
//
// firdecim : finite impulse response decimator
#define FIRDECIM_MANGLE_RRRF(name) LIQUID_CONCAT(firdecim_rrrf,name)
#define FIRDECIM_MANGLE_CRCF(name) LIQUID_CONCAT(firdecim_crcf,name)
#define FIRDECIM_MANGLE_CCCF(name) LIQUID_CONCAT(firdecim_cccf,name)
#define LIQUID_FIRDECIM_DEFINE_API(FIRDECIM,TO,TC,TI) \
typedef struct FIRDECIM(_s) * FIRDECIM(); \
\
/* create decimator from external coefficients */ \
/* _M : decimation factor */ \
/* _h : filter coefficients [size: _h_len x 1] */ \
/* _h_len : filter coefficients length */ \
FIRDECIM() FIRDECIM(_create)(unsigned int _M, \
TC * _h, \
unsigned int _h_len); \
\
/* create decimator from Kaiser prototype */ \
/* _M : decimation factor */ \
/* _m : filter delay (symbols) */ \
/* _As : stop-band attenuation [dB] */ \
FIRDECIM() FIRDECIM(_create_kaiser)(unsigned int _M, \
unsigned int _m, \
float _As); \
\
/* create square-root Nyquist decimator */ \
/* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \
/* _M : samples/symbol (decimation factor) */ \
/* _m : filter delay (symbols) */ \
/* _beta : rolloff factor (0 < beta <= 1) */ \
/* _dt : fractional sample delay */ \
FIRDECIM() FIRDECIM(_create_prototype)(int _type, \
unsigned int _M, \
unsigned int _m, \
float _beta, \
float _dt); \
\
/* destroy decimator object */ \
void FIRDECIM(_destroy)(FIRDECIM() _q); \
\
/* print decimator object propreties to stdout */ \
void FIRDECIM(_print)(FIRDECIM() _q); \
\
/* reset decimator object internal state */ \
void FIRDECIM(_reset)(FIRDECIM() _q); \
\
/* execute decimator on _M input samples */ \
/* _q : decimator object */ \
/* _x : input samples [size: _M x 1] */ \
/* _y : output sample pointer */ \
void FIRDECIM(_execute)(FIRDECIM() _q, \
TI * _x, \
TO * _y); \
\
/* execute decimator on block of _n*_M input samples */ \
/* _q : decimator object */ \
/* _x : input array [size: _n*_M x 1] */ \
/* _n : number of _output_ samples */ \
/* _y : output array [_size: _n x 1] */ \
void FIRDECIM(_execute_block)(FIRDECIM() _q, \
TI * _x, \
unsigned int _n, \
TO * _y); \
LIQUID_FIRDECIM_DEFINE_API(FIRDECIM_MANGLE_RRRF,
float,
float,
float)
LIQUID_FIRDECIM_DEFINE_API(FIRDECIM_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_FIRDECIM_DEFINE_API(FIRDECIM_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
// iirdecim : infinite impulse response decimator
#define IIRDECIM_MANGLE_RRRF(name) LIQUID_CONCAT(iirdecim_rrrf,name)
#define IIRDECIM_MANGLE_CRCF(name) LIQUID_CONCAT(iirdecim_crcf,name)
#define IIRDECIM_MANGLE_CCCF(name) LIQUID_CONCAT(iirdecim_cccf,name)
#define LIQUID_IIRDECIM_DEFINE_API(IIRDECIM,TO,TC,TI) \
typedef struct IIRDECIM(_s) * IIRDECIM(); \
\
/* create decimator from external coefficients */ \
/* _M : decimation factor */ \
/* _b : feed-back coefficients [size: _nb x 1] */ \
/* _nb : feed-back coefficients length */ \
/* _a : feed-forward coefficients [size: _na x 1] */ \
/* _na : feed-forward coefficients length */ \
IIRDECIM() IIRDECIM(_create)(unsigned int _M, \
TC * _b, \
unsigned int _nb, \
TC * _a, \
unsigned int _na); \
\
/* create decimator with default Butterworth prototype */ \
/* _M : decimation factor */ \
/* _order : filter order */ \
IIRDECIM() IIRDECIM(_create_default)(unsigned int _M, \
unsigned int _order); \
\
/* create decimator from prototype */ \
/* _M : decimation factor */ \
/* _ftype : filter type (e.g. LIQUID_IIRDES_BUTTER) */ \
/* _btype : band type (e.g. LIQUID_IIRDES_BANDPASS) */ \
/* _format : coefficients format (e.g. LIQUID_IIRDES_SOS) */ \
/* _n : filter order */ \
/* _fc : low-pass prototype cut-off frequency */ \
/* _f0 : center frequency (band-pass, band-stop) */ \
/* _Ap : pass-band ripple in dB */ \
/* _As : stop-band ripple in dB */ \
IIRDECIM() IIRDECIM(_create_prototype)( \
unsigned int _M, \
liquid_iirdes_filtertype _ftype, \
liquid_iirdes_bandtype _btype, \
liquid_iirdes_format _format, \
unsigned int _order, \
float _fc, \
float _f0, \
float _Ap, \
float _As); \
\
/* destroy decimator object and free internal memory */ \
void IIRDECIM(_destroy)(IIRDECIM() _q); \
\
/* print decimator object internals */ \
void IIRDECIM(_print)(IIRDECIM() _q); \
\
/* reset decimator object */ \
void IIRDECIM(_reset)(IIRDECIM() _q); \
\
/* execute decimator on _M input samples */ \
/* _q : decimator object */ \
/* _x : input samples [size: _M x 1] */ \
/* _y : output sample pointer */ \
void IIRDECIM(_execute)(IIRDECIM() _q, \
TI * _x, \
TO * _y); \
\
/* execute decimator on block of _n*_M input samples */ \
/* _q : decimator object */ \
/* _x : input array [size: _n*_M x 1] */ \
/* _n : number of _output_ samples */ \
/* _y : output array [_sze: _n x 1] */ \
void IIRDECIM(_execute_block)(IIRDECIM() _q, \
TI * _x, \
unsigned int _n, \
TO * _y); \
\
/* get system group delay at frequency _fc */ \
float IIRDECIM(_groupdelay)(IIRDECIM() _q, float _fc); \
LIQUID_IIRDECIM_DEFINE_API(IIRDECIM_MANGLE_RRRF,
float,
float,
float)
LIQUID_IIRDECIM_DEFINE_API(IIRDECIM_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_IIRDECIM_DEFINE_API(IIRDECIM_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// Half-band resampler
//
#define RESAMP2_MANGLE_RRRF(name) LIQUID_CONCAT(resamp2_rrrf,name)
#define RESAMP2_MANGLE_CRCF(name) LIQUID_CONCAT(resamp2_crcf,name)
#define RESAMP2_MANGLE_CCCF(name) LIQUID_CONCAT(resamp2_cccf,name)
#define LIQUID_RESAMP2_DEFINE_API(RESAMP2,TO,TC,TI) \
typedef struct RESAMP2(_s) * RESAMP2(); \
\
/* create half-band resampler */ \
/* _m : filter semi-length (h_len = 4*m+1) */ \
/* _f0 : filter center frequency */ \
/* _As : stop-band attenuation [dB] */ \
RESAMP2() RESAMP2(_create)(unsigned int _m, \
float _f0, \
float _As); \
\
/* re-create half-band resampler with new properties */ \
/* _q : original half-band resampler object */ \
/* _m : filter semi-length (h_len = 4*m+1) */ \
/* _f0 : filter center frequency */ \
/* _As : stop-band attenuation [dB] */ \
RESAMP2() RESAMP2(_recreate)(RESAMP2() _q, \
unsigned int _m, \
float _f0, \
float _As); \
\
/* destroy half-band resampler */ \
void RESAMP2(_destroy)(RESAMP2() _q); \
\
/* print resamp2 object's internals */ \
void RESAMP2(_print)(RESAMP2() _q); \
\
/* reset internal buffer */ \
void RESAMP2(_reset)(RESAMP2() _q); \
\
/* get resampler filter delay (semi-length m) */ \
unsigned int RESAMP2(_get_delay)(RESAMP2() _q); \
\
/* execute resamp2 as half-band filter */ \
/* _q : resamp2 object */ \
/* _x : input sample */ \
/* _y0 : output sample pointer (low frequency) */ \
/* _y1 : output sample pointer (high frequency) */ \
void RESAMP2(_filter_execute)(RESAMP2() _q, \
TI _x, \
TO * _y0, \
TO * _y1); \
\
/* execute resamp2 as half-band analysis filterbank */ \
/* _q : resamp2 object */ \
/* _x : input array [size: 2 x 1] */ \
/* _y : output array [size: 2 x 1] */ \
void RESAMP2(_analyzer_execute)(RESAMP2() _q, \
TI * _x, \
TO * _y); \
\
/* execute resamp2 as half-band synthesis filterbank */ \
/* _q : resamp2 object */ \
/* _x : input array [size: 2 x 1] */ \
/* _y : output array [size: 2 x 1] */ \
void RESAMP2(_synthesizer_execute)(RESAMP2() _q, \
TI * _x, \
TO * _y); \
\
/* execute resamp2 as half-band decimator */ \
/* _q : resamp2 object */ \
/* _x : input array [size: 2 x 1] */ \
/* _y : output sample pointer */ \
void RESAMP2(_decim_execute)(RESAMP2() _q, \
TI * _x, \
TO * _y); \
\
/* execute resamp2 as half-band interpolator */ \
/* _q : resamp2 object */ \
/* _x : input sample */ \
/* _y : output array [size: 2 x 1] */ \
void RESAMP2(_interp_execute)(RESAMP2() _q, \
TI _x, \
TO * _y); \
LIQUID_RESAMP2_DEFINE_API(RESAMP2_MANGLE_RRRF,
float,
float,
float)
LIQUID_RESAMP2_DEFINE_API(RESAMP2_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_RESAMP2_DEFINE_API(RESAMP2_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// Arbitrary resampler
//
#define RESAMP_MANGLE_RRRF(name) LIQUID_CONCAT(resamp_rrrf,name)
#define RESAMP_MANGLE_CRCF(name) LIQUID_CONCAT(resamp_crcf,name)
#define RESAMP_MANGLE_CCCF(name) LIQUID_CONCAT(resamp_cccf,name)
#define LIQUID_RESAMP_DEFINE_API(RESAMP,TO,TC,TI) \
typedef struct RESAMP(_s) * RESAMP(); \
\
/* create arbitrary resampler object */ \
/* _rate : arbitrary resampling rate */ \
/* _m : filter semi-length (delay) */ \
/* _fc : filter cutoff frequency, 0 < _fc < 0.5 */ \
/* _As : filter stop-band attenuation [dB] */ \
/* _npfb : number of filters in the bank */ \
RESAMP() RESAMP(_create)(float _rate, \
unsigned int _m, \
float _fc, \
float _As, \
unsigned int _npfb); \
\
/* create arbitrary resampler object with a specified input */ \
/* resampling rate and default parameters */ \
/* m (filter semi-length) = 7 */ \
/* fc (filter cutoff frequency) = 0.25 */ \
/* As (filter stop-band attenuation) = 60 dB */ \
/* npfb (number of filters in the bank) = 64 */ \
RESAMP() RESAMP(_create_default)(float _rate); \
\
/* destroy arbitrary resampler object */ \
void RESAMP(_destroy)(RESAMP() _q); \
\
/* print resamp object internals to stdout */ \
void RESAMP(_print)(RESAMP() _q); \
\
/* reset resamp object internals */ \
void RESAMP(_reset)(RESAMP() _q); \
\
/* get resampler delay (output samples) */ \
unsigned int RESAMP(_get_delay)(RESAMP() _q); \
\
/* set rate of arbitrary resampler */ \
void RESAMP(_set_rate)(RESAMP() _q, float _rate); \
\
/* adjust rate of arbitrary resampler */ \
void RESAMP(_adjust_rate)(RESAMP() _q, float _delta); \
\
/* execute arbitrary resampler */ \
/* _q : resamp object */ \
/* _x : single input sample */ \
/* _y : output sample array (pointer) */ \
/* _num_written : number of samples written to _y */ \
void RESAMP(_execute)(RESAMP() _q, \
TI _x, \
TO * _y, \
unsigned int * _num_written); \
\
/* execute arbitrary resampler on a block of samples */ \
/* _q : resamp object */ \
/* _x : input buffer [size: _nx x 1] */ \
/* _nx : input buffer */ \
/* _y : output sample array (pointer) */ \
/* _ny : number of samples written to _y */ \
void RESAMP(_execute_block)(RESAMP() _q, \
TI * _x, \
unsigned int _nx, \
TO * _y, \
unsigned int * _ny); \
LIQUID_RESAMP_DEFINE_API(RESAMP_MANGLE_RRRF,
float,
float,
float)
LIQUID_RESAMP_DEFINE_API(RESAMP_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_RESAMP_DEFINE_API(RESAMP_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// Multi-stage half-band resampler
//
// resampling type (interpolator/decimator)
typedef enum {
LIQUID_RESAMP_INTERP=0, // interpolator
LIQUID_RESAMP_DECIM, // decimator
} liquid_resamp_type;
#define MSRESAMP2_MANGLE_RRRF(name) LIQUID_CONCAT(msresamp2_rrrf,name)
#define MSRESAMP2_MANGLE_CRCF(name) LIQUID_CONCAT(msresamp2_crcf,name)
#define MSRESAMP2_MANGLE_CCCF(name) LIQUID_CONCAT(msresamp2_cccf,name)
#define LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2,TO,TC,TI) \
typedef struct MSRESAMP2(_s) * MSRESAMP2(); \
\
/* create multi-stage half-band resampler */ \
/* _type : resampler type (e.g. LIQUID_RESAMP_DECIM) */ \
/* _num_stages : number of resampling stages */ \
/* _fc : filter cut-off frequency 0 < _fc < 0.5 */ \
/* _f0 : filter center frequency */ \
/* _As : stop-band attenuation [dB] */ \
MSRESAMP2() MSRESAMP2(_create)(int _type, \
unsigned int _num_stages, \
float _fc, \
float _f0, \
float _As); \
\
/* destroy multi-stage half-bandresampler */ \
void MSRESAMP2(_destroy)(MSRESAMP2() _q); \
\
/* print msresamp object internals to stdout */ \
void MSRESAMP2(_print)(MSRESAMP2() _q); \
\
/* reset msresamp object internal state */ \
void MSRESAMP2(_reset)(MSRESAMP2() _q); \
\
/* get group delay (number of output samples) */ \
float MSRESAMP2(_get_delay)(MSRESAMP2() _q); \
\
/* execute multi-stage resampler, M = 2^num_stages */ \
/* LIQUID_RESAMP_INTERP: input: 1, output: M */ \
/* LIQUID_RESAMP_DECIM: input: M, output: 1 */ \
/* _q : msresamp object */ \
/* _x : input sample array */ \
/* _y : output sample array */ \
void MSRESAMP2(_execute)(MSRESAMP2() _q, \
TI * _x, \
TO * _y); \
LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2_MANGLE_RRRF,
float,
float,
float)
LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// Multi-stage arbitrary resampler
//
#define MSRESAMP_MANGLE_RRRF(name) LIQUID_CONCAT(msresamp_rrrf,name)
#define MSRESAMP_MANGLE_CRCF(name) LIQUID_CONCAT(msresamp_crcf,name)
#define MSRESAMP_MANGLE_CCCF(name) LIQUID_CONCAT(msresamp_cccf,name)
#define LIQUID_MSRESAMP_DEFINE_API(MSRESAMP,TO,TC,TI) \
typedef struct MSRESAMP(_s) * MSRESAMP(); \
\
/* create multi-stage arbitrary resampler */ \
/* _r : resampling rate [output/input] */ \
/* _As : stop-band attenuation [dB] */ \
MSRESAMP() MSRESAMP(_create)(float _r, \
float _As); \
\
/* destroy multi-stage arbitrary resampler */ \
void MSRESAMP(_destroy)(MSRESAMP() _q); \
\
/* print msresamp object internals to stdout */ \
void MSRESAMP(_print)(MSRESAMP() _q); \
\
/* reset msresamp object internal state */ \
void MSRESAMP(_reset)(MSRESAMP() _q); \
\
/* get filter delay (output samples) */ \
float MSRESAMP(_get_delay)(MSRESAMP() _q); \
\
/* execute multi-stage resampler */ \
/* _q : msresamp object */ \
/* _x : input sample array [size: _nx x 1] */ \
/* _nx : input sample array size */ \
/* _y : output sample array [size: variable] */ \
/* _ny : number of samples written to _y */ \
void MSRESAMP(_execute)(MSRESAMP() _q, \
TI * _x, \
unsigned int _nx, \
TO * _y, \
unsigned int * _ny); \
LIQUID_MSRESAMP_DEFINE_API(MSRESAMP_MANGLE_RRRF,
float,
float,
float)
LIQUID_MSRESAMP_DEFINE_API(MSRESAMP_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_MSRESAMP_DEFINE_API(MSRESAMP_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// Symbol timing recovery (symbol synchronizer)
//
#define SYMSYNC_MANGLE_RRRF(name) LIQUID_CONCAT(symsync_rrrf,name)
#define SYMSYNC_MANGLE_CRCF(name) LIQUID_CONCAT(symsync_crcf,name)
#define LIQUID_SYMSYNC_DEFINE_API(SYMSYNC,TO,TC,TI) \
\
typedef struct SYMSYNC(_s) * SYMSYNC(); \
\
/* create synchronizer object from external coefficients */ \
/* _k : samples per symbol */ \
/* _M : number of filters in the bank */ \
/* _h : matched filter coefficients [size: */ \
/* _h_len : length of matched filter */ \
SYMSYNC() SYMSYNC(_create)(unsigned int _k, \
unsigned int _M, \
TC * _h, \
unsigned int _h_len); \
\
/* create square-root Nyquist symbol synchronizer */ \
/* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \
/* _k : samples/symbol */ \
/* _m : symbol delay */ \
/* _beta : rolloff factor, beta in (0,1] */ \
/* _M : number of filters in the bank */ \
SYMSYNC() SYMSYNC(_create_rnyquist)(int _type, \
unsigned int _k, \
unsigned int _m, \
float _beta, \
unsigned int _M); \
\
/* create symsync using Kaiser filter interpolator; useful */ \
/* when the input signal has matched filter applied already */ \
/* _k : input samples/symbol */ \
/* _m : symbol delay */ \
/* _beta : rolloff factor, beta in (0,1] */ \
/* _M : number of filters in the bank */ \
SYMSYNC() SYMSYNC(_create_kaiser)(unsigned int _k, \
unsigned int _m, \
float _beta, \
unsigned int _M); \
\
/* destroy symsync object, freeing all internal memory */ \
void SYMSYNC(_destroy)(SYMSYNC() _q); \
\
/* print symsync object's parameters */ \
void SYMSYNC(_print)(SYMSYNC() _q); \
\
/* reset symsync internal state */ \
void SYMSYNC(_reset)(SYMSYNC() _q); \
\
/* lock/unlock loop control */ \
void SYMSYNC(_lock)( SYMSYNC() _q); \
void SYMSYNC(_unlock)(SYMSYNC() _q); \
\
/* set synchronizer output rate (samples/symbol) */ \
/* _q : synchronizer object */ \
/* _k_out : output samples/symbol */ \
void SYMSYNC(_set_output_rate)(SYMSYNC() _q, \
unsigned int _k_out); \
\
/* set loop-filter bandwidth */ \
/* _q : synchronizer object */ \
/* _bt : loop bandwidth */ \
void SYMSYNC(_set_lf_bw)(SYMSYNC() _q, \
float _bt); \
\
/* return instantaneous fractional timing offset estimate */ \
float SYMSYNC(_get_tau)(SYMSYNC() _q); \
\
/* execute synchronizer on input data array */ \
/* _q : synchronizer object */ \
/* _x : input data array */ \
/* _nx : number of input samples */ \
/* _y : output data array */ \
/* _ny : number of samples written to output buffer */ \
void SYMSYNC(_execute)(SYMSYNC() _q, \
TI * _x, \
unsigned int _nx, \
TO * _y, \
unsigned int * _ny); \
LIQUID_SYMSYNC_DEFINE_API(SYMSYNC_MANGLE_RRRF,
float,
float,
float)
LIQUID_SYMSYNC_DEFINE_API(SYMSYNC_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
//
// Finite impulse response Farrow filter
//
#define FIRFARROW_MANGLE_RRRF(name) LIQUID_CONCAT(firfarrow_rrrf,name)
#define FIRFARROW_MANGLE_CRCF(name) LIQUID_CONCAT(firfarrow_crcf,name)
//#define FIRFARROW_MANGLE_CCCF(name) LIQUID_CONCAT(firfarrow_cccf,name)
// Macro:
// FIRFARROW : name-mangling macro
// TO : output data type
// TC : coefficients data type
// TI : input data type
#define LIQUID_FIRFARROW_DEFINE_API(FIRFARROW,TO,TC,TI) \
\
typedef struct FIRFARROW(_s) * FIRFARROW(); \
\
/* create firfarrow object */ \
/* _h_len : filter length */ \
/* _p : polynomial order */ \
/* _fc : filter cutoff frequency */ \
/* _As : stopband attenuation [dB] */ \
FIRFARROW() FIRFARROW(_create)(unsigned int _h_len, \
unsigned int _p, \
float _fc, \
float _As); \
\
/* destroy firfarrow object, freeing all internal memory */ \
void FIRFARROW(_destroy)(FIRFARROW() _q); \
\
/* print firfarrow object's internal properties */ \
void FIRFARROW(_print)(FIRFARROW() _q); \
\
/* reset firfarrow object's internal state */ \
void FIRFARROW(_reset)(FIRFARROW() _q); \
\
/* push sample into firfarrow object */ \
/* _q : firfarrow object */ \
/* _x : input sample */ \
void FIRFARROW(_push)(FIRFARROW() _q, \
TI _x); \
\
/* set fractional delay of firfarrow object */ \
/* _q : firfarrow object */ \
/* _mu : fractional sample delay */ \
void FIRFARROW(_set_delay)(FIRFARROW() _q, \
float _mu); \
\
/* execute firfarrow internal dot product */ \
/* _q : firfarrow object */ \
/* _y : output sample pointer */ \
void FIRFARROW(_execute)(FIRFARROW() _q, \
TO * _y); \
\
/* compute firfarrow filter on block of samples; the input */ \
/* and output arrays may have the same pointer */ \
/* _q : firfarrow object */ \
/* _x : input array [size: _n x 1] */ \
/* _n : input, output array size */ \
/* _y : output array [size: _n x 1] */ \
void FIRFARROW(_execute_block)(FIRFARROW() _q, \
TI * _x, \
unsigned int _n, \
TO * _y); \
\
/* get length of firfarrow object (number of filter taps) */ \
unsigned int FIRFARROW(_get_length)(FIRFARROW() _q); \
\
/* get coefficients of firfarrow object */ \
/* _q : firfarrow object */ \
/* _h : output coefficients pointer */ \
void FIRFARROW(_get_coefficients)(FIRFARROW() _q, \
float * _h); \
\
/* compute complex frequency response */ \
/* _q : filter object */ \
/* _fc : frequency */ \
/* _H : output frequency response */ \
void FIRFARROW(_freqresponse)(FIRFARROW() _q, \
float _fc, \
liquid_float_complex * _H); \
\
/* compute group delay [samples] */ \
/* _q : filter object */ \
/* _fc : frequency */ \
float FIRFARROW(_groupdelay)(FIRFARROW() _q, \
float _fc); \
LIQUID_FIRFARROW_DEFINE_API(FIRFARROW_MANGLE_RRRF,
float,
float,
float)
LIQUID_FIRFARROW_DEFINE_API(FIRFARROW_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
//
// MODULE : framing
//
// framesyncstats : generic frame synchronizer statistic structure
typedef struct {
// signal quality
float evm; // error vector magnitude [dB]
float rssi; // received signal strength indicator [dB]
float cfo; // carrier frequency offset (f/Fs)
// demodulated frame symbols
liquid_float_complex * framesyms; // pointer to array [size: framesyms x 1]
unsigned int num_framesyms; // length of framesyms
// modulation/coding scheme etc.
unsigned int mod_scheme; // modulation scheme
unsigned int mod_bps; // modulation depth (bits/symbol)
unsigned int check; // data validity check (crc, checksum)
unsigned int fec0; // forward error-correction (inner)
unsigned int fec1; // forward error-correction (outer)
} framesyncstats_s;
// external framesyncstats default object
extern framesyncstats_s framesyncstats_default;
// initialize framesyncstats object on default
void framesyncstats_init_default(framesyncstats_s * _stats);
// print framesyncstats object
void framesyncstats_print(framesyncstats_s * _stats);
// framedatastats : gather frame data
typedef struct {
unsigned int num_frames_detected;
unsigned int num_headers_valid;
unsigned int num_payloads_valid;
unsigned long int num_bytes_received;
} framedatastats_s;
// reset framedatastats object
void framedatastats_reset(framedatastats_s * _stats);
// print framedatastats object
void framedatastats_print(framedatastats_s * _stats);
// Generic frame synchronizer callback function type
// _header : header data [size: 8 bytes]
// _header_valid : is header valid? (0:no, 1:yes)
// _payload : payload data [size: _payload_len]
// _payload_len : length of payload (bytes)
// _payload_valid : is payload valid? (0:no, 1:yes)
// _stats : frame statistics object
// _userdata : pointer to userdata
typedef int (*framesync_callback)(unsigned char * _header,
int _header_valid,
unsigned char * _payload,
unsigned int _payload_len,
int _payload_valid,
framesyncstats_s _stats,
void * _userdata);
// framesync csma callback functions invoked when signal levels is high or low
// _userdata : user-defined data pointer
typedef void (*framesync_csma_callback)(void * _userdata);
//
// packet encoder/decoder
//
typedef struct qpacketmodem_s * qpacketmodem;
// create packet encoder
qpacketmodem qpacketmodem_create ();
void qpacketmodem_destroy(qpacketmodem _q);
void qpacketmodem_reset (qpacketmodem _q);
void qpacketmodem_print (qpacketmodem _q);
int qpacketmodem_configure(qpacketmodem _q,
unsigned int _payload_len,
crc_scheme _check,
fec_scheme _fec0,
fec_scheme _fec1,
int _ms);
// get length of encoded frame in symbols
unsigned int qpacketmodem_get_frame_len(qpacketmodem _q);
// get unencoded/decoded payload length (bytes)
unsigned int qpacketmodem_get_payload_len(qpacketmodem _q);
// regular access methods
unsigned int qpacketmodem_get_crc (qpacketmodem _q);
unsigned int qpacketmodem_get_fec0 (qpacketmodem _q);
unsigned int qpacketmodem_get_fec1 (qpacketmodem _q);
unsigned int qpacketmodem_get_modscheme(qpacketmodem _q);
// encode packet into un-modulated frame symbol indices
// _q : qpacketmodem object
// _payload : unencoded payload bytes
// _syms : encoded but un-modulated payload symbol indices
void qpacketmodem_encode_syms(qpacketmodem _q,
const unsigned char * _payload,
unsigned char * _syms);
// decode packet from demodulated frame symbol indices (hard-decision decoding)
// _q : qpacketmodem object
// _syms : received hard-decision symbol indices [size: frame_len x 1]
// _payload : recovered decoded payload bytes
int qpacketmodem_decode_syms(qpacketmodem _q,
unsigned char * _syms,
unsigned char * _payload);
// decode packet from demodulated frame bits (soft-decision decoding)
// _q : qpacketmodem object
// _bits : received soft-decision bits, [size: bps*frame_len x 1]
// _payload : recovered decoded payload bytes
int qpacketmodem_decode_bits(qpacketmodem _q,
unsigned char * _bits,
unsigned char * _payload);
// encode and modulate packet into modulated frame samples
// _q : qpacketmodem object
// _payload : unencoded payload bytes
// _frame : encoded/modulated payload symbols
void qpacketmodem_encode(qpacketmodem _q,
const unsigned char * _payload,
liquid_float_complex * _frame);
// decode packet from modulated frame samples, returning flag if CRC passed
// NOTE: hard-decision decoding
// _q : qpacketmodem object
// _frame : encoded/modulated payload symbols
// _payload : recovered decoded payload bytes
int qpacketmodem_decode(qpacketmodem _q,
liquid_float_complex * _frame,
unsigned char * _payload);
// decode packet from modulated frame samples, returning flag if CRC passed
// NOTE: soft-decision decoding
// _q : qpacketmodem object
// _frame : encoded/modulated payload symbols
// _payload : recovered decoded payload bytes
int qpacketmodem_decode_soft(qpacketmodem _q,
liquid_float_complex * _frame,
unsigned char * _payload);
//
// pilot generator for streaming applications
//
typedef struct qpilotgen_s * qpilotgen;
// create packet encoder
qpilotgen qpilotgen_create(unsigned int _payload_len,
unsigned int _pilot_spacing);
qpilotgen qpilotgen_recreate(qpilotgen _q,
unsigned int _payload_len,
unsigned int _pilot_spacing);
void qpilotgen_destroy(qpilotgen _q);
void qpilotgen_reset( qpilotgen _q);
void qpilotgen_print( qpilotgen _q);
unsigned int qpilotgen_get_frame_len(qpilotgen _q);
// insert pilot symbols
void qpilotgen_execute(qpilotgen _q,
liquid_float_complex * _payload,
liquid_float_complex * _frame);
//
// pilot synchronizer for streaming applications
//
typedef struct qpilotsync_s * qpilotsync;
// create packet encoder
qpilotsync qpilotsync_create(unsigned int _payload_len,
unsigned int _pilot_spacing);
qpilotsync qpilotsync_recreate(qpilotsync _q,
unsigned int _payload_len,
unsigned int _pilot_spacing);
void qpilotsync_destroy(qpilotsync _q);
void qpilotsync_reset( qpilotsync _q);
void qpilotsync_print( qpilotsync _q);
unsigned int qpilotsync_get_frame_len(qpilotsync _q);
// recover frame symbols from received frame
void qpilotsync_execute(qpilotsync _q,
liquid_float_complex * _frame,
liquid_float_complex * _payload);
// get estimates
float qpilotsync_get_dphi(qpilotsync _q);
float qpilotsync_get_phi (qpilotsync _q);
float qpilotsync_get_gain(qpilotsync _q);
//
// Basic frame generator (64 bytes data payload)
//
// frame length in samples
#define LIQUID_FRAME64_LEN (1440)
typedef struct framegen64_s * framegen64;
// create frame generator
framegen64 framegen64_create();
// destroy frame generator
void framegen64_destroy(framegen64 _q);
// print frame generator internal properties
void framegen64_print(framegen64 _q);
// generate frame
// _q : frame generator object
// _header : 8-byte header data
// _payload : 64-byte payload data
// _frame : output frame samples [size: LIQUID_FRAME64_LEN x 1]
void framegen64_execute(framegen64 _q,
unsigned char * _header,
unsigned char * _payload,
liquid_float_complex * _frame);
typedef struct framesync64_s * framesync64;
// create framesync64 object
// _callback : callback function
// _userdata : user data pointer passed to callback function
framesync64 framesync64_create(framesync_callback _callback,
void * _userdata);
// destroy frame synchronizer
void framesync64_destroy(framesync64 _q);
// print frame synchronizer internal properties
void framesync64_print(framesync64 _q);
// reset frame synchronizer internal state
void framesync64_reset(framesync64 _q);
// push samples through frame synchronizer
// _q : frame synchronizer object
// _x : input samples [size: _n x 1]
// _n : number of input samples
void framesync64_execute(framesync64 _q,
liquid_float_complex * _x,
unsigned int _n);
// enable/disable debugging
void framesync64_debug_enable(framesync64 _q);
void framesync64_debug_disable(framesync64 _q);
void framesync64_debug_print(framesync64 _q, const char * _filename);
#if 0
// advanced modes
void framesync64_set_csma_callbacks(framesync64 _q,
framesync_csma_callback _csma_lock,
framesync_csma_callback _csma_unlock,
void * _csma_userdata);
#endif
//
// Flexible frame : adjustable payload, mod scheme, etc., but bring
// your own error correction, redundancy check
//
// frame generator
typedef struct {
unsigned int check; // data validity check
unsigned int fec0; // forward error-correction scheme (inner)
unsigned int fec1; // forward error-correction scheme (outer)
unsigned int mod_scheme; // modulation scheme
} flexframegenprops_s;
void flexframegenprops_init_default(flexframegenprops_s * _fgprops);
typedef struct flexframegen_s * flexframegen;
// create flexframegen object
// _props : frame properties (modulation scheme, etc.)
flexframegen flexframegen_create(flexframegenprops_s * _props);
// destroy flexframegen object
void flexframegen_destroy(flexframegen _q);
// print flexframegen object internals
void flexframegen_print(flexframegen _q);
// reset flexframegen object internals
void flexframegen_reset(flexframegen _q);
// is frame assembled?
int flexframegen_is_assembled(flexframegen _q);
// get frame properties
void flexframegen_getprops(flexframegen _q, flexframegenprops_s * _props);
// set frame properties
int flexframegen_setprops(flexframegen _q, flexframegenprops_s * _props);
// get length of assembled frame (samples)
unsigned int flexframegen_getframelen(flexframegen _q);
// assemble a frame from an array of data
// _q : frame generator object
// _header : frame header
// _payload : payload data [size: _payload_len x 1]
// _payload_len : payload data length
void flexframegen_assemble(flexframegen _q,
const unsigned char * _header,
const unsigned char * _payload,
unsigned int _payload_len);
// write samples of assembled frame, two samples at a time, returning
// '1' when frame is complete, '0' otherwise. Zeros will be written
// to the buffer if the frame is not assembled
// _q : frame generator object
// _buffer : output buffer [size: _buffer_len x 1]
// _buffer_len : output buffer length
int flexframegen_write_samples(flexframegen _q,
liquid_float_complex * _buffer,
unsigned int _buffer_len);
// frame synchronizer
typedef struct flexframesync_s * flexframesync;
// create flexframesync object
// _callback : callback function
// _userdata : user data pointer passed to callback function
flexframesync flexframesync_create(framesync_callback _callback,
void * _userdata);
// destroy frame synchronizer
void flexframesync_destroy(flexframesync _q);
// print frame synchronizer internal properties
void flexframesync_print(flexframesync _q);
// reset frame synchronizer internal state
void flexframesync_reset(flexframesync _q);
// push samples through frame synchronizer
// _q : frame synchronizer object
// _x : input samples [size: _n x 1]
// _n : number of input samples
void flexframesync_execute(flexframesync _q,
liquid_float_complex * _x,
unsigned int _n);
// frame data statistics
void flexframesync_reset_framedatastats(flexframesync _q);
framedatastats_s flexframesync_get_framedatastats (flexframesync _q);
// enable/disable debugging
void flexframesync_debug_enable(flexframesync _q);
void flexframesync_debug_disable(flexframesync _q);
void flexframesync_debug_print(flexframesync _q,
const char * _filename);
//
// bpacket : binary packet suitable for data streaming
//
//
// bpacket generator/encoder
//
typedef struct bpacketgen_s * bpacketgen;
// create bpacketgen object
// _m : p/n sequence length (ignored)
// _dec_msg_len : decoded message length (original uncoded data)
// _crc : data validity check (e.g. cyclic redundancy check)
// _fec0 : inner forward error-correction code scheme
// _fec1 : outer forward error-correction code scheme
bpacketgen bpacketgen_create(unsigned int _m,
unsigned int _dec_msg_len,
int _crc,
int _fec0,
int _fec1);
// re-create bpacketgen object from old object
// _q : old bpacketgen object
// _m : p/n sequence length (ignored)
// _dec_msg_len : decoded message length (original uncoded data)
// _crc : data validity check (e.g. cyclic redundancy check)
// _fec0 : inner forward error-correction code scheme
// _fec1 : outer forward error-correction code scheme
bpacketgen bpacketgen_recreate(bpacketgen _q,
unsigned int _m,
unsigned int _dec_msg_len,
int _crc,
int _fec0,
int _fec1);
// destroy bpacketgen object, freeing all internally-allocated memory
void bpacketgen_destroy(bpacketgen _q);
// print bpacketgen internals
void bpacketgen_print(bpacketgen _q);
// return length of full packet
unsigned int bpacketgen_get_packet_len(bpacketgen _q);
// encode packet
void bpacketgen_encode(bpacketgen _q,
unsigned char * _msg_dec,
unsigned char * _packet);
//
// bpacket synchronizer/decoder
//
typedef struct bpacketsync_s * bpacketsync;
typedef int (*bpacketsync_callback)(unsigned char * _payload,
int _payload_valid,
unsigned int _payload_len,
framesyncstats_s _stats,
void * _userdata);
bpacketsync bpacketsync_create(unsigned int _m,
bpacketsync_callback _callback,
void * _userdata);
void bpacketsync_destroy(bpacketsync _q);
void bpacketsync_print(bpacketsync _q);
void bpacketsync_reset(bpacketsync _q);
// run synchronizer on array of input bytes
// _q : bpacketsync object
// _bytes : input data array [size: _n x 1]
// _n : input array size
void bpacketsync_execute(bpacketsync _q,
unsigned char * _bytes,
unsigned int _n);
// run synchronizer on input byte
// _q : bpacketsync object
// _byte : input byte
void bpacketsync_execute_byte(bpacketsync _q,
unsigned char _byte);
// run synchronizer on input symbol
// _q : bpacketsync object
// _sym : input symbol with _bps significant bits
// _bps : number of bits in input symbol
void bpacketsync_execute_sym(bpacketsync _q,
unsigned char _sym,
unsigned int _bps);
// execute one bit at a time
void bpacketsync_execute_bit(bpacketsync _q,
unsigned char _bit);
//
// GMSK frame generator
//
typedef struct gmskframegen_s * gmskframegen;
// create GMSK frame generator
gmskframegen gmskframegen_create();
void gmskframegen_destroy (gmskframegen _q);
int gmskframegen_is_assembled (gmskframegen _q);
void gmskframegen_print (gmskframegen _q);
void gmskframegen_reset (gmskframegen _q);
void gmskframegen_assemble (gmskframegen _q,
const unsigned char * _header,
const unsigned char * _payload,
unsigned int _payload_len,
crc_scheme _check,
fec_scheme _fec0,
fec_scheme _fec1);
unsigned int gmskframegen_getframelen(gmskframegen _q);
int gmskframegen_write_samples(gmskframegen _q,
liquid_float_complex * _y);
//
// GMSK frame synchronizer
//
typedef struct gmskframesync_s * gmskframesync;
// create GMSK frame synchronizer
// _callback : callback function
// _userdata : user data pointer passed to callback function
gmskframesync gmskframesync_create(framesync_callback _callback,
void * _userdata);
void gmskframesync_destroy(gmskframesync _q);
void gmskframesync_print(gmskframesync _q);
void gmskframesync_reset(gmskframesync _q);
void gmskframesync_execute(gmskframesync _q,
liquid_float_complex * _x,
unsigned int _n);
// debugging
void gmskframesync_debug_enable(gmskframesync _q);
void gmskframesync_debug_disable(gmskframesync _q);
void gmskframesync_debug_print(gmskframesync _q, const char * _filename);
//
// OFDM flexframe generator
//
// ofdm frame generator properties
typedef struct {
unsigned int check; // data validity check
unsigned int fec0; // forward error-correction scheme (inner)
unsigned int fec1; // forward error-correction scheme (outer)
unsigned int mod_scheme; // modulation scheme
//unsigned int block_size; // framing block size
} ofdmflexframegenprops_s;
void ofdmflexframegenprops_init_default(ofdmflexframegenprops_s * _props);
typedef struct ofdmflexframegen_s * ofdmflexframegen;
// create OFDM flexible framing generator object
// _M : number of subcarriers, >10 typical
// _cp_len : cyclic prefix length
// _taper_len : taper length (OFDM symbol overlap)
// _p : subcarrier allocation (null, pilot, data), [size: _M x 1]
// _fgprops : frame properties (modulation scheme, etc.)
ofdmflexframegen ofdmflexframegen_create(unsigned int _M,
unsigned int _cp_len,
unsigned int _taper_len,
unsigned char * _p,
ofdmflexframegenprops_s * _fgprops);
// destroy ofdmflexframegen object
void ofdmflexframegen_destroy(ofdmflexframegen _q);
// print parameters, properties, etc.
void ofdmflexframegen_print(ofdmflexframegen _q);
// reset ofdmflexframegen object internals
void ofdmflexframegen_reset(ofdmflexframegen _q);
// is frame assembled?
int ofdmflexframegen_is_assembled(ofdmflexframegen _q);
// get properties
void ofdmflexframegen_getprops(ofdmflexframegen _q,
ofdmflexframegenprops_s * _props);
// set properties
void ofdmflexframegen_setprops(ofdmflexframegen _q,
ofdmflexframegenprops_s * _props);
// get length of frame (symbols)
// _q : OFDM frame generator object
unsigned int ofdmflexframegen_getframelen(ofdmflexframegen _q);
// assemble a frame from an array of data (NULL pointers will use random data)
// _q : OFDM frame generator object
// _header : frame header [8 bytes]
// _payload : payload data [size: _payload_len x 1]
// _payload_len : payload data length
void ofdmflexframegen_assemble(ofdmflexframegen _q,
const unsigned char * _header,
const unsigned char * _payload,
unsigned int _payload_len);
// write samples of assembled frame
// _q : OFDM frame generator object
// _buf : output buffer [size: _buf_len x 1]
// _buf_len : output buffer length
int ofdmflexframegen_write(ofdmflexframegen _q,
liquid_float_complex * _buf,
unsigned int _buf_len);
//
// OFDM flex frame synchronizer
//
typedef struct ofdmflexframesync_s * ofdmflexframesync;
// create OFDM flexible framing synchronizer object
// _M : number of subcarriers
// _cp_len : cyclic prefix length
// _taper_len : taper length (OFDM symbol overlap)
// _p : subcarrier allocation (null, pilot, data), [size: _M x 1]
// _callback : user-defined callback function
// _userdata : user-defined data pointer
ofdmflexframesync ofdmflexframesync_create(unsigned int _M,
unsigned int _cp_len,
unsigned int _taper_len,
unsigned char * _p,
framesync_callback _callback,
void * _userdata);
void ofdmflexframesync_destroy(ofdmflexframesync _q);
void ofdmflexframesync_print(ofdmflexframesync _q);
void ofdmflexframesync_reset(ofdmflexframesync _q);
void ofdmflexframesync_execute(ofdmflexframesync _q,
liquid_float_complex * _x,
unsigned int _n);
// query the received signal strength indication
float ofdmflexframesync_get_rssi(ofdmflexframesync _q);
// query the received carrier offset estimate
float ofdmflexframesync_get_cfo(ofdmflexframesync _q);
// enable/disable debugging
void ofdmflexframesync_debug_enable(ofdmflexframesync _q);
void ofdmflexframesync_debug_disable(ofdmflexframesync _q);
void ofdmflexframesync_debug_print(ofdmflexframesync _q,
const char * _filename);
//
// Binary P/N synchronizer
//
#define BSYNC_MANGLE_RRRF(name) LIQUID_CONCAT(bsync_rrrf,name)
#define BSYNC_MANGLE_CRCF(name) LIQUID_CONCAT(bsync_crcf,name)
#define BSYNC_MANGLE_CCCF(name) LIQUID_CONCAT(bsync_cccf,name)
// Macro:
// BSYNC : name-mangling macro
// TO : output data type
// TC : coefficients data type
// TI : input data type
#define LIQUID_BSYNC_DEFINE_API(BSYNC,TO,TC,TI) \
typedef struct BSYNC(_s) * BSYNC(); \
\
BSYNC() BSYNC(_create)(unsigned int _n, TC * _v); \
\
/* create binary synchronizer from m-sequence */ \
/* _g : m-sequence generator polynomial */ \
/* _k : samples/symbol (over-sampling factor) */ \
BSYNC() BSYNC(_create_msequence)(unsigned int _g, \
unsigned int _k); \
void BSYNC(_destroy)(BSYNC() _fs); \
void BSYNC(_print)(BSYNC() _fs); \
void BSYNC(_correlate)(BSYNC() _fs, TI _sym, TO * _y);
LIQUID_BSYNC_DEFINE_API(BSYNC_MANGLE_RRRF,
float,
float,
float)
LIQUID_BSYNC_DEFINE_API(BSYNC_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_BSYNC_DEFINE_API(BSYNC_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// Pre-demodulation synchronizers (binary and otherwise)
//
#define PRESYNC_MANGLE_CCCF(name) LIQUID_CONCAT( presync_cccf,name)
#define BPRESYNC_MANGLE_CCCF(name) LIQUID_CONCAT(bpresync_cccf,name)
// Macro:
// PRESYNC : name-mangling macro
// TO : output data type
// TC : coefficients data type
// TI : input data type
#define LIQUID_PRESYNC_DEFINE_API(PRESYNC,TO,TC,TI) \
typedef struct PRESYNC(_s) * PRESYNC(); \
\
/* create pre-demod synchronizer */ \
/* _v : baseband sequence */ \
/* _n : baseband sequence length */ \
/* _dphi_max : maximum absolute frequency deviation */ \
/* _m : number of correlators */ \
PRESYNC() PRESYNC(_create)(TC * _v, \
unsigned int _n, \
float _dphi_max, \
unsigned int _m); \
\
/* destroy pre-demod synchronizer */ \
void PRESYNC(_destroy)(PRESYNC() _q); \
\
/* print pre-demod synchronizer internal state */ \
void PRESYNC(_print)(PRESYNC() _q); \
\
/* reset pre-demod synchronizer internal state */ \
void PRESYNC(_reset)(PRESYNC() _q); \
\
/* push input sample into pre-demod synchronizer */ \
/* _q : pre-demod synchronizer object */ \
/* _x : input sample */ \
void PRESYNC(_push)(PRESYNC() _q, \
TI _x); \
\
/* correlate input sequence */ \
/* _q : pre-demod synchronizer object */ \
/* _rxy : output cross correlation */ \
/* _dphi_hat : output frequency offset estiamte */ \
void PRESYNC(_correlate)(PRESYNC() _q, \
TO * _rxy, \
float * _dphi_hat); \
// non-binary pre-demodulation synchronizer
LIQUID_PRESYNC_DEFINE_API(PRESYNC_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
// binary pre-demodulation synchronizer
LIQUID_PRESYNC_DEFINE_API(BPRESYNC_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// Frame detector
//
typedef struct qdetector_cccf_s * qdetector_cccf;
// create detector with generic sequence
// _s : sample sequence
// _s_len : length of sample sequence
qdetector_cccf qdetector_cccf_create(liquid_float_complex * _s,
unsigned int _s_len);
// create detector from sequence of symbols using internal linear interpolator
// _sequence : symbol sequence
// _sequence_len : length of symbol sequence
// _ftype : filter prototype (e.g. LIQUID_FIRFILT_RRC)
// _k : samples/symbol
// _m : filter delay
// _beta : excess bandwidth factor
qdetector_cccf qdetector_cccf_create_linear(liquid_float_complex * _sequence,
unsigned int _sequence_len,
int _ftype,
unsigned int _k,
unsigned int _m,
float _beta);
// create detector from sequence of GMSK symbols
// _sequence : bit sequence
// _sequence_len : length of bit sequence
// _k : samples/symbol
// _m : filter delay
// _beta : excess bandwidth factor
qdetector_cccf qdetector_cccf_create_gmsk(unsigned char * _sequence,
unsigned int _sequence_len,
unsigned int _k,
unsigned int _m,
float _beta);
void qdetector_cccf_destroy(qdetector_cccf _q);
void qdetector_cccf_print (qdetector_cccf _q);
void qdetector_cccf_reset (qdetector_cccf _q);
// run detector, looking for sequence; return pointer to aligned, buffered samples
void * qdetector_cccf_execute(qdetector_cccf _q,
liquid_float_complex _x);
// set detection threshold (should be between 0 and 1, good starting point is 0.5)
void qdetector_cccf_set_threshold(qdetector_cccf _q,
float _threshold);
// set carrier offset search range
void qdetector_cccf_set_range(qdetector_cccf _q,
float _dphi_max);
// access methods
unsigned int qdetector_cccf_get_seq_len (qdetector_cccf _q); // sequence length
const void * qdetector_cccf_get_sequence(qdetector_cccf _q); // pointer to sequence
unsigned int qdetector_cccf_get_buf_len (qdetector_cccf _q); // buffer length
float qdetector_cccf_get_tau (qdetector_cccf _q); // fractional timing offset estimate
float qdetector_cccf_get_gamma (qdetector_cccf _q); // channel gain
float qdetector_cccf_get_dphi (qdetector_cccf _q); // carrier frequency offset estimate
float qdetector_cccf_get_phi (qdetector_cccf _q); // carrier phase offset estimate
//
// Pre-demodulation detector
//
typedef struct detector_cccf_s * detector_cccf;
// create pre-demod detector
// _s : sequence
// _n : sequence length
// _threshold : detection threshold (default: 0.7)
// _dphi_max : maximum carrier offset
detector_cccf detector_cccf_create(liquid_float_complex * _s,
unsigned int _n,
float _threshold,
float _dphi_max);
// destroy pre-demo detector object
void detector_cccf_destroy(detector_cccf _q);
// print pre-demod detector internal state
void detector_cccf_print(detector_cccf _q);
// reset pre-demod detector internal state
void detector_cccf_reset(detector_cccf _q);
// Run sample through pre-demod detector's correlator.
// Returns '1' if signal was detected, '0' otherwise
// _q : pre-demod detector
// _x : input sample
// _tau_hat : fractional sample offset estimate (set when detected)
// _dphi_hat : carrier frequency offset estimate (set when detected)
// _gamma_hat : channel gain estimate (set when detected)
int detector_cccf_correlate(detector_cccf _q,
liquid_float_complex _x,
float * _tau_hat,
float * _dphi_hat,
float * _gamma_hat);
//
// symbol streaming for testing (no meaningful data, just symbols)
//
#define SYMSTREAM_MANGLE_CFLOAT(name) LIQUID_CONCAT(symstreamcf,name)
#define LIQUID_SYMSTREAM_DEFINE_API(SYMSTREAM,TO) \
\
typedef struct SYMSTREAM(_s) * SYMSTREAM(); \
\
/* create default symstream object */ \
/* (LIQUID_RNYQUIST_ARKAISER, k=2, m=7, beta=0.3, QPSK) */ \
SYMSTREAM() SYMSTREAM(_create)(void); \
\
/* create symstream object with linear modulation */ \
/* _ftype : filter type (e.g. LIQUID_RNYQUIST_RRC) */ \
/* _k : samples per symbol */ \
/* _m : filter delay (symbols) */ \
/* _beta : filter excess bandwidth */ \
/* _ms : modulation scheme (e.g. LIQUID_MODEM_QPSK) */ \
SYMSTREAM() SYMSTREAM(_create_linear)(int _ftype, \
unsigned int _k, \
unsigned int _m, \
float _beta, \
int _ms); \
\
/* destroy symstream object, freeing all internal memory */ \
void SYMSTREAM(_destroy)(SYMSTREAM() _q); \
\
/* print symstream object's parameters */ \
void SYMSTREAM(_print)(SYMSTREAM() _q); \
\
/* reset symstream internal state */ \
void SYMSTREAM(_reset)(SYMSTREAM() _q); \
\
/* write block of samples to output buffer */ \
/* _q : synchronizer object */ \
/* _buf : output buffer [size: _buf_len x 1] */ \
/* _buf_len: output buffer size */ \
void SYMSTREAM(_write_samples)(SYMSTREAM() _q, \
TO * _buf, \
unsigned int _buf_len); \
LIQUID_SYMSTREAM_DEFINE_API(SYMSTREAM_MANGLE_CFLOAT, liquid_float_complex)
//
// multi-signal source for testing (no meaningful data, just signals)
//
#define MSOURCE_MANGLE_CFLOAT(name) LIQUID_CONCAT(msourcecf,name)
#define LIQUID_MSOURCE_DEFINE_API(MSOURCE,TO) \
\
typedef struct MSOURCE(_s) * MSOURCE(); \
\
/* create default msource object */ \
MSOURCE() MSOURCE(_create)(void); \
\
/* destroy msource object */ \
void MSOURCE(_destroy)(MSOURCE() _q); \
\
/* print msrouce object */ \
void MSOURCE(_print)(MSOURCE() _q); \
\
/* reset msrouce object */ \
void MSOURCE(_reset)(MSOURCE() _q); \
\
/* add signal sources */ \
int MSOURCE(_add_tone) (MSOURCE() _q); \
int MSOURCE(_add_noise)(MSOURCE() _q, float _bandwidth); \
int MSOURCE(_add_modem)(MSOURCE() _q, \
int _ms, \
unsigned int _k, \
unsigned int _m, \
float _beta); \
\
/* remove signal */ \
void MSOURCE(_remove)(MSOURCE() _q, int _id); \
\
/* enable/disable signal */ \
void MSOURCE(_enable) (MSOURCE() _q, int _id); \
void MSOURCE(_disable)(MSOURCE() _q, int _id); \
\
/* set signal gain */ \
/* _q : msource object */ \
/* _id : source id */ \
/* _gain : signal gain */ \
void MSOURCE(_set_gain)(MSOURCE() _q, \
int _id, \
float _gain_dB); \
\
/* set carrier offset to signal */ \
/* _q : msource object */ \
/* _id : source id */ \
/* _fc : carrier offset, fc in [-0.5,0.5] */ \
void MSOURCE(_set_frequency)(MSOURCE() _q, \
int _id, \
float _dphi); \
\
/* write block of samples to output buffer */ \
/* _q : synchronizer object */ \
/* _buf : output buffer [size: _buf_len x 1] */ \
/* _buf_len: output buffer size */ \
void MSOURCE(_write_samples)(MSOURCE() _q, \
TO * _buf, \
unsigned int _buf_len); \
LIQUID_MSOURCE_DEFINE_API(MSOURCE_MANGLE_CFLOAT, liquid_float_complex)
//
// Symbol tracking: AGC > symsync > EQ > carrier recovery
//
#define SYMTRACK_MANGLE_RRRF(name) LIQUID_CONCAT(symtrack_rrrf,name)
#define SYMTRACK_MANGLE_CCCF(name) LIQUID_CONCAT(symtrack_cccf,name)
// large macro
// SYMTRACK : name-mangling macro
// T : data type, primitive
// TO : data type, output
// TC : data type, coefficients
// TI : data type, input
#define LIQUID_SYMTRACK_DEFINE_API(SYMTRACK,T,TO,TC,TI) \
\
typedef struct SYMTRACK(_s) * SYMTRACK(); \
\
/* create symtrack object with default parameters */ \
/* _ftype : filter type (e.g. LIQUID_RNYQUIST_RRC) */ \
/* _k : samples per symbol */ \
/* _m : filter delay (symbols) */ \
/* _beta : filter excess bandwidth */ \
/* _ms : modulation scheme (e.g. LIQUID_MODEM_QPSK) */ \
SYMTRACK() SYMTRACK(_create)(int _ftype, \
unsigned int _k, \
unsigned int _m, \
float _beta, \
int _ms); \
\
/* create symtrack object using default parameters */ \
SYMTRACK() SYMTRACK(_create_default)(); \
\
/* destroy symtrack object, freeing all internal memory */ \
void SYMTRACK(_destroy)(SYMTRACK() _q); \
\
/* print symtrack object's parameters */ \
void SYMTRACK(_print)(SYMTRACK() _q); \
\
/* reset symtrack internal state */ \
void SYMTRACK(_reset)(SYMTRACK() _q); \
\
/* set symtrack modulation scheme */ \
void SYMTRACK(_set_modscheme)(SYMTRACK() _q, int _ms); \
\
/* set symtrack internal bandwidth */ \
void SYMTRACK(_set_bandwidth)(SYMTRACK() _q, float _bw); \
\
/* adjust internal nco by requested phase */ \
void SYMTRACK(_adjust_phase)(SYMTRACK() _q, T _dphi); \
\
/* execute synchronizer on single input sample */ \
/* _q : synchronizer object */ \
/* _x : input data sample */ \
/* _y : output data array */ \
/* _ny : number of samples written to output buffer */ \
void SYMTRACK(_execute)(SYMTRACK() _q, \
TI _x, \
TO * _y, \
unsigned int * _ny); \
\
/* execute synchronizer on input data array */ \
/* _q : synchronizer object */ \
/* _x : input data array */ \
/* _nx : number of input samples */ \
/* _y : output data array */ \
/* _ny : number of samples written to output buffer */ \
void SYMTRACK(_execute_block)(SYMTRACK() _q, \
TI * _x, \
unsigned int _nx, \
TO * _y, \
unsigned int * _ny); \
LIQUID_SYMTRACK_DEFINE_API(SYMTRACK_MANGLE_RRRF,
float,
float,
float,
float)
LIQUID_SYMTRACK_DEFINE_API(SYMTRACK_MANGLE_CCCF,
float,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// MODULE : math
//
// ln( Gamma(z) )
float liquid_lngammaf(float _z);
// Gamma(z)
float liquid_gammaf(float _z);
// ln( gamma(z,alpha) ) : lower incomplete gamma function
float liquid_lnlowergammaf(float _z, float _alpha);
// ln( Gamma(z,alpha) ) : upper incomplete gamma function
float liquid_lnuppergammaf(float _z, float _alpha);
// gamma(z,alpha) : lower incomplete gamma function
float liquid_lowergammaf(float _z, float _alpha);
// Gamma(z,alpha) : upper incomplete gamma function
float liquid_uppergammaf(float _z, float _alpha);
// n!
float liquid_factorialf(unsigned int _n);
// ln(I_v(z)) : log Modified Bessel function of the first kind
float liquid_lnbesselif(float _nu, float _z);
// I_v(z) : Modified Bessel function of the first kind
float liquid_besselif(float _nu, float _z);
// I_0(z) : Modified Bessel function of the first kind (order zero)
float liquid_besseli0f(float _z);
// J_v(z) : Bessel function of the first kind
float liquid_besseljf(float _nu, float _z);
// J_0(z) : Bessel function of the first kind (order zero)
float liquid_besselj0f(float _z);
// Q function
float liquid_Qf(float _z);
// Marcum Q-function
float liquid_MarcumQf(int _M,
float _alpha,
float _beta);
// Marcum Q-function (M=1)
float liquid_MarcumQ1f(float _alpha,
float _beta);
// sin(pi x) / (pi x)
float sincf(float _x);
// next power of 2 : y = ceil(log2(_x))
unsigned int liquid_nextpow2(unsigned int _x);
// (n choose k) = n! / ( k! (n-k)! )
float liquid_nchoosek(unsigned int _n, unsigned int _k);
//
// Windowing functions
//
// Modulation schemes available
#define LIQUID_WINDOW_NUM_FUNCTIONS (10)
// prototypes
typedef enum {
LIQUID_WINDOW_UNKNOWN=0, // unknown/unsupported scheme
LIQUID_WINDOW_HAMMING, // Hamming
LIQUID_WINDOW_HANN, // Hann
LIQUID_WINDOW_BLACKMANHARRIS, // Blackman-harris (4-term)
LIQUID_WINDOW_BLACKMANHARRIS7, // Blackman-harris (7-term)
LIQUID_WINDOW_KAISER, // Kaiser (beta factor unspecified)
LIQUID_WINDOW_FLATTOP, // flat top (includes negative values)
LIQUID_WINDOW_TRIANGULAR, // triangular
LIQUID_WINDOW_RCOSTAPER, // raised-cosine taper (taper size unspecified)
LIQUID_WINDOW_KBD, // Kaiser-Bessel derived window (beta factor unspecified)
} liquid_window_type;
// pretty names for window
extern const char * liquid_window_str[LIQUID_WINDOW_NUM_FUNCTIONS][2];
// Print compact list of existing and available windowing functions
void liquid_print_windows();
// returns modulation_scheme based on input string
liquid_window_type liquid_getopt_str2window(const char * _str);
// Kaiser-Bessel derived window (single sample)
// _n : index (0 <= _n < _N)
// _N : length of filter (must be even)
// _beta : Kaiser window parameter (_beta > 0)
float liquid_kbd(unsigned int _n, unsigned int _N, float _beta);
// Kaiser-Bessel derived window (full window)
// _n : length of filter (must be even)
// _beta : Kaiser window parameter (_beta > 0)
// _w : resulting window
void liquid_kbd_window(unsigned int _n, float _beta, float * _w);
// Kaiser window
// _n : window index
// _N : full window length
// _beta : Kaiser-Bessel window shape parameter
// _dt : fractional sample offset
float kaiser(unsigned int _n,
unsigned int _N,
float _beta,
float _dt);
// Hamming window
// _n : window index
// _N : full window length
float hamming(unsigned int _n,
unsigned int _N);
// Hann window
// _n : window index
// _N : full window length
float hann(unsigned int _n,
unsigned int _N);
// Blackman-harris window
// _n : window index
// _N : full window length
float blackmanharris(unsigned int _n,
unsigned int _N);
// 7th order Blackman-harris window
// _n : window index
// _N : full window length
float blackmanharris7(unsigned int _n,
unsigned int _N);
// Flat-top window
// _n : window index
// _N : full window length
float flattop(unsigned int _n,
unsigned int _N);
// Triangular window
// _n : window index
// _N : full window length
// _L : triangle length, _L in {_N, _N+1, _N-1}
float triangular(unsigned int _n,
unsigned int _N,
unsigned int _L);
// raised-cosine tapering window
// _n : window index
// _t : taper length
// _N : full window length
float liquid_rcostaper_windowf(unsigned int _n,
unsigned int _t,
unsigned int _N);
// polynomials
#define POLY_MANGLE_DOUBLE(name) LIQUID_CONCAT(poly, name)
#define POLY_MANGLE_FLOAT(name) LIQUID_CONCAT(polyf, name)
#define POLY_MANGLE_CDOUBLE(name) LIQUID_CONCAT(polyc, name)
#define POLY_MANGLE_CFLOAT(name) LIQUID_CONCAT(polycf, name)
// large macro
// POLY : name-mangling macro
// T : data type
// TC : data type (complex)
#define LIQUID_POLY_DEFINE_API(POLY,T,TC) \
/* evaluate polynomial _p (order _k-1) at value _x */ \
T POLY(_val)(T * _p, unsigned int _k, T _x); \
\
/* least-squares polynomial fit (order _k-1) */ \
void POLY(_fit)(T * _x, \
T * _y, \
unsigned int _n, \
T * _p, \
unsigned int _k); \
\
/* Lagrange polynomial exact fit (order _n-1) */ \
void POLY(_fit_lagrange)(T * _x, \
T * _y, \
unsigned int _n, \
T * _p); \
\
/* Lagrange polynomial interpolation */ \
T POLY(_interp_lagrange)(T * _x, \
T * _y, \
unsigned int _n, \
T _x0); \
\
/* Lagrange polynomial fit (barycentric form) */ \
void POLY(_fit_lagrange_barycentric)(T * _x, \
unsigned int _n, \
T * _w); \
\
/* Lagrange polynomial interpolation (barycentric form) */ \
T POLY(_val_lagrange_barycentric)(T * _x, \
T * _y, \
T * _w, \
T _x0, \
unsigned int _n); \
\
/* expands the polynomial: \
* P_n(x) = (1+x)^n \
* as \
* P_n(x) = p[0] + p[1]*x + p[2]*x^2 + ... + p[n]x^n \
* NOTE: _p has order n=m+k (array is length n+1) \
*/ \
void POLY(_expandbinomial)(unsigned int _n, \
T * _p); \
\
/* expands the polynomial: \
* P_n(x) = (1+x)^m * (1-x)^k \
* as \
* P_n(x) = p[0] + p[1]*x + p[2]*x^2 + ... + p[n]x^n \
* NOTE: _p has order n=m+k (array is length n+1) \
*/ \
void POLY(_expandbinomial_pm)(unsigned int _m, \
unsigned int _k, \
T * _p); \
\
/* expands the polynomial: \
* P_n(x) = (x-r[0]) * (x-r[1]) * ... * (x-r[n-1]) \
* as \
* P_n(x) = c[0] + c[1]*x + ... + c[n]*x^n \
* where r[0],r[1],...,r[n-1] are the roots of P_n(x) \
* NOTE: _c has order _n (array is length _n+1) \
*/ \
void POLY(_expandroots)(T * _a, \
unsigned int _n, \
T * _c); \
\
/* expands the polynomial: \
* P_n(x) = \
* (x*b[0]-a[0]) * (x*b[1]-a[1]) * ... * (x*b[n-1]-a[n-1]) \
* as \
* P_n(x) = c[0] + c[1]*x + ... + c[n]*x^n \
* NOTE: _c has order _n (array is length _n+1) \
*/ \
void POLY(_expandroots2)(T * _a, \
T * _b, \
unsigned int _n, \
T * _c); \
\
/* find roots of the polynomial (complex) */ \
/* _poly : poly array, ascending powers [size: _k x 1] */ \
/* _k : poly length (poly order = _k - 1) */ \
/* _roots : resulting complex roots [size: _k-1 x 1] */ \
void POLY(_findroots)(T * _poly, \
unsigned int _n, \
TC * _roots); \
\
/* find the complex roots of the polynomial using the */ \
/* Durand-Kerner method */ \
void POLY(_findroots_durandkerner)(T * _poly, \
unsigned int _k, \
TC * _roots); \
\
/* find the complex roots of the polynomial using */ \
/* Bairstow's method */ \
void POLY(_findroots_bairstow)(T * _poly, \
unsigned int _k, \
TC * _roots); \
\
/* expands the multiplication of two polynomials */ \
void POLY(_mul)(T * _a, \
unsigned int _order_a, \
T * _b, \
unsigned int _order_b, \
T * _c); \
LIQUID_POLY_DEFINE_API(POLY_MANGLE_DOUBLE,
double,
liquid_double_complex)
LIQUID_POLY_DEFINE_API(POLY_MANGLE_FLOAT,
float,
liquid_float_complex)
LIQUID_POLY_DEFINE_API(POLY_MANGLE_CDOUBLE,
liquid_double_complex,
liquid_double_complex)
LIQUID_POLY_DEFINE_API(POLY_MANGLE_CFLOAT,
liquid_float_complex,
liquid_float_complex)
#if 0
// expands the polynomial: (1+x)^n
void poly_binomial_expand(unsigned int _n, int * _c);
// expands the polynomial: (1+x)^k * (1-x)^(n-k)
void poly_binomial_expand_pm(unsigned int _n,
unsigned int _k,
int * _c);
#endif
//
// modular arithmetic, etc.
//
// maximum number of factors
#define LIQUID_MAX_FACTORS (40)
// is number prime?
int liquid_is_prime(unsigned int _n);
// compute number's prime factors
// _n : number to factor
// _factors : pre-allocated array of factors [size: LIQUID_MAX_FACTORS x 1]
// _num_factors: number of factors found, sorted ascending
void liquid_factor(unsigned int _n,
unsigned int * _factors,
unsigned int * _num_factors);
// compute number's unique prime factors
// _n : number to factor
// _factors : pre-allocated array of factors [size: LIQUID_MAX_FACTORS x 1]
// _num_factors: number of unique factors found, sorted ascending
void liquid_unique_factor(unsigned int _n,
unsigned int * _factors,
unsigned int * _num_factors);
// compute c = base^exp (mod n)
unsigned int liquid_modpow(unsigned int _base,
unsigned int _exp,
unsigned int _n);
// find smallest primitive root of _n
unsigned int liquid_primitive_root(unsigned int _n);
// find smallest primitive root of _n, assuming _n is prime
unsigned int liquid_primitive_root_prime(unsigned int _n);
// Euler's totient function
unsigned int liquid_totient(unsigned int _n);
//
// MODULE : matrix
//
#define MATRIX_MANGLE_DOUBLE(name) LIQUID_CONCAT(matrix, name)
#define MATRIX_MANGLE_FLOAT(name) LIQUID_CONCAT(matrixf, name)
#define MATRIX_MANGLE_CDOUBLE(name) LIQUID_CONCAT(matrixc, name)
#define MATRIX_MANGLE_CFLOAT(name) LIQUID_CONCAT(matrixcf, name)
// large macro
// MATRIX : name-mangling macro
// T : data type
#define LIQUID_MATRIX_DEFINE_API(MATRIX,T) \
\
/* print array as matrix */ \
/* _x : input matrix [size: _r x _c] */ \
/* _r : rows */ \
/* _c : columns */ \
void MATRIX(_print)(T * _x, \
unsigned int _r, \
unsigned int _c); \
\
/* add two matrices _x and _y saving the result in _z */ \
/* _x : input matrix [size: _r x _c] */ \
/* _y : input matrix [size: _r x _c] */ \
/* _z : output matrix [size: _r x _c] */ \
/* _r : rows */ \
/* _c : columns */ \
void MATRIX(_add)(T * _x, \
T * _y, \
T * _z, \
unsigned int _r, \
unsigned int _c); \
\
/* subtract two matrices _x and _y saving the result in _z */ \
/* _x : input matrix [size: _r x _c] */ \
/* _y : input matrix [size: _r x _c] */ \
/* _z : output matrix [size: _r x _c] */ \
/* _r : rows */ \
/* _c : columns */ \
void MATRIX(_sub)(T * _x, \
T * _y, \
T * _z, \
unsigned int _r, \
unsigned int _c); \
\
/* perform point-wise multiplication of two matrices _x */ \
/* and _y saving the result in _z */ \
/* _x : input matrix [size: _r x _c] */ \
/* _y : input matrix [size: _r x _c] */ \
/* _z : output matrix [size: _r x _c] */ \
/* _r : rows */ \
/* _c : columns */ \
void MATRIX(_pmul)(T * _x, \
T * _y, \
T * _z, \
unsigned int _r, \
unsigned int _c); \
\
/* perform point-wise division of two matrices _x and _y */ \
/* saving the result in _z */ \
/* _x : input matrix [size: _r x _c] */ \
/* _y : input matrix [size: _r x _c] */ \
/* _z : output matrix [size: _r x _c] */ \
/* _r : rows */ \
/* _c : columns */ \
void MATRIX(_pdiv)(T * _x, \
T * _y, \
T * _z, \
unsigned int _r, \
unsigned int _c); \
\
/* multiply two matrices _x and _y storing the result in _z */ \
/* NOTE: _rz = _rx, _cz = _cy, and _cx = _ry */ \
/* _x : input matrix [size: _rx x _cx] */ \
/* _y : input matrix [size: _ry x _cy] */ \
/* _z : output matrix [size: _rz x _cz] */ \
void MATRIX(_mul)(T * _x, unsigned int _rx, unsigned int _cx, \
T * _y, unsigned int _ry, unsigned int _cy, \
T * _z, unsigned int _rz, unsigned int _cz); \
\
/* solve _x = _y*_z for _z for square matrices of size _n */ \
/* _x : input matrix [size: _n x _n] */ \
/* _y : input matrix [size: _n x _n] */ \
/* _z : output matrix [size: _n x _n] */ \
void MATRIX(_div)(T * _x, \
T * _y, \
T * _z, \
unsigned int _n); \
\
/* compute the determinant of a square matrix _x */ \
/* _x : input matrix [size: _r x _c] */ \
/* _r : rows */ \
/* _c : columns */ \
T MATRIX(_det)(T * _x, \
unsigned int _r, \
unsigned int _c); \
\
/* compute the in-place transpose of the matrix _x */ \
/* _x : input matrix [size: _r x _c] */ \
/* _r : rows */ \
/* _c : columns */ \
void MATRIX(_trans)(T * _x, \
unsigned int _r, \
unsigned int _c); \
\
/* compute the in-place Hermitian transpose of _x */ \
/* _x : input matrix [size: _r x _c] */ \
/* _r : rows */ \
/* _c : columns */ \
void MATRIX(_hermitian)(T * _x, \
unsigned int _r, \
unsigned int _c); \
\
/* compute x*x' on [m x n] matrix, result: [m x m] */ \
/* _x : input matrix [size: _m x _n] */ \
/* _m : input rows */ \
/* _n : input columns */ \
/* _xxT : output matrix [size: _m x _m] */ \
void MATRIX(_mul_transpose)(T * _x, \
unsigned int _m, \
unsigned int _n, \
T * _xxT); \
\
/* compute x'*x on [m x n] matrix, result: [n x n] */ \
/* _x : input matrix [size: _m x _n] */ \
/* _m : input rows */ \
/* _n : input columns */ \
/* _xTx : output matrix [size: _n x _n] */ \
void MATRIX(_transpose_mul)(T * _x, \
unsigned int _m, \
unsigned int _n, \
T * _xTx); \
\
/* compute x*x.' on [m x n] matrix, result: [m x m] */ \
/* _x : input matrix [size: _m x _n] */ \
/* _m : input rows */ \
/* _n : input columns */ \
/* _xxH : output matrix [size: _m x _m] */ \
void MATRIX(_mul_hermitian)(T * _x, \
unsigned int _m, \
unsigned int _n, \
T * _xxH); \
\
/* compute x.'*x on [m x n] matrix, result: [n x n] */ \
/* _x : input matrix [size: _m x _n] */ \
/* _m : input rows */ \
/* _n : input columns */ \
/* _xHx : output matrix [size: _n x _n] */ \
void MATRIX(_hermitian_mul)(T * _x, \
unsigned int _m, \
unsigned int _n, \
T * _xHx); \
\
\
/* augment two matrices _x and _y storing the result in _z */ \
/* NOTE: _rz = _rx = _ry, _rx = _ry, and _cz = _cx + _cy */ \
/* _x : input matrix [size: _rx x _cx] */ \
/* _y : input matrix [size: _ry x _cy] */ \
/* _z : output matrix [size: _rz x _cz] */ \
void MATRIX(_aug)(T * _x, unsigned int _rx, unsigned int _cx, \
T * _y, unsigned int _ry, unsigned int _cy, \
T * _z, unsigned int _rz, unsigned int _cz); \
\
/* compute the inverse of a square matrix _x */ \
/* _x : input/output matrix [size: _r x _c] */ \
/* _r : rows */ \
/* _c : columns */ \
void MATRIX(_inv)(T * _x, \
unsigned int _r, \
unsigned int _c); \
\
/* generate the identity square matrix of size _n */ \
/* _x : output matrix [size: _n x _n] */ \
/* _n : dimensions of _x */ \
void MATRIX(_eye)(T * _x, \
unsigned int _n); \
\
/* generate the all-ones matrix of size _n */ \
/* _x : output matrix [size: _r x _c] */ \
/* _r : rows */ \
/* _c : columns */ \
void MATRIX(_ones)(T * _n, \
unsigned int _r, \
unsigned int _c); \
\
/* generate the all-zeros matrix of size _n */ \
/* _x : output matrix [size: _r x _c] */ \
/* _r : rows */ \
/* _c : columns */ \
void MATRIX(_zeros)(T * _x, \
unsigned int _r, \
unsigned int _c); \
\
/* perform Gauss-Jordan elimination on matrix _x */ \
/* _x : input/output matrix [size: _r x _c] */ \
/* _r : rows */ \
/* _c : columns */ \
void MATRIX(_gjelim)(T * _x, \
unsigned int _r, \
unsigned int _c); \
\
/* pivot on element _x[_r,_c] */ \
/* _x : output matrix [size: _rx x _cx] */ \
/* _rx : rows of _x */ \
/* _cx : columns of _x */ \
/* _r : pivot row */ \
/* _c : pivot column */ \
void MATRIX(_pivot)(T * _x, \
unsigned int _rx, \
unsigned int _cx, \
unsigned int _r, \
unsigned int _c); \
\
/* swap rows _r1 and _r2 of matrix _x */ \
/* _x : input/output matrix [size: _rx x _cx] */ \
/* _rx : rows of _x */ \
/* _cx : columns of _x */ \
/* _r1 : first row to swap */ \
/* _r2 : second row to swap */ \
void MATRIX(_swaprows)(T * _x, \
unsigned int _rx, \
unsigned int _cx, \
unsigned int _r1, \
unsigned int _r2); \
\
/* solve linear system of _n equations: _A*_x = _b */ \
/* _A : system matrix [size: _n x _n] */ \
/* _n : system size */ \
/* _b : equality vector [size: _n x 1] */ \
/* _x : solution vector [size: _n x 1] */ \
/* _opts : options (ignored for now) */ \
void MATRIX(_linsolve)(T * _A, \
unsigned int _n, \
T * _b, \
T * _x, \
void * _opts); \
\
/* solve linear system of equations using conjugate */ \
/* gradient method */ \
/* _A : symmetric positive definite square matrix */ \
/* _n : system dimension */ \
/* _b : equality [size: _n x 1] */ \
/* _x : solution estimate [size: _n x 1] */ \
/* _opts : options (ignored for now) */ \
void MATRIX(_cgsolve)(T * _A, \
unsigned int _n, \
T * _b, \
T * _x, \
void * _opts); \
\
/* L/U/P decomposition, Crout's method */ \
/* _x : input/output matrix [size: _rx x _cx] */ \
/* _rx : rows of _x */ \
/* _cx : columns of _x */ \
/* _L : first row to swap */ \
/* _U : first row to swap */ \
/* _P : first row to swap */ \
void MATRIX(_ludecomp_crout)(T * _x, \
unsigned int _rx, \
unsigned int _cx, \
T * _L, \
T * _U, \
T * _P); \
\
/* L/U/P decomposition, Doolittle's method */ \
/* _x : input/output matrix [size: _rx x _cx] */ \
/* _rx : rows of _x */ \
/* _cx : columns of _x */ \
/* _L : first row to swap */ \
/* _U : first row to swap */ \
/* _P : first row to swap */ \
void MATRIX(_ludecomp_doolittle)(T * _x, \
unsigned int _rx, \
unsigned int _cx, \
T * _L, \
T * _U, \
T * _P); \
\
/* Orthnormalization using the Gram-Schmidt algorithm */ \
/* _A : input matrix [size: _r x _c] */ \
/* _r : rows */ \
/* _c : columns */ \
/* _v : output matrix */ \
void MATRIX(_gramschmidt)(T * _A, \
unsigned int _r, \
unsigned int _c, \
T * _v); \
\
/* Q/R decomposition using the Gram-Schmidt algorithm such */ \
/* that _A = _Q*_R and _Q^T * _Q = _In and _R is a diagonal */ \
/* matrix */ \
/* NOTE: all matrices are square */ \
/* _A : input matrix [size: _m x _m] */ \
/* _m : rows */ \
/* _n : columns (same as cols) */ \
/* _Q : output matrix [size: _m x _m] */ \
/* _R : output matrix [size: _m x _m] */ \
void MATRIX(_qrdecomp_gramschmidt)(T * _A, \
unsigned int _m, \
unsigned int _n, \
T * _Q, \
T * _R); \
\
/* Compute Cholesky decomposition of a symmetric/Hermitian */ \
/* positive-definite matrix as A = L * L^T */ \
/* _A : input square matrix [size: _n x _n] */ \
/* _n : input matrix dimension */ \
/* _L : output lower-triangular matrix */ \
void MATRIX(_chol)(T * _A, \
unsigned int _n, \
T * _L); \
#define matrix_access(X,R,C,r,c) ((X)[(r)*(C)+(c)])
#define matrixc_access(X,R,C,r,c) matrix_access(X,R,C,r,c)
#define matrixf_access(X,R,C,r,c) matrix_access(X,R,C,r,c)
#define matrixcf_access(X,R,C,r,c) matrix_access(X,R,C,r,c)
LIQUID_MATRIX_DEFINE_API(MATRIX_MANGLE_FLOAT, float)
LIQUID_MATRIX_DEFINE_API(MATRIX_MANGLE_DOUBLE, double)
LIQUID_MATRIX_DEFINE_API(MATRIX_MANGLE_CFLOAT, liquid_float_complex)
LIQUID_MATRIX_DEFINE_API(MATRIX_MANGLE_CDOUBLE, liquid_double_complex)
#define SMATRIX_MANGLE_BOOL(name) LIQUID_CONCAT(smatrixb, name)
#define SMATRIX_MANGLE_FLOAT(name) LIQUID_CONCAT(smatrixf, name)
#define SMATRIX_MANGLE_INT(name) LIQUID_CONCAT(smatrixi, name)
// sparse 'alist' matrix type (similar to MacKay, Davey Lafferty convention)
// large macro
// SMATRIX : name-mangling macro
// T : primitive data type
#define LIQUID_SMATRIX_DEFINE_API(SMATRIX,T) \
typedef struct SMATRIX(_s) * SMATRIX(); \
\
/* create _M x _N matrix, initialized with zeros */ \
SMATRIX() SMATRIX(_create)(unsigned int _M, \
unsigned int _N); \
\
/* create _M x _N matrix, initialized on array */ \
SMATRIX() SMATRIX(_create_array)(T * _x, \
unsigned int _m, \
unsigned int _n); \
\
/* destroy object */ \
void SMATRIX(_destroy)(SMATRIX() _q); \
\
/* print compact form */ \
void SMATRIX(_print)(SMATRIX() _q); \
\
/* print expanded form */ \
void SMATRIX(_print_expanded)(SMATRIX() _q); \
\
/* query properties methods */ \
void SMATRIX(_size)(SMATRIX() _q, \
unsigned int * _m, \
unsigned int * _n); \
\
/* zero all elements */ \
void SMATRIX(_clear)(SMATRIX() _q); /* zero and keep memory */ \
void SMATRIX(_reset)(SMATRIX() _q); /* zero and clear memory */ \
\
/* determine if value has been set (allocated memory) */ \
int SMATRIX(_isset)(SMATRIX() _q, \
unsigned int _m, \
unsigned int _n); \
\
/* inserts/deletes element at index (memory allocation) */ \
void SMATRIX(_insert)(SMATRIX() _q, \
unsigned int _m, \
unsigned int _n, \
T _v); \
void SMATRIX(_delete)(SMATRIX() _q, \
unsigned int _m, \
unsigned int _n); \
\
/* sets/gets the value (with memory allocation if needed) */ \
void SMATRIX(_set)(SMATRIX() _q, \
unsigned int _m, \
unsigned int _n, \
T _v); \
T SMATRIX(_get)(SMATRIX() _q, \
unsigned int _m, \
unsigned int _n); \
\
/* initialize to identity matrix */ \
void SMATRIX(_eye)(SMATRIX() _q); \
\
/* multiply two sparse binary matrices */ \
void SMATRIX(_mul)(SMATRIX() _x, \
SMATRIX() _y, \
SMATRIX() _z); \
\
/* multiply sparse matrix by vector */ \
/* _q : sparse matrix */ \
/* _x : input vector [size: _N x 1] */ \
/* _y : output vector [size: _M x 1] */ \
void SMATRIX(_vmul)(SMATRIX() _q, \
T * _x, \
T * _y); \
LIQUID_SMATRIX_DEFINE_API(SMATRIX_MANGLE_BOOL, unsigned char)
LIQUID_SMATRIX_DEFINE_API(SMATRIX_MANGLE_FLOAT, float)
LIQUID_SMATRIX_DEFINE_API(SMATRIX_MANGLE_INT, short int)
//
// smatrix cross methods
//
// multiply sparse binary matrix by floating-point matrix
// _q : sparse matrix [size: A->M x A->N]
// _x : input vector [size: mx x nx ]
// _y : output vector [size: my x ny ]
void smatrixb_mulf(smatrixb _A,
float * _x,
unsigned int _mx,
unsigned int _nx,
float * _y,
unsigned int _my,
unsigned int _ny);
// multiply sparse binary matrix by floating-point vector
// _q : sparse matrix
// _x : input vector [size: _N x 1]
// _y : output vector [size: _M x 1]
void smatrixb_vmulf(smatrixb _q,
float * _x,
float * _y);
//
// MODULE : modem (modulator/demodulator)
//
// Maximum number of allowed bits per symbol
#define MAX_MOD_BITS_PER_SYMBOL 8
// Modulation schemes available
#define LIQUID_MODEM_NUM_SCHEMES (52)
typedef enum {
LIQUID_MODEM_UNKNOWN=0, // Unknown modulation scheme
// Phase-shift keying (PSK)
LIQUID_MODEM_PSK2, LIQUID_MODEM_PSK4,
LIQUID_MODEM_PSK8, LIQUID_MODEM_PSK16,
LIQUID_MODEM_PSK32, LIQUID_MODEM_PSK64,
LIQUID_MODEM_PSK128, LIQUID_MODEM_PSK256,
// Differential phase-shift keying (DPSK)
LIQUID_MODEM_DPSK2, LIQUID_MODEM_DPSK4,
LIQUID_MODEM_DPSK8, LIQUID_MODEM_DPSK16,
LIQUID_MODEM_DPSK32, LIQUID_MODEM_DPSK64,
LIQUID_MODEM_DPSK128, LIQUID_MODEM_DPSK256,
// amplitude-shift keying
LIQUID_MODEM_ASK2, LIQUID_MODEM_ASK4,
LIQUID_MODEM_ASK8, LIQUID_MODEM_ASK16,
LIQUID_MODEM_ASK32, LIQUID_MODEM_ASK64,
LIQUID_MODEM_ASK128, LIQUID_MODEM_ASK256,
// rectangular quadrature amplitude-shift keying (QAM)
LIQUID_MODEM_QAM4,
LIQUID_MODEM_QAM8, LIQUID_MODEM_QAM16,
LIQUID_MODEM_QAM32, LIQUID_MODEM_QAM64,
LIQUID_MODEM_QAM128, LIQUID_MODEM_QAM256,
// amplitude phase-shift keying (APSK)
LIQUID_MODEM_APSK4,
LIQUID_MODEM_APSK8, LIQUID_MODEM_APSK16,
LIQUID_MODEM_APSK32, LIQUID_MODEM_APSK64,
LIQUID_MODEM_APSK128, LIQUID_MODEM_APSK256,
// specific modem types
LIQUID_MODEM_BPSK, // Specific: binary PSK
LIQUID_MODEM_QPSK, // specific: quaternary PSK
LIQUID_MODEM_OOK, // Specific: on/off keying
LIQUID_MODEM_SQAM32, // 'square' 32-QAM
LIQUID_MODEM_SQAM128, // 'square' 128-QAM
LIQUID_MODEM_V29, // V.29 star constellation
LIQUID_MODEM_ARB16OPT, // optimal 16-QAM
LIQUID_MODEM_ARB32OPT, // optimal 32-QAM
LIQUID_MODEM_ARB64OPT, // optimal 64-QAM
LIQUID_MODEM_ARB128OPT, // optimal 128-QAM
LIQUID_MODEM_ARB256OPT, // optimal 256-QAM
LIQUID_MODEM_ARB64VT, // Virginia Tech logo
// arbitrary modem type
LIQUID_MODEM_ARB // arbitrary QAM
} modulation_scheme;
// structure for holding full modulation type descriptor
struct modulation_type_s {
const char * name; // short name (e.g. 'bpsk')
const char * fullname; // full name (e.g. 'binary phase-shift keying')
modulation_scheme scheme; // modulation scheme (e.g. LIQUID_MODEM_BPSK)
unsigned int bps; // modulation depth (e.g. 1)
};
// full modulation type descriptor
extern const struct modulation_type_s modulation_types[LIQUID_MODEM_NUM_SCHEMES];
// Print compact list of existing and available modulation schemes
void liquid_print_modulation_schemes();
// returns modulation_scheme based on input string
modulation_scheme liquid_getopt_str2mod(const char * _str);
// query basic modulation types
int liquid_modem_is_psk(modulation_scheme _ms);
int liquid_modem_is_dpsk(modulation_scheme _ms);
int liquid_modem_is_ask(modulation_scheme _ms);
int liquid_modem_is_qam(modulation_scheme _ms);
int liquid_modem_is_apsk(modulation_scheme _ms);
// useful functions
// counts the number of different bits between two symbols
unsigned int count_bit_errors(unsigned int _s1, unsigned int _s2);
// counts the number of different bits between two arrays of symbols
// _msg0 : original message [size: _n x 1]
// _msg1 : copy of original message [size: _n x 1]
// _n : message size
unsigned int count_bit_errors_array(unsigned char * _msg0,
unsigned char * _msg1,
unsigned int _n);
// converts binary-coded decimal (BCD) to gray, ensuring successive values
// differ by exactly one bit
unsigned int gray_encode(unsigned int symbol_in);
// converts a gray-encoded symbol to binary-coded decimal (BCD)
unsigned int gray_decode(unsigned int symbol_in);
// pack soft bits into symbol
// _soft_bits : soft input bits [size: _bps x 1]
// _bps : bits per symbol
// _sym_out : output symbol, value in [0,2^_bps)
void liquid_pack_soft_bits(unsigned char * _soft_bits,
unsigned int _bps,
unsigned int * _sym_out);
// unpack soft bits into symbol
// _sym_in : input symbol, value in [0,2^_bps)
// _bps : bits per symbol
// _soft_bits : soft output bits [size: _bps x 1]
void liquid_unpack_soft_bits(unsigned int _sym_in,
unsigned int _bps,
unsigned char * _soft_bits);
//
// Linear modem
//
#define LIQUID_MODEM_MANGLE_FLOAT(name) LIQUID_CONCAT(modem,name)
// Macro : MODEM
// MODEM : name-mangling macro
// T : primitive data type
// TC : primitive data type (complex)
#define LIQUID_MODEM_DEFINE_API(MODEM,T,TC) \
\
/* define struct pointer */ \
typedef struct MODEM(_s) * MODEM(); \
\
/* create digital modem object */ \
MODEM() MODEM(_create)(modulation_scheme _scheme); \
\
/* create arbitrary digital modem object */ \
/* _table : array of complex constellation points */ \
/* _M : modulation order and table size */ \
MODEM() MODEM(_create_arbitrary)(TC * _table, \
unsigned int _M); \
\
/* recreate modulation scheme, re-allocating memory as */ \
/* necessary */ \
MODEM() MODEM(_recreate)(MODEM() _q, \
modulation_scheme _scheme); \
\
void MODEM(_destroy)(MODEM() _q); \
void MODEM(_print)( MODEM() _q); \
void MODEM(_reset)( MODEM() _q); \
\
/* generate random symbol */ \
unsigned int MODEM(_gen_rand_sym)(MODEM() _q); \
\
/* Accessor functions */ \
unsigned int MODEM(_get_bps) (MODEM() _q); \
modulation_scheme MODEM(_get_scheme)(MODEM() _q); \
\
/* generic modulate function; simply queries modem scheme */ \
/* and calls appropriate subroutine */ \
/* _q : modem object */ \
/* _s : input symbol */ \
/* _x : output sample */ \
void MODEM(_modulate)(MODEM() _q, \
unsigned int _s, \
TC * _y); \
\
/* generic hard-decision demodulation function */ \
/* _q : modem object */ \
/* _x : input sample */ \
/* _s : output symbol */ \
void MODEM(_demodulate)(MODEM() _q, \
TC _x, \
unsigned int * _s); \
\
/* generic soft-decision demodulation function */ \
/* _q : modem object */ \
/* _x : input sample */ \
/* _s : output hard symbol */ \
/* _soft_bits : output soft bits */ \
void MODEM(_demodulate_soft)(MODEM() _q, \
TC _x, \
unsigned int * _s, \
unsigned char * _soft_bits); \
\
/* get demodulator's estimated transmit sample */ \
void MODEM(_get_demodulator_sample)(MODEM() _q, \
TC * _x_hat); \
\
/* get demodulator phase error */ \
float MODEM(_get_demodulator_phase_error)(MODEM() _q); \
\
/* get demodulator error vector magnitude */ \
float MODEM(_get_demodulator_evm)(MODEM() _q); \
// define modem APIs
LIQUID_MODEM_DEFINE_API(LIQUID_MODEM_MANGLE_FLOAT,float,liquid_float_complex)
//
// continuous-phase modulation
//
// gmskmod : GMSK modulator
typedef struct gmskmod_s * gmskmod;
// create gmskmod object
// _k : samples/symbol
// _m : filter delay (symbols)
// _BT : excess bandwidth factor
gmskmod gmskmod_create(unsigned int _k,
unsigned int _m,
float _BT);
void gmskmod_destroy(gmskmod _q);
void gmskmod_print(gmskmod _q);
void gmskmod_reset(gmskmod _q);
void gmskmod_modulate(gmskmod _q,
unsigned int _sym,
liquid_float_complex * _y);
// gmskdem : GMSK demodulator
typedef struct gmskdem_s * gmskdem;
// create gmskdem object
// _k : samples/symbol
// _m : filter delay (symbols)
// _BT : excess bandwidth factor
gmskdem gmskdem_create(unsigned int _k,
unsigned int _m,
float _BT);
void gmskdem_destroy(gmskdem _q);
void gmskdem_print(gmskdem _q);
void gmskdem_reset(gmskdem _q);
void gmskdem_set_eq_bw(gmskdem _q, float _bw);
void gmskdem_demodulate(gmskdem _q,
liquid_float_complex * _y,
unsigned int * _sym);
//
// continuous phase frequency-shift keying (CP-FSK) modems
//
// CP-FSK filter prototypes
typedef enum {
LIQUID_CPFSK_SQUARE=0, // square pulse
LIQUID_CPFSK_RCOS_FULL, // raised-cosine (full response)
LIQUID_CPFSK_RCOS_PARTIAL, // raised-cosine (partial response)
LIQUID_CPFSK_GMSK, // Gauss minimum-shift keying pulse
} liquid_cpfsk_filter;
// CP-FSK modulator
typedef struct cpfskmod_s * cpfskmod;
// create cpfskmod object (frequency modulator)
// _bps : bits per symbol, _bps > 0
// _h : modulation index, _h > 0
// _k : samples/symbol, _k > 1, _k even
// _m : filter delay (symbols), _m > 0
// _beta : filter bandwidth parameter, _beta > 0
// _type : filter type (e.g. LIQUID_CPFSK_SQUARE)
cpfskmod cpfskmod_create(unsigned int _bps,
float _h,
unsigned int _k,
unsigned int _m,
float _beta,
int _type);
//cpfskmod cpfskmod_create_msk(unsigned int _k);
//cpfskmod cpfskmod_create_gmsk(unsigned int _k, float _BT);
// destroy cpfskmod object
void cpfskmod_destroy(cpfskmod _q);
// print cpfskmod object internals
void cpfskmod_print(cpfskmod _q);
// reset state
void cpfskmod_reset(cpfskmod _q);
// get transmit delay [symbols]
unsigned int cpfskmod_get_delay(cpfskmod _q);
// modulate sample
// _q : frequency modulator object
// _s : input symbol
// _y : output sample array [size: _k x 1]
void cpfskmod_modulate(cpfskmod _q,
unsigned int _s,
liquid_float_complex * _y);
// CP-FSK demodulator
typedef struct cpfskdem_s * cpfskdem;
// create cpfskdem object (frequency modulator)
// _bps : bits per symbol, _bps > 0
// _h : modulation index, _h > 0
// _k : samples/symbol, _k > 1, _k even
// _m : filter delay (symbols), _m > 0
// _beta : filter bandwidth parameter, _beta > 0
// _type : filter type (e.g. LIQUID_CPFSK_SQUARE)
cpfskdem cpfskdem_create(unsigned int _bps,
float _h,
unsigned int _k,
unsigned int _m,
float _beta,
int _type);
//cpfskdem cpfskdem_create_msk(unsigned int _k);
//cpfskdem cpfskdem_create_gmsk(unsigned int _k, float _BT);
// destroy cpfskdem object
void cpfskdem_destroy(cpfskdem _q);
// print cpfskdem object internals
void cpfskdem_print(cpfskdem _q);
// reset state
void cpfskdem_reset(cpfskdem _q);
// get receive delay [symbols]
unsigned int cpfskdem_get_delay(cpfskdem _q);
#if 0
// demodulate array of samples
// _q : continuous-phase frequency demodulator object
// _y : input sample array [size: _n x 1]
// _n : input sample array length
// _s : output symbol array
// _nw : number of output symbols written
void cpfskdem_demodulate(cpfskdem _q,
liquid_float_complex * _y,
unsigned int _n,
unsigned int * _s,
unsigned int * _nw);
#else
// demodulate array of samples, assuming perfect timing
// _q : continuous-phase frequency demodulator object
// _y : input sample array [size: _k x 1]
unsigned int cpfskdem_demodulate(cpfskdem _q,
liquid_float_complex * _y);
#endif
//
// M-ary frequency-shift keying (MFSK) modems
//
// FSK modulator
typedef struct fskmod_s * fskmod;
// create fskmod object (frequency modulator)
// _m : bits per symbol, _bps > 0
// _k : samples/symbol, _k >= 2^_m
// _bandwidth : total signal bandwidth, (0,0.5)
fskmod fskmod_create(unsigned int _m,
unsigned int _k,
float _bandwidth);
// destroy fskmod object
void fskmod_destroy(fskmod _q);
// print fskmod object internals
void fskmod_print(fskmod _q);
// reset state
void fskmod_reset(fskmod _q);
// modulate sample
// _q : frequency modulator object
// _s : input symbol
// _y : output sample array [size: _k x 1]
void fskmod_modulate(fskmod _q,
unsigned int _s,
liquid_float_complex * _y);
// FSK demodulator
typedef struct fskdem_s * fskdem;
// create fskdem object (frequency demodulator)
// _m : bits per symbol, _bps > 0
// _k : samples/symbol, _k >= 2^_m
// _bandwidth : total signal bandwidth, (0,0.5)
fskdem fskdem_create(unsigned int _m,
unsigned int _k,
float _bandwidth);
// destroy fskdem object
void fskdem_destroy(fskdem _q);
// print fskdem object internals
void fskdem_print(fskdem _q);
// reset state
void fskdem_reset(fskdem _q);
// demodulate symbol, assuming perfect symbol timing
// _q : fskdem object
// _y : input sample array [size: _k x 1]
unsigned int fskdem_demodulate(fskdem _q,
liquid_float_complex * _y);
// get demodulator frequency error
float fskdem_get_frequency_error(fskdem _q);
//
// Analog frequency modulator
//
#define LIQUID_FREQMOD_MANGLE_FLOAT(name) LIQUID_CONCAT(freqmod,name)
// Macro : FREQMOD (analog frequency modulator)
// FREQMOD : name-mangling macro
// T : primitive data type
// TC : primitive data type (complex)
#define LIQUID_FREQMOD_DEFINE_API(FREQMOD,T,TC) \
\
/* define struct pointer */ \
typedef struct FREQMOD(_s) * FREQMOD(); \
\
/* create freqmod object (frequency modulator) */ \
/* _kf : modulation factor */ \
FREQMOD() FREQMOD(_create)(float _kf); \
\
/* destroy freqmod object */ \
void FREQMOD(_destroy)(FREQMOD() _q); \
\
/* print freqmod object internals */ \
void FREQMOD(_print)(FREQMOD() _q); \
\
/* reset state */ \
void FREQMOD(_reset)(FREQMOD() _q); \
\
/* modulate single sample */ \
/* _q : frequency modulator object */ \
/* _m : message signal m(t) */ \
/* _s : complex baseband signal s(t) */ \
void FREQMOD(_modulate)(FREQMOD() _q, \
T _m, \
TC * _s); \
\
/* modulate block of samples */ \
/* _q : frequency modulator object */ \
/* _m : message signal m(t), [size: _n x 1] */ \
/* _n : number of input, output samples */ \
/* _s : complex baseband signal s(t) [size: _n x 1] */ \
void FREQMOD(_modulate_block)(FREQMOD() _q, \
T * _m, \
unsigned int _n, \
TC * _s); \
// define freqmod APIs
LIQUID_FREQMOD_DEFINE_API(LIQUID_FREQMOD_MANGLE_FLOAT,float,liquid_float_complex)
//
// Analog frequency demodulator
//
#define LIQUID_FREQDEM_MANGLE_FLOAT(name) LIQUID_CONCAT(freqdem,name)
// Macro : FREQDEM (analog frequency modulator)
// FREQDEM : name-mangling macro
// T : primitive data type
// TC : primitive data type (complex)
#define LIQUID_FREQDEM_DEFINE_API(FREQDEM,T,TC) \
\
/* define struct pointer */ \
typedef struct FREQDEM(_s) * FREQDEM(); \
\
/* create freqdem object (frequency modulator) */ \
/* _kf : modulation factor */ \
FREQDEM() FREQDEM(_create)(float _kf); \
\
/* destroy freqdem object */ \
void FREQDEM(_destroy)(FREQDEM() _q); \
\
/* print freqdem object internals */ \
void FREQDEM(_print)(FREQDEM() _q); \
\
/* reset state */ \
void FREQDEM(_reset)(FREQDEM() _q); \
\
/* demodulate sample */ \
/* _q : frequency modulator object */ \
/* _r : received signal r(t) */ \
/* _m : output message signal m(t) */ \
void FREQDEM(_demodulate)(FREQDEM() _q, \
TC _r, \
T * _m); \
\
/* demodulate block of samples */ \
/* _q : frequency demodulator object */ \
/* _r : received signal r(t) [size: _n x 1] */ \
/* _n : number of input, output samples */ \
/* _m : message signal m(t), [size: _n x 1] */ \
void FREQDEM(_demodulate_block)(FREQDEM() _q, \
TC * _r, \
unsigned int _n, \
T * _m); \
// define freqdem APIs
LIQUID_FREQDEM_DEFINE_API(LIQUID_FREQDEM_MANGLE_FLOAT,float,liquid_float_complex)
// amplitude modulation types
typedef enum {
LIQUID_AMPMODEM_DSB=0, // double side-band
LIQUID_AMPMODEM_USB, // single side-band (upper)
LIQUID_AMPMODEM_LSB // single side-band (lower)
} liquid_ampmodem_type;
typedef struct ampmodem_s * ampmodem;
// create ampmodem object
// _m : modulation index
// _fc : carrier frequency, range: [-0.5,0.5]
// _type : AM type (e.g. LIQUID_AMPMODEM_DSB)
// _suppressed_carrier : carrier suppression flag
ampmodem ampmodem_create(float _m,
float _fc,
liquid_ampmodem_type _type,
int _suppressed_carrier);
// destroy ampmodem object
void ampmodem_destroy(ampmodem _fm);
// print ampmodem object internals
void ampmodem_print(ampmodem _fm);
// reset ampmodem object state
void ampmodem_reset(ampmodem _fm);
// modulate sample
void ampmodem_modulate(ampmodem _fm,
float _x,
liquid_float_complex *_y);
void ampmodem_modulate_block(ampmodem _q,
float * _m,
unsigned int _n,
liquid_float_complex *_s);
// demodulate sample
void ampmodem_demodulate(ampmodem _fm,
liquid_float_complex _y,
float *_x);
void ampmodem_demodulate_block(ampmodem _q,
liquid_float_complex * _r,
unsigned int _n,
float * _m);
//
// MODULE : multichannel
//
#define FIRPFBCH_NYQUIST 0
#define FIRPFBCH_ROOTNYQUIST 1
#define LIQUID_ANALYZER 0
#define LIQUID_SYNTHESIZER 1
//
// Finite impulse response polyphase filterbank channelizer
//
#define FIRPFBCH_MANGLE_CRCF(name) LIQUID_CONCAT(firpfbch_crcf,name)
#define FIRPFBCH_MANGLE_CCCF(name) LIQUID_CONCAT(firpfbch_cccf,name)
// Macro:
// FIRPFBCH : name-mangling macro
// TO : output data type
// TC : coefficients data type
// TI : input data type
#define LIQUID_FIRPFBCH_DEFINE_API(FIRPFBCH,TO,TC,TI) \
typedef struct FIRPFBCH(_s) * FIRPFBCH(); \
\
/* create finite impulse response polyphase filter-bank */ \
/* channelizer object from external coefficients */ \
/* _type : channelizer type, e.g. LIQUID_ANALYZER */ \
/* _M : number of channels */ \
/* _p : number of coefficients for each channel */ \
/* _h : coefficients [size: _M*_p x 1] */ \
FIRPFBCH() FIRPFBCH(_create)(int _type, \
unsigned int _M, \
unsigned int _p, \
TC * _h); \
\
/* create FIR polyphase filterbank channelizer object with */ \
/* prototype filter based on windowed Kaiser design */ \
/* _type : type (LIQUID_ANALYZER | LIQUID_SYNTHESIZER) */ \
/* _M : number of channels */ \
/* _m : filter delay (symbols) */ \
/* _As : stop-band attentuation [dB] */ \
FIRPFBCH() FIRPFBCH(_create_kaiser)(int _type, \
unsigned int _M, \
unsigned int _m, \
float _As); \
\
/* create FIR polyphase filterbank channelizer object with */ \
/* prototype root-Nyquist filter */ \
/* _type : type (LIQUID_ANALYZER | LIQUID_SYNTHESIZER) */ \
/* _M : number of channels */ \
/* _m : filter delay (symbols) */ \
/* _beta : filter excess bandwidth factor, in [0,1] */ \
/* _ftype : filter prototype (rrcos, rkaiser, etc.) */ \
FIRPFBCH() FIRPFBCH(_create_rnyquist)(int _type, \
unsigned int _M, \
unsigned int _m, \
float _beta, \
int _ftype); \
\
/* destroy firpfbch object */ \
void FIRPFBCH(_destroy)(FIRPFBCH() _q); \
\
/* clear/reset firpfbch internal state */ \
void FIRPFBCH(_reset)(FIRPFBCH() _q); \
\
/* print firpfbch internal parameters to stdout */ \
void FIRPFBCH(_print)(FIRPFBCH() _q); \
\
/* execute filterbank as synthesizer on block of samples */ \
/* _q : filterbank channelizer object */ \
/* _x : channelized input, [size: num_channels x 1] */ \
/* _y : output time series, [size: num_channels x 1] */ \
void FIRPFBCH(_synthesizer_execute)(FIRPFBCH() _q, \
TI * _x, \
TO * _y); \
\
/* execute filterbank as analyzer on block of samples */ \
/* _q : filterbank channelizer object */ \
/* _x : input time series, [size: num_channels x 1] */ \
/* _y : channelized output, [size: num_channels x 1] */ \
void FIRPFBCH(_analyzer_execute)(FIRPFBCH() _q, \
TI * _x, \
TO * _y); \
LIQUID_FIRPFBCH_DEFINE_API(FIRPFBCH_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
LIQUID_FIRPFBCH_DEFINE_API(FIRPFBCH_MANGLE_CCCF,
liquid_float_complex,
liquid_float_complex,
liquid_float_complex)
//
// Finite impulse response polyphase filterbank channelizer
// with output rate 2 Fs / M
//
#define FIRPFBCH2_MANGLE_CRCF(name) LIQUID_CONCAT(firpfbch2_crcf,name)
// Macro:
// FIRPFBCH2 : name-mangling macro
// TO : output data type
// TC : coefficients data type
// TI : input data type
#define LIQUID_FIRPFBCH2_DEFINE_API(FIRPFBCH2,TO,TC,TI) \
typedef struct FIRPFBCH2(_s) * FIRPFBCH2(); \
\
/* create firpfbch2 object */ \
/* _type : channelizer type (e.g. LIQUID_ANALYZER) */ \
/* _M : number of channels (must be even) */ \
/* _m : prototype filter semi-lenth, length=2*M*m */ \
/* _h : prototype filter coefficient array */ \
FIRPFBCH2() FIRPFBCH2(_create)(int _type, \
unsigned int _M, \
unsigned int _m, \
TC * _h); \
\
/* create firpfbch2 object using Kaiser window prototype */ \
/* _type : channelizer type (e.g. LIQUID_ANALYZER) */ \
/* _M : number of channels (must be even) */ \
/* _m : prototype filter semi-lenth, length=2*M*m+1 */ \
/* _As : filter stop-band attenuation [dB] */ \
FIRPFBCH2() FIRPFBCH2(_create_kaiser)(int _type, \
unsigned int _M, \
unsigned int _m, \
float _As); \
\
/* destroy firpfbch2 object, freeing internal memory */ \
void FIRPFBCH2(_destroy)(FIRPFBCH2() _q); \
\
/* reset firpfbch2 object internals */ \
void FIRPFBCH2(_reset)(FIRPFBCH2() _q); \
\
/* print firpfbch2 object internals */ \
void FIRPFBCH2(_print)(FIRPFBCH2() _q); \
\
/* execute filterbank channelizer */ \
/* LIQUID_ANALYZER: input: M/2, output: M */ \
/* LIQUID_SYNTHESIZER: input: M, output: M/2 */ \
/* _x : channelizer input */ \
/* _y : channelizer output */ \
void FIRPFBCH2(_execute)(FIRPFBCH2() _q, \
TI * _x, \
TO * _y); \
LIQUID_FIRPFBCH2_DEFINE_API(FIRPFBCH2_MANGLE_CRCF,
liquid_float_complex,
float,
liquid_float_complex)
#define OFDMFRAME_SCTYPE_NULL 0
#define OFDMFRAME_SCTYPE_PILOT 1
#define OFDMFRAME_SCTYPE_DATA 2
// initialize default subcarrier allocation
// _M : number of subcarriers
// _p : output subcarrier allocation array, [size: _M x 1]
void ofdmframe_init_default_sctype(unsigned int _M,
unsigned char * _p);
// initialize default subcarrier allocation
// _M : number of subcarriers
// _f0 : lower frequency band, _f0 in [-0.5,0.5]
// _f1 : upper frequency band, _f1 in [-0.5,0.5]
// _p : output subcarrier allocation array, [size: _M x 1]
void ofdmframe_init_sctype_range(unsigned int _M,
float _f0,
float _f1,
unsigned char * _p);
// validate subcarrier type (count number of null, pilot, and data
// subcarriers in the allocation)
// _p : subcarrier allocation array, [size: _M x 1]
// _M : number of subcarriers
// _M_null : output number of null subcarriers
// _M_pilot : output number of pilot subcarriers
// _M_data : output number of data subcarriers
void ofdmframe_validate_sctype(unsigned char * _p,
unsigned int _M,
unsigned int * _M_null,
unsigned int * _M_pilot,
unsigned int * _M_data);
// print subcarrier allocation to screen
// _p : output subcarrier allocation array, [size: _M x 1]
// _M : number of subcarriers
void ofdmframe_print_sctype(unsigned char * _p,
unsigned int _M);
//
// OFDM frame (symbol) generator
//
typedef struct ofdmframegen_s * ofdmframegen;
// create OFDM framing generator object
// _M : number of subcarriers, >10 typical
// _cp_len : cyclic prefix length
// _taper_len : taper length (OFDM symbol overlap)
// _p : subcarrier allocation (null, pilot, data), [size: _M x 1]
ofdmframegen ofdmframegen_create(unsigned int _M,
unsigned int _cp_len,
unsigned int _taper_len,
unsigned char * _p);
void ofdmframegen_destroy(ofdmframegen _q);
void ofdmframegen_print(ofdmframegen _q);
void ofdmframegen_reset(ofdmframegen _q);
// write first S0 symbol
void ofdmframegen_write_S0a(ofdmframegen _q,
liquid_float_complex *_y);
// write second S0 symbol
void ofdmframegen_write_S0b(ofdmframegen _q,
liquid_float_complex *_y);
// write S1 symbol
void ofdmframegen_write_S1(ofdmframegen _q,
liquid_float_complex *_y);
// write data symbol
void ofdmframegen_writesymbol(ofdmframegen _q,
liquid_float_complex * _x,
liquid_float_complex *_y);
// write tail
void ofdmframegen_writetail(ofdmframegen _q,
liquid_float_complex * _x);
//
// OFDM frame (symbol) synchronizer
//
typedef int (*ofdmframesync_callback)(liquid_float_complex * _y,
unsigned char * _p,
unsigned int _M,
void * _userdata);
typedef struct ofdmframesync_s * ofdmframesync;
// create OFDM framing synchronizer object
// _M : number of subcarriers, >10 typical
// _cp_len : cyclic prefix length
// _taper_len : taper length (OFDM symbol overlap)
// _p : subcarrier allocation (null, pilot, data), [size: _M x 1]
// _callback : user-defined callback function
// _userdata : user-defined data pointer
ofdmframesync ofdmframesync_create(unsigned int _M,
unsigned int _cp_len,
unsigned int _taper_len,
unsigned char * _p,
ofdmframesync_callback _callback,
void * _userdata);
void ofdmframesync_destroy(ofdmframesync _q);
void ofdmframesync_print(ofdmframesync _q);
void ofdmframesync_reset(ofdmframesync _q);
void ofdmframesync_execute(ofdmframesync _q,
liquid_float_complex * _x,
unsigned int _n);
// query methods
float ofdmframesync_get_rssi(ofdmframesync _q); // received signal strength indication
float ofdmframesync_get_cfo(ofdmframesync _q); // carrier offset estimate
// debugging
void ofdmframesync_debug_enable(ofdmframesync _q);
void ofdmframesync_debug_disable(ofdmframesync _q);
void ofdmframesync_debug_print(ofdmframesync _q, const char * _filename);
//
// MODULE : nco (numerically-controlled oscillator)
//
// oscillator type
// LIQUID_NCO : numerically-controlled oscillator (fast)
// LIQUID_VCO : "voltage"-controlled oscillator (precise)
typedef enum {
LIQUID_NCO=0,
LIQUID_VCO
} liquid_ncotype;
#define NCO_MANGLE_FLOAT(name) LIQUID_CONCAT(nco_crcf, name)
// large macro
// NCO : name-mangling macro
// T : primitive data type
// TC : input/output data type
#define LIQUID_NCO_DEFINE_API(NCO,T,TC) \
typedef struct NCO(_s) * NCO(); \
\
NCO() NCO(_create)(liquid_ncotype _type); \
void NCO(_destroy)(NCO() _q); \
void NCO(_print)(NCO() _q); \
\
/* set phase/frequency to zero, reset pll filter */ \
void NCO(_reset)(NCO() _q); \
\
/* get/set/adjust internal frequency/phase */ \
T NCO(_get_frequency)( NCO() _q); \
void NCO(_set_frequency)( NCO() _q, T _f); \
void NCO(_adjust_frequency)(NCO() _q, T _df); \
T NCO(_get_phase)( NCO() _q); \
void NCO(_set_phase)( NCO() _q, T _phi); \
void NCO(_adjust_phase)( NCO() _q, T _dphi); \
\
/* increment phase by internal phase step (frequency) */ \
void NCO(_step)(NCO() _q); \
\
/* compute trigonometric functions */ \
T NCO(_sin)(NCO() _q); \
T NCO(_cos)(NCO() _q); \
void NCO(_sincos)(NCO() _q, T* _s, T* _c); \
void NCO(_cexpf)(NCO() _q, TC * _y); \
\
/* pll : phase-locked loop */ \
void NCO(_pll_set_bandwidth)(NCO() _q, T _bandwidth); \
void NCO(_pll_step)(NCO() _q, T _dphi); \
\
/* Rotate input sample up by NCO angle (no stepping) */ \
void NCO(_mix_up)(NCO() _q, TC _x, TC *_y); \
\
/* Rotate input sample down by NCO angle (no stepping) */ \
void NCO(_mix_down)(NCO() _q, TC _x, TC *_y); \
\
/* Rotate input vector up by NCO angle (stepping) */ \
/* _q : nco object */ \
/* _x : input vector [size: _N x 1] */ \
/* _y : output vector [size: _N x 1] */ \
/* _N : vector size */ \
void NCO(_mix_block_up)(NCO() _q, \
TC *_x, \
TC *_y, \
unsigned int _N); \
\
/* Rotate input vector down by NCO angle (stepping) */ \
/* _q : nco object */ \
/* _x : input vector [size: _N x 1] */ \
/* _y : output vector [size: _N x 1] */ \
/* _N : vector size */ \
void NCO(_mix_block_down)(NCO() _q, \
TC *_x, \
TC *_y, \
unsigned int _N); \
// Define nco APIs
LIQUID_NCO_DEFINE_API(NCO_MANGLE_FLOAT, float, liquid_float_complex)
// nco utilities
// unwrap phase of array (basic)
void liquid_unwrap_phase(float * _theta, unsigned int _n);
// unwrap phase of array (advanced)
void liquid_unwrap_phase2(float * _theta, unsigned int _n);
//
// MODULE : optimization
//
// utility function pointer definition
typedef float (*utility_function)(void * _userdata,
float * _v,
unsigned int _n);
// n-dimensional Rosenbrock utility function (minimum at _v = {1,1,1...}
// _userdata : user-defined data structure (convenience)
// _v : input vector [size: _n x 1]
// _n : input vector size
float liquid_rosenbrock(void * _userdata,
float * _v,
unsigned int _n);
// n-dimensional inverse Gauss utility function (minimum at _v = {0,0,0...}
// _userdata : user-defined data structure (convenience)
// _v : input vector [size: _n x 1]
// _n : input vector size
float liquid_invgauss(void * _userdata,
float * _v,
unsigned int _n);
// n-dimensional multimodal utility function (minimum at _v = {0,0,0...}
// _userdata : user-defined data structure (convenience)
// _v : input vector [size: _n x 1]
// _n : input vector size
float liquid_multimodal(void * _userdata,
float * _v,
unsigned int _n);
// n-dimensional spiral utility function (minimum at _v = {0,0,0...}
// _userdata : user-defined data structure (convenience)
// _v : input vector [size: _n x 1]
// _n : input vector size
float liquid_spiral(void * _userdata,
float * _v,
unsigned int _n);
//
// Gradient search
//
#define LIQUID_OPTIM_MINIMIZE (0)
#define LIQUID_OPTIM_MAXIMIZE (1)
typedef struct gradsearch_s * gradsearch;
// Create a gradient search object
// _userdata : user data object pointer
// _v : array of parameters to optimize
// _num_parameters : array length (number of parameters to optimize)
// _u : utility function pointer
// _direction : search direction (e.g. LIQUID_OPTIM_MAXIMIZE)
gradsearch gradsearch_create(void * _userdata,
float * _v,
unsigned int _num_parameters,
utility_function _utility,
int _direction);
// Destroy a gradsearch object
void gradsearch_destroy(gradsearch _q);
// Prints current status of search
void gradsearch_print(gradsearch _q);
// Iterate once
float gradsearch_step(gradsearch _q);
// Execute the search
float gradsearch_execute(gradsearch _q,
unsigned int _max_iterations,
float _target_utility);
// quasi-Newton search
typedef struct qnsearch_s * qnsearch;
// Create a simple qnsearch object; parameters are specified internally
// _userdata : userdata
// _v : array of parameters to optimize
// _num_parameters : array length
// _get_utility : utility function pointer
// _direction : search direction (e.g. LIQUID_OPTIM_MAXIMIZE)
qnsearch qnsearch_create(void * _userdata,
float * _v,
unsigned int _num_parameters,
utility_function _u,
int _direction);
// Destroy a qnsearch object
void qnsearch_destroy(qnsearch _g);
// Prints current status of search
void qnsearch_print(qnsearch _g);
// Resets internal state
void qnsearch_reset(qnsearch _g);
// Iterate once
void qnsearch_step(qnsearch _g);
// Execute the search
float qnsearch_execute(qnsearch _g,
unsigned int _max_iterations,
float _target_utility);
//
// chromosome (for genetic algorithm search)
//
typedef struct chromosome_s * chromosome;
// create a chromosome object, variable bits/trait
chromosome chromosome_create(unsigned int * _bits_per_trait,
unsigned int _num_traits);
// create a chromosome object, all traits same resolution
chromosome chromosome_create_basic(unsigned int _num_traits,
unsigned int _bits_per_trait);
// create a chromosome object, cloning a parent
chromosome chromosome_create_clone(chromosome _parent);
// copy existing chromosomes' internal traits (all other internal
// parameters must be equal)
void chromosome_copy(chromosome _parent, chromosome _child);
// Destroy a chromosome object
void chromosome_destroy(chromosome _c);
// get number of traits in chromosome
unsigned int chromosome_get_num_traits(chromosome _c);
// Print chromosome values to screen (binary representation)
void chromosome_print(chromosome _c);
// Print chromosome values to screen (floating-point representation)
void chromosome_printf(chromosome _c);
// clear chromosome (set traits to zero)
void chromosome_reset(chromosome _c);
// initialize chromosome on integer values
void chromosome_init(chromosome _c,
unsigned int * _v);
// initialize chromosome on floating-point values
void chromosome_initf(chromosome _c,
float * _v);
// Mutates chromosome _c at _index
void chromosome_mutate(chromosome _c, unsigned int _index);
// Resulting chromosome _c is a crossover of parents _p1 and _p2 at _threshold
void chromosome_crossover(chromosome _p1,
chromosome _p2,
chromosome _c,
unsigned int _threshold);
// Initializes chromosome to random value
void chromosome_init_random(chromosome _c);
// Returns integer representation of chromosome
unsigned int chromosome_value(chromosome _c,
unsigned int _index);
// Returns floating-point representation of chromosome
float chromosome_valuef(chromosome _c,
unsigned int _index);
//
// genetic algorithm search
//
typedef struct gasearch_s * gasearch;
typedef float (*gasearch_utility)(void * _userdata, chromosome _c);
// Create a simple gasearch object; parameters are specified internally
// _utility : chromosome fitness utility function
// _userdata : user data, void pointer passed to _get_utility() callback
// _parent : initial population parent chromosome, governs precision, etc.
// _minmax : search direction
gasearch gasearch_create(gasearch_utility _u,
void * _userdata,
chromosome _parent,
int _minmax);
// Create a gasearch object, specifying search parameters
// _utility : chromosome fitness utility function
// _userdata : user data, void pointer passed to _get_utility() callback
// _parent : initial population parent chromosome, governs precision, etc.
// _minmax : search direction
// _population_size : number of chromosomes in population
// _mutation_rate : probability of mutating chromosomes
gasearch gasearch_create_advanced(gasearch_utility _utility,
void * _userdata,
chromosome _parent,
int _minmax,
unsigned int _population_size,
float _mutation_rate);
// Destroy a gasearch object
void gasearch_destroy(gasearch _q);
// print search parameter internals
void gasearch_print(gasearch _q);
// set mutation rate
void gasearch_set_mutation_rate(gasearch _q,
float _mutation_rate);
// set population/selection size
// _q : ga search object
// _population_size : new population size (number of chromosomes)
// _selection_size : selection size (number of parents for new generation)
void gasearch_set_population_size(gasearch _q,
unsigned int _population_size,
unsigned int _selection_size);
// Execute the search
// _q : ga search object
// _max_iterations : maximum number of iterations to run before bailing
// _target_utility : target utility
float gasearch_run(gasearch _q,
unsigned int _max_iterations,
float _target_utility);
// iterate over one evolution of the search algorithm
void gasearch_evolve(gasearch _q);
// get optimal chromosome
// _q : ga search object
// _c : output optimal chromosome
// _utility_opt : fitness of _c
void gasearch_getopt(gasearch _q,
chromosome _c,
float * _utility_opt);
//
// MODULE : quantization
//
float compress_mulaw(float _x, float _mu);
float expand_mulaw(float _x, float _mu);
void compress_cf_mulaw(liquid_float_complex _x, float _mu, liquid_float_complex * _y);
void expand_cf_mulaw(liquid_float_complex _y, float _mu, liquid_float_complex * _x);
//float compress_alaw(float _x, float _a);
//float expand_alaw(float _x, float _a);
// inline quantizer: 'analog' signal in [-1, 1]
unsigned int quantize_adc(float _x, unsigned int _num_bits);
float quantize_dac(unsigned int _s, unsigned int _num_bits);
// structured quantizer
typedef enum {
LIQUID_COMPANDER_NONE=0,
LIQUID_COMPANDER_LINEAR,
LIQUID_COMPANDER_MULAW,
LIQUID_COMPANDER_ALAW
} liquid_compander_type;
#define QUANTIZER_MANGLE_FLOAT(name) LIQUID_CONCAT(quantizerf, name)
#define QUANTIZER_MANGLE_CFLOAT(name) LIQUID_CONCAT(quantizercf, name)
// large macro
// QUANTIZER : name-mangling macro
// T : data type
#define LIQUID_QUANTIZER_DEFINE_API(QUANTIZER,T) \
typedef struct QUANTIZER(_s) * QUANTIZER(); \
QUANTIZER() QUANTIZER(_create)(liquid_compander_type _ctype, \
float _range, \
unsigned int _num_bits); \
void QUANTIZER(_destroy)(QUANTIZER() _q); \
void QUANTIZER(_print)(QUANTIZER() _q); \
void QUANTIZER(_execute_adc)(QUANTIZER() _q, \
T _x, \
unsigned int * _sample); \
void QUANTIZER(_execute_dac)(QUANTIZER() _q, \
unsigned int _sample, \
T * _x);
LIQUID_QUANTIZER_DEFINE_API(QUANTIZER_MANGLE_FLOAT, float)
LIQUID_QUANTIZER_DEFINE_API(QUANTIZER_MANGLE_CFLOAT, liquid_float_complex)
//
// MODULE : random (number generators)
//
// Uniform random number generator, (0,1]
float randf();
float randf_pdf(float _x);
float randf_cdf(float _x);
// Gauss random number generator, N(0,1)
// f(x) = 1/sqrt(2*pi*sigma^2) * exp{-(x-eta)^2/(2*sigma^2)}
//
// where
// eta = mean
// sigma = standard deviation
//
float randnf();
void awgn(float *_x, float _nstd);
void crandnf(liquid_float_complex *_y);
void cawgn(liquid_float_complex *_x, float _nstd);
float randnf_pdf(float _x, float _eta, float _sig);
float randnf_cdf(float _x, float _eta, float _sig);
// Exponential
// f(x) = lambda exp{ -lambda x }
// where
// lambda = spread parameter, lambda > 0
// x >= 0
float randexpf(float _lambda);
float randexpf_pdf(float _x, float _lambda);
float randexpf_cdf(float _x, float _lambda);
// Weibull
// f(x) = (a/b) (x/b)^(a-1) exp{ -(x/b)^a }
// where
// a = alpha : shape parameter
// b = beta : scaling parameter
// g = gamma : location (threshold) parameter
//
float randweibf(float _alpha, float _beta, float _gamma);
float randweibf_pdf(float _x, float _a, float _b, float _g);
float randweibf_cdf(float _x, float _a, float _b, float _g);
// Gamma
// x^(a-1) exp(-x/b)
// f(x) = -------------------
// Gamma(a) b^a
// where
// a = alpha : shape parameter, a > 0
// b = beta : scale parameter, b > 0
// Gamma(z) = regular gamma function
// x >= 0
float randgammaf(float _alpha, float _beta);
float randgammaf_pdf(float _x, float _alpha, float _beta);
float randgammaf_cdf(float _x, float _alpha, float _beta);
// Nakagami-m
// f(x) = (2/Gamma(m)) (m/omega)^m x^(2m-1) exp{-(m/omega)x^2}
// where
// m : shape parameter, m >= 0.5
// omega : spread parameter, omega > 0
// Gamma(z): regular complete gamma function
// x >= 0
float randnakmf(float _m, float _omega);
float randnakmf_pdf(float _x, float _m, float _omega);
float randnakmf_cdf(float _x, float _m, float _omega);
// Rice-K
// f(x) = (x/sigma^2) exp{ -(x^2+s^2)/(2sigma^2) } I0( x s / sigma^2 )
// where
// s = sqrt( omega*K/(K+1) )
// sigma = sqrt(0.5 omega/(K+1))
// and
// K = shape parameter
// omega = spread parameter
// I0 = modified Bessel function of the first kind
// x >= 0
float randricekf(float _K, float _omega);
float randricekf_cdf(float _x, float _K, float _omega);
float randricekf_pdf(float _x, float _K, float _omega);
// Data scrambler : whiten data sequence
void scramble_data(unsigned char * _x, unsigned int _len);
void unscramble_data(unsigned char * _x, unsigned int _len);
void unscramble_data_soft(unsigned char * _x, unsigned int _len);
//
// MODULE : sequence
//
// Binary sequence (generic)
typedef struct bsequence_s * bsequence;
// Create a binary sequence of a specific length (number of bits)
bsequence bsequence_create(unsigned int num_bits);
// Free memory in a binary sequence
void bsequence_destroy(bsequence _bs);
// Clear binary sequence (set to 0's)
void bsequence_reset(bsequence _bs);
// initialize sequence on external array
void bsequence_init(bsequence _bs,
unsigned char * _v);
// Print sequence to the screen
void bsequence_print(bsequence _bs);
// Push bit into to back of a binary sequence
void bsequence_push(bsequence _bs,
unsigned int _bit);
// circular shift (left)
void bsequence_circshift(bsequence _bs);
// Correlate two binary sequences together
int bsequence_correlate(bsequence _bs1, bsequence _bs2);
// compute the binary addition of two bit sequences
void bsequence_add(bsequence _bs1, bsequence _bs2, bsequence _bs3);
// compute the binary multiplication of two bit sequences
void bsequence_mul(bsequence _bs1, bsequence _bs2, bsequence _bs3);
// accumulate the 1's in a binary sequence
unsigned int bsequence_accumulate(bsequence _bs);
// accessor functions
unsigned int bsequence_get_length(bsequence _bs);
unsigned int bsequence_index(bsequence _bs, unsigned int _i);
// Complementary codes
// intialize two sequences to complementary codes. sequences must
// be of length at least 8 and a power of 2 (e.g. 8, 16, 32, 64,...)
// _a : sequence 'a' (bsequence object)
// _b : sequence 'b' (bsequence object)
void bsequence_create_ccodes(bsequence _a,
bsequence _b);
// M-Sequence
#define LIQUID_MAX_MSEQUENCE_LENGTH 32767
// default m-sequence generators: g (hex) m n g (oct) g (binary)
#define LIQUID_MSEQUENCE_GENPOLY_M2 0x0007 // 2 3 7 111
#define LIQUID_MSEQUENCE_GENPOLY_M3 0x000B // 3 7 13 1011
#define LIQUID_MSEQUENCE_GENPOLY_M4 0x0013 // 4 15 23 10011
#define LIQUID_MSEQUENCE_GENPOLY_M5 0x0025 // 5 31 45 100101
#define LIQUID_MSEQUENCE_GENPOLY_M6 0x0043 // 6 63 103 1000011
#define LIQUID_MSEQUENCE_GENPOLY_M7 0x0089 // 7 127 211 10001001
#define LIQUID_MSEQUENCE_GENPOLY_M8 0x011D // 8 255 435 100101101
#define LIQUID_MSEQUENCE_GENPOLY_M9 0x0211 // 9 511 1021 1000010001
#define LIQUID_MSEQUENCE_GENPOLY_M10 0x0409 // 10 1023 2011 10000001001
#define LIQUID_MSEQUENCE_GENPOLY_M11 0x0805 // 11 2047 4005 100000000101
#define LIQUID_MSEQUENCE_GENPOLY_M12 0x1053 // 12 4095 10123 1000001010011
#define LIQUID_MSEQUENCE_GENPOLY_M13 0x201b // 13 8191 20033 10000000011011
#define LIQUID_MSEQUENCE_GENPOLY_M14 0x402b // 14 16383 40053 100000000101011
#define LIQUID_MSEQUENCE_GENPOLY_M15 0x8003 // 15 32767 100003 1000000000000011
typedef struct msequence_s * msequence;
// create a maximal-length sequence (m-sequence) object with
// an internal shift register length of _m bits.
// _m : generator polynomial length, sequence length is (2^m)-1
// _g : generator polynomial, starting with most-significant bit
// _a : initial shift register state, default: 000...001
msequence msequence_create(unsigned int _m,
unsigned int _g,
unsigned int _a);
// create a maximal-length sequence (m-sequence) object from a generator polynomial
msequence msequence_create_genpoly(unsigned int _g);
// creates a default maximal-length sequence
msequence msequence_create_default(unsigned int _m);
// destroy an msequence object, freeing all internal memory
void msequence_destroy(msequence _m);
// prints the sequence's internal state to the screen
void msequence_print(msequence _m);
// advance msequence on shift register, returning output bit
unsigned int msequence_advance(msequence _ms);
// generate pseudo-random symbol from shift register by
// advancing _bps bits and returning compacted symbol
// _ms : m-sequence object
// _bps : bits per symbol of output
unsigned int msequence_generate_symbol(msequence _ms,
unsigned int _bps);
// reset msequence shift register to original state, typically '1'
void msequence_reset(msequence _ms);
// initialize a bsequence object on an msequence object
// _bs : bsequence object
// _ms : msequence object
void bsequence_init_msequence(bsequence _bs,
msequence _ms);
// get the length of the sequence
unsigned int msequence_get_length(msequence _ms);
// get the internal state of the sequence
unsigned int msequence_get_state(msequence _ms);
// set the internal state of the sequence
void msequence_set_state(msequence _ms,
unsigned int _a);
//
// MODULE : utility
//
// pack binary array with symbol(s)
// _src : source array [size: _n x 1]
// _n : input source array length
// _k : bit index to write in _src
// _b : number of bits in input symbol
// _sym_in : input symbol
void liquid_pack_array(unsigned char * _src,
unsigned int _n,
unsigned int _k,
unsigned int _b,
unsigned char _sym_in);
// unpack symbols from binary array
// _src : source array [size: _n x 1]
// _n : input source array length
// _k : bit index to write in _src
// _b : number of bits in output symbol
// _sym_out : output symbol
void liquid_unpack_array(unsigned char * _src,
unsigned int _n,
unsigned int _k,
unsigned int _b,
unsigned char * _sym_out);
// pack one-bit symbols into bytes (8-bit symbols)
// _sym_in : input symbols array [size: _sym_in_len x 1]
// _sym_in_len : number of input symbols
// _sym_out : output symbols
// _sym_out_len : number of bytes allocated to output symbols array
// _num_written : number of output symbols actually written
void liquid_pack_bytes(unsigned char * _sym_in,
unsigned int _sym_in_len,
unsigned char * _sym_out,
unsigned int _sym_out_len,
unsigned int * _num_written);
// unpack 8-bit symbols (full bytes) into one-bit symbols
// _sym_in : input symbols array [size: _sym_in_len x 1]
// _sym_in_len : number of input symbols
// _sym_out : output symbols array
// _sym_out_len : number of bytes allocated to output symbols array
// _num_written : number of output symbols actually written
void liquid_unpack_bytes(unsigned char * _sym_in,
unsigned int _sym_in_len,
unsigned char * _sym_out,
unsigned int _sym_out_len,
unsigned int * _num_written);
// repack bytes with arbitrary symbol sizes
// _sym_in : input symbols array [size: _sym_in_len x 1]
// _sym_in_bps : number of bits per input symbol
// _sym_in_len : number of input symbols
// _sym_out : output symbols array
// _sym_out_bps : number of bits per output symbol
// _sym_out_len : number of bytes allocated to output symbols array
// _num_written : number of output symbols actually written
void liquid_repack_bytes(unsigned char * _sym_in,
unsigned int _sym_in_bps,
unsigned int _sym_in_len,
unsigned char * _sym_out,
unsigned int _sym_out_bps,
unsigned int _sym_out_len,
unsigned int * _num_written);
// shift array to the left _b bits, filling in zeros
// _src : source address [size: _n x 1]
// _n : input data array size
// _b : number of bits to shift
void liquid_lbshift(unsigned char * _src,
unsigned int _n,
unsigned int _b);
// shift array to the right _b bits, filling in zeros
// _src : source address [size: _n x 1]
// _n : input data array size
// _b : number of bits to shift
void liquid_rbshift(unsigned char * _src,
unsigned int _n,
unsigned int _b);
// circularly shift array to the left _b bits
// _src : source address [size: _n x 1]
// _n : input data array size
// _b : number of bits to shift
void liquid_lbcircshift(unsigned char * _src,
unsigned int _n,
unsigned int _b);
// circularly shift array to the right _b bits
// _src : source address [size: _n x 1]
// _n : input data array size
// _b : number of bits to shift
void liquid_rbcircshift(unsigned char * _src,
unsigned int _n,
unsigned int _b);
// shift array to the left _b bytes, filling in zeros
// _src : source address [size: _n x 1]
// _n : input data array size
// _b : number of bytes to shift
void liquid_lshift(unsigned char * _src,
unsigned int _n,
unsigned int _b);
// shift array to the right _b bytes, filling in zeros
// _src : source address [size: _n x 1]
// _n : input data array size
// _b : number of bytes to shift
void liquid_rshift(unsigned char * _src,
unsigned int _n,
unsigned int _b);
// circular shift array to the left _b bytes
// _src : source address [size: _n x 1]
// _n : input data array size
// _b : number of bytes to shift
void liquid_lcircshift(unsigned char * _src,
unsigned int _n,
unsigned int _b);
// circular shift array to the right _b bytes
// _src : source address [size: _n x 1]
// _n : input data array size
// _b : number of bytes to shift
void liquid_rcircshift(unsigned char * _src,
unsigned int _n,
unsigned int _b);
// Count the number of ones in an integer
unsigned int liquid_count_ones(unsigned int _x);
// count number of ones in an integer, modulo 2
unsigned int liquid_count_ones_mod2(unsigned int _x);
// compute bindary dot-product between two integers
unsigned int liquid_bdotprod(unsigned int _x,
unsigned int _y);
// Count leading zeros in an integer
unsigned int liquid_count_leading_zeros(unsigned int _x);
// Most-significant bit index
unsigned int liquid_msb_index(unsigned int _x);
// Print string of bits to stdout
void liquid_print_bitstring(unsigned int _x,
unsigned int _n);
// reverse byte, word, etc.
unsigned char liquid_reverse_byte( unsigned char _x);
unsigned int liquid_reverse_uint16(unsigned int _x);
unsigned int liquid_reverse_uint24(unsigned int _x);
unsigned int liquid_reverse_uint32(unsigned int _x);
//
// MODULE : vector
//
#define VECTOR_MANGLE_RF(name) LIQUID_CONCAT(liquid_vectorf, name)
#define VECTOR_MANGLE_CF(name) LIQUID_CONCAT(liquid_vectorcf,name)
// large macro
// VECTOR : name-mangling macro
// T : data type
// TP : data type (primitive)
#define LIQUID_VECTOR_DEFINE_API(VECTOR,T,TP) \
\
/* initialize vector with scalar: x[i] = c (scalar) */ \
void VECTOR(_init)(T _c, \
T * _x, \
unsigned int _n); \
\
/* add each element: z[i] = x[i] + y[i] */ \
void VECTOR(_add)(T * _x, \
T * _y, \
unsigned int _n, \
T * _z); \
/* add scalar to each element: y[i] = x[i] + c */ \
void VECTOR(_addscalar)(T * _x, \
unsigned int _n, \
T _c, \
T * _y); \
\
/* multiply each element: z[i] = x[i] * y[i] */ \
void VECTOR(_mul)(T * _x, \
T * _y, \
unsigned int _n, \
T * _z); \
/* multiply each element with scalar: y[i] = x[i] * c */ \
void VECTOR(_mulscalar)(T * _x, \
unsigned int _n, \
T _c, \
T * _y); \
\
/* compute complex phase rotation: x[i] = exp{j theta[i]} */ \
void VECTOR(_cexpj)(TP * _theta, \
unsigned int _n, \
T * _x); \
/* compute angle of each element: theta[i] = arg{ x[i] } */ \
void VECTOR(_carg)(T * _x, \
unsigned int _n, \
TP * _theta); \
/* compute absolute value of each element: y[i] = |x[i]| */ \
void VECTOR(_abs)(T * _x, \
unsigned int _n, \
TP * _y); \
\
/* compute sum of squares: sum{ |x|^2 } */ \
TP VECTOR(_sumsq)(T * _x, \
unsigned int _n); \
\
/* compute l-2 norm: sqrt{ sum{ |x|^2 } } */ \
TP VECTOR(_norm)(T * _x, \
unsigned int _n); \
\
/* compute l-p norm: { sum{ |x|^p } }^(1/p) */ \
TP VECTOR(_pnorm)(T * _x, \
unsigned int _n, \
TP _p); \
\
/* scale vector elements by l-2 norm: y[i] = x[i]/norm(x) */ \
void VECTOR(_normalize)(T * _x, \
unsigned int _n, \
T * _y); \
LIQUID_VECTOR_DEFINE_API(VECTOR_MANGLE_RF, float, float);
LIQUID_VECTOR_DEFINE_API(VECTOR_MANGLE_CF, liquid_float_complex, float);
//
// mixed types
//
#if 0
void liquid_vectorf_add(float * _a,
float * _b,
unsigned int _n,
float * _c);
#endif
#ifdef __cplusplus
} //extern "C"
#endif // __cplusplus
#endif // __LIQUID_H__
|