From c594690aab5f62cd35ab91ba237b237e3813e3e7 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Sun, 12 Mar 2017 21:10:35 -0700 Subject: [PATCH] Update GME, including support for tag-specified fade times for formats which support it, which are SPC and SFM. --- Frameworks/GME/gme/Music_Emu.h | 5 +- Frameworks/GME/gme/Spc_Emu.h | 9 + Frameworks/GME/gme/Spc_Sfm.cpp | 14 +- Frameworks/GME/gme/Spc_Sfm.h | 11 +- Frameworks/GME/gme/gme.cpp | 3 +- Frameworks/GME/gme/gme.h | 8 +- Frameworks/GME/gme/higan/dsp/SPC_DSP.cpp | 794 ++++++++++++----------- Frameworks/GME/gme/higan/dsp/SPC_DSP.h | 11 +- Plugins/GME/GameDecoder.h | 1 + Plugins/GME/GameDecoder.m | 11 +- 10 files changed, 456 insertions(+), 411 deletions(-) diff --git a/Frameworks/GME/gme/Music_Emu.h b/Frameworks/GME/gme/Music_Emu.h index 905b7f6b3..bd1cadb1b 100644 --- a/Frameworks/GME/gme/Music_Emu.h +++ b/Frameworks/GME/gme/Music_Emu.h @@ -102,6 +102,9 @@ public: // Requests use of custom multichannel buffer. Only supported by "classic" emulators; // on others this has no effect. Should be called only once *before* set_sample_rate(). virtual void set_buffer( class Multi_Buffer* ) { } + + // Mutes native effects of a given sound engine. Currently only applies to the SPC emulator. + virtual void mute_effects( bool mute ) { } // Sound equalization (treble/bass) @@ -178,7 +181,7 @@ protected: public: gme_t(); ~gme_t(); - BLARGG_DEPRECATED( const char** voice_names() const { return CONST_CAST(const char**,voice_names_); } ) + const char** voice_names() const { return CONST_CAST(const char**,voice_names_); } protected: virtual void unload(); diff --git a/Frameworks/GME/gme/Spc_Emu.h b/Frameworks/GME/gme/Spc_Emu.h index ea815ed92..982dc6769 100644 --- a/Frameworks/GME/gme/Spc_Emu.h +++ b/Frameworks/GME/gme/Spc_Emu.h @@ -28,6 +28,13 @@ public: // Enables gaussian, cubic or sinc interpolation void interpolation_level( int level = 0 ) { smp.dsp.spc_dsp.interpolation_level( level ); } + // Enables an analog signal simulation filter + void enable_filter( bool enable = true ) { _enable_filter = enable; if (enable) filter.clear(); } + + // Enables native echo + void enable_echo( bool enable = true ) { smp.dsp.spc_dsp.enable_echo( enable ); } + virtual void mute_effects( bool mute ) { enable_echo(!mute); } + SuperFamicom::SMP const* get_smp() const; SuperFamicom::SMP * get_smp(); @@ -81,6 +88,8 @@ private: Spc_Emu_Resampler resampler; Spc_Filter filter; SuperFamicom::SMP smp; + + bool _enable_filter; byte const* trailer_() const; int trailer_size_() const; diff --git a/Frameworks/GME/gme/Spc_Sfm.cpp b/Frameworks/GME/gme/Spc_Sfm.cpp index 8912782f6..e39783627 100644 --- a/Frameworks/GME/gme/Spc_Sfm.cpp +++ b/Frameworks/GME/gme/Spc_Sfm.cpp @@ -27,6 +27,8 @@ Sfm_Emu::Sfm_Emu() set_gain( 1.4 ); set_max_initial_silence( 30 ); set_silence_lookahead( 30 ); // Some SFMs may have a lot of initialization code + enable_filter( false ); + enable_echo( true ); } Sfm_Emu::~Sfm_Emu() { } @@ -68,7 +70,7 @@ static void copy_info( track_info_t* out, const Bml_Parser& in ) if ( value ) out->fade_length = strtoul( value, &end, 10 ); else - out->fade_length = 0; + out->fade_length = -1; } blargg_err_t Sfm_Emu::track_info_( track_info_t* out, int ) const @@ -297,9 +299,9 @@ blargg_err_t Sfm_Emu::start_track_( int track ) value = metadata.enumValue("smp:ports"); if (value) { - for (auto &n : smp.sfm_last) + for (int i = 0; i < _countof(smp.sfm_last); i++) { - n = strtol(value, &end, 10); + smp.sfm_last[i] = strtol(value, &end, 10); if (*end == ',') value = end + 1; else @@ -482,10 +484,10 @@ void Sfm_Emu::create_updated_metadata( Bml_Parser &out ) const oss.str(""); oss.clear(); first = true; - for (auto n : smp.sfm_last) + for (int i = 0; i < _countof(smp.sfm_last); i++) { if (!first) oss << ","; - oss << (unsigned long)n; + oss << (unsigned long)smp.sfm_last[i]; first = false; } out.setValue("smp:ports", oss.str().c_str()); @@ -621,7 +623,7 @@ blargg_err_t Sfm_Emu::save_( gme_writer_t writer, void* your_data ) const blargg_err_t Sfm_Emu::play_and_filter( int count, sample_t out [] ) { smp.render( out, count ); - filter.run( out, count ); + if ( _enable_filter ) filter.run( out, count ); return blargg_ok; } diff --git a/Frameworks/GME/gme/Spc_Sfm.h b/Frameworks/GME/gme/Spc_Sfm.h index 671ea28de..ee2b525b5 100644 --- a/Frameworks/GME/gme/Spc_Sfm.h +++ b/Frameworks/GME/gme/Spc_Sfm.h @@ -36,7 +36,14 @@ public: // Enables gaussian, cubic or sinc interpolation void interpolation_level( int level = 0 ) { smp.dsp.spc_dsp.interpolation_level( level ); } - SuperFamicom::SMP const* get_smp() const; + // Enables an analog signal simulation filter + void enable_filter( bool enable = true ) { _enable_filter = enable; if (enable) filter.clear(); } + + // Enables native echo + void enable_echo(bool enable = true) { smp.dsp.spc_dsp.enable_echo(enable); } + virtual void mute_effects(bool mute) { enable_echo(!mute); } + + SuperFamicom::SMP const* get_smp() const; SuperFamicom::SMP * get_smp(); blargg_err_t hash_( Hash_Function& ) const; @@ -65,6 +72,8 @@ private: Spc_Filter filter; SuperFamicom::SMP smp; + bool _enable_filter; + Bml_Parser metadata; void create_updated_metadata(Bml_Parser &out) const; diff --git a/Frameworks/GME/gme/gme.cpp b/Frameworks/GME/gme/gme.cpp index 2d2bf78c8..6d3df3f66 100644 --- a/Frameworks/GME/gme/gme.cpp +++ b/Frameworks/GME/gme/gme.cpp @@ -257,8 +257,8 @@ gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, int track ) COPY( length ); COPY( intro_length ); COPY( loop_length ); + COPY( fade_length ); - info->i4 = -1; info->i5 = -1; info->i6 = -1; info->i7 = -1; @@ -360,6 +360,7 @@ void gme_set_equalizer ( Music_Emu* gme, gme_equalizer_t const* eq ) { gme void gme_equalizer ( Music_Emu const* gme, gme_equalizer_t* o ) { *o = gme->equalizer(); } const char* gme_voice_name ( Music_Emu const* gme, int i ) { return gme->voice_name( i ); } gme_err_t gme_save ( Music_Emu const* gme, gme_writer_t writer, void* your_data ) { return gme->save( writer, your_data ); } +void gme_mute_effects ( Music_Emu* gme, gme_bool disable ) { gme->mute_effects(disable); } void gme_effects( Music_Emu const* gme, gme_effects_t* out ) { diff --git a/Frameworks/GME/gme/gme.h b/Frameworks/GME/gme/gme.h index 275bb3252..cbf8ea9c0 100644 --- a/Frameworks/GME/gme/gme.h +++ b/Frameworks/GME/gme/gme.h @@ -96,8 +96,11 @@ struct gme_info_t /* Length if available, otherwise intro_length+loop_length*2 if available, otherwise a default of 150000 (2.5 minutes). */ int play_length; + + /* Fade duration, in milliseconds, if the file specifies it */ + int fade_length; - int i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15; /* reserved */ + int i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15; /* reserved */ /* empty string ("") if not available */ const char* system; @@ -135,6 +138,9 @@ void gme_mute_voice( gme_t*, int index, gme_bool mute ); voices, 0 unmutes them all, 0x01 mutes just the first voice, etc. */ void gme_mute_voices( gme_t*, int muting_mask ); +/* Disables native effects, and possibly others. */ +void gme_mute_effects( gme_t*, gme_bool mute ); + /* Frequency equalizer parameters (see gme.txt) */ typedef struct gme_equalizer_t { diff --git a/Frameworks/GME/gme/higan/dsp/SPC_DSP.cpp b/Frameworks/GME/gme/higan/dsp/SPC_DSP.cpp index d962be48c..1742ed3f5 100755 --- a/Frameworks/GME/gme/higan/dsp/SPC_DSP.cpp +++ b/Frameworks/GME/gme/higan/dsp/SPC_DSP.cpp @@ -70,17 +70,16 @@ static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] = #define WRITE_SAMPLES( l, r, out ) \ {\ + if ( out >= m.out_end )\ + {\ + int count = sample_count();\ + m.out_begin = (SPC_DSP::sample_t *) realloc( m.out_begin, (count ? count * 2 : 8192) * sizeof(SPC_DSP::sample_t) );\ + out = m.out_begin + count;\ + m.out_end = m.out_begin + count * 2;\ + }\ out [0] = l;\ out [1] = r;\ out += 2;\ - if ( out >= m.out_end )\ - {\ - check( out == m.out_end );\ - check( m.out_end != &m.extra [extra_size] || \ - (m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\ - out = m.extra;\ - m.out_end = &m.extra [extra_size];\ - }\ }\ void SPC_DSP::set_output( sample_t* out, int size ) @@ -88,8 +87,7 @@ void SPC_DSP::set_output( sample_t* out, int size ) require( (size & 1) == 0 ); // must be even if ( !out ) { - out = m.extra; - size = extra_size; + size = 0; } m.out_begin = out; m.out = out; @@ -137,302 +135,302 @@ static short const gauss [512] = 1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305, }; -static short const cubic [514] = -{ - 0, -4, -8, -12, -16, -20, -23, -27, -30, -34, -37, -41, -44, -47, -50, -53, - -56, -59, -62, -65, -68, -71, -73, -76, -78, -81, -84, -87, -89, -91, -93, -95, - -98,-100,-102,-104,-106,-109,-110,-112,-113,-116,-117,-119,-121,-122,-123,-125, --126,-128,-129,-131,-132,-134,-134,-136,-136,-138,-138,-140,-141,-141,-142,-143, --144,-144,-145,-146,-147,-148,-147,-148,-148,-149,-149,-150,-150,-150,-150,-151, --151,-151,-151,-151,-152,-152,-151,-152,-151,-152,-151,-151,-151,-151,-150,-150, --150,-149,-149,-149,-149,-148,-147,-147,-146,-146,-145,-145,-144,-144,-143,-142, --141,-141,-140,-139,-139,-138,-137,-136,-135,-135,-133,-133,-132,-131,-130,-129, --128,-127,-126,-125,-124,-123,-121,-121,-119,-118,-117,-116,-115,-114,-112,-111, --110,-109,-107,-106,-105,-104,-102,-102,-100, -99, -97, -97, -95, -94, -92, -91, - -90, -88, -87, -86, -85, -84, -82, -81, -79, -78, -76, -76, -74, -73, -71, -70, - -68, -67, -66, -65, -63, -62, -60, -60, -58, -57, -55, -55, -53, -52, -50, -49, - -48, -46, -45, -44, -43, -42, -40, -39, -38, -37, -36, -35, -34, -32, -31, -30, - -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -19, -17, -16, -15, -14, - -14, -13, -12, -11, -11, -10, -9, -9, -8, -8, -7, -7, -6, -5, -4, -4, - -3, -3, -3, -2, -2, -2, -1, -1, 0, -1, 0, -1, 0, 0, 0, 0, - 0, -2048,2048,2048,2048,2047,2047,2046,2045,2043,2042,2041,2039,2037,2035,2033,2031, -2028,2026,2024,2021,2018,2015,2012,2009,2005,2002,1999,1995,1991,1987,1982,1978, -1974,1969,1965,1960,1955,1951,1946,1940,1934,1929,1924,1918,1912,1906,1900,1895, -1888,1882,1875,1869,1862,1856,1849,1842,1835,1828,1821,1814,1806,1799,1791,1783, -1776,1768,1760,1753,1744,1737,1728,1720,1711,1703,1695,1686,1677,1668,1659,1651, -1641,1633,1623,1614,1605,1596,1587,1577,1567,1559,1549,1539,1529,1520,1510,1499, -1490,1480,1470,1460,1450,1440,1430,1420,1408,1398,1389,1378,1367,1357,1346,1336, -1325,1315,1304,1293,1282,1272,1261,1250,1239,1229,1218,1207,1196,1185,1174,1163, -1152,1141,1130,1119,1108,1097,1086,1075,1063,1052,1042,1030,1019,1008, 997, 986, - 974, 964, 952, 941, 930, 919, 908, 897, 886, 875, 864, 853, 842, 831, 820, 809, - 798, 787, 776, 765, 754, 744, 733, 722, 711, 700, 690, 679, 668, 658, 647, 637, - 626, 616, 605, 595, 584, 574, 564, 554, 543, 534, 524, 514, 503, 494, 483, 473, - 464, 454, 444, 435, 425, 416, 407, 397, 387, 378, 370, 360, 351, 342, 333, 325, - 315, 307, 298, 290, 281, 273, 265, 256, 248, 241, 233, 225, 216, 209, 201, 193, - 186, 178, 171, 164, 157, 150, 143, 137, 129, 123, 117, 110, 103, 97, 91, 85, - 79, 74, 68, 62, 56, 51, 46, 41, 35, 31, 27, 22, 17, 13, 8, 4, - 0 -}; - -static short const sinc [2048] = -{ - 39, -315, 666, 15642, 666, -315, 39, -38, - 38, -302, 613, 15642, 718, -328, 41, -38, - 36, -288, 561, 15641, 772, -342, 42, -38, - 35, -275, 510, 15639, 826, -355, 44, -38, - 33, -263, 459, 15636, 880, -369, 46, -38, - 32, -250, 408, 15632, 935, -383, 47, -38, - 31, -237, 358, 15628, 990, -396, 49, -38, - 29, -224, 309, 15622, 1046, -410, 51, -38, - 28, -212, 259, 15616, 1103, -425, 53, -38, - 27, -200, 211, 15609, 1159, -439, 54, -38, - 25, -188, 163, 15601, 1216, -453, 56, -38, - 24, -175, 115, 15593, 1274, -467, 58, -38, - 23, -164, 68, 15583, 1332, -482, 60, -38, - 22, -152, 22, 15573, 1391, -496, 62, -37, - 21, -140, -24, 15562, 1450, -511, 64, -37, - 19, -128, -70, 15550, 1509, -526, 66, -37, - 18, -117, -115, 15538, 1569, -540, 68, -37, - 17, -106, -159, 15524, 1629, -555, 70, -37, - 16, -94, -203, 15510, 1690, -570, 72, -36, - 15, -83, -247, 15495, 1751, -585, 74, -36, - 14, -72, -289, 15479, 1813, -600, 76, -36, - 13, -62, -332, 15462, 1875, -616, 79, -36, - 12, -51, -374, 15445, 1937, -631, 81, -35, - 11, -40, -415, 15426, 2000, -646, 83, -35, - 11, -30, -456, 15407, 2063, -662, 85, -35, - 10, -20, -496, 15387, 2127, -677, 88, -34, - 9, -9, -536, 15366, 2191, -693, 90, -34, - 8, 1, -576, 15345, 2256, -708, 92, -34, - 7, 10, -614, 15323, 2321, -724, 95, -33, - 7, 20, -653, 15300, 2386, -740, 97, -33, - 6, 30, -690, 15276, 2451, -755, 99, -33, - 5, 39, -728, 15251, 2517, -771, 102, -32, - 5, 49, -764, 15226, 2584, -787, 104, -32, - 4, 58, -801, 15200, 2651, -803, 107, -32, - 3, 67, -836, 15173, 2718, -819, 109, -31, - 3, 76, -871, 15145, 2785, -835, 112, -31, - 2, 85, -906, 15117, 2853, -851, 115, -30, - 2, 93, -940, 15087, 2921, -867, 117, -30, - 1, 102, -974, 15057, 2990, -883, 120, -29, - 1, 110, -1007, 15027, 3059, -899, 122, -29, - 0, 118, -1039, 14995, 3128, -915, 125, -29, - 0, 127, -1071, 14963, 3198, -931, 128, -28, - -1, 135, -1103, 14930, 3268, -948, 131, -28, - -1, 142, -1134, 14896, 3338, -964, 133, -27, - -1, 150, -1164, 14862, 3409, -980, 136, -27, - -2, 158, -1194, 14827, 3480, -996, 139, -26, - -2, 165, -1224, 14791, 3551, -1013, 142, -26, - -3, 172, -1253, 14754, 3622, -1029, 144, -25, - -3, 179, -1281, 14717, 3694, -1045, 147, -25, - -3, 187, -1309, 14679, 3766, -1062, 150, -24, - -3, 193, -1337, 14640, 3839, -1078, 153, -24, - -4, 200, -1363, 14601, 3912, -1094, 156, -23, - -4, 207, -1390, 14561, 3985, -1110, 159, -23, - -4, 213, -1416, 14520, 4058, -1127, 162, -22, - -4, 220, -1441, 14479, 4131, -1143, 165, -22, - -4, 226, -1466, 14437, 4205, -1159, 168, -22, - -5, 232, -1490, 14394, 4279, -1175, 171, -21, - -5, 238, -1514, 14350, 4354, -1192, 174, -21, - -5, 244, -1537, 14306, 4428, -1208, 177, -20, - -5, 249, -1560, 14261, 4503, -1224, 180, -20, - -5, 255, -1583, 14216, 4578, -1240, 183, -19, - -5, 260, -1604, 14169, 4653, -1256, 186, -19, - -5, 265, -1626, 14123, 4729, -1272, 189, -18, - -5, 271, -1647, 14075, 4805, -1288, 192, -18, - -5, 276, -1667, 14027, 4881, -1304, 195, -17, - -6, 280, -1687, 13978, 4957, -1320, 198, -17, - -6, 285, -1706, 13929, 5033, -1336, 201, -16, - -6, 290, -1725, 13879, 5110, -1352, 204, -16, - -6, 294, -1744, 13829, 5186, -1368, 207, -15, - -6, 299, -1762, 13777, 5263, -1383, 210, -15, - -6, 303, -1779, 13726, 5340, -1399, 213, -14, - -6, 307, -1796, 13673, 5418, -1414, 216, -14, - -6, 311, -1813, 13620, 5495, -1430, 219, -13, - -5, 315, -1829, 13567, 5573, -1445, 222, -13, - -5, 319, -1844, 13512, 5651, -1461, 225, -13, - -5, 322, -1859, 13458, 5728, -1476, 229, -12, - -5, 326, -1874, 13402, 5806, -1491, 232, -12, - -5, 329, -1888, 13347, 5885, -1506, 235, -11, - -5, 332, -1902, 13290, 5963, -1521, 238, -11, - -5, 335, -1915, 13233, 6041, -1536, 241, -10, - -5, 338, -1928, 13176, 6120, -1551, 244, -10, - -5, 341, -1940, 13118, 6199, -1566, 247, -10, - -5, 344, -1952, 13059, 6277, -1580, 250, -9, - -5, 347, -1964, 13000, 6356, -1595, 253, -9, - -5, 349, -1975, 12940, 6435, -1609, 256, -8, - -4, 352, -1986, 12880, 6514, -1623, 259, -8, - -4, 354, -1996, 12819, 6594, -1637, 262, -8, - -4, 356, -2005, 12758, 6673, -1651, 265, -7, - -4, 358, -2015, 12696, 6752, -1665, 268, -7, - -4, 360, -2024, 12634, 6831, -1679, 271, -7, - -4, 362, -2032, 12572, 6911, -1693, 274, -6, - -4, 364, -2040, 12509, 6990, -1706, 277, -6, - -4, 366, -2048, 12445, 7070, -1719, 280, -6, - -3, 367, -2055, 12381, 7149, -1732, 283, -5, - -3, 369, -2062, 12316, 7229, -1745, 286, -5, - -3, 370, -2068, 12251, 7308, -1758, 289, -5, - -3, 371, -2074, 12186, 7388, -1771, 291, -4, - -3, 372, -2079, 12120, 7467, -1784, 294, -4, - -3, 373, -2084, 12054, 7547, -1796, 297, -4, - -3, 374, -2089, 11987, 7626, -1808, 300, -4, - -2, 375, -2094, 11920, 7706, -1820, 303, -3, - -2, 376, -2098, 11852, 7785, -1832, 305, -3, - -2, 376, -2101, 11785, 7865, -1844, 308, -3, - -2, 377, -2104, 11716, 7944, -1855, 311, -3, - -2, 377, -2107, 11647, 8024, -1866, 313, -2, - -2, 378, -2110, 11578, 8103, -1877, 316, -2, - -2, 378, -2112, 11509, 8182, -1888, 318, -2, - -1, 378, -2113, 11439, 8262, -1899, 321, -2, - -1, 378, -2115, 11369, 8341, -1909, 323, -2, - -1, 378, -2116, 11298, 8420, -1920, 326, -2, - -1, 378, -2116, 11227, 8499, -1930, 328, -1, - -1, 378, -2116, 11156, 8578, -1940, 331, -1, - -1, 378, -2116, 11084, 8656, -1949, 333, -1, - -1, 377, -2116, 11012, 8735, -1959, 335, -1, - -1, 377, -2115, 10940, 8814, -1968, 337, -1, - -1, 377, -2114, 10867, 8892, -1977, 340, -1, - -1, 376, -2112, 10795, 8971, -1985, 342, -1, - 0, 375, -2111, 10721, 9049, -1994, 344, -1, - 0, 375, -2108, 10648, 9127, -2002, 346, 0, - 0, 374, -2106, 10574, 9205, -2010, 348, 0, - 0, 373, -2103, 10500, 9283, -2018, 350, 0, - 0, 372, -2100, 10426, 9360, -2025, 352, 0, - 0, 371, -2097, 10351, 9438, -2032, 354, 0, - 0, 370, -2093, 10276, 9515, -2039, 355, 0, - 0, 369, -2089, 10201, 9592, -2046, 357, 0, - 0, 367, -2084, 10126, 9669, -2052, 359, 0, - 0, 366, -2080, 10050, 9745, -2058, 360, 0, - 0, 365, -2075, 9974, 9822, -2064, 362, 0, - 0, 363, -2070, 9898, 9898, -2070, 363, 0, - 0, 362, -2064, 9822, 9974, -2075, 365, 0, - 0, 360, -2058, 9745, 10050, -2080, 366, 0, - 0, 359, -2052, 9669, 10126, -2084, 367, 0, - 0, 357, -2046, 9592, 10201, -2089, 369, 0, - 0, 355, -2039, 9515, 10276, -2093, 370, 0, - 0, 354, -2032, 9438, 10351, -2097, 371, 0, - 0, 352, -2025, 9360, 10426, -2100, 372, 0, - 0, 350, -2018, 9283, 10500, -2103, 373, 0, - 0, 348, -2010, 9205, 10574, -2106, 374, 0, - 0, 346, -2002, 9127, 10648, -2108, 375, 0, - -1, 344, -1994, 9049, 10721, -2111, 375, 0, - -1, 342, -1985, 8971, 10795, -2112, 376, -1, - -1, 340, -1977, 8892, 10867, -2114, 377, -1, - -1, 337, -1968, 8814, 10940, -2115, 377, -1, - -1, 335, -1959, 8735, 11012, -2116, 377, -1, - -1, 333, -1949, 8656, 11084, -2116, 378, -1, - -1, 331, -1940, 8578, 11156, -2116, 378, -1, - -1, 328, -1930, 8499, 11227, -2116, 378, -1, - -2, 326, -1920, 8420, 11298, -2116, 378, -1, - -2, 323, -1909, 8341, 11369, -2115, 378, -1, - -2, 321, -1899, 8262, 11439, -2113, 378, -1, - -2, 318, -1888, 8182, 11509, -2112, 378, -2, - -2, 316, -1877, 8103, 11578, -2110, 378, -2, - -2, 313, -1866, 8024, 11647, -2107, 377, -2, - -3, 311, -1855, 7944, 11716, -2104, 377, -2, - -3, 308, -1844, 7865, 11785, -2101, 376, -2, - -3, 305, -1832, 7785, 11852, -2098, 376, -2, - -3, 303, -1820, 7706, 11920, -2094, 375, -2, - -4, 300, -1808, 7626, 11987, -2089, 374, -3, - -4, 297, -1796, 7547, 12054, -2084, 373, -3, - -4, 294, -1784, 7467, 12120, -2079, 372, -3, - -4, 291, -1771, 7388, 12186, -2074, 371, -3, - -5, 289, -1758, 7308, 12251, -2068, 370, -3, - -5, 286, -1745, 7229, 12316, -2062, 369, -3, - -5, 283, -1732, 7149, 12381, -2055, 367, -3, - -6, 280, -1719, 7070, 12445, -2048, 366, -4, - -6, 277, -1706, 6990, 12509, -2040, 364, -4, - -6, 274, -1693, 6911, 12572, -2032, 362, -4, - -7, 271, -1679, 6831, 12634, -2024, 360, -4, - -7, 268, -1665, 6752, 12696, -2015, 358, -4, - -7, 265, -1651, 6673, 12758, -2005, 356, -4, - -8, 262, -1637, 6594, 12819, -1996, 354, -4, - -8, 259, -1623, 6514, 12880, -1986, 352, -4, - -8, 256, -1609, 6435, 12940, -1975, 349, -5, - -9, 253, -1595, 6356, 13000, -1964, 347, -5, - -9, 250, -1580, 6277, 13059, -1952, 344, -5, - -10, 247, -1566, 6199, 13118, -1940, 341, -5, - -10, 244, -1551, 6120, 13176, -1928, 338, -5, - -10, 241, -1536, 6041, 13233, -1915, 335, -5, - -11, 238, -1521, 5963, 13290, -1902, 332, -5, - -11, 235, -1506, 5885, 13347, -1888, 329, -5, - -12, 232, -1491, 5806, 13402, -1874, 326, -5, - -12, 229, -1476, 5728, 13458, -1859, 322, -5, - -13, 225, -1461, 5651, 13512, -1844, 319, -5, - -13, 222, -1445, 5573, 13567, -1829, 315, -5, - -13, 219, -1430, 5495, 13620, -1813, 311, -6, - -14, 216, -1414, 5418, 13673, -1796, 307, -6, - -14, 213, -1399, 5340, 13726, -1779, 303, -6, - -15, 210, -1383, 5263, 13777, -1762, 299, -6, - -15, 207, -1368, 5186, 13829, -1744, 294, -6, - -16, 204, -1352, 5110, 13879, -1725, 290, -6, - -16, 201, -1336, 5033, 13929, -1706, 285, -6, - -17, 198, -1320, 4957, 13978, -1687, 280, -6, - -17, 195, -1304, 4881, 14027, -1667, 276, -5, - -18, 192, -1288, 4805, 14075, -1647, 271, -5, - -18, 189, -1272, 4729, 14123, -1626, 265, -5, - -19, 186, -1256, 4653, 14169, -1604, 260, -5, - -19, 183, -1240, 4578, 14216, -1583, 255, -5, - -20, 180, -1224, 4503, 14261, -1560, 249, -5, - -20, 177, -1208, 4428, 14306, -1537, 244, -5, - -21, 174, -1192, 4354, 14350, -1514, 238, -5, - -21, 171, -1175, 4279, 14394, -1490, 232, -5, - -22, 168, -1159, 4205, 14437, -1466, 226, -4, - -22, 165, -1143, 4131, 14479, -1441, 220, -4, - -22, 162, -1127, 4058, 14520, -1416, 213, -4, - -23, 159, -1110, 3985, 14561, -1390, 207, -4, - -23, 156, -1094, 3912, 14601, -1363, 200, -4, - -24, 153, -1078, 3839, 14640, -1337, 193, -3, - -24, 150, -1062, 3766, 14679, -1309, 187, -3, - -25, 147, -1045, 3694, 14717, -1281, 179, -3, - -25, 144, -1029, 3622, 14754, -1253, 172, -3, - -26, 142, -1013, 3551, 14791, -1224, 165, -2, - -26, 139, -996, 3480, 14827, -1194, 158, -2, - -27, 136, -980, 3409, 14862, -1164, 150, -1, - -27, 133, -964, 3338, 14896, -1134, 142, -1, - -28, 131, -948, 3268, 14930, -1103, 135, -1, - -28, 128, -931, 3198, 14963, -1071, 127, 0, - -29, 125, -915, 3128, 14995, -1039, 118, 0, - -29, 122, -899, 3059, 15027, -1007, 110, 1, - -29, 120, -883, 2990, 15057, -974, 102, 1, - -30, 117, -867, 2921, 15087, -940, 93, 2, - -30, 115, -851, 2853, 15117, -906, 85, 2, - -31, 112, -835, 2785, 15145, -871, 76, 3, - -31, 109, -819, 2718, 15173, -836, 67, 3, - -32, 107, -803, 2651, 15200, -801, 58, 4, - -32, 104, -787, 2584, 15226, -764, 49, 5, - -32, 102, -771, 2517, 15251, -728, 39, 5, - -33, 99, -755, 2451, 15276, -690, 30, 6, - -33, 97, -740, 2386, 15300, -653, 20, 7, - -33, 95, -724, 2321, 15323, -614, 10, 7, - -34, 92, -708, 2256, 15345, -576, 1, 8, - -34, 90, -693, 2191, 15366, -536, -9, 9, - -34, 88, -677, 2127, 15387, -496, -20, 10, - -35, 85, -662, 2063, 15407, -456, -30, 11, - -35, 83, -646, 2000, 15426, -415, -40, 11, - -35, 81, -631, 1937, 15445, -374, -51, 12, - -36, 79, -616, 1875, 15462, -332, -62, 13, - -36, 76, -600, 1813, 15479, -289, -72, 14, - -36, 74, -585, 1751, 15495, -247, -83, 15, - -36, 72, -570, 1690, 15510, -203, -94, 16, - -37, 70, -555, 1629, 15524, -159, -106, 17, - -37, 68, -540, 1569, 15538, -115, -117, 18, - -37, 66, -526, 1509, 15550, -70, -128, 19, - -37, 64, -511, 1450, 15562, -24, -140, 21, - -37, 62, -496, 1391, 15573, 22, -152, 22, - -38, 60, -482, 1332, 15583, 68, -164, 23, - -38, 58, -467, 1274, 15593, 115, -175, 24, - -38, 56, -453, 1216, 15601, 163, -188, 25, - -38, 54, -439, 1159, 15609, 211, -200, 27, - -38, 53, -425, 1103, 15616, 259, -212, 28, - -38, 51, -410, 1046, 15622, 309, -224, 29, - -38, 49, -396, 990, 15628, 358, -237, 31, - -38, 47, -383, 935, 15632, 408, -250, 32, - -38, 46, -369, 880, 15636, 459, -263, 33, - -38, 44, -355, 826, 15639, 510, -275, 35, - -38, 42, -342, 772, 15641, 561, -288, 36, - -38, 41, -328, 718, 15642, 613, -302, 38, +static short const cubic [514] = +{ + 0, -4, -8, -12, -16, -20, -23, -27, -30, -34, -37, -41, -44, -47, -50, -53, + -56, -59, -62, -65, -68, -71, -73, -76, -78, -81, -84, -87, -89, -91, -93, -95, + -98,-100,-102,-104,-106,-109,-110,-112,-113,-116,-117,-119,-121,-122,-123,-125, +-126,-128,-129,-131,-132,-134,-134,-136,-136,-138,-138,-140,-141,-141,-142,-143, +-144,-144,-145,-146,-147,-148,-147,-148,-148,-149,-149,-150,-150,-150,-150,-151, +-151,-151,-151,-151,-152,-152,-151,-152,-151,-152,-151,-151,-151,-151,-150,-150, +-150,-149,-149,-149,-149,-148,-147,-147,-146,-146,-145,-145,-144,-144,-143,-142, +-141,-141,-140,-139,-139,-138,-137,-136,-135,-135,-133,-133,-132,-131,-130,-129, +-128,-127,-126,-125,-124,-123,-121,-121,-119,-118,-117,-116,-115,-114,-112,-111, +-110,-109,-107,-106,-105,-104,-102,-102,-100, -99, -97, -97, -95, -94, -92, -91, + -90, -88, -87, -86, -85, -84, -82, -81, -79, -78, -76, -76, -74, -73, -71, -70, + -68, -67, -66, -65, -63, -62, -60, -60, -58, -57, -55, -55, -53, -52, -50, -49, + -48, -46, -45, -44, -43, -42, -40, -39, -38, -37, -36, -35, -34, -32, -31, -30, + -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -19, -17, -16, -15, -14, + -14, -13, -12, -11, -11, -10, -9, -9, -8, -8, -7, -7, -6, -5, -4, -4, + -3, -3, -3, -2, -2, -2, -1, -1, 0, -1, 0, -1, 0, 0, 0, 0, + 0, +2048,2048,2048,2048,2047,2047,2046,2045,2043,2042,2041,2039,2037,2035,2033,2031, +2028,2026,2024,2021,2018,2015,2012,2009,2005,2002,1999,1995,1991,1987,1982,1978, +1974,1969,1965,1960,1955,1951,1946,1940,1934,1929,1924,1918,1912,1906,1900,1895, +1888,1882,1875,1869,1862,1856,1849,1842,1835,1828,1821,1814,1806,1799,1791,1783, +1776,1768,1760,1753,1744,1737,1728,1720,1711,1703,1695,1686,1677,1668,1659,1651, +1641,1633,1623,1614,1605,1596,1587,1577,1567,1559,1549,1539,1529,1520,1510,1499, +1490,1480,1470,1460,1450,1440,1430,1420,1408,1398,1389,1378,1367,1357,1346,1336, +1325,1315,1304,1293,1282,1272,1261,1250,1239,1229,1218,1207,1196,1185,1174,1163, +1152,1141,1130,1119,1108,1097,1086,1075,1063,1052,1042,1030,1019,1008, 997, 986, + 974, 964, 952, 941, 930, 919, 908, 897, 886, 875, 864, 853, 842, 831, 820, 809, + 798, 787, 776, 765, 754, 744, 733, 722, 711, 700, 690, 679, 668, 658, 647, 637, + 626, 616, 605, 595, 584, 574, 564, 554, 543, 534, 524, 514, 503, 494, 483, 473, + 464, 454, 444, 435, 425, 416, 407, 397, 387, 378, 370, 360, 351, 342, 333, 325, + 315, 307, 298, 290, 281, 273, 265, 256, 248, 241, 233, 225, 216, 209, 201, 193, + 186, 178, 171, 164, 157, 150, 143, 137, 129, 123, 117, 110, 103, 97, 91, 85, + 79, 74, 68, 62, 56, 51, 46, 41, 35, 31, 27, 22, 17, 13, 8, 4, + 0 +}; + +static short const sinc [2048] = +{ + 39, -315, 666, 15642, 666, -315, 39, -38, + 38, -302, 613, 15642, 718, -328, 41, -38, + 36, -288, 561, 15641, 772, -342, 42, -38, + 35, -275, 510, 15639, 826, -355, 44, -38, + 33, -263, 459, 15636, 880, -369, 46, -38, + 32, -250, 408, 15632, 935, -383, 47, -38, + 31, -237, 358, 15628, 990, -396, 49, -38, + 29, -224, 309, 15622, 1046, -410, 51, -38, + 28, -212, 259, 15616, 1103, -425, 53, -38, + 27, -200, 211, 15609, 1159, -439, 54, -38, + 25, -188, 163, 15601, 1216, -453, 56, -38, + 24, -175, 115, 15593, 1274, -467, 58, -38, + 23, -164, 68, 15583, 1332, -482, 60, -38, + 22, -152, 22, 15573, 1391, -496, 62, -37, + 21, -140, -24, 15562, 1450, -511, 64, -37, + 19, -128, -70, 15550, 1509, -526, 66, -37, + 18, -117, -115, 15538, 1569, -540, 68, -37, + 17, -106, -159, 15524, 1629, -555, 70, -37, + 16, -94, -203, 15510, 1690, -570, 72, -36, + 15, -83, -247, 15495, 1751, -585, 74, -36, + 14, -72, -289, 15479, 1813, -600, 76, -36, + 13, -62, -332, 15462, 1875, -616, 79, -36, + 12, -51, -374, 15445, 1937, -631, 81, -35, + 11, -40, -415, 15426, 2000, -646, 83, -35, + 11, -30, -456, 15407, 2063, -662, 85, -35, + 10, -20, -496, 15387, 2127, -677, 88, -34, + 9, -9, -536, 15366, 2191, -693, 90, -34, + 8, 1, -576, 15345, 2256, -708, 92, -34, + 7, 10, -614, 15323, 2321, -724, 95, -33, + 7, 20, -653, 15300, 2386, -740, 97, -33, + 6, 30, -690, 15276, 2451, -755, 99, -33, + 5, 39, -728, 15251, 2517, -771, 102, -32, + 5, 49, -764, 15226, 2584, -787, 104, -32, + 4, 58, -801, 15200, 2651, -803, 107, -32, + 3, 67, -836, 15173, 2718, -819, 109, -31, + 3, 76, -871, 15145, 2785, -835, 112, -31, + 2, 85, -906, 15117, 2853, -851, 115, -30, + 2, 93, -940, 15087, 2921, -867, 117, -30, + 1, 102, -974, 15057, 2990, -883, 120, -29, + 1, 110, -1007, 15027, 3059, -899, 122, -29, + 0, 118, -1039, 14995, 3128, -915, 125, -29, + 0, 127, -1071, 14963, 3198, -931, 128, -28, + -1, 135, -1103, 14930, 3268, -948, 131, -28, + -1, 142, -1134, 14896, 3338, -964, 133, -27, + -1, 150, -1164, 14862, 3409, -980, 136, -27, + -2, 158, -1194, 14827, 3480, -996, 139, -26, + -2, 165, -1224, 14791, 3551, -1013, 142, -26, + -3, 172, -1253, 14754, 3622, -1029, 144, -25, + -3, 179, -1281, 14717, 3694, -1045, 147, -25, + -3, 187, -1309, 14679, 3766, -1062, 150, -24, + -3, 193, -1337, 14640, 3839, -1078, 153, -24, + -4, 200, -1363, 14601, 3912, -1094, 156, -23, + -4, 207, -1390, 14561, 3985, -1110, 159, -23, + -4, 213, -1416, 14520, 4058, -1127, 162, -22, + -4, 220, -1441, 14479, 4131, -1143, 165, -22, + -4, 226, -1466, 14437, 4205, -1159, 168, -22, + -5, 232, -1490, 14394, 4279, -1175, 171, -21, + -5, 238, -1514, 14350, 4354, -1192, 174, -21, + -5, 244, -1537, 14306, 4428, -1208, 177, -20, + -5, 249, -1560, 14261, 4503, -1224, 180, -20, + -5, 255, -1583, 14216, 4578, -1240, 183, -19, + -5, 260, -1604, 14169, 4653, -1256, 186, -19, + -5, 265, -1626, 14123, 4729, -1272, 189, -18, + -5, 271, -1647, 14075, 4805, -1288, 192, -18, + -5, 276, -1667, 14027, 4881, -1304, 195, -17, + -6, 280, -1687, 13978, 4957, -1320, 198, -17, + -6, 285, -1706, 13929, 5033, -1336, 201, -16, + -6, 290, -1725, 13879, 5110, -1352, 204, -16, + -6, 294, -1744, 13829, 5186, -1368, 207, -15, + -6, 299, -1762, 13777, 5263, -1383, 210, -15, + -6, 303, -1779, 13726, 5340, -1399, 213, -14, + -6, 307, -1796, 13673, 5418, -1414, 216, -14, + -6, 311, -1813, 13620, 5495, -1430, 219, -13, + -5, 315, -1829, 13567, 5573, -1445, 222, -13, + -5, 319, -1844, 13512, 5651, -1461, 225, -13, + -5, 322, -1859, 13458, 5728, -1476, 229, -12, + -5, 326, -1874, 13402, 5806, -1491, 232, -12, + -5, 329, -1888, 13347, 5885, -1506, 235, -11, + -5, 332, -1902, 13290, 5963, -1521, 238, -11, + -5, 335, -1915, 13233, 6041, -1536, 241, -10, + -5, 338, -1928, 13176, 6120, -1551, 244, -10, + -5, 341, -1940, 13118, 6199, -1566, 247, -10, + -5, 344, -1952, 13059, 6277, -1580, 250, -9, + -5, 347, -1964, 13000, 6356, -1595, 253, -9, + -5, 349, -1975, 12940, 6435, -1609, 256, -8, + -4, 352, -1986, 12880, 6514, -1623, 259, -8, + -4, 354, -1996, 12819, 6594, -1637, 262, -8, + -4, 356, -2005, 12758, 6673, -1651, 265, -7, + -4, 358, -2015, 12696, 6752, -1665, 268, -7, + -4, 360, -2024, 12634, 6831, -1679, 271, -7, + -4, 362, -2032, 12572, 6911, -1693, 274, -6, + -4, 364, -2040, 12509, 6990, -1706, 277, -6, + -4, 366, -2048, 12445, 7070, -1719, 280, -6, + -3, 367, -2055, 12381, 7149, -1732, 283, -5, + -3, 369, -2062, 12316, 7229, -1745, 286, -5, + -3, 370, -2068, 12251, 7308, -1758, 289, -5, + -3, 371, -2074, 12186, 7388, -1771, 291, -4, + -3, 372, -2079, 12120, 7467, -1784, 294, -4, + -3, 373, -2084, 12054, 7547, -1796, 297, -4, + -3, 374, -2089, 11987, 7626, -1808, 300, -4, + -2, 375, -2094, 11920, 7706, -1820, 303, -3, + -2, 376, -2098, 11852, 7785, -1832, 305, -3, + -2, 376, -2101, 11785, 7865, -1844, 308, -3, + -2, 377, -2104, 11716, 7944, -1855, 311, -3, + -2, 377, -2107, 11647, 8024, -1866, 313, -2, + -2, 378, -2110, 11578, 8103, -1877, 316, -2, + -2, 378, -2112, 11509, 8182, -1888, 318, -2, + -1, 378, -2113, 11439, 8262, -1899, 321, -2, + -1, 378, -2115, 11369, 8341, -1909, 323, -2, + -1, 378, -2116, 11298, 8420, -1920, 326, -2, + -1, 378, -2116, 11227, 8499, -1930, 328, -1, + -1, 378, -2116, 11156, 8578, -1940, 331, -1, + -1, 378, -2116, 11084, 8656, -1949, 333, -1, + -1, 377, -2116, 11012, 8735, -1959, 335, -1, + -1, 377, -2115, 10940, 8814, -1968, 337, -1, + -1, 377, -2114, 10867, 8892, -1977, 340, -1, + -1, 376, -2112, 10795, 8971, -1985, 342, -1, + 0, 375, -2111, 10721, 9049, -1994, 344, -1, + 0, 375, -2108, 10648, 9127, -2002, 346, 0, + 0, 374, -2106, 10574, 9205, -2010, 348, 0, + 0, 373, -2103, 10500, 9283, -2018, 350, 0, + 0, 372, -2100, 10426, 9360, -2025, 352, 0, + 0, 371, -2097, 10351, 9438, -2032, 354, 0, + 0, 370, -2093, 10276, 9515, -2039, 355, 0, + 0, 369, -2089, 10201, 9592, -2046, 357, 0, + 0, 367, -2084, 10126, 9669, -2052, 359, 0, + 0, 366, -2080, 10050, 9745, -2058, 360, 0, + 0, 365, -2075, 9974, 9822, -2064, 362, 0, + 0, 363, -2070, 9898, 9898, -2070, 363, 0, + 0, 362, -2064, 9822, 9974, -2075, 365, 0, + 0, 360, -2058, 9745, 10050, -2080, 366, 0, + 0, 359, -2052, 9669, 10126, -2084, 367, 0, + 0, 357, -2046, 9592, 10201, -2089, 369, 0, + 0, 355, -2039, 9515, 10276, -2093, 370, 0, + 0, 354, -2032, 9438, 10351, -2097, 371, 0, + 0, 352, -2025, 9360, 10426, -2100, 372, 0, + 0, 350, -2018, 9283, 10500, -2103, 373, 0, + 0, 348, -2010, 9205, 10574, -2106, 374, 0, + 0, 346, -2002, 9127, 10648, -2108, 375, 0, + -1, 344, -1994, 9049, 10721, -2111, 375, 0, + -1, 342, -1985, 8971, 10795, -2112, 376, -1, + -1, 340, -1977, 8892, 10867, -2114, 377, -1, + -1, 337, -1968, 8814, 10940, -2115, 377, -1, + -1, 335, -1959, 8735, 11012, -2116, 377, -1, + -1, 333, -1949, 8656, 11084, -2116, 378, -1, + -1, 331, -1940, 8578, 11156, -2116, 378, -1, + -1, 328, -1930, 8499, 11227, -2116, 378, -1, + -2, 326, -1920, 8420, 11298, -2116, 378, -1, + -2, 323, -1909, 8341, 11369, -2115, 378, -1, + -2, 321, -1899, 8262, 11439, -2113, 378, -1, + -2, 318, -1888, 8182, 11509, -2112, 378, -2, + -2, 316, -1877, 8103, 11578, -2110, 378, -2, + -2, 313, -1866, 8024, 11647, -2107, 377, -2, + -3, 311, -1855, 7944, 11716, -2104, 377, -2, + -3, 308, -1844, 7865, 11785, -2101, 376, -2, + -3, 305, -1832, 7785, 11852, -2098, 376, -2, + -3, 303, -1820, 7706, 11920, -2094, 375, -2, + -4, 300, -1808, 7626, 11987, -2089, 374, -3, + -4, 297, -1796, 7547, 12054, -2084, 373, -3, + -4, 294, -1784, 7467, 12120, -2079, 372, -3, + -4, 291, -1771, 7388, 12186, -2074, 371, -3, + -5, 289, -1758, 7308, 12251, -2068, 370, -3, + -5, 286, -1745, 7229, 12316, -2062, 369, -3, + -5, 283, -1732, 7149, 12381, -2055, 367, -3, + -6, 280, -1719, 7070, 12445, -2048, 366, -4, + -6, 277, -1706, 6990, 12509, -2040, 364, -4, + -6, 274, -1693, 6911, 12572, -2032, 362, -4, + -7, 271, -1679, 6831, 12634, -2024, 360, -4, + -7, 268, -1665, 6752, 12696, -2015, 358, -4, + -7, 265, -1651, 6673, 12758, -2005, 356, -4, + -8, 262, -1637, 6594, 12819, -1996, 354, -4, + -8, 259, -1623, 6514, 12880, -1986, 352, -4, + -8, 256, -1609, 6435, 12940, -1975, 349, -5, + -9, 253, -1595, 6356, 13000, -1964, 347, -5, + -9, 250, -1580, 6277, 13059, -1952, 344, -5, + -10, 247, -1566, 6199, 13118, -1940, 341, -5, + -10, 244, -1551, 6120, 13176, -1928, 338, -5, + -10, 241, -1536, 6041, 13233, -1915, 335, -5, + -11, 238, -1521, 5963, 13290, -1902, 332, -5, + -11, 235, -1506, 5885, 13347, -1888, 329, -5, + -12, 232, -1491, 5806, 13402, -1874, 326, -5, + -12, 229, -1476, 5728, 13458, -1859, 322, -5, + -13, 225, -1461, 5651, 13512, -1844, 319, -5, + -13, 222, -1445, 5573, 13567, -1829, 315, -5, + -13, 219, -1430, 5495, 13620, -1813, 311, -6, + -14, 216, -1414, 5418, 13673, -1796, 307, -6, + -14, 213, -1399, 5340, 13726, -1779, 303, -6, + -15, 210, -1383, 5263, 13777, -1762, 299, -6, + -15, 207, -1368, 5186, 13829, -1744, 294, -6, + -16, 204, -1352, 5110, 13879, -1725, 290, -6, + -16, 201, -1336, 5033, 13929, -1706, 285, -6, + -17, 198, -1320, 4957, 13978, -1687, 280, -6, + -17, 195, -1304, 4881, 14027, -1667, 276, -5, + -18, 192, -1288, 4805, 14075, -1647, 271, -5, + -18, 189, -1272, 4729, 14123, -1626, 265, -5, + -19, 186, -1256, 4653, 14169, -1604, 260, -5, + -19, 183, -1240, 4578, 14216, -1583, 255, -5, + -20, 180, -1224, 4503, 14261, -1560, 249, -5, + -20, 177, -1208, 4428, 14306, -1537, 244, -5, + -21, 174, -1192, 4354, 14350, -1514, 238, -5, + -21, 171, -1175, 4279, 14394, -1490, 232, -5, + -22, 168, -1159, 4205, 14437, -1466, 226, -4, + -22, 165, -1143, 4131, 14479, -1441, 220, -4, + -22, 162, -1127, 4058, 14520, -1416, 213, -4, + -23, 159, -1110, 3985, 14561, -1390, 207, -4, + -23, 156, -1094, 3912, 14601, -1363, 200, -4, + -24, 153, -1078, 3839, 14640, -1337, 193, -3, + -24, 150, -1062, 3766, 14679, -1309, 187, -3, + -25, 147, -1045, 3694, 14717, -1281, 179, -3, + -25, 144, -1029, 3622, 14754, -1253, 172, -3, + -26, 142, -1013, 3551, 14791, -1224, 165, -2, + -26, 139, -996, 3480, 14827, -1194, 158, -2, + -27, 136, -980, 3409, 14862, -1164, 150, -1, + -27, 133, -964, 3338, 14896, -1134, 142, -1, + -28, 131, -948, 3268, 14930, -1103, 135, -1, + -28, 128, -931, 3198, 14963, -1071, 127, 0, + -29, 125, -915, 3128, 14995, -1039, 118, 0, + -29, 122, -899, 3059, 15027, -1007, 110, 1, + -29, 120, -883, 2990, 15057, -974, 102, 1, + -30, 117, -867, 2921, 15087, -940, 93, 2, + -30, 115, -851, 2853, 15117, -906, 85, 2, + -31, 112, -835, 2785, 15145, -871, 76, 3, + -31, 109, -819, 2718, 15173, -836, 67, 3, + -32, 107, -803, 2651, 15200, -801, 58, 4, + -32, 104, -787, 2584, 15226, -764, 49, 5, + -32, 102, -771, 2517, 15251, -728, 39, 5, + -33, 99, -755, 2451, 15276, -690, 30, 6, + -33, 97, -740, 2386, 15300, -653, 20, 7, + -33, 95, -724, 2321, 15323, -614, 10, 7, + -34, 92, -708, 2256, 15345, -576, 1, 8, + -34, 90, -693, 2191, 15366, -536, -9, 9, + -34, 88, -677, 2127, 15387, -496, -20, 10, + -35, 85, -662, 2063, 15407, -456, -30, 11, + -35, 83, -646, 2000, 15426, -415, -40, 11, + -35, 81, -631, 1937, 15445, -374, -51, 12, + -36, 79, -616, 1875, 15462, -332, -62, 13, + -36, 76, -600, 1813, 15479, -289, -72, 14, + -36, 74, -585, 1751, 15495, -247, -83, 15, + -36, 72, -570, 1690, 15510, -203, -94, 16, + -37, 70, -555, 1629, 15524, -159, -106, 17, + -37, 68, -540, 1569, 15538, -115, -117, 18, + -37, 66, -526, 1509, 15550, -70, -128, 19, + -37, 64, -511, 1450, 15562, -24, -140, 21, + -37, 62, -496, 1391, 15573, 22, -152, 22, + -38, 60, -482, 1332, 15583, 68, -164, 23, + -38, 58, -467, 1274, 15593, 115, -175, 24, + -38, 56, -453, 1216, 15601, 163, -188, 25, + -38, 54, -439, 1159, 15609, 211, -200, 27, + -38, 53, -425, 1103, 15616, 259, -212, 28, + -38, 51, -410, 1046, 15622, 309, -224, 29, + -38, 49, -396, 990, 15628, 358, -237, 31, + -38, 47, -383, 935, 15632, 408, -250, 32, + -38, 46, -369, 880, 15636, 459, -263, 33, + -38, 44, -355, 826, 15639, 510, -275, 35, + -38, 42, -342, 772, 15641, 561, -288, 36, + -38, 41, -328, 718, 15642, 613, -302, 38, }; inline int SPC_DSP::interpolate( voice_t const* v ) @@ -455,67 +453,67 @@ inline int SPC_DSP::interpolate( voice_t const* v ) return out; } -inline int SPC_DSP::interpolate_cubic( voice_t const* v ) -{ - // Make pointers into cubic based on fractional position between samples - int offset = v->interp_pos >> 4 & 0xFF; - short const* fwd = cubic + offset; - short const* rev = cubic + 256 - offset; // mirror left half of cubic - - int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; - int out; - out = fwd [ 0] * in [0]; - out += fwd [257] * in [1]; - out += rev [257] * in [2]; - out += rev [ 0] * in [3]; - out >>= 11; - - CLAMP16( out ); - out &= ~1; - return out; -} - -inline int SPC_DSP::interpolate_sinc( voice_t const* v ) -{ - // Make pointers into cubic based on fractional position between samples - int offset = v->interp_pos & 0xFF0; - short const* filt = (short const*) (((char const*)sinc) + offset); - - int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; - int out; - out = filt [0] * in [0]; - out += filt [1] * in [1]; - out += filt [2] * in [2]; - out += filt [3] * in [3]; - out += filt [4] * in [4]; - out += filt [5] * in [5]; - out += filt [6] * in [6]; - out += filt [7] * in [7]; - out >>= 14; - - CLAMP16( out ); - out &= ~1; - return out; -} - -inline int SPC_DSP::interpolate_linear( voice_t const* v ) -{ - int fract = v->interp_pos & 0xFFF; - - int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; - int out; - out = (0x1000 - fract) * in [0]; - out += fract * in [1]; - out >>= 12; - - // no need to clamp - out &= ~1; - return out; -} - -inline int SPC_DSP::interpolate_nearest( voice_t const* v ) -{ - return v->buf [(v->interp_pos >> 12) + v->buf_pos] & ~1; +inline int SPC_DSP::interpolate_cubic( voice_t const* v ) +{ + // Make pointers into cubic based on fractional position between samples + int offset = v->interp_pos >> 4 & 0xFF; + short const* fwd = cubic + offset; + short const* rev = cubic + 256 - offset; // mirror left half of cubic + + int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; + int out; + out = fwd [ 0] * in [0]; + out += fwd [257] * in [1]; + out += rev [257] * in [2]; + out += rev [ 0] * in [3]; + out >>= 11; + + CLAMP16( out ); + out &= ~1; + return out; +} + +inline int SPC_DSP::interpolate_sinc( voice_t const* v ) +{ + // Make pointers into cubic based on fractional position between samples + int offset = v->interp_pos & 0xFF0; + short const* filt = (short const*) (((char const*)sinc) + offset); + + int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; + int out; + out = filt [0] * in [0]; + out += filt [1] * in [1]; + out += filt [2] * in [2]; + out += filt [3] * in [3]; + out += filt [4] * in [4]; + out += filt [5] * in [5]; + out += filt [6] * in [6]; + out += filt [7] * in [7]; + out >>= 14; + + CLAMP16( out ); + out &= ~1; + return out; +} + +inline int SPC_DSP::interpolate_linear( voice_t const* v ) +{ + int fract = v->interp_pos & 0xFFF; + + int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; + int out; + out = (0x1000 - fract) * in [0]; + out += fract * in [1]; + out >>= 12; + + // no need to clamp + out &= ~1; + return out; +} + +inline int SPC_DSP::interpolate_nearest( voice_t const* v ) +{ + return v->buf [(v->interp_pos >> 12) + v->buf_pos] & ~1; } @@ -739,7 +737,7 @@ MISC_CLOCK( 30 ) if ( m.every_other_sample ) { m.kon = m.new_kon; - m.t_koff = REG(koff) | m.mute_mask; + m.t_koff = REG(koff); } run_counters(); @@ -819,29 +817,29 @@ VOICE_CLOCK( V3c ) // Gaussian interpolation { int output; - - switch ( m.interpolation_level ) - { - case 0: - default: - output = interpolate( v ); - break; - - case 1: - output = interpolate_cubic( v ); - break; - - case 2: - output = interpolate_sinc( v ); - break; - - case -1: - output = interpolate_linear( v ); - break; - - case -2: - output = interpolate_nearest( v ); - break; + + switch ( m.interpolation_level ) + { + case 0: + default: + output = interpolate( v ); + break; + + case 1: + output = interpolate_cubic( v ); + break; + + case 2: + output = interpolate_sinc( v ); + break; + + case -1: + output = interpolate_linear( v ); + break; + + case -2: + output = interpolate_nearest( v ); + break; } // Noise @@ -889,10 +887,14 @@ inline void SPC_DSP::voice_output( voice_t const* v, int ch ) // Apply left/right volume int amp = (m.t_output * vol) >> 7; - int abs_amp = abs( amp ); - if ( abs_amp > m.max_level[v - (const SPC_DSP::voice_t *)&m.voices][ch] ) - m.max_level[v - (const SPC_DSP::voice_t *)&m.voices][ch] = abs_amp; - + int abs_amp = abs( amp ); + if ( abs_amp > m.max_level[v - (const SPC_DSP::voice_t *)&m.voices][ch] ) + m.max_level[v - (const SPC_DSP::voice_t *)&m.voices][ch] = abs_amp; + + // FIX: audibly mute, rather than do it in a way the SPC code can easily detect + if ( m.mute_mask & ( 1 << ( v - m.voices ) ) ) + amp = 0; + // Add to output total m.t_main_out [ch] += amp; CLAMP16( m.t_main_out [ch] ); @@ -1067,7 +1069,7 @@ inline int SPC_DSP::echo_output( int ch ) vol ^= vol >> 7; int out = (int16_t) ((m.t_main_out [ch] * vol) >> 7) + - (int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7); + (int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7) * m.enable_echo; CLAMP16( out ); return out; } diff --git a/Frameworks/GME/gme/higan/dsp/SPC_DSP.h b/Frameworks/GME/gme/higan/dsp/SPC_DSP.h index cc6c6d08d..53e80423c 100755 --- a/Frameworks/GME/gme/higan/dsp/SPC_DSP.h +++ b/Frameworks/GME/gme/higan/dsp/SPC_DSP.h @@ -22,6 +22,7 @@ public: // doesn't generate any. typedef short sample_t; void set_output( sample_t* out, int out_size ); + sample_t* get_output(); // Number of samples written to output since it was last set, always // a multiple of 2. Undefined if more samples were generated than @@ -91,11 +92,10 @@ public: }; public: - enum { extra_size = 16 }; - sample_t* extra() { return m.extra; } sample_t const* out_pos() const { return m.out; } void disable_surround( bool disable = true ); void interpolation_level( int level = 0 ) { m.interpolation_level = level; } + void enable_echo( bool enable = true ) { m.enable_echo = enable ? 1 : 0; } public: BLARGG_DISABLE_NOTHROW @@ -184,10 +184,10 @@ public: int mute_mask; int surround_threshold; int interpolation_level; + int enable_echo; sample_t* out; sample_t* out_end; sample_t* out_begin; - sample_t extra [extra_size]; int max_level[voice_count][2]; }; @@ -299,6 +299,11 @@ inline bool SPC_DSP::check_kon() return old; } +inline SPC_DSP::sample_t* SPC_DSP::get_output() +{ + return m.out_begin; +} + #if !SPC_NO_COPY_STATE_FUNCS class SPC_State_Copier { diff --git a/Plugins/GME/GameDecoder.h b/Plugins/GME/GameDecoder.h index dea76428f..85c986bad 100755 --- a/Plugins/GME/GameDecoder.h +++ b/Plugins/GME/GameDecoder.h @@ -18,6 +18,7 @@ extern gme_err_t readCallback( void* data, void* out, long count ); Music_Emu* emu; id source; long length; + long fade; } - (void)setSource:(id)s; diff --git a/Plugins/GME/GameDecoder.m b/Plugins/GME/GameDecoder.m index 6a72c0f76..336685ec9 100755 --- a/Plugins/GME/GameDecoder.m +++ b/Plugins/GME/GameDecoder.m @@ -121,6 +121,13 @@ gme_err_t readCallback( void* data, void* out, long count ) length = 150000; DLog(@"Setting default: %li", length); } + + if (info->fade_length >= 0) { + fade = info->fade_length; + } + else { + fade = 8000; + } gme_free_info( info ); @@ -134,7 +141,7 @@ gme_err_t readCallback( void* data, void* out, long count ) return NO; } - length += 8000; + length += fade; [self willChangeValueForKey:@"properties"]; @@ -167,7 +174,7 @@ gme_err_t readCallback( void* data, void* out, long count ) if ( IsRepeatOneSet() ) gme_set_fade( emu, -1, 0 ); else - gme_set_fade( emu, (int)(length - 8000), 8000 ); + gme_set_fade( emu, (int)(length - fade), fade ); gme_play(emu, numSamples, (short int *)buf);