/* wildmidi_lib.c Midi Wavetable Processing library Copyright (C)2001-2004 Chris Ison This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Email: cisos@bigpond.net.au wildcode@users.sourceforge.net $Id: wildmidi_lib.c,v 1.18 2004/01/28 05:45:09 wildcode Exp $ ======================================== Changelog ---------------------------------------- Aug 3, 2003 - changed kill envelope from 6th to 5th - changed data_length, loop_start, loop_end to 22:10 fixed point - added fractional position to loop_start and loop_end - added fake reverb Aug 4, 2003 - added MIDI_EVENT_DEBUG to midi event functions - fixed hold release killing off notes that hadn't been turned off by note off - sped up fake reverb by doing it outside the channel mixing loop Aug 5, 2003 - removed note_table init from ParseNewMidi, entries are now fully reset in do_note_on - moved fast kill envelope setting to sample loading - removed envelopes from notes, use ones from sample instead - optimized do_amp_setup functions - do_control_volume, do_control_expression, do_channel_pressure, changed from setting note_table[] to note[] for performance. - optimizations of sample conversion, Aug 6, 2003 - removed changing sample volumes, the amp setting is now apart of the midi volume maths. - re-write conversion functions to make them more clearer and less bug prone Aug 7, 2003 - fixed volume, expression and preasure changes effecting all notes. Aug 8, 2003 - spead up midi processing by using an event index Aug 9, 2003 - spead up sampling and mixing by using a seperate function depending on fixed modes - fixed data lock where it would sleep reguardless of lock state - fixed memory leak ... oops, forgot a free - removed track data storge, isn't required by the core functions Aug 10, 2003 - created error function and changed all error messages to use it - malloc, calloc, realloc audit ensuring all are error checked. - fixed potential reading beyond end of midi bug Aug 11, 2003 - fixed expensive interpolation over-running the sample buffer - changed stereo option so that changing it worked right away Aug 14, 2003 - optimizations for and to the frequency calc code - removal of wide stereo (it sucked anyway) Aug 15, 2003 - fixed volume levels for panning when non-linear volumes are used - removed fake reberb, it sucked on better sound systems. Aug 17, 2003 - fixed autoamp - added env_time#= and env_level#= to timiidty.cfg parser. - fixed bug where last event in the midi before the last eot would have a large delta. This is a bug in the midi file itself. - fixed some midi's having no sound cause they don't supply patch information. Now defaulting all channels to bank 0, patch 0. Aug 18, 2003 - preload samples - optimized envelope checking and controler code - fixed bug where some samples have an envelope rate setting that doesn't actually mean anything .. ie: 0x00 0x40 0x80 0xC0 - fixed amp bug where initial left/right levels were set to 0 - added timidity's keep=[loop|env] support for drum patches, now ignores loops and env settings for drum patches unless keep=[loop|env] is in the patch line in the config. Aug 21, 2003 - float to fixed point math conversions. - frequency range locked to 100 steps between notes NOTE:need to test slow pitchbends with this, fast ones are fine Aug 24, 2003 - optimized sample conversions - optimized note handling and sample/envelope position checks Aug 28, 2003 - compile level optimizations NOTE: gcc builtins used - numerous bug fixes Aug 30, 2003 - fixed sample inc calculation bug - fixed panning volumes, now percieved volume of the sample is the same no matter panning position. ` Sep 2, 2003 - made noteoff/hold behaviour match midi standard - added remove=sustain to patch line - added all sound off controller - fixed all notes off to only effect notes that aren't being held - changed envelope behaviour so that only non-sustaned samples hit envelope 4 while note is on. - Added all controllers off event Sep 4, 2003 - added master sample data lock - improved performance of the resampling algo ======================================== */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #ifndef _WIN32 #include #endif #include #include #include #include #include #include #include #ifdef _WIN32 # include #endif #include "wildmidi_lib.h" /* * ========================= * Global Data and Data Structs * ========================= */ int WM_Initialized = 0; signed short int WM_MasterVolume = 948; unsigned short int WM_SampleRate = 0; unsigned short int WM_MixerOptions = 0; char WM_Version[] = "WildMidi Processing Library " WILDMIDILIB_VERSION; struct _lowpass { signed long int in[2]; signed long int out[2]; }; struct _filter { signed long int *delay[4][2]; unsigned long int delay_pos[4][2]; struct _lowpass lowpass[4][2]; signed long int in[2][2]; signed long int out[2][2]; }; struct _env { float time; float level; unsigned char set; }; struct _sample { unsigned long int data_length; unsigned long int loop_start; unsigned long int loop_end; unsigned long int loop_size; unsigned char loop_fraction; unsigned short int rate; unsigned long int freq_low; unsigned long int freq_high; unsigned long int freq_root; unsigned char modes; unsigned long int env_rate[7]; unsigned long int env_target[7]; unsigned long int inc_div; signed short *data; signed short max_peek; signed short min_peek; signed long int peek_adjust; struct _sample *next; }; struct _patch { unsigned short patchid; unsigned char loaded; char *filename; signed short int amp; unsigned char keep; unsigned char remove; struct _env env[6]; unsigned char note; unsigned long int inuse_count; struct _sample *first_sample; struct _patch *next; }; struct _patch *patch[128]; int patch_lock; struct _channel { unsigned char bank; struct _patch *patch; unsigned char hold; unsigned char volume; unsigned char pressure; unsigned char expression; signed char balance; signed char pan; signed short int left_adjust; signed short int right_adjust; signed short int pitch; signed short int pitch_range; signed long int pitch_adjust; unsigned short reg_data; }; #define HOLD_OFF 0x02 struct _note { unsigned short noteid; unsigned char velocity; struct _patch *patch; struct _sample *sample; unsigned long int sample_pos; unsigned long int sample_inc; signed long int env_inc; unsigned char env; unsigned long int env_level; unsigned char modes; unsigned char hold; unsigned char active; struct _note *next; signed short int vol_lvl; }; struct _miditrack { unsigned long int length; unsigned long int ptr; unsigned long int delta; unsigned char running_event; unsigned char EOT; }; struct _mdi_patches { struct _patch *patch; struct _mdi_patch *next; }; struct _mdi_index { unsigned long int offset; unsigned char event; unsigned long int delta; }; struct _mdi { int lock; unsigned char *data; unsigned long int size; unsigned short int divisions ; unsigned short midi_master_vol; unsigned long int samples_per_delta; unsigned long int samples_to_mix; struct _mdi_index * index; unsigned long int index_count; unsigned long int index_size; struct _WM_Info info; struct _WM_Info *tmp_info; unsigned char recalc_samples; struct _channel channel[16]; struct _note *note[128]; struct _note **last_note; struct _note note_table[2][16][128]; struct _patch **patches; unsigned long int patch_count; unsigned long int sample_count; signed short int amp; // setup data for auto amp signed long int log_cur_vol; signed long int lin_cur_vol; signed long int log_max_vol; signed long int lin_max_vol; unsigned char ch_vol[16]; unsigned char ch_exp[16]; unsigned char note_vel[16][128]; struct _filter filter; }; /* Gauss Interpolation code adapted from code supplied by Eric. A. Welsh */ double newt_coeffs[58][58]; /* for start/end of samples */ float *gauss_table[(1<<10)] = {0}; /* don't need doubles */ int gauss_window[35] = {0}; int gauss_n = 34; /* do not set this value higher than 34 */ /* 34 is as high as we can go before errors crop up */ void init_gauss (void) { /* init gauss table */ int n = 34; int m, i, k, n_half = (n>>1); int j; int sign; double ck; double x, x_inc, xz; double z[35]; float *gptr; newt_coeffs[0][0] = 1; for (i = 0; i <= n; i++) { newt_coeffs[i][0] = 1; newt_coeffs[i][i] = 1; if (i > 1) { newt_coeffs[i][0] = newt_coeffs[i-1][0] / i; newt_coeffs[i][i] = newt_coeffs[i-1][0] / i; } for (j = 1; j < i; j++) { newt_coeffs[i][j] = newt_coeffs[i-1][j-1] + newt_coeffs[i-1][j]; if (i > 1) newt_coeffs[i][j] /= i; } z[i] = i / (4*M_PI); } for (i = 0; i <= n; i++) for (j = 0, sign = pow(-1, i); j <= i; j++, sign *= -1) newt_coeffs[i][j] *= sign; x_inc = 1.0 / (1<<10); for (m = 0, x = 0.0; m < (1<<10); m++, x += x_inc) { xz = (x + n_half) / (4*M_PI); gptr = gauss_table[m] = realloc(gauss_table[m], (n+1)*sizeof(float)); for (k = 0; k <= n; k++) { ck = 1.0; for (i = 0; i <= n; i++) { if (i == k) continue; ck *= (sin(xz - z[i])) / (sin(z[k] - z[i])); } *gptr++ = ck; } } } void free_gauss (void) { for (int i = 0; i < (1<<10); i++) { if (gauss_table[i]) { free (gauss_table[i]); } gauss_table[i] = NULL; } } unsigned long int delay_size[4][2]; signed long int a[5][2]; signed long int b[5][2]; signed long int gain_in[4]; signed long int gain_out[4]; void init_lowpass (void) { float c = 0; int i; float f[] = { 512.0, 1024.0, 2048.0, 4096.0 , 8192.0}; float aa, ab, ba, bb; for (i = 0; i < 5; i++) { c = 1.0 / tan(3.141592654 * f[i] / WM_SampleRate); aa = 1.0 / (1.0 + 1.4 * c + c * c); ab = 2.0 * aa; ba = 2.0 * (1.0 - c * c) * aa; bb = (1.0 - 1.4 * c + c * c) * aa; a[i][0] = (signed long int)(aa * 1024.0); a[i][1] = (signed long int)(ab * 1024.0); b[i][0] = (signed long int)(ba * 1024.0); b[i][1] = (signed long int)(bb * 1024.0); } gain_in[0] = 772; gain_out[0] = 772; gain_in[1] = 570; gain_out[1] = 570; gain_in[2] = 520; gain_out[2] = 520; gain_in[3] = 512; gain_out[3] = 512; delay_size[0][0] = 2191 * WM_SampleRate / 44100; delay_size[0][1] = (2191 + 19) * WM_SampleRate / 44100; delay_size[1][0] = (2971 + 19) * WM_SampleRate / 44100; delay_size[1][1] = 2971 * WM_SampleRate / 44100; delay_size[2][0] = 3253 * WM_SampleRate / 44100; delay_size[2][1] = (3253 + 19) * WM_SampleRate / 44100; delay_size[3][0] = (3307 + 19) * WM_SampleRate / 44100; delay_size[3][1] = 3307 * WM_SampleRate / 44100; } struct _hndl { void * handle; struct _hndl *next; struct _hndl *prev; }; struct _hndl * first_handle = NULL; //f: ( VOLUME / 127 ) //f: pow(( VOLUME / 127 ), 1.660964047 ) //f: pow(( VOLUME / 127 ), 2.0 ) //f: pow(( VOLUME / 127 ), 0.602059991 ) //f: pow(( VOLUME / 127 ), 0.5 ) signed short int lin_volume[] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 129, 137, 145, 153, 161, 169, 177, 185, 193, 201, 209, 217, 225, 233, 241, 249, 258, 266, 274, 282, 290, 298, 306, 314, 322, 330, 338, 346, 354, 362, 370, 378, 387, 395, 403, 411, 419, 427, 435, 443, 451, 459, 467, 475, 483, 491, 499, 507, 516, 524, 532, 540, 548, 556, 564, 572, 580, 588, 596, 604, 612, 620, 628, 636, 645, 653, 661, 669, 677, 685, 693, 701, 709, 717, 725, 733, 741, 749, 757, 765, 774, 782, 790, 798, 806, 814, 822, 830, 838, 846, 854, 862, 870, 878, 886, 894, 903, 911, 919, 927, 935, 943, 951, 959, 967, 975, 983, 991, 999, 1007, 1015, 1024 }; signed short int log_volume[] = { 0, 0, 1, 2, 3, 4, 6, 8, 10, 12, 15, 17, 20, 23, 26, 29, 32, 36, 39, 43, 47, 51, 55, 59, 64, 68, 73, 78, 83, 88, 93, 98, 103, 109, 114, 120, 126, 132, 138, 144, 150, 156, 162, 169, 176, 182, 189, 196, 203, 210, 217, 224, 232, 239, 247, 255, 262, 270, 278, 286, 294, 302, 311, 319, 328, 336, 345, 353, 362, 371, 380, 389, 398, 408, 417, 426, 436, 446, 455, 465, 475, 485, 495, 505, 515, 525, 535, 546, 556, 567, 577, 588, 599, 610, 621, 632, 643, 654, 665, 677, 688, 699, 711, 723, 734, 746, 758, 770, 782, 794, 806, 818, 831, 843, 855, 868, 880, 893, 906, 919, 931, 944, 957, 970, 984, 997, 1010, 1024 }; signed short int sqr_volume[] = { 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 9, 10, 12, 14, 16, 18, 20, 22, 25, 27, 30, 33, 36, 39, 42, 46, 49, 53, 57, 61, 65, 69, 73, 77, 82, 86, 91, 96, 101, 106, 111, 117, 122, 128, 134, 140, 146, 152, 158, 165, 171, 178, 185, 192, 199, 206, 213, 221, 228, 236, 244, 251, 260, 268, 276, 284, 293, 302, 311, 320, 329, 338, 347, 357, 366, 376, 386, 396, 406, 416, 426, 437, 447, 458, 469, 480, 491, 502, 514, 525, 537, 549, 560, 572, 585, 597, 609, 622, 634, 647, 660, 673, 686, 699, 713, 726, 740, 754, 768, 782, 796, 810, 825, 839, 854, 869, 884, 899, 914, 929, 944, 960, 976, 992, 1007, 1024 }; //signed short int pan_volume[] = { 0, 55, 84, 107, 127, 146, 162, 178, 193, 208, 221, 234, 247, 259, 271, 282, 294, 305, 315, 326, 336, 346, 356, 366, 375, 384, 394, 403, 412, 420, 429, 438, 446, 454, 463, 471, 479, 487, 495, 503, 510, 518, 525, 533, 540, 548, 555, 562, 570, 577, 584, 591, 598, 605, 611, 618, 625, 632, 638, 645, 651, 658, 664, 671, 677, 684, 690, 696, 703, 709, 715, 721, 727, 733, 739, 745, 751, 757, 763, 769, 775, 781, 786, 792, 798, 804, 809, 815, 821, 826, 832, 837, 843, 848, 854, 859, 865, 870, 876, 881, 886, 892, 897, 902, 907, 913, 918, 923, 928, 933, 939, 944, 949, 954, 959, 964, 969, 974, 979, 984, 989, 994, 999, 1004, 1009, 1014, 1019, 1024 }; signed short int pan_volume[] = { 0, 90, 128, 157, 181, 203, 222, 240, 257, 272, 287, 301, 314, 327, 339, 351, 363, 374, 385, 396, 406, 416, 426, 435, 445, 454, 463, 472, 480, 489, 497, 505, 514, 521, 529, 537, 545, 552, 560, 567, 574, 581, 588, 595, 602, 609, 616, 622, 629, 636, 642, 648, 655, 661, 667, 673, 679, 686, 692, 697, 703, 709, 715, 721, 726, 732, 738, 743, 749, 754, 760, 765, 771, 776, 781, 786, 792, 797, 802, 807, 812, 817, 822, 827, 832, 837, 842, 847, 852, 857, 862, 866, 871, 876, 880, 885, 890, 894, 899, 904, 908, 913, 917, 922, 926, 931, 935, 939, 944, 948, 953, 957, 961, 965, 970, 974, 978, 982, 987, 991, 995, 999, 1003, 1007, 1011, 1015, 1019, 1024 }; unsigned long int reverb_val = 92; unsigned long int comb_size[8][2]; unsigned long int allpass_size[2][2]; float env_time_table[] = { 0.0, 0.092857143, 0.046428571, 0.030952381, 0.023214286, 0.018571429, 0.015476190, 0.013265306, 0.011607143, 0.010317460, 0.009285714, 0.008441558, 0.007738095, 0.007142857, 0.006632653, 0.006190476, 0.005803571, 0.005462185, 0.005158730, 0.004887218, 0.004642857, 0.004421769, 0.004220779, 0.004037267, 0.003869048, 0.003714286, 0.003571429, 0.003439153, 0.003316327, 0.003201970, 0.003095238, 0.002995392, 0.002901786, 0.002813853, 0.002731092, 0.002653061, 0.002579365, 0.002509653, 0.002443609, 0.002380952, 0.002321429, 0.002264808, 0.002210884, 0.002159468, 0.002110390, 0.002063492, 0.002018634, 0.001975684, 0.001934524, 0.001895044, 0.001857143, 0.001820728, 0.001785714, 0.001752022, 0.001719577, 0.001688312, 0.001658163, 0.001629073, 0.001600985, 0.001573850, 0.001547619, 0.001522248, 0.001497696, 0.001473923, 0.0, 0.742857143, 0.371428571, 0.247619048, 0.185714286, 0.148571429, 0.123809524, 0.106122449, 0.092857143, 0.082539683, 0.074285714, 0.067532468, 0.061904762, 0.057142857, 0.053061224, 0.049523810, 0.046428571, 0.043697479, 0.041269841, 0.039097744, 0.037142857, 0.035374150, 0.033766234, 0.032298137, 0.030952381, 0.029714286, 0.028571429, 0.027513228, 0.026530612, 0.025615764, 0.024761905, 0.023963134, 0.023214286, 0.022510823, 0.021848739, 0.021224490, 0.020634921, 0.020077220, 0.019548872, 0.019047619, 0.018571429, 0.018118467, 0.017687075, 0.017275748, 0.016883117, 0.016507937, 0.016149068, 0.015805471, 0.015476190, 0.015160350, 0.014857143, 0.014565826, 0.014285714, 0.014016173, 0.013756614, 0.013506494, 0.013265306, 0.013032581, 0.012807882, 0.012590799, 0.012380952, 0.012177986, 0.011981567, 0.011791383, 0.0, 5.942857143, 2.971428571, 1.980952381, 1.485714286, 1.188571429, 0.990476190, 0.848979592, 0.742857143, 0.660317460, 0.594285714, 0.540259740, 0.495238095, 0.457142857, 0.424489796, 0.396190476, 0.371428571, 0.349579832, 0.330158730, 0.312781955, 0.297142857, 0.282993197, 0.270129870, 0.258385093, 0.247619048, 0.237714286, 0.228571429, 0.220105820, 0.212244898, 0.204926108, 0.198095238, 0.191705069, 0.185714286, 0.180086580, 0.174789916, 0.169795918, 0.165079365, 0.160617761, 0.156390977, 0.152380952, 0.148571429, 0.144947735, 0.141496599, 0.138205980, 0.135064935, 0.132063492, 0.129192547, 0.126443769, 0.123809524, 0.121282799, 0.118857143, 0.116526611, 0.114285714, 0.112129380, 0.110052910, 0.108051948, 0.106122449, 0.104260652, 0.102463054, 0.100726392, 0.099047619, 0.097423888, 0.095852535, 0.094331066, 0.0, 47.542857143, 23.771428571, 15.847619048, 11.885714286, 9.508571429, 7.923809524, 6.791836735, 5.942857143, 5.282539683, 4.754285714, 4.322077922, 3.961904762, 3.657142857, 3.395918367, 3.169523810, 2.971428571, 2.796638655, 2.641269841, 2.502255639, 2.377142857, 2.263945578, 2.161038961, 2.067080745, 1.980952381, 1.901714286, 1.828571429, 1.760846561, 1.697959184, 1.639408867, 1.584761905, 1.533640553, 1.485714286, 1.440692641, 1.398319328, 1.358367347, 1.320634921, 1.284942085, 1.251127820, 1.219047619, 1.188571429, 1.159581882, 1.131972789, 1.105647841, 1.080519481, 1.056507937, 1.033540373, 1.011550152, 0.990476190, 0.970262391, 0.950857143, 0.932212885, 0.914285714, 0.897035040, 0.880423280, 0.864415584, 0.848979592, 0.834085213, 0.819704433, 0.805811138, 0.792380952, 0.779391101, 0.766820276, 0.754648526 }; #if 0 unsigned long int freq_table[] = { 8372018, 8376855, 8381695, 8386538, 8391384, 8396232, 8401084, 8405938, 8410795, 8415654, 8420517, 8425382, 8430250, 8435121, 8439995, 8444871, 8449751, 8454633, 8459518, 8464406, 8469296, 8474190, 8479086, 8483985, 8488887, 8493792, 8498700, 8503610, 8508523, 8513439, 8518358, 8523280, 8528205, 8533132, 8538063, 8542996, 8547932, 8552871, 8557813, 8562757, 8567705, 8572655, 8577608, 8582564, 8587523, 8592485, 8597450, 8602417, 8607387, 8612361, 8617337, 8622316, 8627298, 8632282, 8637270, 8642261, 8647254, 8652250, 8657250, 8662252, 8667257, 8672264, 8677275, 8682289, 8687305, 8692325, 8697347, 8702372, 8707400, 8712431, 8717465, 8722502, 8727542, 8732585, 8737630, 8742679, 8747730, 8752785, 8757842, 8762902, 8767965, 8773031, 8778100, 8783172, 8788247, 8793325, 8798405, 8803489, 8808575, 8813665, 8818757, 8823853, 8828951, 8834052, 8839157, 8844264, 8849374, 8854487, 8859603, 8864722, 8869844, 8874969, 8880097, 8885227, 8890361, 8895498, 8900638, 8905780, 8910926, 8916075, 8921226, 8926381, 8931538, 8936699, 8941863, 8947029, 8952199, 8957371, 8962546, 8967725, 8972906, 8978091, 8983278, 8988469, 8993662, 8998859, 9004058, 9009260, 9014466, 9019674, 9024886, 9030100, 9035318, 9040538, 9045762, 9050988, 9056218, 9061451, 9066686, 9071925, 9077166, 9082411, 9087659, 9092910, 9098163, 9103420, 9108680, 9113943, 9119209, 9124478, 9129750, 9135025, 9140303, 9145584, 9150868, 9156156, 9161446, 9166739, 9172036, 9177335, 9182638, 9187944, 9193252, 9198564, 9203879, 9209197, 9214518, 9219842, 9225169, 9230499, 9235832, 9241169, 9246508, 9251851, 9257196, 9262545, 9267897, 9273252, 9278610, 9283971, 9289335, 9294702, 9300073, 9305446, 9310823, 9316202, 9321585, 9326971, 9332360, 9337752, 9343147, 9348546, 9353947, 9359352, 9364760, 9370171, 9375585, 9381002, 9386422, 9391845, 9397272, 9402701, 9408134, 9413570, 9419009, 9424451, 9429897, 9435345, 9440797, 9446252, 9451710, 9457171, 9462635, 9468102, 9473573, 9479047, 9484524, 9490004, 9495487, 9500973, 9506463, 9511955, 9517451, 9522950, 9528453, 9533958, 9539467, 9544979, 9550494, 9556012, 9561533, 9567058, 9572585, 9578116, 9583650, 9589188, 9594728, 9600272, 9605819, 9611369, 9616922, 9622479, 9628039, 9633602, 9639168, 9644737, 9650310, 9655886, 9661465, 9667047, 9672633, 9678221, 9683813, 9689409, 9695007, 9700609, 9706214, 9711822, 9717433, 9723048, 9728666, 9734287, 9739911, 9745539, 9751170, 9756804, 9762441, 9768082, 9773726, 9779373, 9785023, 9790677, 9796334, 9801994, 9807657, 9813324, 9818994, 9824667, 9830344, 9836024, 9841707, 9847394, 9853083, 9858776, 9864473, 9870172, 9875875, 9881581, 9887291, 9893003, 9898719, 9904439, 9910162, 9915887, 9921617, 9927349, 9933085, 9938825, 9944567, 9950313, 9956062, 9961815, 9967570, 9973330, 9979092, 9984858, 9990627, 9996399, 10002175, 10007954, 10013737, 10019523, 10025312, 10031104, 10036900, 10042700, 10048502, 10054308, 10060117, 10065930, 10071746, 10077565, 10083388, 10089214, 10095043, 10100876, 10106712, 10112552, 10118395, 10124241, 10130091, 10135944, 10141800, 10147660, 10153523, 10159390, 10165260, 10171133, 10177010, 10182890, 10188774, 10194661, 10200551, 10206445, 10212342, 10218243, 10224147, 10230054, 10235965, 10241879, 10247797, 10253718, 10259642, 10265570, 10271502, 10277436, 10283374, 10289316, 10295261, 10301210, 10307162, 10313117, 10319076, 10325038, 10331004, 10336973, 10342945, 10348921, 10354901, 10360884, 10366870, 10372860, 10378853, 10384850, 10390850, 10396854, 10402861, 10408872, 10414886, 10420904, 10426925, 10432949, 10438977, 10445009, 10451044, 10457083, 10463124, 10469170, 10475219, 10481271, 10487327, 10493387, 10499450, 10505516, 10511586, 10517660, 10523737, 10529817, 10535901, 10541989, 10548080, 10554174, 10560273, 10566374, 10572480, 10578589, 10584701, 10590817, 10596936, 10603059, 10609186, 10615316, 10621449, 10627586, 10633727, 10639871, 10646019, 10652170, 10658325, 10664483, 10670645, 10676811, 10682980, 10689153, 10695329, 10701509, 10707692, 10713879, 10720069, 10726264, 10732461, 10738662, 10744867, 10751076, 10757288, 10763503, 10769722, 10775945, 10782172, 10788402, 10794635, 10800872, 10807113, 10813357, 10819605, 10825857, 10832112, 10838371, 10844634, 10850900, 10857169, 10863443, 10869720, 10876000, 10882284, 10888572, 10894864, 10901159, 10907457, 10913760, 10920066, 10926375, 10932689, 10939006, 10945326, 10951650, 10957978, 10964310, 10970645, 10976984, 10983326, 10989673, 10996022, 11002376, 11008733, 11015094, 11021459, 11027827, 11034199, 11040574, 11046954, 11053337, 11059723, 11066114, 11072508, 11078905, 11085307, 11091712, 11098121, 11104533, 11110949, 11117369, 11123793, 11130220, 11136651, 11143086, 11149525, 11155967, 11162413, 11168863, 11175316, 11181773, 11188234, 11194699, 11201167, 11207639, 11214115, 11220594, 11227078, 11233565, 11240055, 11246550, 11253048, 11259550, 11266056, 11272566, 11279079, 11285596, 11292117, 11298642, 11305170, 11311702, 11318238, 11324778, 11331321, 11337868, 11344420, 11350974, 11357533, 11364095, 11370662, 11377232, 11383805, 11390383, 11396964, 11403550, 11410139, 11416731, 11423328, 11429928, 11436533, 11443141, 11449753, 11456368, 11462988, 11469611, 11476238, 11482869, 11489504, 11496143, 11502785, 11509432, 11516082, 11522736, 11529394, 11536056, 11542721, 11549390, 11556064, 11562741, 11569422, 11576107, 11582795, 11589488, 11596184, 11602885, 11609589, 11616297, 11623009, 11629725, 11636444, 11643168, 11649895, 11656627, 11663362, 11670101, 11676844, 11683591, 11690342, 11697097, 11703855, 11710618, 11717384, 11724154, 11730929, 11737707, 11744489, 11751275, 11758065, 11764859, 11771656, 11778458, 11785264, 11792073, 11798887, 11805704, 11812526, 11819351, 11826180, 11833013, 11839851, 11846692, 11853537, 11860386, 11867239, 11874096, 11880956, 11887821, 11894690, 11901563, 11908440, 11915320, 11922205, 11929094, 11935986, 11942883, 11949784, 11956688, 11963597, 11970510, 11977426, 11984347, 11991271, 11998200, 12005133, 12012069, 12019010, 12025954, 12032903, 12039856, 12046812, 12053773, 12060738, 12067706, 12074679, 12081656, 12088637, 12095622, 12102610, 12109603, 12116600, 12123601, 12130606, 12137615, 12144629, 12151646, 12158667, 12165692, 12172722, 12179755, 12186793, 12193834, 12200880, 12207930, 12214983, 12222041, 12229103, 12236169, 12243239, 12250313, 12257392, 12264474, 12271561, 12278651, 12285746, 12292844, 12299947, 12307054, 12314165, 12321280, 12328400, 12335523, 12342651, 12349782, 12356918, 12364058, 12371202, 12378350, 12385502, 12392658, 12399819, 12406984, 12414152, 12421325, 12428502, 12435684, 12442869, 12450059, 12457252, 12464450, 12471652, 12478858, 12486069, 12493283, 12500502, 12507725, 12514952, 12522183, 12529418, 12536658, 12543901, 12551149, 12558401, 12565658, 12572918, 12580183, 12587452, 12594725, 12602002, 12609283, 12616569, 12623859, 12631153, 12638451, 12645754, 12653061, 12660372, 12667687, 12675006, 12682330, 12689658, 12696990, 12704326, 12711667, 12719012, 12726361, 12733714, 12741072, 12748433, 12755800, 12763170, 12770544, 12777923, 12785306, 12792694, 12800085, 12807481, 12814882, 12822286, 12829695, 12837108, 12844525, 12851947, 12859373, 12866803, 12874237, 12881676, 12889119, 12896567, 12904018, 12911474, 12918934, 12926399, 12933868, 12941341, 12948819, 12956301, 12963787, 12971277, 12978772, 12986271, 12993775, 13001283, 13008795, 13016311, 13023832, 13031357, 13038887, 13046421, 13053959, 13061502, 13069049, 13076600, 13084156, 13091716, 13099280, 13106849, 13114422, 13122000, 13129582, 13137168, 13144759, 13152354, 13159953, 13167557, 13175165, 13182778, 13190395, 13198016, 13205642, 13213273, 13220907, 13228546, 13236190, 13243838, 13251490, 13259147, 13266808, 13274474, 13282144, 13289818, 13297497, 13305180, 13312868, 13320560, 13328257, 13335958, 13343663, 13351373, 13359088, 13366807, 13374530, 13382258, 13389990, 13397727, 13405468, 13413214, 13420964, 13428719, 13436478, 13444241, 13452010, 13459782, 13467559, 13475341, 13483127, 13490918, 13498713, 13506512, 13514316, 13522125, 13529938, 13537756, 13545578, 13553405, 13561236, 13569071, 13576912, 13584756, 13592606, 13600460, 13608318, 13616181, 13624048, 13631920, 13639797, 13647678, 13655564, 13663454, 13671349, 13679248, 13687152, 13695060, 13702974, 13710891, 13718813, 13726740, 13734671, 13742607, 13750548, 13758493, 13766443, 13774397, 13782356, 13790319, 13798287, 13806260, 13814237, 13822219, 13830206, 13838197, 13846193, 13854193, 13862198, 13870208, 13878222, 13886241, 13894264, 13902292, 13910325, 13918363, 13926405, 13934451, 13942503, 13950559, 13958619, 13966685, 13974755, 13982829, 13990909, 13998993, 14007081, 14015175, 14023273, 14031375, 14039483, 14047595, 14055712, 14063833, 14071959, 14080090, 14088225, 14096366, 14104511, 14112660, 14120815, 14128974, 14137137, 14145306, 14153479, 14161657, 14169840, 14178027, 14186219, 14194416, 14202618, 14210824, 14219035, 14227251, 14235471, 14243697, 14251927, 14260161, 14268401, 14276645, 14284894, 14293148, 14301407, 14309670, 14317938, 14326211, 14334489, 14342772, 14351059, 14359351, 14367648, 14375949, 14384256, 14392567, 14400883, 14409204, 14417530, 14425860, 14434196, 14442536, 14450881, 14459230, 14467585, 14475944, 14484309, 14492678, 14501052, 14509430, 14517814, 14526202, 14534596, 14542994, 14551397, 14559805, 14568217, 14576635, 14585057, 14593485, 14601917, 14610354, 14618796, 14627242, 14635694, 14644151, 14652612, 14661078, 14669550, 14678026, 14686507, 14694993, 14703483, 14711979, 14720480, 14728985, 14737496, 14746011, 14754531, 14763057, 14771587, 14780122, 14788662, 14797207, 14805757, 14814311, 14822871, 14831436, 14840005, 14848580, 14857160, 14865744, 14874334, 14882928, 14891527, 14900132, 14908741, 14917355, 14925975, 14934599, 14943228, 14951862, 14960502, 14969146, 14977795, 14986449, 14995109, 15003773, 15012442, 15021116, 15029795, 15038480, 15047169, 15055863, 15064563, 15073267, 15081976, 15090691, 15099410, 15108135, 15116864, 15125599, 15134338, 15143083, 15151833, 15160587, 15169347, 15178112, 15186882, 15195657, 15204437, 15213222, 15222013, 15230808, 15239608, 15248414, 15257224, 15266040, 15274861, 15283687, 15292518, 15301354, 15310195, 15319041, 15327893, 15336749, 15345611, 15354477, 15363349, 15372226, 15381108, 15389996, 15398888, 15407786, 15416688, 15425596, 15434509, 15443427, 15452350, 15461279, 15470212, 15479151, 15488095, 15497044, 15505998, 15514958, 15523922, 15532892, 15541867, 15550847, 15559832, 15568823, 15577819, 15586820, 15595826, 15604837, 15613853, 15622875, 15631902, 15640934, 15649972, 15659014, 15668062, 15677115, 15686173, 15695237, 15704306, 15713380, 15722459, 15731543, 15740633, 15749728, 15758828, 15767934, 15777045, 15786161, 15795282, 15804408, 15813540, 15822677, 15831820, 15840967, 15850120, 15859279, 15868442, 15877611, 15886785, 15895965, 15905149, 15914339, 15923535, 15932735, 15941941, 15951153, 15960369, 15969591, 15978818, 15988051, 15997289, 16006532, 16015781, 16025035, 16034294, 16043559, 16052829, 16062104, 16071385, 16080671, 16089962, 16099259, 16108561, 16117869, 16127182, 16136500, 16145824, 16155153, 16164488, 16173828, 16183173, 16192523, 16201880, 16211241, 16220608, 16229980, 16239358, 16248741, 16258130, 16267524, 16276923, 16286328, 16295738, 16305154, 16314575, 16324002, 16333434, 16342871, 16352314, 16361763, 16371217, 16380676, 16390141, 16399611, 16409087, 16418568, 16428055, 16437547, 16447044, 16456548, 16466056, 16475570, 16485090, 16494615, 16504146, 16513682, 16523224, 16532771, 16542323, 16551882, 16561445, 16571015, 16580589, 16590170, 16599755, 16609347, 16618944, 16628546, 16638154, 16647768, 16657387, 16667012, 16676642, 16686278, 16695919, 16705566, 16715219, 16724877, 16734540 }; #endif unsigned long int freq_table[] = { 837201792, 837685632, 838169728, 838653568, 839138240, 839623232, 840108480, 840593984, 841079680, 841565184, 842051648, 842538240, 843025152, 843512320, 843999232, 844486976, 844975040, 845463360, 845951936, 846440320, 846929536, 847418944, 847908608, 848398656, 848888960, 849378944, 849869824, 850361024, 850852416, 851344192, 851835584, 852327872, 852820480, 853313280, 853806464, 854299328, 854793024, 855287040, 855781312, 856275904, 856770752, 857265344, 857760704, 858256448, 858752448, 859248704, 859744768, 860241600, 860738752, 861236160, 861733888, 862231360, 862729600, 863228160, 863727104, 864226176, 864725696, 865224896, 865724864, 866225152, 866725760, 867226688, 867727296, 868228736, 868730496, 869232576, 869734912, 870236928, 870739904, 871243072, 871746560, 872250368, 872754496, 873258240, 873762880, 874267840, 874773184, 875278720, 875783936, 876290112, 876796480, 877303232, 877810176, 878317504, 878824512, 879332416, 879840576, 880349056, 880857792, 881366272, 881875712, 882385280, 882895296, 883405440, 883915456, 884426304, 884937408, 885448832, 885960512, 886472512, 886984192, 887496768, 888009728, 888522944, 889036352, 889549632, 890063680, 890578048, 891092736, 891607680, 892122368, 892637952, 893153792, 893670016, 894186496, 894703232, 895219648, 895737024, 896254720, 896772672, 897290880, 897808896, 898327744, 898846912, 899366336, 899886144, 900405568, 900925952, 901446592, 901967552, 902488768, 903010368, 903531584, 904053760, 904576256, 905099008, 905622016, 906144896, 906668480, 907192512, 907716800, 908241408, 908765632, 909290816, 909816256, 910342144, 910868160, 911394624, 911920768, 912447680, 912975104, 913502720, 914030592, 914558208, 915086784, 915615552, 916144768, 916674176, 917203968, 917733440, 918263744, 918794496, 919325440, 919856704, 920387712, 920919616, 921451840, 921984320, 922517184, 923049728, 923583168, 924116928, 924651008, 925185344, 925720000, 926254336, 926789696, 927325312, 927861120, 928397440, 928933376, 929470208, 930007296, 930544768, 931082560, 931619968, 932158464, 932697152, 933236160, 933775488, 934315072, 934854464, 935394688, 935935296, 936476224, 937017344, 937558208, 938100160, 938642304, 939184640, 939727488, 940269888, 940813312, 941357056, 941900992, 942445440, 942990016, 943534400, 944079680, 944625280, 945171200, 945717440, 946263360, 946810176, 947357376, 947904832, 948452672, 949000192, 949548608, 950097280, 950646400, 951195776, 951745472, 952294912, 952845184, 953395904, 953946880, 954498176, 955049216, 955601088, 956153408, 956705920, 957258816, 957812032, 958364928, 958918848, 959472960, 960027456, 960582272, 961136768, 961692224, 962248000, 962804032, 963360448, 963916608, 964473600, 965031040, 965588736, 966146816, 966705152, 967263168, 967822144, 968381440, 968941120, 969501056, 970060736, 970621376, 971182272, 971743488, 972305088, 972866368, 973428608, 973991104, 974554048, 975117312, 975680768, 976243968, 976808192, 977372736, 977937536, 978502656, 979067584, 979633344, 980199488, 980765888, 981332736, 981899200, 982466688, 983034432, 983602624, 984171008, 984739776, 985308160, 985877632, 986447360, 987017472, 987587904, 988157952, 988729088, 989300416, 989872192, 990444224, 991016000, 991588672, 992161728, 992735168, 993308864, 993882880, 994456576, 995031296, 995606336, 996181696, 996757440, 997332800, 997909184, 998485888, 999062912, 999640256, 1000217984, 1000795392, 1001373696, 1001952448, 1002531520, 1003110848, 1003689920, 1004270016, 1004850304, 1005431040, 1006012160, 1006592832, 1007174592, 1007756608, 1008339008, 1008921792, 1009504768, 1010087552, 1010671296, 1011255360, 1011839808, 1012424576, 1013009024, 1013594368, 1014180160, 1014766272, 1015352768, 1015938880, 1016526016, 1017113472, 1017701248, 1018289408, 1018877824, 1019465984, 1020055104, 1020644672, 1021234496, 1021824768, 1022414528, 1023005440, 1023596608, 1024188160, 1024780096, 1025371584, 1025964160, 1026557120, 1027150336, 1027744000, 1028337920, 1028931520, 1029526144, 1030121152, 1030716480, 1031312128, 1031907456, 1032503808, 1033100480, 1033697536, 1034294912, 1034892032, 1035490048, 1036088512, 1036687232, 1037286336, 1037885824, 1038484928, 1039085056, 1039685632, 1040286464, 1040887680, 1041488448, 1042090368, 1042692608, 1043295168, 1043898176, 1044501440, 1045104384, 1045708288, 1046312640, 1046917376, 1047522368, 1048127040, 1048732800, 1049338816, 1049945280, 1050552128, 1051158528, 1051765952, 1052373824, 1052982016, 1053590592, 1054199424, 1054807936, 1055417600, 1056027456, 1056637760, 1057248448, 1057858752, 1058470016, 1059081728, 1059693824, 1060306304, 1060918336, 1061531392, 1062144896, 1062758656, 1063372928, 1063987392, 1064601664, 1065216896, 1065832448, 1066448448, 1067064704, 1067680704, 1068297728, 1068915136, 1069532864, 1070150976, 1070768640, 1071387520, 1072006720, 1072626240, 1073246080, 1073866368, 1074486272, 1075107200, 1075728512, 1076350208, 1076972160, 1077593856, 1078216704, 1078839680, 1079463296, 1080087040, 1080710528, 1081335168, 1081960064, 1082585344, 1083211008, 1083836928, 1084462592, 1085089280, 1085716352, 1086343936, 1086971648, 1087599104, 1088227712, 1088856576, 1089485824, 1090115456, 1090745472, 1091375104, 1092005760, 1092636928, 1093268352, 1093900160, 1094531584, 1095164160, 1095796992, 1096430336, 1097064064, 1097697280, 1098331648, 1098966400, 1099601536, 1100237056, 1100872832, 1101508224, 1102144768, 1102781824, 1103419136, 1104056832, 1104694144, 1105332608, 1105971328, 1106610432, 1107249920, 1107889152, 1108529408, 1109170048, 1109811072, 1110452352, 1111094144, 1111735552, 1112377984, 1113020928, 1113664128, 1114307712, 1114950912, 1115595264, 1116240000, 1116885120, 1117530624, 1118175744, 1118821888, 1119468416, 1120115456, 1120762752, 1121410432, 1122057856, 1122706176, 1123355136, 1124004224, 1124653824, 1125303040, 1125953408, 1126604160, 1127255168, 1127906560, 1128557696, 1129209984, 1129862528, 1130515456, 1131168768, 1131822592, 1132475904, 1133130368, 1133785216, 1134440448, 1135096064, 1135751296, 1136407680, 1137064448, 1137721472, 1138379008, 1139036800, 1139694336, 1140353024, 1141012096, 1141671424, 1142331264, 1142990592, 1143651200, 1144312192, 1144973440, 1145635200, 1146296448, 1146958976, 1147621760, 1148285056, 1148948608, 1149612672, 1150276224, 1150940928, 1151606144, 1152271616, 1152937600, 1153603072, 1154269824, 1154936832, 1155604352, 1156272128, 1156939648, 1157608192, 1158277248, 1158946560, 1159616384, 1160286464, 1160956288, 1161627264, 1162298624, 1162970240, 1163642368, 1164314112, 1164987008, 1165660160, 1166333824, 1167007872, 1167681536, 1168356352, 1169031552, 1169707136, 1170383104, 1171059584, 1171735552, 1172412672, 1173090304, 1173768192, 1174446592, 1175124480, 1175803648, 1176483072, 1177163008, 1177843328, 1178523264, 1179204352, 1179885824, 1180567680, 1181249920, 1181932544, 1182614912, 1183298304, 1183982208, 1184666368, 1185351040, 1186035328, 1186720640, 1187406464, 1188092672, 1188779264, 1189466368, 1190152960, 1190840832, 1191528960, 1192217600, 1192906624, 1193595136, 1194285056, 1194975232, 1195665792, 1196356736, 1197047296, 1197739136, 1198431360, 1199123968, 1199816960, 1200510336, 1201203328, 1201897600, 1202592128, 1203287040, 1203982464, 1204677504, 1205373696, 1206070272, 1206767232, 1207464704, 1208161664, 1208859904, 1209558528, 1210257536, 1210956928, 1211656832, 1212356224, 1213056768, 1213757952, 1214459392, 1215161216, 1215862656, 1216565376, 1217268352, 1217971840, 1218675712, 1219379200, 1220083840, 1220788992, 1221494528, 1222200448, 1222906752, 1223612672, 1224319872, 1225027456, 1225735424, 1226443648, 1227151616, 1227860864, 1228570496, 1229280512, 1229990912, 1230700928, 1231412096, 1232123776, 1232835840, 1233548288, 1234261248, 1234973696, 1235687424, 1236401536, 1237116032, 1237831040, 1238545536, 1239261312, 1239977472, 1240694144, 1241411072, 1242128512, 1242845568, 1243563776, 1244282496, 1245001600, 1245721088, 1246440192, 1247160448, 1247881216, 1248602368, 1249324032, 1250045184, 1250767616, 1251490432, 1252213632, 1252937344, 1253661440, 1254385152, 1255110016, 1255835392, 1256561152, 1257287424, 1258013184, 1258740096, 1259467648, 1260195456, 1260923648, 1261651584, 1262380800, 1263110272, 1263840256, 1264570624, 1265301504, 1266031872, 1266763520, 1267495552, 1268227968, 1268961024, 1269693440, 1270427264, 1271161472, 1271896064, 1272631168, 1273365760, 1274101632, 1274838016, 1275574784, 1276311808, 1277049472, 1277786624, 1278525056, 1279264000, 1280003328, 1280743040, 1281482368, 1282222976, 1282963968, 1283705344, 1284447232, 1285188736, 1285931392, 1286674560, 1287418240, 1288162176, 1288906624, 1289650688, 1290395904, 1291141760, 1291887872, 1292634496, 1293380608, 1294128128, 1294875904, 1295624320, 1296373120, 1297122304, 1297870976, 1298621056, 1299371520, 1300122496, 1300873856, 1301624832, 1302376960, 1303129600, 1303882752, 1304636288, 1305389312, 1306143872, 1306898688, 1307654016, 1308409600, 1309165696, 1309921536, 1310678528, 1311435904, 1312193920, 1312952192, 1313710080, 1314469248, 1315228928, 1315988992, 1316749568, 1317509632, 1318271104, 1319032960, 1319795200, 1320557952, 1321321088, 1322083840, 1322847872, 1323612416, 1324377216, 1325142656, 1325907584, 1326673920, 1327440512, 1328207744, 1328975360, 1329742464, 1330510976, 1331279872, 1332049152, 1332819072, 1333589248, 1334359168, 1335130240, 1335901824, 1336673920, 1337446400, 1338218368, 1338991744, 1339765632, 1340539904, 1341314560, 1342088832, 1342864512, 1343640576, 1344417024, 1345193984, 1345971456, 1346748416, 1347526656, 1348305408, 1349084672, 1349864320, 1350643456, 1351424000, 1352205056, 1352986496, 1353768448, 1354550784, 1355332608, 1356115968, 1356899712, 1357683840, 1358468480, 1359252608, 1360038144, 1360824192, 1361610624, 1362397440, 1363183872, 1363971712, 1364760064, 1365548672, 1366337792, 1367127424, 1367916672, 1368707200, 1369498240, 1370289664, 1371081472, 1371873024, 1372665856, 1373459072, 1374252800, 1375047040, 1375840768, 1376635904, 1377431552, 1378227584, 1379024000, 1379820928, 1380617472, 1381415296, 1382213760, 1383012480, 1383811840, 1384610560, 1385410816, 1386211456, 1387012480, 1387814144, 1388615168, 1389417728, 1390220672, 1391024128, 1391827968, 1392632320, 1393436288, 1394241536, 1395047296, 1395853568, 1396660224, 1397466368, 1398274048, 1399082112, 1399890688, 1400699648, 1401508224, 1402318080, 1403128576, 1403939456, 1404750848, 1405562624, 1406374016, 1407186816, 1408000000, 1408813696, 1409627904, 1410441728, 1411256704, 1412072320, 1412888320, 1413704960, 1414521856, 1415338368, 1416156288, 1416974720, 1417793664, 1418612992, 1419431808, 1420252160, 1421072896, 1421894144, 1422715904, 1423537280, 1424359808, 1425183104, 1426006784, 1426830848, 1427655296, 1428479488, 1429305088, 1430131072, 1430957568, 1431784576, 1432611072, 1433438976, 1434267392, 1435096192, 1435925632, 1436754432, 1437584768, 1438415616, 1439246848, 1440078720, 1440910848, 1441742720, 1442575872, 1443409664, 1444243584, 1445078400, 1445912576, 1446748032, 1447584256, 1448420864, 1449257856, 1450094464, 1450932480, 1451771008, 1452609920, 1453449472, 1454289408, 1455128960, 1455969920, 1456811264, 1457653248, 1458495616, 1459337600, 1460180864, 1461024768, 1461869056, 1462713984, 1463558272, 1464404096, 1465250304, 1466097152, 1466944384, 1467792128, 1468639488, 1469488256, 1470337408, 1471187200, 1472037376, 1472887168, 1473738368, 1474589952, 1475442304, 1476294912, 1477148160, 1478000768, 1478854912, 1479709696, 1480564608, 1481420288, 1482275456, 1483132160, 1483989248, 1484846976, 1485704960, 1486562688, 1487421696, 1488281344, 1489141504, 1490002048, 1490863104, 1491723776, 1492585856, 1493448448, 1494311424, 1495175040, 1496038144, 1496902656, 1497767808, 1498633344, 1499499392, 1500365056, 1501232128, 1502099712, 1502967808, 1503836416, 1504705536, 1505574016, 1506444032, 1507314688, 1508185856, 1509057408, 1509928576, 1510801280, 1511674240, 1512547840, 1513421952, 1514295680, 1515170816, 1516046464, 1516922624, 1517799296, 1518676224, 1519552896, 1520431104, 1521309824, 1522188928, 1523068800, 1523948032, 1524828672, 1525709824, 1526591616, 1527473792, 1528355456, 1529238784, 1530122496, 1531006720, 1531891712, 1532776832, 1533661824, 1534547968, 1535434880, 1536322304, 1537210112, 1538097408, 1538986368, 1539875840, 1540765696, 1541656192, 1542547072, 1543437440, 1544329472, 1545221888, 1546114944, 1547008384, 1547901440, 1548796032, 1549691136, 1550586624, 1551482752, 1552378368, 1553275520, 1554173184, 1555071232, 1555970048, 1556869248, 1557767936, 1558668288, 1559568896, 1560470272, 1561372032, 1562273408, 1563176320, 1564079616, 1564983424, 1565888000, 1566791808, 1567697408, 1568603392, 1569509760, 1570416896, 1571324416, 1572231424, 1573140096, 1574049152, 1574958976, 1575869184, 1576778752, 1577689984, 1578601728, 1579514112, 1580426880, 1581339264, 1582253056, 1583167488, 1584082432, 1584997888, 1585913984, 1586829440, 1587746304, 1588663936, 1589582080, 1590500736, 1591418880, 1592338560, 1593258752, 1594179584, 1595100928, 1596021632, 1596944000, 1597866880, 1598790272, 1599714304, 1600638848, 1601562752, 1602488320, 1603414272, 1604340992, 1605268224, 1606194816, 1607123072, 1608051968, 1608981120, 1609911040, 1610841344, 1611771264, 1612702848, 1613634688, 1614567168, 1615500288, 1616432896, 1617367040, 1618301824, 1619237120, 1620172800, 1621108096, 1622044928, 1622982272, 1623920128, 1624858752, 1625797632, 1626736256, 1627676416, 1628616960, 1629558272, 1630499968, 1631441152, 1632384000, 1633327232, 1634271232, 1635215744, 1636159744, 1637105152, 1638051328, 1638998016, 1639945088, 1640892928, 1641840128, 1642788992, 1643738368, 1644688384, 1645638784, 1646588672, 1647540352, 1648492416, 1649445120, 1650398464, 1651351168, 1652305408, 1653260288, 1654215808, 1655171712, 1656128256, 1657084288, 1658041856, 1659000064, 1659958784, 1660918272, 1661876992, 1662837376, 1663798400, 1664759936, 1665721984, 1666683520, 1667646720, 1668610560, 1669574784, 1670539776, 1671505024, 1672470016, 1673436544, }; #define SAMPLE_16BIT 0x01 #define SAMPLE_UNSIGNED 0x02 #define SAMPLE_LOOP 0x04 #define SAMPLE_PINGPONG 0x08 #define SAMPLE_REVERSE 0x10 #define SAMPLE_SUSTAIN 0x20 #define SAMPLE_ENVELOPE 0x40 #ifdef DEBUG_SAMPLES #define SAMPLE_CONVERT_DEBUG(dx) printf("\r%s\n",dx) #else #define SAMPLE_CONVERT_DEBUG(dx) #endif #ifdef DEBUG_MIDI #define MIDI_EVENT_DEBUG(dx,dy) printf("\r%s, %x\n",dx,dy) #else #define MIDI_EVENT_DEBUG(dx,dy) #endif #define WM_ERR_MEM 0 #define WM_ERR_STAT 1 #define WM_ERR_LOAD 2 #define WM_ERR_OPEN 3 #define WM_ERR_READ 4 #define WM_ERR_INVALID 5 #define WM_ERR_CORUPT 6 #define WM_ERR_NOT_INIT 7 #define WM_ERR_INVALID_ARG 8 #define MAX_AUTO_AMP 2.0 #define FPBITS 10 #define FPMASK ((1L<pw_dir; } else { home = getenv ("HOME"); } if (home) { buffer_file = realloc(buffer_file,(strlen(buffer_file) + strlen(home) + 1)); if (buffer_file == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, errno); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, errno); free(buffer_file); return NULL; } memmove((buffer_file + strlen(home)), (buffer_file + 1), (strlen(buffer_file))); strncpy (buffer_file, home,strlen(home)); } } else if (buffer_file[0] != '/') { char *res = getcwd(buffer_dir,1024); if (buffer_dir[strlen(buffer_dir)-1] != '/') { buffer_dir[strlen(buffer_dir)+1] = '\0'; buffer_dir[strlen(buffer_dir)] = '/'; } buffer_file = realloc(buffer_file,(strlen(buffer_file) + strlen(buffer_dir) + 1)); if (buffer_file == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, errno); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, errno); free(buffer_file); return NULL; } memmove((buffer_file + strlen(buffer_dir)), buffer_file, strlen(buffer_file)+1); strncpy (buffer_file,buffer_dir,strlen(buffer_dir)); } #endif if (stat(buffer_file,&buffer_stat)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_STAT, filename, errno); free(buffer_file); return NULL; } *size = buffer_stat.st_size; data = malloc(*size); if (data == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, errno); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, errno); free(buffer_file); return NULL; } #ifdef _WIN32 if ((buffer_fd = open(buffer_file,(O_RDONLY | O_BINARY))) == -1) { #else if ((buffer_fd = open(buffer_file,O_RDONLY)) == -1) { #endif WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_OPEN, filename, errno); free(buffer_file); free(data); return NULL; } if (read(buffer_fd,data,*size) != buffer_stat.st_size) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_READ, filename, errno); free(buffer_file); free(data); close(buffer_fd); return NULL; } close(buffer_fd); free(buffer_file); return data; } static inline void WM_Lock (int * wmlock) { LOCK_START: if (__builtin_expect(((*wmlock) == 0),1)) { (*wmlock)++; if (__builtin_expect(((*wmlock) == 1), 1)) { return; } (*wmlock)--; } #ifdef _WIN32 Sleep(10); #else usleep(500); #endif goto LOCK_START; } static inline void WM_Unlock (int *wmlock) { (*wmlock)--; } void WM_InitPatches ( void ) { int i; for (i = 0; i < 128; i++) { patch[i] = NULL; } } void WM_FreePatches ( void ) { int i; struct _patch * tmp_patch; struct _sample * tmp_sample; WM_Lock(&patch_lock); for (i = 0; i < 128; i++) { if (patch[i] != NULL) { while (patch[i] != NULL) { if (patch[i]->filename != NULL) { if (patch[i]->first_sample != NULL) { while (patch[i]->first_sample != NULL) { tmp_sample = patch[i]->first_sample->next; if (patch[i]->first_sample->data != NULL) free (patch[i]->first_sample->data); free (patch[i]->first_sample); patch[i]->first_sample = tmp_sample; } } free (patch[i]->filename); } tmp_patch = patch[i]->next; free(patch[i]); patch[i] = tmp_patch; } } } WM_Unlock(&patch_lock); } int WM_LoadConfig (const char *config_file, const char *top_config_dir) { unsigned long int config_size = 0; unsigned char *config_buffer = NULL; char * dir_end = NULL; char * config_dir = NULL; unsigned long int config_ptr = 0; unsigned long int line_start_ptr = 0; char * line_buffer = NULL; unsigned long int line_ptr = 0; char * chr_ptr = NULL; unsigned short int patchid = 0; char * new_config = NULL; struct _patch * tmp_patch; if ((config_buffer = WM_BufferFile(config_file, &config_size)) == NULL) { return -1; } if (top_config_dir) { config_dir = strdup (top_config_dir); } if (config_buffer == NULL) { WM_FreePatches(); if (config_dir) { free (config_dir); } return -1; } if (!config_dir) { dir_end = strrchr(config_file,'/'); if (dir_end != NULL) { config_dir = malloc((dir_end - config_file + 2) + 4); if (config_dir == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse config", errno); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); free (config_buffer); return -1; } strncpy(config_dir, config_file, (dir_end - config_file + 1)); config_dir[dir_end - config_file + 1] = '\0'; } } config_ptr = 0; line_start_ptr = 0; while (config_ptr < config_size) { // find end of line if (config_buffer[config_ptr] != '\n') { // remove unwanted crud if (config_buffer[config_ptr] == '\t') { config_buffer[config_ptr] = ' '; } else if (config_buffer[config_ptr] == '\r') { config_buffer[config_ptr] = ' '; } if ((config_buffer[config_ptr] == ' ') && (config_ptr == line_start_ptr)) { line_start_ptr++; } config_ptr++; continue; } config_buffer[config_ptr] = '\0'; if (config_ptr == line_start_ptr) { config_ptr++; line_start_ptr++; continue; } if (config_buffer[line_start_ptr] == '#') { config_ptr++; line_start_ptr = config_ptr; continue; } // copy line into a workable buffer line_buffer = realloc(line_buffer, (config_ptr - line_start_ptr + 1) + 4); if (line_buffer == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse config", errno); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); if (config_dir != NULL) free(config_dir); free (config_buffer); return -1; } strcpy(line_buffer, &config_buffer[line_start_ptr]); config_ptr++; line_start_ptr = config_ptr; // remove unwnted crud from line for easier parsing if ((chr_ptr = strstr(line_buffer," ")) != NULL) { while ((chr_ptr = strstr(line_buffer," ")) != NULL) { memmove(chr_ptr, &chr_ptr[1], strlen(chr_ptr)); } } if ((chr_ptr = strchr(line_buffer, '#')) != NULL) { *chr_ptr = '\0'; } if (line_buffer[strlen(line_buffer) -1] == ' ') { while (line_buffer[strlen(line_buffer) -1] == ' ') { line_buffer[strlen(line_buffer) -1] = '\0'; } } // now parse line if (strncasecmp(line_buffer, "dir ", 4) == 0) { if (line_buffer[strlen(line_buffer) - 1] == '/') { config_dir = realloc(config_dir, strlen(&line_buffer[4]) + 1 + 4); if (config_dir == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse config", errno); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); free (line_buffer); free (config_buffer); return -1; } strcpy(config_dir, &line_buffer[4]); } else { config_dir = realloc(config_dir, strlen(&line_buffer[4]) + 2 + 4); if (config_dir == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse config", errno); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); free (line_buffer); free (config_buffer); return -1; } strcpy(config_dir, &line_buffer[4]); strcat(config_dir,"/"); } continue; } else if (strncasecmp(line_buffer, "source ", 7) == 0) { if (config_dir != NULL && line_buffer[7] != '/') { new_config = malloc(strlen(config_dir) + strlen(&line_buffer[7]) + 1 + 4); if (new_config == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse config", errno); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); free (config_dir); free (line_buffer); free (config_buffer); return -1; } strcpy(new_config,config_dir); strcpy(&new_config[strlen(config_dir)], &line_buffer[7]); } else { new_config = malloc(strlen(&line_buffer[7]) + 1 + 4); if (new_config == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse config", errno); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); free (line_buffer); free (config_buffer); return -1; } strcpy(new_config, &line_buffer[7]); } if (WM_LoadConfig(new_config, config_dir) == -1) { free (new_config); free (line_buffer); free (config_buffer); //if (config_dir != NULL) // free (config_dir); return -1; } free (new_config); continue; } else if (strncasecmp(line_buffer, "bank ", 5) == 0) { if (!isdigit(line_buffer[5])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in bank line)", 0); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); if (config_dir != NULL) free (config_dir); free (line_buffer); free (config_buffer); return -1; } patchid = (atoi(&line_buffer[5]) & 0xFF ) << 8; continue; } else if (strncasecmp(line_buffer, "drumset ", 8) == 0) { if (!isdigit(line_buffer[8])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in drumset line)", 0); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); if (config_dir != NULL) free (config_dir); free (line_buffer); free (config_buffer); return -1; } patchid = ((atoi(&line_buffer[8]) & 0xFF ) << 8) | 0x80; continue; } else if (isdigit(line_buffer[0])) { patchid = (patchid & 0xFF80) | (atoi(line_buffer) & 0x7F); if (patch[(patchid & 0x7F)] == NULL) { patch[(patchid & 0x7F)] = malloc (sizeof(struct _patch)); if (patch[(patchid & 0x7F)] == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, errno); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); if (config_dir != NULL) free (config_dir); free (line_buffer); free (config_buffer); return -1; } tmp_patch = patch[(patchid & 0x7F)]; tmp_patch->patchid = patchid; tmp_patch->filename = NULL; tmp_patch->amp = 1024; tmp_patch->note = 0; tmp_patch->next = NULL; tmp_patch->first_sample = NULL; tmp_patch->loaded = 0; tmp_patch->inuse_count = 0; } else { tmp_patch = patch[(patchid & 0x7F)]; if (tmp_patch->patchid == patchid) { free (tmp_patch->filename); tmp_patch->filename = NULL; tmp_patch->amp = 1024; tmp_patch->note = 0; } else { if (tmp_patch->next != NULL) { while (tmp_patch->next != NULL) { if (tmp_patch->next->patchid == patchid) break; tmp_patch = tmp_patch->next; } if (tmp_patch->next == NULL) { tmp_patch->next = malloc (sizeof(struct _patch)); if (tmp_patch->next == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, 0); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); if (config_dir != NULL) free (config_dir); free (line_buffer); free (config_buffer); return -1; } tmp_patch = tmp_patch->next; tmp_patch->patchid = patchid; tmp_patch->filename = NULL; tmp_patch->amp = 1024; tmp_patch->note = 0; tmp_patch->next = NULL; tmp_patch->first_sample = NULL; tmp_patch->loaded = 0; tmp_patch->inuse_count = 0; } else { tmp_patch = tmp_patch->next; free (tmp_patch->filename); tmp_patch->filename = NULL; tmp_patch->amp = 1024; tmp_patch->note = 0; } } else { tmp_patch->next = malloc (sizeof(struct _patch)); if (tmp_patch->next == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, errno); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); if (config_dir != NULL) free (config_dir); free (line_buffer); free (config_buffer); return -1; } tmp_patch = tmp_patch->next; tmp_patch->patchid = patchid; tmp_patch->filename = NULL; tmp_patch->amp = 1024; tmp_patch->note = 0; tmp_patch->next = NULL; tmp_patch->first_sample = NULL; tmp_patch->loaded = 0; tmp_patch->inuse_count = 0; } } } chr_ptr = strchr(line_buffer,' ') + 1; if (chr_ptr == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); if (config_dir != NULL) free (config_dir); free (line_buffer); free (config_buffer); return -1; } line_ptr = chr_ptr - line_buffer; chr_ptr = strchr(&line_buffer[line_ptr],' '); if (chr_ptr != NULL) { *chr_ptr = '\0'; } if (strncasecmp(&line_buffer[(line_ptr + strlen(&line_buffer[line_ptr]) - 5)], ".pat", 4) != 0, 0) { if (config_dir != NULL) { tmp_patch->filename = malloc(strlen(config_dir) + strlen(&line_buffer[line_ptr]) + 5); if (tmp_patch->filename == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, 0); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); if (config_dir != NULL) free (config_dir); free (line_buffer); free (config_buffer); return -1; } strcpy(tmp_patch->filename, config_dir); strcat(tmp_patch->filename, &line_buffer[line_ptr]); } else { tmp_patch->filename = malloc(strlen(&line_buffer[line_ptr]) + 5); if (tmp_patch->filename == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, 0); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); free (line_buffer); free (config_buffer); return -1; } strcpy(tmp_patch->filename, &line_buffer[line_ptr]); } strcat(tmp_patch->filename, ".pat"); } else { if (config_dir != NULL) { tmp_patch->filename = malloc(strlen(config_dir) + strlen(&line_buffer[line_ptr]) + 1); if (tmp_patch->filename == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, 0); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); if (config_dir != NULL) free (config_dir); free (line_buffer); free (config_buffer); return -1; } strcpy(tmp_patch->filename, config_dir); strcat(tmp_patch->filename, &line_buffer[line_ptr]); } else { tmp_patch->filename = malloc(strlen(&line_buffer[line_ptr]) + 1); if (tmp_patch->filename == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, 0); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); WM_FreePatches(); free (line_buffer); free (config_buffer); return -1; } strcpy(tmp_patch->filename, &line_buffer[line_ptr]); } } tmp_patch->env[0].set = 0x00; tmp_patch->env[1].set = 0x00; tmp_patch->env[2].set = 0x00; tmp_patch->env[3].set = 0x00; tmp_patch->env[4].set = 0x00; tmp_patch->env[5].set = 0x00; tmp_patch->keep = 0; tmp_patch->remove = 0; if (chr_ptr != NULL) { line_ptr = chr_ptr - line_buffer + 1; chr_ptr = strstr(&line_buffer[line_ptr], "amp="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[4])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->amp = ((atoi(&chr_ptr[4]) << 10) / 100); } } chr_ptr = strstr(&line_buffer[line_ptr], "note="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[5])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->note = atoi(&chr_ptr[5]); } } chr_ptr = strstr(&line_buffer[line_ptr], "keep=loop"); if (chr_ptr != NULL) { tmp_patch->keep |= SAMPLE_LOOP; } chr_ptr = strstr(&line_buffer[line_ptr], "keep=env"); if (chr_ptr != NULL) { tmp_patch->keep |= SAMPLE_ENVELOPE; } chr_ptr = strstr(&line_buffer[line_ptr], "remove=sustain"); if (chr_ptr != NULL) { tmp_patch->remove |= SAMPLE_SUSTAIN; } chr_ptr = strstr(&line_buffer[line_ptr], "env_time0="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[10])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->env[0].time = atof(&chr_ptr[10]); if ((tmp_patch->env[0].time > 45000.0) || (tmp_patch->env[0].time < 1.47)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(range error in patch line)", 0); tmp_patch->env[0].set &= 0xFE; } else { tmp_patch->env[0].set |= 0x01; } } } chr_ptr = strstr(&line_buffer[line_ptr], "env_time1="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[10])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->env[1].time = atof(&chr_ptr[10]); if ((tmp_patch->env[1].time > 45000.0) || (tmp_patch->env[1].time < 1.47)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(range error in patch line)", 0); tmp_patch->env[1].set &= 0xFE; } else { tmp_patch->env[1].set |= 0x01; } } } chr_ptr = strstr(&line_buffer[line_ptr], "env_time2="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[10])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->env[2].time = atof(&chr_ptr[10]); if ((tmp_patch->env[2].time > 45000.0) || (tmp_patch->env[2].time < 1.47)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(range error in patch line)", 0); tmp_patch->env[2].set &= 0xFE; } else { tmp_patch->env[2].set |= 0x01; } } } chr_ptr = strstr(&line_buffer[line_ptr], "env_time3="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[10])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->env[3].time = atof(&chr_ptr[10]); if ((tmp_patch->env[3].time > 45000.0) || (tmp_patch->env[3].time < 1.47)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(range error in patch line)", 0); tmp_patch->env[3].set &= 0xFE; } else { tmp_patch->env[3].set |= 0x01; } } } chr_ptr = strstr(&line_buffer[line_ptr], "env_time4="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[10])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->env[4].time = atof(&chr_ptr[10]); if ((tmp_patch->env[4].time > 45000.0) || (tmp_patch->env[4].time < 1.47)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(range error in patch line)", 0); tmp_patch->env[4].set &= 0xFE; } else { tmp_patch->env[4].set |= 0x01; } } } chr_ptr = strstr(&line_buffer[line_ptr], "env_time5="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[10])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->env[5].time = atof(&chr_ptr[10]); if ((tmp_patch->env[5].time > 45000.0) || (tmp_patch->env[5].time < 1.47)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(range error in patch line)", 0); tmp_patch->env[5].set &= 0xFE; } else { tmp_patch->env[5].set |= 0x01; } } } chr_ptr = strstr(&line_buffer[line_ptr], "env_level0="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[11])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->env[0].level = atof(&chr_ptr[10]); if ((tmp_patch->env[0].level > 1.0) || (tmp_patch->env[0].level < 0.0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(range error in patch line)", 0); tmp_patch->env[0].set &= 0xFD; } else { tmp_patch->env[0].set |= 0x02; } } } chr_ptr = strstr(&line_buffer[line_ptr], "env_level1="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[11])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->env[1].level = atof(&chr_ptr[10]); if ((tmp_patch->env[1].level > 1.0) || (tmp_patch->env[1].level < 0.0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(range error in patch line)", 0); tmp_patch->env[1].set &= 0xFD; } else { tmp_patch->env[1].set |= 0x02; } } } chr_ptr = strstr(&line_buffer[line_ptr], "env_level2="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[11])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->env[2].level = atof(&chr_ptr[10]); if ((tmp_patch->env[2].level > 1.0) || (tmp_patch->env[2].level < 0.0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(range error in patch line)", 0); tmp_patch->env[2].set &= 0xFD; } else { tmp_patch->env[2].set |= 0x02; } } } chr_ptr = strstr(&line_buffer[line_ptr], "env_level3="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[11])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->env[3].level = atof(&chr_ptr[10]); if ((tmp_patch->env[3].level > 1.0) || (tmp_patch->env[3].level < 0.0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(range error in patch line)", 0); tmp_patch->env[3].set &= 0xFD; } else { tmp_patch->env[3].set |= 0x02; } } } chr_ptr = strstr(&line_buffer[line_ptr], "env_level4="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[11])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->env[4].level = atof(&chr_ptr[10]); if ((tmp_patch->env[4].level > 1.0) || (tmp_patch->env[4].level < 0.0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(range error in patch line)", 0); tmp_patch->env[4].set &= 0xFD; } else { tmp_patch->env[4].set |= 0x02; } } } chr_ptr = strstr(&line_buffer[line_ptr], "env_level5="); if (chr_ptr != NULL) { if (!isdigit(chr_ptr[11])) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(syntax error in patch line)", 0); } else { tmp_patch->env[5].level = atof(&chr_ptr[10]); if ((tmp_patch->env[5].level > 1.0) || (tmp_patch->env[5].level < 0.0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(range error in patch line)", 0); tmp_patch->env[5].set &= 0xFD; } else { tmp_patch->env[5].set |= 0x02; } } } } } } if (line_buffer != NULL) free (line_buffer); free (config_buffer); if (config_dir != NULL) free (config_dir); return 0; } /* * sample data conversion functions * convert data to signed shorts */ /* 8bit signed */ int convert_8s (unsigned char *data, struct _sample *gus_sample ) { unsigned char *read_data = data; unsigned char *read_end = data + gus_sample->data_length; signed short int *write_data = NULL; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc((gus_sample->data_length + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data; do { *write_data = (*read_data++) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data != read_end); return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 8bit signed ping pong */ int convert_8sp (unsigned char *data, struct _sample *gus_sample ) { unsigned long int loop_length = gus_sample->loop_end - gus_sample->loop_start; unsigned long int dloop_length = loop_length * 2; unsigned long int new_length = gus_sample->data_length + dloop_length; unsigned char *read_data = data; unsigned char *read_end = data + gus_sample->loop_start; signed short int *write_data = NULL; signed short int *write_data_a = NULL; signed short int *write_data_b = NULL; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc((new_length + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data; do { *write_data = (*read_data++) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data != read_end); *write_data = (*read_data++ << 8); write_data_a = write_data + dloop_length; *write_data_a-- = *write_data; write_data++; write_data_b = write_data + dloop_length; read_end = data + gus_sample->loop_end; do { *write_data = (*read_data++) << 8; *write_data_a-- = *write_data; *write_data_b++ = *write_data; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data != read_end); *write_data = (*read_data++ << 8); *write_data_b++ = *write_data; read_end = data + gus_sample->data_length; if (__builtin_expect((read_data != read_end),1)) { do { *write_data_b = (*read_data++) << 8; if (*write_data_b > gus_sample->max_peek) { gus_sample->max_peek = *write_data_b; } else if (*write_data_b < gus_sample->min_peek) { gus_sample->min_peek = *write_data_b; } write_data_b++; } while (read_data != read_end); } gus_sample->loop_start += loop_length; gus_sample->loop_end += dloop_length; gus_sample->data_length = new_length; gus_sample->modes ^= SAMPLE_PINGPONG; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 8bit signed reverse */ int convert_8sr (unsigned char *data, struct _sample *gus_sample ) { unsigned char *read_data = data; unsigned char *read_end = data + gus_sample->data_length; signed short int *write_data = NULL; unsigned long int tmp_loop = 0; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc((gus_sample->data_length + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data + gus_sample->data_length - 1; do { *write_data = (*read_data++) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data--; } while (read_data != read_end); tmp_loop = gus_sample->loop_end; gus_sample->loop_end = gus_sample->data_length - gus_sample->loop_start; gus_sample->loop_start = gus_sample->data_length - tmp_loop; gus_sample->loop_fraction = ((gus_sample->loop_fraction & 0x0f) << 4) | ((gus_sample->loop_fraction & 0xf0) >> 4); gus_sample->modes ^= SAMPLE_REVERSE; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 8bit signed reverse ping pong */ int convert_8srp (unsigned char *data, struct _sample *gus_sample ) { unsigned long int loop_length = gus_sample->loop_end - gus_sample->loop_start; unsigned long int dloop_length = loop_length * 2; unsigned long int new_length = gus_sample->data_length + dloop_length; unsigned char *read_data = data + gus_sample->data_length - 1; unsigned char *read_end = data + gus_sample->loop_end; signed short int *write_data = NULL; signed short int *write_data_a = NULL; signed short int *write_data_b = NULL; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc((new_length + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data; do { *write_data = (*read_data--) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data != read_end); *write_data = (*read_data-- << 8); write_data_a = write_data + dloop_length; *write_data_a-- = *write_data; write_data++; write_data_b = write_data + dloop_length; read_end = data + gus_sample->loop_start; do { *write_data = (*read_data--) << 8; *write_data_a-- = *write_data; *write_data_b++ = *write_data; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data != read_end); *write_data = (*read_data-- << 8); *write_data_b++ = *write_data; read_end = data - 1; do { *write_data_b = (*read_data--) << 8; if (*write_data_b > gus_sample->max_peek) { gus_sample->max_peek = *write_data_b; } else if (*write_data_b < gus_sample->min_peek) { gus_sample->min_peek = *write_data_b; } write_data_b++; } while (read_data != read_end); gus_sample->loop_start += loop_length; gus_sample->loop_end += dloop_length; gus_sample->data_length = new_length; gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_REVERSE; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 8bit unsigned */ int convert_8u (unsigned char *data, struct _sample *gus_sample ) { unsigned char *read_data = data; unsigned char *read_end = data + gus_sample->data_length; signed short int *write_data = NULL; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc((gus_sample->data_length + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data; do { *write_data = ((*read_data++) ^ 0x80) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data != read_end); gus_sample->modes ^= SAMPLE_UNSIGNED; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 8bit unsigned ping pong */ int convert_8up (unsigned char *data, struct _sample *gus_sample ) { unsigned long int loop_length = gus_sample->loop_end - gus_sample->loop_start; unsigned long int dloop_length = loop_length * 2; unsigned long int new_length = gus_sample->data_length + dloop_length; unsigned char *read_data = data; unsigned char *read_end = data + gus_sample->loop_start; signed short int *write_data = NULL; signed short int *write_data_a = NULL; signed short int *write_data_b = NULL; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc((new_length + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data; do { *write_data = ((*read_data++) ^ 0x80) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data != read_end); *write_data = ((*read_data++) ^ 0x80) << 8; write_data_a = write_data + dloop_length; *write_data_a-- = *write_data; write_data++; write_data_b = write_data + dloop_length; read_end = data + gus_sample->loop_end; do { *write_data = ((*read_data++) ^ 0x80) << 8; *write_data_a-- = *write_data; *write_data_b++ = *write_data; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data != read_end); *write_data = ((*read_data++) ^ 0x80) << 8; *write_data_b++ = *write_data; read_end = data + gus_sample->data_length; if (__builtin_expect((read_data != read_end),1)) { do { *write_data_b = ((*read_data++) ^ 0x80) << 8; if (*write_data_b > gus_sample->max_peek) { gus_sample->max_peek = *write_data_b; } else if (*write_data_b < gus_sample->min_peek) { gus_sample->min_peek = *write_data_b; } write_data_b++; } while (read_data != read_end); } gus_sample->loop_start += loop_length; gus_sample->loop_end += dloop_length; gus_sample->data_length = new_length; gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_UNSIGNED; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 8bit unsigned reverse */ int convert_8ur (unsigned char *data, struct _sample *gus_sample ) { unsigned char *read_data = data; unsigned char *read_end = data + gus_sample->data_length; signed short int *write_data = NULL; unsigned long int tmp_loop = 0; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc((gus_sample->data_length + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data + gus_sample->data_length - 1; do { *write_data = ((*read_data++) ^ 0x80) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data--; } while (read_data != read_end); tmp_loop = gus_sample->loop_end; gus_sample->loop_end = gus_sample->data_length - gus_sample->loop_start; gus_sample->loop_start = gus_sample->data_length - tmp_loop; gus_sample->loop_fraction = ((gus_sample->loop_fraction & 0x0f) << 4) | ((gus_sample->loop_fraction & 0xf0) >> 4); gus_sample->modes ^= SAMPLE_REVERSE | SAMPLE_UNSIGNED; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 8bit unsigned reverse ping pong */ int convert_8urp (unsigned char *data, struct _sample *gus_sample ) { unsigned long int loop_length = gus_sample->loop_end - gus_sample->loop_start; unsigned long int dloop_length = loop_length * 2; unsigned long int new_length = gus_sample->data_length + dloop_length; unsigned char *read_data = data + gus_sample->data_length - 1; unsigned char *read_end = data + gus_sample->loop_end; signed short int *write_data = NULL; signed short int *write_data_a = NULL; signed short int *write_data_b = NULL; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc((new_length + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data; do { *write_data = ((*read_data--) ^ 0x80) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data != read_end); *write_data = ((*read_data--) ^ 0x80) << 8; write_data_a = write_data + dloop_length; *write_data_a-- = *write_data; write_data++; write_data_b = write_data + dloop_length; read_end = data + gus_sample->loop_start; do { *write_data = ((*read_data--) ^ 0x80) << 8; *write_data_a-- = *write_data; *write_data_b++ = *write_data; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data != read_end); *write_data = ((*read_data--) ^ 0x80) << 8; *write_data_b++ = *write_data; read_end = data - 1; do { *write_data_b = ((*read_data--) ^ 0x80) << 8; if (*write_data_b > gus_sample->max_peek) { gus_sample->max_peek = *write_data_b; } else if (*write_data_b < gus_sample->min_peek) { gus_sample->min_peek = *write_data_b; } write_data_b++; } while (read_data != read_end); gus_sample->loop_start += loop_length; gus_sample->loop_end += dloop_length; gus_sample->data_length = new_length; gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_REVERSE | SAMPLE_UNSIGNED; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 16bit signed */ int convert_16s (unsigned char *data, struct _sample *gus_sample ) { unsigned char *read_data = data; unsigned char *read_end = data + gus_sample->data_length; signed short int *write_data = NULL; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc(((gus_sample->data_length >> 1) + 1),sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data; do { *write_data = *read_data++; *write_data |= (*read_data++) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data < read_end); gus_sample->loop_start >>= 1; gus_sample->loop_end >>= 1; gus_sample->data_length >>= 1; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 16bit signed ping pong */ int convert_16sp (unsigned char *data, struct _sample *gus_sample ) { unsigned long int loop_length = gus_sample->loop_end - gus_sample->loop_start; unsigned long int dloop_length = loop_length * 2; unsigned long int new_length = gus_sample->data_length + dloop_length; unsigned char *read_data = data; unsigned char *read_end = data + gus_sample->loop_start; signed short int *write_data = NULL; signed short int *write_data_a = NULL; signed short int *write_data_b = NULL; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc(((new_length >> 1) + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data; do { *write_data = (*read_data++); *write_data |= (*read_data++) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data < read_end); *write_data = (*read_data++); *write_data |= (*read_data++) << 8; write_data_a = write_data + (dloop_length >> 1); *write_data_a-- = *write_data; write_data++; write_data_b = write_data + (dloop_length >> 1); read_end = data + gus_sample->loop_end; do { *write_data = (*read_data++); *write_data |= (*read_data++) << 8; *write_data_a-- = *write_data; *write_data_b++ = *write_data; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data < read_end); *write_data = *(read_data++); *write_data |= (*read_data++) << 8; *write_data_b++ = *write_data; read_end = data + gus_sample->data_length; if (__builtin_expect((read_data != read_end),1)) { do { *write_data_b = *(read_data++); *write_data_b |= (*read_data++) << 8; if (*write_data_b > gus_sample->max_peek) { gus_sample->max_peek = *write_data_b; } else if (*write_data_b < gus_sample->min_peek) { gus_sample->min_peek = *write_data_b; } write_data_b++; } while (read_data < read_end); } gus_sample->loop_start += loop_length; gus_sample->loop_end += dloop_length; gus_sample->data_length = new_length; gus_sample->modes ^= SAMPLE_PINGPONG; gus_sample->loop_start >>= 1; gus_sample->loop_end >>= 1; gus_sample->data_length >>= 1; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 16bit signed reverse */ int convert_16sr (unsigned char *data, struct _sample *gus_sample ) { unsigned char *read_data = data; unsigned char *read_end = data + gus_sample->data_length; signed short int *write_data = NULL; unsigned long int tmp_loop = 0; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc(((gus_sample->data_length >> 1) + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data + (gus_sample->data_length >> 1) - 1; do { *write_data = *read_data++; *write_data |= (*read_data++) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data--; } while (read_data < read_end); tmp_loop = gus_sample->loop_end; gus_sample->loop_end = gus_sample->data_length - gus_sample->loop_start; gus_sample->loop_start = gus_sample->data_length - tmp_loop; gus_sample->loop_fraction = ((gus_sample->loop_fraction & 0x0f) << 4) | ((gus_sample->loop_fraction & 0xf0) >> 4); gus_sample->loop_start >>= 1; gus_sample->loop_end >>= 1; gus_sample->data_length >>= 1; gus_sample->modes ^= SAMPLE_REVERSE; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 16bit signed reverse ping pong */ int convert_16srp (unsigned char *data, struct _sample *gus_sample ) { unsigned long int loop_length = gus_sample->loop_end - gus_sample->loop_start; unsigned long int dloop_length = loop_length * 2; unsigned long int new_length = gus_sample->data_length + dloop_length; unsigned char *read_data = data + gus_sample->data_length - 1; unsigned char *read_end = data + gus_sample->loop_end; signed short int *write_data = NULL; signed short int *write_data_a = NULL; signed short int *write_data_b = NULL; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc(((new_length >> 1) + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data; do { *write_data = (*read_data--) << 8; *write_data |= *read_data--; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data < read_end); *write_data = (*read_data-- << 8); *write_data |= *read_data--; write_data_a = write_data + (dloop_length >> 1); *write_data_a-- = *write_data; write_data++; write_data_b = write_data + (dloop_length >> 1); read_end = data + gus_sample->loop_start; do { *write_data = (*read_data--) << 8; *write_data |= *read_data--; *write_data_a-- = *write_data; *write_data_b++ = *write_data; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data < read_end); *write_data = ((*read_data--) << 8); *write_data |= *read_data--; *write_data_b++ = *write_data; read_end = data - 1; do { *write_data_b = (*read_data--) << 8; *write_data_b |= *read_data--; if (*write_data_b > gus_sample->max_peek) { gus_sample->max_peek = *write_data_b; } else if (*write_data_b < gus_sample->min_peek) { gus_sample->min_peek = *write_data_b; } write_data_b++; } while (read_data < read_end); gus_sample->loop_start += loop_length; gus_sample->loop_end += dloop_length; gus_sample->data_length = new_length; gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_REVERSE; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 16bit unsigned */ int convert_16u (unsigned char *data, struct _sample *gus_sample ) { unsigned char *read_data = data; unsigned char *read_end = data + gus_sample->data_length; signed short int *write_data = NULL; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc(((gus_sample->data_length >> 1) + 1),sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data; do { *write_data = *read_data++; *write_data |= ((*read_data++) ^ 0x80) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data < read_end); gus_sample->loop_start >>= 1; gus_sample->loop_end >>= 1; gus_sample->data_length >>= 1; gus_sample->modes ^= SAMPLE_UNSIGNED; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 16bit unsigned ping pong */ int convert_16up (unsigned char *data, struct _sample *gus_sample ) { unsigned long int loop_length = gus_sample->loop_end - gus_sample->loop_start; unsigned long int dloop_length = loop_length * 2; unsigned long int new_length = gus_sample->data_length + dloop_length; unsigned char *read_data = data; unsigned char *read_end = data + gus_sample->loop_start; signed short int *write_data = NULL; signed short int *write_data_a = NULL; signed short int *write_data_b = NULL; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc(((new_length >> 1) + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data; do { *write_data = (*read_data++); *write_data |= ((*read_data++) ^ 0x80) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data < read_end); *write_data = (*read_data++); *write_data |= ((*read_data++) ^ 0x80) << 8; write_data_a = write_data + (dloop_length >> 1); *write_data_a-- = *write_data; write_data++; write_data_b = write_data + (dloop_length >> 1); read_end = data + gus_sample->loop_end; do { *write_data = (*read_data++); *write_data |= ((*read_data++) ^ 0x80) << 8; *write_data_a-- = *write_data; *write_data_b++ = *write_data; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data < read_end); *write_data = (*read_data++); *write_data |= ((*read_data++) ^ 0x80) << 8; *write_data_b++ = *write_data; read_end = data + gus_sample->data_length; if (__builtin_expect((read_data != read_end),1)) { do { *write_data_b = (*read_data++); *write_data_b |= ((*read_data++) ^ 0x80) << 8; if (*write_data_b > gus_sample->max_peek) { gus_sample->max_peek = *write_data_b; } else if (*write_data_b < gus_sample->min_peek) { gus_sample->min_peek = *write_data_b; } write_data_b++; } while (read_data < read_end); } gus_sample->loop_start += loop_length; gus_sample->loop_end += dloop_length; gus_sample->data_length = new_length; gus_sample->modes ^= SAMPLE_PINGPONG; gus_sample->loop_start >>= 1; gus_sample->loop_end >>= 1; gus_sample->data_length >>= 1; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 16bit unsigned reverse */ int convert_16ur (unsigned char *data, struct _sample *gus_sample ) { unsigned char *read_data = data; unsigned char *read_end = data + gus_sample->data_length; signed short int *write_data = NULL; unsigned long int tmp_loop = 0; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc(((gus_sample->data_length >> 1) + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data + (gus_sample->data_length >> 1) - 1; do { *write_data = *read_data++; *write_data |= ((*read_data++) ^ 0x80) << 8; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data--; } while (read_data < read_end); tmp_loop = gus_sample->loop_end; gus_sample->loop_end = gus_sample->data_length - gus_sample->loop_start; gus_sample->loop_start = gus_sample->data_length - tmp_loop; gus_sample->loop_fraction = ((gus_sample->loop_fraction & 0x0f) << 4) | ((gus_sample->loop_fraction & 0xf0) >> 4); gus_sample->loop_start >>= 1; gus_sample->loop_end >>= 1; gus_sample->data_length >>= 1; gus_sample->modes ^= SAMPLE_REVERSE | SAMPLE_UNSIGNED; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* 16bit unsigned reverse ping pong */ int convert_16urp (unsigned char *data, struct _sample *gus_sample ) { unsigned long int loop_length = gus_sample->loop_end - gus_sample->loop_start; unsigned long int dloop_length = loop_length * 2; unsigned long int new_length = gus_sample->data_length + dloop_length; unsigned char *read_data = data + gus_sample->data_length - 1; unsigned char *read_end = data + gus_sample->loop_end; signed short int *write_data = NULL; signed short int *write_data_a = NULL; signed short int *write_data_b = NULL; SAMPLE_CONVERT_DEBUG(__FUNCTION__); gus_sample->data = calloc(((new_length >> 1) + 1), sizeof(signed short int)); if (__builtin_expect((gus_sample->data != NULL),1)) { write_data = gus_sample->data; do { *write_data = ((*read_data--) ^ 0x80) << 8; *write_data |= *read_data--; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data < read_end); *write_data = ((*read_data--) ^ 0x80) << 8; *write_data |= *read_data--; write_data_a = write_data + (dloop_length >> 1); *write_data_a-- = *write_data; write_data++; write_data_b = write_data + (dloop_length >> 1); read_end = data + gus_sample->loop_start; do { *write_data = ((*read_data--) ^ 0x80) << 8; *write_data |= *read_data--; *write_data_a-- = *write_data; *write_data_b++ = *write_data; if (*write_data > gus_sample->max_peek) { gus_sample->max_peek = *write_data; } else if (*write_data < gus_sample->min_peek) { gus_sample->min_peek = *write_data; } write_data++; } while (read_data < read_end); *write_data = ((*read_data--) ^ 0x80) << 8; *write_data |= *read_data--; *write_data_b++ = *write_data; read_end = data - 1; do { *write_data_b = ((*read_data--) ^ 0x80) << 8; *write_data_b |= *read_data--; if (*write_data_b > gus_sample->max_peek) { gus_sample->max_peek = *write_data_b; } else if (*write_data_b < gus_sample->min_peek) { gus_sample->min_peek = *write_data_b; } write_data_b++; } while (read_data < read_end); gus_sample->loop_start += loop_length; gus_sample->loop_end += dloop_length; gus_sample->data_length = new_length; gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_REVERSE | SAMPLE_UNSIGNED; return 0; } WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno); return -1; } /* sample loading */ int load_sample (struct _patch *sample_patch) { unsigned char *gus_patch; unsigned long int gus_size; unsigned long int gus_ptr; unsigned char no_of_samples; struct _sample *gus_sample = NULL; unsigned long int i = 0; int (*do_convert[])(unsigned char *data, struct _sample *gus_sample ) = { convert_8s, convert_16s, convert_8u, convert_16u, convert_8sp, convert_16sp, convert_8up, convert_16up, convert_8sr, convert_16sr, convert_8ur, convert_16ur, convert_8srp, convert_16srp, convert_8urp, convert_16urp }; unsigned long int tmp_loop; SAMPLE_CONVERT_DEBUG(__FUNCTION__); SAMPLE_CONVERT_DEBUG(sample_patch->filename); sample_patch->loaded = 1; if ((gus_patch = WM_BufferFile(sample_patch->filename,&gus_size)) == NULL) { return -1; } if (gus_size < 239) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, sample_patch->filename, 0); free(gus_patch); return -1; } if (memcmp(gus_patch, "GF1PATCH110\0ID#000002", 22) && memcmp(gus_patch, "GF1PATCH100\0ID#000002", 22)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID,"(unsupported format)", 0); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, sample_patch->filename, 0); free(gus_patch); return -1; } if (gus_patch[82] > 1) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID,"(unsupported format)", 0); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, sample_patch->filename, 0); free(gus_patch); return -1; } if (gus_patch[151] > 1) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID,"(unsupported format)", 0); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, sample_patch->filename, 0); free(gus_patch); return -1; } no_of_samples = gus_patch[198]; sample_patch->first_sample = NULL; gus_ptr = 239; while (no_of_samples) { unsigned long int tmp_cnt; if (sample_patch->first_sample == NULL) { sample_patch->first_sample = malloc(sizeof(struct _sample)); gus_sample = sample_patch->first_sample; } else { gus_sample->next = malloc(sizeof(struct _sample)); gus_sample = gus_sample->next; } if (gus_sample == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, 0); WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, sample_patch->filename, 0); return -1; } gus_sample->next = NULL; gus_sample->loop_fraction = gus_patch[gus_ptr+7]; gus_sample->data_length = (gus_patch[gus_ptr+11] << 24) | (gus_patch[gus_ptr+10] << 16) | (gus_patch[gus_ptr+9] << 8) | gus_patch[gus_ptr+8]; gus_sample->loop_start = (gus_patch[gus_ptr+15] << 24) | (gus_patch[gus_ptr+14] << 16) | (gus_patch[gus_ptr+13] << 8) | gus_patch[gus_ptr+12]; gus_sample->loop_end = (gus_patch[gus_ptr+19] << 24) | (gus_patch[gus_ptr+18] << 16) | (gus_patch[gus_ptr+17] << 8) | gus_patch[gus_ptr+16]; gus_sample->rate = (gus_patch[gus_ptr+21] << 8) | gus_patch[gus_ptr+20]; gus_sample->freq_low = ((gus_patch[gus_ptr+25] << 24) | (gus_patch[gus_ptr+24] << 16) | (gus_patch[gus_ptr+23] << 8) | gus_patch[gus_ptr+22]); gus_sample->freq_high = ((gus_patch[gus_ptr+29] << 24) | (gus_patch[gus_ptr+28] << 16) | (gus_patch[gus_ptr+27] << 8) | gus_patch[gus_ptr+26]); gus_sample->freq_root = ((gus_patch[gus_ptr+33] << 24) | (gus_patch[gus_ptr+32] << 16) | (gus_patch[gus_ptr+31] << 8) | gus_patch[gus_ptr+30]); /* This is done this way instead of ((freq * 1024) / rate) to avoid 32bit overflow. */ /* Result is 0.001% inacurate */ gus_sample->inc_div = ((gus_sample->freq_root * 512) / gus_sample->rate) * 2; #if 0 printf("\rTremolo Sweep: %i, Rate: %i, Depth %i\n", gus_patch[gus_ptr+49], gus_patch[gus_ptr+50], gus_patch[gus_ptr+51]); printf("\rVibrato Sweep: %i, Rate: %i, Depth %i\n", gus_patch[gus_ptr+52], gus_patch[gus_ptr+53], gus_patch[gus_ptr+54]); #endif gus_sample->modes = gus_patch[gus_ptr+55] & 0x7F; if ((sample_patch->remove & SAMPLE_SUSTAIN) && (gus_sample->modes & SAMPLE_SUSTAIN)) { gus_sample->modes ^= SAMPLE_SUSTAIN; } if (sample_patch->patchid & 0x0080) { if (!(sample_patch->keep & SAMPLE_LOOP)) { gus_sample->modes &= 0xFB; } if (!(sample_patch->keep & SAMPLE_ENVELOPE)) { gus_sample->modes &= 0xBF; } } if (gus_sample->loop_start > gus_sample->loop_end) { tmp_loop = gus_sample->loop_end; gus_sample->loop_end = gus_sample->loop_start; gus_sample->loop_start = tmp_loop; gus_sample->loop_fraction = ((gus_sample->loop_fraction & 0x0f) << 4) | ((gus_sample->loop_fraction & 0xf0) >> 4); } for (i = 0; i < 6; i++) { if (gus_sample->modes & SAMPLE_ENVELOPE) { unsigned char env_rate = gus_patch[gus_ptr+37+i]; if (sample_patch->env[i].set & 0x02) { gus_sample->env_target[i] = 16448 * (unsigned long int)(255.0 * sample_patch->env[i].level); } else { gus_sample->env_target[i] = 16448 * gus_patch[gus_ptr+43+i]; } if (sample_patch->env[i].set & 0x01) { gus_sample->env_rate[i] = (unsigned long int)(4194303.0 / ((float)WM_SampleRate * (sample_patch->env[i].time / 1000.0))); } else { gus_sample->env_rate[i] = (unsigned long int)(4194303.0 / ((float)WM_SampleRate * env_time_table[env_rate])); if (gus_sample->env_rate[i] == 0) { fprintf(stderr,"\rWarning: libWildMidi %s found invalid envelope(%lu) rate setting in %s. Using %f instead.\n",__FUNCTION__, i, sample_patch->filename, env_time_table[63]); gus_sample->env_rate[i] = (unsigned long int)(4194303.0 / ((float)WM_SampleRate * env_time_table[63])); } } } else { gus_sample->env_target[i] = 4194303; gus_sample->env_rate[i] = (unsigned long int)(4194303.0 / ((float)WM_SampleRate * env_time_table[63])); } } gus_sample->env_target[6] = 0; gus_sample->env_rate[6] = (unsigned long int)(4194303.0 / ((float)WM_SampleRate * env_time_table[63])); if ((sample_patch->patchid == 47) && (!(gus_sample->modes & SAMPLE_LOOP))) { for (i = 3; i < 6; i++) { gus_sample->env_target[i] = gus_sample->env_target[2]; gus_sample->env_rate[i] = gus_sample->env_rate[2]; } } gus_ptr += 96; tmp_cnt = gus_sample->data_length; /* convert to float */ gus_sample->min_peek = 0; gus_sample->max_peek = 0; if (do_convert[(((gus_sample->modes & 0x18) >> 1)| (gus_sample->modes & 0x03))](&gus_patch[gus_ptr], gus_sample) == -1) { return -1; }; if (gus_sample->max_peek > (-gus_sample->min_peek)) { gus_sample->peek_adjust = 33553408 / gus_sample->max_peek; } else { gus_sample->peek_adjust = 33554432 / (-gus_sample->min_peek); } gus_sample->peek_adjust = (gus_sample->peek_adjust * sample_patch->amp) >> 10; gus_ptr += tmp_cnt; gus_sample->loop_start = (gus_sample->loop_start << 10) | (((gus_sample->loop_fraction & 0x0f) << 10) / 16); gus_sample->loop_end = (gus_sample->loop_end << 10) | (((gus_sample->loop_fraction & 0xf0) << 6) / 16); gus_sample->loop_size = gus_sample->loop_end - gus_sample->loop_start; gus_sample->data_length = gus_sample->data_length << 10; no_of_samples--; } free(gus_patch); return 0; } struct _patch * get_patch_data(struct _mdi *mdi, unsigned short patchid) { struct _patch *search_patch; WM_Lock(&patch_lock); search_patch = patch[patchid & 0x007F]; if (search_patch == NULL) { WM_Unlock(&patch_lock); return NULL; } while(search_patch != NULL) { if (search_patch->patchid == patchid) { WM_Unlock(&patch_lock); return search_patch; } search_patch = search_patch->next; } if ((patchid >> 8) != 0) { WM_Unlock(&patch_lock); return (get_patch_data(mdi, patchid & 0x00FF)); } WM_Unlock(&patch_lock); return NULL; } void load_patch (struct _mdi *mdi, unsigned short patchid) { int i; struct _patch *tmp_patch = NULL; for (i = 0; i < mdi->patch_count; i++) { if (mdi->patches[i]->patchid == patchid) { return; } } tmp_patch = get_patch_data(mdi, patchid); if (tmp_patch == NULL) { return; } WM_Lock(&patch_lock); if (!tmp_patch->loaded) { if (load_sample(tmp_patch) == -1) { WM_Unlock(&patch_lock); return; } } if (tmp_patch->first_sample == NULL) { WM_Unlock(&patch_lock); return; } mdi->patch_count++; mdi->patches = realloc(mdi->patches, (sizeof(struct _patch) * mdi->patch_count)); mdi->patches[mdi->patch_count -1] = tmp_patch; tmp_patch->inuse_count++; WM_Unlock(&patch_lock); return; } struct _sample * get_sample_data (struct _patch *sample_patch, unsigned long int freq) { struct _sample *last_sample = NULL; struct _sample *return_sample = NULL; WM_Lock(&patch_lock); if (sample_patch == NULL) { WM_Unlock(&patch_lock); return NULL; } if (sample_patch->first_sample == NULL) { WM_Unlock(&patch_lock); return NULL; } if (freq == 0) { WM_Unlock(&patch_lock); return sample_patch->first_sample; } return_sample = sample_patch->first_sample; last_sample = sample_patch->first_sample; while (last_sample != NULL) { if (freq > last_sample->freq_low) { if (freq < last_sample->freq_high) { WM_Unlock(&patch_lock); return last_sample; } else { return_sample = last_sample; } } last_sample = last_sample->next; } WM_Unlock(&patch_lock); return return_sample; } unsigned long int read_var_length (struct _mdi *mdi, struct _miditrack *track) { unsigned long int var_data = 0; if (mdi->data[track->ptr] > 0x7f) { while(mdi->data[track->ptr] > 0x7f) { var_data |= mdi->data[track->ptr] & 0x7f; track->ptr++; if (track->ptr > mdi->size) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0); return 0xFFFFFFFF; } var_data = (var_data << 7); } } var_data |= mdi->data[track->ptr] & 0x7f; track->ptr++; if (track->ptr > mdi->size) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0); return 0xFFFFFFFF; } return var_data; } void do_note_off (unsigned char ch, struct _mdi *mdi, unsigned long int ptr) { struct _note *nte; MIDI_EVENT_DEBUG(__FUNCTION__,ch); nte = &mdi->note_table[0][ch][mdi->data[ptr]]; if (!nte->active) nte = &mdi->note_table[1][ch][mdi->data[ptr]]; if (!nte->active) { return; } if ((ch == 9) && (!(nte->modes & SAMPLE_LOOP))) { return; } if (nte->hold) { nte->hold |= HOLD_OFF; } else { #if 0 if (nte->modes & SAMPLE_SUSTAIN) { nte->env = 3; if (nte->env_level > nte->sample->env_target[3]) { nte->env_inc = -nte->sample->env_rate[3]; } else { nte->env_inc = nte->sample->env_rate[3]; } } else #endif { if (nte->env < 4) { nte->env = 4; if (nte->env_level > nte->sample->env_target[4]) { nte->env_inc = -nte->sample->env_rate[4]; } else { nte->env_inc = nte->sample->env_rate[4]; } } } } return; } static inline unsigned long int get_inc (struct _mdi *mdi, struct _note *nte) { int ch = nte->noteid >> 8; signed long int note_f; unsigned long int freq; if (__builtin_expect((nte->patch->note != 0),0)) { note_f = nte->patch->note * 100; } else { note_f = (nte->noteid & 0x7f) * 100; } note_f += mdi->channel[ch].pitch_adjust; if (__builtin_expect((note_f < 0), 0)) { note_f = 0; } else if (__builtin_expect((note_f > 12700), 0)) { note_f = 12700; } freq = freq_table[(note_f % 1200)] >> (10 - (note_f / 1200)); return (((freq / ((WM_SampleRate * 100) / 1024)) * 1024 / nte->sample->inc_div)); } static inline signed short int get_volume(struct _mdi *mdi, unsigned char ch, struct _note *nte) { signed long int volume; if (mdi->info.mixer_options & WM_MO_LINEAR_VOLUME) { volume = (lin_volume[mdi->channel[ch].volume] * lin_volume[mdi->channel[ch].expression] * lin_volume[nte->velocity]) / 1048576; } else { volume = (sqr_volume[mdi->channel[ch].volume] * sqr_volume[mdi->channel[ch].expression] * sqr_volume[nte->velocity]) / 1048576; } return ((volume * nte->sample->peek_adjust) >> 10); } void do_note_on (unsigned char ch, struct _mdi *mdi, unsigned long int ptr) { struct _note *nte; unsigned long int freq = 0; struct _patch *patch; struct _sample *sample; if (mdi->data[ptr+1] == 0x00) { do_note_off(ch, mdi, ptr); return; } MIDI_EVENT_DEBUG(__FUNCTION__,ch); if (ch != 9) { patch = mdi->channel[ch].patch; if (patch == NULL) { return; } freq = freq_table[(mdi->data[ptr] % 12) * 100] >> (10 -(mdi->data[ptr] / 12)); } else { patch = get_patch_data(mdi, ((mdi->channel[ch].bank << 8) | mdi->data[ptr] | 0x80)); if (patch == NULL) { return; } if (patch->note) { freq = freq_table[(patch->note % 12) * 100] >> (10 -(patch->note / 12)); } else { freq = freq_table[(mdi->data[ptr] % 12) * 100] >> (10 -(mdi->data[ptr] / 12)); } } sample = get_sample_data(patch, (freq / 100)); if (sample == NULL) { return; } nte = &mdi->note_table[0][ch][mdi->data[ptr]]; if (nte->active) { if ((nte->modes & SAMPLE_ENVELOPE) && (nte->env < 3) && (!(nte->hold & HOLD_OFF))) return; nte->next = &mdi->note_table[1][ch][mdi->data[ptr]]; nte->env = 6; nte->env_inc = -nte->sample->env_rate[6]; nte = &mdi->note_table[1][ch][mdi->data[ptr]]; } else { if (mdi->note_table[1][ch][mdi->data[ptr]].active) { if ((nte->modes & SAMPLE_ENVELOPE) && (nte->env < 3) && (!(nte->hold & HOLD_OFF))) return; mdi->note_table[1][ch][mdi->data[ptr]].next = nte; mdi->note_table[1][ch][mdi->data[ptr]].env = 6; mdi->note_table[1][ch][mdi->data[ptr]].env_inc = -mdi->note_table[1][ch][mdi->data[ptr]].sample->env_rate[6]; } else { *mdi->last_note = nte; mdi->last_note++; nte->active = 1; } } nte->noteid = (ch << 8) | mdi->data[ptr]; nte->patch = patch; nte->sample = sample; nte->sample_pos = 0; nte->sample_inc = get_inc (mdi, nte); nte->velocity = mdi->data[ptr+1]; nte->env = 0; nte->env_inc = nte->sample->env_rate[0]; nte->env_level = 0; nte->modes = sample->modes; nte->hold = mdi->channel[ch].hold; nte->vol_lvl = get_volume(mdi, ch, nte); nte->next = NULL; } void do_aftertouch (unsigned char ch, struct _mdi *mdi, unsigned long int ptr) { struct _note *nte; MIDI_EVENT_DEBUG(__FUNCTION__,ch); nte = &mdi->note_table[0][ch][mdi->data[ptr]]; if (!nte->active) { nte = &mdi->note_table[1][ch][mdi->data[ptr]]; if (!nte->active) { return; } } nte->velocity = mdi->data[ptr+1]; nte->vol_lvl = get_volume(mdi, ch, nte); if (nte->next) { nte->next->velocity = mdi->data[ptr+1]; nte->next->vol_lvl = get_volume(mdi, ch, nte->next); } } void do_pan_adjust (struct _mdi *mdi, unsigned char ch) { signed short int pan_adjust = mdi->channel[ch].balance + mdi->channel[ch].pan; signed long int left, right; if (pan_adjust > 63) { pan_adjust = 63; } else if (pan_adjust < -64) { pan_adjust = -64; } pan_adjust += 64; if (mdi->info.mixer_options & WM_MO_LINEAR_VOLUME) { left = (lin_volume[127 - pan_adjust] * WM_MasterVolume * mdi->amp) / 1048576; right= (lin_volume[pan_adjust] * WM_MasterVolume * mdi->amp) / 1048576; } else { left = (pan_volume[127 - pan_adjust] * WM_MasterVolume * mdi->amp) / 1048576; right = (pan_volume[pan_adjust] * WM_MasterVolume * mdi->amp) / 1048576; } mdi->channel[ch].left_adjust = left; mdi->channel[ch].right_adjust = right; } void do_control (unsigned char ch, struct _mdi *mdi, unsigned long int ptr) { struct _note **note_data = mdi->note; switch (mdi->data[ptr]) { case 0: // Bank Select mdi->channel[ch].bank = mdi->data[ptr+1]; break; case 1: case 2: case 3: case 4: case 5: break; case 6: // Data Entry Course if (mdi->channel[ch].reg_data == 0x0000) { // Pitch Bend Range int data_tmp; data_tmp = mdi->channel[ch].pitch_range % 100; mdi->channel[ch].pitch_range = mdi->data[ptr+1] * 100 + data_tmp; } break; case 7: // Channel Volume mdi->channel[ch].volume = mdi->data[ptr+1]; if (note_data != mdi->last_note) { do { if (((*note_data)->noteid >> 8) == ch) { (*note_data)->vol_lvl = get_volume(mdi, ch, *note_data); if ((*note_data)->next) (*note_data)->next->vol_lvl = get_volume(mdi, ch, (*note_data)->next); } note_data++; } while (note_data != mdi->last_note); } break; case 8: // Channel Balance mdi->channel[ch].balance = mdi->data[ptr+1] - 64; do_pan_adjust(mdi, ch); break; case 9: break; case 10: // Channel Pan mdi->channel[ch].pan = mdi->data[ptr+1] - 64; do_pan_adjust(mdi, ch); break; case 11: // Channel Expression mdi->channel[ch].expression = mdi->data[ptr+1]; if (note_data != mdi->last_note) { do { if (((*note_data)->noteid >> 8) == ch) { (*note_data)->vol_lvl = get_volume(mdi, ch, *note_data); if ((*note_data)->next) (*note_data)->next->vol_lvl = get_volume(mdi, ch, (*note_data)->next); } note_data++; } while (note_data != mdi->last_note); } break; case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: break; case 38: // Data Entry Fine if (mdi->channel[ch].reg_data == 0x0000) { // Pitch Bend Range int data_tmp; data_tmp = mdi->channel[ch].pitch_range / 100; mdi->channel[ch].pitch_range = (data_tmp * 100) + mdi->data[ptr+1]; } break; case 39: case 40: case 41: case 42: case 43: printf("\rController %i used\n",mdi->data[ptr]); break; case 44: case 45: case 46: case 47: case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63: break; case 64: // Channel Hold if (mdi->data[ptr+1] > 63) { mdi->channel[ch].hold = 1; } else { mdi->channel[ch].hold = 0; if (note_data != mdi->last_note) { do { if (((*note_data)->noteid >> 8) == ch) { if ((*note_data)->hold & HOLD_OFF) { if ((*note_data)->modes & SAMPLE_ENVELOPE) { #if 0 if ((*note_data)->modes & SAMPLE_SUSTAIN) { (*note_data)->env = 3; if ((*note_data)->env_level > (*note_data)->sample->env_target[3]) { (*note_data)->env_inc = -(*note_data)->sample->env_rate[3]; } else { (*note_data)->env_inc = (*note_data)->sample->env_rate[3]; } } else #endif { if ((*note_data)->env < 4) { (*note_data)->env = 4; if ((*note_data)->env_level > (*note_data)->sample->env_target[4]) { (*note_data)->env_inc = -(*note_data)->sample->env_rate[4]; } else { (*note_data)->env_inc = (*note_data)->sample->env_rate[4]; } } } } } (*note_data)->hold = 0x00; } note_data++; } while (note_data != mdi->last_note); } } break; case 65: case 66: case 67: case 68: case 69: case 70: case 71: case 72: case 73: case 74: case 75: case 76: case 77: case 78: case 79: case 80: case 81: case 82: case 83: case 84: case 85: case 86: case 87: case 88: case 89: case 90: case 91: case 92: case 93: case 94: case 95: case 96: case 97: case 98: case 99: break; case 100: // Registered Param Fine mdi->channel[ch].reg_data = (mdi->channel[ch].reg_data & 0xFF00) | mdi->data[ptr+1]; break; case 101: // Registered Param Course mdi->channel[ch].reg_data = (mdi->channel[ch].reg_data & 0xFF) | (mdi->data[ptr+1] << 8); break; case 102: case 103: case 104: case 105: case 106: case 107: case 108: case 109: case 110: case 111: case 112: case 113: case 114: case 115: case 116: case 117: case 118: case 119: break; case 120: // All Channel Sound Off if (note_data != mdi->last_note) { do { if (((*note_data)->noteid >> 8) == ch) { (*note_data)->active = 0; if ((*note_data)->next) { (*note_data)->next = NULL; } } note_data++; } while (note_data != mdi->last_note); mdi->last_note = mdi->note; } break; case 121: // All Controlers Off mdi->channel[ch].expression = 127; mdi->channel[ch].pressure = 0; mdi->channel[ch].volume = 100; mdi->channel[ch].pan = 0; mdi->channel[ch].balance = 0; mdi->channel[ch].reg_data = 0xffff; mdi->channel[ch].pitch_range = 200; mdi->channel[ch].pitch = 0; mdi->channel[ch].pitch_adjust = 0; mdi->channel[ch].hold = 0; do_pan_adjust(mdi, ch); if (note_data != mdi->last_note) { do { if (((*note_data)->noteid >> 8 ) == ch) { (*note_data)->sample_inc = get_inc (mdi, *note_data); (*note_data)->velocity = 0; (*note_data)->vol_lvl = get_volume(mdi, ch, *note_data); (*note_data)->hold = 0; if ((*note_data)->next) { (*note_data)->next->velocity = mdi->data[ptr]; (*note_data)->next->vol_lvl = get_volume(mdi, ch, (*note_data)->next); } } note_data++; } while (note_data != mdi->last_note); } break; case 122: break; case 123: // All Channel Notes Off if (ch == 9) return; if (note_data != mdi->last_note) { do { if (((*note_data)->noteid >> 8) == ch) { if (!(*note_data)->hold){ if ((*note_data)->modes & SAMPLE_ENVELOPE) { if ((*note_data)->env < 5) { if ((*note_data)->env_level > (*note_data)->sample->env_target[5]) { (*note_data)->env_inc = -(*note_data)->sample->env_rate[5]; } else { (*note_data)->env_inc = (*note_data)->sample->env_rate[5]; } (*note_data)->env = 5; } } } else { (*note_data)->hold |= HOLD_OFF; } } note_data++; } while (note_data != mdi->last_note); } break; case 124: case 125: case 126: case 127: break; } } void do_patch (unsigned char ch, struct _mdi *mdi, unsigned long int ptr) { MIDI_EVENT_DEBUG(__FUNCTION__,ch); if (ch != 9) { mdi->channel[ch].patch = get_patch_data(mdi, ((mdi->channel[ch].bank << 8) | mdi->data[ptr])); } else { mdi->channel[ch].bank = mdi->data[ptr]; } } void do_channel_pressure (unsigned char ch, struct _mdi *mdi, unsigned long int ptr) { struct _note **note_data = mdi->note; MIDI_EVENT_DEBUG(__FUNCTION__,ch); if (note_data != mdi->last_note) { do { if (((*note_data)->noteid >> 8 ) == ch) { (*note_data)->velocity = mdi->data[ptr]; (*note_data)->vol_lvl = get_volume(mdi, ch, *note_data); if ((*note_data)->next) { (*note_data)->next->velocity = mdi->data[ptr]; (*note_data)->next->vol_lvl = get_volume(mdi, ch, (*note_data)->next); } } note_data++; } while (note_data != mdi->last_note); } } void do_pitch (unsigned char ch, struct _mdi *mdi, unsigned long int ptr) { struct _note **note_data = mdi->note; MIDI_EVENT_DEBUG(__FUNCTION__,ch); mdi->channel[ch].pitch = ((mdi->data[ptr+1] << 7) | mdi->data[ptr]) - 0x2000; if (mdi->channel[ch].pitch < 0) { mdi->channel[ch].pitch_adjust = mdi->channel[ch].pitch_range * mdi->channel[ch].pitch / 8192; } else { mdi->channel[ch].pitch_adjust = mdi->channel[ch].pitch_range * mdi->channel[ch].pitch / 8191; } if (note_data != mdi->last_note) { do { if (((*note_data)->noteid >> 8 ) == ch) { (*note_data)->sample_inc = get_inc (mdi, *note_data); } note_data++; } while (note_data != mdi->last_note); } } void do_message (unsigned char ch, struct _mdi *mdi, unsigned long int ptr) { unsigned char event_type = 0xF0 | ch; static unsigned long int tempo = 500000; MIDI_EVENT_DEBUG(__FUNCTION__,ch); if (event_type == 0xFF) { if ((mdi->data[ptr] == 0x51) && (mdi->data[ptr+1] == 3)) { tempo = (mdi->data[ptr+2] << 16) | (mdi->data[ptr+3] << 8) | mdi->data[ptr+4]; if (tempo == 0) mdi->samples_per_delta = (WM_SampleRate << 10) / (2 * mdi->divisions); else mdi->samples_per_delta = (WM_SampleRate << 10) / ((1000000 * mdi->divisions) / tempo); } } } void do_null (unsigned char ch, struct _mdi *mdi, unsigned long int ptr) { MIDI_EVENT_DEBUG(__FUNCTION__,ch); }; void WM_ResetToStart(midi * handle) { struct _mdi *mdi = (struct _mdi *)handle; int i; mdi->index_count = 0; mdi->samples_per_delta = (WM_SampleRate << 10) / (2 * mdi->divisions); mdi->samples_to_mix = 0; mdi->info.current_sample= 0; for (i=0; i<16; i++) { mdi->channel[i].bank = 0; mdi->channel[i].patch = NULL; mdi->channel[i].hold = 0; mdi->channel[i].volume = 100; mdi->channel[i].pressure = 127; mdi->channel[i].expression = 127; mdi->channel[i].balance = 0; mdi->channel[i].pan = 0; mdi->channel[i].left_adjust = 1.0; mdi->channel[i].right_adjust = 1.0; mdi->channel[i].pitch = 0; mdi->channel[i].pitch_range = 200; mdi->channel[i].reg_data = 0xFFFF; } } void WM_RecalcSamples (midi * handle) { struct _mdi *mdi = (struct _mdi *)handle; struct _note **note_data = mdi->note; unsigned long int total_samples = 0; unsigned long int count_a; unsigned long int count_b; unsigned long int env_level; if (note_data != mdi->last_note) { do { env_level = (*note_data)->env_level; count_a = 0; count_b = 0; if ((*note_data)->env < 4) { if (env_level > (*note_data)->sample->env_target[3]) { count_a += (env_level - (*note_data)->sample->env_target[3] + (*note_data)->sample->env_rate[3] - 1) / (*note_data)->sample->env_rate[3]; } else { count_a += ((*note_data)->sample->env_target[3] - env_level + (*note_data)->sample->env_rate[3] - 1) / (*note_data)->sample->env_rate[3]; } env_level = (*note_data)->sample->env_target[3]; } if ((*note_data)->env < 5) { if (env_level > (*note_data)->sample->env_target[4]) { count_a += (env_level - (*note_data)->sample->env_target[4] + (*note_data)->sample->env_rate[4] - 1) / (*note_data)->sample->env_rate[4]; } else { count_a += ((*note_data)->sample->env_target[4] - env_level + (*note_data)->sample->env_rate[4] - 1) / (*note_data)->sample->env_rate[4]; } env_level = (*note_data)->sample->env_target[4]; } if ((*note_data)->env < 6) { if (env_level > (*note_data)->sample->env_target[5]) { count_a += (env_level - (*note_data)->sample->env_target[5] + (*note_data)->sample->env_rate[5] - 1) / (*note_data)->sample->env_rate[5]; } else { count_a += ((*note_data)->sample->env_target[5] - env_level + (*note_data)->sample->env_rate[5] - 1) / (*note_data)->sample->env_rate[5]; } env_level = (*note_data)->sample->env_target[5]; } if ((*note_data)->env == 6) { count_a = (env_level + (*note_data)->sample->env_rate[6] - 1) / (*note_data)->sample->env_rate[6]; env_level = (*note_data)->sample->env_target[6]; } if (env_level != 0) { if ((*note_data)->modes & SAMPLE_LOOP) { unsigned long int smpl_pos = (*note_data)->sample_pos + (count_a * (*note_data)->sample_inc); if (smpl_pos > ((*note_data)->sample->loop_end << 10)) { while (smpl_pos > ((*note_data)->sample->loop_end << 10)) { smpl_pos -= ((*note_data)->sample->loop_end - (*note_data)->sample->loop_start) << 10; } count_a += (((*note_data)->sample->data_length << 10) - smpl_pos + (*note_data)->sample_inc - 1) / (*note_data)->sample_inc; } } else { count_b = (((*note_data)->sample->data_length << 10) - (*note_data)->sample_pos + (*note_data)->sample_inc - 1) / (*note_data)->sample_inc; } if (count_b != 0) { if (count_b < count_a) { if (total_samples < count_b) total_samples = count_b; } else { if (total_samples < count_a) total_samples = count_a; } } else { if (total_samples < count_a) total_samples = count_a; } } else { if (!((*note_data)->modes & SAMPLE_LOOP)) { count_b = (((*note_data)->sample->data_length << 10) - (*note_data)->sample_pos) / (*note_data)->sample_inc; if (count_b < count_a) { if (total_samples < count_b) total_samples = count_b; } else { if (total_samples < count_a) total_samples = count_a; } } else { if (total_samples < count_a) total_samples = count_a; } } note_data++; } while (note_data != mdi->last_note); } mdi->info.approx_total_samples += total_samples; mdi->recalc_samples = 0; } void do_amp_setup_note_off (unsigned char ch, struct _mdi *mdi, struct _miditrack *track) { MIDI_EVENT_DEBUG(__FUNCTION__,ch); mdi->lin_cur_vol -= (lin_volume[mdi->note_vel[ch][mdi->data[track->ptr]]] * lin_volume[mdi->ch_exp[ch]] * lin_volume[mdi->ch_vol[ch]]) / 1048576; mdi->log_cur_vol -= (sqr_volume[mdi->note_vel[ch][mdi->data[track->ptr]]] * log_volume[mdi->ch_exp[ch]] * log_volume[mdi->ch_vol[ch]]) / 1048576; mdi->note_vel[ch][mdi->data[track->ptr]] = 0; track->running_event = 0x80 | ch; track->ptr += 2; return; } void do_amp_setup_note_on (unsigned char ch, struct _mdi *mdi, struct _miditrack *track) { MIDI_EVENT_DEBUG(__FUNCTION__,ch); if (mdi->data[track->ptr+1] == 0x00) { do_amp_setup_note_off(ch, mdi, track); track->running_event = 0x90 | ch; return; } if (mdi->note_vel[ch][mdi->data[track->ptr]]) { mdi->lin_cur_vol -= (lin_volume[mdi->note_vel[ch][mdi->data[track->ptr]]] * lin_volume[mdi->ch_exp[ch]] * lin_volume[mdi->ch_vol[ch]]) / 1048576; mdi->log_cur_vol -= (sqr_volume[mdi->note_vel[ch][mdi->data[track->ptr]]] * log_volume[mdi->ch_exp[ch]] * log_volume[mdi->ch_vol[ch]]) / 1048576; } mdi->note_vel[ch][mdi->data[track->ptr]] = mdi->data[track->ptr+1]; mdi->lin_cur_vol += (lin_volume[mdi->note_vel[ch][mdi->data[track->ptr]]] * lin_volume[mdi->ch_exp[ch]] * lin_volume[mdi->ch_vol[ch]]) / 1048576; mdi->log_cur_vol += (sqr_volume[mdi->note_vel[ch][mdi->data[track->ptr]]] * log_volume[mdi->ch_exp[ch]] * log_volume[mdi->ch_vol[ch]]) / 1048576; if (mdi->lin_cur_vol > mdi->lin_max_vol) { mdi->lin_max_vol = mdi->lin_cur_vol; } if (mdi->log_cur_vol > mdi->log_max_vol) { mdi->log_max_vol = mdi->log_cur_vol; } if (ch == 9) { load_patch(mdi, ((mdi->channel[ch].bank << 8) | (mdi->data[track->ptr] | 0x80))); } track->running_event = 0x90 | ch; track->ptr += 2; return; } void do_amp_setup_aftertouch (unsigned char ch, struct _mdi *mdi, struct _miditrack *track) { unsigned char pres = mdi->data[track->ptr+1]; MIDI_EVENT_DEBUG(__FUNCTION__,ch); if (pres == 0) pres = 1; if (mdi->note_vel[ch][mdi->data[track->ptr]] != 0) { mdi->lin_cur_vol -= (lin_volume[mdi->note_vel[ch][mdi->data[track->ptr]]] * lin_volume[mdi->ch_exp[ch]] * lin_volume[mdi->ch_vol[ch]]) / 1048576; mdi->log_cur_vol -= (sqr_volume[mdi->note_vel[ch][mdi->data[track->ptr]]] * log_volume[mdi->ch_exp[ch]] * log_volume[mdi->ch_vol[ch]]) / 1048576; mdi->note_vel[ch][mdi->data[track->ptr]] = pres; mdi->lin_cur_vol += (lin_volume[mdi->note_vel[ch][mdi->data[track->ptr]]] * lin_volume[mdi->ch_exp[ch]] * lin_volume[mdi->ch_vol[ch]]) / 1048576; mdi->log_cur_vol += (sqr_volume[mdi->note_vel[ch][mdi->data[track->ptr]]] * log_volume[mdi->ch_exp[ch]] * log_volume[mdi->ch_vol[ch]]) / 1048576; if (mdi->lin_cur_vol > mdi->lin_max_vol) { mdi->lin_max_vol = mdi->lin_cur_vol; } if (mdi->log_cur_vol > mdi->log_max_vol) { mdi->log_max_vol = mdi->log_cur_vol; } } track->running_event = 0xA0 | ch; track->ptr += 2; return; } void do_amp_setup_control (unsigned char ch, struct _mdi *mdi, struct _miditrack *track) { int i; MIDI_EVENT_DEBUG(__FUNCTION__,ch); if (mdi->data[track->ptr] == 0x00) { mdi->channel[ch].bank = mdi->data[track->ptr + 1]; } else if (mdi->data[track->ptr] == 0x07) { for (i=0; i < 128; i++) { if (mdi->note_vel[ch][i] == 0) continue; mdi->lin_cur_vol -= (lin_volume[mdi->note_vel[ch][i]] * lin_volume[mdi->ch_exp[ch]] * lin_volume[mdi->ch_vol[ch]]) / 1048576; mdi->log_cur_vol -= (sqr_volume[mdi->note_vel[ch][i]] * log_volume[mdi->ch_exp[ch]] * log_volume[mdi->ch_vol[ch]]) / 1048576; mdi->lin_cur_vol += (lin_volume[mdi->note_vel[ch][i]] * lin_volume[mdi->ch_exp[ch]] * lin_volume[mdi->data[track->ptr + 1]]) / 1048576; mdi->log_cur_vol += (sqr_volume[mdi->note_vel[ch][i]] * log_volume[mdi->ch_exp[ch]] * log_volume[mdi->data[track->ptr + 1]]) / 1048576; } mdi->ch_vol[ch] = mdi->data[track->ptr + 1]; if (mdi->lin_cur_vol > mdi->lin_max_vol) { mdi->lin_max_vol = mdi->lin_cur_vol; } if (mdi->log_cur_vol > mdi->log_max_vol) { mdi->log_max_vol = mdi->log_cur_vol; } } else if (mdi->data[track->ptr] == 0x0B) { for (i=0; i < 128; i++) { if (mdi->note_vel[ch][i] == 0) continue; mdi->lin_cur_vol -= (lin_volume[mdi->note_vel[ch][i]] * lin_volume[mdi->ch_vol[ch]] * lin_volume[mdi->ch_exp[ch]]) / 1048576; mdi->log_cur_vol -= (sqr_volume[mdi->note_vel[ch][i]] * log_volume[mdi->ch_vol[ch]] * log_volume[mdi->ch_exp[ch]]) / 1048576; mdi->lin_cur_vol += (lin_volume[mdi->note_vel[ch][i]] * lin_volume[mdi->ch_vol[ch]] * lin_volume[mdi->data[track->ptr + 1]]) / 1048576; mdi->log_cur_vol += (sqr_volume[mdi->note_vel[ch][i]] * log_volume[mdi->ch_vol[ch]] * log_volume[mdi->data[track->ptr + 1]]) / 1048576; } mdi->ch_exp[ch] = mdi->data[track->ptr + 1]; if (mdi->lin_cur_vol > mdi->lin_max_vol) { mdi->lin_max_vol = mdi->lin_cur_vol; } if (mdi->log_cur_vol > mdi->log_max_vol) { mdi->log_max_vol = mdi->log_cur_vol; } } track->running_event = 0xB0 | ch; track->ptr += 2; return; } void do_amp_setup_patch (unsigned char ch, struct _mdi *mdi, struct _miditrack *track) { if (ch == 9) { mdi->channel[ch].bank = mdi->data[track->ptr]; } else { load_patch(mdi, ((mdi->channel[ch].bank << 8) | mdi->data[track->ptr])); } track->running_event = 0xC0 | ch; track->ptr++; return; } void do_amp_setup_channel_pressure (unsigned char ch, struct _mdi *mdi, struct _miditrack *track) { int i; unsigned char pres = mdi->data[track->ptr]; MIDI_EVENT_DEBUG(__FUNCTION__,ch); if (pres == 0) pres = 1; for (i=0; i < 128; i++) { if (mdi->note_vel[ch][i] == 0) continue; mdi->lin_cur_vol -= (lin_volume[mdi->note_vel[ch][i]] * lin_volume[mdi->ch_exp[ch]] * lin_volume[mdi->ch_vol[ch]]) / 1048576; mdi->log_cur_vol -= (sqr_volume[mdi->note_vel[ch][i]] * log_volume[mdi->ch_exp[ch]] * log_volume[mdi->ch_vol[ch]]) / 1048576; mdi->note_vel[ch][i] = pres; mdi->lin_cur_vol += (lin_volume[mdi->note_vel[ch][i]] * lin_volume[mdi->ch_exp[ch]] * lin_volume[mdi->ch_vol[ch]]) / 1048576; mdi->log_cur_vol += (sqr_volume[mdi->note_vel[ch][i]] * log_volume[mdi->ch_exp[ch]] * log_volume[mdi->ch_vol[ch]]) / 1048576; } if (mdi->lin_cur_vol > mdi->lin_max_vol) { mdi->lin_max_vol = mdi->lin_cur_vol; } if (mdi->log_cur_vol > mdi->log_max_vol) { mdi->log_max_vol = mdi->log_cur_vol; } track->running_event = 0xD0 | ch; track->ptr++; return; } void do_amp_setup_pitch (unsigned char ch, struct _mdi *mdi, struct _miditrack *track) { MIDI_EVENT_DEBUG(__FUNCTION__,ch); track->running_event = 0xE0 | ch; track->ptr += 2; return; } void do_amp_setup_message (unsigned char ch, struct _mdi *mdi, struct _miditrack *track) { unsigned long int event_length; unsigned char event_type = 0xF0 | ch; unsigned char event_data = mdi->data[track->ptr]; static unsigned long int tempo = 500000; MIDI_EVENT_DEBUG(__FUNCTION__,ch); if (event_type == 0xF0) { track->running_event = 0x00; do { track->ptr++; } while ( mdi->data[track->ptr] != 0xF7); track->ptr++; } else { track->ptr += 1; event_length = read_var_length(mdi, track); if (event_length == 0xFFFFFFFF) { track->delta = 0xFFFFFFFF; return; } if (event_type == 0xFF) { if ((event_data == 0x2F) && (event_length == 0)) { // Track End track->EOT = 1; return; } else if ((event_data == 0x51) && (event_length == 3)) { // Tempo Change tempo = (mdi->data[track->ptr] << 16) | (mdi->data[track->ptr+1] << 8) | mdi->data[track->ptr+2]; if (tempo == 0) mdi->samples_per_delta = (WM_SampleRate << 10) / (2 * mdi->divisions); else mdi->samples_per_delta = (WM_SampleRate << 10) / ((1000000 * mdi->divisions) / tempo); } } track->ptr += event_length; } } struct _mdi * WM_ParseNewMidi(unsigned char *mididata, unsigned long int midisize ) { int i; unsigned char eot[] = { 0xff, 0x2f, 0x00}; unsigned long int index_count = 0; unsigned long int temp_delta = 0xffffff00; struct _mdi *mdi = NULL; void (*do_event[])(unsigned char ch, struct _mdi *midifile, struct _miditrack *track) = { *do_amp_setup_note_off, *do_amp_setup_note_on, *do_amp_setup_aftertouch, *do_amp_setup_control, *do_amp_setup_patch, *do_amp_setup_channel_pressure, *do_amp_setup_pitch, *do_amp_setup_message }; unsigned long int midiofs = 0; unsigned long int midi_track_counter = 0; unsigned long int last_delta; unsigned long int minus_delta = 0; unsigned char current_event = 0; unsigned short int no_tracks; unsigned long int EOT_count = 0; struct _miditrack *tmp_trackdata; struct _hndl *tmp_handle = NULL; mdi = malloc(sizeof(struct _mdi)); if (mdi == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM," to parse midi data", errno); free (mididata); return NULL; } // Initialize data memset(mdi, 0, sizeof(struct _mdi)); mdi->lock = 0; mdi->data = mididata; mdi->size = midisize; mdi->info.mixer_options = WM_MixerOptions; mdi->index = malloc(((midisize / 2) + 1)* sizeof(struct _mdi_index)); if (mdi->index == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM," to parse midi data", errno); free(mdi); return NULL; } load_patch(mdi, 0x0000); for (i=0; i<16; i++) { mdi->channel[i].volume = 100; mdi->channel[i].pressure = 127; mdi->channel[i].expression = 127; mdi->channel[i].pitch_range = 200; mdi->channel[i].reg_data = 0xFFFF; mdi->ch_vol[i] = 100; mdi->ch_exp[i] = 127; mdi->channel[i].patch = get_patch_data(mdi, 0x0000); } midiofs = 0; if (strncmp(mididata,"RIFF",4) == 0) midiofs = 20; if (strncmp(&mididata[midiofs],"MThd",4) != 0) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID,"(not a midi file)", 0); free(mdi->index); free(mdi); return NULL; } if ((midiofs + 25) > midisize) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT,"(too short)", 0); free(mdi->index); free(mdi); return NULL; } midiofs += 9; if (mididata[midiofs] > 1) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, NULL, 0); free(mdi->index); free(mdi); return NULL; } midiofs++; no_tracks = mididata[midiofs] << 8 | mididata[midiofs+1]; midiofs += 2; mdi->divisions = mididata[midiofs] << 8 | mididata[midiofs+1]; mdi->samples_per_delta = (WM_SampleRate << 10) / (2 * mdi->divisions); midiofs += 2; tmp_trackdata = calloc(no_tracks, sizeof(struct _miditrack)); if (first_handle == NULL) { first_handle = malloc(sizeof(struct _hndl)); if (first_handle == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM," to parse midi data", errno); free (tmp_trackdata); free(mdi->data); free(mdi); return NULL; } first_handle->handle = (void *)mdi; first_handle->prev = NULL; first_handle->next = NULL; } else { tmp_handle = first_handle; if (tmp_handle->next != NULL) { while (tmp_handle->next != NULL) tmp_handle = tmp_handle->next; } tmp_handle->next = malloc(sizeof(struct _hndl)); if (tmp_handle->next == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM," to parse midi data", errno); free(tmp_trackdata); free(mdi->data); free(mdi); return NULL; } tmp_handle->next->prev = tmp_handle; tmp_handle = tmp_handle->next; tmp_handle->next = NULL; tmp_handle->handle = (void *)mdi; } // grab track offsets; midi_track_counter = 0; while (midi_track_counter != no_tracks) { if ((midiofs + 12) > midisize) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0); WildMidi_Close(mdi); free(tmp_trackdata); return NULL; } if (strncmp(&mididata[midiofs],"MTrk",4) != 0) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(Expected track header)", 0); WildMidi_Close(mdi); free(tmp_trackdata); return NULL; } midiofs += 4; tmp_trackdata[midi_track_counter].length = mididata[midiofs] << 24 | mididata[midiofs+1] << 16 | mididata[midiofs+2] << 8 | mididata[midiofs+3]; midiofs += 4; if (midisize < (midiofs + tmp_trackdata[midi_track_counter].length)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0); WildMidi_Close(mdi); free(tmp_trackdata); return NULL; } tmp_trackdata[midi_track_counter].ptr = midiofs; tmp_trackdata[midi_track_counter].EOT = 0; tmp_trackdata[midi_track_counter].running_event = 0; tmp_trackdata[midi_track_counter].delta = read_var_length(mdi, &tmp_trackdata[midi_track_counter]); if (tmp_trackdata[midi_track_counter].delta == 0xFFFFFFFF) { WildMidi_Close(mdi); free(tmp_trackdata); return NULL; } midiofs += tmp_trackdata[midi_track_counter].length; if (memcmp(&mididata[midiofs-3], eot,3) != 0) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(Expected EOT)", 0); WildMidi_Close(mdi); free(tmp_trackdata); return NULL; } if (tmp_trackdata[midi_track_counter].delta < temp_delta) { temp_delta = tmp_trackdata[midi_track_counter].delta; } midi_track_counter++; } // set midi info mdi->index[0].offset = 0; mdi->index[0].delta = temp_delta; while (EOT_count != no_tracks) { last_delta = 0; for (i = 0; i < no_tracks; i++) { if (tmp_trackdata[i].EOT) { continue; } if (tmp_trackdata[i].delta) { tmp_trackdata[i].delta -= minus_delta; if (tmp_trackdata[i].delta) { if ((last_delta == 0) || (last_delta > tmp_trackdata[i].delta)) { last_delta = tmp_trackdata[i].delta; } continue; } } do { if (mdi->data[tmp_trackdata[i].ptr] < 0x80) { current_event = tmp_trackdata[i].running_event; if (current_event < 0x80) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(expected event)", 0); WildMidi_Close(mdi); free(tmp_trackdata); return NULL; } } else { current_event = mdi->data[tmp_trackdata[i].ptr]; tmp_trackdata[i].ptr++; } index_count++; mdi->index[index_count].offset = tmp_trackdata[i].ptr; mdi->index[index_count].delta = 0; mdi->index[index_count].event = current_event; do_event[((current_event & 0xF0) >> 4) - 8]((current_event & 0x0F), mdi, &tmp_trackdata[i]); if (tmp_trackdata[i].delta == 0xFFFFFFFF) { WildMidi_Close(mdi); free(tmp_trackdata); return NULL; } if (tmp_trackdata[i].EOT) { EOT_count++; break; } tmp_trackdata[i].delta = read_var_length(mdi, &tmp_trackdata[i]); if (tmp_trackdata[i].delta == 0xFFFFFFFF) { WildMidi_Close(mdi); free(tmp_trackdata); return NULL; } } while (!(tmp_trackdata[i].delta)); if ((last_delta == 0) || (last_delta > tmp_trackdata[i].delta)) { if (tmp_trackdata[i].delta != 0) { last_delta = tmp_trackdata[i].delta; } } } // printf("\rLast Delta %lu\n",last_delta); mdi->index[index_count].delta = last_delta; mdi->samples_to_mix += last_delta * mdi->samples_per_delta; mdi->sample_count += mdi->samples_to_mix >> 10; mdi->samples_to_mix %= 1024; minus_delta = last_delta; } mdi->sample_count -= (mdi->index[index_count - 1].delta * mdi->samples_per_delta) >> 10; mdi->index[index_count - 1].delta = 0; mdi->index_size = index_count; mdi->index = realloc(mdi->index, (sizeof(struct _mdi_index) * mdi->index_size)); if (mdi->index == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, errno); WildMidi_Close(mdi); free(tmp_trackdata); return NULL; } mdi->info.approx_total_samples = mdi->sample_count + 1; mdi->samples_to_mix = 0; mdi->sample_count = 0; mdi->info.current_sample = 0; mdi->samples_per_delta = (WM_SampleRate << 10) / (2 * mdi->divisions); mdi->recalc_samples = 1; mdi->last_note = mdi->note; if ((mdi->info.mixer_options & WM_MO_LINEAR_VOLUME) || !mdi->log_max_vol) { mdi->amp = 281; } else { mdi->amp = 281 * mdi->lin_max_vol / mdi->log_max_vol; } for (i = 0; i < 16; i++) { mdi->channel[i].bank = 0; do_pan_adjust(mdi, i); } for (i = 0; i < 4; i++) { mdi->filter.lowpass[i][0].in[0] = 0; mdi->filter.lowpass[i][0].in[1] = 0; mdi->filter.lowpass[i][1].in[0] = 0; mdi->filter.lowpass[i][1].in[1] = 0; mdi->filter.lowpass[i][0].out[0] = 0; mdi->filter.lowpass[i][0].out[1] = 0; mdi->filter.lowpass[i][1].out[0] = 0; mdi->filter.lowpass[i][1].out[1] = 0; mdi->filter.delay_pos[i][0] = 0; mdi->filter.delay_pos[i][1] = 0; mdi->filter.delay[i][0] = malloc(delay_size[i][0] * sizeof(signed long int)); mdi->filter.delay[i][1] = malloc(delay_size[i][1] * sizeof(signed long int)); memset (mdi->filter.delay[i][0], 0, (delay_size[i][0] * sizeof(signed long int))); memset (mdi->filter.delay[i][1], 0, (delay_size[i][1] * sizeof(signed long int))); } mdi->filter.in[0][0] = 0; mdi->filter.in[0][1] = 0; mdi->filter.in[1][0] = 0; mdi->filter.in[1][1] = 0; mdi->filter.out[0][0] = 0; mdi->filter.out[0][1] = 0; mdi->filter.out[1][0] = 0; mdi->filter.out[1][1] = 0; free(tmp_trackdata); return (mdi); } /* * ========================= * External Functions * ========================= */ const char * WildMidi_GetString (unsigned short int info) { switch (info) { case WM_GS_VERSION: return WM_Version; } return NULL; } int WildMidi_Init (const char * config_file, unsigned short int rate, unsigned short int options) { if (WM_Initialized) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); return -1; } if (config_file == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL config file pointer)", 0); return -1; } WM_InitPatches(); if (WM_LoadConfig(config_file, NULL) == -1) { return -1; } if (options & 0xFFD8) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(invalid option)", 0); WM_FreePatches(); return -1; } WM_MixerOptions = options; if ((rate < 11000) || (rate > 65000)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(rate out of bounds, range is 11000 - 65000)", 0); WM_FreePatches(); return -1; } WM_SampleRate = rate; WM_Initialized = 1; patch_lock = 0; init_gauss(); init_lowpass(); return 0; } int WildMidi_MasterVolume (unsigned char master_volume) { struct _mdi *mdi = NULL; struct _hndl * tmp_handle = first_handle; int i = 0; if (!WM_Initialized) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); return -1; } if (master_volume > 127) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(master volume out of range, range is 0-127)", 0); return -1; } WM_MasterVolume = lin_volume[master_volume]; if (tmp_handle != NULL) { while(tmp_handle != NULL) { mdi = (struct _mdi *)tmp_handle->handle; for (i = 0; i < 16; i++) { do_pan_adjust(mdi, i); } tmp_handle = tmp_handle->next; } } return 0; } int WildMidi_Close (midi * handle) { struct _mdi *mdi = (struct _mdi *)handle; struct _hndl * tmp_handle; struct _sample *tmp_sample; int i; if (!WM_Initialized) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); return -1; } if (handle == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL handle)", 0); return -1; } if (first_handle == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(no midi's open)", 0); return -1; } WM_Lock(&mdi->lock); if (first_handle->handle == handle) { tmp_handle = first_handle->next; free (first_handle); first_handle = tmp_handle; if (first_handle != NULL) first_handle->prev = NULL; } else { tmp_handle = first_handle; while (tmp_handle->handle != handle) { tmp_handle = tmp_handle->next; if (tmp_handle == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(handle does not exist)", 0); return -1; } } tmp_handle->prev->next = tmp_handle->next; if (tmp_handle->next != NULL) { tmp_handle->next->prev = tmp_handle->prev; } free (tmp_handle); } if (mdi->patch_count != 0) { WM_Lock(&patch_lock); for (i = 0; i < mdi->patch_count; i++) { mdi->patches[i]->inuse_count--; if (mdi->patches[i]->inuse_count == 0) { //free samples here if (mdi->patches[i]->first_sample != NULL) { while (mdi->patches[i]->first_sample != NULL) { tmp_sample = mdi->patches[i]->first_sample->next; if (mdi->patches[i]->first_sample->data) free(mdi->patches[i]->first_sample->data); free(mdi->patches[i]->first_sample); mdi->patches[i]->first_sample = tmp_sample; } mdi->patches[i]->loaded = 0; } } } WM_Unlock(&patch_lock); free (mdi->patches); } if (mdi->data != NULL) { free (mdi->data); } if (mdi->tmp_info != NULL) { free (mdi->tmp_info); } if (mdi->index != NULL) free (mdi->index); for (i = 0; i < 4; i++) { free (mdi->filter.delay[i][0]); free (mdi->filter.delay[i][1]); } free (mdi); // no need to unlock cause the struct containing the lock no-longer exists; return 0; } midi * WildMidi_Open (const char *midifile) { unsigned char *mididata = NULL; unsigned long int midisize = 0; if (!WM_Initialized) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); return NULL; } if (midifile == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL filename)", 0); return NULL; } if ((mididata = WM_BufferFile(midifile, &midisize)) == NULL) { return NULL; } return (void *)WM_ParseNewMidi(mididata,midisize); } midi * WildMidi_OpenBuffer (unsigned char *midibuffer, unsigned long int size) { if (!WM_Initialized) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); return NULL; } if (midibuffer == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL midi data buffer)", 0); return NULL; } return (void *)WM_ParseNewMidi(midibuffer,size); } int WildMidi_LoadSamples( midi * handle) { return 0; } int WildMidi_FastSeek ( midi * handle, unsigned long int *sample_pos) { struct _mdi *mdi = (struct _mdi *)handle; struct _note **note_data = mdi->note; void (*do_event[])(unsigned char ch, struct _mdi *midifile, unsigned long int ptr) = { *do_null, *do_null, *do_aftertouch, *do_control, *do_patch, *do_channel_pressure, *do_pitch, *do_message }; unsigned long int real_samples_to_mix = 0; if (!WM_Initialized) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); return -1; } if (handle == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL handle)", 0); return -1; } WM_Lock(&mdi->lock); if (sample_pos == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL seek position pointer)", 0); WM_Unlock(&mdi->lock); return -1; } if (*sample_pos == mdi->info.current_sample) { WM_Unlock(&mdi->lock); return 0; } if (*sample_pos > mdi->info.current_sample) { if ((mdi->sample_count == 0) && (mdi->index_count == mdi->index_size) && (mdi->last_note == 0)) { *sample_pos = mdi->info.current_sample; WM_Unlock(&mdi->lock); return 0; } } else { WM_ResetToStart(handle); } //reset all notes if (note_data != mdi->last_note) { do { (*note_data)->active = 0; *note_data = NULL; note_data++; } while (note_data != mdi->last_note); mdi->last_note = mdi->note; } while (*sample_pos != mdi->info.current_sample) { if (!mdi->sample_count) { if (mdi->index_count != mdi->index_size) { do { if (mdi->index_count == mdi->index_size) { break; } if (mdi->index_count != 0) { do_event[((mdi->index[mdi->index_count].event & 0xF0) >> 4) - 8]((mdi->index[mdi->index_count].event & 0x0F), mdi, mdi->index[mdi->index_count].offset); } } while (mdi->index[mdi->index_count++].delta == 0); mdi->samples_to_mix += mdi->index[mdi->index_count-1].delta * mdi->samples_per_delta; mdi->sample_count = mdi->samples_to_mix >> 10; mdi->samples_to_mix %= 1024; } else { mdi->sample_count = WM_SampleRate; } } if (mdi->sample_count <= (*sample_pos - mdi->info.current_sample)) { real_samples_to_mix = mdi->sample_count; if (real_samples_to_mix == 0) { continue; } } else { real_samples_to_mix = (*sample_pos - mdi->info.current_sample); } mdi->info.current_sample += real_samples_to_mix; mdi->sample_count -= real_samples_to_mix; if ((mdi->index_count == mdi->index_size) && (mdi->last_note == 0)) { mdi->sample_count = 0; *sample_pos = mdi->info.current_sample; WM_Unlock(&mdi->lock); return 0; } } WM_Unlock(&mdi->lock); return 0; } int WildMidi_SampledSeek ( midi * handle, unsigned long int *sample_pos) { struct _mdi *mdi = (struct _mdi *)handle; struct _note **note_data = mdi->note; unsigned long int real_samples_to_mix = 0; unsigned long int tmp_samples_to_mix = 0; if (!WM_Initialized) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); return -1; } if (handle == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL handle)", 0); return -1; } WM_Lock(&mdi->lock); if (sample_pos == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL seek position pointer)", 0); WM_Unlock(&mdi->lock); return -1; } if (*sample_pos == mdi->info.current_sample) { WM_Unlock(&mdi->lock); return 0; } if (*sample_pos > mdi->info.current_sample) { if ((mdi->sample_count == 0) && (mdi->index_count == mdi->index_size) && (mdi->last_note == 0)) { *sample_pos = mdi->info.current_sample; WM_Unlock(&mdi->lock); return 0; } } else { WM_ResetToStart(handle); if (note_data != mdi->last_note) { do { (*note_data)->active = 0; *note_data = NULL; note_data++; } while (note_data != mdi->last_note); mdi->last_note = mdi->note; } } while (*sample_pos != mdi->info.current_sample) { if (!mdi->sample_count) { if (mdi->index_count != mdi->index_size) { do { if (mdi->index_count == mdi->index_size) { break; } if (mdi->index_count != 0) { do_event[((mdi->index[mdi->index_count].event & 0xF0) >> 4) - 8]((mdi->index[mdi->index_count].event & 0x0F), mdi, mdi->index[mdi->index_count].offset); } } while (mdi->index[mdi->index_count++].delta == 0); mdi->samples_to_mix += mdi->index[mdi->index_count-1].delta * mdi->samples_per_delta; mdi->sample_count = mdi->samples_to_mix >> 10; mdi->samples_to_mix %= 1024; } else { if (mdi->recalc_samples) { WM_RecalcSamples(mdi); } mdi->sample_count = mdi->info.approx_total_samples - mdi->info.current_sample; if (mdi->sample_count == 0) { WM_Unlock(&mdi->lock); return 0; } } } if (mdi->sample_count <= (*sample_pos - mdi->info.current_sample)) { real_samples_to_mix = mdi->sample_count; if (real_samples_to_mix == 0) { continue; } } else { real_samples_to_mix = (*sample_pos - mdi->info.current_sample); } // do mixing here tmp_samples_to_mix = real_samples_to_mix; do { if (mdi->last_note != mdi->note) { note_data = mdi->note; while (note_data != mdi->last_note) { /* * ======================== * sample position checking * ======================== */ (*note_data)->sample_pos += (*note_data)->sample_inc; if (__builtin_expect(((*note_data)->sample_pos > (*note_data)->sample->loop_end), 0)) { if ((*note_data)->modes & SAMPLE_LOOP) { (*note_data)->sample_pos = (*note_data)->sample->loop_start + (((*note_data)->sample_pos - (*note_data)->sample->loop_start) % (*note_data)->sample->loop_size); } else if (__builtin_expect(((*note_data)->sample_pos >= (*note_data)->sample->data_length), 0)) { if (__builtin_expect(((*note_data)->next == NULL), 1)) { goto KILL_NOTE; } goto RESTART_NOTE; } } if (__builtin_expect(((*note_data)->env_inc == 0), 0)) { note_data++; continue; } (*note_data)->env_level += (*note_data)->env_inc; if (__builtin_expect(((*note_data)->env_level > 4194304), 0)) { (*note_data)->env_level = (*note_data)->sample->env_target[(*note_data)->env]; } if (__builtin_expect((((*note_data)->env_inc < 0) && ((*note_data)->env_level > (*note_data)->sample->env_target[(*note_data)->env])) || (((*note_data)->env_inc > 0) && ((*note_data)->env_level < (*note_data)->sample->env_target[(*note_data)->env])), 1)) { note_data++; continue; } (*note_data)->env_level = (*note_data)->sample->env_target[(*note_data)->env]; switch ((*note_data)->env) { case 0: if (!((*note_data)->modes & SAMPLE_ENVELOPE)) { (*note_data)->env_inc = 0; note_data++; continue; } break; case 2: if ((*note_data)->modes & SAMPLE_SUSTAIN) { (*note_data)->env_inc = 0; note_data++; continue; } break; case 5: if (__builtin_expect(((*note_data)->env_level == 0), 1)) { goto KILL_NOTE; } // sample release if ((*note_data)->modes & SAMPLE_LOOP) (*note_data)->modes ^= SAMPLE_LOOP; (*note_data)->env_inc = 0; note_data++; continue; case 6: if (__builtin_expect(((*note_data)->next != NULL), 1)) { RESTART_NOTE: (*note_data)->active = 0; *note_data = (*note_data)->next; (*note_data)->active = 1; note_data++; } else { KILL_NOTE: (*note_data)->active = 0; mdi->last_note--; if (note_data != mdi->last_note) { *note_data = *mdi->last_note; } } continue; } (*note_data)->env++; if ((*note_data)->env_level > (*note_data)->sample->env_target[(*note_data)->env]) { (*note_data)->env_inc = -(*note_data)->sample->env_rate[(*note_data)->env]; } else { (*note_data)->env_inc = (*note_data)->sample->env_rate[(*note_data)->env]; } note_data++; continue; } } else { break; } } while (--tmp_samples_to_mix); mdi->info.current_sample += real_samples_to_mix; mdi->sample_count -= real_samples_to_mix; if (mdi->index_count == mdi->index_size) { if (mdi->last_note == 0) { mdi->sample_count = 0; *sample_pos = mdi->info.current_sample; WM_Unlock(&mdi->lock); return 0; } } } WM_Unlock(&mdi->lock); return 0; } int WildMidi_GetOutput_Linear (midi * handle, char * buffer, unsigned long int size) { unsigned long int buffer_used = 0; struct _mdi *mdi = (struct _mdi *)handle; unsigned long int real_samples_to_mix = 0; unsigned long int data_pos; signed long int premix, left_mix, right_mix; signed long int vol_mul; struct _note **note_data = NULL; unsigned long int count; if (__builtin_expect((!WM_Initialized),0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); return -1; } if (__builtin_expect((handle == NULL),0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL handle)", 0); return -1; } if (__builtin_expect((buffer == NULL),0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL buffer pointer)", 0); return -1; } if (__builtin_expect((size == 0),0)) { return 0; } if (__builtin_expect((size % 4),0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(size not a multiple of 4)", 0); return -1; } WM_Lock(&mdi->lock); if (__builtin_expect(((mdi->index_count == mdi->index_size) && (mdi->last_note == 0)), 0)) { WM_Unlock(&mdi->lock); return 0; } buffer_used = 0; memset(buffer, 0, size); do { if (__builtin_expect((!mdi->sample_count),0)) { if (__builtin_expect((mdi->index_count != mdi->index_size),1)) { do { if (__builtin_expect((mdi->index_count == mdi->index_size), 0)) { break; } if (__builtin_expect((mdi->index_count != 0), 1)) { do_event[((mdi->index[mdi->index_count].event & 0xF0) >> 4) - 8]((mdi->index[mdi->index_count].event & 0x0F), mdi, mdi->index[mdi->index_count].offset); } } while (mdi->index[mdi->index_count++].delta == 0); mdi->samples_to_mix += mdi->index[mdi->index_count-1].delta * mdi->samples_per_delta; mdi->sample_count = mdi->samples_to_mix >> 10; mdi->samples_to_mix %= 1024; } else { if (mdi->recalc_samples) { WM_RecalcSamples(mdi); } mdi->sample_count = mdi->info.approx_total_samples - mdi->info.current_sample; if (mdi->sample_count == 0) { WM_Unlock(&mdi->lock); return buffer_used; } } } if (__builtin_expect((mdi->sample_count > (size >> 2)),1)) { real_samples_to_mix = size >> 2; } else { real_samples_to_mix = mdi->sample_count; if (real_samples_to_mix == 0) { continue; } } // do mixing here count = real_samples_to_mix; do { note_data = mdi->note; left_mix = right_mix = 0; if (__builtin_expect((mdi->last_note != mdi->note),1)) { while (note_data != mdi->last_note) { /* * =================== * resample the sample * =================== */ data_pos = (*note_data)->sample_pos >> FPBITS; vol_mul = (((*note_data)->vol_lvl * ((*note_data)->env_level >> 12)) >> FPBITS); premix = ((*note_data)->sample->data[data_pos] + (((*note_data)->sample->data[data_pos + 1] - (*note_data)->sample->data[data_pos]) * (signed long int)((*note_data)->sample_pos & FPMASK) >> FPBITS)) * vol_mul / 1024; left_mix += premix * mdi->channel[(*note_data)->noteid >> 8].left_adjust; right_mix += premix * mdi->channel[(*note_data)->noteid >> 8].right_adjust; /* * ======================== * sample position checking * ======================== */ (*note_data)->sample_pos += (*note_data)->sample_inc; if (__builtin_expect(((*note_data)->sample_pos > (*note_data)->sample->loop_end), 0)) { if ((*note_data)->modes & SAMPLE_LOOP) { (*note_data)->sample_pos = (*note_data)->sample->loop_start + (((*note_data)->sample_pos - (*note_data)->sample->loop_start) % (*note_data)->sample->loop_size); } else if (__builtin_expect(((*note_data)->sample_pos >= (*note_data)->sample->data_length), 0)) { if (__builtin_expect(((*note_data)->next == NULL), 1)) { goto KILL_NOTE; } goto RESTART_NOTE; } } if (__builtin_expect(((*note_data)->env_inc == 0), 0)) { note_data++; continue; } (*note_data)->env_level += (*note_data)->env_inc; if (__builtin_expect(((*note_data)->env_level > 4194304), 0)) { (*note_data)->env_level = (*note_data)->sample->env_target[(*note_data)->env]; } if (__builtin_expect((((*note_data)->env_inc < 0) && ((*note_data)->env_level > (*note_data)->sample->env_target[(*note_data)->env])) || (((*note_data)->env_inc > 0) && ((*note_data)->env_level < (*note_data)->sample->env_target[(*note_data)->env])), 1)) { note_data++; continue; } (*note_data)->env_level = (*note_data)->sample->env_target[(*note_data)->env]; switch ((*note_data)->env) { case 0: if (!((*note_data)->modes & SAMPLE_ENVELOPE)) { (*note_data)->env_inc = 0; note_data++; continue; } break; case 2: if ((*note_data)->modes & SAMPLE_SUSTAIN) { (*note_data)->env_inc = 0; note_data++; continue; } break; case 5: if (__builtin_expect(((*note_data)->env_level == 0), 1)) { goto KILL_NOTE; } // sample release if ((*note_data)->modes & SAMPLE_LOOP) (*note_data)->modes ^= SAMPLE_LOOP; (*note_data)->env_inc = 0; note_data++; continue; case 6: if (__builtin_expect(((*note_data)->next != NULL), 1)) { RESTART_NOTE: (*note_data)->active = 0; *note_data = (*note_data)->next; (*note_data)->active = 1; note_data++; } else { KILL_NOTE: (*note_data)->active = 0; mdi->last_note--; if (note_data != mdi->last_note) { *note_data = *mdi->last_note; } } continue; } (*note_data)->env++; if ((*note_data)->env_level > (*note_data)->sample->env_target[(*note_data)->env]) { (*note_data)->env_inc = -(*note_data)->sample->env_rate[(*note_data)->env]; } else { (*note_data)->env_inc = (*note_data)->sample->env_rate[(*note_data)->env]; } note_data++; continue; } /* * ========================= * mix the channels together * ========================= */ left_mix /= 1024; right_mix /= 1024; } #ifdef EXPERIMENT_626 /* * ========================== * Experimental Reverb Engine * ========================== */ if (mdi->info.mixer_options & WM_MO_REVERB) { signed long int filteral = mdi->filter.delay[0][0][mdi->filter.delay_pos[0][0]]; signed long int filterar = mdi->filter.delay[0][1][mdi->filter.delay_pos[0][1]]; signed long int filterbl = mdi->filter.delay[1][0][mdi->filter.delay_pos[1][0]]; signed long int filterbr = mdi->filter.delay[1][1][mdi->filter.delay_pos[1][1]]; signed long int filtercl = mdi->filter.delay[2][0][mdi->filter.delay_pos[2][0]]; signed long int filtercr = mdi->filter.delay[2][1][mdi->filter.delay_pos[2][1]]; signed long int filterdl = mdi->filter.delay[3][0][mdi->filter.delay_pos[3][0]]; signed long int filterdr = mdi->filter.delay[3][1][mdi->filter.delay_pos[3][1]]; signed long int tfal = (a[0][0] * filteral + a[0][1] * mdi->filter.lowpass[0][0].in[0] + a[0][0] * mdi->filter.lowpass[0][0].in[1] - b[0][0] * mdi->filter.lowpass[0][0].out[0] - b[0][1] * mdi->filter.lowpass[0][0].out[1]) / 1024; signed long int tfar = (a[0][0] * filterar + a[0][1] * mdi->filter.lowpass[0][1].in[0] + a[0][0] * mdi->filter.lowpass[0][1].in[1] - b[0][0] * mdi->filter.lowpass[0][1].out[0] - b[0][1] * mdi->filter.lowpass[0][1].out[1]) / 1024; signed long int tfbl = (a[1][0] * filterbl + a[1][1] * mdi->filter.lowpass[1][0].in[0] + a[1][0] * mdi->filter.lowpass[1][0].in[1] - b[1][0] * mdi->filter.lowpass[1][0].out[0] - b[1][1] * mdi->filter.lowpass[1][0].out[1]) / 1024; signed long int tfbr = (a[1][0] * filterbr + a[1][1] * mdi->filter.lowpass[1][1].in[0] + a[1][0] * mdi->filter.lowpass[1][1].in[1] - b[1][0] * mdi->filter.lowpass[1][1].out[0] - b[1][1] * mdi->filter.lowpass[1][1].out[1]) / 1024; signed long int tfcl = (a[2][0] * filtercl + a[2][1] * mdi->filter.lowpass[2][0].in[0] + a[2][0] * mdi->filter.lowpass[2][0].in[1] - b[2][0] * mdi->filter.lowpass[2][0].out[0] - b[2][1] * mdi->filter.lowpass[2][0].out[1]) / 1024; signed long int tfcr = (a[2][0] * filtercr + a[2][1] * mdi->filter.lowpass[2][1].in[0] + a[2][0] * mdi->filter.lowpass[2][1].in[1] - b[2][0] * mdi->filter.lowpass[2][1].out[0] - b[2][1] * mdi->filter.lowpass[2][1].out[1]) / 1024; signed long int tfdl = (a[3][0] * filterdl + a[3][1] * mdi->filter.lowpass[3][0].in[0] + a[3][0] * mdi->filter.lowpass[3][0].in[1] - b[3][0] * mdi->filter.lowpass[3][0].out[0] - b[3][1] * mdi->filter.lowpass[3][0].out[1]) / 1024; signed long int tfdr = (a[3][0] * filterdr + a[3][1] * mdi->filter.lowpass[3][1].in[0] + a[3][0] * mdi->filter.lowpass[3][1].in[1] - b[3][0] * mdi->filter.lowpass[3][1].out[0] - b[3][1] * mdi->filter.lowpass[3][1].out[1]) / 1024; signed long int tfl, tflo; signed long int tfr, tfro; mdi->filter.lowpass[0][0].in[1] = mdi->filter.lowpass[0][0].in[0]; mdi->filter.lowpass[0][0].in[0] = filteral; mdi->filter.lowpass[0][1].in[1] = mdi->filter.lowpass[0][1].in[0]; mdi->filter.lowpass[0][1].in[0] = filterar; mdi->filter.lowpass[1][0].in[1] = mdi->filter.lowpass[1][0].in[0]; mdi->filter.lowpass[1][0].in[0] = filterbl; mdi->filter.lowpass[1][1].in[1] = mdi->filter.lowpass[1][1].in[0]; mdi->filter.lowpass[1][1].in[0] = filterbr; mdi->filter.lowpass[2][0].in[1] = mdi->filter.lowpass[2][0].in[0]; mdi->filter.lowpass[2][0].in[0] = filtercl; mdi->filter.lowpass[2][1].in[1] = mdi->filter.lowpass[2][1].in[0]; mdi->filter.lowpass[2][1].in[0] = filtercr; mdi->filter.lowpass[3][0].in[1] = mdi->filter.lowpass[3][0].in[0]; mdi->filter.lowpass[3][0].in[0] = filterdl; mdi->filter.lowpass[3][1].in[1] = mdi->filter.lowpass[3][1].in[0]; mdi->filter.lowpass[3][1].in[0] = filterdr; mdi->filter.lowpass[0][0].out[1] = mdi->filter.lowpass[0][0].out[0]; mdi->filter.lowpass[0][0].out[0] = tfal; mdi->filter.lowpass[0][1].out[1] = mdi->filter.lowpass[0][1].out[0]; mdi->filter.lowpass[0][1].out[0] = tfar; mdi->filter.lowpass[1][0].out[1] = mdi->filter.lowpass[1][0].out[0]; mdi->filter.lowpass[1][0].out[0] = tfbl; mdi->filter.lowpass[1][1].out[1] = mdi->filter.lowpass[1][1].out[0]; mdi->filter.lowpass[1][1].out[0] = tfbr; mdi->filter.lowpass[2][0].out[1] = mdi->filter.lowpass[2][0].out[0]; mdi->filter.lowpass[2][0].out[0] = tfcl; mdi->filter.lowpass[2][1].out[1] = mdi->filter.lowpass[2][1].out[0]; mdi->filter.lowpass[2][1].out[0] = tfcr; mdi->filter.lowpass[3][0].out[1] = mdi->filter.lowpass[3][0].out[0]; mdi->filter.lowpass[3][0].out[0] = tfdl; mdi->filter.lowpass[3][1].out[1] = mdi->filter.lowpass[3][1].out[0]; mdi->filter.lowpass[3][1].out[0] = tfdr; mdi->filter.delay[0][0][mdi->filter.delay_pos[0][0]] = (tfbr * 405 + tfcr * 368) / 1024 + (left_mix * gain_in[0] / 1024); mdi->filter.delay[0][1][mdi->filter.delay_pos[0][1]] = (tfbl * 402 + tfcl * 370) / 1024 + (right_mix * gain_in[0] / 1024); mdi->filter.delay[1][0][mdi->filter.delay_pos[1][0]] = (tfar * -545 + tfdr * -364) / 1024 + (left_mix * gain_in[1] / 1024); mdi->filter.delay[1][1][mdi->filter.delay_pos[1][1]] = (tfal * -550 + tfdl * -362) / 1024 + (right_mix * gain_in[1] / 1024); mdi->filter.delay[2][0][mdi->filter.delay_pos[2][0]] = (tfar * 545 + tfdr * -364) / 1024 + (left_mix * gain_in[2] / 1024); mdi->filter.delay[2][1][mdi->filter.delay_pos[2][1]] = (tfal * 550 + tfdl * 362) / 1024 + (right_mix * gain_in[2] / 1024); mdi->filter.delay[3][0][mdi->filter.delay_pos[3][0]] = (tfbr * 405 + tfcr * -368) / 1024 + (left_mix * gain_in[3] / 1024); mdi->filter.delay[3][1][mdi->filter.delay_pos[3][1]] = (tfbl * 402 + tfcl * -370) / 1024 + (right_mix * gain_in[3] / 1024); tfl = ((tfal * gain_out[0] / 1024) + (tfbl * gain_out[1] / 1024) + (tfcl * gain_out[2] / 1024) + (tfdl * gain_out[3] / 1024)); tfr = ((tfar * gain_out[0] / 1024) + (tfbr * gain_out[1] / 1024) + (tfcr * gain_out[2] / 1024) + (tfdr * gain_out[3] / 1024)); tflo = (a[4][0] * tfl + a[4][1] * mdi->filter.in[0][0] + a[4][0] * mdi->filter.in[1][0] - b[4][0] * mdi->filter.out[0][0] - b[4][1] * mdi->filter.out[1][0]) / 1024; tfro = (a[4][0] * tfr + a[4][1] * mdi->filter.in[0][1] + a[4][0] * mdi->filter.in[1][1] - b[4][0] * mdi->filter.out[0][1] - b[4][1] * mdi->filter.out[1][1]) / 1024; mdi->filter.in[1][0] = mdi->filter.in[0][0]; mdi->filter.in[0][0] = tfl; mdi->filter.in[1][1] = mdi->filter.in[0][1]; mdi->filter.in[0][1] = tfr; mdi->filter.out[1][0] = mdi->filter.out[0][0]; mdi->filter.out[0][0] = tflo; mdi->filter.out[1][1] = mdi->filter.out[0][1]; mdi->filter.out[0][1] = tfro; left_mix += tflo; right_mix += tfro; mdi->filter.delay_pos[0][0]++; mdi->filter.delay_pos[0][1]++; mdi->filter.delay_pos[1][0]++; mdi->filter.delay_pos[1][1]++; mdi->filter.delay_pos[2][0]++; mdi->filter.delay_pos[2][1]++; mdi->filter.delay_pos[3][0]++; mdi->filter.delay_pos[3][1]++; if (mdi->filter.delay_pos[0][0] == delay_size[0][0]) mdi->filter.delay_pos[0][0] = 0; if (mdi->filter.delay_pos[0][1] == delay_size[0][1]) mdi->filter.delay_pos[0][1] = 0; if (mdi->filter.delay_pos[1][0] == delay_size[1][0]) mdi->filter.delay_pos[1][0] = 0; if (mdi->filter.delay_pos[1][1] == delay_size[1][1]) mdi->filter.delay_pos[1][1] = 0; if (mdi->filter.delay_pos[2][0] == delay_size[2][0]) mdi->filter.delay_pos[2][0] = 0; if (mdi->filter.delay_pos[2][1] == delay_size[2][1]) mdi->filter.delay_pos[2][1] = 0; if (mdi->filter.delay_pos[3][0] == delay_size[3][0]) mdi->filter.delay_pos[3][0] = 0; if (mdi->filter.delay_pos[3][1] == delay_size[3][1]) mdi->filter.delay_pos[3][1] = 0; } #endif if (left_mix > 32767) { left_mix = 32767; } else if (left_mix < -32768) { left_mix = -32768; } if (right_mix > 32767) { right_mix = 32767; } else if (right_mix < -32768) { right_mix = -32768; } /* * =================== * Write to the buffer * =================== */ (*buffer++) = left_mix & 0xff; (*buffer++) = (left_mix >> 8) & 0xff; (*buffer++) = right_mix & 0xff; (*buffer++) = (right_mix >> 8) & 0xff; } while (--count); buffer_used += real_samples_to_mix * 4; size -= (real_samples_to_mix << 2); mdi->info.current_sample += real_samples_to_mix; mdi->sample_count -= real_samples_to_mix; if (mdi->index_count == mdi->index_size) { if (mdi->last_note == 0) { mdi->sample_count = 0; WM_Unlock(&mdi->lock); return buffer_used; } } } while (size); if ((mdi->index_count == mdi->index_size) && (mdi->recalc_samples)) { WM_RecalcSamples(mdi); mdi->sample_count = mdi->info.approx_total_samples - mdi->info.current_sample; } WM_Unlock(&mdi->lock); return buffer_used; } int WildMidi_GetOutput_Gauss (midi * handle, char * buffer, unsigned long int size) { unsigned long int buffer_used = 0; struct _mdi *mdi = (struct _mdi *)handle; unsigned long int real_samples_to_mix = 0; unsigned long int data_pos; signed long int premix, left_mix, right_mix; signed long int vol_mul; struct _note **note_data = NULL; unsigned long int count; signed short int *sptr; double y, xd; float *gptr, *gend; int left, right, temp_n; int ii, jj; if (__builtin_expect((!WM_Initialized),0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); return -1; } if (__builtin_expect((handle == NULL),0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL handle)", 0); return -1; } if (__builtin_expect((buffer == NULL),0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL buffer pointer)", 0); return -1; } if (__builtin_expect((size == 0),0)) { return 0; } if (__builtin_expect((size % 4),0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(size not a multiple of 4)", 0); return -1; } WM_Lock(&mdi->lock); if (__builtin_expect(((mdi->index_count == mdi->index_size) && (mdi->last_note == 0)), 0)) { WM_Unlock(&mdi->lock); return 0; } buffer_used = 0; memset(buffer, 0, size); do { if (__builtin_expect((!mdi->sample_count),0)) { if (__builtin_expect((mdi->index_count != mdi->index_size),1)) { do { if (__builtin_expect((mdi->index_count == mdi->index_size), 0)) { break; } if (__builtin_expect((mdi->index_count != 0), 1)) { do_event[((mdi->index[mdi->index_count].event & 0xF0) >> 4) - 8]((mdi->index[mdi->index_count].event & 0x0F), mdi, mdi->index[mdi->index_count].offset); } } while (mdi->index[mdi->index_count++].delta == 0); mdi->samples_to_mix += mdi->index[mdi->index_count-1].delta * mdi->samples_per_delta; mdi->sample_count = mdi->samples_to_mix >> 10; mdi->samples_to_mix %= 1024; } else { if (mdi->recalc_samples) { WM_RecalcSamples(mdi); } mdi->sample_count = mdi->info.approx_total_samples - mdi->info.current_sample; if (mdi->sample_count == 0) { WM_Unlock(&mdi->lock); return buffer_used; } } } if (__builtin_expect((mdi->sample_count > (size >> 2)),1)) { real_samples_to_mix = size >> 2; } else { real_samples_to_mix = mdi->sample_count; if (real_samples_to_mix == 0) { continue; } } // do mixing here count = real_samples_to_mix; do { note_data = mdi->note; left_mix = right_mix = 0; if (__builtin_expect((mdi->last_note != mdi->note),1)) { while (note_data != mdi->last_note) { /* * =================== * resample the sample * =================== */ data_pos = (*note_data)->sample_pos >> FPBITS; vol_mul = (((*note_data)->vol_lvl * ((*note_data)->env_level >> 12)) >> FPBITS); /* check to see if we're near one of the ends */ left = data_pos; right = ((*note_data)->sample->data_length>>FPBITS)- left -1; temp_n = (right<<1)-1; if (temp_n <= 0) temp_n = 1; if (temp_n > (left<<1)+1) temp_n = (left<<1)+1; /* use Newton if we can't fill the window */ if (temp_n < gauss_n) { xd = (*note_data)->sample_pos & FPMASK; xd /= (1L<>1; y = 0; sptr = (*note_data)->sample->data + ((*note_data)->sample_pos>>FPBITS) - (temp_n>>1); for (ii = temp_n; ii;) { for (jj = 0; jj <= ii; jj++) y += sptr[jj] * newt_coeffs[ii][jj]; y *= xd - --ii; } y += *sptr; } else { /* otherwise, use Gauss as usual */ y = 0; gptr = gauss_table[(*note_data)->sample_pos & FPMASK]; gend = gptr + gauss_n; sptr = (*note_data)->sample->data + ((*note_data)->sample_pos >> FPBITS) - (gauss_n>>1); do { y += *(sptr++) * *(gptr++); } while (gptr <= gend); } premix = y * vol_mul / 1024; left_mix += premix * mdi->channel[(*note_data)->noteid >> 8].left_adjust; right_mix += premix * mdi->channel[(*note_data)->noteid >> 8].right_adjust; /* * ======================== * sample position checking * ======================== */ (*note_data)->sample_pos += (*note_data)->sample_inc; if (__builtin_expect(((*note_data)->sample_pos > (*note_data)->sample->loop_end), 0)) { if ((*note_data)->modes & SAMPLE_LOOP) { (*note_data)->sample_pos = (*note_data)->sample->loop_start + (((*note_data)->sample_pos - (*note_data)->sample->loop_start) % (*note_data)->sample->loop_size); } else if (__builtin_expect(((*note_data)->sample_pos >= (*note_data)->sample->data_length), 0)) { if (__builtin_expect(((*note_data)->next == NULL), 1)) { goto KILL_NOTE; } goto RESTART_NOTE; } } if (__builtin_expect(((*note_data)->env_inc == 0), 0)) { note_data++; continue; } (*note_data)->env_level += (*note_data)->env_inc; if (__builtin_expect(((*note_data)->env_level > 4194304), 0)) { (*note_data)->env_level = (*note_data)->sample->env_target[(*note_data)->env]; } if (__builtin_expect((((*note_data)->env_inc < 0) && ((*note_data)->env_level > (*note_data)->sample->env_target[(*note_data)->env])) || (((*note_data)->env_inc > 0) && ((*note_data)->env_level < (*note_data)->sample->env_target[(*note_data)->env])), 1)) { note_data++; continue; } (*note_data)->env_level = (*note_data)->sample->env_target[(*note_data)->env]; switch ((*note_data)->env) { case 0: if (!((*note_data)->modes & SAMPLE_ENVELOPE)) { (*note_data)->env_inc = 0; note_data++; continue; } break; case 2: if ((*note_data)->modes & SAMPLE_SUSTAIN) { (*note_data)->env_inc = 0; note_data++; continue; } break; case 5: if (__builtin_expect(((*note_data)->env_level == 0), 1)) { goto KILL_NOTE; } // sample release if ((*note_data)->modes & SAMPLE_LOOP) (*note_data)->modes ^= SAMPLE_LOOP; (*note_data)->env_inc = 0; note_data++; continue; case 6: if (__builtin_expect(((*note_data)->next != NULL), 1)) { RESTART_NOTE: (*note_data)->active = 0; *note_data = (*note_data)->next; (*note_data)->active = 1; note_data++; } else { KILL_NOTE: (*note_data)->active = 0; mdi->last_note--; if (note_data != mdi->last_note) { *note_data = *mdi->last_note; } } continue; } (*note_data)->env++; if ((*note_data)->env_level > (*note_data)->sample->env_target[(*note_data)->env]) { (*note_data)->env_inc = -(*note_data)->sample->env_rate[(*note_data)->env]; } else { (*note_data)->env_inc = (*note_data)->sample->env_rate[(*note_data)->env]; } note_data++; continue; } /* * ========================= * mix the channels together * ========================= */ left_mix /= 1024; right_mix /= 1024; } #ifdef EXPERIMENT_626 /* * ========================== * Experimental Reverb Engine * ========================== */ if (mdi->info.mixer_options & WM_MO_REVERB) { signed long int filteral = mdi->filter.delay[0][0][mdi->filter.delay_pos[0][0]]; signed long int filterar = mdi->filter.delay[0][1][mdi->filter.delay_pos[0][1]]; signed long int filterbl = mdi->filter.delay[1][0][mdi->filter.delay_pos[1][0]]; signed long int filterbr = mdi->filter.delay[1][1][mdi->filter.delay_pos[1][1]]; signed long int filtercl = mdi->filter.delay[2][0][mdi->filter.delay_pos[2][0]]; signed long int filtercr = mdi->filter.delay[2][1][mdi->filter.delay_pos[2][1]]; signed long int filterdl = mdi->filter.delay[3][0][mdi->filter.delay_pos[3][0]]; signed long int filterdr = mdi->filter.delay[3][1][mdi->filter.delay_pos[3][1]]; signed long int tfal = (a[0][0] * filteral + a[0][1] * mdi->filter.lowpass[0][0].in[0] + a[0][0] * mdi->filter.lowpass[0][0].in[1] - b[0][0] * mdi->filter.lowpass[0][0].out[0] - b[0][1] * mdi->filter.lowpass[0][0].out[1]) / 1024; signed long int tfar = (a[0][0] * filterar + a[0][1] * mdi->filter.lowpass[0][1].in[0] + a[0][0] * mdi->filter.lowpass[0][1].in[1] - b[0][0] * mdi->filter.lowpass[0][1].out[0] - b[0][1] * mdi->filter.lowpass[0][1].out[1]) / 1024; signed long int tfbl = (a[1][0] * filterbl + a[1][1] * mdi->filter.lowpass[1][0].in[0] + a[1][0] * mdi->filter.lowpass[1][0].in[1] - b[1][0] * mdi->filter.lowpass[1][0].out[0] - b[1][1] * mdi->filter.lowpass[1][0].out[1]) / 1024; signed long int tfbr = (a[1][0] * filterbr + a[1][1] * mdi->filter.lowpass[1][1].in[0] + a[1][0] * mdi->filter.lowpass[1][1].in[1] - b[1][0] * mdi->filter.lowpass[1][1].out[0] - b[1][1] * mdi->filter.lowpass[1][1].out[1]) / 1024; signed long int tfcl = (a[2][0] * filtercl + a[2][1] * mdi->filter.lowpass[2][0].in[0] + a[2][0] * mdi->filter.lowpass[2][0].in[1] - b[2][0] * mdi->filter.lowpass[2][0].out[0] - b[2][1] * mdi->filter.lowpass[2][0].out[1]) / 1024; signed long int tfcr = (a[2][0] * filtercr + a[2][1] * mdi->filter.lowpass[2][1].in[0] + a[2][0] * mdi->filter.lowpass[2][1].in[1] - b[2][0] * mdi->filter.lowpass[2][1].out[0] - b[2][1] * mdi->filter.lowpass[2][1].out[1]) / 1024; signed long int tfdl = (a[3][0] * filterdl + a[3][1] * mdi->filter.lowpass[3][0].in[0] + a[3][0] * mdi->filter.lowpass[3][0].in[1] - b[3][0] * mdi->filter.lowpass[3][0].out[0] - b[3][1] * mdi->filter.lowpass[3][0].out[1]) / 1024; signed long int tfdr = (a[3][0] * filterdr + a[3][1] * mdi->filter.lowpass[3][1].in[0] + a[3][0] * mdi->filter.lowpass[3][1].in[1] - b[3][0] * mdi->filter.lowpass[3][1].out[0] - b[3][1] * mdi->filter.lowpass[3][1].out[1]) / 1024; signed long int tfl, tflo; signed long int tfr, tfro; mdi->filter.lowpass[0][0].in[1] = mdi->filter.lowpass[0][0].in[0]; mdi->filter.lowpass[0][0].in[0] = filteral; mdi->filter.lowpass[0][1].in[1] = mdi->filter.lowpass[0][1].in[0]; mdi->filter.lowpass[0][1].in[0] = filterar; mdi->filter.lowpass[1][0].in[1] = mdi->filter.lowpass[1][0].in[0]; mdi->filter.lowpass[1][0].in[0] = filterbl; mdi->filter.lowpass[1][1].in[1] = mdi->filter.lowpass[1][1].in[0]; mdi->filter.lowpass[1][1].in[0] = filterbr; mdi->filter.lowpass[2][0].in[1] = mdi->filter.lowpass[2][0].in[0]; mdi->filter.lowpass[2][0].in[0] = filtercl; mdi->filter.lowpass[2][1].in[1] = mdi->filter.lowpass[2][1].in[0]; mdi->filter.lowpass[2][1].in[0] = filtercr; mdi->filter.lowpass[3][0].in[1] = mdi->filter.lowpass[3][0].in[0]; mdi->filter.lowpass[3][0].in[0] = filterdl; mdi->filter.lowpass[3][1].in[1] = mdi->filter.lowpass[3][1].in[0]; mdi->filter.lowpass[3][1].in[0] = filterdr; mdi->filter.lowpass[0][0].out[1] = mdi->filter.lowpass[0][0].out[0]; mdi->filter.lowpass[0][0].out[0] = tfal; mdi->filter.lowpass[0][1].out[1] = mdi->filter.lowpass[0][1].out[0]; mdi->filter.lowpass[0][1].out[0] = tfar; mdi->filter.lowpass[1][0].out[1] = mdi->filter.lowpass[1][0].out[0]; mdi->filter.lowpass[1][0].out[0] = tfbl; mdi->filter.lowpass[1][1].out[1] = mdi->filter.lowpass[1][1].out[0]; mdi->filter.lowpass[1][1].out[0] = tfbr; mdi->filter.lowpass[2][0].out[1] = mdi->filter.lowpass[2][0].out[0]; mdi->filter.lowpass[2][0].out[0] = tfcl; mdi->filter.lowpass[2][1].out[1] = mdi->filter.lowpass[2][1].out[0]; mdi->filter.lowpass[2][1].out[0] = tfcr; mdi->filter.lowpass[3][0].out[1] = mdi->filter.lowpass[3][0].out[0]; mdi->filter.lowpass[3][0].out[0] = tfdl; mdi->filter.lowpass[3][1].out[1] = mdi->filter.lowpass[3][1].out[0]; mdi->filter.lowpass[3][1].out[0] = tfdr; mdi->filter.delay[0][0][mdi->filter.delay_pos[0][0]] = (tfbr * 405 + tfcr * 368) / 1024 + (left_mix * gain_in[0] / 1024); mdi->filter.delay[0][1][mdi->filter.delay_pos[0][1]] = (tfbl * 402 + tfcl * 370) / 1024 + (right_mix * gain_in[0] / 1024); mdi->filter.delay[1][0][mdi->filter.delay_pos[1][0]] = (tfar * -545 + tfdr * -364) / 1024 + (left_mix * gain_in[1] / 1024); mdi->filter.delay[1][1][mdi->filter.delay_pos[1][1]] = (tfal * -550 + tfdl * -362) / 1024 + (right_mix * gain_in[1] / 1024); mdi->filter.delay[2][0][mdi->filter.delay_pos[2][0]] = (tfar * 545 + tfdr * -364) / 1024 + (left_mix * gain_in[2] / 1024); mdi->filter.delay[2][1][mdi->filter.delay_pos[2][1]] = (tfal * 550 + tfdl * 362) / 1024 + (right_mix * gain_in[2] / 1024); mdi->filter.delay[3][0][mdi->filter.delay_pos[3][0]] = (tfbr * 405 + tfcr * -368) / 1024 + (left_mix * gain_in[3] / 1024); mdi->filter.delay[3][1][mdi->filter.delay_pos[3][1]] = (tfbl * 402 + tfcl * -370) / 1024 + (right_mix * gain_in[3] / 1024); tfl = ((tfal * gain_out[0] / 1024) + (tfbl * gain_out[1] / 1024) + (tfcl * gain_out[2] / 1024) + (tfdl * gain_out[3] / 1024)); tfr = ((tfar * gain_out[0] / 1024) + (tfbr * gain_out[1] / 1024) + (tfcr * gain_out[2] / 1024) + (tfdr * gain_out[3] / 1024)); tflo = (a[4][0] * tfl + a[4][1] * mdi->filter.in[0][0] + a[4][0] * mdi->filter.in[1][0] - b[4][0] * mdi->filter.out[0][0] - b[4][1] * mdi->filter.out[1][0]) / 1024; tfro = (a[4][0] * tfr + a[4][1] * mdi->filter.in[0][1] + a[4][0] * mdi->filter.in[1][1] - b[4][0] * mdi->filter.out[0][1] - b[4][1] * mdi->filter.out[1][1]) / 1024; mdi->filter.in[1][0] = mdi->filter.in[0][0]; mdi->filter.in[0][0] = tfl; mdi->filter.in[1][1] = mdi->filter.in[0][1]; mdi->filter.in[0][1] = tfr; mdi->filter.out[1][0] = mdi->filter.out[0][0]; mdi->filter.out[0][0] = tflo; mdi->filter.out[1][1] = mdi->filter.out[0][1]; mdi->filter.out[0][1] = tfro; left_mix += tflo; right_mix += tfro; mdi->filter.delay_pos[0][0]++; mdi->filter.delay_pos[0][1]++; mdi->filter.delay_pos[1][0]++; mdi->filter.delay_pos[1][1]++; mdi->filter.delay_pos[2][0]++; mdi->filter.delay_pos[2][1]++; mdi->filter.delay_pos[3][0]++; mdi->filter.delay_pos[3][1]++; if (mdi->filter.delay_pos[0][0] == delay_size[0][0]) mdi->filter.delay_pos[0][0] = 0; if (mdi->filter.delay_pos[0][1] == delay_size[0][1]) mdi->filter.delay_pos[0][1] = 0; if (mdi->filter.delay_pos[1][0] == delay_size[1][0]) mdi->filter.delay_pos[1][0] = 0; if (mdi->filter.delay_pos[1][1] == delay_size[1][1]) mdi->filter.delay_pos[1][1] = 0; if (mdi->filter.delay_pos[2][0] == delay_size[2][0]) mdi->filter.delay_pos[2][0] = 0; if (mdi->filter.delay_pos[2][1] == delay_size[2][1]) mdi->filter.delay_pos[2][1] = 0; if (mdi->filter.delay_pos[3][0] == delay_size[3][0]) mdi->filter.delay_pos[3][0] = 0; if (mdi->filter.delay_pos[3][1] == delay_size[3][1]) mdi->filter.delay_pos[3][1] = 0; } #endif if (left_mix > 32767) { left_mix = 32767; } else if (left_mix < -32768) { left_mix = -32768; } if (right_mix > 32767) { right_mix = 32767; } else if (right_mix < -32768) { right_mix = -32768; } /* * =================== * Write to the buffer * =================== */ (*buffer++) = left_mix & 0xff; (*buffer++) = (left_mix >> 8) & 0xff; (*buffer++) = right_mix & 0xff; (*buffer++) = (right_mix >> 8) & 0xff; } while (--count); buffer_used += real_samples_to_mix * 4; size -= (real_samples_to_mix << 2); mdi->info.current_sample += real_samples_to_mix; mdi->sample_count -= real_samples_to_mix; if (mdi->index_count == mdi->index_size) { if (mdi->last_note == 0) { mdi->sample_count = 0; WM_Unlock(&mdi->lock); return buffer_used; } } } while (size); if ((mdi->index_count == mdi->index_size) && (mdi->recalc_samples)) { WM_RecalcSamples(mdi); mdi->sample_count = mdi->info.approx_total_samples - mdi->info.current_sample; } WM_Unlock(&mdi->lock); return buffer_used; } int WildMidi_GetOutput (midi * handle, char * buffer, unsigned long int size) { struct _mdi *mdi = (struct _mdi *)handle; if (__builtin_expect((!WM_Initialized),0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); return -1; } if (__builtin_expect((handle == NULL),0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL handle)", 0); return -1; } if (__builtin_expect((buffer == NULL),0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL buffer pointer)", 0); return -1; } if (__builtin_expect((size == 0),0)) { return 0; } if (__builtin_expect((size % 4),0)) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(size not a multiple of 4)", 0); return -1; } if (mdi->info.mixer_options & WM_MO_EXPENSIVE_INTERPOLATION) { return WildMidi_GetOutput_Gauss (handle, buffer,size); } else { return WildMidi_GetOutput_Linear (handle, buffer, size); } } int WildMidi_SetOption (midi * handle, unsigned short int options, unsigned short int setting) { struct _mdi *mdi = (struct _mdi *)handle; struct _note **note_data = mdi->note; int i; if (!WM_Initialized) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); return -1; } if (handle == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL handle)", 0); return -1; } WM_Lock(&mdi->lock); if ((!(options & 0x0007)) || (options & 0xFFF8)){ WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(invalid option)", 0); WM_Unlock(&mdi->lock); return -1; } if (setting & 0xFFF8) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(invalid setting)", 0); WM_Unlock(&mdi->lock); return -1; } mdi->info.mixer_options = ((mdi->info.mixer_options & (0x00FF ^ options)) | (options & setting)); if (options & WM_MO_LINEAR_VOLUME) { if (mdi->info.mixer_options & WM_MO_LINEAR_VOLUME) { mdi->amp = 281; } else { mdi->amp = 281 * mdi->lin_max_vol / mdi->log_max_vol; } for (i = 0; i < 16; i++) { do_pan_adjust(mdi, i); } if (note_data != mdi->last_note) { do { (*note_data)->vol_lvl = get_volume(mdi, ((*note_data)->noteid >> 8), *note_data); if ((*note_data)->next) (*note_data)->next->vol_lvl = get_volume(mdi, ((*note_data)->noteid >> 8), (*note_data)->next); note_data++; } while (note_data != mdi->last_note); } } if (options & WM_MO_REVERB) { for (i = 0; i < 4; i++) { mdi->filter.lowpass[i][0].in[0] = 0; mdi->filter.lowpass[i][0].in[1] = 0; mdi->filter.lowpass[i][1].in[0] = 0; mdi->filter.lowpass[i][1].in[1] = 0; mdi->filter.lowpass[i][0].out[0] = 0; mdi->filter.lowpass[i][0].out[1] = 0; mdi->filter.lowpass[i][1].out[0] = 0; mdi->filter.lowpass[i][1].out[1] = 0; mdi->filter.delay_pos[i][0] = 0; mdi->filter.delay_pos[i][1] = 0; memset (mdi->filter.delay[i][0], 0, (delay_size[i][0] * sizeof(signed long int))); memset (mdi->filter.delay[i][1], 0, (delay_size[i][1] * sizeof(signed long int))); } } WM_Unlock(&mdi->lock); return 0; } struct _WM_Info * WildMidi_GetInfo (midi * handle) { struct _mdi *mdi = (struct _mdi *)handle; if (!WM_Initialized) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); return NULL; } if (handle == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL handle)", 0); return NULL; } WM_Lock(&mdi->lock); if (mdi->tmp_info == NULL) { mdi->tmp_info = malloc(sizeof(struct _WM_Info)); if (mdi->tmp_info == NULL) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to set info", 0); WM_Unlock(&mdi->lock); return NULL; } } mdi->tmp_info->current_sample = mdi->info.current_sample; mdi->tmp_info->approx_total_samples = mdi->info.approx_total_samples; mdi->tmp_info->mixer_options = mdi->info.mixer_options; WM_Unlock(&mdi->lock); return mdi->tmp_info; } int WildMidi_Shutdown ( void ) { struct _hndl * tmp_hdle; if (!WM_Initialized) { WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); return -1; } if (first_handle != NULL) { while (first_handle != NULL) { tmp_hdle = first_handle->next; WildMidi_Close((struct _mdi *)first_handle->handle); free (first_handle); first_handle = tmp_hdle; } } WM_FreePatches(); free_gauss (); WM_Initialized = 0; return 0; }