2015-11-28 16:38:40 +00:00
/*
wildmidi_lib . c
Midi Wavetable Processing library
Copyright ( C ) Chris Ison 2001 - 2014
Copyright ( C ) Bret Curtis 2013 - 2014
This file is part of WildMIDI .
WildMIDI is free software : you can redistribute and / or modify the player
under the terms of the GNU General Public License and you can redistribute
and / or modify the library under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation , either version 3 of
the licenses , or ( at your option ) any later version .
WildMIDI 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 General Public License and
the GNU Lesser General Public License for more details .
You should have received a copy of the GNU General Public License and the
GNU Lesser General Public License along with WildMIDI . If not , see
< http : //www.gnu.org/licenses/>.
*/
//#include "config.h"
# define UNUSED(x) (void)(x)
# include <errno.h>
# include <fcntl.h>
# include <math.h>
# ifndef _WIN32
# include <pwd.h>
# include <strings.h>
# include <unistd.h>
# endif
# include <stdarg.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <sys/stat.h>
# include <sys/types.h>
# include "common.h"
# include "wm_error.h"
# include "file_io.h"
# include "reverb.h"
# include "gus_pat.h"
# include "wildmidi_lib.h"
2015-12-29 22:24:16 +00:00
# include "critsec.h"
2018-02-22 21:35:49 +00:00
# include "files.h"
# include "i_soundfont.h"
2015-11-28 16:38:40 +00:00
# define IS_DIR_SEPARATOR(c) ((c) == ' / ' || (c) == '\\')
# ifdef _WIN32
# define HAS_DRIVE_SPEC(f) ((f)[0] && ((f)[1] == ':'))
# else
# define HAS_DRIVE_SPEC(f) (0)
# endif
# define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || HAS_DRIVE_SPEC((f)))
/*
* = = = = = = = = = = = = = = = = = = = = = = = = =
* Global Data and Data Structs
* = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# define MEM_CHUNK 8192
static int WM_Initialized = 0 ;
static signed short int WM_MasterVolume = 948 ;
static unsigned short int WM_MixerOptions = 0 ;
static char WM_Version [ ] = " WildMidi Processing Library " ;
unsigned short int _WM_SampleRate ;
static struct _patch * patch [ 128 ] ;
static float reverb_room_width = 16.875f ;
static float reverb_room_length = 22.5f ;
static float reverb_listen_posx = 8.4375f ;
static float reverb_listen_posy = 16.875f ;
static int fix_release = 0 ;
static int auto_amp = 0 ;
static int auto_amp_with_amp = 0 ;
2015-12-29 22:24:16 +00:00
static FCriticalSection patch_lock ;
2018-02-22 21:35:49 +00:00
extern std : : unique_ptr < FSoundFontReader > wm_sfreader ;
2015-11-28 16:38:40 +00:00
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 ;
unsigned char reg_non ;
unsigned char isdrum ;
} ;
# define HOLD_OFF 0x02
struct _note {
unsigned short noteid ;
unsigned char velocity ;
struct _patch * patch ;
struct _sample * sample ;
2016-01-12 01:21:41 +00:00
unsigned int sample_pos ;
unsigned int sample_inc ;
signed int env_inc ;
2015-11-28 16:38:40 +00:00
unsigned char env ;
2016-01-12 01:21:41 +00:00
signed int env_level ;
2015-11-28 16:38:40 +00:00
unsigned char modes ;
unsigned char hold ;
unsigned char active ;
struct _note * replay ;
struct _note * next ;
2016-01-12 01:21:41 +00:00
unsigned int left_mix_volume ;
unsigned int right_mix_volume ;
2015-11-28 16:38:40 +00:00
unsigned char is_off ;
} ;
struct _event_data {
unsigned char channel ;
2016-01-12 01:21:41 +00:00
unsigned int data ;
2015-11-28 16:38:40 +00:00
} ;
struct _mdi {
2015-12-29 22:24:16 +00:00
_mdi ( )
{
samples_to_mix = 0 ;
midi_master_vol = 0 ;
memset ( & info , 0 , sizeof ( info ) ) ;
tmp_info = NULL ;
memset ( & channel , 0 , sizeof ( channel ) ) ;
note = NULL ;
memset ( note_table , 0 , sizeof ( note_table ) ) ;
patches = NULL ;
patch_count = 0 ;
amp = 0 ;
mix_buffer = NULL ;
2015-12-30 09:58:52 +00:00
mix_buffer_size = 0 ;
2015-12-29 22:24:16 +00:00
reverb = NULL ;
}
FCriticalSection lock ;
2015-11-28 16:38:40 +00:00
unsigned long int samples_to_mix ;
unsigned short midi_master_vol ;
struct _WM_Info info ;
struct _WM_Info * tmp_info ;
struct _channel channel [ 16 ] ;
struct _note * note ;
struct _note note_table [ 2 ] [ 16 ] [ 128 ] ;
struct _patch * * patches ;
unsigned long int patch_count ;
signed short int amp ;
2015-12-29 02:33:41 +00:00
signed int * mix_buffer ;
2015-11-28 16:38:40 +00:00
unsigned long int mix_buffer_size ;
struct _rvb * reverb ;
} ;
# define FPBITS 10
# define FPMASK ((1L<<FPBITS)-1L)
/* Gauss Interpolation code adapted from code supplied by Eric. A. Welsh */
static double newt_coeffs [ 58 ] [ 58 ] ; /* for start/end of samples */
# define MAX_GAUSS_ORDER 34 /* 34 is as high as we can go before errors crop up */
static double * gauss_table = NULL ; /* *gauss_table[1<<FPBITS] */
static int gauss_n = MAX_GAUSS_ORDER ;
2015-12-29 22:24:16 +00:00
static FCriticalSection gauss_lock ;
2015-11-28 16:38:40 +00:00
static void init_gauss ( void ) {
/* init gauss table */
int n = gauss_n ;
int m , i , k , n_half = ( n > > 1 ) ;
int j ;
int sign ;
double ck ;
double x , x_inc , xz ;
double z [ 35 ] ;
double * gptr , * t ;
2015-12-29 22:24:16 +00:00
gauss_lock . Enter ( ) ;
2015-11-28 16:38:40 +00:00
if ( gauss_table ) {
2015-12-29 22:24:16 +00:00
gauss_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return ;
}
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 = ( int ) pow ( - 1. , i ) ; j < = i ; j + + , sign * = - 1 )
newt_coeffs [ i ] [ j ] * = sign ;
t = ( double * ) malloc ( ( 1 < < FPBITS ) * ( n + 1 ) * sizeof ( double ) ) ;
x_inc = 1.0 / ( 1 < < FPBITS ) ;
for ( m = 0 , x = 0.0 ; m < ( 1 < < FPBITS ) ; m + + , x + = x_inc ) {
xz = ( x + n_half ) / ( 4 * M_PI ) ;
gptr = & t [ m * ( n + 1 ) ] ;
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 ;
}
}
gauss_table = t ;
2015-12-29 22:24:16 +00:00
gauss_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
}
static void free_gauss ( void ) {
2015-12-29 22:24:16 +00:00
gauss_lock . Enter ( ) ;
2015-11-28 16:38:40 +00:00
free ( gauss_table ) ;
gauss_table = NULL ;
2015-12-29 22:24:16 +00:00
gauss_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
}
struct _hndl {
void * handle ;
struct _hndl * next ;
struct _hndl * prev ;
} ;
static struct _hndl * first_handle = NULL ;
/* f: ( VOLUME / 127.0 ) * 1024.0 */
static 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 } ;
2016-01-12 01:21:41 +00:00
/* f: As per midi 2 standard */
static float dBm_volume [ ] = { - 999999.999999f , - 84.15214884f , - 72.11094901f ,
- 65.06729865f , - 60.06974919f , - 56.19334866f , - 53.02609882f , - 50.34822724f ,
- 48.02854936f , - 45.98244846f , - 44.15214884f , - 42.49644143f , - 40.984899f ,
- 39.59441475f , - 38.30702741f , - 37.10849848f , - 35.98734953f , - 34.93419198f ,
- 33.94124863f , - 33.0020048f , - 32.11094901f , - 31.26337705f , - 30.45524161f ,
- 29.6830354f , - 28.94369917f , - 28.23454849f , - 27.55321492f , - 26.89759827f ,
- 26.26582758f , - 25.65622892f , - 25.06729865f , - 24.49768108f , - 23.94614971f ,
- 23.41159124f , - 22.89299216f , - 22.38942706f , - 21.90004881f , - 21.42407988f ,
- 20.96080497f , - 20.50956456f , - 20.06974919f , - 19.64079457f , - 19.22217722f ,
- 18.81341062f , - 18.41404178f , - 18.02364829f , - 17.64183557f , - 17.26823452f ,
- 16.90249934f , - 16.54430564f , - 16.19334866f , - 15.84934179f , - 15.51201509f ,
- 15.18111405f , - 14.85639845f , - 14.53764126f , - 14.22462776f , - 13.91715461f ,
- 13.6150291f , - 13.31806837f , - 13.02609882f , - 12.73895544f , - 12.45648126f ,
- 12.17852686f , - 11.90494988f , - 11.63561457f , - 11.37039142f , - 11.10915673f ,
- 10.85179233f , - 10.59818521f , - 10.34822724f , - 10.10181489f , - 9.858848981f ,
- 9.619234433f , - 9.382880049f , - 9.149698303f , - 8.919605147f , - 8.692519831f ,
- 8.468364731f , - 8.247065187f , - 8.028549359f , - 7.812748083f , - 7.599594743f ,
- 7.389025143f , - 7.180977396f , - 6.97539181f , - 6.772210788f , - 6.571378733f ,
- 6.372841952f , - 6.176548572f , - 5.982448461f , - 5.790493145f , - 5.600635744f ,
- 5.412830896f , - 5.227034694f , - 5.043204627f , - 4.861299517f , - 4.681279468f ,
- 4.503105811f , - 4.326741054f , - 4.152148838f , - 3.979293887f , - 3.808141968f ,
- 3.63865985f , - 3.470815266f , - 3.304576875f , - 3.139914228f , - 2.976797731f ,
- 2.815198619f , - 2.655088921f , - 2.496441432f , - 2.339229687f , - 2.183427931f ,
- 2.029011099f , - 1.875954785f , - 1.724235224f , - 1.573829269f , - 1.424714368f ,
- 1.276868546f , - 1.130270383f , - 0.9848989963f , - 0.8407340256f , - 0.6977556112f ,
- 0.5559443807f , - 0.4152814317f , - 0.2757483179f , - 0.1373270335f , 0 } ;
/* f: As per midi 2 standard */
2016-01-12 02:01:14 +00:00
static float dBm_pan_volume [ 127 ] = {
- 999999.999999f , - 87.6945020928f , - 73.8331126923f , - 65.7264009888f ,
- 59.9763864074f , - 55.5181788833f , - 51.8774481743f , - 48.8011722841f ,
- 46.1383198371f , - 43.7914727130f , - 41.6941147218f , - 39.7988027954f ,
- 38.0705069530f , - 36.4826252703f , - 35.0144798827f , - 33.6496789707f ,
- 32.3750084716f , - 31.1796603753f , - 30.0546819321f , - 28.9925739783f ,
- 27.9869924122f , - 27.0325225804f , - 26.1245061976f , - 25.2589067713f ,
- 24.4322036893f , - 23.6413079424f , - 22.8834943857f , - 22.1563467917f ,
- 21.4577129008f , - 20.7856673630f , - 20.1384809653f , - 19.5145949062f ,
- 18.9125991563f , - 18.3312141503f , - 17.7692752119f , - 17.2257192381f ,
- 16.6995732597f , - 16.1899445690f , - 15.6960121652f , - 15.2170193110f ,
- 14.7522670314f , - 14.3011084168f , - 13.8629436112f , - 13.4372153915f ,
- 13.0234052546f , - 12.6210299451f , - 12.2296383638f , - 11.8488088095f ,
- 11.4781465116f , - 11.1172814164f , - 10.7658661983f , - 10.4235744668f ,
- 10.0900991491f , - 9.7651510261f , - 9.4484574055f , - 9.1397609172f ,
- 8.8388184168f , - 8.5453999868f , - 8.2592880250f , - 7.9802764101f ,
- 7.7081697387f , - 7.4427826248f , - 7.1839390567f , - 6.9314718056f ,
- 6.6852218807f , - 6.4450380272f , - 6.2107762624f , - 5.9822994468f ,
- 5.7594768878f , - 5.5421839719f , - 5.3303018237f , - 5.1237169899f ,
- 4.9223211445f , - 4.7260108155f , - 4.5346871303f , - 4.3482555779f ,
- 4.1666257875f , - 3.9897113219f , - 3.8174294843f , - 3.6497011373f ,
- 3.4864505345f , - 3.3276051620f , - 3.1730955900f , - 3.0228553340f ,
- 2.8768207245f , - 2.7349307844f , - 2.5971271143f , - 2.4633537845f ,
- 2.3335572335f , - 2.2076861725f , - 2.0856914960f , - 1.9675261968f ,
- 1.8531452871f , - 1.7425057233f , - 1.6355663356f , - 1.5322877618f ,
- 1.4326323846f , - 1.3365642732f , - 1.2440491272f , - 1.1550542250f ,
- 1.0695483746f , - 0.9875018671f , - 0.9088864335f , - 0.8336752037f ,
- 0.7618426682f , - 0.6933646420f , - 0.6282182304f , - 0.5663817981f ,
- 0.5078349388f , - 0.4525584478f , - 0.4005342959f , - 0.3517456058f ,
- 0.3061766293f , - 0.2638127266f , - 0.2246403475f , - 0.1886470134f ,
- 0.1558213016f , - 0.1261528303f , - 0.0996322457f , - 0.0762512098f ,
- 0.0560023899f , - 0.0388794497f , - 0.0248770409f , - 0.0139907967f ,
- 0.0062173263f , - 0.0015542108f , 0.0000000000f } ;
2016-01-12 01:21:41 +00:00
static unsigned int freq_table [ ] = { 837201792 , 837685632 , 838169728 ,
2015-11-28 16:38:40 +00:00
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 , } ;
# 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 MAX_AUTO_AMP 2.0
/*
* = = = = = = = = = = = = = = = = = = = = = = = = =
* Internal Functions
* = = = = = = = = = = = = = = = = = = = = = = = = =
*/
static void WM_InitPatches ( void ) {
int i ;
for ( i = 0 ; i < 128 ; i + + ) {
patch [ i ] = NULL ;
}
}
static void WM_FreePatches ( void ) {
int i ;
struct _patch * tmp_patch ;
struct _sample * tmp_sample ;
2015-12-29 22:24:16 +00:00
patch_lock . Enter ( ) ;
2015-11-28 16:38:40 +00:00
for ( i = 0 ; i < 128 ; i + + ) {
while ( patch [ i ] ) {
while ( patch [ i ] - > first_sample ) {
tmp_sample = patch [ i ] - > first_sample - > next ;
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 ;
}
}
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
}
/* wm_strdup -- adds extra space for appending up to 4 chars */
static char * wm_strdup ( const char * str ) {
size_t l = strlen ( str ) + 5 ;
char * d = ( char * ) malloc ( l * sizeof ( char ) ) ;
if ( d ) {
strcpy ( d , str ) ;
return d ;
}
return NULL ;
}
static inline int wm_isdigit ( int c ) {
return ( c > = ' 0 ' & & c < = ' 9 ' ) ;
}
# define TOKEN_CNT_INC 8
2015-12-29 17:01:15 +00:00
static char * * WM_LC_Tokenize_Line ( char * line_data )
{
2016-01-11 22:46:12 +00:00
int line_length = ( int ) strlen ( line_data ) ;
2015-11-28 16:38:40 +00:00
int token_data_length = 0 ;
int line_ofs = 0 ;
int token_start = 0 ;
char * * token_data = NULL ;
int token_count = 0 ;
2015-12-29 17:01:15 +00:00
bool in_quotes = false ;
2015-11-28 16:38:40 +00:00
if ( line_length = = 0 )
return NULL ;
do {
/* ignore everything after # */
if ( line_data [ line_ofs ] = = ' # ' ) {
break ;
}
2015-12-29 17:01:15 +00:00
if ( line_data [ line_ofs ] = = ' " ' )
{
in_quotes = ! in_quotes ;
}
else if ( ! in_quotes & & ( ( line_data [ line_ofs ] = = ' ' ) | | ( line_data [ line_ofs ] = = ' \t ' ) ) ) {
2015-11-28 16:38:40 +00:00
/* whitespace means we aren't in a token */
if ( token_start ) {
token_start = 0 ;
line_data [ line_ofs ] = ' \0 ' ;
}
} else {
if ( ! token_start ) {
/* the start of a token in the line */
token_start = 1 ;
if ( token_count > = token_data_length ) {
token_data_length + = TOKEN_CNT_INC ;
token_data = ( char * * ) realloc ( token_data , token_data_length * sizeof ( char * ) ) ;
if ( token_data = = NULL ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_MEM , " to parse config " , errno ) ;
return NULL ;
}
}
token_data [ token_count ] = & line_data [ line_ofs ] ;
token_count + + ;
}
}
line_ofs + + ;
} while ( line_ofs ! = line_length ) ;
/* if we have found some tokens then add a null token to the end */
if ( token_count ) {
if ( token_count > = token_data_length ) {
token_data = ( char * * ) realloc ( token_data ,
( ( token_count + 1 ) * sizeof ( char * ) ) ) ;
}
token_data [ token_count ] = NULL ;
}
return token_data ;
}
2018-02-22 21:35:49 +00:00
static int WM_LoadConfig ( const char * config_file , bool main ) {
2015-11-28 16:38:40 +00:00
unsigned long int config_size = 0 ;
char * config_buffer = NULL ;
const char * dir_end = NULL ;
char * config_dir = NULL ;
unsigned long int config_ptr = 0 ;
unsigned long int line_start_ptr = 0 ;
unsigned short int patchid = 0 ;
struct _patch * tmp_patch ;
char * * line_tokens = NULL ;
int token_count = 0 ;
2018-02-22 21:35:49 +00:00
auto config_parm = config_file ;
2015-11-28 16:38:40 +00:00
2018-02-22 21:35:49 +00:00
FileReader * fr = nullptr ;
if ( main )
{
if ( ! _WM_InitReader ( config_file ) ) return - 1 ; // unable to open this as a config file.
config_parm = nullptr ;
}
config_buffer = ( char * ) _WM_BufferFile ( config_parm , & config_size ) ;
2015-11-28 16:38:40 +00:00
if ( ! config_buffer ) {
WM_FreePatches ( ) ;
return - 1 ;
}
2018-02-22 21:35:49 +00:00
FString bp = wm_sfreader - > basePath ( ) ;
if ( config_parm = = nullptr ) config_file = bp . GetChars ( ) ; // Re-get the base path because for archives this is empty.
2015-11-28 16:38:40 +00:00
// This part was rewritten because the original depended on a header that was GPL'd.
dir_end = strrchr ( config_file , ' / ' ) ;
# ifdef _WIN32
const char * dir_end2 = strrchr ( config_file , ' \\ ' ) ;
if ( dir_end2 > dir_end ) dir_end = dir_end2 ;
# endif
if ( dir_end ) {
config_dir = ( char * ) malloc ( ( dir_end - config_file + 2 ) ) ;
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 ;
/* handle files without a newline at the end: this relies on
* _WM_BufferFile ( ) allocating the buffer with one extra byte */
config_buffer [ config_size ] = ' \n ' ;
while ( config_ptr < = config_size ) {
if ( config_buffer [ config_ptr ] = = ' \r ' | |
config_buffer [ config_ptr ] = = ' \n ' )
{
config_buffer [ config_ptr ] = ' \0 ' ;
if ( config_ptr ! = line_start_ptr ) {
line_tokens = WM_LC_Tokenize_Line ( & config_buffer [ line_start_ptr ] ) ;
if ( line_tokens ) {
2015-12-29 09:33:20 +00:00
if ( stricmp ( line_tokens [ 0 ] , " dir " ) = = 0 ) {
2015-11-28 16:38:40 +00:00
free ( config_dir ) ;
if ( ! line_tokens [ 1 ] ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (missing name in dir line) " , 0 ) ;
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_LOAD ,
config_file , 0 ) ;
WM_FreePatches ( ) ;
free ( line_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
} else if ( ! ( config_dir = wm_strdup ( line_tokens [ 1 ] ) ) ) {
_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_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
}
if ( ! IS_DIR_SEPARATOR ( config_dir [ strlen ( config_dir ) - 1 ] ) ) {
config_dir [ strlen ( config_dir ) + 1 ] = ' \0 ' ;
config_dir [ strlen ( config_dir ) ] = ' / ' ;
}
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ 0 ] , " source " ) = = 0 ) {
2015-11-28 16:38:40 +00:00
char * new_config = NULL ;
if ( ! line_tokens [ 1 ] ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (missing name in source line) " , 0 ) ;
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_LOAD ,
config_file , 0 ) ;
WM_FreePatches ( ) ;
free ( line_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
} else if ( ! IS_ABSOLUTE_PATH ( line_tokens [ 1 ] ) & & config_dir ) {
new_config = ( char * ) malloc (
strlen ( config_dir ) + strlen ( line_tokens [ 1 ] )
+ 1 ) ;
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_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
}
strcpy ( new_config , config_dir ) ;
strcpy ( & new_config [ strlen ( config_dir ) ] , line_tokens [ 1 ] ) ;
} else {
if ( ! ( new_config = wm_strdup ( line_tokens [ 1 ] ) ) ) {
_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_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
}
}
2018-02-22 21:35:49 +00:00
if ( WM_LoadConfig ( new_config , false ) = = - 1 ) {
2015-11-28 16:38:40 +00:00
free ( new_config ) ;
free ( line_tokens ) ;
free ( config_buffer ) ;
free ( config_dir ) ;
return - 1 ;
}
free ( new_config ) ;
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ 0 ] , " bank " ) = = 0 ) {
2015-11-28 16:38:40 +00:00
if ( ! line_tokens [ 1 ] | | ! wm_isdigit ( line_tokens [ 1 ] [ 0 ] ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (syntax error in bank line) " , 0 ) ;
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_LOAD ,
config_file , 0 ) ;
WM_FreePatches ( ) ;
free ( config_dir ) ;
free ( line_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
}
patchid = ( atoi ( line_tokens [ 1 ] ) & 0xFF ) < < 8 ;
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ 0 ] , " drumset " ) = = 0 ) {
2015-11-28 16:38:40 +00:00
if ( ! line_tokens [ 1 ] | | ! wm_isdigit ( line_tokens [ 1 ] [ 0 ] ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (syntax error in drumset line) " , 0 ) ;
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_LOAD ,
config_file , 0 ) ;
WM_FreePatches ( ) ;
free ( config_dir ) ;
free ( line_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
}
patchid = ( ( atoi ( line_tokens [ 1 ] ) & 0xFF ) < < 8 ) | 0x80 ;
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ 0 ] , " reverb_room_width " ) = = 0 ) {
2015-11-28 16:38:40 +00:00
if ( ! line_tokens [ 1 ] | | ! wm_isdigit ( line_tokens [ 1 ] [ 0 ] ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (syntax error in reverb_room_width line) " ,
0 ) ;
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_LOAD ,
config_file , 0 ) ;
WM_FreePatches ( ) ;
free ( config_dir ) ;
free ( line_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
}
reverb_room_width = ( float ) atof ( line_tokens [ 1 ] ) ;
if ( reverb_room_width < 1.0f ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (reverb_room_width < 1 meter, setting to minimum of 1 meter) " ,
0 ) ;
reverb_room_width = 1.0f ;
} else if ( reverb_room_width > 100.0f ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (reverb_room_width > 100 meters, setting to maximum of 100 meters) " ,
0 ) ;
reverb_room_width = 100.0f ;
}
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ 0 ] , " reverb_room_length " ) = = 0 ) {
2015-11-28 16:38:40 +00:00
if ( ! line_tokens [ 1 ] | | ! wm_isdigit ( line_tokens [ 1 ] [ 0 ] ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (syntax error in reverb_room_length line) " ,
0 ) ;
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_LOAD ,
config_file , 0 ) ;
WM_FreePatches ( ) ;
free ( config_dir ) ;
free ( line_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
}
reverb_room_length = ( float ) atof ( line_tokens [ 1 ] ) ;
if ( reverb_room_length < 1.0f ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (reverb_room_length < 1 meter, setting to minimum of 1 meter) " ,
0 ) ;
reverb_room_length = 1.0f ;
} else if ( reverb_room_length > 100.0f ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (reverb_room_length > 100 meters, setting to maximum of 100 meters) " ,
0 ) ;
reverb_room_length = 100.0f ;
}
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ 0 ] , " reverb_listener_posx " ) = = 0 ) {
2015-11-28 16:38:40 +00:00
if ( ! line_tokens [ 1 ] | | ! wm_isdigit ( line_tokens [ 1 ] [ 0 ] ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (syntax error in reverb_listen_posx line) " ,
0 ) ;
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_LOAD ,
config_file , 0 ) ;
WM_FreePatches ( ) ;
free ( config_dir ) ;
free ( line_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
}
reverb_listen_posx = ( float ) atof ( line_tokens [ 1 ] ) ;
if ( ( reverb_listen_posx > reverb_room_width )
| | ( reverb_listen_posx < 0.0f ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (reverb_listen_posx set outside of room) " ,
0 ) ;
reverb_listen_posx = reverb_room_width / 2.0f ;
}
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ 0 ] ,
2015-11-28 16:38:40 +00:00
" reverb_listener_posy " ) = = 0 ) {
if ( ! line_tokens [ 1 ] | | ! wm_isdigit ( line_tokens [ 1 ] [ 0 ] ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (syntax error in reverb_listen_posy line) " ,
0 ) ;
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_LOAD ,
config_file , 0 ) ;
WM_FreePatches ( ) ;
free ( config_dir ) ;
free ( line_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
}
reverb_listen_posy = ( float ) atof ( line_tokens [ 1 ] ) ;
if ( ( reverb_listen_posy > reverb_room_width )
| | ( reverb_listen_posy < 0.0f ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (reverb_listen_posy set outside of room) " ,
0 ) ;
reverb_listen_posy = reverb_room_length * 0.75f ;
}
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ 0 ] ,
2015-11-28 16:38:40 +00:00
" guspat_editor_author_cant_read_so_fix_release_time_for_me " )
= = 0 ) {
fix_release = 1 ;
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ 0 ] , " auto_amp " ) = = 0 ) {
2015-11-28 16:38:40 +00:00
auto_amp = 1 ;
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ 0 ] , " auto_amp_with_amp " )
2015-11-28 16:38:40 +00:00
= = 0 ) {
auto_amp = 1 ;
auto_amp_with_amp = 1 ;
} else if ( wm_isdigit ( line_tokens [ 0 ] [ 0 ] ) ) {
patchid = ( patchid & 0xFF80 )
| ( atoi ( line_tokens [ 0 ] ) & 0x7F ) ;
if ( patch [ ( patchid & 0x7F ) ] = = NULL ) {
patch [ ( patchid & 0x7F ) ] = ( struct _patch * ) 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 ( ) ;
free ( config_dir ) ;
free ( line_tokens ) ;
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 ) {
while ( tmp_patch - > next ) {
if ( tmp_patch - > next - > patchid = = patchid )
break ;
tmp_patch = tmp_patch - > next ;
}
if ( tmp_patch - > next = = NULL ) {
if ( ( tmp_patch - > next = ( struct _patch * ) malloc (
sizeof ( struct _patch ) ) )
= = NULL ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ ,
WM_ERR_MEM , NULL , 0 ) ;
_WM_ERROR ( __FUNCTION__ , __LINE__ ,
WM_ERR_LOAD , config_file ,
0 ) ;
WM_FreePatches ( ) ;
free ( config_dir ) ;
free ( line_tokens ) ;
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 = ( struct _patch * ) 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 ( ) ;
free ( config_dir ) ;
free ( line_tokens ) ;
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 ;
}
}
}
if ( ! line_tokens [ 1 ] ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (missing name in patch line) " , 0 ) ;
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_LOAD ,
config_file , 0 ) ;
WM_FreePatches ( ) ;
free ( config_dir ) ;
free ( line_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
} else if ( ! IS_ABSOLUTE_PATH ( line_tokens [ 1 ] ) & & config_dir ) {
tmp_patch - > filename = ( char * ) malloc (
strlen ( config_dir ) + strlen ( line_tokens [ 1 ] )
+ 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 ( config_dir ) ;
free ( line_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
}
strcpy ( tmp_patch - > filename , config_dir ) ;
strcat ( tmp_patch - > filename , line_tokens [ 1 ] ) ;
} else {
if ( ! ( tmp_patch - > filename = wm_strdup ( line_tokens [ 1 ] ) ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_MEM ,
NULL , 0 ) ;
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_LOAD ,
config_file , 0 ) ;
WM_FreePatches ( ) ;
free ( config_dir ) ;
free ( line_tokens ) ;
free ( config_buffer ) ;
return - 1 ;
}
}
2015-12-29 09:33:20 +00:00
if ( strnicmp (
2015-11-28 16:38:40 +00:00
& tmp_patch - > filename [ strlen ( tmp_patch - > filename )
- 4 ] , " .pat " , 4 ) ! = 0 ) {
strcat ( tmp_patch - > filename , " .pat " ) ;
}
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 ;
token_count = 0 ;
while ( line_tokens [ token_count ] ) {
2015-12-29 09:33:20 +00:00
if ( strnicmp ( line_tokens [ token_count ] , " amp= " , 4 )
2015-11-28 16:38:40 +00:00
= = 0 ) {
if ( ! wm_isdigit ( line_tokens [ token_count ] [ 4 ] ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ ,
WM_ERR_INVALID_ARG ,
" (syntax error in patch line) " , 0 ) ;
} else {
tmp_patch - > amp = ( atoi (
& line_tokens [ token_count ] [ 4 ] ) < < 10 )
/ 100 ;
}
2015-12-29 09:33:20 +00:00
} else if ( strnicmp ( line_tokens [ token_count ] ,
2015-11-28 16:38:40 +00:00
" note= " , 5 ) = = 0 ) {
if ( ! wm_isdigit ( line_tokens [ token_count ] [ 5 ] ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ ,
WM_ERR_INVALID_ARG ,
" (syntax error in patch line) " , 0 ) ;
} else {
tmp_patch - > note = atoi (
& line_tokens [ token_count ] [ 5 ] ) ;
}
2015-12-29 09:33:20 +00:00
} else if ( strnicmp ( line_tokens [ token_count ] ,
2015-11-28 16:38:40 +00:00
" env_time " , 8 ) = = 0 ) {
if ( ( ! wm_isdigit ( line_tokens [ token_count ] [ 8 ] ) )
| | ( ! wm_isdigit (
line_tokens [ token_count ] [ 10 ] ) )
| | ( line_tokens [ token_count ] [ 9 ] ! = ' = ' ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ ,
WM_ERR_INVALID_ARG ,
" (syntax error in patch line) " , 0 ) ;
} else {
unsigned int env_no = atoi (
& line_tokens [ token_count ] [ 8 ] ) ;
if ( env_no > 5 ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ ,
WM_ERR_INVALID_ARG ,
" (syntax error in patch line) " ,
0 ) ;
} else {
tmp_patch - > env [ env_no ] . time =
( float ) atof (
& line_tokens [ token_count ] [ 10 ] ) ;
if ( ( tmp_patch - > env [ env_no ] . time
> 45000.0f )
| | ( tmp_patch - > env [ env_no ] . time
< 1.47f ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ ,
WM_ERR_INVALID_ARG ,
" (range error in patch line) " ,
0 ) ;
tmp_patch - > env [ env_no ] . set & = 0xFE ;
} else {
tmp_patch - > env [ env_no ] . set | = 0x01 ;
}
}
}
2015-12-29 09:33:20 +00:00
} else if ( strnicmp ( line_tokens [ token_count ] ,
2015-11-28 16:38:40 +00:00
" env_level " , 9 ) = = 0 ) {
if ( ( ! wm_isdigit ( line_tokens [ token_count ] [ 9 ] ) )
| | ( ! wm_isdigit (
line_tokens [ token_count ] [ 11 ] ) )
| | ( line_tokens [ token_count ] [ 10 ] ! = ' = ' ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ ,
WM_ERR_INVALID_ARG ,
" (syntax error in patch line) " , 0 ) ;
} else {
unsigned int env_no = atoi (
& line_tokens [ token_count ] [ 9 ] ) ;
if ( env_no > 5 ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ ,
WM_ERR_INVALID_ARG ,
" (syntax error in patch line) " ,
0 ) ;
} else {
tmp_patch - > env [ env_no ] . level =
( float ) atof (
& line_tokens [ token_count ] [ 11 ] ) ;
if ( ( tmp_patch - > env [ env_no ] . level > 1.0f )
| | ( tmp_patch - > env [ env_no ] . level
< 0.0f ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ ,
WM_ERR_INVALID_ARG ,
" (range error in patch line) " ,
0 ) ;
tmp_patch - > env [ env_no ] . set & = 0xFD ;
} else {
tmp_patch - > env [ env_no ] . set | = 0x02 ;
}
}
}
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ token_count ] ,
2015-11-28 16:38:40 +00:00
" keep=loop " ) = = 0 ) {
tmp_patch - > keep | = SAMPLE_LOOP ;
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ token_count ] ,
2015-11-28 16:38:40 +00:00
" keep=env " ) = = 0 ) {
tmp_patch - > keep | = SAMPLE_ENVELOPE ;
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ token_count ] ,
2015-11-28 16:38:40 +00:00
" remove=sustain " ) = = 0 ) {
tmp_patch - > remove | = SAMPLE_SUSTAIN ;
2015-12-29 09:33:20 +00:00
} else if ( stricmp ( line_tokens [ token_count ] ,
2015-11-28 16:38:40 +00:00
" remove=clamped " ) = = 0 ) {
tmp_patch - > remove | = SAMPLE_CLAMPED ;
}
token_count + + ;
}
}
}
/* free up tokens */
free ( line_tokens ) ;
}
line_start_ptr = config_ptr + 1 ;
}
config_ptr + + ;
}
free ( config_buffer ) ;
free ( config_dir ) ;
return 0 ;
}
/* sample loading */
static int load_sample ( struct _patch * sample_patch ) {
struct _sample * guspat = NULL ;
struct _sample * tmp_sample = NULL ;
unsigned int i = 0 ;
/* we only want to try loading the guspat once. */
sample_patch - > loaded = 1 ;
if ( ( guspat = _WM_load_gus_pat ( sample_patch - > filename , fix_release ) ) = = NULL ) {
return - 1 ;
}
if ( auto_amp ) {
signed short int tmp_max = 0 ;
signed short int tmp_min = 0 ;
signed short samp_max = 0 ;
signed short samp_min = 0 ;
tmp_sample = guspat ;
do {
samp_max = 0 ;
samp_min = 0 ;
for ( i = 0 ; i < ( tmp_sample - > data_length > > 10 ) ; i + + ) {
if ( tmp_sample - > data [ i ] > samp_max )
samp_max = tmp_sample - > data [ i ] ;
if ( tmp_sample - > data [ i ] < samp_min )
samp_min = tmp_sample - > data [ i ] ;
}
if ( samp_max > tmp_max )
tmp_max = samp_max ;
if ( samp_min < tmp_min )
tmp_min = samp_min ;
tmp_sample = tmp_sample - > next ;
} while ( tmp_sample ) ;
if ( auto_amp_with_amp ) {
if ( tmp_max > = - tmp_min ) {
sample_patch - > amp = ( sample_patch - > amp
* ( ( 32767 < < 10 ) / tmp_max ) ) > > 10 ;
} else {
sample_patch - > amp = ( sample_patch - > amp
* ( ( 32768 < < 10 ) / - tmp_min ) ) > > 10 ;
}
} else {
if ( tmp_max > = - tmp_min ) {
sample_patch - > amp = ( 32767 < < 10 ) / tmp_max ;
} else {
sample_patch - > amp = ( 32768 < < 10 ) / - tmp_min ;
}
}
}
sample_patch - > first_sample = guspat ;
if ( sample_patch - > patchid & 0x0080 ) {
if ( ! ( sample_patch - > keep & SAMPLE_LOOP ) ) {
do {
guspat - > modes & = 0xFB ;
guspat = guspat - > next ;
} while ( guspat ) ;
}
guspat = sample_patch - > first_sample ;
if ( ! ( sample_patch - > keep & SAMPLE_ENVELOPE ) ) {
do {
guspat - > modes & = 0xBF ;
guspat = guspat - > next ;
} while ( guspat ) ;
}
guspat = sample_patch - > first_sample ;
}
if ( sample_patch - > patchid = = 47 ) {
do {
if ( ! ( guspat - > modes & SAMPLE_LOOP ) ) {
for ( i = 3 ; i < 6 ; i + + ) {
guspat - > env_target [ i ] = guspat - > env_target [ 2 ] ;
guspat - > env_rate [ i ] = guspat - > env_rate [ 2 ] ;
}
}
guspat = guspat - > next ;
} while ( guspat ) ;
guspat = sample_patch - > first_sample ;
}
do {
if ( ( sample_patch - > remove & SAMPLE_SUSTAIN )
& & ( guspat - > modes & SAMPLE_SUSTAIN ) ) {
guspat - > modes ^ = SAMPLE_SUSTAIN ;
}
if ( ( sample_patch - > remove & SAMPLE_CLAMPED )
& & ( guspat - > modes & SAMPLE_CLAMPED ) ) {
guspat - > modes ^ = SAMPLE_CLAMPED ;
}
if ( sample_patch - > keep & SAMPLE_ENVELOPE ) {
guspat - > modes | = SAMPLE_ENVELOPE ;
}
for ( i = 0 ; i < 6 ; i + + ) {
if ( guspat - > modes & SAMPLE_ENVELOPE ) {
if ( sample_patch - > env [ i ] . set & 0x02 ) {
guspat - > env_target [ i ] = 16448
* ( signed long int ) ( 255.0
* sample_patch - > env [ i ] . level ) ;
}
if ( sample_patch - > env [ i ] . set & 0x01 ) {
guspat - > env_rate [ i ] = ( signed long int ) ( 4194303.0
/ ( ( float ) _WM_SampleRate
* ( sample_patch - > env [ i ] . time / 1000.0 ) ) ) ;
}
} else {
guspat - > env_target [ i ] = 4194303 ;
guspat - > env_rate [ i ] = ( signed long int ) ( 4194303.0
/ ( ( float ) _WM_SampleRate * env_time_table [ 63 ] ) ) ;
}
}
guspat = guspat - > next ;
} while ( guspat ) ;
return 0 ;
}
static struct _patch *
2015-11-29 10:27:08 +00:00
get_patch_data ( unsigned short patchid ) {
2015-11-28 16:38:40 +00:00
struct _patch * search_patch ;
2015-12-29 22:24:16 +00:00
patch_lock . Enter ( ) ;
2015-11-28 16:38:40 +00:00
search_patch = patch [ patchid & 0x007F ] ;
if ( search_patch = = NULL ) {
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return NULL ;
}
while ( search_patch ) {
if ( search_patch - > patchid = = patchid ) {
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return search_patch ;
}
search_patch = search_patch - > next ;
}
if ( ( patchid > > 8 ) ! = 0 ) {
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-29 10:27:08 +00:00
return ( get_patch_data ( patchid & 0x00FF ) ) ;
2015-11-28 16:38:40 +00:00
}
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return NULL ;
}
static void load_patch ( struct _mdi * mdi , unsigned short patchid ) {
unsigned int i ;
struct _patch * tmp_patch = NULL ;
for ( i = 0 ; i < mdi - > patch_count ; i + + ) {
if ( mdi - > patches [ i ] - > patchid = = patchid ) {
return ;
}
}
2015-11-29 10:27:08 +00:00
tmp_patch = get_patch_data ( patchid ) ;
2015-11-28 16:38:40 +00:00
if ( tmp_patch = = NULL ) {
return ;
}
2015-12-29 22:24:16 +00:00
patch_lock . Enter ( ) ;
2015-11-28 16:38:40 +00:00
if ( ! tmp_patch - > loaded ) {
if ( load_sample ( tmp_patch ) = = - 1 ) {
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return ;
}
}
if ( tmp_patch - > first_sample = = NULL ) {
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return ;
}
mdi - > patch_count + + ;
mdi - > patches = ( struct _patch * * ) realloc ( mdi - > patches ,
( sizeof ( struct _patch * ) * mdi - > patch_count ) ) ;
mdi - > patches [ mdi - > patch_count - 1 ] = tmp_patch ;
tmp_patch - > inuse_count + + ;
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
}
static struct _sample *
get_sample_data ( struct _patch * sample_patch , unsigned long int freq ) {
struct _sample * last_sample = NULL ;
struct _sample * return_sample = NULL ;
2015-12-29 22:24:16 +00:00
patch_lock . Enter ( ) ;
2015-11-28 16:38:40 +00:00
if ( sample_patch = = NULL ) {
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return NULL ;
}
if ( sample_patch - > first_sample = = NULL ) {
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return NULL ;
}
if ( freq = = 0 ) {
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return sample_patch - > first_sample ;
}
return_sample = sample_patch - > first_sample ;
last_sample = sample_patch - > first_sample ;
while ( last_sample ) {
if ( freq > last_sample - > freq_low ) {
if ( freq < last_sample - > freq_high ) {
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return last_sample ;
} else {
return_sample = last_sample ;
}
}
last_sample = last_sample - > next ;
}
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return return_sample ;
}
2016-01-12 01:21:41 +00:00
/* Should be called in any function that effects note volumes */
void _WM_AdjustNoteVolumes ( struct _mdi * mdi , unsigned char ch , struct _note * nte ) {
double premix_dBm ;
double premix_lin ;
2016-01-12 12:34:29 +00:00
int pan_ofs ;
2016-01-12 01:21:41 +00:00
double premix_dBm_left ;
double premix_dBm_right ;
double premix_left ;
double premix_right ;
double volume_adj ;
unsigned vol_ofs ;
/*
Pointless CPU heating checks to shoosh up a compiler
*/
if ( ch > 0x0f ) ch = 0x0f ;
pan_ofs = mdi - > channel [ ch ] . balance + mdi - > channel [ ch ] . pan - 64 ;
vol_ofs = ( nte - > velocity * ( ( mdi - > channel [ ch ] . expression * mdi - > channel [ ch ] . volume ) / 127 ) ) / 127 ;
/*
This value is to reduce the chance of clipping .
Higher value means lower overall volume ,
Lower value means higher overall volume .
NOTE : The lower the value the higher the chance of clipping .
FIXME : Still needs tuning . Clipping heard at a value of 3.75
*/
# define VOL_DIVISOR 4.0
volume_adj = ( ( float ) WM_MasterVolume / 1024.0 ) / VOL_DIVISOR ;
2016-01-12 02:01:14 +00:00
// Pan 0 and 1 are both hard left so 64 can be centered
2016-01-12 01:21:41 +00:00
if ( pan_ofs > 127 ) pan_ofs = 127 ;
2016-01-12 02:01:14 +00:00
if ( - - pan_ofs < 0 ) pan_ofs = 0 ;
premix_dBm_left = dBm_pan_volume [ 126 - pan_ofs ] ;
2016-01-12 01:21:41 +00:00
premix_dBm_right = dBm_pan_volume [ pan_ofs ] ;
if ( mdi - > info . mixer_options & WM_MO_LOG_VOLUME ) {
premix_dBm = dBm_volume [ vol_ofs ] ;
premix_dBm_left + = premix_dBm ;
premix_dBm_right + = premix_dBm ;
premix_left = ( pow ( 10.0 , ( premix_dBm_left / 20.0 ) ) ) * volume_adj ;
premix_right = ( pow ( 10.0 , ( premix_dBm_right / 20.0 ) ) ) * volume_adj ;
} else {
premix_lin = ( float ) ( lin_volume [ vol_ofs ] ) / 1024.0 ;
premix_left = premix_lin * pow ( 10.0 , ( premix_dBm_left / 20 ) ) * volume_adj ;
premix_right = premix_lin * pow ( 10.0 , ( premix_dBm_right / 20 ) ) * volume_adj ;
}
nte - > left_mix_volume = ( int ) ( premix_left * 1024.0 ) ;
nte - > right_mix_volume = ( int ) ( premix_right * 1024.0 ) ;
}
/* Should be called in any function that effects channel volumes */
/* Calling this function with a value > 15 will make it adjust notes on all channels */
void _WM_AdjustChannelVolumes ( struct _mdi * mdi , unsigned char ch ) {
struct _note * nte = mdi - > note ;
if ( nte ! = NULL ) {
do {
if ( ch < = 15 ) {
if ( ( nte - > noteid > > 8 ) = = ch ) {
goto _DO_ADJUST ;
}
} else {
_DO_ADJUST :
_WM_AdjustNoteVolumes ( mdi , ch , nte ) ;
if ( nte - > replay ) _WM_AdjustNoteVolumes ( mdi , ch , nte - > replay ) ;
}
nte = nte - > next ;
} while ( nte ! = NULL ) ;
}
}
2016-01-12 01:19:06 +00:00
2015-11-28 16:38:40 +00:00
static void do_note_off_extra ( struct _note * nte ) {
nte - > is_off = 0 ;
2016-01-12 01:19:06 +00:00
if ( ! ( nte - > modes & SAMPLE_ENVELOPE ) ) {
if ( nte - > modes & SAMPLE_LOOP ) {
nte - > modes ^ = SAMPLE_LOOP ;
}
nte - > env_inc = 0 ;
} else if ( nte - > hold ) {
2015-11-28 16:38:40 +00:00
nte - > hold | = HOLD_OFF ;
2016-01-12 01:19:06 +00:00
} else if ( nte - > modes & SAMPLE_SUSTAIN ) {
if ( nte - > env < 3 ) {
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 ] ;
2015-11-28 16:38:40 +00:00
}
2016-01-12 01:19:06 +00:00
}
} else if ( nte - > modes & SAMPLE_CLAMPED ) {
if ( nte - > env < 5 ) {
nte - > env = 5 ;
if ( nte - > env_level > nte - > sample - > env_target [ 5 ] ) {
nte - > env_inc = - nte - > sample - > env_rate [ 5 ] ;
2015-11-28 16:38:40 +00:00
} else {
2016-01-12 01:19:06 +00:00
nte - > env_inc = nte - > sample - > env_rate [ 5 ] ;
2015-11-28 16:38:40 +00:00
}
}
2016-01-12 01:19:06 +00:00
} else 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 ] ;
}
2015-11-28 16:38:40 +00:00
}
}
static void do_note_off ( struct _mdi * mdi , struct _event_data * data ) {
struct _note * nte ;
unsigned char ch = data - > channel ;
MIDI_EVENT_DEBUG ( __FUNCTION__ , ch ) ;
nte = & mdi - > note_table [ 0 ] [ ch ] [ ( data - > data > > 8 ) ] ;
if ( ! nte - > active )
nte = & mdi - > note_table [ 1 ] [ ch ] [ ( data - > data > > 8 ) ] ;
if ( ! nte - > active ) {
return ;
}
if ( ( mdi - > channel [ ch ] . isdrum ) & & ( ! ( nte - > modes & SAMPLE_LOOP ) ) ) {
return ;
}
2016-01-12 01:21:41 +00:00
if ( ( nte - > modes & SAMPLE_ENVELOPE ) & & ( nte - > env = = 0 ) ) {
// This is a fix for notes that end before the
// initial step of the envelope has completed
// making it impossible to hear them at times.
2015-11-28 16:38:40 +00:00
nte - > is_off = 1 ;
} else {
do_note_off_extra ( nte ) ;
}
}
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 ;
2015-12-29 10:36:56 +00:00
if ( nte - > patch - > note ! = 0 ) {
2015-11-28 16:38:40 +00:00
note_f = nte - > patch - > note * 100 ;
} else {
note_f = ( nte - > noteid & 0x7f ) * 100 ;
}
note_f + = mdi - > channel [ ch ] . pitch_adjust ;
2015-12-29 10:36:56 +00:00
if ( note_f < 0 ) {
2015-11-28 16:38:40 +00:00
note_f = 0 ;
2015-12-29 10:36:56 +00:00
} else if ( note_f > 12700 ) {
2015-11-28 16:38:40 +00:00
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 void do_note_on ( struct _mdi * mdi , struct _event_data * data ) {
struct _note * nte ;
struct _note * prev_nte ;
struct _note * nte_array ;
unsigned long int freq = 0 ;
struct _patch * patch ;
struct _sample * sample ;
unsigned char ch = data - > channel ;
unsigned char note = ( unsigned char ) ( data - > data > > 8 ) ;
2016-01-12 01:21:41 +00:00
unsigned char velocity = ( unsigned char ) ( data - > data & 0xFF ) ;
2015-11-28 16:38:40 +00:00
if ( velocity = = 0x00 ) {
do_note_off ( mdi , data ) ;
return ;
}
MIDI_EVENT_DEBUG ( __FUNCTION__ , ch ) ;
if ( ! mdi - > channel [ ch ] . isdrum ) {
patch = mdi - > channel [ ch ] . patch ;
if ( patch = = NULL ) {
return ;
}
freq = freq_table [ ( note % 12 ) * 100 ] > > ( 10 - ( note / 12 ) ) ;
} else {
2015-11-29 10:27:08 +00:00
patch = get_patch_data ( ( ( mdi - > channel [ ch ] . bank < < 8 ) | note | 0x80 ) ) ;
2015-11-28 16:38:40 +00:00
if ( patch = = NULL ) {
return ;
}
if ( patch - > note ) {
freq = freq_table [ ( patch - > note % 12 ) * 100 ]
> > ( 10 - ( patch - > note / 12 ) ) ;
} else {
freq = freq_table [ ( note % 12 ) * 100 ] > > ( 10 - ( note / 12 ) ) ;
}
}
sample = get_sample_data ( patch , ( freq / 100 ) ) ;
if ( sample = = NULL ) {
return ;
}
nte = & mdi - > note_table [ 0 ] [ ch ] [ note ] ;
if ( nte - > active ) {
if ( ( nte - > modes & SAMPLE_ENVELOPE ) & & ( nte - > env < 3 )
& & ( ! ( nte - > hold & HOLD_OFF ) ) )
return ;
nte - > replay = & mdi - > note_table [ 1 ] [ ch ] [ note ] ;
nte - > env = 6 ;
nte - > env_inc = - nte - > sample - > env_rate [ 6 ] ;
nte = nte - > replay ;
} else {
if ( mdi - > note_table [ 1 ] [ ch ] [ note ] . active ) {
if ( ( nte - > modes & SAMPLE_ENVELOPE ) & & ( nte - > env < 3 )
& & ( ! ( nte - > hold & HOLD_OFF ) ) )
return ;
mdi - > note_table [ 1 ] [ ch ] [ note ] . replay = nte ;
mdi - > note_table [ 1 ] [ ch ] [ note ] . env = 6 ;
mdi - > note_table [ 1 ] [ ch ] [ note ] . env_inc =
- mdi - > note_table [ 1 ] [ ch ] [ note ] . sample - > env_rate [ 6 ] ;
} else {
nte_array = mdi - > note ;
if ( nte_array = = NULL ) {
mdi - > note = nte ;
} else {
do {
prev_nte = nte_array ;
nte_array = nte_array - > next ;
} while ( nte_array ) ;
prev_nte - > next = nte ;
}
nte - > active = 1 ;
nte - > next = NULL ;
}
}
nte - > noteid = ( ch < < 8 ) | note ;
nte - > patch = patch ;
nte - > sample = sample ;
nte - > sample_pos = 0 ;
nte - > sample_inc = get_inc ( mdi , nte ) ;
nte - > velocity = velocity ;
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 - > replay = NULL ;
nte - > is_off = 0 ;
2016-01-12 01:21:41 +00:00
_WM_AdjustNoteVolumes ( mdi , ch , nte ) ;
2015-11-28 16:38:40 +00:00
}
static void do_aftertouch ( struct _mdi * mdi , struct _event_data * data ) {
struct _note * nte ;
unsigned char ch = data - > channel ;
MIDI_EVENT_DEBUG ( __FUNCTION__ , ch ) ;
nte = & mdi - > note_table [ 0 ] [ ch ] [ ( data - > data > > 8 ) ] ;
if ( ! nte - > active ) {
nte = & mdi - > note_table [ 1 ] [ ch ] [ ( data - > data > > 8 ) ] ;
if ( ! nte - > active ) {
return ;
}
}
2016-01-12 01:21:41 +00:00
nte - > velocity = ( unsigned char ) data - > data ;
_WM_AdjustNoteVolumes ( mdi , ch , nte ) ;
2015-11-28 16:38:40 +00:00
if ( nte - > replay ) {
2016-01-12 01:21:41 +00:00
nte - > replay - > velocity = ( unsigned char ) data - > data ;
_WM_AdjustNoteVolumes ( mdi , ch , nte - > replay ) ;
2015-11-28 16:38:40 +00:00
}
}
static void do_control_bank_select ( struct _mdi * mdi , struct _event_data * data ) {
unsigned char ch = data - > channel ;
mdi - > channel [ ch ] . bank = ( unsigned char ) data - > data ;
}
static void do_control_data_entry_course ( struct _mdi * mdi ,
struct _event_data * data ) {
unsigned char ch = data - > channel ;
int data_tmp ;
if ( ( mdi - > channel [ ch ] . reg_non = = 0 )
& & ( mdi - > channel [ ch ] . reg_data = = 0x0000 ) ) { /* Pitch Bend Range */
data_tmp = mdi - > channel [ ch ] . pitch_range % 100 ;
mdi - > channel [ ch ] . pitch_range = short ( data - > data * 100 + data_tmp ) ;
/* printf("Data Entry Course: pitch_range: %i\n\r",mdi->channel[ch].pitch_range);*/
/* printf("Data Entry Course: data %li\n\r",data->data);*/
}
}
static void do_control_channel_volume ( struct _mdi * mdi ,
struct _event_data * data ) {
struct _note * note_data = mdi - > note ;
unsigned char ch = data - > channel ;
mdi - > channel [ ch ] . volume = ( unsigned char ) data - > data ;
2016-01-12 01:21:41 +00:00
_WM_AdjustChannelVolumes ( mdi , ch ) ;
2015-11-28 16:38:40 +00:00
}
static void do_control_channel_balance ( struct _mdi * mdi ,
struct _event_data * data ) {
unsigned char ch = data - > channel ;
2016-01-12 01:21:41 +00:00
mdi - > channel [ ch ] . balance = ( signed char ) ( data - > data ) ;
_WM_AdjustChannelVolumes ( mdi , ch ) ;
2015-11-28 16:38:40 +00:00
}
static void do_control_channel_pan ( struct _mdi * mdi , struct _event_data * data ) {
unsigned char ch = data - > channel ;
2016-01-12 01:21:41 +00:00
mdi - > channel [ ch ] . pan = ( signed char ) ( data - > data ) ;
_WM_AdjustChannelVolumes ( mdi , ch ) ;
2015-11-28 16:38:40 +00:00
}
static void do_control_channel_expression ( struct _mdi * mdi ,
struct _event_data * data ) {
struct _note * note_data = mdi - > note ;
unsigned char ch = data - > channel ;
mdi - > channel [ ch ] . expression = ( unsigned char ) data - > data ;
2016-01-12 01:21:41 +00:00
_WM_AdjustChannelVolumes ( mdi , ch ) ;
2015-11-28 16:38:40 +00:00
}
static void do_control_data_entry_fine ( struct _mdi * mdi ,
struct _event_data * data ) {
unsigned char ch = data - > channel ;
int data_tmp ;
if ( ( mdi - > channel [ ch ] . reg_non = = 0 )
& & ( mdi - > channel [ ch ] . reg_data = = 0x0000 ) ) { /* Pitch Bend Range */
data_tmp = mdi - > channel [ ch ] . pitch_range / 100 ;
mdi - > channel [ ch ] . pitch_range = short ( ( data_tmp * 100 ) + data - > data ) ;
/* printf("Data Entry Fine: pitch_range: %i\n\r",mdi->channel[ch].pitch_range);*/
/* printf("Data Entry Fine: data: %li\n\r", data->data);*/
}
}
static void do_control_channel_hold ( struct _mdi * mdi , struct _event_data * data ) {
struct _note * note_data = mdi - > note ;
unsigned char ch = data - > channel ;
if ( data - > data > 63 ) {
mdi - > channel [ ch ] . hold = 1 ;
} else {
mdi - > channel [ ch ] . hold = 0 ;
if ( note_data ) {
do {
if ( ( note_data - > noteid > > 8 ) = = ch ) {
if ( note_data - > hold & HOLD_OFF ) {
if ( note_data - > modes & SAMPLE_ENVELOPE ) {
if ( note_data - > modes & SAMPLE_CLAMPED ) {
if ( note_data - > env < 5 ) {
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 ] ;
}
}
} else 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 ] ;
}
}
} else {
if ( note_data - > modes & SAMPLE_LOOP ) {
note_data - > modes ^ = SAMPLE_LOOP ;
}
note_data - > env_inc = 0 ;
}
}
note_data - > hold = 0x00 ;
}
note_data = note_data - > next ;
} while ( note_data ) ;
}
}
}
static void do_control_data_increment ( struct _mdi * mdi ,
struct _event_data * data ) {
unsigned char ch = data - > channel ;
if ( ( mdi - > channel [ ch ] . reg_non = = 0 )
& & ( mdi - > channel [ ch ] . reg_data = = 0x0000 ) ) { /* Pitch Bend Range */
if ( mdi - > channel [ ch ] . pitch_range < 0x3FFF )
mdi - > channel [ ch ] . pitch_range + + ;
}
}
static void do_control_data_decrement ( struct _mdi * mdi ,
struct _event_data * data ) {
unsigned char ch = data - > channel ;
if ( ( mdi - > channel [ ch ] . reg_non = = 0 )
& & ( mdi - > channel [ ch ] . reg_data = = 0x0000 ) ) { /* Pitch Bend Range */
if ( mdi - > channel [ ch ] . pitch_range > 0 )
mdi - > channel [ ch ] . pitch_range - - ;
}
}
2016-01-12 01:15:27 +00:00
static void do_control_non_registered_param_fine ( struct _mdi * mdi ,
struct _event_data * data ) {
unsigned char ch = data - > channel ;
mdi - > channel [ ch ] . reg_data = ( mdi - > channel [ ch ] . reg_data & 0x3F80 )
| data - > data ;
mdi - > channel [ ch ] . reg_non = 1 ;
}
static void do_control_non_registered_param_course ( struct _mdi * mdi ,
2015-11-28 16:38:40 +00:00
struct _event_data * data ) {
unsigned char ch = data - > channel ;
2016-01-12 01:15:27 +00:00
mdi - > channel [ ch ] . reg_data = ( mdi - > channel [ ch ] . reg_data & 0x7F )
| ( data - > data < < 7 ) ;
2015-11-28 16:38:40 +00:00
mdi - > channel [ ch ] . reg_non = 1 ;
}
static void do_control_registered_param_fine ( struct _mdi * mdi ,
struct _event_data * data ) {
unsigned char ch = data - > channel ;
mdi - > channel [ ch ] . reg_data = ( unsigned short ) ( ( mdi - > channel [ ch ] . reg_data & 0x3F80 )
| data - > data ) ;
mdi - > channel [ ch ] . reg_non = 0 ;
}
static void do_control_registered_param_course ( struct _mdi * mdi ,
struct _event_data * data ) {
unsigned char ch = data - > channel ;
mdi - > channel [ ch ] . reg_data = ( unsigned short ) ( ( mdi - > channel [ ch ] . reg_data & 0x7F )
| ( data - > data < < 7 ) ) ;
mdi - > channel [ ch ] . reg_non = 0 ;
}
static void do_control_channel_sound_off ( struct _mdi * mdi ,
struct _event_data * data ) {
struct _note * note_data = mdi - > note ;
unsigned char ch = data - > channel ;
if ( note_data ) {
do {
if ( ( note_data - > noteid > > 8 ) = = ch ) {
note_data - > active = 0 ;
if ( note_data - > replay ) {
note_data - > replay = NULL ;
}
}
note_data = note_data - > next ;
} while ( note_data ) ;
}
}
static void do_control_channel_controllers_off ( struct _mdi * mdi ,
struct _event_data * data ) {
struct _note * note_data = mdi - > note ;
unsigned char ch = data - > channel ;
mdi - > channel [ ch ] . expression = 127 ;
mdi - > channel [ ch ] . pressure = 127 ;
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 ;
2016-01-12 01:21:41 +00:00
_WM_AdjustChannelVolumes ( mdi , ch ) ;
2015-11-28 16:38:40 +00:00
}
static void do_control_channel_notes_off ( struct _mdi * mdi ,
struct _event_data * data ) {
struct _note * note_data = mdi - > note ;
unsigned char ch = data - > channel ;
if ( mdi - > channel [ ch ] . isdrum )
return ;
if ( note_data ) {
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 = note_data - > next ;
} while ( note_data ) ;
}
}
static void do_patch ( struct _mdi * mdi , struct _event_data * data ) {
unsigned char ch = data - > channel ;
MIDI_EVENT_DEBUG ( __FUNCTION__ , ch ) ;
if ( ! mdi - > channel [ ch ] . isdrum ) {
2015-11-29 10:27:08 +00:00
mdi - > channel [ ch ] . patch = get_patch_data ( ( unsigned short ) ( ( ( mdi - > channel [ ch ] . bank < < 8 ) | data - > data ) ) ) ;
2015-11-28 16:38:40 +00:00
} else {
mdi - > channel [ ch ] . bank = ( unsigned char ) data - > data ;
}
}
static void do_channel_pressure ( struct _mdi * mdi , struct _event_data * data ) {
struct _note * note_data = mdi - > note ;
unsigned char ch = data - > channel ;
MIDI_EVENT_DEBUG ( __FUNCTION__ , ch ) ;
2016-01-12 01:21:41 +00:00
while ( note_data ) {
if ( ( note_data - > noteid > > 8 ) = = ch ) {
note_data - > velocity = ( unsigned char ) data - > data ;
_WM_AdjustNoteVolumes ( mdi , ch , note_data ) ;
if ( note_data - > replay ) {
note_data - > replay - > velocity = ( unsigned char ) data - > data ;
_WM_AdjustNoteVolumes ( mdi , ch , note_data - > replay ) ;
2015-11-28 16:38:40 +00:00
}
2016-01-12 01:21:41 +00:00
}
note_data = note_data - > next ;
2015-11-28 16:38:40 +00:00
}
}
static void do_pitch ( struct _mdi * mdi , struct _event_data * data ) {
struct _note * note_data = mdi - > note ;
unsigned char ch = data - > channel ;
MIDI_EVENT_DEBUG ( __FUNCTION__ , ch ) ;
mdi - > channel [ ch ] . pitch = short ( data - > data - 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 ) {
do {
if ( ( note_data - > noteid > > 8 ) = = ch ) {
note_data - > sample_inc = get_inc ( mdi , note_data ) ;
}
note_data = note_data - > next ;
} while ( note_data ) ;
}
}
static void do_sysex_roland_drum_track ( struct _mdi * mdi ,
struct _event_data * data ) {
unsigned char ch = data - > channel ;
MIDI_EVENT_DEBUG ( __FUNCTION__ , ch ) ;
if ( data - > data > 0 ) {
mdi - > channel [ ch ] . isdrum = 1 ;
mdi - > channel [ ch ] . patch = NULL ;
} else {
mdi - > channel [ ch ] . isdrum = 0 ;
2015-11-29 10:27:08 +00:00
mdi - > channel [ ch ] . patch = get_patch_data ( 0 ) ;
2015-11-28 16:38:40 +00:00
}
}
2016-01-12 00:59:56 +00:00
static void do_sysex_gm_reset ( struct _mdi * mdi , struct _event_data * data ) {
2015-11-28 16:38:40 +00:00
int i ;
for ( i = 0 ; i < 16 ; i + + ) {
mdi - > channel [ i ] . bank = 0 ;
if ( i ! = 9 ) {
2015-11-29 10:27:08 +00:00
mdi - > channel [ i ] . patch = get_patch_data ( 0 ) ;
2015-11-28 16:38:40 +00:00
} else {
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 ;
2016-01-12 01:21:41 +00:00
mdi - > channel [ i ] . balance = 64 ;
mdi - > channel [ i ] . pan = 64 ;
2015-11-28 16:38:40 +00:00
mdi - > channel [ i ] . pitch = 0 ;
mdi - > channel [ i ] . pitch_range = 200 ;
mdi - > channel [ i ] . reg_data = 0xFFFF ;
mdi - > channel [ i ] . isdrum = 0 ;
}
2016-01-12 01:21:41 +00:00
/* I would not expect notes to be active when this event
triggers but we ' ll adjust active notes as well just in case */
_WM_AdjustChannelVolumes ( mdi , 16 ) ; // A setting > 15 adjusts all channels
2015-11-28 16:38:40 +00:00
mdi - > channel [ 9 ] . isdrum = 1 ;
UNUSED ( data ) ; /* NOOP, to please the compiler gods */
}
2016-01-12 00:59:56 +00:00
static void do_sysex_roland_reset ( struct _mdi * mdi , struct _event_data * data ) {
do_sysex_gm_reset ( mdi , data ) ;
}
static void do_sysex_yamaha_reset ( struct _mdi * mdi , struct _event_data * data ) {
do_sysex_gm_reset ( mdi , data ) ;
}
2015-11-28 16:38:40 +00:00
static int add_handle ( void * handle ) {
struct _hndl * tmp_handle = NULL ;
if ( first_handle = = NULL ) {
first_handle = ( struct _hndl * ) malloc ( sizeof ( struct _hndl ) ) ;
if ( first_handle = = NULL ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_MEM , " to get ram " , errno ) ;
return - 1 ;
}
first_handle - > handle = handle ;
first_handle - > prev = NULL ;
first_handle - > next = NULL ;
} else {
tmp_handle = first_handle ;
if ( tmp_handle - > next ) {
while ( tmp_handle - > next )
tmp_handle = tmp_handle - > next ;
}
tmp_handle - > next = ( struct _hndl * ) malloc ( sizeof ( struct _hndl ) ) ;
if ( tmp_handle - > next = = NULL ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_MEM , " to get ram " , errno ) ;
return - 1 ;
}
tmp_handle - > next - > prev = tmp_handle ;
tmp_handle = tmp_handle - > next ;
tmp_handle - > next = NULL ;
tmp_handle - > handle = handle ;
}
return 0 ;
}
static struct _mdi *
Init_MDI ( void ) {
struct _mdi * mdi ;
2015-12-29 22:24:16 +00:00
mdi = new _mdi ;
2015-11-28 16:38:40 +00:00
mdi - > info . copyright = NULL ;
mdi - > info . mixer_options = WM_MixerOptions ;
load_patch ( mdi , 0x0000 ) ;
mdi - > samples_to_mix = 0 ;
mdi - > info . current_sample = 0 ;
mdi - > info . total_midi_time = 0 ;
mdi - > info . approx_total_samples = 0 ;
do_sysex_roland_reset ( mdi , NULL ) ;
return mdi ;
}
static void freeMDI ( struct _mdi * mdi ) {
struct _sample * tmp_sample ;
unsigned long int i ;
if ( mdi - > patch_count ! = 0 ) {
2015-12-29 22:24:16 +00:00
patch_lock . Enter ( ) ;
2015-11-28 16:38:40 +00:00
for ( i = 0 ; i < mdi - > patch_count ; i + + ) {
mdi - > patches [ i ] - > inuse_count - - ;
if ( mdi - > patches [ i ] - > inuse_count = = 0 ) {
/* free samples here */
while ( mdi - > patches [ i ] - > first_sample ) {
tmp_sample = mdi - > patches [ i ] - > first_sample - > next ;
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 ;
}
}
2015-12-29 22:24:16 +00:00
patch_lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
free ( mdi - > patches ) ;
}
free ( mdi - > tmp_info ) ;
_WM_free_reverb ( mdi - > reverb ) ;
free ( mdi - > mix_buffer ) ;
free ( mdi ) ;
}
2015-12-29 02:33:41 +00:00
static int * WM_Mix_Linear ( midi * handle , int * buffer , unsigned long int count )
{
struct _mdi * mdi = ( struct _mdi * ) handle ;
unsigned long int data_pos ;
signed int premix , left_mix , right_mix ;
struct _note * note_data = NULL ;
do {
note_data = mdi - > note ;
left_mix = right_mix = 0 ;
2015-12-29 10:36:56 +00:00
if ( note_data ! = NULL ) {
2015-12-29 02:33:41 +00:00
while ( note_data ) {
/*
* = = = = = = = = = = = = = = = = = = =
* resample the sample
* = = = = = = = = = = = = = = = = = = =
*/
data_pos = note_data - > sample_pos > > FPBITS ;
2016-01-12 01:21:41 +00:00
premix = ( ( note_data - > sample - > data [ data_pos ] + ( ( ( note_data - > sample - > data [ data_pos + 1 ] - note_data - > sample - > data [ data_pos ] ) * ( int ) ( note_data - > sample_pos & FPMASK ) ) / 1024 ) ) * ( note_data - > env_level > > 12 ) ) / 1024 ;
2015-12-29 02:33:41 +00:00
2016-01-12 01:21:41 +00:00
left_mix + = ( premix * ( int ) note_data - > left_mix_volume ) / 1024 ;
right_mix + = ( premix * ( int ) note_data - > right_mix_volume ) / 1024 ;
2015-12-29 02:33:41 +00:00
/*
* = = = = = = = = = = = = = = = = = = = = = = = =
* sample position checking
* = = = = = = = = = = = = = = = = = = = = = = = =
*/
note_data - > sample_pos + = note_data - > sample_inc ;
2016-01-12 01:19:06 +00:00
if ( note_data - > modes & SAMPLE_LOOP ) {
if ( note_data - > sample_pos > note_data - > sample - > loop_end ) {
2015-12-29 02:33:41 +00:00
note_data - > sample_pos =
2016-01-12 01:19:06 +00:00
note_data - > sample - > loop_start
+ ( ( note_data - > sample_pos
- note_data - > sample - > loop_start )
% note_data - > sample - > loop_size ) ;
2015-12-29 02:33:41 +00:00
}
2016-01-12 01:19:06 +00:00
} else if ( note_data - > sample_pos > = note_data - > sample - > data_length ) {
goto END_THIS_NOTE ;
2015-12-29 02:33:41 +00:00
}
2015-12-29 10:36:56 +00:00
if ( note_data - > env_inc = = 0 ) {
2015-12-29 02:33:41 +00:00
note_data = note_data - > next ;
continue ;
}
note_data - > env_level + = note_data - > env_inc ;
2016-01-12 01:19:06 +00:00
if ( note_data - > env_inc < 0 ) {
if ( note_data - > env_level > note_data - > sample - > env_target [ note_data - > env ] ) {
note_data = note_data - > next ;
continue ;
}
} else if ( note_data - > env_inc > 0 ) {
if ( note_data - > env_level < note_data - > sample - > env_target [ note_data - > env ] ) {
note_data = note_data - > next ;
continue ;
}
2015-12-29 02:33:41 +00:00
}
2016-01-12 01:19:06 +00:00
// Yes could have a condition here but
// it would create another bottleneck
2015-12-29 02:33:41 +00:00
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 = note_data - > next ;
continue ;
}
break ;
case 2 :
2016-01-12 01:19:06 +00:00
if ( note_data - > modes & SAMPLE_SUSTAIN /*|| note_data->hold*/ ) {
2015-12-29 02:33:41 +00:00
note_data - > env_inc = 0 ;
note_data = note_data - > next ;
continue ;
} else if ( note_data - > modes & SAMPLE_CLAMPED ) {
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 ] ;
}
continue ;
}
break ;
case 5 :
2015-12-29 10:36:56 +00:00
if ( note_data - > env_level = = 0 ) {
2016-01-12 01:19:06 +00:00
goto END_THIS_NOTE ;
2015-12-29 02:33:41 +00:00
}
/* sample release */
if ( note_data - > modes & SAMPLE_LOOP )
note_data - > modes ^ = SAMPLE_LOOP ;
note_data - > env_inc = 0 ;
note_data = note_data - > next ;
continue ;
case 6 :
2016-01-12 01:19:06 +00:00
END_THIS_NOTE :
2015-12-29 10:36:56 +00:00
if ( note_data - > replay ! = NULL ) {
2016-01-12 01:19:06 +00:00
note_data - > active = 0 ;
2015-12-29 02:33:41 +00:00
{
struct _note * prev_note = NULL ;
struct _note * nte_array = mdi - > note ;
if ( nte_array ! = note_data ) {
do {
prev_note = nte_array ;
nte_array = nte_array - > next ;
} while ( nte_array ! = note_data ) ;
}
if ( prev_note ) {
prev_note - > next = note_data - > replay ;
} else {
mdi - > note = note_data - > replay ;
}
note_data - > replay - > next = note_data - > next ;
note_data = note_data - > replay ;
note_data - > active = 1 ;
}
} else {
2016-01-12 01:19:06 +00:00
note_data - > active = 0 ;
2015-12-29 02:33:41 +00:00
{
struct _note * prev_note = NULL ;
struct _note * nte_array = mdi - > note ;
if ( nte_array ! = note_data ) {
do {
prev_note = nte_array ;
nte_array = nte_array - > next ;
} while ( ( nte_array ! = note_data )
& & ( nte_array ) ) ;
}
if ( prev_note ) {
prev_note - > next = note_data - > next ;
} else {
mdi - > note = note_data - > next ;
}
note_data = note_data - > next ;
}
}
continue ;
}
note_data - > env + + ;
if ( note_data - > is_off = = 1 ) {
do_note_off_extra ( note_data ) ;
}
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 = note_data - > next ;
continue ;
}
/*
* = = = = = = = = = = = = = = = = = = = = = = = = =
* mix the channels together
* = = = = = = = = = = = = = = = = = = = = = = = = =
*/
}
* buffer + + = left_mix ;
* buffer + + = right_mix ;
} while ( - - count ) ;
return buffer ;
}
static int * WM_Mix_Gauss ( midi * handle , int * buffer , unsigned long int count )
{
2015-12-29 02:44:10 +00:00
if ( ! gauss_table ) init_gauss ( ) ;
2015-12-29 02:33:41 +00:00
struct _mdi * mdi = ( struct _mdi * ) handle ;
2015-11-28 16:38:40 +00:00
unsigned long int data_pos ;
2015-12-29 02:33:41 +00:00
signed int premix , left_mix , right_mix ;
2015-11-28 16:38:40 +00:00
struct _note * note_data = NULL ;
signed short int * sptr ;
double y , xd ;
double * gptr , * gend ;
int left , right , temp_n ;
int ii , jj ;
2015-12-29 02:33:41 +00:00
do {
note_data = mdi - > note ;
left_mix = right_mix = 0 ;
2015-12-29 10:36:56 +00:00
if ( note_data ! = NULL ) {
2015-12-29 02:33:41 +00:00
while ( note_data ) {
/*
* = = = = = = = = = = = = = = = = = = =
* resample the sample
* = = = = = = = = = = = = = = = = = = =
*/
data_pos = note_data - > sample_pos > > 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 < < FPBITS ) ;
xd + = temp_n > > 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 ) *
( gauss_n + 1 ) ] ;
gend = gptr + gauss_n ;
sptr = note_data - > sample - > data
+ ( note_data - > sample_pos > > FPBITS )
- ( gauss_n > > 1 ) ;
do {
y + = * ( sptr + + ) * * ( gptr + + ) ;
} while ( gptr < = gend ) ;
}
2016-01-12 01:21:41 +00:00
premix = ( int ) ( ( y * ( note_data - > env_level > > 12 ) ) / 1024 ) ;
2015-12-29 02:33:41 +00:00
2016-01-12 01:21:41 +00:00
left_mix + = ( premix * ( int ) note_data - > left_mix_volume ) / 1024 ;
right_mix + = ( premix * ( int ) note_data - > right_mix_volume ) / 1024 ;
2015-12-29 02:33:41 +00:00
/*
* = = = = = = = = = = = = = = = = = = = = = = = =
* sample position checking
* = = = = = = = = = = = = = = = = = = = = = = = =
*/
note_data - > sample_pos + = note_data - > sample_inc ;
2015-12-29 10:36:56 +00:00
if ( note_data - > sample_pos > note_data - > sample - > loop_end )
{
2015-12-29 02:33:41 +00:00
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 ) ;
2015-12-29 10:36:56 +00:00
} else if ( note_data - > sample_pos > = note_data - > sample - > data_length ) {
2016-01-12 01:19:06 +00:00
goto END_THIS_NOTE ;
2015-12-29 02:33:41 +00:00
}
}
2015-12-29 10:36:56 +00:00
if ( note_data - > env_inc = = 0 ) {
2015-12-29 02:33:41 +00:00
note_data = note_data - > next ;
continue ;
}
note_data - > env_level + = note_data - > env_inc ;
2016-01-12 01:19:06 +00:00
if ( note_data - > env_inc < 0 ) {
if ( note_data - > env_level
> note_data - > sample - > env_target [ note_data - > env ] ) {
note_data = note_data - > next ;
continue ;
}
} else if ( note_data - > env_inc > 0 ) {
if ( note_data - > env_level
< note_data - > sample - > env_target [ note_data - > env ] ) {
note_data = note_data - > next ;
continue ;
}
2015-12-29 02:33:41 +00:00
}
2016-01-12 01:19:06 +00:00
// Yes could have a condition here but
// it would create another bottleneck
2015-12-29 02:33:41 +00:00
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 = note_data - > next ;
continue ;
}
break ;
case 2 :
if ( note_data - > modes & SAMPLE_SUSTAIN ) {
note_data - > env_inc = 0 ;
note_data = note_data - > next ;
continue ;
} else if ( note_data - > modes & SAMPLE_CLAMPED ) {
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 ] ;
}
continue ;
}
break ;
case 5 :
2015-12-29 10:36:56 +00:00
if ( note_data - > env_level = = 0 ) {
2016-01-12 01:19:06 +00:00
goto END_THIS_NOTE ;
2015-12-29 02:33:41 +00:00
}
/* sample release */
if ( note_data - > modes & SAMPLE_LOOP )
note_data - > modes ^ = SAMPLE_LOOP ;
note_data - > env_inc = 0 ;
note_data = note_data - > next ;
continue ;
case 6 :
2016-01-12 01:19:06 +00:00
END_THIS_NOTE :
2015-12-29 10:36:56 +00:00
if ( note_data - > replay ! = NULL ) {
2016-01-12 01:19:06 +00:00
note_data - > active = 0 ;
2015-12-29 02:33:41 +00:00
{
struct _note * prev_note = NULL ;
struct _note * nte_array = mdi - > note ;
if ( nte_array ! = note_data ) {
do {
prev_note = nte_array ;
nte_array = nte_array - > next ;
} while ( nte_array ! = note_data ) ;
}
if ( prev_note ) {
prev_note - > next = note_data - > replay ;
} else {
mdi - > note = note_data - > replay ;
}
note_data - > replay - > next = note_data - > next ;
note_data = note_data - > replay ;
note_data - > active = 1 ;
}
} else {
2016-01-12 01:19:06 +00:00
note_data - > active = 0 ;
2015-12-29 02:33:41 +00:00
{
struct _note * prev_note = NULL ;
struct _note * nte_array = mdi - > note ;
if ( nte_array ! = note_data ) {
do {
prev_note = nte_array ;
nte_array = nte_array - > next ;
} while ( ( nte_array ! = note_data )
& & ( nte_array ) ) ;
}
if ( prev_note ) {
prev_note - > next = note_data - > next ;
} else {
mdi - > note = note_data - > next ;
}
note_data = note_data - > next ;
}
}
continue ;
}
note_data - > env + + ;
if ( note_data - > is_off = = 1 ) {
do_note_off_extra ( note_data ) ;
}
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 = note_data - > next ;
continue ;
}
/*
* = = = = = = = = = = = = = = = = = = = = = = = = =
* mix the channels together
* = = = = = = = = = = = = = = = = = = = = = = = = =
*/
}
* buffer + + = left_mix ;
* buffer + + = right_mix ;
} while ( - - count ) ;
return buffer ;
}
2015-12-29 04:07:51 +00:00
int * WM_Mix ( midi * handle , int * buffer , unsigned long count )
{
if ( ( ( struct _mdi * ) handle ) - > info . mixer_options & WM_MO_ENHANCED_RESAMPLING )
{
return WM_Mix_Gauss ( handle , buffer , count ) ;
}
else
{
return WM_Mix_Linear ( handle , buffer , count ) ;
}
}
2015-11-28 16:38:40 +00:00
/*
* = = = = = = = = = = = = = = = = = = = = = = = = =
* External Functions
* = = = = = = = = = = = = = = = = = = = = = = = = =
*/
WM_SYMBOL const char *
WildMidi_GetString ( unsigned short int info ) {
switch ( info ) {
case WM_GS_VERSION :
return WM_Version ;
}
return NULL ;
}
WM_SYMBOL int WildMidi_Init ( const char * config_file , unsigned short int rate ,
unsigned short int options ) {
if ( WM_Initialized ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_ALR_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 ( ) ;
2018-02-22 21:35:49 +00:00
if ( WM_LoadConfig ( config_file , true ) = = - 1 ) {
2015-11-28 16:38:40 +00:00
return - 1 ;
}
if ( options & 0x5FF8 ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG , " (invalid option) " ,
0 ) ;
WM_FreePatches ( ) ;
return - 1 ;
}
WM_MixerOptions = options ;
if ( rate < 11025 ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (rate out of bounds, range is 11025 - 65535) " , 0 ) ;
WM_FreePatches ( ) ;
return - 1 ;
}
_WM_SampleRate = rate ;
WM_Initialized = 1 ;
return 0 ;
}
2015-12-29 04:07:51 +00:00
WM_SYMBOL int WildMidi_GetSampleRate ( void )
{
return _WM_SampleRate ;
}
2015-11-28 16:38:40 +00:00
WM_SYMBOL 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 ] ;
return 0 ;
}
WM_SYMBOL int WildMidi_Close ( midi * handle ) {
struct _mdi * mdi = ( struct _mdi * ) handle ;
struct _hndl * tmp_handle ;
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 ;
}
2015-12-29 22:24:16 +00:00
mdi - > lock . Enter ( ) ;
2015-11-28 16:38:40 +00:00
if ( first_handle - > handle = = handle ) {
tmp_handle = first_handle - > next ;
free ( first_handle ) ;
first_handle = tmp_handle ;
if ( first_handle )
first_handle - > prev = NULL ;
} else {
tmp_handle = first_handle ;
while ( tmp_handle - > handle ! = handle ) {
tmp_handle = tmp_handle - > next ;
if ( tmp_handle = = NULL ) {
break ;
}
}
if ( tmp_handle ) {
tmp_handle - > prev - > next = tmp_handle - > next ;
if ( tmp_handle - > next ) {
tmp_handle - > next - > prev = tmp_handle - > prev ;
}
free ( tmp_handle ) ;
}
}
freeMDI ( mdi ) ;
return 0 ;
}
2015-12-29 04:07:51 +00:00
midi * WildMidi_NewMidi ( ) {
midi * ret = NULL ;
if ( ! WM_Initialized ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_NOT_INIT , NULL , 0 ) ;
return NULL ;
}
ret = Init_MDI ( ) ;
if ( ret ) {
if ( add_handle ( ret ) ! = 0 ) {
WildMidi_Close ( ret ) ;
ret = NULL ;
}
}
2015-12-30 09:14:18 +00:00
2015-12-30 19:32:19 +00:00
if ( ( ( ( _mdi * ) ret ) - > reverb = _WM_init_reverb ( _WM_SampleRate , reverb_room_width ,
reverb_room_length , reverb_listen_posx , reverb_listen_posy ) )
= = NULL ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_MEM , " to init reverb " , 0 ) ;
2015-12-30 09:14:18 +00:00
WildMidi_Close ( ret ) ;
ret = NULL ;
2015-12-30 19:32:19 +00:00
}
2015-12-30 09:14:18 +00:00
2015-12-29 04:07:51 +00:00
return ret ;
}
2015-11-28 16:38:40 +00:00
WM_SYMBOL int WildMidi_SetOption ( midi * handle , unsigned short int options ,
unsigned short int setting ) {
struct _mdi * mdi ;
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 ;
}
mdi = ( struct _mdi * ) handle ;
2015-12-29 22:24:16 +00:00
mdi - > lock . Enter ( ) ;
2015-11-28 16:38:40 +00:00
if ( ( ! ( options & 0x0007 ) ) | | ( options & 0xFFF8 ) ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG , " (invalid option) " ,
0 ) ;
2015-12-29 22:24:16 +00:00
mdi - > lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return - 1 ;
}
if ( setting & 0xFFF8 ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_INVALID_ARG ,
" (invalid setting) " , 0 ) ;
2015-12-29 22:24:16 +00:00
mdi - > lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return - 1 ;
}
mdi - > info . mixer_options = ( ( mdi - > info . mixer_options & ( 0x00FF ^ options ) )
| ( options & setting ) ) ;
if ( options & WM_MO_LOG_VOLUME ) {
2016-01-12 01:21:41 +00:00
_WM_AdjustChannelVolumes ( mdi , 16 ) ; // Settings greater than 15
// adjust all channels
2015-11-28 16:38:40 +00:00
} else if ( options & WM_MO_REVERB ) {
_WM_reset_reverb ( mdi - > reverb ) ;
}
2015-12-29 22:24:16 +00:00
mdi - > lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return 0 ;
}
WM_SYMBOL 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 ;
}
2015-12-29 22:24:16 +00:00
mdi - > lock . Enter ( ) ;
2015-11-28 16:38:40 +00:00
if ( mdi - > tmp_info = = NULL ) {
mdi - > tmp_info = ( struct _WM_Info * ) malloc ( sizeof ( struct _WM_Info ) ) ;
if ( mdi - > tmp_info = = NULL ) {
_WM_ERROR ( __FUNCTION__ , __LINE__ , WM_ERR_MEM , " to set info " , 0 ) ;
2015-12-29 22:24:16 +00:00
mdi - > lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return NULL ;
}
mdi - > tmp_info - > copyright = 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 ;
if ( mdi - > info . copyright ) {
free ( mdi - > tmp_info - > copyright ) ;
mdi - > tmp_info - > copyright = ( char * ) malloc ( strlen ( mdi - > info . copyright ) + 1 ) ;
strcpy ( mdi - > tmp_info - > copyright , mdi - > info . copyright ) ;
} else {
mdi - > tmp_info - > copyright = NULL ;
}
2015-12-29 22:24:16 +00:00
mdi - > lock . Leave ( ) ;
2015-11-28 16:38:40 +00:00
return mdi - > tmp_info ;
}
WM_SYMBOL int WildMidi_Shutdown ( void ) {
if ( ! WM_Initialized ) {
2015-12-28 20:23:21 +00:00
// No error if trying to shut down an uninitialized device.
return 0 ;
2015-11-28 16:38:40 +00:00
}
while ( first_handle ) {
/* closes open handle and rotates the handles list. */
WildMidi_Close ( ( struct _mdi * ) first_handle - > handle ) ;
}
WM_FreePatches ( ) ;
free_gauss ( ) ;
/* reset the globals */
WM_MasterVolume = 948 ;
WM_MixerOptions = 0 ;
fix_release = 0 ;
auto_amp = 0 ;
auto_amp_with_amp = 0 ;
reverb_room_width = 16.875f ;
reverb_room_length = 22.5f ;
reverb_listen_posx = 8.4375f ;
reverb_listen_posy = 16.875f ;
WM_Initialized = 0 ;
return 0 ;
}
2015-12-29 04:07:51 +00:00
WildMidi_Renderer : : WildMidi_Renderer ( )
{
handle = WildMidi_NewMidi ( ) ;
}
WildMidi_Renderer : : ~ WildMidi_Renderer ( )
{
WildMidi_Close ( ( midi * ) handle ) ;
}
void WildMidi_Renderer : : ShortEvent ( int status , int parm1 , int parm2 )
{
_mdi * mdi = ( _mdi * ) handle ;
_event_data ev ;
ev . channel = status & 0x0F ;
switch ( ( status & 0xF0 ) > > 4 ) // command
{
case 0x8 :
ev . data = ( parm1 < < 8 ) | parm2 ;
do_note_off ( mdi , & ev ) ;
break ;
case 0x9 :
ev . data = ( parm1 < < 8 ) | parm2 ;
do_note_on ( mdi , & ev ) ;
break ;
case 0xA :
ev . data = ( parm1 < < 8 ) | parm2 ;
do_aftertouch ( mdi , & ev ) ;
break ;
case 0xC :
ev . data = parm1 ;
do_patch ( mdi , & ev ) ;
break ;
case 0xD :
ev . data = parm1 ;
do_channel_pressure ( mdi , & ev ) ;
break ;
case 0xE :
ev . data = parm1 | ( parm2 < < 7 ) ;
do_pitch ( mdi , & ev ) ;
break ;
case 0xB : // Controllers
ev . data = parm2 ;
switch ( parm1 )
{
2016-01-12 01:15:27 +00:00
case 0 : do_control_bank_select ( mdi , & ev ) ; break ;
case 6 : do_control_data_entry_course ( mdi , & ev ) ; break ; // [sic]
case 7 : do_control_channel_volume ( mdi , & ev ) ; break ;
case 8 : do_control_channel_balance ( mdi , & ev ) ; break ;
case 10 : do_control_channel_pan ( mdi , & ev ) ; break ;
case 11 : do_control_channel_expression ( mdi , & ev ) ; break ;
case 38 : do_control_data_entry_fine ( mdi , & ev ) ; break ;
case 64 : do_control_channel_hold ( mdi , & ev ) ; break ;
case 96 : do_control_data_increment ( mdi , & ev ) ; break ;
case 97 : do_control_data_decrement ( mdi , & ev ) ; break ;
case 98 : do_control_non_registered_param_fine ( mdi , & ev ) ; break ;
case 99 : do_control_non_registered_param_course ( mdi , & ev ) ; break ; // [sic]
case 100 : do_control_registered_param_fine ( mdi , & ev ) ; break ;
case 101 : do_control_registered_param_course ( mdi , & ev ) ; break ; // [sic]
case 120 : do_control_channel_sound_off ( mdi , & ev ) ; break ;
case 121 : do_control_channel_controllers_off ( mdi , & ev ) ; break ;
case 123 : do_control_channel_notes_off ( mdi , & ev ) ; break ;
2015-12-29 04:07:51 +00:00
}
}
}
2015-12-30 09:58:52 +00:00
void WildMidi_Renderer : : LongEvent ( const unsigned char * data , int len )
2015-12-29 04:07:51 +00:00
{
2015-12-29 23:49:43 +00:00
// Check for Roland SysEx
if ( len > = 11 & & // Must be at least 11 bytes
data [ len - 1 ] = = 0xF7 & & // SysEx end
data [ 0 ] = = 0xF0 & & // SysEx
data [ 1 ] = = 0x41 & & // Roland
data [ 2 ] = = 0x10 & & // Device ID, defaults to 0x10
data [ 3 ] = = 0x42 & & // Model ID, 0x42 indicates a GS synth
data [ 4 ] = = 0x12 & & // The other end is sending data to us
data [ 5 ] = = 0x40 ) // We only care about addresses with this first byte
{
// Calculate checksum
int cksum = 0 ;
for ( int i = 5 ; i < len - 2 ; + + i )
{
cksum + = data [ i ] ;
}
cksum = 128 - ( cksum & 0x7F ) ;
if ( data [ len - 2 ] = = cksum )
{ // Check destination address
if ( ( ( data [ 6 ] & 0xF0 ) = = 0x10 ) & & data [ 7 ] = = 0x15 )
{ // Roland drum track setting
2015-12-30 09:58:52 +00:00
unsigned char sysex_ch = data [ 6 ] & 0x0F ;
2015-12-29 23:49:43 +00:00
if ( sysex_ch = = 0 )
{
sysex_ch = 9 ;
}
else if ( sysex_ch < = 9 )
{
sysex_ch - = 1 ;
}
2016-01-12 10:12:19 +00:00
_event_data ev = { sysex_ch , data [ 8 ] } ;
2015-12-29 23:49:43 +00:00
do_sysex_roland_drum_track ( ( _mdi * ) handle , & ev ) ;
}
else if ( data [ 6 ] = = 0x00 & & data [ 7 ] = = 0x7F & & data [ 8 ] = = 0x00 )
{ // Roland GS reset
do_sysex_roland_reset ( ( _mdi * ) handle , NULL ) ;
}
}
}
2016-01-12 00:59:56 +00:00
// For non-Roland Sysex messages */
else
{
const unsigned char gm_reset [ ] = { 0xf0 , 0x7e , 0x7f , 0x09 , 0x01 , 0xf7 } ;
const unsigned char yamaha_reset [ ] = { 0xf0 , 0x43 , 0x10 , 0x4c , 0x00 , 0x00 , 0x7e , 0x00 , 0xf7 } ;
if ( len = = 6 & & memcmp ( gm_reset , data , 6 ) = = 0 )
{
do_sysex_gm_reset ( ( _mdi * ) handle , NULL ) ;
}
else if ( len = = 9 & & memcmp ( yamaha_reset , data , 9 ) = = 0 )
{
do_sysex_yamaha_reset ( ( _mdi * ) handle , NULL ) ;
}
}
2015-12-29 04:07:51 +00:00
}
void WildMidi_Renderer : : ComputeOutput ( float * fbuffer , int len )
{
_mdi * mdi = ( _mdi * ) handle ;
int * buffer = ( int * ) fbuffer ;
int * newbuf = WM_Mix ( handle , buffer , len ) ;
// assert(newbuf - buffer == len);
if ( mdi - > info . mixer_options & WM_MO_REVERB ) {
_WM_do_reverb ( mdi - > reverb , buffer , len * 2 ) ;
}
for ( ; buffer < newbuf ; + + buffer )
{
2018-02-22 21:35:49 +00:00
* ( float * ) buffer = ( float ) * buffer * ( 2. / 32768.f ) ; // boost the volume because Wildmidi is far more quiet than the other synths and therefore hard to balance.
2015-12-29 04:07:51 +00:00
}
}
void WildMidi_Renderer : : LoadInstrument ( int bank , int percussion , int instr )
{
load_patch ( ( _mdi * ) handle , ( bank < < 8 ) | instr | ( percussion ? 0x80 : 0 ) ) ;
}
int WildMidi_Renderer : : GetVoiceCount ( )
{
int count = 0 ;
for ( _note * note_data = ( ( _mdi * ) handle ) - > note ; note_data ! = NULL ; note_data = note_data - > next )
{
count + + ;
}
return count ;
}
2015-12-30 09:14:18 +00:00
void WildMidi_Renderer : : SetOption ( int opt , int set )
{
WildMidi_SetOption ( ( _mdi * ) handle , ( unsigned short ) opt , ( unsigned short ) set ) ;
}