📄 ym2151.c
字号:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include "driver.h"#include "sasound.h"#include "ym2151.h"/*undef this to not use MAME timer system*///#define USE_MAME_TIMERS/*#define FM_EMU*/#ifdef FM_EMU #define INLINE static __inline__ #ifdef USE_MAME_TIMERS #undef USE_MAME_TIMERS #endif#endif#ifdef USE_MAME_TIMERS /*#define LOG_CYM_FILE*/ #ifdef LOG_CYM_FILE FILE * cymfile = NULL; void * cymfiletimer = 0; #endif#endif/*operator data*/typedef struct{ unsigned int phase; /*accumulated operator phase*/ unsigned int freq; /*operator frequency*/ signed int DT1v; /*operator DT1 phase inc/decrement*/ unsigned int MUL; /*phase multiply*/ unsigned int DT1; /*DT1 * 32 */ unsigned int DT2; /*DT2 index */ signed int *connect; /*operator output 'direction'*//*Begin of channel specific data*//*note: each operator number 0 contains channel specific data*/ unsigned int FeedBack; /*feedback shift value for operators 0 in each channel*/ signed int FB; /*operator self feedback value used only by operators 0*/ signed int FB0; /*previous output value*/ unsigned int KC; /*operator KC (copied to all operators)*/ unsigned int KCindex; /*speedup*/ unsigned int PMS; /*channel PMS*/ unsigned int AMS; /*channel AMS*//*End of channel specific data*/ unsigned int AMSmask; /*LFO AMS enable mask*/ unsigned int state; /*Envelope state: 4-attack(AR) 3-decay(D1R) 2-sustain(D2R) 1-release(RR) 0-off*/ unsigned int delta_AR; /*volume delta for attack phase*/ unsigned int TL; /*Total attenuation Level*/ signed int volume; /*operator attenuation level*/ unsigned int delta_D1R; /*volume delta for decay phase*/ unsigned int D1L; /*EG switches to D2R, when envelope reaches this level*/ unsigned int delta_D2R; /*volume delta for sustain phase*/ unsigned int delta_RR; /*volume delta for release phase*/ unsigned int key; /*0=last key was KEY OFF, 1=last key was KEY ON*/ unsigned int KS; /*Key Scale */ unsigned int AR; /*Attack rate */ unsigned int D1R; /*Decay rate */ unsigned int D2R; /*Sustain rate */ unsigned int RR; /*Release rate */ unsigned int reserved0; /**/ signed int reserved1; /**/ signed int reserved2; /**/} OscilRec;typedef struct{ OscilRec Oscils[32]; /*there are 32 operators in YM2151*/ unsigned int PAN[16]; /*channels output masks (0xffffffff = enable)*/ unsigned int LFOphase; /*accumulated LFO phase */ unsigned int LFOfrq; /*LFO frequency */ unsigned int LFOwave; /*LFO waveform (0-saw, 1-square, 2-triangle, 3-random noise)*/ unsigned int PMD; /*LFO Phase Modulation Depth */ unsigned int AMD; /*LFO Amplitude Modulation Depth*/ unsigned int LFA; /*current AM from LFO*/ signed int LFP; /*current PM from LFO*/ unsigned int test; /*TEST register*/ unsigned int CT; /*output control pins (bit7 CT2, bit6 CT1)*/ unsigned int noise; /*noise register (bit 7 - noise enable, bits 4-0 - noise period*/ unsigned int noiseRNG; /*17 bit noise shift register*/ unsigned int noise_p; /*noise 'phase'*/ unsigned int noise_f; /*noise period*/ unsigned int CSMreq; /*CSM KEYON/KEYOFF sequence request*/ unsigned int IRQenable; /*IRQ enable for timer B (bit 3) and timer A (bit 2); bit 7 - CSM mode (keyon to all slots, everytime timer A overflows)*/ unsigned int status; /*chip status (BUSY, IRQ Flags)*/#ifdef USE_MAME_TIMERS void *TimATimer,*TimBTimer; /*ASG 980324 -- added for tracking timers*/ double TimerATime[1024]; /*Timer A times for MAME*/ double TimerBTime[256]; /*Timer B times for MAME*/#else int TimA,TimB; /*timer A,B enable (0-disabled)*/ signed int TimAVal,TimBVal; /*current value of timer*/ unsigned int TimerA[1024]; /*Timer A deltas*/ unsigned int TimerB[256]; /*Timer B deltas*/#endif unsigned int TimAIndex; /*Timer A index*/ unsigned int TimBIndex; /*Timer B index*/ unsigned int TimAOldIndex; /*Timer A previous index*/ unsigned int TimBOldIndex; /*Timer B previous index*/ /* * Frequency-deltas to get the closest frequency possible. * There're 11 octaves because of DT2 (max 950 cents over base frequency) * and LFO phase modulation (max 800 cents below AND over base frequency) * Summary: octave explanation * 0 note code - LFO PM * 1 note code * 2 note code * 3 note code * 4 note code * 5 note code * 6 note code * 7 note code * 8 note code * 9 note code + DT2 + LFO PM * 10 note code + DT2 + LFO PM */ unsigned int freq[11*768];/*11 octaves, 768 'cents' per octave*/ /* * Frequency deltas for DT1. These deltas alter operator frequency * after it has been taken from frequency-deltas table. */ signed int DT1freq[8*32]; /*8 DT1 levels, 32 KC values*/ unsigned int EG_tab [32+64+32]; /*Envelope Generator deltas (32 + 64 rates + 32 RKS)*/ unsigned int LFOfreq[256]; /*LFO frequency deltas*/ unsigned int noise_tab[32]; /*17bit Noise Generator periods*/ void (*irqhandler)(int irq); /*IRQ function handler*/ mem_write_handler porthandler; /*port write function handler*/ unsigned int clock; /*chip clock in Hz (passed from 2151intf.c)*/ unsigned int sampfreq; /*sampling frequency in Hz (passed from 2151intf.c)*/} YM2151;/*** Shifts below are subject to change when sampling frequency changes...*/#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */#define ENV_SH 16 /* 16.16 fixed point (envelope calculations) */#define LFO_SH 23 /* 9.23 fixed point (LFO calculations) */#define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */#define FREQ_MASK ((1<<FREQ_SH)-1)#define ENV_MASK ((1<<ENV_SH)-1)#define ENV_BITS 10#define ENV_LEN (1<<ENV_BITS)#define ENV_STEP (128.0/ENV_LEN)#define ENV_QUIET ((int)(0x68/(ENV_STEP)))#define MAX_ATT_INDEX ((ENV_LEN<<ENV_SH)-1) /*1023.ffff*/#define MIN_ATT_INDEX ( (1<<ENV_SH)-1) /* 0.ffff*/#define EG_ATT 4#define EG_DEC 3#define EG_SUS 2#define EG_REL 1#define EG_OFF 0#define SIN_BITS 10#define SIN_LEN (1<<SIN_BITS)#define SIN_MASK (SIN_LEN-1)#define TL_RES_LEN (256) /* 8 bits addressing (real chip) */#define LFO_BITS 9#define LFO_LEN (1<<LFO_BITS)#define LFO_MASK (LFO_LEN-1)#if (SAMPLE_BITS==16) #define FINAL_SH (0) #define MAXOUT (+32767) #define MINOUT (-32768)#else #define FINAL_SH (8) #define MAXOUT (+127) #define MINOUT (-128)#endif/* TL_TAB_LEN is calculated as: * 13 - sinus amplitude bits (Y axis) * 2 - sinus sign bit (Y axis) * ENV_LEN - sinus resolution (X axis)*/#define TL_TAB_LEN (13*2*TL_RES_LEN)static signed int TL_TAB[TL_TAB_LEN];/* sin waveform table in 'decibel' scale*/static unsigned int sin_tab[SIN_LEN];/* four AM/PM LFO waveforms (8 in total)*/static unsigned int lfo_tab[LFO_LEN*4*2];/* LFO amplitude modulation depth table (128 levels)*/static unsigned int lfo_md_tab[128];/* translate from D1L to volume index (16 D1L levels)*/static unsigned int D1L_tab[16];/* * DT2 defines offset in cents from base note * * This table defines offset in frequency-deltas table. * User's Manual page 22 * * Values below were calculated using formula: value = orig.val / 1.5625 * * DT2=0 DT2=1 DT2=2 DT2=3 * 0 600 781 950*/static unsigned int DT2_tab[4] = { 0, 384, 500, 608 };/* * DT1 defines offset in Hertz from base note * This table is converted while initialization... * Detune table in YM2151 User's Manual is wrong (checked against the real chip)*/static unsigned char DT1_tab[4*32] = { /* 4*32 DT1 values *//* DT1=0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* DT1=1 */ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,/* DT1=2 */ 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,/* DT1=3 */ 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22};static unsigned short phaseinc_rom[768]={1299,1300,1301,1302,1303,1304,1305,1306,1308,1309,1310,1311,1313,1314,1315,1316,1318,1319,1320,1321,1322,1323,1324,1325,1327,1328,1329,1330,1332,1333,1334,1335,1337,1338,1339,1340,1341,1342,1343,1344,1346,1347,1348,1349,1351,1352,1353,1354,1356,1357,1358,1359,1361,1362,1363,1364,1366,1367,1368,1369,1371,1372,1373,1374,1376,1377,1378,1379,1381,1382,1383,1384,1386,1387,1388,1389,1391,1392,1393,1394,1396,1397,1398,1399,1401,1402,1403,1404,1406,1407,1408,1409,1411,1412,1413,1414,1416,1417,1418,1419,1421,1422,1423,1424,1426,1427,1429,1430,1431,1432,1434,1435,1437,1438,1439,1440,1442,1443,1444,1445,1447,1448,1449,1450,1452,1453,1454,1455,1458,1459,1460,1461,1463,1464,1465,1466,1468,1469,1471,1472,1473,1474,1476,1477,1479,1480,1481,1482,1484,1485,1486,1487,1489,1490,1492,1493,1494,1495,1497,1498,1501,1502,1503,1504,1506,1507,1509,1510,1512,1513,1514,1515,1517,1518,1520,1521,1523,1524,1525,1526,1528,1529,1531,1532,1534,1535,1536,1537,1539,1540,1542,1543,1545,1546,1547,1548,1550,1551,1553,1554,1556,1557,1558,1559,1561,1562,1564,1565,1567,1568,1569,1570,1572,1573,1575,1576,1578,1579,1580,1581,1583,1584,1586,1587,1590,1591,1592,1593,1595,1596,1598,1599,1601,1602,1604,1605,1607,1608,1609,1610,1613,1614,1615,1616,1618,1619,1621,1622,1624,1625,1627,1628,1630,1631,1632,1633,1637,1638,1639,1640,1642,1643,1645,1646,1648,1649,1651,1652,1654,1655,1656,1657,1660,1661,1663,1664,1666,1667,1669,1670,1672,1673,1675,1676,1678,1679,1681,1682,1685,1686,1688,1689,1691,1692,1694,1695,1697,1698,1700,1701,1703,1704,1706,1707,1709,1710,1712,1713,1715,1716,1718,1719,1721,1722,1724,1725,1727,1728,1730,1731,1734,1735,1737,1738,1740,1741,1743,1744,1746,1748,1749,1751,1752,1754,1755,1757,1759,1760,1762,1763,1765,1766,1768,1769,1771,1773,1774,1776,1777,1779,1780,1782,1785,1786,1788,1789,1791,1793,1794,1796,1798,1799,1801,1802,1804,1806,1807,1809,1811,1812,1814,1815,1817,1819,1820,1822,1824,1825,1827,1828,1830,1832,1833,1835,1837,1838,1840,1841,1843,1845,1846,1848,1850,1851,1853,1854,1856,1858,1859,1861,1864,1865,1867,1868,1870,1872,1873,1875,1877,1879,1880,1882,1884,1885,1887,1888,1891,1892,1894,1895,1897,1899,1900,1902,1904,1906,1907,1909,1911,1912,1914,1915,1918,1919,1921,1923,1925,1926,1928,1930,1932,1933,1935,1937,1939,1940,1942,1944,1946,1947,1949,1951,1953,1954,1956,1958,1960,1961,1963,1965,1967,1968,1970,1972,1975,1976,1978,1980,1982,1983,1985,1987,1989,1990,1992,1994,1996,1997,1999,2001,2003,2004,2006,2008,2010,2011,2013,2015,2017,2019,2021,2022,2024,2026,2028,2029,2032,2033,2035,2037,2039,2041,2043,2044,2047,2048,2050,2052,2054,2056,2058,2059,2062,2063,2065,2067,2069,2071,2073,2074,2077,2078,2080,2082,2084,2086,2088,2089,2092,2093,2095,2097,2099,2101,2103,2104,2107,2108,2110,2112,2114,2116,2118,2119,2122,2123,2125,2127,2129,2131,2133,2134,2137,2139,2141,2142,2145,2146,2148,2150,2153,2154,2156,2158,2160,2162,2164,2165,2168,2170,2172,2173,2176,2177,2179,2181,2185,2186,2188,2190,2192,2194,2196,2197,2200,2202,2204,2205,2208,2209,2211,2213,2216,2218,2220,2222,2223,2226,2227,2230,2232,2234,2236,2238,2239,2242,2243,2246,2249,2251,2253,2255,2256,2259,2260,2263,2265,2267,2269,2271,2272,2275,2276,2279,2281,2283,2285,2287,2288,2291,2292,2295,2297,2299,2301,2303,2304,2307,2308,2311,2315,2317,2319,2321,2322,2325,2326,2329,2331,2333,2335,2337,2338,2341,2342,2345,2348,2350,2352,2354,2355,2358,2359,2362,2364,2366,2368,2370,2371,2374,2375,2378,2382,2384,2386,2388,2389,2392,2393,2396,2398,2400,2402,2404,2407,2410,2411,2414,2417,2419,2421,2423,2424,2427,2428,2431,2433,2435,2437,2439,2442,2445,2446,2449,2452,2454,2456,2458,2459,2462,2463,2466,2468,2470,2472,2474,2477,2480,2481,2484,2488,2490,2492,2494,2495,2498,2499,2502,2504,2506,2508,2510,2513,2516,2517,2520,2524,2526,2528,2530,2531,2534,2535,2538,2540,2542,2544,2546,2549,2552,2553,2556,2561,2563,2565,2567,2568,2571,2572,2575,2577,2579,2581,2583,2586,2589,2590,2593};static YM2151 * YMPSG = NULL; /* array of YM2151's */static unsigned int YMNumChips; /* total # of YM2151's emulated *//*these variables stay here because of speedup purposes only */static YM2151 * PSG;static signed int chanout[8];static signed int c1,m2,c2; /*Phase Modulation input for operators 2,3,4*//*save output as raw 16-bit sample*//*#define SAVE_SAMPLE*//*#define SAVE_SEPARATE_CHANNELS*/#if defined SAVE_SAMPLE || defined SAVE_SEPARATE_CHANNELSstatic FILE *sample[9];#endif/* own PI definition */#ifdef PI #undef PI#endif#define PI 3.14159265358979323846static void init_tables(void){ signed int i,x; signed int n; double o,m; for (x=0; x<TL_RES_LEN; x++) { m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0); m = floor(m); /* we never reach (1<<16) here due to the (x+1) */ /* result fits within 16 bits at maximum */ n = (int)m; /* 16 bits here */ n >>= 4; /* 12 bits here */ if (n&1) /* round to closest */ n = (n>>1)+1; else n = n>>1; /* 11 bits here (rounded) */ n <<= 2; /* 13 bits here (as in real chip) */ TL_TAB[ x*2 + 0 ] = n; TL_TAB[ x*2 + 1 ] = -TL_TAB[ x*2 + 0 ]; for (i=1; i<13; i++) { TL_TAB[ x*2+0 + i*2*TL_RES_LEN ] = TL_TAB[ x*2+0 ]>>i; TL_TAB[ x*2+1 + i*2*TL_RES_LEN ] = -TL_TAB[ x*2+0 + i*2*TL_RES_LEN ]; } #if 0 logerror("tl %04i", x); for (i=0; i<13; i++) logerror(", [%02i] %4x", i*2, TL_TAB[ x*2 /*+1*/ + i*2*TL_RES_LEN ]); logerror("\n"); } #endif } /*logerror("TL_TAB_LEN = %i (%i bytes)\n",TL_TAB_LEN, (int)sizeof(TL_TAB));*/ for (i=0; i<SIN_LEN; i++) { /* non-standard sinus */ m = sin( ((i*2)+1) * PI / SIN_LEN ); /* checked against the real chip */ /* we never reach zero here due to ((i*2)+1) */ if (m>0.0) o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */ else o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */ o = o / (ENV_STEP/4); n = (int)(2.0*o); if (n&1) /* round to closest */ n = (n>>1)+1; else n = n>>1; sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 ); /*logerror("sin [%4i]= %4i (TL_TAB value=%5i)\n", i, sin_tab[i],TL_TAB[sin_tab[i]]);*/ } /*logerror("ENV_QUIET= %08x\n",ENV_QUIET );*/ /* calculate LFO AM waveforms*/ for (x=0; x<4; x++) { for (i=0; i<LFO_LEN; i++) { switch (x) { case 0: /* saw (255 down to 0) */ m = 255 - (i/2); break; case 1: /* square (255,0) */ if (i<256) m = 255; else m = 0; break; case 2: /* triangle (255 down to 0, up to 255) */ if (i<256) m = 255 - i; else m = i - 256; break; case 3: /* random (range 0 to 255) */ m = ((int)rand()) & 255; break; } /* we reach m = zero here !!!*/ if (m>0.0) o = 8*log(255.0/m)/log(2); /* convert to 'decibels' */ else { if (m<0.0) o = 8*log(-255.0/m)/log(2); /* convert to 'decibels' */ else o = 8*log(255.0/0.01)/log(2); /* small number */ } o = o / (ENV_STEP/4); n = (int)(2.0*o); if (n&1) /* round to closest */ n = (n>>1)+1; else n = n>>1; lfo_tab[ x*LFO_LEN*2 + i*2 ] = n*2 + (m>=0.0? 0: 1 ); /*logerror("lfo am waveofs[%i] %04i = %i\n", x, i*2, lfo_tab[ x*LFO_LEN*2 + i*2 ] );*/ } } for (i=0; i<128; i++) { m = i*2; /*m=0,2,4,6,8,10,..,252,254*/ /* we reach m = zero here !!!*/ if (m>0.0) o = 8*log(8192.0/m)/log(2); /* convert to 'decibels' */ else o = 8*log(8192.0/0.01)/log(2); /* small number (m=0)*/ o = o / (ENV_STEP/4); n = (int)(2.0*o); if (n&1) /* round to closest */ n = (n>>1)+1; else n = n>>1; lfo_md_tab[ i ] = n*2; /*logerror("lfo_md_tab[%i](%i) = ofs %i shr by %i\n", i, i*2, (lfo_md_tab[i]>>1)&255, lfo_md_tab[i]>>9 );*/ } /* calculate LFO PM waveforms*/ for (x=0; x<4; x++) { for (i=0; i<LFO_LEN; i++) { switch (x) { case 0: /* saw (0 to 127, -128 to -1) */ if (i<256) m = (i/2); else m = (i/2)-256; break; case 1: /* square (127,-128) */ if (i<256) m = 127; else m = -128; break; case 2: /* triangle (0 to 127,127 to -128,-127 to 0) */ if (i<128) m = i; /*0 to 127*/ else { if (i<384) m = 255 - i; /*127 down to -128*/ else m = i - 511; /*-127 to 0*/ } break; case 3: /* random (range -128 to 127) */ m = ((int)rand()) & 255; m -=128; break; } /* we reach m = zero here !!!*/ if (m>0.0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -