summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/SOURCES6
-rw-r--r--apps/plugins/metronome.c2483
-rw-r--r--apps/plugins/viewers.config2
-rw-r--r--docs/CREDITS1
-rw-r--r--manual/plugins/metronome.tex175
5 files changed, 1907 insertions, 760 deletions
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index fba1655..3865fbf 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 c519608..e8014b7 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"
-
-
-
-#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};
+#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.
+
+ 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_tock(void)
+static void play_tick(void)
{
- rb->pcm_play_data(NULL, NULL, sndbuf, sizeof(sndbuf));
+ rb->pcm_play_data(NULL, NULL, tick_buf, sizeof(tick_buf));
}
-#endif /* CONFIG_CODEC != SWCODEC */
-
-static void calc_period(void)
+static void play_tock(void)
{
- period = 61440/bpm-1; /* (60*1024)/bpm; */
+ rb->pcm_play_data(NULL, NULL, tock_buf, sizeof(tock_buf));
}
+#endif /* CONFIG_CODEC != SWCODEC */
-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
}
-#ifdef HAVE_REMOTE_LCD
- else
+
+ if(track_mode)
{
- display->puts(0, 5, "Rec to TAP");
- display->puts(0, 6, "Mode to SYNC");
+
+#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
+ {
+#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);
+ 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 */
- 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);
+ 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->hline(0, 111, 12);
- if(sound_paused)
- display->puts(0,2,METRONOME_MSG_START);
- else
- display->puts(0,2,METRONOME_MSG_STOP);
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;
}
}
-static void cleanup(void)
+/* 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)
+{
+ 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
}
-static void tap(void)
+/*
+ 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)
{
- if (tap_count == 0 || tap_time < tap_count) {
- tap_time = 0;
- }
- else {
- if (tap_time > 0) {
- bpm = 61440/(tap_time/tap_count);
+ 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; i<ps->beats_per_bar*ps->bars; ++i)
+ {
+ int num;
+ if(!subtok) return false;
+ if(subtok != token) ++subtok;
+
+ num = rb->atoi(subtok);
+ if(num < 1) return false;
- if (bpm > 400)
- bpm = 400;
+ ps->beat_bpm[i] = (unsigned int) num;
+ subtok = rb->strchr(subtok, ',');
}
+ }
+ return true;
+}
- calc_period();
- draw_display();
+/* 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; pi<pats; ++pi)
+ switch(token[pi])
+ {
+ case 'X':
+ case 'x':
+ case '.':
+ break;
+ default: return false;
+ }
+
+ if(!(ps->pattern || (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) /* <bars> <tempo> */
+ {
+ CHECK(parse_tempo(token[1], ps), MERR_TEMPO);
+ } else
+ if(tokens == 3)
+ {
+ /* <bars> <meter> <tempo> */
+ if(parse_meter(token[1], ps))
+ {
+ CHECK(parse_tempo(token[2], ps), MERR_TEMPO);
+ } else
+ /* <bars> <tempo> <pattern> */
+ if(parse_pattern(token[2], ps))
+ {
+ CHECK(parse_tempo(token[1], ps), MERR_TEMPO);
+ } else
+ /* <bars> <tempo> <volume> */
+ {
+ CHECK(parse_tempo(token[1], ps), MERR_TEMPO);
+ CHECK(parse_volume(token[2], ps), MERR_VOLUME);
+ }
+ } else
+ if(tokens == 4)
+ {
+ /* <bars> <meter> <tempo> <pattern> */
+ if(parse_meter(token[1], ps) && parse_pattern(token[3], ps))
+ {
+ CHECK(parse_tempo(token[2], ps), MERR_TEMPO);
+ } else
+ /* <bars> <tempo> <pattern> <volume> */
+ if(parse_pattern(token[2], ps))
+ {
+ CHECK(parse_tempo(token[1], ps), MERR_TEMPO);
+ CHECK(parse_volume(token[3], ps), MERR_VOLUME);
+ } else
+ /* <bars> <meter> <tempo> <volume> */
+ {
+ 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 */
+ {
+ /* <bars> <meter> <tempo> <pattern> <volume> */
+ 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)
+{
+ struct part *ps = part;
+
+ /* 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;
+ }
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. */
+ }
+
+ 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;
+ }
}
-#else
- button = pluginlib_getaction(TIMEOUT_BLOCK,
- plugin_contexts,PLA_ARRAY_COUNT);
-#endif /* SWCODEC */
- switch (button) {
+ 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 24c888b..9eca2da 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 8d33a65..17f1d56 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 e792498..760507e 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}