A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1734 lines 63 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2004 Matthias Wientapper, 2014-2015 Thomas Orgis 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 * TODO: 21 * - Think about generating the sounds on startup with SWCODEC. 22 ****************************************************************************/ 23#include "plugin.h" 24#include "lib/pluginlib_actions.h" 25#include "lib/pluginlib_exit.h" 26#include "fixedpoint.h" 27 28/* About time resolution: 29 1000 means 1 ms resolution. It should get better with higher values 30 in theory, but in practice, too small timer intervals increase the 31 chance of being missed and make the metronome lag behind. Mean tempo 32 still works out with very small divider values (29 even) as long as 33 the rounding error compensation is active, although beat intervals 34 become jerky. You compromise between long-term accuracy and steadyness 35 from one beat to the next. 36 37 A drift you have to accept comes just from the audio clock itself, or even 38 from the difference between clocks in the device. The Sansa Clip+ has around 39 0.04 % error in audio frequency using the "good" PLLB. I presume that the 40 difference between timing using PLLA and PLLB is at least that big. Something 41 up to 40 ms time difference over one minute when comparing to an external 42 reference or just the metronome plugin with playback of a prepared PCM track 43 is to be expected. 44 45 Also, since playback on SWCODEC is not allowed to happen inside the timer 46 callback, there is a delay introduced by the main loop scheduling. This 47 could be compensated for by delaying the audio depending on a counter 48 incremented since the period elapsed in the callback, at the price of 49 putting the display out of sync. On a Clip+, the schedule delay isn't 50 biggest problem (drift for fine timer resolution is). 51 52 All in all, 1 ms is too small, 2 ms seems to work fine ... 53 4 ms might still be cool, too. 54*/ 55#if defined(SIMULATOR) 56/* Simulator really wants 1024. Not 1000, not 512, only 1024. 57 Otherwise it is strangely slow. */ 58static const unsigned int timerfreq_div = 1024; 59#else 60static const unsigned int timerfreq_div = 500; /* 2 ms resolution */ 61#endif 62/* actual (not quarter) beats per minute above which display blinking 63 is deactivated (since it is not needed anymore and because of performance 64 issues) */ 65static const unsigned int blinklimit = 135; 66 67enum metronome_errors 68{ 69 MERR_NOTHING = 0 70, MERR_MISSING 71, MERR_OOM 72, MERR_TEMPO 73, MERR_METER 74, MERR_VOLUME 75, MERR_PATTERN 76}; 77 78#define PART_MAX 10 /* maximum count of programmed parts */ 79 80#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) \ 81 || (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) 82#define MET_SYNC 83#endif 84 85#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \ 86 || (CONFIG_KEYPAD == IPOD_3G_PAD) \ 87 || (CONFIG_KEYPAD == IPOD_4G_PAD) 88#define METRONOME_QUIT PLA_UP 89#else 90#define METRONOME_QUIT PLA_EXIT 91#endif 92 93#ifdef HAVE_SCROLLWHEEL 94#define METRONOME_VOL_UP PLA_SCROLL_FWD 95#define METRONOME_VOL_UP_REP PLA_SCROLL_FWD_REPEAT 96#define METRONOME_VOL_DOWN PLA_SCROLL_BACK 97#define METRONOME_VOL_DOWN_REP PLA_SCROLL_BACK_REPEAT 98#else 99#define METRONOME_VOL_UP PLA_UP 100#define METRONOME_VOL_DOWN PLA_DOWN 101#define METRONOME_VOL_UP_REP PLA_UP_REPEAT 102#define METRONOME_VOL_DOWN_REP PLA_DOWN_REPEAT 103#endif 104#define METRONOME_LEFT PLA_LEFT 105#define METRONOME_RIGHT PLA_RIGHT 106#define METRONOME_LEFT_REP PLA_LEFT_REPEAT 107#define METRONOME_RIGHT_REP PLA_RIGHT_REPEAT 108#define METRONOME_TAP PLA_SELECT_REL 109#define METRONOME_PAUSE PLA_CANCEL 110#define METRONOME_PLAY PLA_SELECT_REPEAT 111 112#define METRONOME_START PLA_SELECT 113 114#ifdef MET_SYNC 115enum{ METRONOME_SYNC = LAST_PLUGINLIB_ACTION+1 }; 116static const struct button_mapping iriver_syncaction[] = 117{ 118 { METRONOME_SYNC, BUTTON_REC, BUTTON_NONE }, 119 LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_PLUGIN) 120}; 121#endif /* IRIVER_H100_PAD||IRIVER_H300_PAD */ 122 123const struct button_mapping *plugin_contexts[] = 124{ 125 pla_main_ctx, 126#if defined(MET_SYNC) 127 iriver_syncaction, 128#endif 129}; 130#define PLA_ARRAY_COUNT sizeof(plugin_contexts)/sizeof(plugin_contexts[0]) 131 132/* raw PCM */ 133static signed short tick_sound[] = 134{ 135 32767,32764,32767,32767,32763,32767,32762,32767,32765,32767,32767 136,32766,32767,32766,32767,32767,32765,32767,32764,32767,32764,32767 137,32763,-32764,-32768,-32766,-32768,-32768,-32767,-32767,-32767,-32765,-32768 138,-32764,-32768,-32768,-32766,-32768,-32764,-32768,-32766,-32767,-32768,-32767 139,-32766,32763,32767,32763,32767,32767,32766,32767,32766,32767,32765 140,32767,32763,32767,32766,32767,32766,32767,32763,32767,32765,32767 141,32767,-32768,-32765,-32768,-32767,-32765,-32767,-32765,-32768,-32764,-32768 142,-32766,-32768,-32768,-32766,-32767,-32768,-32764,-32768,-32764,-32768,-32768 143,-32766,32716,32668,32620,32564,32520,32467,32418,32370,32316,32272 144,32214,32176,32114,32074,32020,31972,31922,31873,31823,31775,31726 145,31676,-31627,-31579,-31530,-31479,-31433,-31383,-31333,-31287,-31236,-31188 146,-31141,-31090,-31042,-30998,-30943,-30899,-30849,-30800,-30757,-30702,-30659 147,-30609,30561,30515,30463,30422,30365,30326,30273,30229,30177,30135 148,30084,30035,29995,29936,29903,29844,29802,29755,29706,29661,29614 149,29565,-29519,-29472,-29426,-29381,-29331,-29288,-29239,-29191,-29149,-29099 150,-29055,-29007,-28962,-28914,-28871,-28821,-28779,-28730,-28685,-28638,-28596 151,-28544,28496,28463,28404,28371,28314,28278,28225,28185,28136,28093 152,28048,28001,27956,27912,27865,27824,27773,27736,27682,27646,27593 153,27555,-27509,-27462,-27418,-27375,-27328,-27286,-27239,-27200,-27145,-27116 154,-27055,-27026,-26972,-26930,-26891,-26838,-26805,-26750,-26716,-26663,-26630 155,-26575,26534,26495,26448,26408,26360,26324,26272,26235,26188,26149 156,26101,26061,26016,25976,25930,25888,25847,25800,25763,25714,25676 157,25632,-25589,-25547,-25505,-25461,-25419,-25376,-25337,-25291,-25251,-25209 158,-25162,-25129,-25078,-25043,-24995,-24960,-24910,-24876,-24830,-24787,-24751 159,-24703,24663,24622,24583,24539,24499,24456,24418,24374,24334,24292 160,24252,24209,24173,24124,24092,24042,24011,23960,23930,23879,23845 161,23803,-23762,-23722,-23680,-23644,-23597,-23562,-23518,-23482,-23437,-23402 162,-23357,-23320,-23281,-23236,-23203,-23158,-23119,-23082,-23040,-23000,-22962 163,-22922,22885,22837,22809,22759,22728,22685,22644,22608,22567,22528 164,22491,22449,22412,22372,22334,22295,22254,22221,22173,22146,22096 165,22066,-22026,-21984,-21947,-21911,-21867,-21836,-21790,-21757,-21719,-21677 166,-21644,-21601,-21567,-21526,-21489,-21454,-21411,-21378,-21337,-21301,-21263 167,-21226,21189,21151,21111,21077,21036,21002,20964,20926,20889,20852 168,20814,20779,20741,20703,20666,20632,20590,20562,20512,20490,20440 169,20416,-20380,-20331,-20303,-20261,-20230,-20188,-20158,-20114,-20085,-20045 170,-20009,-19975,-19935,-19904,-19864,-19829,-19797,-19753,-19726,-19685,-19650 171,-19616,19580,19544,19508,19471,19441,19397,19373,19325,19301,19256 172,19229,19189,19155,19122,19081,19055,19013,18980,18947,18908,18879 173,18840,-18807,-18771,-18739,-18701,-18669,-18634,-18600,-18564,-18531,-18497 174,-18461,-18430,-18392,-18360,-18326,-18291,-18258,-18223,-18191,-18154,-18123 175,-18088,18055,18019,17989,17953,17919,17887,17853,17817,17791,17746 176,17726,17680,17656,17619,17585,17555,17519,17488,17453,17423,17385 177,17359,17320,-17287,-17261,-17220,-17196,-17156,-17128,-17093,-17062,-17029 178,-16996,-16966,-16929,-16901,-16868,-16834,-16804,-16769,-16741,-16705,-16675 179,-16644,-16609,16579,16545,16519,16479,16455,16419,16388,16359,16321 180,16300,16256,16235,16198,16166,16141,16102,16076,16043,16011,15981 181,15950,15920,-15891,-15852,-15832,-15789,-15768,-15732,-15703,-15672,-15642 182,-15609,-15582,-15548,-15521,-15487,-15459,-15426,-15401,-15364,-15339,-15305 183,-15275,-15250,15219,15184,15159,15122,15101,15061,15041,15002,14981 184,14944,14919,14886,14858,14829,14797,14772,14736,14715,14675,14657 185,14617,14598,-14567,-14533,-14506,-14475,-14447,-14419,-14389,-14358,-14334 186,-14299,-14277,-14241,-14218,-14186,-14158,-14131,-14100,-14072,-14046,-14012 187,-13991,-13955,13927,13904,13873,13844,13819,13787,13761,13732,13706 188,13674,13651,13619,13590,13570,13530,13516,13475,13457,13423,13401 189,13368,13345,-13317,-13287,-13260,-13234,-13204,-13178,-13152,-13122,-13098 190,-13068,-13043,-13013,-12990,-12958,-12937,-12902,-12884,-12849,-12829,-12798 191,-12771,-12746,12718,12693,12663,12641,12611,12586,12559,12531,12510 192,12475,12459,12421,12408,12367,12357,12315,12301,12268,12244,12218 193,12194,12164,-12140,-12113,-12093,-12056,-12043,-12008,-11987,-11961,-11931 194,-11911,-11884,-11855,-11836,-11804,-11782,-11757,-11729,-11708,-11679,-11655 195,-11631,-11601,11574,11560,11525,11508,11479,11454,11431,11403,11382 196,11356,11329,11307,11279,11260,11229,11211,11179,11161,11133,11110 197,11085,11061,-11038,-11010,-10991,-10960,-10944,-10913,-10893,-10866,-10845 198,-10818,-10796,-10772,-10747,-10725,-10699,-10676,-10653,-10629,-10605,-10580 199,-10561,-10531,10507,10491,10461,10442,10416,10394,10369,10350,10319 200,10305,10276,10252,10236,10202,10190,10160,10138,10117,10093,10070 201,10050,10020,-9997,-9984,-9953,-9935,-9912,-9885,-9871,-9840,-9823 202,-9799,-9773,-9756,-9730,-9710,-9687,-9664,-9642,-9620,-9598,-9576 203,-9554,-9532,9510,9488,9466,9444,9419,9405,9374,9361,9331 204,9314,9293,9268,9250,9225,9206,9184,9160,9143,9118,9098 205,9077,9053,-9029,-9018,-8988,-8973,-8948,-8928,-8906,-8888,-8862 206,-8848,-8819,-8805,-8780,-8760,-8740,-8720,-8695,-8681,-8653,-8638 207,-8615,-8594,8573,8556,8531,8515,8492,8472,8451,8433,8409 208,8393,8368,8354,8326,8315,8284,8277,8243,8236,8206,8192 209,8170,8151,-8133,-8107,-8095,-8068,-8054,-8030,-8014,-7991,-7975 210,-7953,-7933,-7916,-7894,-7876,-7857,-7836,-7818,-7799,-7778,-7761 211,-7740,-7720,7700,7684,7665,7645,7626,7610,7582,7577,7545 212,7534,7513,7493,7477,7455,7438,7419,7402,7379,7368,7341 213,7328,7307,-7289,-7272,-7250,-7237,-7216,-7196,-7183,-7157,-7146 214,-7123,-7108,-7091,-7065,-7058,-7030,-7020,-6998,-6979,-6965,-6944 215,-6927,-6911,6895,6870,6859,6836,6824,6800,6790,6763,6755 216,6730,6717,6699,6679,6667,6642,6632,6610,6596,6574,6564 217,6539,6529,6507,-6492,-6474,-6457,-6442,-6422,-6406,-6392,-6371 218,-6358,-6338,-6322,-6306,-6291,-6269,-6259,-6237,-6223,-6206,-6190 219,-6172,-6157,-6139,6123,6108,6088,6077,6057,6043,6025,6010 220,5992,5978,5962,5944,5928,5914,5897,5879,5869,5844,5837 221,5816,5799,5789,-5773,-5750,-5742,-5720,-5710,-5687,-5680,-5656 222,-5648,-5627,-5613,-5600,-5581,-5568,-5552,-5534,-5525,-5501,-5496 223,-5470,-5464,-5443,5430,5413,5402,5383,5370,5353,5343,5320 224,5314,5292,5280,5267,5248,5237,5219,5208,5190,5176,5162 225,5148,5131,5121,-5107,-5086,-5077,-5058,-5047,-5030,-5017,-5002 226,-4990,-4971,-4963,-4941,-4935,-4915,-4902,-4892,-4869,-4867,-4841 227,-4836,-4816,-4806,4792,4774,4767,4744,4740,4716,4712,4692 228,4680,4668,4649,4642,4624,4612,4599,4584,4570,4560,4541 229,4535,4513,4508,-4496,-4472,-4467,-4450,-4437,-4427,-4407,-4401 230,-4384,-4372,-4358,-4346,-4331,-4322,-4305,-4294,-4281,-4266,-4257 231,-4240,-4231,-4216,4204,4190,4180,4162,4156,4137,4131,4111 232,4104,4091,4075,4068,4048,4043,4026,4016,4002,3990,3980 233,3962,3957,3938,-3926,-3919,-3904,-3892,-3882,-3866,-3858,-3843 234,-3833,-3820,-3810,-3792,-3789,-3769,-3762,-3751,-3732,-3730,-3710 235,-3704,-3689,-3678,3666,3656,3640,3637,3615,3613,3594,3586 236,3576,3560,3555,3537,3529,3518,3504,3497,3481,3473,3462 237,3447,3441,3425,-3414,-3406,-3394,-3383,-3372,-3359,-3353,-3336 238,-3330,-3316,-3306,-3295,-3287,-3270,-3266,-3251,-3241,-3233,-3218 239,-3210,-3197,-3192,3182,3160,3165,3139,3140,3121,3116,3104 240,3093,3083,3075,3057,3058,3038,3033,3021,3009,3003,2990 241,2981,2969,2960,-2947,-2943,-2928,-2921,-2910,-2898,-2891,-2881 242,-2868,-2863,-2846,-2846,-2826,-2824,-2810,-2800,-2795,-2779,-2774 243,-2763,-2751,-2746,2735,2724,2715,2705,2697,2682,2682,2662 244,2663,2645,2641,2629,2620,2612,2602,2592,2585,2572,2566 245,2557,2544,2540,-2530,-2520,-2508,-2503,-2492,-2482,-2477,-2463 246,-2457,-2447,-2439,-2430,-2419,-2416,-2398,-2399,-2382,-2380,-2365 247,-2364,-2346,-2345,2335,2324,2316,2308,2301,2290,2281,2275 248,2263,2262,2241,2250,2220,2232,2211,2208,2199,2189,2180 249,2177,2161,2163,-2154,-2137,-2138,-2119,-2122,-2102,-2107,-2087 250,-2088,-2073,-2073,-2055,-2057,-2040,-2040,-2027,-2022,-2013,-2005 251,-1997,-1991,-1981,1973,1967,1959,1953,1940,1941,1922,1928 252,1908,1911,1892,1896,1879,1882,1862,1866,1850,1847,1840 253,1829,1827,1815,-1809,-1802,-1797,-1785,-1784,-1770,-1768,-1757 254,-1755,-1742,-1740,-1729,-1724,-1716,-1711,-1701,-1697,-1688,-1682 255,-1676,-1665,-1663,1654,1649,1638,1637,1624,1622,1611,1611 256,1594,1599,1582,1582,1573,1566,1560,1554,1547,1538,1538 257,1523,1524,1512,1509,-1502,-1493,-1491,-1480,-1478,-1469,-1462 258,-1458,-1450,-1444,-1441,-1427,-1431,-1414,-1418,-1405,-1400,-1397 259,-1385,-1388,-1371,-1376,1370,1354,1355,1345,1341,1334,1329 260,1323,1316,1311,1305,1299,1294,1287,1282,1276,1270,1266 261,1255,1258,1244,1244,-1239,-1226,-1231,-1212,-1220,-1205,-1202 262,-1199,-1190,-1186,-1182,-1173,-1171,-1163,-1158,-1156,-1145,-1145 263,-1136,-1131,-1128,-1121,1116,1111,1106,1100,1094,1092,1082 264,1084,1068,1075,1061,1061,1053,1047,1047,1037,1036,1025 265,1027,1016,1017,1007,-1005,-996,-998,-986,-986,-980,-973 266,-973,-962,-962,-956,-949,-949,-939,-938,-931,-929,-920 267,-921,-911,-911,-903,899,896,891,885,880,881,869 268,873,858,863,853,851,847,840,840,829,833,819 269,826,811,815,804,-801,-800,-794,-788,-791,-778,-780 270,-774,-766,-771,-755,-764,-747,-754,-742,-743,-736,-734 271,-728,-727,-718,-720,715,708,708,699,703,687,697 272,681,687,675,679,665,675,657,665,653,654,648 273,646,642,637,634,-629,-629,-621,-623,-614,-615,-607 274,-607,-602,-599,-594,-594,-586,-588,-577,-583,-571,-574 275,-567,-564,-562,-559,557,548,552,541,546,532,542 276,527,531,524,522,521,515,513,509,507,504,500 277,497,495,490,489,-485,-482,-479,-476,-474,-468,-470 278,-462,-462,-458,-455,-454,-449,-447,-443,-442,-437,-437 279,-432,-429,-429,-422,420,419,417,412,411,409,404 280,403,400,397,394,393,388,388,382,384,375,381 281,371,372,369,364,-360,-365,-355,-360,-351,-354,-347 282,-347,-345,-340,-341,-336,-335,-331,-333,-323,-329,-322 283,-319,-321,-314,-316,314,308,308,303,304,300,298 284,297,292,294,288,288,285,281,285,275,279,276 285,270,272,269,264,-260,-267,-257,-261,-256,-254,-254 286,-249,-250,-247,-244,-245,-238,-242,-235,-237,-233,-232 287,-229,-229,-225,-225,222,222,218,218,214,215,211 288,212,206,210,201,206,202,199,199,197,192,197 289,191,188,192,183,-185,-179,-189,-174,-183,-177,-174 290,-178,-169,-174,-168,-169,-167,-165,-165,-161,-162,-158 291,-160,-155,-155,-155,154,149,151,148,147,146,143 292,145,138,144,136,139,136,134,136,129,135,125 293,134,123,130,120,-119,-126,-118,-123,-116,-122,-111 294,-120,-113,-111,-115,-108,-111,-109,-108,-104,-107,-103 295,-106,-99,-104,-94,93,100,95,98,93,97,88 296,96,85,96,84,91,85,84,89,81,84,82 297,79,84,75,82,75,-76,-75,-76,-73,-74,-71 298,-73,-70,-68,-72,-65,-70,-65,-65,-67,-61,-66 299,-62,-60,-62,-61,-57,54,64,52,61,52,57 300,54,54,53,53,50,53,48,53,45,53,43 301,51,45,45,47,42,-41,-45,-43,-40,-44,-39 302,-42,-40,-38,-38,-40,-36,-39,-34,-39,-32,-37 303,-33,-34,-34,-34,-29,28,35,28,32,29,30 304,27,31,27,28,27,26,27,24,30,20,28 305,21,27,20,27,18,-19,-23,-21,-22,-19,-23 306,-16,-24,-15,-23,-15,-21,-16,-17,-20,-14,-19 307,-14,-18,-13,-19,-11,11,18,10,19,8,17 308,13,10,18,5,18,7,16,8,12,11,10 309,10,12,6,14,5,-4,-14,-5,-10,-10,-5 310,-11,-6,-8,-8,-6,-9,-5,-7,-8,-2,-12 311,-1,-8,-6,-4,-7,6,5,4,7,2,6 312,4,3,8,1,4,4,4,3,5,1,5 313,3,1,5,2,3,-1,-5,-2,0,-5,1 314,-6,2,-6,3,-6,1,-5,2,-6,5,-8 315,4,-6,3,-5,3,-2,2,1,0,1,4 316,-5,6,-3,1,3,-2,3,-3,5,-5,5 317,-1,0,0,2,-3,4,-3,0,1,-1,-1 318,2,-2,1,-1,0,1,-1,0,0,0,1 319,-1,1,-2,2,-1,1,0,-3,5,-5,4 320,-1,-2,2,-1,1,0,-1,1,-1,2,-3 321,3,-3 322}; 323static signed short tock_sound[] = 324{ 325 32767,32761,32767,32762,32767,32763,32767,32765,32767,32767,32766 326,32767,32764,32767,32765,32767,32763,32767,32761,32767,32765,32767 327,32766,32767,32766,32767,32767,32764,32767,32763,32767,32767,32766 328,32767,32766,32767,32767,32765,32767,32763,32767,32761,32767,32764 329,32767,-32766,-32768,-32765,-32767,-32768,-32762,-32768,-32762,-32768,-32768 330,-32765,-32768,-32765,-32768,-32766,-32766,-32766,-32766,-32768,-32766,-32768 331,-32766,-32768,-32767,-32768,-32766,-32768,-32767,-32767,-32768,-32763,-32768 332,-32765,-32768,-32768,-32765,-32768,-32767,-32768,-32768,-32767,-32766,-32768 333,-32767,32720,32666,32619,32567,32516,32471,32414,32373,32314,32270 334,32220,32167,32123,32068,32023,31970,31924,31872,31824,31775,31725 335,31678,31625,31581,31527,31482,31431,31383,31334,31286,31238,31185 336,31144,31087,31046,30993,30947,30898,30848,30804,30750,30709,30653 337,30614,-30566,-30509,-30470,-30415,-30371,-30322,-30276,-30226,-30181,-30131 338,-30085,-30039,-29988,-29945,-29894,-29849,-29800,-29756,-29707,-29658,-29617 339,-29562,-29522,-29473,-29425,-29380,-29334,-29283,-29242,-29193,-29145,-29103 340,-29051,-29011,-28959,-28917,-28866,-28827,-28773,-28735,-28682,-28641,-28591 341,-28550,28503,28457,28407,28369,28316,28275,28229,28182,28137,28094 342,28044,28006,27952,27915,27864,27823,27775,27734,27682,27645,27597 343,27550,27513,27455,27426,27368,27333,27284,27240,27197,27152,27105 344,27069,27012,26982,26926,26891,26841,26799,26756,26712,26666,26628 345,26574,-26528,-26502,-26443,-26410,-26362,-26318,-26277,-26233,-26189,-26147 346,-26103,-26059,-26019,-25973,-25931,-25888,-25846,-25801,-25763,-25714,-25675 347,-25633,-25587,-25549,-25502,-25463,-25419,-25378,-25333,-25294,-25249,-25208 348,-25167,-25123,-25084,-25037,-25000,-24954,-24917,-24871,-24832,-24788,-24748 349,-24706,24665,24622,24582,24539,24501,24454,24420,24371,24336,24292 350,24251,24212,24167,24131,24084,24052,24001,23969,23921,23886,23842 351,23804,23760,23724,23678,23644,23598,23561,23521,23478,23440,23401 352,23356,23324,23275,23243,23197,23161,23118,23082,23039,23003,22959 353,22922,-22882,-22844,-22801,-22763,-22729,-22679,-22653,-22601,-22569,-22529 354,-22488,-22453,-22409,-22374,-22331,-22297,-22254,-22220,-22176,-22141,-22100 355,-22064,-22024,-21985,-21947,-21910,-21869,-21833,-21794,-21754,-21721,-21675 356,-21645,-21601,-21566,-21529,-21486,-21455,-21410,-21380,-21335,-21304,-21258 357,-21232,21195,21144,21118,21072,21038,21003,20960,20932,20882,20858 358,20810,20781,20740,20703,20668,20628,20595,20557,20518,20483,20447 359,20409,20374,20336,20299,20265,20225,20194,20150,20123,20079,20047 360,20008,19975,19937,19902,19866,19827,19797,19755,19725,19682,19654 361,19614,-19581,-19540,-19512,-19471,-19437,-19405,-19362,-19335,-19292,-19264 362,-19223,-19194,-19151,-19124,-19082,-19053,-19014,-18980,-18946,-18911,-18876 363,-18842,-18804,-18775,-18735,-18704,-18668,-18634,-18598,-18568,-18527,-18500 364,-18460,-18428,-18394,-18360,-18324,-18295,-18254,-18225,-18190,-18154,-18124 365,-18087,18054,18021,17987,17953,17921,17884,17855,17818,17786,17754 366,17718,17685,17654,17619,17586,17554,17519,17488,17454,17421,17387 367,17358,17319,17295,17251,17230,17186,17164,17123,17096,17061,17028 368,16996,16967,16929,16902,16865,16837,16801,16774,16736,16708,16675 369,16641,16612,-16578,-16549,-16513,-16486,-16449,-16423,-16385,-16361,-16321 370,-16297,-16260,-16233,-16198,-16169,-16137,-16102,-16080,-16038,-16017,-15976 371,-15954,-15914,-15892,-15855,-15826,-15796,-15762,-15735,-15702,-15673,-15638 372,-15617,-15572,-15556,-15515,-15489,-15461,-15424,-15400,-15365,-15338,-15304 373,-15281,-15241,15212,15189,15155,15125,15098,15064,15038,15005,14977 374,14947,14918,14886,14859,14827,14799,14771,14738,14711,14681,14651 375,14623,14592,14565,14532,14508,14474,14449,14416,14391,14357,14334 376,14301,14273,14246,14214,14188,14159,14128,14104,14069,14046,14016 377,13986,13958,-13928,-13905,-13869,-13849,-13816,-13789,-13758,-13736,-13702 378,-13678,-13649,-13616,-13598,-13561,-13539,-13508,-13480,-13455,-13424,-13399 379,-13371,-13341,-13318,-13284,-13263,-13232,-13205,-13179,-13150,-13124,-13096 380,-13069,-13041,-13017,-12984,-12965,-12930,-12908,-12881,-12849,-12831,-12793 381,-12779,-12739,12714,12694,12666,12636,12616,12583,12561,12531,12509 382,12476,12459,12421,12406,12373,12347,12325,12294,12271,12244,12218 383,12194,12164,12142,12112,12091,12062,12038,12009,11989,11956,11939 384,11903,11888,11855,11834,11806,11782,11755,11732,11705,11679,11658 385,11628,11605,-11579,-11557,-11527,-11505,-11480,-11455,-11429,-11406,-11380 386,-11355,-11331,-11305,-11283,-11256,-11231,-11210,-11178,-11166,-11126,-11117 387,-11080,-11063,-11037,-11010,-10992,-10961,-10940,-10916,-10890,-10871,-10838 388,-10825,-10791,-10774,-10747,-10724,-10699,-10679,-10648,-10634,-10600,-10586 389,-10554,-10537,10513,10485,10466,10438,10420,10391,10370,10349,10321 390,10305,10273,10257,10228,10211,10183,10164,10138,10115,10096,10066 391,10053,10019,10007,9975,9960,9930,9916,9883,9871,9839,9823 392,9801,9771,9759,9726,9714,9684,9666,9640,9623,9596,9577 393,9553,9532,-9510,-9487,-9467,-9443,-9422,-9401,-9377,-9358,-9334 394,-9313,-9292,-9270,-9248,-9227,-9205,-9182,-9165,-9138,-9121,-9098 395,-9075,-9057,-9032,-9015,-8989,-8973,-8947,-8929,-8907,-8885,-8867 396,-8842,-8824,-8802,-8780,-8763,-8737,-8720,-8699,-8676,-8657,-8637 397,-8614,-8597,8576,8554,8532,8513,8494,8470,8454,8429,8413 398,8390,8371,8351,8328,8314,8286,8274,8247,8233,8207,8192 399,8170,8149,8134,8108,8092,8070,8053,8031,8014,7991,7974 400,7953,7935,7912,7899,7872,7861,7832,7820,7798,7779,7761 401,7739,7724,-7706,-7679,-7669,-7641,-7628,-7607,-7588,-7570,-7551 402,-7530,-7515,-7491,-7478,-7456,-7438,-7419,-7401,-7379,-7369,-7338 403,-7335,-7300,-7295,-7267,-7255,-7233,-7218,-7196,-7181,-7159,-7145 404,-7124,-7107,-7090,-7068,-7055,-7033,-7018,-6999,-6979,-6966,-6942 405,-6929,-6909,6891,6875,6855,6840,6820,6803,6787,6768,6750 406,6733,6717,6695,6687,6657,6650,6629,6608,6599,6573,6562 407,6543,6525,6508,6494,6470,6462,6437,6426,6405,6391,6371 408,6358,6338,6323,6305,6289,6273,6254,6241,6221,6206,6191 409,6170,6160,6136,-6121,-6108,-6090,-6075,-6057,-6044,-6023,-6013 410,-5988,-5983,-5955,-5950,-5926,-5914,-5897,-5879,-5867,-5846,-5837 411,-5813,-5806,-5780,-5774,-5751,-5741,-5720,-5710,-5687,-5680,-5656 412,-5648,-5626,-5616,-5596,-5584,-5566,-5552,-5538,-5519,-5507,-5490 413,-5475,-5463,-5440,5425,5419,5396,5385,5373,5350,5342,5324 414,5308,5297,5278,5266,5250,5236,5218,5209,5190,5176,5162 415,5148,5131,5120,5103,5088,5075,5061,5043,5035,5013,5005 416,4988,4973,4960,4946,4931,4916,4905,4885,4879,4856,4850 417,4829,4823,4799,-4785,-4783,-4758,-4749,-4738,-4718,-4710,-4693 418,-4679,-4669,-4649,-4643,-4621,-4616,-4596,-4585,-4572,-4555,-4548 419,-4527,-4521,-4501,-4492,-4477,-4464,-4451,-4437,-4425,-4410,-4399 420,-4384,-4372,-4359,-4345,-4332,-4320,-4307,-4292,-4283,-4265,-4256 421,-4243,-4227,-4217,4201,4196,4171,4173,4145,4147,4123,4117 422,4103,4087,4079,4065,4051,4042,4026,4014,4005,3988,3981 423,3962,3956,3939,3931,3917,3903,3892,3882,3866,3860,3841 424,3831,3824,3804,3800,3782,3772,3761,3749,3737,3726,3712 425,3702,3690,3679,-3667,-3656,-3640,-3637,-3614,-3614,-3594,-3587 426,-3573,-3564,-3549,-3542,-3528,-3517,-3506,-3494,-3482,-3475,-3458 427,-3452,-3437,-3427,-3417,-3406,-3392,-3384,-3372,-3359,-3354,-3335 428,-3330,-3316,-3306,-3297,-3283,-3276,-3259,-3256,-3239,-3232,-3220 429,-3210,-3196,-3192,3182,3161,3161,3143,3137,3124,3114,3103 430,3096,3080,3075,3060,3054,3040,3034,3018,3013,2999,2992 431,2980,2971,2958,2953,2937,2933,2918,2910,2901,2889,2881 432,2869,2862,2849,2842,2828,2824,2810,2801,2793,2780,2774 433,2762,2755,2740,-2730,-2729,-2711,-2706,-2697,-2683,-2681,-2665 434,-2658,-2650,-2636,-2633,-2618,-2614,-2599,-2593,-2585,-2571,-2568 435,-2556,-2542,-2544,-2521,-2526,-2507,-2502,-2492,-2483,-2474,-2467 436,-2455,-2447,-2440,-2428,-2422,-2412,-2402,-2396,-2385,-2376,-2369 437,-2359,-2351,-2344,2336,2323,2319,2303,2306,2282,2290,2269 438,2268,2254,2251,2238,2234,2221,2217,2203,2203,2187,2184 439,2171,2168,2155,2150,2141,2132,2125,2116,2109,2099,2094 440,2083,2078,2066,2062,2052,2045,2037,2027,2023,2011,2009 441,1994,1992,1980,-1973,-1967,-1959,-1950,-1945,-1937,-1926,-1923 442,-1911,-1907,-1899,-1889,-1885,-1873,-1871,-1860,-1853,-1847,-1838 443,-1832,-1824,-1816,-1811,-1801,-1795,-1789,-1778,-1776,-1765,-1759 444,-1753,-1742,-1742,-1726,-1728,-1714,-1710,-1703,-1696,-1688,-1682 445,-1676,-1664,-1667,1661,1641,1645,1632,1625,1625,1607,1612 446,1596,1596,1585,1581,1570,1571,1556,1556,1546,1539,1536 447,1525,1523,1512,1511,1497,1499,1487,1481,1480,1465,1466 448,1455,1450,1447,1436,1434,1423,1420,1414,1407,1401,1395 449,1388,1382,1379,1369,-1364,-1359,-1352,-1348,-1338,-1336,-1328 450,-1322,-1318,-1310,-1305,-1300,-1291,-1290,-1280,-1277,-1269,-1267 451,-1256,-1255,-1246,-1242,-1238,-1228,-1225,-1221,-1212,-1209,-1203 452,-1195,-1193,-1186,-1180,-1175,-1170,-1163,-1161,-1150,-1150,-1142 453,-1137,-1133,-1126,-1119,1113,1112,1105,1100,1096,1089,1084 454,1080,1075,1068,1067,1054,1059,1045,1045,1041,1031,1031 455,1022,1018,1016,1007,1006,997,996,987,986,979,975 456,970,966,959,957,949,948,940,939,928,932,920 457,918,915,907,906,-900,-896,-890,-885,-883,-877,-871 458,-870,-862,-860,-856,-848,-848,-841,-837,-834,-827,-827 459,-817,-817,-811,-808,-803,-798,-794,-791,-786,-783,-777 460,-774,-769,-765,-763,-756,-754,-748,-746,-741,-737,-732 461,-731,-722,-727,-710,707,714,704,700,702,690,693 462,684,685,676,677,671,665,668,656,657,653,649 463,644,645,632,640,626,631,620,623,614,615,607 464,608,601,598,598,588,592,582,584,576,577,568 465,571,564,561,558,-554,-553,-546,-546,-541,-540,-532 466,-537,-522,-531,-519,-521,-515,-513,-510,-505,-507,-495 467,-503,-489,-495,-486,-486,-481,-480,-476,-472,-472,-465 468,-467,-458,-461,-453,-455,-450,-444,-446,-439,-441,-433 469,-435,-428,-428,-425,424,416,417,413,411,407,407 470,401,400,397,396,389,394,381,388,379,381,375 471,376,368,371,365,365,360,360,356,353,353,347 472,347,346,340,339,339,331,337,326,330,323,325 473,319,321,312,318,-316,-305,-310,-303,-303,-302,-296 474,-298,-292,-293,-289,-288,-285,-283,-281,-279,-278,-274 475,-273,-269,-271,-265,-265,-264,-257,-262,-255,-254,-255 476,-248,-250,-247,-243,-247,-236,-244,-232,-240,-231,-232 477,-232,-223,-232,-220,219,224,217,218,216,212,212 478,212,207,208,204,202,204,200,197,197,195,193 479,194,187,191,186,184,187,177,186,175,180,175 480,173,175,169,172,168,165,167,162,166,157,162 481,156,158,156,152,-152,-151,-149,-149,-146,-147,-142 482,-145,-140,-141,-138,-137,-139,-131,-138,-128,-135,-126 483,-132,-124,-129,-123,-125,-121,-123,-116,-123,-116,-117 484,-115,-113,-114,-112,-112,-107,-110,-108,-104,-109,-100 485,-105,-103,-99,-101,99,99,94,98,93,96,89 486,96,87,91,88,89,86,88,81,86,83,82 487,82,78,83,73,83,73,77,76,72,74,73 488,69,73,70,67,71,63,71,62,69,59,68 489,58,66,58,63,57,-58,-58,-57,-56,-56,-55 490,-56,-51,-57,-47,-56,-48,-53,-49,-48,-50,-45 491,-50,-45,-46,-46,-43,-45,-43,-43,-41,-43,-39 492,-43,-37,-42,-35,-42,-34,-39,-36,-36,-35,-35 493,-34,-34,-34,-31,-35,35,28,34,27,35,23 494,35,23,32,26,27,28,24,28,23,27,24 495,24,25,21,25,22,22,23,19,23,20,20 496,22,16,23,15,23,13,23,12,23,13,18 497,16,15,16,16,14,-14,-14,-16,-11,-18,-9 498,-17,-8,-17,-10,-14,-10,-11,-13,-10,-12,-9 499,-10,-11,-9,-11,-8,-9,-10,-6,-13,-4,-12 500,-4,-12,-2,-14,-1,-12,-3,-8,-6,-7,-6 501,-6,-5,-6,-5,-6,6,3,8,2,7,2 502,7,2,6,1,6,4,1,9,-5,12,-5 503,10,-1,5,0,5,1,5,0,3,3,1 504,3,2,1,3,0,5,-2,4,0,2,3 505,-1,4,-3,6,-3,2,-2,-2,0,-1,-2 506,1,-1,-2,1,-2,0,0,-2,2,-3,2 507,-4,4,-5,5,-5,2,0,-1,0,1,-4 508,5,-5,4,-3,2,-1,-1,1,-2,2,-2 509,2,-2,2,-1,0,1,-1,0,1,-2,3 510,-3,2,-1,0,1,-1,0,0,1,-1,1 511,-2,3 512}; 513 514/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 515 Utilities from pdbox plugin (Copyright (C) 2009 Wincent Balin) --- am I 516 supposed to supply these functions with the plugin? Should I use a library? 517* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 518 519/* Implementation of strtod() and atof(), 520 taken from SanOS (http://www.jbox.dk/sanos/). */ 521static int rb_errno = 0; 522 523static double rb_strtod(const char *str, char **endptr) 524{ 525 double number; 526 int exponent; 527 int negative; 528 char *p = (char *) str; 529 double p10; 530 int n; 531 int num_digits; 532 int num_decimals; 533 534 /* Reset Rockbox errno -- W.B. */ 535#ifdef ROCKBOX 536 rb_errno = 0; 537#endif 538 539 // Skip leading whitespace 540 while (isspace(*p)) p++; 541 542 // Handle optional sign 543 negative = 0; 544 switch (*p) 545 { 546 case '-': negative = 1; // Fall through to increment position 547 case '+': p++; 548 } 549 550 number = 0.; 551 exponent = 0; 552 num_digits = 0; 553 num_decimals = 0; 554 555 // Process string of digits 556 while (isdigit(*p)) 557 { 558 number = number * 10. + (*p - '0'); 559 p++; 560 num_digits++; 561 } 562 563 // Process decimal part 564 if (*p == '.') 565 { 566 p++; 567 568 while (isdigit(*p)) 569 { 570 number = number * 10. + (*p - '0'); 571 p++; 572 num_digits++; 573 num_decimals++; 574 } 575 576 exponent -= num_decimals; 577 } 578 579 if (num_digits == 0) 580 { 581#ifdef ROCKBOX 582 rb_errno = 1; 583#else 584 errno = ERANGE; 585#endif 586 return 0.0; 587 } 588 589 // Correct for sign 590 if (negative) number = -number; 591 592 // Process an exponent string 593 if (*p == 'e' || *p == 'E') 594 { 595 // Handle optional sign 596 negative = 0; 597 switch(*++p) 598 { 599 case '-': negative = 1; // Fall through to increment pos 600 case '+': p++; 601 } 602 603 // Process string of digits 604 n = 0; 605 while (isdigit(*p)) 606 { 607 n = n * 10 + (*p - '0'); 608 p++; 609 } 610 611 if (negative) 612 exponent -= n; 613 else 614 exponent += n; 615 } 616 617#ifndef ROCKBOX 618 if (exponent < DBL_MIN_EXP || exponent > DBL_MAX_EXP) 619 { 620 errno = ERANGE; 621 return HUGE_VAL; 622 } 623#endif 624 625 // Scale the result 626 p10 = 10.; 627 n = exponent; 628 if (n < 0) n = -n; 629 while (n) 630 { 631 if (n & 1) 632 { 633 if (exponent < 0) 634 number /= p10; 635 else 636 number *= p10; 637 } 638 n >>= 1; 639 p10 *= p10; 640 } 641 642#ifndef ROCKBOX 643 if (number == HUGE_VAL) errno = ERANGE; 644#endif 645 if (endptr) *endptr = p; 646 647 return number; 648} 649 650static double rb_atof(const char *str) 651{ 652 return rb_strtod(str, NULL); 653} 654 655/* * * * * * * * * * * * * * * * * * * * * * * 656 Actual metronome stuff 657* * * * * * * * * * * * * * * * * * * * * * */ 658 659static int fd = -1; /* file descriptor, global for cleanup(). */ 660 661/* Round fixed-point number to integer. */ 662static int fp_rint(long fp_num) 663{ 664 fp_num += fp_num > 0 ? +((long)1<<15) : -((long)1<<15); 665 return (int)(fp_num / ((long)1<<16)); 666} 667/* float to fixed-point */ 668static long fp_frac(float fl_num) 669{ 670 return (long)(fl_num*((long)1<<16)); 671} 672 673/* simple dynamic memory management 674 - only allocate blocks serially 675 - deallocation of most recent blocks by resetting the free region pointer 676 - everything aligned to 4 bytes (wasting some bytes, but playing safe) 677*/ 678static void *mem_begin = NULL; /* beginning of managed region. */ 679static void *mem_end = NULL; /* just after end of managed region */ 680static void *mem_free_region = NULL; /* pointer to unused free space */ 681static void *mem_checkpointer = NULL; /* position to reset to */ 682 683/* Initialize memory management. */ 684static void mem_init(void) 685{ 686 size_t bufsize; 687 /* Can I trust that pointer to be aligned? Better be safe. */ 688 mem_begin = ALIGN_UP(rb->plugin_get_buffer(&bufsize), 4); 689 mem_end = mem_begin + bufsize - 3; 690 mem_free_region = mem_begin; 691 mem_checkpointer = mem_begin; 692} 693 694/* Remember and reset free region, for temporary mem usage. */ 695static void mem_checkpoint(void){ mem_checkpointer = mem_free_region; } 696static void mem_reset (void){ mem_free_region = mem_checkpointer; } 697static void *mem_allocate(size_t bytes) 698{ 699 void *handout = mem_free_region; 700 /* Always handing out multiples of alignment size. */ 701 if(bytes % 4) bytes += 4 - bytes % 4; 702 if(mem_free_region + bytes >= mem_end) 703 { 704 rb->splash(2*HZ, "Out Of Memory"); 705 return NULL; 706 } 707 mem_free_region += bytes; 708 return handout; 709} 710 711struct part; 712struct part /* One part of a track, with one tempo (range), meter, etc. */ 713{ 714 struct part *prev, *next; /* linked list links*/ 715 unsigned int id; /* index (in order, please) */ 716 char *label; 717 unsigned int bars; /* Duration of part in bars. */ 718 unsigned int beats_per_bar; /* 3 in 3/4 */ 719 unsigned int base_beat; /* 4 in 3/4 to adjust bpm value */ 720 unsigned int bpm; /* base tempo (1/4 notes per minute) */ 721 unsigned int bpm2; /* end tempo */ 722 unsigned int *beat_bpm; /* either NULL or (bars*beats_per_bar) values */ 723 long accel; /* fixed-point acceleration in 1/min (really) */ 724 int volume; /* volume offset in integer dB */ 725 /* Store pattern characters verbatim for max. 64 beats (no string 726 termination). One could save storage here by encoding things in bits, 727 or by allocating dynamically to begin with. */ 728 char *pattern; 729}; 730 731static struct part *part_list = NULL; /* linked list of parts */ 732static struct part *part = NULL; /* current part */ 733static unsigned int parts = 0; /* total number of parts */ 734static unsigned int bad_parts = 0; /* Count parts with parsing errors. */ 735 736/* Initialize a part that is not yet placed into the list. */ 737static void part_init(struct part *ps) 738{ 739 ps->prev = NULL; 740 ps->next = NULL; 741 ps->id = 0; 742 ps->label = NULL; 743 ps->bars = 0; 744 ps->beats_per_bar = 4; 745 ps->base_beat = 4; 746 ps->bpm = 120; 747 ps->bpm2 = 120; 748 ps->beat_bpm = NULL; 749 ps->accel = 0; 750 ps->volume = 0; 751 ps->pattern = NULL; 752} 753 754/* Add to the list. */ 755static void part_add(struct part *ps) 756{ 757 if(part) 758 { 759 part->next = ps; 760 ps->prev = part; 761 part = ps; 762 } 763 else part = part_list = ps; 764 765 ps->id = parts++; 766} 767 768/* Stay away from zero. */ 769static unsigned int positive(long long value) 770{ 771 return value > 0 ? value : 1; 772} 773 774/* Yay! Global state variables! */ 775static bool track_mode = false; /* switch for programmed tracks metronome */ 776static int loop = 0; /* Needed? */ 777static unsigned int beat = 0; 778static unsigned int bar = 0; /* How big shall this become? */ 779/* The currently (approximate) active bpm value, set from calc_period(). */ 780static unsigned int bpm = 1; 781 782/* Should be unsigned? */ 783static unsigned int period = 0; /* beat interval in timer ticks */ 784static long period_diff = 0; /* fixed-point error of last period computation */ 785static unsigned int minitick = 0; /* elapsed ticks */ 786static bool beating = false; /* A beat is/was playing and count needs to increase. */ 787static int display_state = 0; /* Current display state code. */ 788static bool display_trigger = false; /* Draw display on next occasion */ 789 790static bool sound_active = false; 791static bool sound_paused = true; 792 793/* global static buffer for messages in any situation */ 794static char buffer[64]; 795/* For line parsing, more is needed, allocated on demand. 796 As my memory management doesn't allow to free it, keeping it local 797 ist not smart. */ 798static char* linebuf = NULL; 799size_t linebuf_size = 0; 800 801 802/* global state for tempo tapping */ 803static bool reset_tap = false; 804static int tap_count = 0; 805static int tap_time = 0; 806static int tap_timeout = 0; 807 808static int bpm_step_counter = 0; 809 810static bool sound_trigger = false; 811 812#define MET_IS_PLAYING rb->pcm_is_playing() 813#define MET_PLAY_STOP rb->audio_stop() 814 815/* Really necessary? Cannot just play mono? 816 Also: This is wasted memory! */ 817static short tick_buf[sizeof(tick_sound)*2]; 818static short tock_buf[sizeof(tock_sound)*2]; 819 820/* Convert the mono samples to interleaved stereo */ 821static void prepare_buffers(void) 822{ 823 size_t i; 824 for(i = 0;i < sizeof(tick_sound)/sizeof(short);i++) 825 tick_buf[i*2] = tick_buf[i*2+1] = tick_sound[i]; 826 for(i = 0;i < sizeof(tock_sound)/sizeof(short);i++) 827 tock_buf[i*2] = tock_buf[i*2+1] = tock_sound[i]; 828} 829 830static void play_tick(void) 831{ 832 rb->pcm_play_data(NULL, NULL, tick_buf, sizeof(tick_buf)); 833} 834 835static void play_tock(void) 836{ 837 rb->pcm_play_data(NULL, NULL, tock_buf, sizeof(tock_buf)); 838} 839 840/* State: 0: blank/title, 1: tick, 2: tock 3: silent klick */ 841/* TODO: Could use more smart placement, using 842 lcd_getstringsize() and such. */ 843static void metronome_draw(struct screen* display, int state) 844{ 845 struct part *ps; 846 int textlen = display->lcdwidth / display->getcharwidth(); 847 ps = part; 848 display->clear_display(); 849 display->setfont(FONT_SYSFIXED); 850 int rectangle_height = display->lcdheight - ((SYSFONT_HEIGHT + 1) * 7); 851 if (rectangle_height < 12) 852 rectangle_height = 12; 853 switch(state) 854 { 855 case 0: 856 if(sound_paused) 857 { 858 if(track_mode) display->puts(0, 0, "Metronome Track"); 859 else display->puts(0, 0, "Metronome"); 860 861 display->hline(0, display->lcdwidth, 12); 862 } 863 break; 864 /* Draw odd/even ticks/tocks differently to be able to go without 865 display clearing in between for fast beats. */ 866 case 1: 867 if((beat+1) % 2 == 0) 868 display->fillrect( display->lcdwidth/2, 0 869 , display->lcdwidth, rectangle_height ); 870 else 871 display->fillrect( 0, 0 872 , display->lcdwidth/2-1, rectangle_height ); 873 break; 874 case 2: 875 if((beat+1) % 2 == 0) 876 display->fillrect( display->lcdwidth/2, display->lcdheight - rectangle_height - 1 877 , display->lcdwidth, rectangle_height ); 878 else 879 display->fillrect( 0, display->lcdheight - rectangle_height - 1 880 , display->lcdwidth/2-1, rectangle_height ); 881 break; 882 case 3: 883 display->puts((textlen-3)/2,0, "o.O"); 884 break; 885 } 886 887 if(track_mode) 888 { 889 890 /* One line in several. */ 891 rb->snprintf( buffer, sizeof(buffer), "%u/%u@%u V%d" 892 , ps->beats_per_bar, ps->base_beat 893 , bpm, rb->global_status->volume ); 894 display->puts(0,4, buffer); 895 896 /* Would it hurt to draw a 3rd line to 2-line display? 897 I guess there are 3-line displays out there. */ 898 if(ps->label && rb->strlen(ps->label)) 899 { 900 rb->snprintf(buffer, sizeof(buffer), "\"%s\"", ps->label); 901 display->puts((textlen-rb->strlen(buffer))/2, 2, buffer); 902 } 903 904 /* Wildly guessing here with puts(). */ 905 if(ps->bars) 906 rb->snprintf( buffer, sizeof(buffer), "P%u/%u: B%u/%u+%u" 907 , part->id+1, parts, bar+1, ps->bars, beat+1 ); 908 else 909 rb->snprintf( buffer, sizeof(buffer), "P%u/%u: B%u/_+%u" 910 , part->id+1, parts, bar+1, beat+1 ); 911 display->puts(0, 5, buffer); 912 913 } 914 else /* track mode */ 915 { 916 917 if(display->screen_type==SCREEN_MAIN) 918 { 919#ifdef MET_SYNC 920 display->puts(0, 5, "Select=TAP Rec=SYNC"); 921#else 922 display->puts(0, 5, "Select=TAP"); 923#endif 924 } 925#ifdef HAVE_REMOTE_LCD 926 else 927 { 928#ifdef MET_SYNC 929 display->puts(0, 5, "Rec=TAP Mode=SYNC"); 930#else 931 display->puts(0, 5, "Rec=TAP"); 932#endif 933 } 934#endif 935 936 rb->snprintf( buffer, sizeof(buffer), "BPM: %d Vol: %d" 937 , bpm, rb->global_status->volume ); 938 display->puts(0,3, buffer); 939 940 display->hline(0, 111, 12); 941 if(sound_paused) display->puts(0,2,"start: hold select"); 942 else display->puts(0,2,"stop : cancel"); 943 944 } /* !track_mode */ 945 946 display->setfont(FONT_UI); 947 display->update(); 948} 949 950/* Trigger drawing of display at the next occasion using given state. */ 951static void trigger_display(int state) 952{ 953 display_state = state; 954 display_trigger = true; 955} 956 957/* Actually draw display. */ 958static void draw_display(void) 959{ 960 FOR_NB_SCREENS(i) 961 metronome_draw(rb->screens[i], display_state); 962} 963 964/* Modify actual volume by given offset without changing the configured one. 965 This is for parts with associated volume. */ 966static void tweak_volume(int offset) 967{ 968 int vol = rb->global_status->volume + offset; 969 int minvol = rb->sound_min(SOUND_VOLUME); 970 int maxvol = rb->sound_max(SOUND_VOLUME); 971 972 if (vol > maxvol) vol = maxvol; 973 else if(vol < minvol) vol = minvol; 974 975 rb->sound_set(SOUND_VOLUME, vol); 976} 977 978/* tempo at a certain point in beat space in an accelerated part */ 979static long accel_tempo(struct part *ps, long offset) 980{ 981 long fp_bpm = (long)ps->bpm<<16; 982 long fp_bpm2 = (long)ps->bpm2<<16; 983 long v = fp_bpm + fp_mul(ps->accel, offset, 16); 984 /* Offset could be negative, actually, so ensure tempo stays within both 985 bounds */ 986 if(ps->accel > 0) 987 { 988 if(v < fp_bpm) v = fp_bpm; 989 if(v > fp_bpm2) v = fp_bpm2; 990 } 991 else /* deceleration */ 992 { 993 if(v > fp_bpm) v = fp_bpm; 994 if(v < fp_bpm2) v = fp_bpm2; 995 } 996 return v; 997} 998 999/* Calculate number of ticks to wait till next beat. */ 1000static void calc_period(void) 1001{ 1002 struct part *ps = part; 1003 long deltat; 1004 long beatlen; /* in quarter notes */ 1005 long period_fp; 1006 1007 beatlen = fp_div(4<<16, ps->base_beat<<16, 16); 1008 /* Hack: Put the factor 60 in before computing deltat, to preserve 1009 some accuracty. */ 1010 if(ps->beat_bpm) 1011 { 1012 bpm = ps->beat_bpm[bar*ps->beats_per_bar+beat]; 1013 deltat = fp_div(fp_mul(60<<16,beatlen,16), bpm<<16, 16); 1014 } else 1015 if(ps->accel == 0.f) 1016 { /* Fixed tempo. */ 1017 bpm = ps->bpm; 1018 /* Minutes per base beat, from quarters per minute. */ 1019 deltat = fp_div(fp_mul(60<<16,beatlen,16), bpm<<16, 16); 1020 } 1021 else 1022 { /* Acceleration, varying period with each beat. */ 1023 long v0, v1; 1024 long offset = (bar*ps->beats_per_bar + beat) << 16; 1025 /* Always computed from start of part for seeking and accuracy. */ 1026 v0 = accel_tempo(ps, fp_mul(beatlen, offset, 16)); 1027 offset += 1<<16; 1028 v1 = accel_tempo(ps, fp_mul(beatlen, offset, 16)); 1029 /* Playing safe with too small tempo changes, avoiding the acceleration 1030 math that might divide by very small deltat. */ 1031 if(labs(v1-v0) > 1<<8) 1032 { 1033 /* deltat = 1.f / ps->accel * rb_log(v1/v0) */ 1034 deltat = fp_mul( fp_div(60<<16, ps->accel, 16) 1035 , fp16_log(fp_div(v1, v0, 16)) 1036 , 16 ); 1037 bpm = fp_rint(fp_div(fp_mul(60<<16, beatlen, 16), deltat, 16)); 1038 } 1039 else 1040 { /* Arbitrarily choosing v1. */ 1041 bpm = fp_rint(v1); 1042 deltat = fp_div(fp_mul(60<<16,beatlen,16), v1, 16); 1043 } 1044 } 1045 /* The treatment of the rounding error when converting to integer 1046 period using period_diff helps a lot to keep track lengths close to 1047 "correct" even with timerfreq_div as low as 77. Actually, I have _less_ 1048 drift than with timerfreq_div of 1000! */ 1049 period_fp = fp_mul(timerfreq_div<<16, deltat, 16) + period_diff; 1050 period = positive(fp_rint( period_fp )); 1051 period_diff = period_fp - (long)(period<<16); 1052} 1053 1054/* Last beat finished, to prepare for the next one. */ 1055static void advance_beat(void) 1056{ 1057 if(++beat == part->beats_per_bar) 1058 { 1059 beat = 0; 1060 /* Bar counter always incremented for acceleration, but only checked 1061 against a limit if there is one. */ 1062 ++bar; 1063 if(part->bars && bar == part->bars) 1064 { 1065 bar = 0; 1066 if(part->next) part = part->next; 1067 else 1068 { 1069 part = part_list; 1070 if(!loop) sound_paused = true; 1071 } 1072 tweak_volume(part->volume); 1073 } 1074 } 1075 /* Always recompute period, as acceleration changes it for each beat. */ 1076 calc_period(); 1077} 1078 1079/* Decide what to play, update display, play it. 1080 Beat counting happens here, too. */ 1081static void play_ticktock(void) 1082{ 1083 if(beating) advance_beat(); 1084 1085 /* Hack: Clear trigger to avoid race condition. */ 1086 display_trigger = 0; 1087 if(sound_paused) 1088 { 1089 beating = false; 1090 display_state = 0; 1091 draw_display(); 1092 } 1093 else 1094 { 1095 char pat = 'x'; 1096 if(part->pattern) pat = part->pattern[beat]; 1097 1098 beating = true; 1099 /* Blinking and specific sound for tick, tock and silent beat. 1100 Drawing display first for slow machines (YH820), to avoid 1101 interrupting audio for regular playback. */ 1102 switch(pat) 1103 { 1104 case 'X': 1105 display_state = 1; 1106 draw_display(); 1107 play_tick(); 1108 break; 1109 case 'x': 1110 display_state = 2; 1111 draw_display(); 1112 play_tock(); 1113 break; 1114 default: 1115 display_state = 3; 1116 draw_display(); 1117 } 1118 } 1119} 1120 1121/* helper function to change the volume by a certain amount, +/- 1122 ripped from video.c */ 1123static void change_volume(int delta) 1124{ 1125 int minvol = rb->sound_min(SOUND_VOLUME); 1126 int maxvol = rb->sound_max(SOUND_VOLUME); 1127 int vol = rb->global_status->volume + delta; 1128 1129 if (vol > maxvol) vol = maxvol; 1130 else if(vol < minvol) vol = minvol; 1131 if(vol != rb->global_status->volume) 1132 { 1133 rb->global_status->volume = vol; 1134 tweak_volume(part->volume); 1135 trigger_display(display_state); 1136 } 1137} 1138 1139/*function to accelerate bpm change*/ 1140static void change_bpm(int direction) 1141{ 1142 if( (bpm_step_counter < 20) 1143 || (bpm > 389) 1144 || (bpm < 10) ) 1145 bpm = bpm + direction; 1146 else if(bpm_step_counter < 60) 1147 bpm = bpm + direction * 2; 1148 else 1149 bpm = bpm + direction * 9; 1150 1151 if(bpm > 400) bpm = 400; 1152 if(bpm < 1) bpm = 1; 1153 1154 part->bpm = bpm; 1155 calc_period(); 1156 trigger_display(display_state); 1157 bpm_step_counter++; 1158} 1159 1160/* I presume the timer ensures that not more than one instance 1161 of the callback is running at a given time. */ 1162static void timer_callback(void) 1163{ 1164 ++minitick; 1165 1166 /* Clear blinker if tempo is slow enough. */ 1167 if( (bpm*part->base_beat)/4 <= blinklimit && 1168 !sound_paused && minitick == period/2 ) 1169 trigger_display(0); 1170 1171 if(minitick >= period) 1172 { 1173 minitick = 0; 1174 if(!sound_active && !sound_paused && !tap_count) 1175 { 1176 sound_trigger = true; 1177 rb->reset_poweroff_timer(); 1178 } 1179 } 1180 1181 if(tap_count) 1182 { 1183 tap_time++; 1184 if(tap_count > 1 && tap_time > tap_timeout) 1185 tap_count = 0; 1186 } 1187} 1188 1189/* Stopping playback means incrementing the beat. Normally, it would be 1190 incremented after the passing of the current note duration, naturally 1191 while starting the next one. */ 1192static void metronome_pause(void) 1193{ 1194 if(beating) 1195 { 1196 /* Finish the current beat. */ 1197 advance_beat(); 1198 beating = false; 1199 } 1200 sound_paused = true; 1201 trigger_display(0); 1202 rb->timer_unregister(); 1203} 1204 1205static void metronome_unpause(void) 1206{ 1207 sound_paused = false; 1208 minitick = period; /* Start playing immediately (or after a millisecond). */ 1209 /* Conserve power: Only start timer when actually playing. */ 1210 rb->timer_register( 1, NULL, TIMER_FREQ/timerfreq_div 1211 , timer_callback IF_COP(, CPU) ); 1212} 1213 1214static void cleanup(void) 1215{ 1216 if(fd >= 0) rb->close(fd); 1217 1218 metronome_pause(); 1219 MET_PLAY_STOP; /* stop audio ISR */ 1220 tweak_volume(0); 1221 rb->led(0); 1222 rb->pcm_set_frequency(HW_SAMPR_DEFAULT); 1223} 1224 1225/* 1226 Parse part definitions from tempomap file (see header for format). 1227 Not bothering with encoding issues here. 1228*/ 1229 1230/* parse meter spec into part structure if given token matches */ 1231static bool parse_meter(char *token, struct part *ps) 1232{ 1233 char *toktok; 1234 /* Careful not to misinterpret accelerated tempo specification: 1235 120-150/4 -> tempo 1236 3/4 -> meter */ 1237 if( !rb->strchr(token, '-') && (toktok = rb->strchr(token, '/')) ) 1238 { 1239 /* Number before and after the '/'. */ 1240 int num[2]; 1241 num[0] = rb->atoi(token); 1242 num[1] = rb->atoi(++toktok); 1243 /* Only accept positive numbers. */ 1244 if(num[0] > 0 && num[1] > 0) 1245 { 1246 ps->beats_per_bar = (unsigned int) num[0]; 1247 ps->base_beat = (unsigned int) num[1]; 1248 return true; 1249 } 1250 } 1251 return false; 1252} 1253 1254/* Parse tempo, successful when getting a positive integer out of the token. */ 1255static bool parse_tempo(char *token, struct part *ps) 1256{ 1257 char *toktok; 1258 /* tempo[-tempo2/accel] ... first number always main tempo */ 1259 int num = rb->atoi(token); 1260 /* Only positive numbers. This avoids the pattern string and general 1261 strangeness, unless -150 should mean "from previous tempo to 150". */ 1262 if(num < 1) return false; 1263 1264 ps->bpm = (unsigned int) num; 1265 ps->bpm2 = ps->bpm; 1266 ps->accel = 0; 1267 /* This parser is not fool-proof. It parses valid data, but could 1268 do funny things if you provide tempo/tempo2-accel, for example. 1269 My credo is that the application doesn't crash, but if you give rubbish, 1270 you'll get rubbish. */ 1271 if( (toktok = rb->strchr(token, '-')) ) 1272 { 1273 char *subtok = toktok+1; 1274 float faccel = 0.; 1275 ps->bpm2 = positive(rb->atoi(subtok)); 1276 /* Parse or compute accel in bpm/bar. */ 1277 if( (toktok = rb->strchr(subtok, '/')) ) 1278 { /* bars/bpm */ 1279 float c = rb_atof(++toktok); 1280 if( (c > 0.f ? c : -c) > 0.0001f) 1281 faccel = 1./c; 1282 } 1283 else if( (toktok = rb->strchr(subtok, '*')) ) 1284 { /* bpm/bar */ 1285 faccel = rb_atof(++toktok); 1286 } 1287 else if(ps->bars > 0) 1288 { /* Compute from tempo difference and bar count. */ 1289 faccel = ((float)ps->bpm2 - (float)ps->bpm)/ps->bars; 1290 } 1291 /* Correct sign for all cases, starting with positive value. */ 1292 if(faccel < 0) faccel = -faccel; 1293 /* Negative only when end tempo is smaller. */ 1294 if(ps->bpm2 < ps->bpm) faccel = -faccel; 1295 /* Convert (quarterbeats-per-minute per bar) -> 1/min, which could be 1296 seen as beats-per-minute/beat */ 1297 faccel *= 1.f / (4.f/ps->base_beat * ps->beats_per_bar); /* 1/min */ 1298 ps->accel = fp_frac(faccel); 1299 } else 1300 /* The other fancy variant: One tempo per beat. */ 1301 if( (toktok = rb->strchr(token, ',')) ) 1302 { 1303 size_t i; 1304 char *subtok = token; 1305 /* It is a bug when the parser called this before. Alloc once. */ 1306 if( ps->beat_bpm || !(ps->beat_bpm = 1307 mem_allocate(sizeof(unsigned int)*ps->beats_per_bar*ps->bars)) ) 1308 return false; 1309 for(i=0; i<ps->beats_per_bar*ps->bars; ++i) 1310 { 1311 int num; 1312 if(!subtok) return false; 1313 if(subtok != token) ++subtok; 1314 1315 num = rb->atoi(subtok); 1316 if(num < 1) return false; 1317 1318 ps->beat_bpm[i] = (unsigned int) num; 1319 subtok = rb->strchr(subtok, ','); 1320 } 1321 } 1322 return true; 1323} 1324 1325/* The metronome pattern. 1326 Ensure that the correct meter is present before calling this! */ 1327static bool parse_pattern(char *token, struct part *ps) 1328{ 1329 size_t pi; 1330 size_t pats = rb->strlen(token); 1331 1332 /* First check if the pattern is valid, error out if not. */ 1333 if(pats != ps->beats_per_bar) 1334 return false; 1335 for(pi=0; pi<pats; ++pi) 1336 switch(token[pi]) 1337 { 1338 case 'X': 1339 case 'x': 1340 case '.': 1341 break; 1342 default: return false; 1343 } 1344 1345 if(!(ps->pattern || (ps->pattern = mem_allocate(pats)))) 1346 return false; 1347 /* Now store it. */ 1348 memcpy(ps->pattern, token, pats); 1349 return true; 1350} 1351 1352static bool parse_volume(char *token, struct part *ps) 1353{ 1354 float factor = rb_atof(token); 1355 ps->volume = fp_rint(fp_decibels(fp_frac(factor > 0.f ? factor : 0.f), 16)); 1356 return true; 1357} 1358 1359/* Check condition, set error code and bail out if violated. */ 1360#define CHECK(a, c) if(!(a)){ errcode = c; goto parse_part_revert; } 1361 1362static void parse_part(char *line, unsigned int num) 1363{ 1364 char *saveptr; 1365 char *toktok; 1366 char *token[5]; 1367 struct part *ps; 1368 size_t tokens = 0; 1369 unsigned int errcode = MERR_NOTHING; 1370 1371 while (isspace(*line)) line++; 1372 /* Skip comments and empty lines quickly. */ 1373 if(line[0] == '#' || line[0] == 0) return; 1374 1375 mem_checkpoint(); 1376 CHECK(ps = mem_allocate(sizeof(struct part)), MERR_OOM); 1377 part_init(ps); 1378 1379 /* Check for and store label. */ 1380 if( (toktok = rb->strchr(line, ':')) ) 1381 { 1382 size_t len = toktok-line; 1383 CHECK(ps->label = mem_allocate(len+1), MERR_OOM); 1384 rb->memcpy(ps->label, line, len); 1385 ps->label[len] = 0; 1386 line = toktok+1; 1387 } 1388 1389 CHECK(token[0] = rb->strtok_r(line, " \t", &saveptr), MERR_MISSING); 1390 tokens = 1; 1391 /* After the optional label, there can be up to 5 tokens of interest. 1392 Collect them in advance to make the parser code more sane. */ 1393 while( tokens < 5 1394 && (token[tokens] = rb->strtok_r(NULL, " \t", &saveptr)) ) 1395 { 1396 if(token[tokens][0] == '#') 1397 break; 1398 ++tokens; 1399 } 1400 1401 CHECK(tokens >= 2, MERR_MISSING); 1402 1403 /* Now try to be smart about guessing which token can be what value. 1404 Remember: Always parse meter before pattern or tempo! */ 1405 ps->bars = (unsigned int) rb->atoi(token[0]); 1406 if(tokens == 2) /* <bars> <tempo> */ 1407 { 1408 CHECK(parse_tempo(token[1], ps), MERR_TEMPO); 1409 } else 1410 if(tokens == 3) 1411 { 1412 /* <bars> <meter> <tempo> */ 1413 if(parse_meter(token[1], ps)) 1414 { 1415 CHECK(parse_tempo(token[2], ps), MERR_TEMPO); 1416 } else 1417 /* <bars> <tempo> <pattern> */ 1418 if(parse_pattern(token[2], ps)) 1419 { 1420 CHECK(parse_tempo(token[1], ps), MERR_TEMPO); 1421 } else 1422 /* <bars> <tempo> <volume> */ 1423 { 1424 CHECK(parse_tempo(token[1], ps), MERR_TEMPO); 1425 CHECK(parse_volume(token[2], ps), MERR_VOLUME); 1426 } 1427 } else 1428 if(tokens == 4) 1429 { 1430 /* <bars> <meter> <tempo> <pattern> */ 1431 if(parse_meter(token[1], ps) && parse_pattern(token[3], ps)) 1432 { 1433 CHECK(parse_tempo(token[2], ps), MERR_TEMPO); 1434 } else 1435 /* <bars> <tempo> <pattern> <volume> */ 1436 if(parse_pattern(token[2], ps)) 1437 { 1438 CHECK(parse_tempo(token[1], ps), MERR_TEMPO); 1439 CHECK(parse_volume(token[3], ps), MERR_VOLUME); 1440 } else 1441 /* <bars> <meter> <tempo> <volume> */ 1442 { 1443 CHECK(parse_meter(token[1], ps), MERR_METER); 1444 CHECK(parse_tempo(token[2], ps), MERR_TEMPO); 1445 CHECK(parse_volume(token[3], ps), MERR_VOLUME); 1446 } 1447 } else 1448 if(tokens == 5) /* the complete set */ 1449 { 1450 /* <bars> <meter> <tempo> <pattern> <volume> */ 1451 CHECK(parse_meter(token[1], ps), MERR_METER); 1452 CHECK(parse_tempo(token[2], ps), MERR_TEMPO); 1453 CHECK(parse_pattern(token[3], ps), MERR_PATTERN); 1454 CHECK(parse_volume(token[4], ps), MERR_VOLUME); 1455 } 1456 1457 if(!ps->pattern) 1458 { 1459 /* For parsed parts default to emphasize every first beat. */ 1460 CHECK(ps->pattern = mem_allocate(ps->beats_per_bar), MERR_OOM); 1461 memset(ps->pattern, 'x', ps->beats_per_bar); 1462 ps->pattern[0] = 'X'; 1463 } 1464 1465 part_add(ps); 1466 return; /* all good */ 1467 1468 /* Remove part after some error. */ 1469parse_part_revert: 1470 rb->snprintf(buffer, sizeof(buffer), "ERR %u @line %u", errcode, num); 1471 rb->splash(2*HZ, buffer); 1472 ++bad_parts; 1473 mem_reset(); 1474} 1475 1476#undef CHECK 1477 1478static void step_back(void) 1479{ 1480 beating = false; 1481 beat = 0; 1482 if(bar) 1483 { 1484 /* Endless parts only know position 0 to step to. */ 1485 if(part->bars) --bar; 1486 else bar = 0; 1487 } 1488 else if(part->prev) 1489 { 1490 part = part->prev; 1491 /* This will jump to bar 0 for endless parts. */ 1492 bar = positive(part->bars)-1; 1493 tweak_volume(part->volume); 1494 } 1495 /* Always calculate period for acceleration. */ 1496 calc_period(); 1497 minitick = period; 1498} 1499 1500static void step_forw(void) 1501{ 1502 beating = false; 1503 /* Stepping forward in endless part always goes to the next one, if any. */ 1504 if(part->bars == 0 || bar+1 == part->bars) 1505 { 1506 if(part->next) 1507 { /* Advanced one part. */ 1508 part = part->next; 1509 bar = 0; 1510 beat = 0; 1511 tweak_volume(part->volume); 1512 } 1513 } 1514 else ++bar; 1515 /* Always calculate period for acceleration. */ 1516 calc_period(); 1517 minitick = period; 1518} 1519 1520static void tap(void) 1521{ 1522 struct part *ps = part; 1523 1524 /* Each tap resets the position. */ 1525 beat = 0; 1526 bar = 0; 1527 1528 if(tap_count == 0 || tap_time < tap_count) 1529 tap_time = 0; 1530 else 1531 { 1532 if(tap_time > 0) 1533 { 1534 /* Could use fixed point math and rounding, even. */ 1535 ps->bpm = 60*timerfreq_div*tap_count/tap_time; 1536 1537 if(ps->bpm > 400) ps->bpm = 400; 1538 } 1539 tap_timeout = (tap_count+2)*tap_time/tap_count; 1540 } 1541 1542 tap_count++; 1543 minitick = 0; /* sync tock to tapping */ 1544 reset_tap = false; 1545 play_ticktock(); 1546} 1547 1548enum plugin_status plugin_start(const void* file) 1549{ 1550 int button; 1551 static int last_button = BUTTON_NONE; 1552 bool common_action; 1553 1554 atexit(cleanup); 1555 1556 mem_init(); 1557 1558 if(MET_IS_PLAYING) MET_PLAY_STOP; /* stop audio IS */ 1559 1560 prepare_buffers(); 1561#if INPUT_SRC_CAPS != 0 1562 /* Select playback */ 1563 rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); 1564 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); 1565#endif 1566 rb->pcm_set_frequency(SAMPR_44); 1567 1568 if(file) 1569 { 1570 parts = 0; 1571 bad_parts = 0; 1572 fd = rb->open(file, O_RDONLY); 1573 if(fd >= 0) 1574 { 1575 unsigned int linenum = 0; 1576 /* Crazyness, allocating line buffer depending on free memory. */ 1577 linebuf_size = mem_end - mem_free_region > 32*1024 1578 ? 1024 1579 : ( mem_end - mem_free_region > 16*1024 1580 ? 256 1581 : 128 ); 1582 if(!(linebuf = mem_allocate(linebuf_size))) return PLUGIN_ERROR; 1583 /* I'm assuming that read_line always terminates. */ 1584 while(rb->read_line(fd, linebuf, linebuf_size) > 0) 1585 { 1586 parse_part(linebuf, ++linenum); 1587 } 1588 } 1589 rb->close(fd); 1590 if(bad_parts) 1591 { 1592 rb->snprintf(buffer, sizeof(buffer), "%u bad parts", bad_parts); 1593 rb->splash(2*HZ, buffer); 1594 } 1595 if(!parts) 1596 { 1597 rb->splash(2*HZ, "Got no parts. Bye!"); 1598 return PLUGIN_OK; 1599 } 1600 } 1601 1602 /* If no parts given, start in simple metronome mode. */ 1603 if(!parts) 1604 { /* Just checking the early bailout here. */ 1605 struct part *ps = mem_allocate(sizeof(struct part)); 1606 if(!ps) return PLUGIN_ERROR; 1607 part_init(ps); 1608 part_add(ps); 1609 track_mode = false; 1610 } 1611 else track_mode = true; 1612 1613 part = part_list; 1614 tweak_volume(part->volume); 1615 calc_period(); 1616 draw_display(); 1617 1618 /* main loop */ 1619 while(true) 1620 { 1621 reset_tap = true; 1622 button = pluginlib_getaction( TIMEOUT_NOBLOCK, plugin_contexts 1623 , PLA_ARRAY_COUNT ); 1624 if(sound_trigger) 1625 { 1626 sound_trigger = false; 1627 play_ticktock(); /* Draws display before playback. */ 1628 } 1629 1630 common_action = false; 1631 if(track_mode) 1632 { 1633 switch(button) 1634 { 1635 case METRONOME_START: 1636 if(sound_paused) metronome_unpause(); 1637 else metronome_pause(); 1638 break; 1639 case METRONOME_PAUSE: 1640 if(!sound_paused) metronome_pause(); 1641 break; 1642 case METRONOME_LEFT: 1643 case METRONOME_LEFT_REP: 1644 step_back(); 1645 trigger_display(0); 1646 break; 1647 case METRONOME_RIGHT: 1648 case METRONOME_RIGHT_REP: 1649 step_forw(); 1650 trigger_display(0); 1651 break; 1652 default: 1653 common_action = true; 1654 } 1655 } 1656 else 1657 { 1658 switch(button) 1659 { 1660 case METRONOME_PAUSE: 1661 if(!sound_paused) metronome_pause(); 1662 break; 1663 case METRONOME_PLAY: 1664 if(sound_paused) metronome_unpause(); 1665 break; 1666 case METRONOME_TAP: 1667 if(last_button != METRONOME_PLAY) 1668 { 1669 if(sound_paused) metronome_unpause(); 1670 tap(); 1671 } 1672 break; 1673 case METRONOME_LEFT: 1674 bpm_step_counter = 0; 1675 /* fallthrough */ 1676 case METRONOME_LEFT_REP: 1677 change_bpm(-1); 1678 break; 1679 case METRONOME_RIGHT: 1680 bpm_step_counter = 0; 1681 /* fallthrough */ 1682 case METRONOME_RIGHT_REP: 1683 change_bpm(1); 1684 break; 1685#ifdef MET_SYNC 1686 case METRONOME_SYNC: 1687 minitick = period; 1688 break; 1689#endif 1690 default: 1691 common_action = true; 1692 } 1693 } 1694 1695 if(common_action) 1696 switch(button) 1697 { 1698 case METRONOME_QUIT: 1699 /* get out of here */ 1700 return PLUGIN_OK; 1701 case METRONOME_VOL_UP: 1702 case METRONOME_VOL_UP_REP: 1703 change_volume(1); 1704 trigger_display(0); 1705 break; 1706 case METRONOME_VOL_DOWN: 1707 case METRONOME_VOL_DOWN_REP: 1708 change_volume(-1); 1709 trigger_display(0); 1710 break; 1711 default: 1712 exit_on_usb(button); 1713 reset_tap = false; 1714 break; 1715 } 1716 1717 if(button) 1718 last_button = button; 1719 if(reset_tap) 1720 tap_count = 0; 1721 /* If there was some action, display drawing is still needed. 1722 This _might_ disturb audio on slow machines, but 1723 then, you could just stop pressing buttons, then;-) */ 1724 if(display_trigger) 1725 { 1726 display_trigger = false; 1727 draw_display(); 1728 } 1729 1730 /* This determines the accuracy of the metronome with SWCODEC ... the 1731 scheduler decides when we are allowed to play. */ 1732 rb->yield(); 1733 } 1734}