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