diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index fba165527d..3865fbf85e 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES @@ -134,13 +134,7 @@ wavrecord.c #endif /* PLATFORM_NATIVE */ - - -#if CONFIG_CODEC == SWCODEC || !defined(SIMULATOR) /* Not for hwcodec sims */ metronome.c -#endif - - #ifdef HAVE_LCD_BITMAP /* Not for the Archos Player */ diff --git a/apps/plugins/metronome.c b/apps/plugins/metronome.c index c519608372..e8014b7f9d 100644 --- a/apps/plugins/metronome.c +++ b/apps/plugins/metronome.c @@ -7,7 +7,7 @@ * \/ \/ \/ \/ \/ * $Id$ * - * Copyright (C) 2004 Matthias Wientapper + * Copyright (C) 2004 Matthias Wientapper, 2014-2015 Thomas Orgis * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -17,600 +17,68 @@ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * + * TODO: + * - Think about generating the sounds on startup with SWCODEC. ****************************************************************************/ #include "plugin.h" #include "lib/pluginlib_actions.h" #include "lib/pluginlib_exit.h" +#include "fixedpoint.h" +/* About time resolution: + 1000 means 1 ms resolution. It should get better with higher values + in theory, but in practice, too small timer intervals increase the + chance of being missed and make the metronome lag behind. Mean tempo + still works out with very small divider values (29 even) as long as + the rounding error compensation is active, although beat intervals + become jerky. You compromise between long-term accuracy and steadyness + from one beat to the next. + A drift you have to accept comes just from the audio clock itself, or even + from the difference between clocks in the device. The Sansa Clip+ has around + 0.04 % error in audio frequency using the "good" PLLB. I presume that the + difference between timing using PLLA and PLLB is at least that big. Something + up to 40 ms time difference over one minute when comparing to an external + reference or just the metronome plugin with playback of a prepared PCM track + is to be expected. -#if CONFIG_CODEC != SWCODEC -/* tick sound from a metronome */ -static unsigned char sound[] = { -255,251, 80,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 73,110,102,111, 0, 0, 0, 15, 0, 0, 0, 4, 0, 0, 4, 19, 0, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, -128,128,128,128,128,128,128,128,192,192,192,192,192,192,192,192,192,192,192,192, -192,192,192,192,192,192,192,192,192,192,192,192,192,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 0, - 58, 76, 65, 77, 69, 51, 46, 57, 50, 32, 1,137, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 64, 36, 5,191, 65, 0, 0, 0, 0, 0, 4, 19,168,187,153, 93, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,255,251, 80,196, 0, 0, 10, 81, 57, 65,184,120, -128, 1, 95,159,239,191,144, 96, 0, 0,128, 0, 0, 0, 0, 0, 0, 48, 24, 12, - 0, 0, 15,175,185,222, 39, 7,126, 46, 50,191,243,197,255,247, 62, 92,111,252, -115, 15, 27,140,153,159,247,242,124, 44, 92,164,177, 57,175,255,236, 79,164, 98, - 68,205, 69,160, 64, 15,251,127,128,168, 38, 92,138, 17, 67,196, 80,184,223,255, -255,161,117, 33, 55, 83,191,255,193,240, 33, 57,114, 17, 0, 2, 0, 0, 0, 10, -191, 10, 8,196,209, 75, 55,236,177,115,238,223,203, 61,176, 89, 78,101,219,118, -118, 65,154,126,187,239,241,127,247,245, 59, 18,219, 94,105,245,221,161,173, 91, -191, 27,255,247, 18,124, 71,117,139,133,170,221,227,251,135,110,236,255,183,219, -100, 78,184,125,212,131, 65, 95,212,245,145, 67, 77, 10,153,250,132,195, 4,138, -224, 0, 0, 0,158,107, 42, 65,227,185, 90,158, 86, 6,155, 77,255,251, 82,196, - 8, 0, 10,136,185,103, 4, 61, 48, 65,118,173, 44, 60,147, 10,152,107, 49, 74, - 18,208, 91, 23,178,196,220, 25, 64,233,230, 36,170, 0,210,219,131, 40,165, 22, - 86,195, 23,145, 33, 16,138, 99,109,117,245, 71,162, 69, 42,220,164, 91, 72,165, - 26, 69,146,150,199,222, 73,102,148, 29, 19, 5, 65, 86, 6,150,120,180, 26, 88, - 75, 18,191,255,250,171, 4, 8,132,140, 0, 0, 20,186,242,162, 66,100, 62, 86, -206, 86,255, 26,203,201,255,255,141,128,166,196,175,133, 9, 70,188,146,175,133, - 60, 17,217,229, 90, 27, 87, 93, 34, 76,113,185, 84,213, 56, 17,170, 83, 75,180, -203,116,101, 93, 90, 99, 35,174,230, 42,125, 12,128, 79, 93, 81,234, 67, 66,137, -105,157,157, 23, 71, 53, 40,250,204,105, 89,203,107,250, 63,174, 89,133, 81,140, - 0, 52, 17, 16, 0, 0, 18,111, 20, 92, 32,213, 48,179, 50, 26,244,179, 27,230, -154, 34,133,177, 88,255,251, 82,196, 13, 0, 10,125, 65, 85,244, 85, 0, 1,210, -172,231, 7, 31, 32, 0, 37, 11, 68, 69, 13, 37, 48,210, 23, 69, 36,122,143,148, -211,141, 44, 76,135, 72,148,195,135,174, 84,149,167, 30,198,183,255,213,111, 61, - 27,155,191,177,207,246,163,255,230, 30,137,219,255,182,186,185,239, 52,148,171, - 75, 63,167, 44, 0, 2, 81,190, 41,253,248,182,180, 23, 43,127,217,161, 41,191, - 36,199, 40,153,108, 66,224,131,192,217, 12, 67,217, 6,218,240,108,112, 63, 33, - 93, 12, 8, 43, 66, 42, 74, 12,215,135,100,172, 33, 65,172, 29, 98, 4, 83, 34, - 40, 17,111,133,255, 18,145, 60, 59,136,145, 92,106,144, 34,185, 58, 76,154,254, -146,144,115, 4, 84,180,142,178, 38, 79,253, 34,237,105, 31,106, 70, 73, 36,138, - 73,164,181,127,253,182, 82,217, 26,245,117,163,255,219, 50,115,223,245, 92,198, -165,173, 0, 15,249,132, 50, 19,157, 85,121,153,245, 51,255,251, 82,196, 6,131, - 74, 96,134,156, 92, 19, 0, 8, 0, 0, 52,128, 0, 0, 0, 60,226, 73, 57, 26, -249,253,122,211,128, 65, 86, 10, 1, 9,195,128, 36, 72,225,196,146,115, 73, 18, - 75, 65, 77, 9, 5,200, 43, 16,163,129, 77, 9, 5,200,110, 39,127,255,255,255, -255,255,255,255,252, 83, 66,142,140, 21,136, 46, 64,166,133, 28, 12, 21,136, 46, - 64,166,133, 21, 6, 76, 65, 77, 69, 51, 46, 57, 50, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85}; + Also, since playback on SWCODEC is not allowed to happen inside the timer + callback, there is a delay introduced by the main loop scheduling. This + could be compensated for by delaying the audio depending on a counter + incremented since the period elapsed in the callback, at the price of + putting the display out of sync. On a Clip+, the schedule delay isn't + biggest problem (drift for fine timer resolution is). + + All in all, 1 ms is too small, 2 ms seems to work fine ... + 4 ms might still be cool, too. +*/ +#if defined(SIMULATOR) +/* Simulator really wants 1024. Not 1000, not 512, only 1024. + Otherwise it is strangely slow. */ +static const unsigned int timerfreq_div = 1024; #else -static signed short sound[] = { - 1, -1, 1, -1, 0, 0, 0, 1, -1, 0, 0, - 0, -1, 2, -2, 2, -1, 0, 0, 0, 0, 1, - -1, 0, -1, 1, 0, 0, 0, 1, -1, 1, -2, - 1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 2, -2, 2, -1, 0, 1, -1, 1, - -1, 0, 0, 0, 0, 1, -2, 2, -2, 1, 0, - 1, -1, 0, 1, -1, 0, 1, -2, 2, -1, 0, - 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, - 0, -1, 1, -1, 2, -2, 2, -2, 2, -2, 1, - 0, 0, 0, 1, -2, 2, -2, 1, 0, 0, 0, - 0, 0, 0, -1, 1, 0, -1, 2, -2, 2, -1, - 0, 0, 0, -1, 1, -1, 1, -1, 2, -2, 1, - 0, -1, 2, -2, 2, -2, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 1, -1, 0, 0, -1, 1, 0, - 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, - 1, -2, 2, -1, 0, 0, 0, 0, 0, 1, -2, - 1, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, - 2, -2, 2, -2, 2, -1, 0, 0, -1, 1, -1, - 1, -1, 1, -1, 1, -1, 1, 0, 0, -1, 2, - -2, 1, 0, 0, 0, 0, 0, 1, -1, 0, 0, - -1, 1, 0, 0, 0, 0, 0, 0, 1, -2, 2, - -2, 2, -1, 1, -1, 1, -2, 2, -2, 2, -2, - 2, -2, 2, -2, 2, -1, 0, 0, 0, -1, 2, - -2, 2, -1, 1, -1, 1, -2, 2, -2, 1, 0, - 1, -1, 1, -2, 1, -1, 1, 0, 0, 0, 0, - 0, 0, 0, 0, -1, 1, 0, -1, 2, -1, 0, - 0, -1, 1, 0, -1, 2, -2, 1, 0, 0, 0, - 0, 0, 0, -1, 2, -1, 1, -1, 0, 0, 1, - -2, 2, -1, 1, -1, 0, 1, -1, 0, 0, 0, - 0, 0, 0, -1, 1, 0, 0, 0, 0, -1, 2, - -2, 2, -1, 0, 1, -1, 0, 0, 0, 0, 0, - 0, 0, 0, 1, -1, 1, -1, 0, 0, 0, 0, - 0, 1, -1, 1, -1, 0, 1, -2, 2, -1, 0, - 1, -2, 2, -2, 2, -2, 2, -1, 0, 1, -1, - 0, 1, -1, 0, 0, 0, 0, 0, 0, 1, -2, - 2, -2, 1, 0, -1, 2, -2, 1, 0, 0, 0, - 0, -1, 1, 0, 0, 1, -1, 0, 0, 0, 0, - 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, - -1, 1, 0, 0, 0, 0, 0, 0, -1, 2, -1, - 0, 0, 0, 0, 1, -1, 0, 0, 1, -2, 2, - -1, 0, 0, 0, 0, -1, 1, 0, 0, -1, 2, - -2, 1, 0, -1, 1, -1, 2, -2, 2, -2, 2, - -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 1, 0, 1, -2, - 2, -1, 0, 1, -1, 0, 0, 0, 0, 0, 0, - -1, 2, -2, 2, -2, 2, -1, 0, 0, 0, -1, - 1, 0, -1, 1, 0, 0, 0, 0, 0, 0, 1, - -1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, - 1, -2, 2, -2, 1, 0, 0, 0, 0, 0, 0, - 0, 1, -1, 0, 1, -1, 1, -1, 0, -1, 2, - -1, 0, 0, 0, -1, 1, -1, 1, 0, 1, -1, - 1, -2, 1, 0, 0, 1, -2, 2, -2, 2, -2, - 2, -2, 2, -1, 0, 0, 0, 0, 0, -1, 2, - -2, 2, -1, 0, 0, 0, 1, -1, 0, 0, 0, - 0, -1, 1, -1, 1, 0, 0, 0, 1, -2, 1, - 0, -1, 2, -2, 1, -1, 0, 2, -2, 2, 0, - -1, 0, 0, 0, -1, 2, -2, 2, -2, 2, -2, - 2, -1, 0, 1, -2, 2, -1, 0, 0, 0, 0, - 1, -1, 0, 0, 0, 0, 0, 0, 0, 1, -2, - 1, 0, 0, 0, 0, 0, 0, -1, 1, -1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, -1, - 2, -2, 1, 0, 0, 0, 0, 0, -1, 2, -2, - 2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -1, 2, -1, 0, 0, -1, 1, 0, - 0, 0, 0, 0, 1, -1, 0, 0, -1, 1, 0, - 0, 0, 0, -1, 1, 0, -1, 2, -1, 0, 0, - 0, 1, -2, 2, -1, 0, 0, 0, -1, 1, -1, - 1, 0, 0, 0, 0, 0, 0, 1, -1, 1, -1, - 0, 0, -1, 2, -2, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 1, -1, 1, 0, - -1, 2, -2, 1, 1, -1, 0, 0, -1, 1, 0, - 0, 0, 1, -2, 2, -2, 1, 0, 1, -2, 2, - -1, 0, 0, 0, -1, 2, -1, 0, 0, 0, 0, - 0, 0, 0, 0, -1, 2, -2, 2, -1, 0, 0, - 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -1, 2, -2, 2, -1, 0, 1, - -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, -2, - 2, -1, 0, 0, 0, -1, 2, -2, 2, -2, 1, - 0, -1, 1, 0, -1, 1, 0, 0, 0, 0, 0, - -1, 1, -1, 2, -2, 2, -1, 1, -1, 0, 0, - 0, 0, 1, -1, 0, 0, 0, 0, 1, -2, 2, - -2, 1, 1, -1, 1, -1, 1, -2, 2, -2, 1, - -1, 2, -2, 1, 0, 0, 0, 0, 0, -1, 2, - -2, 2, -1, -1, 1, -1, 1, -1, 2, -2, 2, - -1, 0, 0, 1, -2, 2, -2, 1, 0, 0, 0, - 0, 1, -2, 1, -1, 1, -1, 1, 0, 0, 0, - 0, 0, -1, 1, 0, 0, 0, -1, 1, 0, 0, - 1, -2, 2, -2, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, -1, 1, -2, 1, 0, 0, - 0, 0, 0, 0, -1, 1, 0, 0, 0, -1, 1, - 0, 0, 0, 0, 0, 0, 1, -2, 2, -1, 0, - 0, 0, 0, 0, 0, 1, -2, 2, -1, 1, -1, - 0, 0, 0, 1, -1, 0, 0, -1, 2, -1, 0, - 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 1, - -1, 0, 0, 0, 0, 0, 0, -1, 2, -2, 2, - -1, 1, -1, 0, 0, -1, 2, -1, 1, -1, 1, - -2, 2, -2, 2, -2, 2, -1, 0, 0, 0, 0, - 0, 0, 0, 0, 1, -1, 0, 0, 1, -2, 2, - -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1, 1, 0, 0, 0, -1, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -1, 2, -2, 2, -1, 0, 1, - -2, 1, 0, 0, 1, -2, 2, -2, 2, -1, -1, - 2, -2, 1, 0, 0, 0, 1, -2, 2, -1, 0, - 0, 0, 0, 0, 0, 0, -1, 1, -1, 2, -1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 2, - -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, - 1, 0, 0, 1, -1, 1, -1, 0, 0, -1, 2, - -2, 2, -1, 0, 0, 0, 1, -1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, - 0, -1, 2, -2, 1, 0, -1, 1, 0, 0, 1, - -1, 0, 0, -1, 2, -2, 1, 0, -1, 2, -1, - 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, - 1, -2, 2, -2, 1, 0, 0, 0, 0, -1, 1, - 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, - -1, 1, 0, 0, 0, 1, -1, 0, 0, 0, 0, - 1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 2, - -2, 1, 0, 0, 0, -1, 2, -2, 1, 0, 0, - 1, -2, 2, -1, 0, 1, -1, 0, 0, 0, -1, - 1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -1, 1, 0, -1, 2, -2, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -1, 2, -2, - 1, -1, 1, -1, 2, -2, 1, 0, -1, 2, -2, - 2, -1, 0, 0, 0, -1, 1, 0, 0, 0, 1, - -2, 2, -2, 2, -2, 1, 0, 0, 0, 0, 1, - -1, 1, -1, 0, 0, 0, 0, 0, 0, 1, -1, - 0, 0, 0, 0, 1, -1, 0, 0, 0, -1, 2, - -2, 2, -1, 0, 1, -2, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -1, 2, -2, - 2, -2, 1, 0, 0, 0, 0, 0, 0, -1, 2, - -2, 2, -1, 0, 1, -1, 0, 0, 0, 0, 0, - 0, 1, -1, 0, 1, -2, 1, 0, -1, 1, 0, - -1, 1, 0, 0, 0, 0, 1, -1, 0, 0, 0, - 0, 0, -1, 2, -2, 2, -2, 2, -2, 1, 0, - 0, 0, 0, 1, -2, 2, -2, 2, -1, 0, 1, - -2, 2, -2, 1, 0, 0, 0, 1, -1, 0, 0, - -1, 1, 0, 0, 0, 0, -1, 2, -2, 2, -1, - 0, 0, 0, -1, 2, -1, 0, 1, -1, 0, 0, - 0, 0, 1, -2, 2, -1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, - 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -1, 1, 0, 0, -1, 1, -1, 2, - -2, 2, -2, 2, -1, 0, 0, -1, 1, -1, 1, - 0, -1, 2, -2, 2, -1, 0, 0, 0, 0, 0, - 0, 0, 1, -2, 2, -2, 1, 0, 0, 0, -1, - 2, -2, 1, 0, 1, -1, 0, 0, 1, -1, 1, - -2, 1, 0, 0, 0, -1, 1, -1, 2, -2, 2, - -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, -2, 2, -1, 0, 1, -2, 2, -1, 0, 0, - 0, 0, 1, -1, 1, -1, 0, -1, 2, -2, 2, - -2, 2, -1, 0, 0, 0, 0, 0, 0, 0, 1, - -1, 0, 0, 0, -1, 2, -2, 1, 1, -2, 2, - -1, 0, 1, -2, 1, 0, 0, 0, 0, 1, -1, - 0, 1, -1, 0, 0, -1, 2, -2, 2, -2, 2, - -2, 2, -2, 2, -2, 2, -2, 2, -1, 1, -1, - 1, -1, 1, 0, -1, 1, -1, 1, 0, 0, -1, - 0, 1, 0, 1, -2, 2, -2, 1, 1, -2, 1, - 0, 0, 0, 0, 0, 0, 0, -1, 2, -1, 0, - 0, -1, 1, 0, 0, 0, -1, 0, 1, 0, 1, - -2, 0, -1, 1, 0, 1, 0, -1, 0, 0, 1, - -1, 1, -2, 1, 1, -1, 1, -1, -1, 0, 1, - 0, 1, -1, 0, -1, 0, 1, 1, -2, 1, -1, - 1, 1, 0, -1, 0, 0, 1, 1, 1, -1, 0, - -1, 0, 1, -1, 1, -2, 2, 0, 0, 1, -2, - -1, 0, 0, 1, -1, 0, -1, 1, 0, 0, 0, - 0, 0, 0, 0, -1, 1, -1, 1, 0, 2, 1, - -1, 0, 0, 0, 1, 1, 1, -1, 1, 1, 0, - 1, -2, 1, -1, 2, 2, 0, -1, -1, -1, 0, - 1, -1, 1, -1, 1, 1, 1, 1, -3, 0, 3, - 0, 0, -4, -2, 4, 5, 4, -3, -1, 1, -3, - -2, -5, -6, -1, 5, 2, 1, -3, -2, -5, 1, - -4, -5, 3, 5, 0, 1, 2, 0, -5, -1, 3, - 5, 2, 1, 1, 6, 5, 3, -1, 0, 2, 5, - 10, 8, 4, 2, -5, -5, 3, 11, 8, -4, -8, - -2, 2, -1, -1, 5, -6, -12, -11, -5, -9, -5, - 10, 6, 3, -4, -3, -9, -8, -18, -9, 5, 13, - 7, 13, 29, 17, -1, -1, 15, 21, 15, -9, -29, - -15, 10, 10, -15, -31, -48, -49, -30, -7, -1, -8, - -6, 15, 39, 43, 24, 16, 27, 28, 9, -16, -6, - 34, 60, 41, 15, 11, 26, 14, -28, -77, -83, -60, - -32, 1, 10, -11, -59, -83, -49, 27, 93, 82, 11, - -27, -8, 9, 1, 12, 22, 6, -22, -15, 4, 8, - -19, -23, 49, 143, 139, 39, -31, -56, -101, -145, -102, - -10, 20, -61, -196, -258, -136, 70, 172, 112, 43, 55, - 75, 12, -69, -33, 89, 114, -26, -137, -14, 239, 335, - 202, 68, 115, 231, 169, -131, -459, -540, -338, -72, 43, - 20, -53, -174, -290, -195, 192, 593, 628, 322, 95, 159, - 264, 163, -50, -202, -229, -114, 18, -31, -212, -264, -36, - 432, 807, 619, -52, -483, -452, -414, -404, -98, 228, -3, - -760, -1444, -1414, -458, 624, 732, 35, -209, 476, 1113, 586, - -785, -1405, -480, 753, 881, 280, 81, 441, 753, 687, 711, - 1440, 2140, 1110, -1470, -2963, -1770, 607, 1427, -399, -3146, -3899, - -2064, 28, 715, 874, 1442, 1606, 394, -1483, -2014, -354, 1531, - 1156, -984, -2108, -821, 1635, 3003, 2087, 186, -155, 1569, 3328, - 3463, 2110, 9, -2200, -3876, -4298, -2871, -266, 1039, -393, -2357, - -1809, 1079, 4019, 5685, 5742, 4435, 3098, 2963, 3181, 2018, -691, - -3919, -6922, -9001, -8935, -6374, -3215, -1862, -2089, -1508, 731, 3186, - 4763, 5160, 3629, 706, -712, 739, 2391, 1570, -1015, -3502, -4979, - -4798, -2615, 420, 2178, 1457, -602, -1287, 741, 3741, 5018, 3687, - 934, -757, 497, 3094, 3163, 113, -2188, -1194, 911, 998, -254, - 484, 3643, 4907, 1023, -4718, -6191, -1911, 3621, 4508, -687, -6491, - -6309, -1015, 3007, 3184, 1911, 471, -1763, -4048, -4414, -2046, 1179, - 1513, -1919, -4522, -2259, 2368, 4547, 3613, 2320, 2847, 5035, 6432, - 4390, -835, -5857, -7419, -5497, -2768, -1012, -27, -294, -2444, -3889, - -1911, 942, 1212, 859, 2879, 5141, 4107, 108, -3768, -4853, -2787, - -162, 142, -1594, -2490, -498, 3349, 5670, 4368, 1089, -1548, -3118, - -3936, -3319, -1583, -547, -360, 985, 3125, 2273, -1728, -2291, 4071, - 10390, 9283, 3620, 79, -90, 1293, 1968, -2030,-10963,-16320,-10631, - 1236, 8206, 6740, 2418, 1132, 3007, 3504, -1371, -8877, -9321, 2657, - 17866, 22245, 14739, 4801, -2737, -7071, -2808, 12289, 25609, 19526, -6479, --30563,-29780, -6434, 13879, 13263, 83, -8239, -7874, -6445, -8032, -9180, - -7691, -7914,-12368,-13982, -7090, -1018, -8154,-21862,-22142, -3867, 14327, - 14436, 1712, -5853, -2462, 3311, 4605, 1731, -3832,-11191,-17673,-17400, - -4049, 17643, 27851, 14373, -7582,-15759, -9573, -1277, 5996, 13903, 17168, - 11276, 1603, -4763, -7550, -7537, -2186, 6709, 10980, 6990, -1127, -9765, --16805,-19102,-18420,-18687,-13775, 3373, 21405, 23456, 12651, 3319, -1287, - -4637, -3954, 3883, 11849, 8344, -6853,-17292, -7204, 16901, 31089, 21726, - 1084, -7875, 1459, 15092, 20527, 18496, 10594, -3296,-12835, -6081, 9842, - 15942, 3977,-16959,-26888,-12200, 13260, 20645, 6239, -5950, -2526, 6054, - 8073, 3123, -4656,-11949,-15611,-12153, -2236, 4314, -2887,-19936,-30928, --23846, -1429, 17759, 15264, -1868, -7505, 5991, 19737, 18946, 8185, -600, - 44, 6127, 5321, -4750,-11829, -8743, -1330, 3689, 3252, -3513,-11859, --14753,-10198, 72, 10949, 13370, 5735, -564, 2639, 9903, 13145, 11045, - 6754, 3123, -724, -6600,-10509, -8340, -6244,-12133,-21055,-20385, -5186, - 15105, 23034, 11762, -3750, -5737, 2612, 6060, 33, -7014, -4975, 7697, - 18684, 12606, -7934,-23083,-20429, -7355, 2345, 4875, 7094, 14569, 22636, - 22509, 13749, 4800, 2246, 4805, 7497, 7404, 4042, -3207,-13334,-19292, --12274, 5051, 15820, 7212,-12051,-20991,-11633, 3886, 11417, 10491, 8967, - 9849, 9995, 8305, 7497, 7731, 5549, -49, -6582,-12286,-16545,-19489, --22478,-23536,-16116, -123, 14039, 19014, 16964, 11024, 3746, 1174, 5696, - 10510, 9283, 3833, -1113, -4247, -7485,-11448,-12665, -9329, -7052,-10656, --14627,-10081, 3317, 16454, 18316, 6990, -6264,-10409, -7182, -2463, 3812, - 10794, 12717, 7460, 215, -2353, 676, 983, -9207,-21161,-17629, 361, - 11731, 2863,-15895,-22726, -8619, 11663, 17157, 7331, -255, 4522, 15016, - 20742, 18465, 12205, 6509, 836, -6050,-10016, -8310, -6482, -9596,-13628, --12443, -6667, -1745, -487, 633, 6363, 14319, 17428, 14246, 9598, 6752, - 5527, 5289, 5673, 6272, 5900, 2123, -5034,-10908,-12352,-12153,-13371, --14974,-15335,-14089, -9874, -1589, 8285, 14571, 13761, 7383, 1668, 1519, - 4509, 3987, -1719, -7872,-10985,-12263,-12864,-11713, -9423, -8944,-10937, --12477,-11078, -6884, -1052, 5798, 13303, 20195, 23473, 20387, 12863, 7217, - 6080, 4059, -3737,-13190,-17239,-15342,-11071, -5970, -543, 4259, 7968, - 8781, 4097, -3427, -7041, -5374, -2595, 70, 4218, 8042, 8534, 7403, - 8758, 12712, 15141, 12739, 6198, -414, -2420, 331, 780, -7211,-18274, --21587,-15771, -7472, 733, 9880, 17443, 19723, 16661, 10520, 4467, 1343, - 308, -1550, -3368, -1921, 1564, 1426, -5086,-13434,-16483,-12675, -6499, - -2040, -586, -2374, -5424, -5786, -2131, 3305, 7892, 9432, 7024, 3000, - 410, -274, 396, 1514, 785, -2873, -7609,-11931,-15458,-16897,-15275, --10823, -3469, 5396, 11785, 13505, 11686, 7478, 2801, 1972, 6978, 13591, - 14815, 7016, -6127,-15851,-17122,-13183, -9425, -7273, -5029, -1087, 3485, - 5516, 4834, 5156, 7648, 9472, 9387, 8481, 7313, 6847, 7922, 8488, - 6309, 2375, -1821, -6179, -9633,-10798,-10521,-10565,-11165,-11055, -8661, - -3781, 1960, 6819, 9680, 9920, 8944, 9396, 10975, 10715, 7182, 861, - -7005,-13267,-15283,-15034,-15703,-15867,-12193, -5329, 829, 3996, 5377, - 7152, 9312, 10386, 10275, 10167, 10500, 10694, 9601, 6318, 2012, -1381, - -4917,-10834,-17053,-18962,-15907,-11261, -7518, -4754, -2399, -32, 2969, - 6930, 10871, 13043, 13087, 12045, 10546, 9003, 8103, 6739, 2241, -5153, --11768,-15213,-15636,-13473, -9655, -6045, -3220, -430, 2055, 3835, 6558, - 11429, 15904, 16225, 12337, 7477, 3631, -122, -4854, -9898,-13734,-15118, --13861,-11287, -8854, -6458, -3768, -1724, -385, 2105, 5993, 8742, 9121, - 8765, 8415, 6764, 3536, 104, -2912, -5635, -7580, -8217, -7502, -5362, - -2617, -1366, -2262, -3363, -3163, -2137, -589, 1870, 4595, 6301, 6764, - 6718, 6520, 5842, 4638, 3882, 4279, 4700, 3357, 183, -2935, -3952, - -2906, -2493, -4469, -6460, -5616, -2932, -231, 3057, 6959, 9364, 9069, - 6831, 4078, 2556, 2602, 2068, -153, -1834, -1310, -248, -795, -2717, - -4126, -3995, -3695, -4963, -6850, -7066, -5258, -2772, -846, 139, 1073, - 2821, 4490, 5430, 6971, 8941, 8259, 3626, -2713, -8358,-12049,-13228, --12856,-12123,-10333, -7012, -3862, -1844, 527, 4263, 8105, 10304, 10453, - 9346, 7786, 5793, 3181, 40, -3553, -7164, -9520, -9740, -8339, -6135, - -3335, 16, 3345, 5455, 5356, 3793, 2943, 3715, 4965, 5638, 6024, - 6657, 7270, 6829, 4385, 593, -2392, -3644, -4633, -6185, -6575, -4682, - -2249, -1081, -648, 222, 1873, 4273, 6609, 7328, 6269, 5017, 4332, - 3500, 2200, 704, -1135, -3367, -5373, -6705, -7346, -7055, -5618, -3596, - -1716, 117, 2133, 3576, 3514, 2437, 1568, 1147, 588, -490, -1976, - -3125, -2983, -1979, -1775, -2637, -2993, -2327, -2013, -2843, -4077, -4841, - -4778, -3915, -2756, -1663, -78, 2401, 4777, 5910, 6074, 5858, 4886, - 2889, 688, -970, -2010, -2413, -2357, -2511, -3033, -3218, -2983, -2783, - -2022, 315, 3490, 5687, 6228, 5642, 4405, 3006, 2065, 1656, 1592, - 2141, 3191, 3485, 2147, -131, -2437, -4663, -6289, -6118, -3991, -1098, - 1550, 3446, 4204, 4186, 4379, 4801, 4654, 3956, 3267, 2297, 512, - -1660, -3571, -5057, -5713, -5051, -3695, -2719, -2075, -1180, -306, 43, - 201, 527, 896, 1415, 2085, 2103, 1018, -171, -613, -825, -1316, - -1701, -1787, -1766, -1462, -922, -997, -1987, -2857, -2699, -1736, -514, - 484, 696, 221, 24, 316, 48, -973, -1304, -49, 1921, 3426, - 4026, 3875, 3529, 3327, 2659, 1002, -723, -1568, -2055, -2862, -3247, - -2368, -873, 62, 184, 58, 315, 1196, 2204, 2563, 2494, 2945, - 3730, 3479, 1991, 500, -527, -1710, -3069, -4146, -4921, -5126, -4168, - -2410, -881, 287, 1399, 2210, 2737, 3559, 4435, 4390, 3402, 2338, - 1278, -271, -1954, -2896, -3007, -2752, -2482, -2724, -3874, -5145, -5390, - -4613, -3122, -402, 3217, 5859, 6536, 6136, 5381, 4239, 3021, 1905, - 465, -1127, -2074, -2588, -3532, -4652, -5131, -4876, -4054, -2586, -848, - 525, 1727, 3291, 4715, 5094, 4595, 3990, 3426, 2642, 1618, 196, - -1676, -3238, -3809, -3789, -3482, -2326, -697, -239, -1207, -1820, -939, - 863, 2740, 4260, 5221, 5856, 6299, 5671, 3229, -23, -2465, -3892, - -4948, -5454, -5047, -4443, -4355, -4055, -2592, -469, 1194, 2038, 2285, - 2563, 3653, 5162, 5484, 4235, 2697, 1473, 27, -1754, -3674, -5673, - -6983, -6577, -4808, -2747, -690, 1257, 2527, 3071, 3338, 3313, 2895, - 2726, 3203, 3522, 2793, 1295, -325, -2074, -3850, -4855, -4744, -4000, - -2801, -1095, 473, 1418, 2150, 2712, 2651, 2407, 2619, 2775, 2513, - 2523, 2737, 2113, 659, -598, -1376, -2019, -2413, -2377, -2143, -1792, - -1119, -403, -404, -963, -894, 215, 1579, 2770, 3868, 4081, 2660, - 398, -1501, -2862, -3573, -3200, -2109, -1097, -276, 295, 45, -1024, - -1953, -2120, -1736, -971, 274, 1597, 2369, 2667, 2840, 2417, 947, - -823, -1912, -2224, -1940, -1203, -452, 127, 811, 1272, 788, -366, - -1342, -1806, -1746, -1161, -266, 928, 2469, 3661, 3707, 2956, 2179, - 1379, 340, -690, -1418, -1852, -2028, -1928, -1591, -1202, -864, -267, - 806, 1949, 2658, 2868, 2653, 2202, 1866, 1534, 768, -230, -1027, - -1800, -2455, -2301, -1394, -707, -605, -610, -403, -39, 282, 371, - 423, 917, 1881, 2543, 1980, 235, -1335, -1767, -1786, -2298, -2787, - -2689, -2421, -2133, -1460, -694, -214, 424, 1435, 2307, 2819, 3041, - 2652, 1573, 324, -754, -1729, -2520, -2956, -2933, -2321, -1260, -306, - 165, 305, 416, 646, 985, 1362, 1745, 2076, 2245, 2234, 1930, - 1150, -10, -1337, -2785, -3969, -4138, -3350, -2371, -1256, 303, 1810, - 2722, 3265, 3605, 3559, 3246, 2772, 1942, 766, -553, -1923, -2939, - -3124, -2592, -1721, -657, 340, 1033, 1514, 1616, 1076, 417, 322, - 591, 787, 929, 1058, 1046, 827, 255, -548, -1069, -1232, -1508, - -1928, -2066, -1828, -1384, -836, -313, 165, 570, 710, 593, 549, - 566, 338, -42, -215, -86, 93, -71, -692, -1242, -1361, -1405, - -1612, -1705, -1546, -1012, 64, 1202, 1774, 2110, 2444, 2028, 747, - -280, -586, -712, -687, -214, 222, 21, -651, -1402, -2075, -2301, - -1607, -374, 420, 528, 623, 906, 895, 646, 748, 1155, 1401, - 1471, 1569, 1443, 829, -102, -1009, -1730, -2195, -2295, -1957, -1121, - 235, 1663, 2296, 1932, 1429, 1359, 1289, 1045, 1074, 1308, 1229, - 771, 13, -1126, -2275, -2863, -2931, -2658, -1849, -660, 316, 931, - 1418, 1586, 1154, 592, 633, 1166, 1428, 1169, 759, 275, -489, - -1425, -2208, -2714, -2705, -2029, -1090, -367, 236, 886, 1413, 1728, - 1903, 1867, 1576, 1097, 393, -463, -1157, -1465, -1417, -1112, -615, - 82, 923, 1390, 889, -291, -1250, -1686, -1756, -1338, -411, 577, - 1291, 1751, 1854, 1480, 897, 393, -43, -439, -733, -924, -979, - -751, -354, -58, 122, 314, 418, 311, 171, 225, 428, 678, - 1000, 1304, 1263, 748, 37, -586, -1042, -1237, -1070, -664, -243, - 97, 262, 167, -128, -402, -445, -184, 202, 446, 534, 519, - 323, -11, -258, -385, -468, -463, -350, -191, -36, -2, -163, - -207, 82, 406, 588, 861, 1087, 900, 461, 73, -396, -872, - -917, -514, -44, 332, 667, 771, 490, -59, -620, -1123, -1495, - -1448, -811, 63, 751, 1214, 1446, 1336, 1005, 611, 60, -531, - -828, -837, -740, -478, -139, -25, -63, 30, 245, 481, 790, - 1033, 1002, 750, 462, 140, -197, -433, -516, -516, -578, -715, - -818, -821, -742, -548, -228, 77, 233, 247, 183, 100, 60, - 91, 155, 208, 257, 275, 154, -136, -387, -429, -428, -486, - -396, -72, 259, 435, 450, 397, 400, 373, 153, -57, 23, - 181, 231, 390, 496, 87, -627, -1036, -1047, -785, -216, 465, - 823, 761, 501, 269, 197, 282, 395, 502, 597, 684, 687, - 440, -91, -581, -803, -853, -677, -155, 367, 520, 472, 351, - -35, -523, -708, -585, -312, 103, 471, 530, 378, 226, 51, - -164, -377, -542, -582, -404, -134, 42, 91, 4, -205, -400, - -488, -528, -548, -453, -157, 305, 794, 1106, 1134, 866, 307, - -368, -839, -979, -916, -721, -436, -226, -164, -84, 26, 32, - 27, 249, 614, 889, 1016, 1036, 931, 663, 248, -235, -632, - -864, -967, -997, -965, -800, -394, 150, 614, 919, 1096, 1049, - 791, 514, 271, 19, -107, -93, -145, -295, -384, -365, -257, - -96, -26, -115, -232, -332, -437, -400, -167, 106, 387, 655, - 726, 536, 231, -134, -519, -793, -961, -1068, -1019, -800, -555, - -275, 62, 333, 543, 777, 937, 940, 888, 784, 519, 133, - -278, -630, -849, -905, -836, -598, -266, -41, 129, 370, 501, - 401, 294, 265, 159, 100, 253, 410, 336, 166, 11, -162, - -313, -295, -159, -70, -82, -123, -159, -195, -141, 128, 547, - 900, 1123, 1218, 1047, 565, -14, -513, -944, -1193, -1088, -735, - -411, -189, -17, 62, 33, 33, 114, 218, 335, 449, 434, - 244, -53, -414, -720, -786, -594, -314, -119, -107, -289, -515, - -670, -755, -661, -218, 419, 945, 1257, 1343, 1140, 688, 146, - -364, -747, -941, -997, -923, -669, -334, -74, 97, 267, 439, - 594, 715, 741, 715, 739, 823, 817, 615, 225, -241, -642, - -911, -1033, -958, -683, -356, -53, 232, 432, 478, 491, 616, - 782, 862, 863, 794, 586, 230, -181, -534, -750, -738, -528, - -311, -238, -262, -256, -227, -207, -107, 83, 179, 121, 79, - 115, 135, 168, 205, 147, 48, 78, 104, -77, -367, -617, - -883, -1084, -1016, -718, -373, -15, 361, 660, 801, 781, 677, - 554, 320, -73, -437, -617, -681, -645, -434, -130, 113, 293, - 396, 325, 127, -74, -166, -76, 183, 416, 509, 518, 451, - 293, 114, -37, -135, -139, -66, 9, 69, 133, 172, 213, - 302, 407, 464, 465, 362, 169, -59, -340, -635, -779, -688, - -447, -84, 362, 661, 681, 514, 221, -144, -386, -357, -167, - 107, 375, 463, 237, -179, -650, -1045, -1222, -1130, -842, -392, - 138, 538, 675, 607, 418, 190, 41, -18, -35, -35, -32, - -96, -207, -325, -456, -537, -470, -334, -214, -45, 183, 298, - 318, 354, 397, 377, 383, 478, 558, 567, 484, 302, 21, - -283, -518, -634, -630, -538, -323, -11, 257, 390, 440, 384, - 210, 120, 251, 418, 464, 415, 286, 41, -216, -388, -514, - -519, -335, -65, 96, 139, 108, -19, -217, -360, -319, -84, - 209, 472, 622, 599, 404, 185, 16, -167, -362, -491, -580, - -659, -617, -457, -316, -190, 29, 245, 336, 321, 250, 116, - 2, -41, -39, 27, 143, 200, 119, -28, -153, -219, -211, - -152, -101, -31, 29, 24, -42, -109, -150, -121, -8, 81, - 114, 185, 282, 308, 280, 243, 149, 11, -54, -87, -184, - -283, -303, -254, -123, 83, 232, 239, 165, 62, -49, -140, - -173, -148, -67, 24, 67, 84, 92, 54, -41, -121, -154, - -114, -23, 33, -42, -166, -268, -347, -412, -399, -276, -56, - 203, 449, 635, 747, 724, 565, 367, 166, -64, -263, -360, - -406, -447, -446, -403, -362, -295, -156, -16, 98, 230, 381, - 493, 512, 456, 390, 345, 296, 223, 156, 56, -121, -320, - -500, -665, -754, -680, -487, -234, 79, 378, 518, 528, 469, - 319, 127, 35, 48, 65, 106, 170, 121, -91, -334, -506, - -625, -686, -636, -473, -258, -40, 168, 349, 443, 477, 509, - 514, 432, 311, 186, -4, -269, -460, -541, -600, -629, -558, - -432, -326, -227, -105, 34, 209, 394, 534, 582, 577, 524, - 403, 246, 118, 23, -71, -157, -166, -96, -30, -27, -54, - -75, -74, -38, -12, -25, -9, 103, 245, 354, 449, 504, - 459, 321, 148, -52, -248, -357, -383, -369, -327, -281, -274, - -281, -215, -56, 146, 351, 547, 692, 699, 525, 253, 5, - -185, -301, -328, -280, -255, -260, -282, -372, -505, -535, -391, - -184, 26, 233, 392, 410, 313, 173, 39, -67, -108, -93, - -70, -85, -151, -261, -381, -475, -495, -443, -313, -91, 211, - 503, 688, 732, 648, 464, 220, -12, -159, -211, -226, -273, - -324, -329, -267, -147, -8, 120, 253, 422, 558, 570, 491, - 394, 269, 115, 6, -26, -46, -102, -183, -263, -295, -279, - -200, -55, 104, 181, 191, 229, 264, 234, 170, 120, 23, - -99, -169, -217, -323, -368, -285, -173, -113, -33, 59, 81, - 15, -85, -169, -191, -127, 0, 127, 178, 111, -6, -94, - -130, -110, -20, 82, 87, 38, 1, -73, -175, -203, -108, - 24, 142, 243, 255, 154, 20, -64, -99, -88, -26, 73, - 178, 230, 191, 70, -70, -165, -187, -142, -52, 49, 163, - 267, 320, 304, 230, 146, 70, 6, -38, -84, -144, -224, - -289, -349, -368, -291, -88, 163, 372, 491, 466, 307, 89, - -105, -254, -332, -311, -217, -111, -19, -4, -66, -132, -161, - -159, -125, -50, -13, -36, -42, 14, 105, 212, 311, 353, - 331, 264, 120, -101, -320, -487, -564, -501, -331, -168, -22, - 130, 249, 281, 288, 283, 239, 225, 267, 268, 198, 126, - 28, -139, -302, -389, -442, -438, -302, -96, 102, 291, 438, - 476, 423, 334, 223, 106, 14, -82, -191, -290, -397, -494, - -518, -425, -238, -23, 164, 270, 324, 355, 319, 215, 89, - -27, -147, -236, -288, -347, -395, -360, -243, -125, -43, 25, - 75, 85, 82, 119, 160, 166, 148, 130, 82, 8, -29, - -63, -124, -173, -166, -121, -63, 16, 87, 163, 235, 250, - 217, 191, 187, 142, 76, 12, -71, -137, -169, -189, -183, - -106, 8, 87, 134, 154, 99, 45, 84, 178, 241, 277, - 270, 209, 125, 50, -62, -190, -254, -235, -179, -106, -18, - 33, 46, 32, 9, -22, -35, -13, 22, 64, 78, 29, - -63, -133, -169, -189, -166, -121, -98, -67, -3, 15, 5, - 44, 100, 108, 108, 114, 64, -46, -141, -245, -316, -233, - -59, 21, -10, -20, -6, -7, -6, 7, -3, -2, 9, - -2, -25, -17, -1, 1, -8, -1, -5, -11, -13, -10, - -14, -12, -3, 11, 6, 2, 1, -9, -13, 0, 11, - 12, 16, 17, 9, -4, -9, -13, -11, 1, 7, 2, - 13, 13, -3, 0, 10, 9, 3, 6, 4, -4, -9, - -7, -2, 6, 5, -14, -19, -9, -11, -10, -5, -16, - -22, -4, 17, 16, 1, -14, -17, -6, 6, 3, -2, - -5, -10, -11, -1, -2, -12, -12, -4, 9, 14, 15, - 6, 9, 13, 7, -6, -5, 5, 3, -6, -10, -14, - -11, -4, 4, 3, -1, 3, -1, -12, -13, 2, 9, - -1, -7, -1, 1, 1, 12, 7, 2, -1, 3, 3, - 7, 7, 3, -1, 4, 8, 3, 6, 6, 2, -3, - -2, -5, -6, 1, -2, -6, -9, -10, -7, -5, 3, - -4, -10, -7, 5, 7, 1, 0, 0, -8, -7, -5, - -1, 2, 4, 6, -1, -2, 5, 5, 0, -1, 0, - 1, -8, -8, -12, -9, -4, -2, -3, -4, -1, 2, - 3, 3, -3, -4, -5, 3, 6, -1, -5, -14, -13, - -12, -13, -11, 0, 9, 13, 10, 9, 7, 1, 1, - -2, 1, 3, 3, 2, 0, -2, 0, 0, 3, 1, - 4, 2, 4, 0, 1, -1, -1, -1, 0, -2, -2, - -1, -2, 2, -1, 1, 0, 1, 2, 2, 1, 1, - 1, 0, -1, -1, 0, -1, 1, -2, 2, 0, 1, - 0, -1, -1, -1, 1, 0, 0, -1, -2, -2, -1, - -2, -1, 2, 1, 3, 0, 3, 0, -1, 1, -1, - 1, 0, 1, 0, -1, 1, -2, 2, -1, 1, 0, - 1, 0, 0, 0, 0, 0, -1, 1, -2, 1, -1, - 1, 0, 0, 0, 0, 0, 0, 1, -1, 1, 0, - 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, - 0, 0, 1, 0, 0, 0, -1, 0, -1, 1, -1, - 1, 0, -1, 2, -1, 1, -1, 1, -1, 0, 1, - -1, 0, 1, -1, 2, -2, 1, -1, 1, -1, 0, - 1, -1, 1, 0, -1, 1, 0, -1, 1, -1, 0, - 1, -1, 1, 0, -1, 1, -1, 0, 0, 1, -1, - 1, -1, 1, 0, -1, 1, -1, 1, 0, -1, 1, - -1, 1, -1, 0, 1, -1, 1, -1, 1, -2, 2, - -1, 0, 1, -1, 0, 1, -1, 1, 0, 0, 0, - 0, 0, 0, -1, 1, -1, 1, -1, 1, -1, 1, - -1, 1, -1, 0, 1, -2, 2, -1, 0, 0, 1, - -1, 1, 0, -1, 0, 0, 1, -2, 2, -1, 0, - 1, -1, 0, 1, -1, 1, -1, 1, -1, 1, -1, - 1, -1, 0, 1, -1, 1, 0, -1, 0, 0, 1, - -1, 0, 0, 1, -1, 0, 0, 0, 1, -1, 1, - -1, 0, 1, -1, 1, -1, 0, 0, 0, 1, -1, - 1, -1, 1, -1, 1, 0, 0, 0, -1, 0, 1, - -1, 1, -1, 0, 0, 0, 0, 1, -1, 1, -1, - 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, - -1, 0, 1, -1, 1, 0, -1, 1, 0, -1, 1, - -1, 1, -1, 1, -1, 1, -1, 0, 1, -2, 2, - 0, -1, 1, -1, 1, -1, 1, 0, -1, 1, -1, - 0, 1, -2, 2, -1, 1, 0, 0, 0, -1, 1, - -1, 1, -1, 0, 0, 0, 1, -1, 1, 0, -1, - 1, -1, 0, 1, -1, 1, -1, 1, -1, 0, 1, - -1, 1, -1, 0, 0, 1, -1, 1, -1, 0, 1, - -2, 2, -1, 0, 1, -2, 2, 0, 0, 0, -1, - 1, -1, 0, 1, -1, 1, -1, 1, -1, 1, -1, - 0, 1, -1, 1, -1, 0, 0, 1, -1, 1, -2, - 2, -2, 3, -3, 3, -2, 0, 1, -1, 0, 0, - 1, -1, 1, -1, 0, 1, -1, 0, 0, 0, 1, - -1, 0, 1, -1, 1, -1, 0, 0, 0, 1, -1, - 0, 0, 0, 0, 1, -1, 1, -1, 0, 1, -1, - 1, -1, 1, 0, -1, 1, 0, -1, 1, -1, 0, - 1, -1, 1, -1, 1, 0, -1, 1, -1, 0, 1, - -1, 1, 0, 0, 0, -1, 1, -1, 0, 0, 0, - 0, 1, -1, 1, 0, -1, 0, 1, -1, 0, 1, - -1, 1, -1, 1, -1, 0, 1, -2, 2, -1, 0, - 0, 0, 1, -1, 1, -1, 1, -1, 1, -1, 1, - -1, 0, 1, -1, 1, -1, 1, 0, 0, -1, 1, - -1, 0, 0, 0, 0, 1, -1, 1, -1, 0, 1, - -1, 0, 1, -1, 1, -1, 1, -1, 0, 1, -1, - 0, 1, -1, 1, 0, -1, 1, -1, 0, 1, -2, - 2, -1, 0, 0, 0, 1, -1, 1, -1, 1, 0, - -1, 1, -1, 0, 1, -2, 2, -1, 0, 0, 0, - 1, -1, 0, 0, 1, -1, 1, 0, -1, 0, 1, - -2, 2, -1, 1, 0, -1, 0, 1, -2, 3, -2, - 1, -1, 1, -2, 2, -2, 2, -1, 1, -1, 1, - -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, - 0, 0, 1, -1, 1, -2, 2, -1, 1, -1, 1, - -1, 0, 1, -2, 2, -1, 1, -1, 0, 0, 0, - 0, 1, -1, 1, -1, 1, -2, 2, -1, 1, 0, - -1, 1, -1, 1, -1, 0, 0, 0, 0, 0, 0, - 1, -1, 1, -1, 1, -1, 0, 0, 0, 1, 0, - -1, 1, 0, -1, 1, -2, 2, -2, 2, -1, 0, - 0, 0, 1, -1, 1, -1, 1, -1, 1, -1, 1, - 0, 0, -1, 1, -1, 1, -1, 1, -1, 0, 0, - 0, 0, 1, -1, 1, 0, -1, 0, 0, 0, 1, - -1, 1, -1, 0, 1, -1, 0 -}; +static const unsigned int timerfreq_div = 500; /* 2 ms resolution */ #endif +/* actual (not quarter) beats per minute above which display blinking + is deactivated (since it is not needed anymore and because of performance + issues) */ +static const unsigned int blinklimit = 135; + +enum metronome_errors +{ + MERR_NOTHING = 0 +, MERR_MISSING +, MERR_OOM +, MERR_TEMPO +, MERR_METER +, MERR_VOLUME +, MERR_PATTERN +}; + +#define PART_MAX 10 /* maximum count of programmed parts */ #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) \ - || (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) \ + || (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) \ || (CONFIG_KEYPAD == SAMSUNG_YH920_PAD) #define MET_SYNC #endif @@ -636,20 +104,13 @@ static signed short sound[] = { #define METRONOME_PAUSE PLA_CANCEL #define METRONOME_PLAY PLA_SELECT_REPEAT -#if defined(MET_SYNC) -enum { - METRONOME_SYNC = LAST_PLUGINLIB_ACTION+1, -}; -#endif /* IRIVER_H100_PAD||IRIVER_H300_PAD */ - - -#define METRONOME_MSG_START "start: hold select" -#define METRONOME_MSG_STOP "stop : cancel" +#define METRONOME_START PLA_SELECT #ifdef MET_SYNC +enum{ METRONOME_SYNC = LAST_PLUGINLIB_ACTION+1 }; static const struct button_mapping iriver_syncaction[] = { - {METRONOME_SYNC, BUTTON_REC, BUTTON_NONE }, + { METRONOME_SYNC, BUTTON_REC, BUTTON_NONE }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_PLUGIN) }; #endif /* IRIVER_H100_PAD||IRIVER_H300_PAD */ @@ -663,24 +124,836 @@ const struct button_mapping *plugin_contexts[] = }; #define PLA_ARRAY_COUNT sizeof(plugin_contexts)/sizeof(plugin_contexts[0]) -static int bpm = 120; -static int period = 0; -static int minitick = 0; +#if CONFIG_CODEC != SWCODEC +#ifndef SIMULATOR +/* MP3 tick sounds */ +static unsigned char tick_sound[] = +{ + 255,251,112,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 73,110,102,111, 0, 0, 0, 15, 0, 0, 0, 3, 0, 0, 4,229, 0, 85, 85 +, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85 +, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,170,170,170,170,170,170,170,170,170 +,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170 +,170,170,170,170,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 +,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 0 +, 57, 76, 65, 77, 69, 51, 46, 57, 57,114, 1,205, 0, 0, 0, 0, 46,102, 0, 0 +, 20, 96, 36, 3, 64, 66, 0, 0, 96, 0, 0, 4,229,101,175,184,232, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,251,112,196, 0, 0, 13 +, 92,189,103, 52,194,128, 2,165,176,176,247, 51, 16, 2, 0, 0, 24, 32, 0, 12 +,204,204,204,204,207,215,221,121,229, 74,224,152, 1,128, 24, 19, 17,207,217,246 +,252,132,212,226,225,192, 16, 0, 0, 0, 0, 32,163,100,111,255, 66, 7, 0, 48 +, 12, 14, 31, 59,255,255,234,112,248,112, 56, 40,223,193, 0, 64, 16, 4, 1, 51 +,229, 29,234, 4,193,240,124, 31, 62, 15,135,255, 7,193, 0, 64, 16, 12, 9, 1 +, 15,168, 16, 1,131,224,254,254,146,224,254, 8, 28, 88,127,255,148, 4, 32,128 +, 32,196,182,166,245,242,214,222,214, 73, 45,110, 52,137, 81, 39,107,255, 44, 76 +,148,140, 8,250, 66,148,195, 43, 3, 41, 15, 18,163, 80, 5, 20,248,174,140,138 +,115, 1,146, 50, 49, 32, 44,201,152,157, 53, 32, 33,157, 8, 34, 85,135, 88,105 +,186,131,252, 48,143,168,162, 44,209,142, 16, 88,221, 10,214, 94, 51, 52, 46,148 +,133, 36, 38,129,165, 36,164,139, 64,211, 11,115,101, 49, 5,136, 33,157, 18,241 +,137, 50, 53,194,213,173, 78,241,108, 1, 24,172,129,146,141,136, 24,119, 73, 51 +, 85,162,138,146, 51, 20,101,163,242,129, 56,212, 84,233, 44, 94, 11, 97,117, 74 +, 73, 37,162, 58, 20,146, 95,203, 31,246, 50, 55,111,214,223,205,213,230, 31,232 +,122,143,183, 14, 39, 91, 57, 15,251,186, 21,185,149, 48, 1,100, 64,200, 16,121 +,155, 72,110, 24,130, 98,255,251,114,196, 7,128, 17,169,247, 95,221,152,128, 10 +, 80, 62,233,185,150,170,113,174,203,251, 59, 12,190,170, 98, 4,156,122,140, 97 +,155, 60, 39, 8,145,195,116, 22,164, 82,118,116, 42,116,157, 68, 88, 70, 64, 93 +, 17, 35, 39,163,118,118, 77, 75, 82,187,215, 89,140, 46,100,112,151, 75, 73,169 +,107,181,157,170,251, 45,140, 75, 34,122, 28,228,146,111,255,235,210, 81,124,114 +,199, 52,180,138,174,207,255,235, 82,210, 64,123, 34,197,101, 47,255,254,234, 91 +, 14, 74, 68,234,219,255,254,206,131,143,162,120,234,210,191,255,245, 93, 18,200 +,225, 42, 29,171,255,254,165,164,196, 24,137, 32,223, 90, 93, 96, 64,217, 78, 35 +, 32, 53,185,107,237, 43,113, 98, 80,107,161, 3,206, 60,192, 10, 78,226,219,199 +,158,146,158, 47, 59, 90,253,154,221,198,138,147,100,150,206,233, 32, 39,192, 73 +, 23, 76,150,201, 41,209,186,217, 37,250,233, 38,198, 34, 24, 18, 33,130, 38,158 +, 73, 54, 69,146, 91, 36,182, 75,235, 64,216,196,138, 9,201, 69,174,138,157,244 +,154,150,208,246, 57, 72, 71, 2,148, 23, 76,115, 83,255,210,218,161, 56, 3, 68 +, 81, 49,190,139,253,125, 81,205, 25, 13,202,146,156,173,255,250,234,194, 8, 69 +, 13,142,255,255,209, 88,136, 73, 6,145,235, 26,142,191,255, 85,100,154,104,178 +,131,213, 0, 34, 0, 17,132, 0, 7,227, 82,135, 11,113, 70,110,105, 94,118, 22 +,255,251,112,196, 9, 0, 17, 61,249, 41,128,101,163, 73,217,178,153, 88,147, 21 +, 48,158,206,220,162,156,221, 7,209, 69, 20,117,163, 69,146, 68,145, 26,131,150 +, 0, 4,132, 41, 8,214,202,209, 69, 30,191,116, 76,156,240, 41,194,118, 23,147 +, 67,173, 87,255,233, 29, 64,216, 73,129, 10, 28,227,197,217, 43,255,254,203, 40 +,140, 48,129, 5,201, 21, 58, 95,255,232,180,168, 70,136,131,201,146,255,254,182 +,169,206, 5,216,101, 36,146,217,109,255,250,169, 38, 96, 35, 69, 51,167,157,191 +,255, 82,158,152,225, 46, 14, 99,235,100,159,255,253, 22, 29,162, 98, 84,108,210 +,202,128, 74, 16, 23,220, 23, 96,152, 17, 5,129,242, 49,137, 75, 60, 81, 16, 80 +, 34,106, 74, 91,255,222, 53, 18, 64,160, 70, 1,195, 5,139,230, 84,118,254,236 +, 44, 29, 1,130,196,195,130,236,237,255,253,156, 84, 60, 17, 10, 10, 19, 35,179 +,255,254,206,198, 14,132,130,194,196, 14, 67,179,255,254,198, 40,144,136, 80, 80 +, 76, 64,228, 57, 29,191,251, 57, 76, 34, 18, 8,132, 66,132,200,114, 59, 63,255 +,220,166, 17, 18, 18, 26, 32,112,201,159,240,144,184,169, 23,127,197,133, 69, 85 +, 76, 65, 77, 69, 51, 46, 57, 57, 46, 53, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85 +, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85 +, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85 +}; +static unsigned char tock_sound[] = +{ + 255,251,112,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 73,110,102,111, 0, 0, 0, 15, 0, 0, 0, 3, 0, 0, 4,229, 0, 85, 85 +, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85 +, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,170,170,170,170,170,170,170,170,170 +,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170 +,170,170,170,170,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 +,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 0 +, 57, 76, 65, 77, 69, 51, 46, 57, 57,114, 1,205, 0, 0, 0, 0, 46,100, 0, 0 +, 20, 96, 36, 3, 64, 66, 0, 0, 96, 0, 0, 4,229,187,155,119, 17, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,251,112,196, 0, 0, 13 +,105, 19,104,212,146,128, 10,164, 41,175,119, 51, 32, 0, 2, 32, 41, 84, 9,130 +, 96,152,109,228, 0, 16, 0, 6, 9,209,163,111,127,154, 48, 0, 0, 0, 0,129 +,194, 19,212,226, 97,240,248,187,255, 65, 0,248,124, 92,255,144,130, 1,192,225 +, 9,249,206,115,138, 16,158,132, 57,206,115,191,242, 16,132,111,212,231, 14, 7 +, 8, 70,243,156,231, 57,206,121,207,200, 66, 16, 92,231,255,134, 0, 0, 0,127 +,244, 60, 60, 51,255,192, 3,195,207,252, 0, 0, 0, 29, 39,244, 60, 48, 3,255 +,195,219,177,171,179,181, 8,157,251,239,155,104,162, 80, 5,194, 16,165,199, 42 +,104,133, 19,109, 88, 96, 61,104,242,117,118, 94,135, 29, 53, 72, 67, 85, 11, 54 +, 59, 64,154,155,128,195, 23,148, 98, 43,186, 43,139, 64,218, 82, 68,160,197,168 +,125, 10, 50, 41, 16,240, 30, 6,228, 52,117, 0, 51,130,146,122,152,109,162,201 +, 45,154, 30, 11, 66, 30, 76, 73,145,224, 52,149, 17, 55,138,112,105, 51, 36,147 +, 22,130, 89, 20,138, 36,114,212,145, 3,199,107,101,213, 25, 21,222,196,209,162 +, 40,168,168,165,162,100,142,163,220,186,250, 72,106, 54, 75, 48,243, 79,153, 54 +,163, 93,179,171,204,144,232,190,115, 19,208, 90,172,244, 40, 98,126, 35,161,234 +,122,143,221, 39,250,159, 61, 35,111,250,213,216, 6,252, 9,138, 17, 64, 1, 13 +, 56, 80, 58,104,184, 37,255,251,114,196, 7,128, 17,250, 1, 97,189,152, 0, 10 +, 44,192, 41,253,151,169,185,237, 56, 3,131,220, 24,180,204,165,221,129,107,210 +,192, 50,130, 26, 22, 26,180, 77, 81, 85,221,146, 33,197,224,198,197,228,146, 89 +,162,210, 69,100,233, 13, 25,145, 61, 19,206,151,232,172,212, 58,162,149, 53, 70 +,234,234, 81,176,186, 28, 39,145,253, 87, 33,130,150, 43, 36,187,245,169,141,200 +, 41,178,191,230, 68,233,170,255,230, 37,227,101,183,237, 49, 56,109,255,115,134 +,232,223,247,156, 62,191,250, 43, 42,169,127,245, 26,160,255,234,151,157,191,215 +, 46,164,223,235, 98,137,118,223,238,112,189,111,247, 56, 94,106, 16, 1, 77, 8 +, 25, 4,204, 0, 0,134, 96, 41,151,170, 74,147,135, 11,136, 28,220, 96,102,179 +, 16,145, 89,202, 11,197,114, 72, 0,241, 77, 88,211, 70,174,171, 10, 11, 84,163 +, 5, 53,191,241,191,106,245,209,114, 21,240,208, 75,172,190,150,103,205,178,252 +, 78, 36,166,139,132,106,231, 86,253,130, 80,178,201,254,193, 68, 20,207,254,206 +, 49, 19, 78,127,253,159,255, 33, 37, 37, 95,238,112,188, 89, 37, 79,238,165, 5 +,163,151,249,168,130,215,255,169,223,249,231, 15,149,191,161,227,209,235, 63,232 +,166, 10,198,183,232,150, 34,119,255,213, 17,255,231, 17, 44, 8, 2, 96, 1,101 +,184,243,226,216, 18, 60,216,132,105,150,250,101,165, 64,237,172,186, 35,114,126 +,255,251,112,196, 12,128,144,142, 3, 44,140,180,241, 1,207, 47,217, 72,244, 10 +, 48, 29, 88, 20, 21,128, 36,231,157,173,100,202, 35,136,119,133,228,209, 55,186 +,218,198,197,208,217, 11,233,178,254,186,137,128, 8,110, 71,253,212,136,138, 45 +,118,253,216, 34, 7, 74, 99,255, 60, 22,144,101,111,209, 72,136,196,175,254, 58 +, 15, 76, 71,249,184,138, 45, 30,127,234,199, 21, 35,191,245, 17, 75, 63,252,120 +,108, 58,223,209,199, 74,141, 91,254,131, 98, 70,255,212, 69, 42, 71,254,172, 54 +,127,252,116,107,255,168,212,194, 64, 61,126, 46,224,170, 52, 71,208,229, 19,209 +,148, 64,203,225,206,126, 29,230, 1,134,123,159,138,246, 67,199, 93,127,253, 50 +,148, 81, 37, 13, 40,145, 8, 37, 12, 6, 4, 49, 67,204,186,186,255,255,213,149 +,149,137, 16,132,162, 8,128, 90, 58, 93, 95,255,121,138, 96,161,131, 3, 33,200 +,118,127,255,238, 83, 5, 10, 8,228, 58, 47,255,252,197, 48, 96,104,116, 84, 84 +, 69,255,251, 24, 40, 80, 74, 69, 69, 64, 96,193, 7,141, 1, 89,203, 5,113, 81 +, 70,255,245,139, 85, 76, 65, 77, 69, 51, 46, 57, 57, 46, 53, 85, 85, 85, 85, 85 +, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85 +, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85 +, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85 +}; +#endif /* SIMULATOR */ +#else +/* raw PCM */ +static signed short tick_sound[] = +{ + 32767,32764,32767,32767,32763,32767,32762,32767,32765,32767,32767 +,32766,32767,32766,32767,32767,32765,32767,32764,32767,32764,32767 +,32763,-32764,-32768,-32766,-32768,-32768,-32767,-32767,-32767,-32765,-32768 +,-32764,-32768,-32768,-32766,-32768,-32764,-32768,-32766,-32767,-32768,-32767 +,-32766,32763,32767,32763,32767,32767,32766,32767,32766,32767,32765 +,32767,32763,32767,32766,32767,32766,32767,32763,32767,32765,32767 +,32767,-32768,-32765,-32768,-32767,-32765,-32767,-32765,-32768,-32764,-32768 +,-32766,-32768,-32768,-32766,-32767,-32768,-32764,-32768,-32764,-32768,-32768 +,-32766,32716,32668,32620,32564,32520,32467,32418,32370,32316,32272 +,32214,32176,32114,32074,32020,31972,31922,31873,31823,31775,31726 +,31676,-31627,-31579,-31530,-31479,-31433,-31383,-31333,-31287,-31236,-31188 +,-31141,-31090,-31042,-30998,-30943,-30899,-30849,-30800,-30757,-30702,-30659 +,-30609,30561,30515,30463,30422,30365,30326,30273,30229,30177,30135 +,30084,30035,29995,29936,29903,29844,29802,29755,29706,29661,29614 +,29565,-29519,-29472,-29426,-29381,-29331,-29288,-29239,-29191,-29149,-29099 +,-29055,-29007,-28962,-28914,-28871,-28821,-28779,-28730,-28685,-28638,-28596 +,-28544,28496,28463,28404,28371,28314,28278,28225,28185,28136,28093 +,28048,28001,27956,27912,27865,27824,27773,27736,27682,27646,27593 +,27555,-27509,-27462,-27418,-27375,-27328,-27286,-27239,-27200,-27145,-27116 +,-27055,-27026,-26972,-26930,-26891,-26838,-26805,-26750,-26716,-26663,-26630 +,-26575,26534,26495,26448,26408,26360,26324,26272,26235,26188,26149 +,26101,26061,26016,25976,25930,25888,25847,25800,25763,25714,25676 +,25632,-25589,-25547,-25505,-25461,-25419,-25376,-25337,-25291,-25251,-25209 +,-25162,-25129,-25078,-25043,-24995,-24960,-24910,-24876,-24830,-24787,-24751 +,-24703,24663,24622,24583,24539,24499,24456,24418,24374,24334,24292 +,24252,24209,24173,24124,24092,24042,24011,23960,23930,23879,23845 +,23803,-23762,-23722,-23680,-23644,-23597,-23562,-23518,-23482,-23437,-23402 +,-23357,-23320,-23281,-23236,-23203,-23158,-23119,-23082,-23040,-23000,-22962 +,-22922,22885,22837,22809,22759,22728,22685,22644,22608,22567,22528 +,22491,22449,22412,22372,22334,22295,22254,22221,22173,22146,22096 +,22066,-22026,-21984,-21947,-21911,-21867,-21836,-21790,-21757,-21719,-21677 +,-21644,-21601,-21567,-21526,-21489,-21454,-21411,-21378,-21337,-21301,-21263 +,-21226,21189,21151,21111,21077,21036,21002,20964,20926,20889,20852 +,20814,20779,20741,20703,20666,20632,20590,20562,20512,20490,20440 +,20416,-20380,-20331,-20303,-20261,-20230,-20188,-20158,-20114,-20085,-20045 +,-20009,-19975,-19935,-19904,-19864,-19829,-19797,-19753,-19726,-19685,-19650 +,-19616,19580,19544,19508,19471,19441,19397,19373,19325,19301,19256 +,19229,19189,19155,19122,19081,19055,19013,18980,18947,18908,18879 +,18840,-18807,-18771,-18739,-18701,-18669,-18634,-18600,-18564,-18531,-18497 +,-18461,-18430,-18392,-18360,-18326,-18291,-18258,-18223,-18191,-18154,-18123 +,-18088,18055,18019,17989,17953,17919,17887,17853,17817,17791,17746 +,17726,17680,17656,17619,17585,17555,17519,17488,17453,17423,17385 +,17359,17320,-17287,-17261,-17220,-17196,-17156,-17128,-17093,-17062,-17029 +,-16996,-16966,-16929,-16901,-16868,-16834,-16804,-16769,-16741,-16705,-16675 +,-16644,-16609,16579,16545,16519,16479,16455,16419,16388,16359,16321 +,16300,16256,16235,16198,16166,16141,16102,16076,16043,16011,15981 +,15950,15920,-15891,-15852,-15832,-15789,-15768,-15732,-15703,-15672,-15642 +,-15609,-15582,-15548,-15521,-15487,-15459,-15426,-15401,-15364,-15339,-15305 +,-15275,-15250,15219,15184,15159,15122,15101,15061,15041,15002,14981 +,14944,14919,14886,14858,14829,14797,14772,14736,14715,14675,14657 +,14617,14598,-14567,-14533,-14506,-14475,-14447,-14419,-14389,-14358,-14334 +,-14299,-14277,-14241,-14218,-14186,-14158,-14131,-14100,-14072,-14046,-14012 +,-13991,-13955,13927,13904,13873,13844,13819,13787,13761,13732,13706 +,13674,13651,13619,13590,13570,13530,13516,13475,13457,13423,13401 +,13368,13345,-13317,-13287,-13260,-13234,-13204,-13178,-13152,-13122,-13098 +,-13068,-13043,-13013,-12990,-12958,-12937,-12902,-12884,-12849,-12829,-12798 +,-12771,-12746,12718,12693,12663,12641,12611,12586,12559,12531,12510 +,12475,12459,12421,12408,12367,12357,12315,12301,12268,12244,12218 +,12194,12164,-12140,-12113,-12093,-12056,-12043,-12008,-11987,-11961,-11931 +,-11911,-11884,-11855,-11836,-11804,-11782,-11757,-11729,-11708,-11679,-11655 +,-11631,-11601,11574,11560,11525,11508,11479,11454,11431,11403,11382 +,11356,11329,11307,11279,11260,11229,11211,11179,11161,11133,11110 +,11085,11061,-11038,-11010,-10991,-10960,-10944,-10913,-10893,-10866,-10845 +,-10818,-10796,-10772,-10747,-10725,-10699,-10676,-10653,-10629,-10605,-10580 +,-10561,-10531,10507,10491,10461,10442,10416,10394,10369,10350,10319 +,10305,10276,10252,10236,10202,10190,10160,10138,10117,10093,10070 +,10050,10020,-9997,-9984,-9953,-9935,-9912,-9885,-9871,-9840,-9823 +,-9799,-9773,-9756,-9730,-9710,-9687,-9664,-9642,-9620,-9598,-9576 +,-9554,-9532,9510,9488,9466,9444,9419,9405,9374,9361,9331 +,9314,9293,9268,9250,9225,9206,9184,9160,9143,9118,9098 +,9077,9053,-9029,-9018,-8988,-8973,-8948,-8928,-8906,-8888,-8862 +,-8848,-8819,-8805,-8780,-8760,-8740,-8720,-8695,-8681,-8653,-8638 +,-8615,-8594,8573,8556,8531,8515,8492,8472,8451,8433,8409 +,8393,8368,8354,8326,8315,8284,8277,8243,8236,8206,8192 +,8170,8151,-8133,-8107,-8095,-8068,-8054,-8030,-8014,-7991,-7975 +,-7953,-7933,-7916,-7894,-7876,-7857,-7836,-7818,-7799,-7778,-7761 +,-7740,-7720,7700,7684,7665,7645,7626,7610,7582,7577,7545 +,7534,7513,7493,7477,7455,7438,7419,7402,7379,7368,7341 +,7328,7307,-7289,-7272,-7250,-7237,-7216,-7196,-7183,-7157,-7146 +,-7123,-7108,-7091,-7065,-7058,-7030,-7020,-6998,-6979,-6965,-6944 +,-6927,-6911,6895,6870,6859,6836,6824,6800,6790,6763,6755 +,6730,6717,6699,6679,6667,6642,6632,6610,6596,6574,6564 +,6539,6529,6507,-6492,-6474,-6457,-6442,-6422,-6406,-6392,-6371 +,-6358,-6338,-6322,-6306,-6291,-6269,-6259,-6237,-6223,-6206,-6190 +,-6172,-6157,-6139,6123,6108,6088,6077,6057,6043,6025,6010 +,5992,5978,5962,5944,5928,5914,5897,5879,5869,5844,5837 +,5816,5799,5789,-5773,-5750,-5742,-5720,-5710,-5687,-5680,-5656 +,-5648,-5627,-5613,-5600,-5581,-5568,-5552,-5534,-5525,-5501,-5496 +,-5470,-5464,-5443,5430,5413,5402,5383,5370,5353,5343,5320 +,5314,5292,5280,5267,5248,5237,5219,5208,5190,5176,5162 +,5148,5131,5121,-5107,-5086,-5077,-5058,-5047,-5030,-5017,-5002 +,-4990,-4971,-4963,-4941,-4935,-4915,-4902,-4892,-4869,-4867,-4841 +,-4836,-4816,-4806,4792,4774,4767,4744,4740,4716,4712,4692 +,4680,4668,4649,4642,4624,4612,4599,4584,4570,4560,4541 +,4535,4513,4508,-4496,-4472,-4467,-4450,-4437,-4427,-4407,-4401 +,-4384,-4372,-4358,-4346,-4331,-4322,-4305,-4294,-4281,-4266,-4257 +,-4240,-4231,-4216,4204,4190,4180,4162,4156,4137,4131,4111 +,4104,4091,4075,4068,4048,4043,4026,4016,4002,3990,3980 +,3962,3957,3938,-3926,-3919,-3904,-3892,-3882,-3866,-3858,-3843 +,-3833,-3820,-3810,-3792,-3789,-3769,-3762,-3751,-3732,-3730,-3710 +,-3704,-3689,-3678,3666,3656,3640,3637,3615,3613,3594,3586 +,3576,3560,3555,3537,3529,3518,3504,3497,3481,3473,3462 +,3447,3441,3425,-3414,-3406,-3394,-3383,-3372,-3359,-3353,-3336 +,-3330,-3316,-3306,-3295,-3287,-3270,-3266,-3251,-3241,-3233,-3218 +,-3210,-3197,-3192,3182,3160,3165,3139,3140,3121,3116,3104 +,3093,3083,3075,3057,3058,3038,3033,3021,3009,3003,2990 +,2981,2969,2960,-2947,-2943,-2928,-2921,-2910,-2898,-2891,-2881 +,-2868,-2863,-2846,-2846,-2826,-2824,-2810,-2800,-2795,-2779,-2774 +,-2763,-2751,-2746,2735,2724,2715,2705,2697,2682,2682,2662 +,2663,2645,2641,2629,2620,2612,2602,2592,2585,2572,2566 +,2557,2544,2540,-2530,-2520,-2508,-2503,-2492,-2482,-2477,-2463 +,-2457,-2447,-2439,-2430,-2419,-2416,-2398,-2399,-2382,-2380,-2365 +,-2364,-2346,-2345,2335,2324,2316,2308,2301,2290,2281,2275 +,2263,2262,2241,2250,2220,2232,2211,2208,2199,2189,2180 +,2177,2161,2163,-2154,-2137,-2138,-2119,-2122,-2102,-2107,-2087 +,-2088,-2073,-2073,-2055,-2057,-2040,-2040,-2027,-2022,-2013,-2005 +,-1997,-1991,-1981,1973,1967,1959,1953,1940,1941,1922,1928 +,1908,1911,1892,1896,1879,1882,1862,1866,1850,1847,1840 +,1829,1827,1815,-1809,-1802,-1797,-1785,-1784,-1770,-1768,-1757 +,-1755,-1742,-1740,-1729,-1724,-1716,-1711,-1701,-1697,-1688,-1682 +,-1676,-1665,-1663,1654,1649,1638,1637,1624,1622,1611,1611 +,1594,1599,1582,1582,1573,1566,1560,1554,1547,1538,1538 +,1523,1524,1512,1509,-1502,-1493,-1491,-1480,-1478,-1469,-1462 +,-1458,-1450,-1444,-1441,-1427,-1431,-1414,-1418,-1405,-1400,-1397 +,-1385,-1388,-1371,-1376,1370,1354,1355,1345,1341,1334,1329 +,1323,1316,1311,1305,1299,1294,1287,1282,1276,1270,1266 +,1255,1258,1244,1244,-1239,-1226,-1231,-1212,-1220,-1205,-1202 +,-1199,-1190,-1186,-1182,-1173,-1171,-1163,-1158,-1156,-1145,-1145 +,-1136,-1131,-1128,-1121,1116,1111,1106,1100,1094,1092,1082 +,1084,1068,1075,1061,1061,1053,1047,1047,1037,1036,1025 +,1027,1016,1017,1007,-1005,-996,-998,-986,-986,-980,-973 +,-973,-962,-962,-956,-949,-949,-939,-938,-931,-929,-920 +,-921,-911,-911,-903,899,896,891,885,880,881,869 +,873,858,863,853,851,847,840,840,829,833,819 +,826,811,815,804,-801,-800,-794,-788,-791,-778,-780 +,-774,-766,-771,-755,-764,-747,-754,-742,-743,-736,-734 +,-728,-727,-718,-720,715,708,708,699,703,687,697 +,681,687,675,679,665,675,657,665,653,654,648 +,646,642,637,634,-629,-629,-621,-623,-614,-615,-607 +,-607,-602,-599,-594,-594,-586,-588,-577,-583,-571,-574 +,-567,-564,-562,-559,557,548,552,541,546,532,542 +,527,531,524,522,521,515,513,509,507,504,500 +,497,495,490,489,-485,-482,-479,-476,-474,-468,-470 +,-462,-462,-458,-455,-454,-449,-447,-443,-442,-437,-437 +,-432,-429,-429,-422,420,419,417,412,411,409,404 +,403,400,397,394,393,388,388,382,384,375,381 +,371,372,369,364,-360,-365,-355,-360,-351,-354,-347 +,-347,-345,-340,-341,-336,-335,-331,-333,-323,-329,-322 +,-319,-321,-314,-316,314,308,308,303,304,300,298 +,297,292,294,288,288,285,281,285,275,279,276 +,270,272,269,264,-260,-267,-257,-261,-256,-254,-254 +,-249,-250,-247,-244,-245,-238,-242,-235,-237,-233,-232 +,-229,-229,-225,-225,222,222,218,218,214,215,211 +,212,206,210,201,206,202,199,199,197,192,197 +,191,188,192,183,-185,-179,-189,-174,-183,-177,-174 +,-178,-169,-174,-168,-169,-167,-165,-165,-161,-162,-158 +,-160,-155,-155,-155,154,149,151,148,147,146,143 +,145,138,144,136,139,136,134,136,129,135,125 +,134,123,130,120,-119,-126,-118,-123,-116,-122,-111 +,-120,-113,-111,-115,-108,-111,-109,-108,-104,-107,-103 +,-106,-99,-104,-94,93,100,95,98,93,97,88 +,96,85,96,84,91,85,84,89,81,84,82 +,79,84,75,82,75,-76,-75,-76,-73,-74,-71 +,-73,-70,-68,-72,-65,-70,-65,-65,-67,-61,-66 +,-62,-60,-62,-61,-57,54,64,52,61,52,57 +,54,54,53,53,50,53,48,53,45,53,43 +,51,45,45,47,42,-41,-45,-43,-40,-44,-39 +,-42,-40,-38,-38,-40,-36,-39,-34,-39,-32,-37 +,-33,-34,-34,-34,-29,28,35,28,32,29,30 +,27,31,27,28,27,26,27,24,30,20,28 +,21,27,20,27,18,-19,-23,-21,-22,-19,-23 +,-16,-24,-15,-23,-15,-21,-16,-17,-20,-14,-19 +,-14,-18,-13,-19,-11,11,18,10,19,8,17 +,13,10,18,5,18,7,16,8,12,11,10 +,10,12,6,14,5,-4,-14,-5,-10,-10,-5 +,-11,-6,-8,-8,-6,-9,-5,-7,-8,-2,-12 +,-1,-8,-6,-4,-7,6,5,4,7,2,6 +,4,3,8,1,4,4,4,3,5,1,5 +,3,1,5,2,3,-1,-5,-2,0,-5,1 +,-6,2,-6,3,-6,1,-5,2,-6,5,-8 +,4,-6,3,-5,3,-2,2,1,0,1,4 +,-5,6,-3,1,3,-2,3,-3,5,-5,5 +,-1,0,0,2,-3,4,-3,0,1,-1,-1 +,2,-2,1,-1,0,1,-1,0,0,0,1 +,-1,1,-2,2,-1,1,0,-3,5,-5,4 +,-1,-2,2,-1,1,0,-1,1,-1,2,-3 +,3,-3 +}; +static signed short tock_sound[] = +{ + 32767,32761,32767,32762,32767,32763,32767,32765,32767,32767,32766 +,32767,32764,32767,32765,32767,32763,32767,32761,32767,32765,32767 +,32766,32767,32766,32767,32767,32764,32767,32763,32767,32767,32766 +,32767,32766,32767,32767,32765,32767,32763,32767,32761,32767,32764 +,32767,-32766,-32768,-32765,-32767,-32768,-32762,-32768,-32762,-32768,-32768 +,-32765,-32768,-32765,-32768,-32766,-32766,-32766,-32766,-32768,-32766,-32768 +,-32766,-32768,-32767,-32768,-32766,-32768,-32767,-32767,-32768,-32763,-32768 +,-32765,-32768,-32768,-32765,-32768,-32767,-32768,-32768,-32767,-32766,-32768 +,-32767,32720,32666,32619,32567,32516,32471,32414,32373,32314,32270 +,32220,32167,32123,32068,32023,31970,31924,31872,31824,31775,31725 +,31678,31625,31581,31527,31482,31431,31383,31334,31286,31238,31185 +,31144,31087,31046,30993,30947,30898,30848,30804,30750,30709,30653 +,30614,-30566,-30509,-30470,-30415,-30371,-30322,-30276,-30226,-30181,-30131 +,-30085,-30039,-29988,-29945,-29894,-29849,-29800,-29756,-29707,-29658,-29617 +,-29562,-29522,-29473,-29425,-29380,-29334,-29283,-29242,-29193,-29145,-29103 +,-29051,-29011,-28959,-28917,-28866,-28827,-28773,-28735,-28682,-28641,-28591 +,-28550,28503,28457,28407,28369,28316,28275,28229,28182,28137,28094 +,28044,28006,27952,27915,27864,27823,27775,27734,27682,27645,27597 +,27550,27513,27455,27426,27368,27333,27284,27240,27197,27152,27105 +,27069,27012,26982,26926,26891,26841,26799,26756,26712,26666,26628 +,26574,-26528,-26502,-26443,-26410,-26362,-26318,-26277,-26233,-26189,-26147 +,-26103,-26059,-26019,-25973,-25931,-25888,-25846,-25801,-25763,-25714,-25675 +,-25633,-25587,-25549,-25502,-25463,-25419,-25378,-25333,-25294,-25249,-25208 +,-25167,-25123,-25084,-25037,-25000,-24954,-24917,-24871,-24832,-24788,-24748 +,-24706,24665,24622,24582,24539,24501,24454,24420,24371,24336,24292 +,24251,24212,24167,24131,24084,24052,24001,23969,23921,23886,23842 +,23804,23760,23724,23678,23644,23598,23561,23521,23478,23440,23401 +,23356,23324,23275,23243,23197,23161,23118,23082,23039,23003,22959 +,22922,-22882,-22844,-22801,-22763,-22729,-22679,-22653,-22601,-22569,-22529 +,-22488,-22453,-22409,-22374,-22331,-22297,-22254,-22220,-22176,-22141,-22100 +,-22064,-22024,-21985,-21947,-21910,-21869,-21833,-21794,-21754,-21721,-21675 +,-21645,-21601,-21566,-21529,-21486,-21455,-21410,-21380,-21335,-21304,-21258 +,-21232,21195,21144,21118,21072,21038,21003,20960,20932,20882,20858 +,20810,20781,20740,20703,20668,20628,20595,20557,20518,20483,20447 +,20409,20374,20336,20299,20265,20225,20194,20150,20123,20079,20047 +,20008,19975,19937,19902,19866,19827,19797,19755,19725,19682,19654 +,19614,-19581,-19540,-19512,-19471,-19437,-19405,-19362,-19335,-19292,-19264 +,-19223,-19194,-19151,-19124,-19082,-19053,-19014,-18980,-18946,-18911,-18876 +,-18842,-18804,-18775,-18735,-18704,-18668,-18634,-18598,-18568,-18527,-18500 +,-18460,-18428,-18394,-18360,-18324,-18295,-18254,-18225,-18190,-18154,-18124 +,-18087,18054,18021,17987,17953,17921,17884,17855,17818,17786,17754 +,17718,17685,17654,17619,17586,17554,17519,17488,17454,17421,17387 +,17358,17319,17295,17251,17230,17186,17164,17123,17096,17061,17028 +,16996,16967,16929,16902,16865,16837,16801,16774,16736,16708,16675 +,16641,16612,-16578,-16549,-16513,-16486,-16449,-16423,-16385,-16361,-16321 +,-16297,-16260,-16233,-16198,-16169,-16137,-16102,-16080,-16038,-16017,-15976 +,-15954,-15914,-15892,-15855,-15826,-15796,-15762,-15735,-15702,-15673,-15638 +,-15617,-15572,-15556,-15515,-15489,-15461,-15424,-15400,-15365,-15338,-15304 +,-15281,-15241,15212,15189,15155,15125,15098,15064,15038,15005,14977 +,14947,14918,14886,14859,14827,14799,14771,14738,14711,14681,14651 +,14623,14592,14565,14532,14508,14474,14449,14416,14391,14357,14334 +,14301,14273,14246,14214,14188,14159,14128,14104,14069,14046,14016 +,13986,13958,-13928,-13905,-13869,-13849,-13816,-13789,-13758,-13736,-13702 +,-13678,-13649,-13616,-13598,-13561,-13539,-13508,-13480,-13455,-13424,-13399 +,-13371,-13341,-13318,-13284,-13263,-13232,-13205,-13179,-13150,-13124,-13096 +,-13069,-13041,-13017,-12984,-12965,-12930,-12908,-12881,-12849,-12831,-12793 +,-12779,-12739,12714,12694,12666,12636,12616,12583,12561,12531,12509 +,12476,12459,12421,12406,12373,12347,12325,12294,12271,12244,12218 +,12194,12164,12142,12112,12091,12062,12038,12009,11989,11956,11939 +,11903,11888,11855,11834,11806,11782,11755,11732,11705,11679,11658 +,11628,11605,-11579,-11557,-11527,-11505,-11480,-11455,-11429,-11406,-11380 +,-11355,-11331,-11305,-11283,-11256,-11231,-11210,-11178,-11166,-11126,-11117 +,-11080,-11063,-11037,-11010,-10992,-10961,-10940,-10916,-10890,-10871,-10838 +,-10825,-10791,-10774,-10747,-10724,-10699,-10679,-10648,-10634,-10600,-10586 +,-10554,-10537,10513,10485,10466,10438,10420,10391,10370,10349,10321 +,10305,10273,10257,10228,10211,10183,10164,10138,10115,10096,10066 +,10053,10019,10007,9975,9960,9930,9916,9883,9871,9839,9823 +,9801,9771,9759,9726,9714,9684,9666,9640,9623,9596,9577 +,9553,9532,-9510,-9487,-9467,-9443,-9422,-9401,-9377,-9358,-9334 +,-9313,-9292,-9270,-9248,-9227,-9205,-9182,-9165,-9138,-9121,-9098 +,-9075,-9057,-9032,-9015,-8989,-8973,-8947,-8929,-8907,-8885,-8867 +,-8842,-8824,-8802,-8780,-8763,-8737,-8720,-8699,-8676,-8657,-8637 +,-8614,-8597,8576,8554,8532,8513,8494,8470,8454,8429,8413 +,8390,8371,8351,8328,8314,8286,8274,8247,8233,8207,8192 +,8170,8149,8134,8108,8092,8070,8053,8031,8014,7991,7974 +,7953,7935,7912,7899,7872,7861,7832,7820,7798,7779,7761 +,7739,7724,-7706,-7679,-7669,-7641,-7628,-7607,-7588,-7570,-7551 +,-7530,-7515,-7491,-7478,-7456,-7438,-7419,-7401,-7379,-7369,-7338 +,-7335,-7300,-7295,-7267,-7255,-7233,-7218,-7196,-7181,-7159,-7145 +,-7124,-7107,-7090,-7068,-7055,-7033,-7018,-6999,-6979,-6966,-6942 +,-6929,-6909,6891,6875,6855,6840,6820,6803,6787,6768,6750 +,6733,6717,6695,6687,6657,6650,6629,6608,6599,6573,6562 +,6543,6525,6508,6494,6470,6462,6437,6426,6405,6391,6371 +,6358,6338,6323,6305,6289,6273,6254,6241,6221,6206,6191 +,6170,6160,6136,-6121,-6108,-6090,-6075,-6057,-6044,-6023,-6013 +,-5988,-5983,-5955,-5950,-5926,-5914,-5897,-5879,-5867,-5846,-5837 +,-5813,-5806,-5780,-5774,-5751,-5741,-5720,-5710,-5687,-5680,-5656 +,-5648,-5626,-5616,-5596,-5584,-5566,-5552,-5538,-5519,-5507,-5490 +,-5475,-5463,-5440,5425,5419,5396,5385,5373,5350,5342,5324 +,5308,5297,5278,5266,5250,5236,5218,5209,5190,5176,5162 +,5148,5131,5120,5103,5088,5075,5061,5043,5035,5013,5005 +,4988,4973,4960,4946,4931,4916,4905,4885,4879,4856,4850 +,4829,4823,4799,-4785,-4783,-4758,-4749,-4738,-4718,-4710,-4693 +,-4679,-4669,-4649,-4643,-4621,-4616,-4596,-4585,-4572,-4555,-4548 +,-4527,-4521,-4501,-4492,-4477,-4464,-4451,-4437,-4425,-4410,-4399 +,-4384,-4372,-4359,-4345,-4332,-4320,-4307,-4292,-4283,-4265,-4256 +,-4243,-4227,-4217,4201,4196,4171,4173,4145,4147,4123,4117 +,4103,4087,4079,4065,4051,4042,4026,4014,4005,3988,3981 +,3962,3956,3939,3931,3917,3903,3892,3882,3866,3860,3841 +,3831,3824,3804,3800,3782,3772,3761,3749,3737,3726,3712 +,3702,3690,3679,-3667,-3656,-3640,-3637,-3614,-3614,-3594,-3587 +,-3573,-3564,-3549,-3542,-3528,-3517,-3506,-3494,-3482,-3475,-3458 +,-3452,-3437,-3427,-3417,-3406,-3392,-3384,-3372,-3359,-3354,-3335 +,-3330,-3316,-3306,-3297,-3283,-3276,-3259,-3256,-3239,-3232,-3220 +,-3210,-3196,-3192,3182,3161,3161,3143,3137,3124,3114,3103 +,3096,3080,3075,3060,3054,3040,3034,3018,3013,2999,2992 +,2980,2971,2958,2953,2937,2933,2918,2910,2901,2889,2881 +,2869,2862,2849,2842,2828,2824,2810,2801,2793,2780,2774 +,2762,2755,2740,-2730,-2729,-2711,-2706,-2697,-2683,-2681,-2665 +,-2658,-2650,-2636,-2633,-2618,-2614,-2599,-2593,-2585,-2571,-2568 +,-2556,-2542,-2544,-2521,-2526,-2507,-2502,-2492,-2483,-2474,-2467 +,-2455,-2447,-2440,-2428,-2422,-2412,-2402,-2396,-2385,-2376,-2369 +,-2359,-2351,-2344,2336,2323,2319,2303,2306,2282,2290,2269 +,2268,2254,2251,2238,2234,2221,2217,2203,2203,2187,2184 +,2171,2168,2155,2150,2141,2132,2125,2116,2109,2099,2094 +,2083,2078,2066,2062,2052,2045,2037,2027,2023,2011,2009 +,1994,1992,1980,-1973,-1967,-1959,-1950,-1945,-1937,-1926,-1923 +,-1911,-1907,-1899,-1889,-1885,-1873,-1871,-1860,-1853,-1847,-1838 +,-1832,-1824,-1816,-1811,-1801,-1795,-1789,-1778,-1776,-1765,-1759 +,-1753,-1742,-1742,-1726,-1728,-1714,-1710,-1703,-1696,-1688,-1682 +,-1676,-1664,-1667,1661,1641,1645,1632,1625,1625,1607,1612 +,1596,1596,1585,1581,1570,1571,1556,1556,1546,1539,1536 +,1525,1523,1512,1511,1497,1499,1487,1481,1480,1465,1466 +,1455,1450,1447,1436,1434,1423,1420,1414,1407,1401,1395 +,1388,1382,1379,1369,-1364,-1359,-1352,-1348,-1338,-1336,-1328 +,-1322,-1318,-1310,-1305,-1300,-1291,-1290,-1280,-1277,-1269,-1267 +,-1256,-1255,-1246,-1242,-1238,-1228,-1225,-1221,-1212,-1209,-1203 +,-1195,-1193,-1186,-1180,-1175,-1170,-1163,-1161,-1150,-1150,-1142 +,-1137,-1133,-1126,-1119,1113,1112,1105,1100,1096,1089,1084 +,1080,1075,1068,1067,1054,1059,1045,1045,1041,1031,1031 +,1022,1018,1016,1007,1006,997,996,987,986,979,975 +,970,966,959,957,949,948,940,939,928,932,920 +,918,915,907,906,-900,-896,-890,-885,-883,-877,-871 +,-870,-862,-860,-856,-848,-848,-841,-837,-834,-827,-827 +,-817,-817,-811,-808,-803,-798,-794,-791,-786,-783,-777 +,-774,-769,-765,-763,-756,-754,-748,-746,-741,-737,-732 +,-731,-722,-727,-710,707,714,704,700,702,690,693 +,684,685,676,677,671,665,668,656,657,653,649 +,644,645,632,640,626,631,620,623,614,615,607 +,608,601,598,598,588,592,582,584,576,577,568 +,571,564,561,558,-554,-553,-546,-546,-541,-540,-532 +,-537,-522,-531,-519,-521,-515,-513,-510,-505,-507,-495 +,-503,-489,-495,-486,-486,-481,-480,-476,-472,-472,-465 +,-467,-458,-461,-453,-455,-450,-444,-446,-439,-441,-433 +,-435,-428,-428,-425,424,416,417,413,411,407,407 +,401,400,397,396,389,394,381,388,379,381,375 +,376,368,371,365,365,360,360,356,353,353,347 +,347,346,340,339,339,331,337,326,330,323,325 +,319,321,312,318,-316,-305,-310,-303,-303,-302,-296 +,-298,-292,-293,-289,-288,-285,-283,-281,-279,-278,-274 +,-273,-269,-271,-265,-265,-264,-257,-262,-255,-254,-255 +,-248,-250,-247,-243,-247,-236,-244,-232,-240,-231,-232 +,-232,-223,-232,-220,219,224,217,218,216,212,212 +,212,207,208,204,202,204,200,197,197,195,193 +,194,187,191,186,184,187,177,186,175,180,175 +,173,175,169,172,168,165,167,162,166,157,162 +,156,158,156,152,-152,-151,-149,-149,-146,-147,-142 +,-145,-140,-141,-138,-137,-139,-131,-138,-128,-135,-126 +,-132,-124,-129,-123,-125,-121,-123,-116,-123,-116,-117 +,-115,-113,-114,-112,-112,-107,-110,-108,-104,-109,-100 +,-105,-103,-99,-101,99,99,94,98,93,96,89 +,96,87,91,88,89,86,88,81,86,83,82 +,82,78,83,73,83,73,77,76,72,74,73 +,69,73,70,67,71,63,71,62,69,59,68 +,58,66,58,63,57,-58,-58,-57,-56,-56,-55 +,-56,-51,-57,-47,-56,-48,-53,-49,-48,-50,-45 +,-50,-45,-46,-46,-43,-45,-43,-43,-41,-43,-39 +,-43,-37,-42,-35,-42,-34,-39,-36,-36,-35,-35 +,-34,-34,-34,-31,-35,35,28,34,27,35,23 +,35,23,32,26,27,28,24,28,23,27,24 +,24,25,21,25,22,22,23,19,23,20,20 +,22,16,23,15,23,13,23,12,23,13,18 +,16,15,16,16,14,-14,-14,-16,-11,-18,-9 +,-17,-8,-17,-10,-14,-10,-11,-13,-10,-12,-9 +,-10,-11,-9,-11,-8,-9,-10,-6,-13,-4,-12 +,-4,-12,-2,-14,-1,-12,-3,-8,-6,-7,-6 +,-6,-5,-6,-5,-6,6,3,8,2,7,2 +,7,2,6,1,6,4,1,9,-5,12,-5 +,10,-1,5,0,5,1,5,0,3,3,1 +,3,2,1,3,0,5,-2,4,0,2,3 +,-1,4,-3,6,-3,2,-2,-2,0,-1,-2 +,1,-1,-2,1,-2,0,0,-2,2,-3,2 +,-4,4,-5,5,-5,2,0,-1,0,1,-4 +,5,-5,4,-3,2,-1,-1,1,-2,2,-2 +,2,-2,2,-1,0,1,-1,0,1,-2,3 +,-3,2,-1,0,1,-1,0,0,1,-1,1 +,-2,3 +}; +#endif + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + Utilities from pdbox plugin (Copyright (C) 2009 Wincent Balin) --- am I + supposed to supply these functions with the plugin? Should I use a library? +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Implementation of strtod() and atof(), + taken from SanOS (http://www.jbox.dk/sanos/). */ +static int rb_errno = 0; + +static double rb_strtod(const char *str, char **endptr) +{ + double number; + int exponent; + int negative; + char *p = (char *) str; + double p10; + int n; + int num_digits; + int num_decimals; + + /* Reset Rockbox errno -- W.B. */ +#ifdef ROCKBOX + rb_errno = 0; +#endif + + // Skip leading whitespace + while (isspace(*p)) p++; + + // Handle optional sign + negative = 0; + switch (*p) + { + case '-': negative = 1; // Fall through to increment position + case '+': p++; + } + + number = 0.; + exponent = 0; + num_digits = 0; + num_decimals = 0; + + // Process string of digits + while (isdigit(*p)) + { + number = number * 10. + (*p - '0'); + p++; + num_digits++; + } + + // Process decimal part + if (*p == '.') + { + p++; + + while (isdigit(*p)) + { + number = number * 10. + (*p - '0'); + p++; + num_digits++; + num_decimals++; + } + + exponent -= num_decimals; + } + + if (num_digits == 0) + { +#ifdef ROCKBOX + rb_errno = 1; +#else + errno = ERANGE; +#endif + return 0.0; + } + + // Correct for sign + if (negative) number = -number; + + // Process an exponent string + if (*p == 'e' || *p == 'E') + { + // Handle optional sign + negative = 0; + switch(*++p) + { + case '-': negative = 1; // Fall through to increment pos + case '+': p++; + } + + // Process string of digits + n = 0; + while (isdigit(*p)) + { + n = n * 10 + (*p - '0'); + p++; + } + + if (negative) + exponent -= n; + else + exponent += n; + } + +#ifndef ROCKBOX + if (exponent < DBL_MIN_EXP || exponent > DBL_MAX_EXP) + { + errno = ERANGE; + return HUGE_VAL; + } +#endif + + // Scale the result + p10 = 10.; + n = exponent; + if (n < 0) n = -n; + while (n) + { + if (n & 1) + { + if (exponent < 0) + number /= p10; + else + number *= p10; + } + n >>= 1; + p10 *= p10; + } + +#ifndef ROCKBOX + if (number == HUGE_VAL) errno = ERANGE; +#endif + if (endptr) *endptr = p; + + return number; +} + +static double rb_atof(const char *str) +{ + return rb_strtod(str, NULL); +} + +/* * * * * * * * * * * * * * * * * * * * * * * + Actual metronome stuff +* * * * * * * * * * * * * * * * * * * * * * */ + +static int fd = -1; /* file descriptor, global for cleanup(). */ + +/* Round fixed-point number to integer. */ +static int fp_rint(long fp_num) +{ + fp_num += fp_num > 0 ? +((long)1<<15) : -((long)1<<15); + return (int)(fp_num / ((long)1<<16)); +} +/* float to fixed-point */ +static long fp_frac(float fl_num) +{ + return (long)(fl_num*((long)1<<16)); +} + +/* simple dynamic memory management + - only allocate blocks serially + - deallocation of most recent blocks by resetting the free region pointer + - everything aligned to 4 bytes (wasting some bytes, but playing safe) +*/ +static void *mem_begin = NULL; /* beginning of managed region. */ +static void *mem_end = NULL; /* just after end of managed region */ +static void *mem_free_region = NULL; /* pointer to unused free space */ +static void *mem_checkpointer = NULL; /* position to reset to */ + +/* Initialize memory management. */ +static void mem_init(void) +{ + size_t bufsize; + /* Can I trust that pointer to be aligned? Better be safe. */ + mem_begin = ALIGN_UP(rb->plugin_get_buffer(&bufsize), 4); + mem_end = mem_begin + bufsize - 3; + mem_free_region = mem_begin; + mem_checkpointer = mem_begin; +} + +/* Remember and reset free region, for temporary mem usage. */ +static void mem_checkpoint(void){ mem_checkpointer = mem_free_region; } +static void mem_reset (void){ mem_free_region = mem_checkpointer; } +static void *mem_allocate(size_t bytes) +{ + void *handout = mem_free_region; + /* Always handing out multiples of alignment size. */ + if(bytes % 4) bytes += 4 - bytes % 4; + if(mem_free_region + bytes >= mem_end) + { + rb->splash(2*HZ, "Out Of Memory"); + return NULL; + } + mem_free_region += bytes; + return handout; +} + +struct part; +struct part /* One part of a track, with one tempo (range), meter, etc. */ +{ + struct part *prev, *next; /* linked list links*/ + unsigned int id; /* index (in order, please) */ + char *label; + unsigned int bars; /* Duration of part in bars. */ + unsigned int beats_per_bar; /* 3 in 3/4 */ + unsigned int base_beat; /* 4 in 3/4 to adjust bpm value */ + unsigned int bpm; /* base tempo (1/4 notes per minute) */ + unsigned int bpm2; /* end tempo */ + unsigned int *beat_bpm; /* either NULL or (bars*beats_per_bar) values */ + long accel; /* fixed-point acceleration in 1/min (really) */ + int volume; /* volume offset in integer dB */ + /* Store pattern characters verbatim for max. 64 beats (no string + termination). One could save storage here by encoding things in bits, + or by allocating dynamically to begin with. */ + char *pattern; +}; + +static struct part *part_list = NULL; /* linked list of parts */ +static struct part *part = NULL; /* current part */ +static unsigned int parts = 0; /* total number of parts */ +static unsigned int bad_parts = 0; /* Count parts with parsing errors. */ + +/* Initialize a part that is not yet placed into the list. */ +static void part_init(struct part *ps) +{ + ps->prev = NULL; + ps->next = NULL; + ps->id = 0; + ps->label = NULL; + ps->bars = 0; + ps->beats_per_bar = 4; + ps->base_beat = 4; + ps->bpm = 120; + ps->bpm2 = 120; + ps->beat_bpm = NULL; + ps->accel = 0; + ps->volume = 0; + ps->pattern = NULL; +} + +/* Add to the list. */ +static void part_add(struct part *ps) +{ + if(part) + { + part->next = ps; + ps->prev = part; + part = ps; + } + else part = part_list = ps; + + ps->id = parts++; +} + +/* Stay away from zero. */ +static unsigned int positive(long long value) +{ + return value > 0 ? value : 1; +} + +/* Yay! Global state variables! */ +static bool track_mode = false; /* switch for programmed tracks metronome */ +static int loop = 0; /* Needed? */ +static unsigned int beat = 0; +static unsigned int bar = 0; /* How big shall this become? */ +/* The currently (approximate) active bpm value, set from calc_period(). */ +static unsigned int bpm = 1; + +/* Should be unsigned? */ +static unsigned int period = 0; /* beat interval in timer ticks */ +static long period_diff = 0; /* fixed-point error of last period computation */ +static unsigned int minitick = 0; /* elapsed ticks */ +static bool beating = false; /* A beat is/was playing and count needs to increase. */ +static int display_state = 0; /* Current display state code. */ +static bool display_trigger = false; /* Draw display on next occasion */ static bool sound_active = false; static bool sound_paused = true; -static char buffer[30]; +/* global static buffer for messages in any situation */ +static char buffer[64]; +/* For line parsing, more is needed, allocated on demand. + As my memory management doesn't allow to free it, keeping it local + ist not smart. */ +static char* linebuf = NULL; +size_t linebuf_size = 0; + +/* global state for tempo tapping */ static bool reset_tap = false; static int tap_count = 0; static int tap_time = 0; static int tap_timeout = 0; -int bpm_step_counter = 0; +static int bpm_step_counter = 0; + +static bool sound_trigger = false; #if CONFIG_CODEC != SWCODEC +#ifdef SIMULATOR + +/* No audio in HWCODEC simulator build. */ +#define MET_IS_PLAYING 0 +#define MET_PLAY_STOP do {} while(0) +static void play_tick(void){ printf("tick\n"); } +static void play_tock(void){ printf("tock\n"); } + +#else + #define MET_IS_PLAYING rb->mp3_is_playing() #define MET_PLAY_STOP rb->mp3_play_stop() @@ -692,98 +965,390 @@ static void callback(const void** start, size_t* size) rb->led(0); } +/* Wondering: Should one prevent playing again while sound_active == true? */ + +static void play_tick(void) +{ + sound_active = true; + rb->led(1); + rb->mp3_play_data(tick_sound, sizeof(tick_sound), callback); + rb->mp3_play_pause(true); /* kickoff audio */ +} + static void play_tock(void) { sound_active = true; rb->led(1); - rb->mp3_play_data(sound, sizeof(sound), callback); - rb->mp3_play_pause(true); /* kickoff audio */ + rb->mp3_play_data(tock_sound, sizeof(tock_sound), callback); + rb->mp3_play_pause(true); /* kickoff audio */ } +#endif /* SIMULATOR */ + #else /* CONFIG_CODEC == SWCODEC */ #define MET_IS_PLAYING rb->pcm_is_playing() #define MET_PLAY_STOP rb->audio_stop() +/* Really necessary? Cannot just play mono? + Also: This is wasted memory! */ +static short tick_buf[sizeof(tick_sound)*2]; +static short tock_buf[sizeof(tock_sound)*2]; -bool need_to_play = false; - -short sndbuf[sizeof(sound)*2]; - -/* Convert the mono "tock" sample to interleaved stereo */ -static void prepare_tock(void) +/* Convert the mono samples to interleaved stereo */ +static void prepare_buffers(void) { - int i; - for(i = 0;i < (int)sizeof(sound)/2;i++) { - sndbuf[i*2] = sound[i]; - sndbuf[i*2+1] = sound[i]; - } + size_t i; + for(i = 0;i < sizeof(tick_sound)/sizeof(short);i++) + tick_buf[i*2] = tick_buf[i*2+1] = tick_sound[i]; + for(i = 0;i < sizeof(tock_sound)/sizeof(short);i++) + tock_buf[i*2] = tock_buf[i*2+1] = tock_sound[i]; +} + +static void play_tick(void) +{ + rb->pcm_play_data(NULL, NULL, tick_buf, sizeof(tick_buf)); } static void play_tock(void) { - rb->pcm_play_data(NULL, NULL, sndbuf, sizeof(sndbuf)); + rb->pcm_play_data(NULL, NULL, tock_buf, sizeof(tock_buf)); } #endif /* CONFIG_CODEC != SWCODEC */ -static void calc_period(void) -{ - period = 61440/bpm-1; /* (60*1024)/bpm; */ -} - - -static void metronome_draw(struct screen* display) +/* State: 0: blank/title, 1: tick, 2: tock 3: silent klick */ +/* TODO: Could use more smart placement, using + lcd_getstringsize() and such. */ +static void metronome_draw(struct screen* display, int state) { + struct part *ps; +#ifndef HAVE_LCD_BITMAP + char beat1 = ' '; + char beat2 = ' '; +#else + int textlen = display->lcdwidth / display->getcharwidth(); +#endif + ps = part; display->clear_display(); - -#ifdef HAVE_LCD_BITMAP +#ifdef HAVE_LCD_BITMAP display->setfont(FONT_SYSFIXED); - display->puts(0, 0, "Metronome"); - if(display->screen_type==SCREEN_MAIN) +#endif + switch(state) { - display->puts(0, 5, "Select to TAP"); - display->puts(0, 6, "Rec to SYNC"); +#ifdef HAVE_LCD_BITMAP + case 0: + if(sound_paused) + { + if(track_mode) display->puts(0, 0, "Metronome Track"); + else display->puts(0, 0, "Metronome"); + + display->hline(0, display->lcdwidth, 12); + } + break; + /* Draw odd/even ticks/tocks differently to be able to go without + display clearing in between for fast beats. */ + case 1: + if((beat+1) % 2 == 0) + display->fillrect( display->lcdwidth/2, 0 + , display->lcdwidth, 12 ); + else + display->fillrect( 0, 0 + , display->lcdwidth/2-1, 12 ); + break; + case 2: + if((beat+1) % 2 == 0) + display->fillrect( display->lcdwidth/2, display->lcdheight-13 + , display->lcdwidth, 12 ); + else + display->fillrect( 0, display->lcdheight-13 + , display->lcdwidth/2-1, 12 ); + break; + case 3: + display->puts((textlen-3)/2,0, "o.O"); + break; +#else /* Much simpler on 2-line text display, but same thing. */ + case 1: + if((beat+1) % 2 == 0) + beat1 = '/'; + else + beat1 = '\\'; + break; + case 2: + if((beat+1) % 2 == 0) + beat2 = '/'; + else + beat2 = '\\'; + break; + case 3: + beat1 = '.'; + break; +#endif } + + if(track_mode) + { + +#ifdef HAVE_LCD_BITMAP + /* One line in several. */ + rb->snprintf( buffer, sizeof(buffer), "%u/%u@%u V%d" + , ps->beats_per_bar, ps->base_beat + , bpm, rb->global_settings->volume ); + display->puts(0,4, buffer); +#else + /* Just two short lines with integrated beat indicator. */ + rb->snprintf( buffer, sizeof(buffer), "%c %u/%u@%u" + , beat1 + , ps->beats_per_bar, ps->base_beat + , bpm ); + display->puts(0,0, buffer); + /* Simulator prints format %+02d ... real Rockbox doesn't. */ + rb->snprintf( buffer, sizeof(buffer), "%c V%d" + , beat2 + , rb->global_settings->volume ); + display->puts(0,1, buffer); +#endif /* HAVE_LCD_BITMAP */ + +#ifdef HAVE_LCD_BITMAP + /* Would it hurt to draw a 3rd line to 2-line display? + I guess there are 3-line displays out there. */ + if(ps->label && rb->strlen(ps->label)) + { + rb->snprintf(buffer, sizeof(buffer), "\"%s\"", ps->label); + display->puts((textlen-rb->strlen(buffer))/2, 2, buffer); + } + + /* Wildly guessing here with puts(). */ + if(ps->bars) + rb->snprintf( buffer, sizeof(buffer), "P%u/%u: B%u/%u+%u" + , part->id+1, parts, bar+1, ps->bars, beat+1 ); + else + rb->snprintf( buffer, sizeof(buffer), "P%u/%u: B%u/_+%u" + , part->id+1, parts, bar+1, beat+1 ); + display->puts(0, 5, buffer); +#endif /* HAVE_LCD_BITMAP */ + + } + else /* track mode */ + { + +#ifdef HAVE_LCD_BITMAP + if(display->screen_type==SCREEN_MAIN) + { +#ifdef MET_SYNC + display->puts(0, 5, "Select=TAP Rec=SYNC"); +#else + display->puts(0, 5, "Select=TAP"); +#endif + } #ifdef HAVE_REMOTE_LCD - else - { - display->puts(0, 5, "Rec to TAP"); - display->puts(0, 6, "Mode to SYNC"); - } + else + { +#ifdef MET_SYNC + display->puts(0, 5, "Rec=TAP Mode=SYNC"); +#else + display->puts(0, 5, "Rec=TAP"); +#endif + } #endif #endif /* HAVE_LCD_BITMAP */ - rb->snprintf(buffer, sizeof(buffer), "BPM: %d ",bpm); #ifdef HAVE_LCD_BITMAP - display->puts(0,3, buffer); + rb->snprintf( buffer, sizeof(buffer), "BPM: %d Vol: %d" + , bpm, rb->global_settings->volume ); + display->puts(0,3, buffer); #else - display->puts(0,0, buffer); -#endif /* HAVE_LCD_BITMAP */ - - rb->snprintf(buffer, sizeof(buffer), "Vol: %d", - rb->global_settings->volume); -#ifdef HAVE_LCD_BITMAP - display->puts(10, 3, buffer); -#else - display->puts(0,1, buffer); + rb->snprintf( buffer, sizeof(buffer), "%c BPM: %d " + , beat1, bpm ); + display->puts(0,0, buffer); + rb->snprintf( buffer, sizeof(buffer), "%c Vol: %d" + , beat2, rb->global_settings->volume ); + display->puts(0,1, buffer); #endif /* HAVE_LCD_BITMAP */ #ifdef HAVE_LCD_BITMAP - display->hline(0, 111, 12); - if(sound_paused) - display->puts(0,2,METRONOME_MSG_START); - else - display->puts(0,2,METRONOME_MSG_STOP); + display->hline(0, 111, 12); + if(sound_paused) display->puts(0,2,"start: hold select"); + else display->puts(0,2,"stop : cancel"); +#endif /* HAVE_LCD_BITMAP */ + + } /* !track_mode */ + +#ifdef HAVE_LCD_BITMAP display->setfont(FONT_UI); #endif /* HAVE_LCD_BITMAP */ display->update(); } +/* Trigger drawing of display at the next occasion using given state. */ +static void trigger_display(int state) +{ + display_state = state; + display_trigger = true; +} + +/* Actually draw display. */ static void draw_display(void) { FOR_NB_SCREENS(i) - metronome_draw(rb->screens[i]); + metronome_draw(rb->screens[i], display_state); +} + +/* Modify actual volume by given offset without changing the configured one. + This is for parts with associated volume. */ +static void tweak_volume(int offset) +{ + int vol = rb->global_settings->volume + offset; + int minvol = rb->sound_min(SOUND_VOLUME); + int maxvol = rb->sound_max(SOUND_VOLUME); + + if (vol > maxvol) vol = maxvol; + else if(vol < minvol) vol = minvol; + + rb->sound_set(SOUND_VOLUME, vol); +} + +/* tempo at a certain point in beat space in an accelerated part */ +static long accel_tempo(struct part *ps, long offset) +{ + long fp_bpm = (long)ps->bpm<<16; + long fp_bpm2 = (long)ps->bpm2<<16; + long v = fp_bpm + fp_mul(ps->accel, offset, 16); + /* Offset could be negative, actually, so ensure tempo stays within both + bounds */ + if(ps->accel > 0) + { + if(v < fp_bpm) v = fp_bpm; + if(v > fp_bpm2) v = fp_bpm2; + } + else /* deceleration */ + { + if(v > fp_bpm) v = fp_bpm; + if(v < fp_bpm2) v = fp_bpm2; + } + return v; +} + +/* Calculate number of ticks to wait till next beat. */ +static void calc_period(void) +{ + struct part *ps = part; + long deltat; + long beatlen; /* in quarter notes */ + long period_fp; + + beatlen = fp_div(4<<16, ps->base_beat<<16, 16); + /* Hack: Put the factor 60 in before computing deltat, to preserve + some accuracty. */ + if(ps->beat_bpm) + { + bpm = ps->beat_bpm[bar*ps->beats_per_bar+beat]; + deltat = fp_div(fp_mul(60<<16,beatlen,16), bpm<<16, 16); + } else + if(ps->accel == 0.f) + { /* Fixed tempo. */ + bpm = ps->bpm; + /* Minutes per base beat, from quarters per minute. */ + deltat = fp_div(fp_mul(60<<16,beatlen,16), bpm<<16, 16); + } + else + { /* Acceleration, varying period with each beat. */ + long v0, v1; + long offset = (bar*ps->beats_per_bar + beat) << 16; + /* Always computed from start of part for seeking and accuracy. */ + v0 = accel_tempo(ps, fp_mul(beatlen, offset, 16)); + offset += 1<<16; + v1 = accel_tempo(ps, fp_mul(beatlen, offset, 16)); + /* Playing safe with too small tempo changes, avoiding the acceleration + math that might divide by very small deltat. */ + if(labs(v1-v0) > 1<<8) + { + /* deltat = 1.f / ps->accel * rb_log(v1/v0) */ + deltat = fp_mul( fp_div(60<<16, ps->accel, 16) + , fp16_log(fp_div(v1, v0, 16)) + , 16 ); + bpm = fp_rint(fp_div(fp_mul(60<<16, beatlen, 16), deltat, 16)); + } + else + { /* Arbitrarily choosing v1. */ + bpm = fp_rint(v1); + deltat = fp_div(fp_mul(60<<16,beatlen,16), v1, 16); + } + } + /* The treatment of the rounding error when converting to integer + period using period_diff helps a lot to keep track lengths close to + "correct" even with timerfreq_div as low as 77. Actually, I have _less_ + drift than with timerfreq_div of 1000! */ + period_fp = fp_mul(timerfreq_div<<16, deltat, 16) + period_diff; + period = positive(fp_rint( period_fp )); + period_diff = period_fp - (long)(period<<16); +} + +/* Last beat finished, to prepare for the next one. */ +static void advance_beat(void) +{ + if(++beat == part->beats_per_bar) + { + beat = 0; + /* Bar counter always incremented for acceleration, but only checked + against a limit if there is one. */ + ++bar; + if(part->bars && bar == part->bars) + { + bar = 0; + if(part->next) part = part->next; + else + { + part = part_list; + if(!loop) sound_paused = true; + } + tweak_volume(part->volume); + } + } + /* Always recompute period, as acceleration changes it for each beat. */ + calc_period(); +} + +/* Decide what to play, update display, play it. + Beat counting happens here, too. */ +static void play_ticktock(void) +{ + if(beating) advance_beat(); + + /* Hack: Clear trigger to avoid race condition. */ + display_trigger = 0; + if(sound_paused) + { + beating = false; + display_state = 0; + draw_display(); + } + else + { + char pat = 'x'; + if(part->pattern) pat = part->pattern[beat]; + + beating = true; + /* Blinking and specific sound for tick, tock and silent beat. + Drawing display first for slow machines (YH820), to avoid + interrupting audio for regular playback. */ + switch(pat) + { + case 'X': + display_state = 1; + draw_display(); + play_tick(); + break; + case 'x': + display_state = 2; + draw_display(); + play_tock(); + break; + default: + display_state = 3; + draw_display(); + } + } } /* helper function to change the volume by a certain amount, +/- @@ -792,112 +1357,448 @@ static void change_volume(int delta) { int minvol = rb->sound_min(SOUND_VOLUME); int maxvol = rb->sound_max(SOUND_VOLUME); - int vol = rb->global_settings->volume + delta; + int vol = rb->global_settings->volume + delta; - if (vol > maxvol) vol = maxvol; - else if (vol < minvol) vol = minvol; - if (vol != rb->global_settings->volume) { - rb->sound_set(SOUND_VOLUME, vol); + if (vol > maxvol) vol = maxvol; + else if(vol < minvol) vol = minvol; + if(vol != rb->global_settings->volume) + { rb->global_settings->volume = vol; - draw_display(); + tweak_volume(part->volume); + trigger_display(display_state); } } /*function to accelerate bpm change*/ static void change_bpm(int direction) { - if((bpm_step_counter < 20) - || (bpm > 389) - || (bpm < 10)) + if( (bpm_step_counter < 20) + || (bpm > 389) + || (bpm < 10) ) bpm = bpm + direction; - else if (bpm_step_counter < 60) + else if(bpm_step_counter < 60) bpm = bpm + direction * 2; else - bpm = bpm + direction * 9; + bpm = bpm + direction * 9; - if (bpm > 400) bpm = 400; - if (bpm < 1) bpm = 1; + if(bpm > 400) bpm = 400; + if(bpm < 1) bpm = 1; + + part->bpm = bpm; calc_period(); - draw_display(); + trigger_display(display_state); bpm_step_counter++; } +/* I presume the timer ensures that not more than one instance + of the callback is running at a given time. */ static void timer_callback(void) { - if(minitick >= period){ + ++minitick; + + /* Clear blinker if tempo is slow enough. */ + if( (bpm*part->base_beat)/4 <= blinklimit && + !sound_paused && minitick == period/2 ) + trigger_display(0); + + if(minitick >= period) + { minitick = 0; - if(!sound_active && !sound_paused && !tap_count) { -#if CONFIG_CODEC == SWCODEC - /* On SWCODEC we can't call play_tock() directly from an ISR. */ - need_to_play = true; -#else - play_tock(); -#endif + if(!sound_active && !sound_paused && !tap_count) + { + sound_trigger = true; rb->reset_poweroff_timer(); } } - else { - minitick++; - } - if (tap_count) { + if(tap_count) + { tap_time++; - if (tap_count > 1 && tap_time > tap_timeout) + if(tap_count > 1 && tap_time > tap_timeout) tap_count = 0; } } +/* Stopping playback means incrementing the beat. Normally, it would be + incremented after the passing of the current note duration, naturally + while starting the next one. */ +static void metronome_pause(void) +{ + if(beating) + { + /* Finish the current beat. */ + advance_beat(); + beating = false; + } + sound_paused = true; + trigger_display(0); + rb->timer_unregister(); +} + +static void metronome_unpause(void) +{ + sound_paused = false; + minitick = period; /* Start playing immediately (or after a millisecond). */ + /* Conserve power: Only start timer when actually playing. */ + rb->timer_register( 1, NULL, TIMER_FREQ/timerfreq_div + , timer_callback IF_COP(, CPU) ); +} + static void cleanup(void) { - rb->timer_unregister(); + if(fd >= 0) rb->close(fd); + + metronome_pause(); MET_PLAY_STOP; /* stop audio ISR */ + tweak_volume(0); rb->led(0); #if CONFIG_CODEC == SWCODEC rb->pcm_set_frequency(HW_SAMPR_DEFAULT); #endif } +/* + Parse part definitions from tempomap file (see header for format). + Not bothering with encoding issues here. +*/ + +/* parse meter spec into part structure if given token matches */ +static bool parse_meter(char *token, struct part *ps) +{ + char *toktok; + /* Careful not to misinterpret accelerated tempo specification: + 120-150/4 -> tempo + 3/4 -> meter */ + if( !rb->strchr(token, '-') && (toktok = rb->strchr(token, '/')) ) + { + /* Number before and after the '/'. */ + int num[2]; + num[0] = rb->atoi(token); + num[1] = rb->atoi(++toktok); + /* Only accept positive numbers. */ + if(num[0] > 0 && num[1] > 0) + { + ps->beats_per_bar = (unsigned int) num[0]; + ps->base_beat = (unsigned int) num[1]; + return true; + } + } + return false; +} + +/* Parse tempo, successful when getting a positive integer out of the token. */ +static bool parse_tempo(char *token, struct part *ps) +{ + char *toktok; + /* tempo[-tempo2/accel] ... first number always main tempo */ + int num = rb->atoi(token); + /* Only positive numbers. This avoids the pattern string and general + strangeness, unless -150 should mean "from previous tempo to 150". */ + if(num < 1) return false; + + ps->bpm = (unsigned int) num; + ps->bpm2 = ps->bpm; + ps->accel = 0; + /* This parser is not fool-proof. It parses valid data, but could + do funny things if you provide tempo/tempo2-accel, for example. + My credo is that the application doesn't crash, but if you give rubbish, + you'll get rubbish. */ + if( (toktok = rb->strchr(token, '-')) ) + { + char *subtok = toktok+1; + float faccel = 0.; + ps->bpm2 = positive(rb->atoi(subtok)); + /* Parse or compute accel in bpm/bar. */ + if( (toktok = rb->strchr(subtok, '/')) ) + { /* bars/bpm */ + float c = rb_atof(++toktok); + if( (c > 0.f ? c : -c) > 0.0001f) + faccel = 1./c; + } + else if( (toktok = rb->strchr(subtok, '*')) ) + { /* bpm/bar */ + faccel = rb_atof(++toktok); + } + else if(ps->bars > 0) + { /* Compute from tempo difference and bar count. */ + faccel = ((float)ps->bpm2 - (float)ps->bpm)/ps->bars; + } + /* Correct sign for all cases, starting with positive value. */ + if(faccel < 0) faccel = -faccel; + /* Negative only when end tempo is smaller. */ + if(ps->bpm2 < ps->bpm) faccel = -faccel; + /* Convert (quarterbeats-per-minute per bar) -> 1/min, which could be + seen as beats-per-minute/beat */ + faccel *= 1.f / (4.f/ps->base_beat * ps->beats_per_bar); /* 1/min */ + ps->accel = fp_frac(faccel); + } else + /* The other fancy variant: One tempo per beat. */ + if( (toktok = rb->strchr(token, ',')) ) + { + size_t i; + char *subtok = token; + /* It is a bug when the parser called this before. Alloc once. */ + if( ps->beat_bpm || !(ps->beat_bpm = + mem_allocate(sizeof(unsigned int)*ps->beats_per_bar*ps->bars)) ) + return false; + for(i=0; ibeats_per_bar*ps->bars; ++i) + { + int num; + if(!subtok) return false; + if(subtok != token) ++subtok; + + num = rb->atoi(subtok); + if(num < 1) return false; + + ps->beat_bpm[i] = (unsigned int) num; + subtok = rb->strchr(subtok, ','); + } + } + return true; +} + +/* The metronome pattern. + Ensure that the correct meter is present before calling this! */ +static bool parse_pattern(char *token, struct part *ps) +{ + size_t pi; + size_t pats = rb->strlen(token); + + /* First check if the pattern is valid, error out if not. */ + if(pats != ps->beats_per_bar) + return false; + for(pi=0; pipattern || (ps->pattern = mem_allocate(pats)))) + return false; + /* Now store it. */ + memcpy(ps->pattern, token, pats); + return true; +} + +static bool parse_volume(char *token, struct part *ps) +{ + float factor = rb_atof(token); + ps->volume = fp_rint(fp_decibels(fp_frac(factor > 0.f ? factor : 0.f), 16)); + return true; +} + +/* Check condition, set error code and bail out if violated. */ +#define CHECK(a, c) if(!(a)){ errcode = c; goto parse_part_revert; } + +static void parse_part(char *line, unsigned int num) +{ + char *saveptr; + char *toktok; + char *token[5]; + struct part *ps; + size_t tokens = 0; + unsigned int errcode = MERR_NOTHING; + + while (isspace(*line)) line++; + /* Skip comments and empty lines quickly. */ + if(line[0] == '#' || line[0] == 0) return; + + mem_checkpoint(); + CHECK(ps = mem_allocate(sizeof(struct part)), MERR_OOM); + part_init(ps); + + /* Check for and store label. */ + if( (toktok = rb->strchr(line, ':')) ) + { + size_t len = toktok-line; + CHECK(ps->label = mem_allocate(len+1), MERR_OOM); + rb->memcpy(ps->label, line, len); + ps->label[len] = 0; + line = toktok+1; + } + + CHECK(token[0] = rb->strtok_r(line, " \t", &saveptr), MERR_MISSING); + tokens = 1; + /* After the optional label, there can be up to 5 tokens of interest. + Collect them in advance to make the parser code more sane. */ + while( tokens < 5 + && (token[tokens] = rb->strtok_r(NULL, " \t", &saveptr)) ) + { + if(token[tokens][0] == '#') + break; + ++tokens; + } + + CHECK(tokens >= 2, MERR_MISSING); + + /* Now try to be smart about guessing which token can be what value. + Remember: Always parse meter before pattern or tempo! */ + ps->bars = (unsigned int) rb->atoi(token[0]); + if(tokens == 2) /* */ + { + CHECK(parse_tempo(token[1], ps), MERR_TEMPO); + } else + if(tokens == 3) + { + /* */ + if(parse_meter(token[1], ps)) + { + CHECK(parse_tempo(token[2], ps), MERR_TEMPO); + } else + /* */ + if(parse_pattern(token[2], ps)) + { + CHECK(parse_tempo(token[1], ps), MERR_TEMPO); + } else + /* */ + { + CHECK(parse_tempo(token[1], ps), MERR_TEMPO); + CHECK(parse_volume(token[2], ps), MERR_VOLUME); + } + } else + if(tokens == 4) + { + /* */ + if(parse_meter(token[1], ps) && parse_pattern(token[3], ps)) + { + CHECK(parse_tempo(token[2], ps), MERR_TEMPO); + } else + /* */ + if(parse_pattern(token[2], ps)) + { + CHECK(parse_tempo(token[1], ps), MERR_TEMPO); + CHECK(parse_volume(token[3], ps), MERR_VOLUME); + } else + /* */ + { + CHECK(parse_meter(token[1], ps), MERR_METER); + CHECK(parse_tempo(token[2], ps), MERR_TEMPO); + CHECK(parse_volume(token[3], ps), MERR_VOLUME); + } + } else + if(tokens == 5) /* the complete set */ + { + /* */ + CHECK(parse_meter(token[1], ps), MERR_METER); + CHECK(parse_tempo(token[2], ps), MERR_TEMPO); + CHECK(parse_pattern(token[3], ps), MERR_PATTERN); + CHECK(parse_volume(token[4], ps), MERR_VOLUME); + } + + if(!ps->pattern) + { + /* For parsed parts default to emphasize every first beat. */ + CHECK(ps->pattern = mem_allocate(ps->beats_per_bar), MERR_OOM); + memset(ps->pattern, 'x', ps->beats_per_bar); + ps->pattern[0] = 'X'; + } + + part_add(ps); + return; /* all good */ + + /* Remove part after some error. */ +parse_part_revert: + rb->snprintf(buffer, sizeof(buffer), "ERR %u @line %u", errcode, num); + rb->splash(2*HZ, buffer); + ++bad_parts; + mem_reset(); +} + +#undef CHECK + +static void step_back(void) +{ + beating = false; + beat = 0; + if(bar) + { + /* Endless parts only know position 0 to step to. */ + if(part->bars) --bar; + else bar = 0; + } + else if(part->prev) + { + part = part->prev; + /* This will jump to bar 0 for endless parts. */ + bar = positive(part->bars)-1; + tweak_volume(part->volume); + } + /* Always calculate period for acceleration. */ + calc_period(); + minitick = period; +} + +static void step_forw(void) +{ + beating = false; + /* Stepping forward in endless part always goes to the next one, if any. */ + if(part->bars == 0 || bar+1 == part->bars) + { + if(part->next) + { /* Advanced one part. */ + part = part->next; + bar = 0; + beat = 0; + tweak_volume(part->volume); + } + } + else ++bar; + /* Always calculate period for acceleration. */ + calc_period(); + minitick = period; +} + static void tap(void) { - if (tap_count == 0 || tap_time < tap_count) { - tap_time = 0; - } - else { - if (tap_time > 0) { - bpm = 61440/(tap_time/tap_count); + struct part *ps = part; - if (bpm > 400) - bpm = 400; + /* Each tap resets the position. */ + beat = 0; + bar = 0; + + if(tap_count == 0 || tap_time < tap_count) + tap_time = 0; + else + { + if(tap_time > 0) + { + /* Could use fixed point math and rounding, even. */ + ps->bpm = 60*timerfreq_div*tap_count/tap_time; + + if(ps->bpm > 400) ps->bpm = 400; } - - calc_period(); - draw_display(); - tap_timeout = (tap_count+2)*tap_time/tap_count; } tap_count++; minitick = 0; /* sync tock to tapping */ - play_tock(); - reset_tap = false; + play_ticktock(); } -enum plugin_status plugin_start(const void* parameter) +enum plugin_status plugin_start(const void* file) { int button; static int last_button = BUTTON_NONE; + bool common_action; - (void)parameter; atexit(cleanup); - if (MET_IS_PLAYING) - MET_PLAY_STOP; /* stop audio IS */ + mem_init(); -#if CONFIG_CODEC != SWCODEC - rb->bitswap(sound, sizeof(sound)); + if(MET_IS_PLAYING) MET_PLAY_STOP; /* stop audio IS */ + +#if (CONFIG_CODEC != SWCODEC) +#ifndef SIMULATOR + rb->bitswap(tick_sound, sizeof(tick_sound)); + rb->bitswap(tock_sound, sizeof(tock_sound)); +#endif #else - prepare_tock(); + prepare_buffers(); #if INPUT_SRC_CAPS != 0 /* Select playback */ rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); @@ -906,92 +1807,168 @@ enum plugin_status plugin_start(const void* parameter) rb->pcm_set_frequency(SAMPR_44); #endif /* CONFIG_CODEC != SWCODEC */ - calc_period(); - rb->timer_register(1, NULL, TIMER_FREQ/1024, timer_callback IF_COP(, CPU)); + if(file) + { + parts = 0; + bad_parts = 0; + fd = rb->open(file, O_RDONLY); + if(fd >= 0) + { + unsigned int linenum = 0; + /* Crazyness, allocating line buffer depending on free memory. */ + linebuf_size = mem_end - mem_free_region > 32*1024 + ? 1024 + : ( mem_end - mem_free_region > 16*1024 + ? 256 + : 128 ); + if(!(linebuf = mem_allocate(linebuf_size))) return PLUGIN_ERROR; + /* I'm assuming that read_line always terminates. */ + while(rb->read_line(fd, linebuf, linebuf_size) > 0) + { + parse_part(linebuf, ++linenum); + } + } + rb->close(fd); + if(bad_parts) + { + rb->snprintf(buffer, sizeof(buffer), "%u bad parts", bad_parts); + rb->splash(2*HZ, buffer); + } + if(!parts) + { + rb->splash(2*HZ, "Got no parts. Bye!"); + return PLUGIN_OK; + } + } + /* If no parts given, start in simple metronome mode. */ + if(!parts) + { /* Just checking the early bailout here. */ + struct part *ps = mem_allocate(sizeof(struct part)); + if(!ps) return PLUGIN_ERROR; + part_init(ps); + part_add(ps); + track_mode = false; + } + else track_mode = true; + + part = part_list; + tweak_volume(part->volume); + calc_period(); draw_display(); /* main loop */ - while (true){ + while(true) + { reset_tap = true; -#if CONFIG_CODEC == SWCODEC - button = pluginlib_getaction(TIMEOUT_NOBLOCK,plugin_contexts,PLA_ARRAY_COUNT); - if (need_to_play) + button = pluginlib_getaction( TIMEOUT_NOBLOCK, plugin_contexts + , PLA_ARRAY_COUNT ); + if(sound_trigger) { - need_to_play = false; - play_tock(); + sound_trigger = false; + play_ticktock(); /* Draws display before playback. */ } -#else - button = pluginlib_getaction(TIMEOUT_BLOCK, - plugin_contexts,PLA_ARRAY_COUNT); -#endif /* SWCODEC */ - switch (button) { + common_action = false; + if(track_mode) + { + switch(button) + { + case METRONOME_START: + if(sound_paused) metronome_unpause(); + else metronome_pause(); + break; + case METRONOME_PAUSE: + if(!sound_paused) metronome_pause(); + break; + case METRONOME_LEFT: + case METRONOME_LEFT_REP: + step_back(); + trigger_display(0); + break; + case METRONOME_RIGHT: + case METRONOME_RIGHT_REP: + step_forw(); + trigger_display(0); + break; + default: + common_action = true; + } + } + else + { + switch(button) + { + case METRONOME_PAUSE: + if(!sound_paused) metronome_pause(); + break; + case METRONOME_PLAY: + if(sound_paused) metronome_unpause(); + break; + case METRONOME_TAP: + if(last_button != METRONOME_PLAY) + { + if(sound_paused) metronome_unpause(); + tap(); + } + break; + case METRONOME_LEFT: + bpm_step_counter = 0; + case METRONOME_LEFT_REP: + change_bpm(-1); + break; + case METRONOME_RIGHT: + bpm_step_counter = 0; + case METRONOME_RIGHT_REP: + change_bpm(1); + break; +#ifdef MET_SYNC + case METRONOME_SYNC: + minitick = period; + break; +#endif + default: + common_action = true; + } + } + + if(common_action) + switch(button) + { case METRONOME_QUIT: /* get out of here */ return PLUGIN_OK; - - case METRONOME_PAUSE: - if(!sound_paused) - { - sound_paused = true; - draw_display(); - } - break; - case METRONOME_PLAY: - if(sound_paused) - { - sound_paused = false; - calc_period(); - draw_display(); - } - break; - case METRONOME_TAP: - if (last_button != METRONOME_PLAY) - tap(); - break; case METRONOME_VOL_UP: case METRONOME_VOL_UP_REP: change_volume(1); - calc_period(); + trigger_display(0); break; - case METRONOME_VOL_DOWN: case METRONOME_VOL_DOWN_REP: change_volume(-1); - calc_period(); + trigger_display(0); break; - - case METRONOME_LEFT: - bpm_step_counter = 0; - case METRONOME_LEFT_REP: - change_bpm(-1); - break; - - case METRONOME_RIGHT: - bpm_step_counter = 0; - case METRONOME_RIGHT_REP: - change_bpm(1); - break; - -#ifdef MET_SYNC - case METRONOME_SYNC: - minitick = period; - break; -#endif - default: exit_on_usb(button); reset_tap = false; break; + } - } - if (button) + if(button) last_button = button; - if (reset_tap) { + if(reset_tap) tap_count = 0; + /* If there was some action, display drawing is still needed. + This _might_ disturb audio on slow machines, but + then, you could just stop pressing buttons, then;-) */ + if(display_trigger) + { + display_trigger = false; + draw_display(); } + + /* This determines the accuracy of the metronome with SWCODEC ... the + scheduler decides when we are allowed to play. */ rb->yield(); } } - diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config index 24c888b956..9eca2dab1a 100644 --- a/apps/plugins/viewers.config +++ b/apps/plugins/viewers.config @@ -63,6 +63,8 @@ sok,games/sokoban,1 pgn,games/chessbox,1 sgf,games/goban,1 ss,games/sudoku,1 +tempo,apps/metronome,1 +tempo,apps/text_editor,2 wav,viewers/wavplay,9 wav,viewers/wavview,10 wav,viewers/wav2wv,- diff --git a/docs/CREDITS b/docs/CREDITS index 8d33a65780..17f1d56020 100644 --- a/docs/CREDITS +++ b/docs/CREDITS @@ -644,6 +644,7 @@ Jonathan Bettencourt Ilia Sergachev Nial Shui Mihail Zenkov +Thomas Orgis The libmad team The wavpack team diff --git a/manual/plugins/metronome.tex b/manual/plugins/metronome.tex index e792498984..760507e9b9 100644 --- a/manual/plugins/metronome.tex +++ b/manual/plugins/metronome.tex @@ -1,6 +1,23 @@ \subsection{Metronome} + This plugin can be used as a metronome to keep time during music -practice. Adjust the tempo through the interface or by tapping it out +practice. It supports two modes of operation, depending on it being +started from the plugin menu or as viewer for tempomap (\verb:.tempo:) +files. + +The sound is a piercing square wave that can be heard well also +through loud music from a band. +In addition, the display also indicates the beats while playing +so that you can discreetly place the device +in your sight for checking the tempo instead of wearing +headphones at a concert. + +\subsubsection{Simple Interactive Mode} + +This is the mode of operation that is active when starting the +plugin directly from the menu. It offers a uniform metronome sound at +a constant tempo. +You can adjust the tempo through the interface or by tapping it out on the appropriate button. \begin{btnmap} @@ -34,3 +51,159 @@ on the appropriate button. \opt{HAVEREMOTEKEYMAP}{& } & Sync tap \\} \end{btnmap} + + +\subsubsection{Programmed Track Mode} + +When starting the plugin as a viewer for tempomap files +(ending in \verb:.tempo:), it starts in the track mode that offers +playback of a preprogrammed metronome track consisting out of +multiple parts, each with possibly different properties. + +In contrast to the simple mode, there exists the notion of +meter and bars, along with emphasis on certain beats. +Parts can have these properties: + +\begin{itemize} + \item finite or infinite duration in bars (navigation only jumps + to the beginning of infinite parts), + \item differing meters (4/4, 3/4, 6/8, etc., default 4/4), + \item differing tempo (always in quarter beats per minute, + default 120) with + \begin{itemize} + \item one tempo per bar or even one tempo per beat, or + \item smooth tempo changes with configurable acceleration, and + \end{itemize} + \item custom beat patterns (tick/tock/silence on each beat), + default being emphasis (tick) on first beat, normal sound + (tock) on others. +\end{itemize} + +\paragraph{The button mapping} +is different to enable navigation in the programmed track. +\begin{btnmap} + \PluginExit + \opt{HAVEREMOTEKEYMAP}{& } + & Exit plugin \\ + + \PluginCancel + \opt{HAVEREMOTEKEYMAP}{& \PluginRCCancel} + & Stop (stay at position) \\ + + \PluginSelect + \opt{HAVEREMOTEKEYMAP}{& \PluginRCSelect} + & Start from / Stop at current position \\ + + \PluginLeft{} / \PluginRight + \opt{HAVEREMOTEKEYMAP}{& \PluginRCLeft{} / \PluginRCRight} + & Seek in track \\ + + \opt{scrollwheel}{\PluginScrollFwd{} / \PluginScrollBack} + \nopt{scrollwheel}{\PluginUp{} / \PluginDown} + \opt{HAVEREMOTEKEYMAP}{& \PluginRCUp{} / \PluginRCDown} + & Adjust volume \\ + + \opt{IRIVER_H100_PAD,IRIVER_H300_PAD,SANSA_E200_PAD}{ + \ButtonRec + \opt{HAVEREMOTEKEYMAP}{& } + & Sync tap \\} +\end{btnmap} + +\paragraph{Navigation} +The display indicates the part properties and position in track as such: +\begin{verbatim} + Metronome Track + --------------- + "Interlude" + 3/4@120 V-25 + P2/13: B1/5+2 +\end{verbatim} +In this example, the part label is ``Interlude'', the meter is 3/4 and +the tempo 120 quarter beats per minute (bpm). The volume setting is at -25 +and this is the second part of a track with 13 total. In that part, +the position is at the second beat of the first bar of five. + +\paragraph{The syntax of programmed tracks} +in tempomap files follows the format defined by +\url{http://das.nasophon.de/klick/}. +Actually, the goal is to keep compatibility between klick and this +Rockbox metronome. +The parts of a track are specified one line each in this scheme +(pieces in [] optional): +\begin{verbatim} +[name:] bars [meter ]tempo[-tempo2[*accel|/accel] [pattern] [volume] +\end{verbatim} +The bar count and tempo always have to be specified, the rest is optional. + +One example is +\begin{verbatim} +part I: 12 3/4 133 +\end{verbatim} +for a part named ``part I'' , 12 bars long, in 3/4 meter with +a tempo of 133 quarter beats per minute. +Tempo changes are indicated by specifying a tempo range and the +acceleration in one of these ways: +\begin{verbatim} +0 4/4 90-150*0.25 +0 4/4 150-90/4 +16 4/4 100-200 +\end{verbatim} +The first one goes from 90 to 150 bpm in an endless part with 0.25 bpm +increase per bar. The second one goes down from 150 to 90 with +4 bars per bpm change, which is the same acceleration as in the first line. +The last one is a part of 16 bars length that changes tempo from 100 to 200 +smoothly during its whole lifetime (6.25 bpm/bar). For details on how the +acceleration works, see +\url{http://thomas.orgis.org/science/metronome-tempomath/tempomath.html}. + +It is also possible to provide a tempo for each individual beat in a part +by separating values with a comma (no spaces), +\begin{verbatim} +varibeat: 3 4/4 135,90,78,100,120,120,99,100,43,94,120,133 +\end{verbatim} +where the beat duration is first according to 135 bpm, then 90 bpm, +and so forth. You are required to provide a value for each beat +in all bars of the part. + +You can provide a pattern that controls how the beats are played: +\begin{center} +\begin{tabular}{c|l} + Symbol & Meaning \\ + \hline + X & emphasized beat (Tick) \\ + x & normal beat (Tock) \\ + . & silent beat +\end{tabular} +\end{center} + +Some examples: +\begin{verbatim} +default: 0 4/4 120 Xxxx +rockon2: 0 4/4 120 xXxX + solea: 0 12/4 180 xxXxxXxXxXxX +shuffle: 0 12/12 120 x.xX.xx.xX.. + funky: 0 16/16 120 x.x.X..X.Xx.X..X +\end{verbatim} +The 12/12 for the shuffle create 1/4 triplets. Just do a bit of math;-) +This is still a metronome, not a drum machine, but it can act like a basic +one, helping you to figure out a certain rhythm within the meter. + +The UI is developed so that it fits into the display of a Sansa Clip+ and +that is the hardware device it is tested on. It seems to work reasonably +on some other models in the simulator. + +At last, a more complete tempomap file: +\begin{verbatim} +# An example track exercising the programmable Rockbox metronome +# or also http://das.nasophon.de/klick/. + lead-in: 1 4/4 120 XXXX 0.5 # 4 emphasized but less loud ticks + intro: 4 4/4 120 # standard beat +tearing down: 4 120-90 # changing tempo from 120 to 90 + break: 2 1/4 90 # 2 1/4 bars at 90 + rolling: 2 6/8 90 # 2 6/8 at same tempo (quarters!) + rumbling: 4 3/4 90 X.x # 3/4, first (tick) and last (tock) + ramp-up: 8 2/4 90-150 # speeding up to 150 bpm again + flow: 4 150 # steady 4/4 at 150 bpm + death: 8 150-60 # going down to 60 + final: 1 1/1 60 # one last hit +\end{verbatim}