//Nick Collins chord detection algorithm adapted from my SuperCollider KeyTrack code, with addition of MeanSeperation step for vertical vs horizontal, e.g., only use FFT information where tonal predominates over percussive, following:
//Derry FitzGerald (2010) "Harmonic/Percussive Separation using Median Filtering" International Conference on Digital Audio Effects (DAFx)


function MMLLChordDetector(sampleRate, keydecay=2, chromaleak=0.5) {
    
    var self = this; 
    
    //helpful constants
    //#define N 4096
   
    //weighting parameters
    
    //4096 FFT at 44100 SR
    //[720]
    self.g_weights44100 = [ 0.89160997732426, 0.10839002267574, 0.39160997732426, 0.10839002267574, 0.2249433106576, 0.10839002267574, 0.14160997732426, 0.10839002267574, 0.091609977324263, 0.10839002267574, 0.05827664399093, 0.10839002267574, 0.58784929938181, 0.41215070061819, 0.087849299381813, 0.41215070061819, 0.25451596604848, 0.078817367284855, 0.087849299381813, 0.16215070061819, 0.18784929938181, 0.012150700618187, 0.087849299381812, 0.078817367284855, 0.26602607158423, 0.73397392841577, 0.26602607158423, 0.23397392841577, 0.26602607158423, 0.067307261749107, 0.016026071584227, 0.23397392841577, 0.066026071584226, 0.13397392841577, 0.099359404917559, 0.067307261749107, 0.9250662388251, 0.074933761174898, 0.4250662388251, 0.074933761174898, 0.25839957215844, 0.074933761174898, 0.1750662388251, 0.074933761174898, 0.1250662388251, 0.074933761174898, 0.091732905491768, 0.074933761174898, 0.56383187935789, 0.43616812064211, 0.063831879357891, 0.43616812064211, 0.23049854602456, 0.10283478730877, 0.063831879357891, 0.18616812064211, 0.16383187935789, 0.03616812064211, 0.063831879357892, 0.10283478730877, 0.18111740708786, 0.81888259291214, 0.18111740708786, 0.31888259291214, 0.18111740708786, 0.15221592624547, 0.18111740708786, 0.068882592912141, 0.18111740708786, 0.018882592912141, 0.014450740421193, 0.15221592624547, 0.77564554804057, 0.22435445195943, 0.27564554804057, 0.22435445195943, 0.1089788813739, 0.22435445195943, 0.02564554804057, 0.22435445195943, 0.17564554804057, 0.024354451959429, 0.1089788813739, 0.057687785292764, 0.34606307757871, 0.65393692242129, 0.34606307757871, 0.15393692242129, 0.012729744245378, 0.32060358908796, 0.096063077578711, 0.15393692242129, 0.14606307757871, 0.053936922421289, 0.012729744245378, 0.15393692242129, 0.89093630414068, 0.10906369585932, 0.39093630414068, 0.10906369585932, 0.22426963747401, 0.10906369585932, 0.14093630414068, 0.10906369585932, 0.090936304140679, 0.10906369585932, 0.057602970807346, 0.10906369585932, 0.40874628442826, 0.59125371557174, 0.40874628442826, 0.091253715571737, 0.075412951094929, 0.2579203822384, 0.15874628442826, 0.091253715571737, 0.0087462844282626, 0.19125371557174, 0.075412951094929, 0.091253715571738, 0.89788375407457, 0.10211624592543, 0.39788375407457, 0.10211624592543, 0.23121708740791, 0.10211624592543, 0.14788375407457, 0.10211624592543, 0.097883754074573, 0.10211624592543, 0.06455042074124, 0.10211624592543, 0.35664375687383, 0.64335624312617, 0.35664375687383, 0.14335624312617, 0.023310423540502, 0.31002290979283, 0.10664375687383, 0.14335624312617, 0.15664375687384, 0.043356243126163, 0.023310423540502, 0.14335624312616, 0.78321995464853, 0.21678004535147, 0.28321995464853, 0.21678004535147, 0.11655328798186, 0.21678004535147, 0.033219954648526, 0.21678004535147, 0.18321995464853, 0.016780045351474, 0.11655328798186, 0.050113378684807, 0.17569859876363, 0.82430140123637, 0.17569859876363, 0.32430140123637, 0.17569859876362, 0.15763473456971, 0.17569859876363, 0.074301401236374, 0.17569859876363, 0.024301401236373, 0.0090319320969575, 0.15763473456971, 0.53205214316846, 0.46794785683154, 0.032052143168455, 0.46794785683154, 0.19871880983512, 0.13461452349821, 0.032052143168455, 0.21794785683154, 0.13205214316846, 0.067947856831543, 0.032052143168454, 0.13461452349821, 0.8501324776502, 0.1498675223498, 0.3501324776502, 0.1498675223498, 0.18346581098354, 0.1498675223498, 0.1001324776502, 0.1498675223498, 0.050132477650203, 0.1498675223498, 0.01679914431687, 0.1498675223498, 0.12766375871578, 0.87233624128422, 0.12766375871578, 0.37233624128422, 0.12766375871578, 0.20566957461755, 0.12766375871578, 0.12233624128422, 0.12766375871578, 0.072336241284219, 0.12766375871578, 0.039002907950883, 0.36223481417572, 0.63776518582428, 0.36223481417572, 0.13776518582428, 0.028901480842386, 0.30443185249095, 0.11223481417572, 0.13776518582428, 0.16223481417572, 0.037765185824279, 0.028901480842386, 0.13776518582428, 0.55129109608114, 0.44870890391886, 0.05129109608114, 0.44870890391886, 0.21795776274781, 0.11537557058553, 0.05129109608114, 0.19870890391886, 0.15129109608114, 0.048708903918859, 0.051291096081139, 0.11537557058553, 0.69212615515742, 0.30787384484258, 0.19212615515742, 0.30787384484258, 0.025459488490756, 0.30787384484258, 0.19212615515742, 0.057873844842579, 0.092126155157422, 0.10787384484258, 0.025459488490756, 0.14120717817591, 0.78187260828136, 0.21812739171864, 0.28187260828136, 0.21812739171864, 0.11520594161469, 0.21812739171864, 0.031872608281361, 0.21812739171864, 0.18187260828136, 0.018127391718639, 0.11520594161469, 0.051460725051972, 0.81749256885653, 0.18250743114347, 0.31749256885653, 0.18250743114347, 0.15082590218986, 0.18250743114348, 0.067492568856526, 0.18250743114347, 0.017492568856525, 0.18250743114347, 0.15082590218986, 0.015840764476809, 0.79576750814915, 0.20423249185085, 0.29576750814915, 0.20423249185085, 0.12910084148248, 0.20423249185085, 0.045767508149147, 0.20423249185085, 0.19576750814915, 0.0042324918508541, 0.12910084148248, 0.037565825184186, 0.71328751374767, 0.28671248625233, 0.21328751374767, 0.28671248625233, 0.046620847081009, 0.28671248625232, 0.21328751374767, 0.036712486252327, 0.11328751374767, 0.086712486252327, 0.046620847081009, 0.12004581958566, 0.56643990929705, 0.43356009070295, 0.066439909297053, 0.43356009070295, 0.23310657596372, 0.10022675736961, 0.066439909297053, 0.18356009070295, 0.16643990929705, 0.033560090702949, 0.066439909297053, 0.10022675736961, 0.35139719752725, 0.64860280247275, 0.35139719752725, 0.14860280247275, 0.018063864193915, 0.31526946913942, 0.10139719752725, 0.14860280247275, 0.15139719752725, 0.048602802472746, 0.018063864193915, 0.14860280247275, 0.06410428633691, 0.93589571366309, 0.06410428633691, 0.43589571366309, 0.064104286336909, 0.26922904699642, 0.06410428633691, 0.18589571366309, 0.064104286336914, 0.13589571366309, 0.064104286336909, 0.10256238032976, 0.70026495530041, 0.29973504469959, 0.20026495530041, 0.29973504469959, 0.03359828863374, 0.29973504469959, 0.20026495530041, 0.049735044699592, 0.10026495530041, 0.099735044699594, 0.03359828863374, 0.13306837803293, 0.25532751743156, 0.74467248256844, 0.25532751743156, 0.24467248256844, 0.25532751743157, 0.078005815901766, 0.0053275174315637, 0.24467248256844, 0.055327517431562, 0.14467248256844, 0.088660850764901, 0.078005815901766, 0.72446962835144, 0.27553037164856, 0.22446962835144, 0.27553037164856, 0.057802961684772, 0.27553037164856, 0.22446962835144, 0.025530371648557, 0.12446962835144, 0.075530371648557, 0.057802961684772, 0.1088637049819, 0.10258219216228, 0.89741780783772, 0.10258219216228, 0.39741780783772, 0.10258219216228, 0.23075114117105, 0.10258219216228, 0.14741780783772, 0.10258219216228, 0.097417807837718, 0.10258219216228, 0.064084474504388, 0.38425231031485, 0.61574768968515, 0.38425231031485, 0.11574768968515, 0.050918976981516, 0.28241435635182, 0.13425231031485, 0.11574768968515, 0.18425231031485, 0.015747689685151, 0.050918976981516, 0.11574768968515, 0.56374521656272, 0.43625478343728, 0.063745216562722, 0.43625478343728, 0.23041188322939, 0.10292145010394, 0.063745216562722, 0.18625478343728, 0.16374521656272, 0.036254783437278, 0.063745216562722, 0.10292145010394, 0.63498513771305, 0.36501486228695, 0.13498513771305, 0.36501486228695, 0.30165180437972, 0.031681528953617, 0.13498513771305, 0.11501486228695, 0.034985137713051, 0.16501486228695, 0.13498513771305, 0.031681528953617, 0.5915350162983, 0.4084649837017, 0.091535016298302, 0.4084649837017, 0.25820168296497, 0.075131650368367, 0.091535016298302, 0.1584649837017, 0.1915350162983, 0.0084649837017025, 0.091535016298299, 0.075131650368367, 0.42657502749535, 0.57342497250465, 0.42657502749535, 0.073424972504654, 0.093241694162018, 0.24009163917132, 0.17657502749535, 0.073424972504654, 0.026575027495346, 0.17342497250465, 0.093241694162018, 0.073424972504649, 0.13287981859411, 0.86712018140589, 0.13287981859411, 0.36712018140589, 0.13287981859411, 0.20045351473923, 0.13287981859411, 0.11712018140589, 0.1328798185941, 0.067120181405897, 0.13287981859411, 0.033786848072561, 0.7027943950545, 0.2972056049455, 0.2027943950545, 0.2972056049455, 0.03612772838783, 0.2972056049455, 0.2027943950545, 0.047205604945496, 0.10279439505451, 0.097205604945492, 0.03612772838783, 0.13053893827884, 0.12820857267382, 0.87179142732618, 0.12820857267382, 0.37179142732618, 0.12820857267382, 0.20512476065952, 0.12820857267382, 0.12179142732618, 0.12820857267383, 0.071791427326173, 0.12820857267382, 0.038458093992849, 0.40052991060082, 0.59947008939918, 0.40052991060082, 0.099470089399183, 0.067196577267481, 0.26613675606585, 0.15052991060082, 0.099470089399183, 0.0005299106008124, 0.19947008939919, 0.067196577267481, 0.099470089399186, 0.51065503486313, 0.48934496513687, 0.010655034863127, 0.48934496513687, 0.1773217015298, 0.15601163180353, 0.010655034863127, 0.23934496513687, 0.11065503486312, 0.089344965136877, 0.010655034863134, 0.15601163180353, 0.44893925670289, 0.55106074329711, 0.44893925670289, 0.051060743297114, 0.11560592336954, 0.21772740996379, 0.19893925670289, 0.051060743297114, 0.048939256702886, 0.15106074329711, 0.11560592336954, 0.051060743297124, 0.20516438432456, 0.79483561567544, 0.20516438432456, 0.29483561567544, 0.20516438432456, 0.12816894900878, 0.20516438432456, 0.044835615675439, 0.0051643843245643, 0.19483561567544, 0.03849771765789, 0.12816894900878, 0.7685046206297, 0.2314953793703, 0.2685046206297, 0.2314953793703, 0.10183795396303, 0.2314953793703, 0.018504620629699, 0.2314953793703, 0.1685046206297, 0.031495379370301, 0.10183795396303, 0.064828712703635, 0.12749043312544, 0.87250956687456, 0.12749043312544, 0.37250956687456, 0.12749043312544, 0.20584290020789, 0.12749043312544, 0.12250956687456, 0.12749043312544, 0.072509566874555, 0.12749043312544, 0.039176233541222, 0.2699702754261, 0.7300297245739, 0.2699702754261, 0.2300297245739, 0.2699702754261, 0.063363057907234, 0.019970275426104, 0.2300297245739, 0.069970275426101, 0.1300297245739, 0.10330360875943, 0.063363057907234, 0.1830700325966, 0.8169299674034, 0.1830700325966, 0.3169299674034, 0.1830700325966, 0.15026330073673, 0.1830700325966, 0.066929967403397, 0.18307003259659, 0.016929967403405, 0.016403365929932, 0.15026330073673, 0.85315005499069, 0.14684994500931, 0.35315005499069, 0.14684994500931, 0.18648338832404, 0.1468499450093, 0.10315005499069, 0.14684994500931, 0.053150054990692, 0.14684994500931, 0.019816721657368, 0.1468499450093, 0.26575963718821, 0.73424036281179, 0.26575963718821, 0.23424036281179, 0.26575963718821, 0.067573696145123, 0.015759637188211, 0.23424036281179, 0.065759637188205, 0.13424036281179, 0.099092970521544, 0.067573696145123, 0.40558879010901, 0.59441120989099, 0.40558879010901, 0.094411209890993, 0.07225545677566, 0.26107787655767, 0.15558879010901, 0.094411209890993, 0.0055887901090159, 0.19441120989098, 0.07225545677566, 0.094411209891007, 0.25641714534767, 0.74358285465233, 0.25641714534767, 0.24358285465233, 0.25641714534767, 0.07691618798566, 0.0064171453476689, 0.24358285465233, 0.056417145347666, 0.14358285465233, 0.089750478681007, 0.07691618798566, 0.80105982120163, 0.19894017879837, 0.30105982120163, 0.19894017879837, 0.13439315453496, 0.19894017879837, 0.051059821201633, 0.19894017879837, 0.0010598212016248, 0.19894017879838, 0.13439315453496, 0.032273512131705, 0.021310069726255, 0.97868993027375, 0.021310069726255, 0.47868993027375, 0.021310069726269, 0.31202326360706, 0.021310069726255, 0.22868993027375, 0.021310069726246, 0.17868993027375, 0.021310069726269, 0.1453565969404, 0.89787851340579, 0.10212148659421, 0.39787851340579, 0.10212148659421, 0.23121184673912, 0.10212148659421, 0.14787851340579, 0.10212148659421, 0.097878513405794, 0.10212148659421, 0.064545180072457, 0.10212148659421, 0.41032876864912, 0.58967123135088, 0.41032876864912, 0.089671231350877, 0.07699543531578, 0.25633789801755, 0.16032876864912, 0.089671231350877, 0.010328768649129, 0.18967123135087, 0.07699543531578, 0.089671231350887, 0.5370092412594, 0.4629907587406, 0.037009241259398, 0.4629907587406, 0.20367590792606, 0.12965742540727, 0.037009241259398, 0.2129907587406, 0.1370092412594, 0.062990758740602, 0.037009241259398, 0.12965742540727, 0.25498086625089, 0.74501913374911, 0.25498086625089, 0.24501913374911, 0.25498086625089, 0.078352467082444, 0.0049808662508894, 0.24501913374911, 0.054980866250889, 0.14501913374911, 0.088314199584223, 0.078352467082444, 0.53994055085221, 0.46005944914779, 0.039940550852208, 0.46005944914779, 0.20660721751887, 0.12672611581447, 0.039940550852208, 0.21005944914779, 0.1399405508522, 0.060059449147798, 0.039940550852198, 0.12672611581447, 0.36614006519321, 0.63385993480679, 0.36614006519321, 0.13385993480679, 0.032806731859864, 0.30052660147347, 0.11614006519321, 0.13385993480679, 0.16614006519319, 0.03385993480681, 0.032806731859864, 0.1338599348068, 0.70630010998138, 0.29369989001862, 0.20630010998138, 0.29369989001862, 0.039633443314737, 0.2936998900186, 0.20630010998138, 0.043699890018615, 0.10630010998138, 0.093699890018615, 0.039633443314737, 0.12703322335193 ];
    //720
    self.g_bins44100 = [ 5, 6, 10, 11, 15, 16, 20, 21, 25, 26, 30, 31, 5, 6, 10, 11, 16, 17, 21, 22, 27, 28, 32, 33, 5, 6, 11, 12, 17, 18, 22, 23, 28, 29, 34, 35, 6, 7, 12, 13, 18, 19, 24, 25, 30, 31, 36, 37, 6, 7, 12, 13, 19, 20, 25, 26, 32, 33, 38, 39, 6, 7, 13, 14, 20, 21, 27, 28, 34, 35, 40, 41, 7, 8, 14, 15, 21, 22, 28, 29, 36, 37, 43, 44, 7, 8, 15, 16, 22, 23, 30, 31, 38, 39, 45, 46, 8, 9, 16, 17, 24, 25, 32, 33, 40, 41, 48, 49, 8, 9, 17, 18, 25, 26, 34, 35, 42, 43, 51, 52, 9, 10, 18, 19, 27, 28, 36, 37, 45, 46, 54, 55, 9, 10, 19, 20, 28, 29, 38, 39, 48, 49, 57, 58, 10, 11, 20, 21, 30, 31, 40, 41, 51, 52, 61, 62, 10, 11, 21, 22, 32, 33, 43, 44, 54, 55, 64, 65, 11, 12, 22, 23, 34, 35, 45, 46, 57, 58, 68, 69, 12, 13, 24, 25, 36, 37, 48, 49, 60, 61, 72, 73, 12, 13, 25, 26, 38, 39, 51, 52, 64, 65, 77, 78, 13, 14, 27, 28, 40, 41, 54, 55, 68, 69, 81, 82, 14, 15, 28, 29, 43, 44, 57, 58, 72, 73, 86, 87, 15, 16, 30, 31, 45, 46, 61, 62, 76, 77, 91, 92, 16, 17, 32, 33, 48, 49, 64, 65, 81, 82, 97, 98, 17, 18, 34, 35, 51, 52, 68, 69, 85, 86, 103, 104, 18, 19, 36, 37, 54, 55, 72, 73, 91, 92, 109, 110, 19, 20, 38, 39, 57, 58, 77, 78, 96, 97, 115, 116, 20, 21, 40, 41, 61, 62, 81, 82, 102, 103, 122, 123, 21, 22, 43, 44, 64, 65, 86, 87, 108, 109, 129, 130, 22, 23, 45, 46, 68, 69, 91, 92, 114, 115, 137, 138, 24, 25, 48, 49, 72, 73, 97, 98, 121, 122, 145, 146, 25, 26, 51, 52, 77, 78, 102, 103, 128, 129, 154, 155, 27, 28, 54, 55, 81, 82, 109, 110, 136, 137, 163, 164, 28, 29, 57, 58, 86, 87, 115, 116, 144, 145, 173, 174, 30, 31, 61, 62, 91, 92, 122, 123, 153, 154, 183, 184, 32, 33, 64, 65, 97, 98, 129, 130, 162, 163, 194, 195, 34, 35, 68, 69, 103, 104, 137, 138, 171, 172, 206, 207, 36, 37, 72, 73, 109, 110, 145, 146, 182, 183, 218, 219, 38, 39, 77, 78, 115, 116, 154, 155, 192, 193, 231, 232, 40, 41, 81, 82, 122, 123, 163, 164, 204, 205, 245, 246, 43, 44, 86, 87, 129, 130, 173, 174, 216, 217, 259, 260, 45, 46, 91, 92, 137, 138, 183, 184, 229, 230, 275, 276, 48, 49, 97, 98, 145, 146, 194, 195, 242, 243, 291, 292, 51, 52, 102, 103, 154, 155, 205, 206, 257, 258, 308, 309, 54, 55, 109, 110, 163, 164, 218, 219, 272, 273, 327, 328, 57, 58, 115, 116, 173, 174, 231, 232, 288, 289, 346, 347, 61, 62, 122, 123, 183, 184, 244, 245, 306, 307, 367, 368, 64, 65, 129, 130, 194, 195, 259, 260, 324, 325, 389, 390, 68, 69, 137, 138, 206, 207, 274, 275, 343, 344, 412, 413, 72, 73, 145, 146, 218, 219, 291, 292, 364, 365, 436, 437, 77, 78, 154, 155, 231, 232, 308, 309, 385, 386, 462, 463, 81, 82, 163, 164, 245, 246, 326, 327, 408, 409, 490, 491, 86, 87, 173, 174, 259, 260, 346, 347, 432, 433, 519, 520, 91, 92, 183, 184, 275, 276, 366, 367, 458, 459, 550, 551, 97, 98, 194, 195, 291, 292, 388, 389, 485, 486, 583, 584, 102, 103, 205, 206, 308, 309, 411, 412, 514, 515, 617, 618, 109, 110, 218, 219, 327, 328, 436, 437, 545, 546, 654, 655, 115, 116, 231, 232, 346, 347, 462, 463, 577, 578, 693, 694, 122, 123, 244, 245, 367, 368, 489, 490, 612, 613, 734, 735, 129, 130, 259, 260, 389, 390, 518, 519, 648, 649, 778, 779, 137, 138, 274, 275, 412, 413, 549, 550, 687, 688, 824, 825, 145, 146, 291, 292, 436, 437, 582, 583, 728, 729, 873, 874, 154, 155, 308, 309, 462, 463, 617, 618, 771, 772, 925, 926 ];
    
    //4096 FFT at 48000 SR
    //[720]
    self.g_weights48000 = [ 0.30666666666667, 0.69333333333333, 0.30666666666667, 0.19333333333333, 0.30666666666667, 0.026666666666667, 0.056666666666667, 0.19333333333333, 0.10666666666667, 0.093333333333333, 0.14, 0.026666666666667, 0.027586543807041, 0.97241345619296, 0.027586543807041, 0.47241345619296, 0.02758654380704, 0.30574678952629, 0.027586543807041, 0.22241345619296, 0.027586543807041, 0.17241345619296, 0.02758654380704, 0.13908012285963, 0.73191145326801, 0.26808854673199, 0.23191145326801, 0.26808854673199, 0.065244786601342, 0.26808854673199, 0.23191145326801, 0.018088546731992, 0.13191145326801, 0.068088546731992, 0.065244786601342, 0.10142188006533, 0.41865460692056, 0.58134539307944, 0.41865460692056, 0.081345393079437, 0.08532127358723, 0.2480120597461, 0.16865460692056, 0.081345393079437, 0.018654606920562, 0.18134539307944, 0.08532127358723, 0.081345393079437, 0.086770539160062, 0.91322946083994, 0.086770539160062, 0.41322946083994, 0.086770539160063, 0.24656279417327, 0.086770539160062, 0.16322946083994, 0.086770539160062, 0.11322946083994, 0.086770539160063, 0.079896127506604, 0.73515161776197, 0.26484838223803, 0.23515161776197, 0.26484838223803, 0.068484951095304, 0.26484838223803, 0.23515161776197, 0.014848382238029, 0.13515161776197, 0.064848382238029, 0.068484951095304, 0.098181715571363, 0.36262434726227, 0.63737565273773, 0.36262434726227, 0.13737565273773, 0.02929101392894, 0.30404231940439, 0.11262434726227, 0.13737565273773, 0.16262434726227, 0.037375652737727, 0.02929101392894, 0.13737565273773, 0.96794545252544, 0.032054547474559, 0.46794545252544, 0.032054547474559, 0.30127878585877, 0.03205454747456, 0.21794545252544, 0.032054547474559, 0.16794545252544, 0.03205454747456, 0.13461211919211, 0.03205454747456, 0.54979772942925, 0.45020227057075, 0.049797729429249, 0.45020227057075, 0.21646439609592, 0.11686893723742, 0.049797729429249, 0.20020227057075, 0.14979772942925, 0.05020227057075, 0.049797729429249, 0.11686893723742, 0.10678564881847, 0.89321435118153, 0.10678564881847, 0.39321435118153, 0.10678564881847, 0.22654768451487, 0.10678564881847, 0.14321435118153, 0.10678564881847, 0.093214351181534, 0.10678564881847, 0.059881017848201, 0.63743069905602, 0.36256930094398, 0.13743069905602, 0.36256930094398, 0.30409736572268, 0.029235967610653, 0.13743069905602, 0.11256930094398, 0.037430699056014, 0.16256930094399, 0.13743069905601, 0.029235967610653, 0.14016645162784, 0.85983354837216, 0.14016645162784, 0.35983354837216, 0.14016645162784, 0.1931668817055, 0.14016645162784, 0.10983354837216, 0.14016645162784, 0.059833548372163, 0.14016645162784, 0.02650021503883, 0.61333333333333, 0.38666666666667, 0.11333333333333, 0.38666666666667, 0.28, 0.053333333333333, 0.11333333333333, 0.13666666666667, 0.013333333333334, 0.18666666666667, 0.11333333333333, 0.053333333333333, 0.055173087614081, 0.94482691238592, 0.055173087614081, 0.44482691238592, 0.055173087614081, 0.27816024571925, 0.055173087614081, 0.19482691238592, 0.055173087614082, 0.14482691238592, 0.055173087614081, 0.11149357905259, 0.46382290653602, 0.53617709346398, 0.46382290653602, 0.036177093463982, 0.13048957320268, 0.20284376013065, 0.21382290653602, 0.036177093463982, 0.063822906536019, 0.13617709346398, 0.13048957320268, 0.036177093463982, 0.83730921384113, 0.16269078615887, 0.33730921384113, 0.16269078615887, 0.17064254717446, 0.16269078615887, 0.087309213841126, 0.16269078615887, 0.037309213841124, 0.16269078615888, 0.0039758805077928, 0.16269078615887, 0.17354107832012, 0.82645892167988, 0.17354107832012, 0.32645892167988, 0.17354107832013, 0.15979225501321, 0.17354107832012, 0.076458921679876, 0.17354107832012, 0.026458921679875, 0.0068744116534584, 0.15979225501321, 0.47030323552394, 0.52969676447606, 0.47030323552394, 0.029696764476057, 0.13696990219061, 0.19636343114272, 0.22030323552394, 0.029696764476057, 0.070303235523944, 0.12969676447606, 0.13696990219061, 0.029696764476057, 0.72524869452455, 0.27475130547545, 0.22524869452455, 0.27475130547545, 0.058582027857881, 0.27475130547545, 0.22524869452455, 0.024751305475453, 0.12524869452455, 0.074751305475453, 0.058582027857881, 0.10808463880879, 0.93589090505088, 0.064109094949119, 0.43589090505088, 0.064109094949119, 0.26922423838421, 0.06410909494912, 0.18589090505088, 0.064109094949119, 0.13589090505088, 0.06410909494912, 0.10255757171755, 0.06410909494912, 0.0995954588585, 0.9004045411415, 0.0995954588585, 0.4004045411415, 0.0995954588585, 0.23373787447483, 0.0995954588585, 0.1504045411415, 0.099595458858502, 0.1004045411415, 0.0995954588585, 0.067071207808167, 0.21357129763693, 0.78642870236307, 0.21357129763693, 0.28642870236307, 0.21357129763693, 0.1197620356964, 0.21357129763693, 0.036428702363068, 0.013571297636932, 0.18642870236307, 0.046904630970265, 0.1197620356964, 0.27486139811203, 0.72513860188797, 0.27486139811203, 0.22513860188797, 0.27486139811203, 0.058471935221306, 0.02486139811203, 0.22513860188797, 0.074861398112029, 0.12513860188797, 0.10819473144536, 0.058471935221306, 0.28033290325568, 0.71966709674432, 0.28033290325568, 0.21966709674432, 0.28033290325568, 0.053000430077657, 0.030332903255676, 0.21966709674432, 0.080332903255675, 0.11966709674433, 0.11366623658901, 0.053000430077657, 0.22666666666667, 0.77333333333333, 0.22666666666667, 0.27333333333333, 0.22666666666667, 0.10666666666667, 0.22666666666667, 0.023333333333333, 0.026666666666668, 0.17333333333333, 0.06, 0.10666666666667, 0.11034617522816, 0.88965382477184, 0.11034617522816, 0.38965382477184, 0.11034617522816, 0.22298715810517, 0.11034617522816, 0.13965382477184, 0.11034617522816, 0.089653824771835, 0.11034617522816, 0.056320491438505, 0.92764581307204, 0.072354186927964, 0.42764581307204, 0.072354186927964, 0.26097914640537, 0.072354186927965, 0.17764581307204, 0.072354186927964, 0.12764581307204, 0.072354186927961, 0.094312479738702, 0.072354186927965, 0.67461842768225, 0.32538157231775, 0.17461842768225, 0.32538157231775, 0.0079517610155856, 0.32538157231775, 0.17461842768225, 0.075381572317749, 0.074618427682248, 0.12538157231775, 0.0079517610155856, 0.15871490565108, 0.34708215664025, 0.65291784335975, 0.34708215664025, 0.15291784335975, 0.013748823306917, 0.31958451002642, 0.097082156640248, 0.15291784335975, 0.14708215664025, 0.052917843359751, 0.013748823306917, 0.15291784335975, 0.94060647104789, 0.059393528952114, 0.44060647104789, 0.059393528952114, 0.27393980438122, 0.059393528952114, 0.19060647104789, 0.059393528952114, 0.14060647104789, 0.059393528952111, 0.10727313771455, 0.059393528952114, 0.45049738904909, 0.54950261095091, 0.45049738904909, 0.049502610950906, 0.11716405571576, 0.21616927761757, 0.20049738904909, 0.049502610950906, 0.050497389049093, 0.14950261095091, 0.11716405571576, 0.049502610950905, 0.87178181010177, 0.12821818989823, 0.37178181010177, 0.12821818989823, 0.2051151434351, 0.12821818989823, 0.12178181010177, 0.12821818989823, 0.071781810101766, 0.12821818989823, 0.038448476768437, 0.12821818989823, 0.199190917717, 0.800809082283, 0.199190917717, 0.300809082283, 0.199190917717, 0.13414241561633, 0.199190917717, 0.050809082282999, 0.199190917717, 0.00080908228299563, 0.032524251050333, 0.13414241561633, 0.42714259527386, 0.57285740472614, 0.42714259527386, 0.072857404726136, 0.093809261940531, 0.2395240713928, 0.17714259527386, 0.072857404726136, 0.027142595273864, 0.17285740472614, 0.093809261940531, 0.072857404726136, 0.54972279622406, 0.45027720377594, 0.04972279622406, 0.45027720377594, 0.21638946289073, 0.1169438704426, 0.04972279622406, 0.20027720377594, 0.14972279622406, 0.050277203775937, 0.049722796224065, 0.1169438704426, 0.56066580651135, 0.43933419348865, 0.060665806511352, 0.43933419348865, 0.22733247317802, 0.10600086015531, 0.060665806511352, 0.18933419348865, 0.16066580651135, 0.039334193488651, 0.060665806511352, 0.10600086015531, 0.45333333333333, 0.54666666666667, 0.45333333333333, 0.046666666666667, 0.12, 0.21333333333333, 0.20333333333333, 0.046666666666667, 0.053333333333336, 0.14666666666666, 0.12, 0.046666666666667, 0.22069235045632, 0.77930764954368, 0.22069235045632, 0.27930764954368, 0.22069235045632, 0.11264098287701, 0.22069235045632, 0.029307649543675, 0.020692350456329, 0.17930764954367, 0.054025683789656, 0.11264098287701, 0.85529162614407, 0.14470837385593, 0.35529162614407, 0.14470837385593, 0.1886249594774, 0.14470837385593, 0.10529162614407, 0.14470837385593, 0.055291626144077, 0.14470837385592, 0.021958292810737, 0.14470837385593, 0.3492368553645, 0.6507631446355, 0.3492368553645, 0.1507631446355, 0.015903522031171, 0.31742981130216, 0.099236855364502, 0.1507631446355, 0.1492368553645, 0.050763144635505, 0.015903522031171, 0.1507631446355, 0.6941643132805, 0.3058356867195, 0.1941643132805, 0.3058356867195, 0.027497646613834, 0.3058356867195, 0.1941643132805, 0.055835686719504, 0.094164313280498, 0.1058356867195, 0.027497646613834, 0.13916902005283, 0.88121294209577, 0.11878705790423, 0.38121294209577, 0.11878705790423, 0.21454627542911, 0.11878705790423, 0.13121294209577, 0.11878705790423, 0.081212942095777, 0.11878705790422, 0.047879608762438, 0.11878705790423, 0.90099477809819, 0.099005221901812, 0.40099477809819, 0.099005221901812, 0.23432811143152, 0.09900522190181, 0.15099477809819, 0.099005221901812, 0.10099477809819, 0.099005221901814, 0.067661444764857, 0.09900522190181, 0.74356362020353, 0.25643637979647, 0.24356362020353, 0.25643637979647, 0.076896953536874, 0.25643637979646, 0.24356362020353, 0.0064363797964688, 0.14356362020353, 0.056436379796469, 0.076896953536874, 0.089769713129793, 0.398381835434, 0.601618164566, 0.398381835434, 0.101618164566, 0.065048502100666, 0.26828483123267, 0.148381835434, 0.101618164566, 0.19838183543401, 0.0016181645659913, 0.065048502100666, 0.101618164566, 0.85428519054773, 0.14571480945227, 0.35428519054773, 0.14571480945227, 0.18761852388106, 0.14571480945227, 0.10428519054773, 0.14571480945227, 0.054285190547728, 0.14571480945227, 0.020951857214394, 0.14571480945227, 0.09944559244812, 0.90055440755188, 0.09944559244812, 0.40055440755188, 0.09944559244813, 0.2338877408852, 0.09944559244812, 0.15055440755188, 0.099445592448126, 0.10055440755187, 0.09944559244813, 0.067221074218537, 0.1213316130227, 0.8786683869773, 0.1213316130227, 0.3786683869773, 0.1213316130227, 0.21200172031063, 0.1213316130227, 0.1286683869773, 0.1213316130227, 0.078668386977301, 0.1213316130227, 0.045335053643962, 0.90666666666667, 0.093333333333334, 0.40666666666667, 0.093333333333334, 0.24, 0.093333333333334, 0.15666666666667, 0.093333333333334, 0.10666666666667, 0.093333333333328, 0.073333333333333, 0.093333333333334, 0.44138470091265, 0.55861529908735, 0.44138470091265, 0.05861529908735, 0.10805136757931, 0.22528196575402, 0.19138470091265, 0.05861529908735, 0.041384700912658, 0.15861529908734, 0.10805136757931, 0.058615299087355, 0.71058325228817, 0.28941674771183, 0.21058325228817, 0.28941674771183, 0.043916585621503, 0.28941674771183, 0.21058325228817, 0.039416747711826, 0.11058325228817, 0.089416747711834, 0.043916585621503, 0.12275008104516, 0.698473710729, 0.301526289271, 0.198473710729, 0.301526289271, 0.031807044062343, 0.30152628927099, 0.198473710729, 0.051526289270996, 0.09847371072899, 0.10152628927101, 0.031807044062343, 0.13485962260432, 0.38832862656099, 0.61167137343901, 0.38832862656099, 0.11167137343901, 0.054995293227667, 0.27833804010567, 0.13832862656099, 0.11167137343901, 0.188328626561, 0.011671373439003, 0.054995293227667, 0.111671373439, 0.76242588419157, 0.23757411580843, 0.26242588419157, 0.23757411580843, 0.095759217524896, 0.23757411580844, 0.012425884191572, 0.23757411580843, 0.16242588419157, 0.037574115808434, 0.095759217524896, 0.070907449141771, 0.80198955619638, 0.19801044380362, 0.30198955619638, 0.19801044380362, 0.13532288952971, 0.19801044380362, 0.051989556196375, 0.19801044380362, 0.0019895561963722, 0.19801044380363, 0.13532288952971, 0.031343777136954, 0.48712724040706, 0.51287275959294, 0.48712724040706, 0.012872759592938, 0.15379390707375, 0.17953942625959, 0.23712724040706, 0.012872759592938, 0.087127240407062, 0.11287275959294, 0.15379390707375, 0.012872759592919, 0.796763670868, 0.203236329132, 0.296763670868, 0.203236329132, 0.13009700420133, 0.203236329132, 0.046763670868003, 0.203236329132, 0.19676367086802, 0.0032363291319825, 0.13009700420133, 0.036569662465335, 0.70857038109546, 0.29142961890454, 0.20857038109546, 0.29142961890454, 0.041903714428789, 0.29142961890454, 0.20857038109546, 0.041429618904544, 0.10857038109546, 0.091429618904544, 0.041903714428789, 0.12476295223788, 0.19889118489624, 0.80110881510376, 0.19889118489624, 0.30110881510376, 0.19889118489626, 0.13444214843707, 0.19889118489624, 0.05110881510376, 0.19889118489625, 0.0011088151037484, 0.032224518229593, 0.13444214843707, 0.24266322604541, 0.75733677395459, 0.24266322604541, 0.25733677395459, 0.24266322604541, 0.090670107287925, 0.24266322604541, 0.0073367739545915, 0.042663226045397, 0.1573367739546, 0.075996559378742, 0.090670107287925 ];
    //[720]
    self.g_bins48000 = [ 4, 5, 9, 10, 14, 15, 18, 19, 23, 24, 28, 29, 4, 5, 9, 10, 14, 15, 19, 20, 24, 25, 29, 30, 5, 6, 10, 11, 15, 16, 21, 22, 26, 27, 31, 32, 5, 6, 11, 12, 16, 17, 22, 23, 27, 28, 33, 34, 5, 6, 11, 12, 17, 18, 23, 24, 29, 30, 35, 36, 6, 7, 12, 13, 18, 19, 25, 26, 31, 32, 37, 38, 6, 7, 13, 14, 19, 20, 26, 27, 33, 34, 39, 40, 7, 8, 14, 15, 21, 22, 28, 29, 35, 36, 42, 43, 7, 8, 14, 15, 22, 23, 29, 30, 37, 38, 44, 45, 7, 8, 15, 16, 23, 24, 31, 32, 39, 40, 47, 48, 8, 9, 16, 17, 25, 26, 33, 34, 41, 42, 50, 51, 8, 9, 17, 18, 26, 27, 35, 36, 44, 45, 53, 54, 9, 10, 18, 19, 28, 29, 37, 38, 46, 47, 56, 57, 9, 10, 19, 20, 29, 30, 39, 40, 49, 50, 59, 60, 10, 11, 21, 22, 31, 32, 42, 43, 52, 53, 63, 64, 11, 12, 22, 23, 33, 34, 44, 45, 55, 56, 66, 67, 11, 12, 23, 24, 35, 36, 47, 48, 59, 60, 70, 71, 12, 13, 25, 26, 37, 38, 50, 51, 62, 63, 75, 76, 13, 14, 26, 27, 39, 40, 53, 54, 66, 67, 79, 80, 14, 15, 28, 29, 42, 43, 56, 57, 70, 71, 84, 85, 14, 15, 29, 30, 44, 45, 59, 60, 74, 75, 89, 90, 15, 16, 31, 32, 47, 48, 63, 64, 78, 79, 94, 95, 16, 17, 33, 34, 50, 51, 66, 67, 83, 84, 100, 101, 17, 18, 35, 36, 53, 54, 70, 71, 88, 89, 106, 107, 18, 19, 37, 38, 56, 57, 75, 76, 93, 94, 112, 113, 19, 20, 39, 40, 59, 60, 79, 80, 99, 100, 119, 120, 21, 22, 42, 43, 63, 64, 84, 85, 105, 106, 126, 127, 22, 23, 44, 45, 66, 67, 89, 90, 111, 112, 133, 134, 23, 24, 47, 48, 70, 71, 94, 95, 118, 119, 141, 142, 25, 26, 50, 51, 75, 76, 100, 101, 125, 126, 150, 151, 26, 27, 53, 54, 79, 80, 106, 107, 132, 133, 159, 160, 28, 29, 56, 57, 84, 85, 112, 113, 140, 141, 168, 169, 29, 30, 59, 60, 89, 90, 119, 120, 149, 150, 178, 179, 31, 32, 63, 64, 94, 95, 126, 127, 157, 158, 189, 190, 33, 34, 66, 67, 100, 101, 133, 134, 167, 168, 200, 201, 35, 36, 70, 71, 106, 107, 141, 142, 177, 178, 212, 213, 37, 38, 75, 76, 112, 113, 150, 151, 187, 188, 225, 226, 39, 40, 79, 80, 119, 120, 159, 160, 198, 199, 238, 239, 42, 43, 84, 85, 126, 127, 168, 169, 210, 211, 252, 253, 44, 45, 89, 90, 133, 134, 178, 179, 223, 224, 267, 268, 47, 48, 94, 95, 141, 142, 189, 190, 236, 237, 283, 284, 50, 51, 100, 101, 150, 151, 200, 201, 250, 251, 300, 301, 53, 54, 106, 107, 159, 160, 212, 213, 265, 266, 318, 319, 56, 57, 112, 113, 168, 169, 225, 226, 281, 282, 337, 338, 59, 60, 119, 120, 178, 179, 238, 239, 298, 299, 357, 358, 63, 64, 126, 127, 189, 190, 252, 253, 315, 316, 378, 379, 66, 67, 133, 134, 200, 201, 267, 268, 334, 335, 401, 402, 70, 71, 141, 142, 212, 213, 283, 284, 354, 355, 425, 426, 75, 76, 150, 151, 225, 226, 300, 301, 375, 376, 450, 451, 79, 80, 159, 160, 238, 239, 318, 319, 397, 398, 477, 478, 84, 85, 168, 169, 252, 253, 337, 338, 421, 422, 505, 506, 89, 90, 178, 179, 267, 268, 357, 358, 446, 447, 535, 536, 94, 95, 189, 190, 283, 284, 378, 379, 473, 474, 567, 568, 100, 101, 200, 201, 300, 301, 400, 401, 501, 502, 601, 602, 106, 107, 212, 213, 318, 319, 424, 425, 530, 531, 637, 638, 112, 113, 225, 226, 337, 338, 450, 451, 562, 563, 675, 676, 119, 120, 238, 239, 357, 358, 476, 477, 596, 597, 715, 716, 126, 127, 252, 253, 378, 379, 505, 506, 631, 632, 757, 758, 133, 134, 267, 268, 401, 402, 535, 536, 669, 670, 802, 803, 141, 142, 283, 284, 425, 426, 567, 568, 708, 709, 850, 851 ];
   
    //major chord, minor chord, not worrying about 7ths, 9ths, sus 4, sus 2 et al
    self.g_diatonicmajor = [ 10.0, 0.0, 0.0, 0.0,  9, 0.0, 0.0, 8,  0.0, 0.0, 0.0, 0.0];
    self.g_diatonicminor = [ 10.0, 0.0, 0.0, 9,  0.0, 0.0, 0.0, 8,  0, 0.0, 0.0, 0.0];
    
    //[3] //[7]
    self.g_minor = [0,3,7]; //[0,2,3,5,7,8,11];
    self.g_major = [0,4,7]; //[0,2,4,5,7,9,11];
   

self.setup = function(sampleRate) {
	var i;
    
    self.m_srate = sampleRate;
    
	//if sample rate is 88200 or 96000, assume taking double size FFT to start with
	if(self.m_srate >= (44100*2)) {
        
        //presume double size function withfft(powers){}
        self.stft = new MMLLSTFT(8192,4096,0);
        
        self.m_srate = self.m_srate/2;
    } else {
        
        self.stft = new MMLLSTFT(4096,2048,0);
        
    }
    
    
	if(self.m_srate==44100)
	{
		self.m_weights = self.g_weights44100;
		self.m_bins = self.g_bins44100;
		self.m_frameperiod = 0.046439909297052;
	}
	else  //else 48000; potentially dangerous if it isn't! Fortunately, shouldn't write any data to unknown memory
	{
		self.m_weights = self.g_weights48000;
		self.m_bins = self.g_bins48000;
		self.m_frameperiod = 0.042666666666667;
	}
    
    
    self.numpreviousframes = 10;
    self.halfnumpreviousframes = Math.floor(self.numpreviousframes/2);
    
    self.lower = Math.floor(self.numpreviousframes/2);
    self.upper = Math.floor(self.numpreviousframes/2);
    
    //even
    if(self.numpreviousframes%2==0) {
        
        self.upper = self.upper-1;
        
    }
    
    self.previousfftdata = new Array(1024*self.numpreviousframes);
    self.previousfftdatapointer = 0;
    
    for(i=0; i<(1024*self.numpreviousframes); ++i)
        self.previousfftdata[i] = 0;
    
    
    self.chroma = new Array(12);
    self.m_key = new Array(24);
    self.m_histogram = new Array(24);
    
	//zero chroma
    for(i=0; i<12; ++i)
        self.chroma[i] = 0;
    
    for(i=0; i<24; ++i) {
        self.m_key[i] = 0;
        self.m_histogram[i] = 0;
    }
    
	self.chord = -1; //starts with unknown chord

    self.keydecay = keydecay;
    self.chromaleak = chromaleak;
    
}

    self.setup(sampleRate);

//must pass in fft data (power spectrum)
self.next = function(input) {

    var i,j;
 
    var ready = self.stft.next(input);
    
    if(ready) {
    
	var sum;
	var indexbase, index;
	//experimental; added leaky integration on each note; also, only add to sum if harmonic, i.e., not a transient
    
	var weights = self.m_weights;
	var bins = self.m_bins;
        
    var fftbuf = self.stft.powers;
    
    //update fftbuf based on tonal vs percussive, zero out bin energy of percussive (e.g. more vertical)
    //bins only dealt with below 1024 anyway, so no need to go higher in checks
 
    var previousfftdataoffset = self.previousfftdatapointer * 1024;
    
    var vertical = 0;
    var horizontal = 0;
    
    for (i=self.halfnumpreviousframes; i<1024; ++i) {
        
        self.previousfftdata[previousfftdataoffset+i] = fftbuf[i];
    
        horizontal = 0;
        
        for (j=0; j<self.numpreviousframes; ++j) {
            
            horizontal += self.previousfftdata[j*1024+i];
            
        }
        
        vertical = 0;
        
        for (j=(i-self.lower); j<=(i+self.upper); ++j) {
            
            vertical += fftbuf[j];
            
        }
        
        if(vertical>horizontal) {
            
            fftbuf[i] = 0;
            
        }
        
    }
    
    self.previousfftdatapointer = (self.previousfftdatapointer+1)%self.numpreviousframes;

	//update for new round; leaky integration
	for (i=0;i<12;++i)
		self.chroma[i] *= self.chromaleak;
    
	for (i=0;i<60;++i) {
		var chromaindex = (i+9)%12; //starts at A1 up to G#6
        
		sum = 0.0;
        
		indexbase = 12*i; //6 partials, 2 of each
        
		for(j=0;j<12;++j) { //12 if 144 data points
            
			index=indexbase+j;
            
			sum+= (weights[index])* (fftbuf[bins[index]]);
		}
        
        self.chroma[chromaindex]+= sum;
	}
    
	var key = self.m_key;
    
	//major
	for (i=0;i<12;++i) {
        
		sum = 0.0;
        
		for (j=0;j<3;++j) {
			indexbase = self.g_major[j];
            
			index = (i+indexbase)%12;
			//sum+=(chroma[index]*g_kkmajor[indexbase]);
            
			sum += self.chroma[index] * self.g_diatonicmajor[indexbase];
            
		}
        
		key[i] = sum; //10*log10(sum+1);
	}
    
	//minor
	for (i=0;i<12;++i) {
        
		sum = 0.0;
        
		for (j=0;j<3;++j) {
			
            indexbase = self.g_minor[j];
            
			index = (i+indexbase)%12;
			//sum+=(chroma[index]*g_kkminor[indexbase]);
            
			sum += self.chroma[index]*self.g_diatonicminor[indexbase];
            
		}
        
		key[12+i] = sum;
	}
 
	//keyleak in seconds, convert to drop time in FFT hop frames (FRAMEPERIOD)
    var testmax = self.keydecay/self.m_frameperiod;
	
    var keyleak = testmax>0.001 ? testmax : 0.001; //FRAMEPERIOD;
    
	//now number of frames, actual leak param is decay exponent to reach 0.01 in x seconds, ie 0.01 = leakparam ** (x/ffthopsize)
	//0.01 is -40dB
	keyleak = Math.pow(0.01,(1/keyleak));
    
	var histogram = self.m_histogram;
    
	var bestchord = 0;
	var bestscore = 0;
    
	for (i=0;i<24;++i) {
		histogram[i] = (keyleak*histogram[i])+key[i];
        
		if(histogram[i]>bestscore) {
			bestscore = histogram[i];
			bestchord = i;
		}
        
        //printf("%f ",histogram[i]);
	}
    
	//should find secondbest and only swap if win by a margin
    
	//printf(" best %d \n\n",bestkey);
	//what is winning currently? find max in histogram
    
	self.chord = bestchord;
    
    //return self.m_currentKey;
    
    }
    
    return self.chord;
    
  }


}


