rockbox/apps/plugins/metronome.c
Sebastian Leonhardt a507bb2837 YH8xx,YH9xx: Keymap improvement
The main "innovation" in this patch are two "virtual buttons"
for the record switch on YH92x targets. When the switch state
changes, a single BUTTON_REC_SW_ON or .._OFF button event will
be generated. Thus keymap code can react on switching, but
not on the actual state of the switch.

Wherever sensible, the following user scheme is applied:
- use PLAY as confirm button
- use REW button or Long REW to exit
- use REC (YH820) or FFWD (YH92X) as modifier key for button combos

Change-Id: Ic8d1db9cc6869daed8dda98990dfdf7f6fd5d5a1
2015-11-15 23:46:39 +01:00

1973 lines
74 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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.
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 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)
#define MET_SYNC
#endif
#define METRONOME_QUIT PLA_EXIT
#ifdef HAVE_SCROLLWHEEL
#define METRONOME_VOL_UP PLA_SCROLL_FWD
#define METRONOME_VOL_UP_REP PLA_SCROLL_FWD_REPEAT
#define METRONOME_VOL_DOWN PLA_SCROLL_BACK
#define METRONOME_VOL_DOWN_REP PLA_SCROLL_BACK_REPEAT
#else
#define METRONOME_VOL_UP PLA_UP
#define METRONOME_VOL_DOWN PLA_DOWN
#define METRONOME_VOL_UP_REP PLA_UP_REPEAT
#define METRONOME_VOL_DOWN_REP PLA_DOWN_REPEAT
#endif
#define METRONOME_LEFT PLA_LEFT
#define METRONOME_RIGHT PLA_RIGHT
#define METRONOME_LEFT_REP PLA_LEFT_REPEAT
#define METRONOME_RIGHT_REP PLA_RIGHT_REPEAT
#define METRONOME_TAP PLA_SELECT_REL
#define METRONOME_PAUSE PLA_CANCEL
#define METRONOME_PLAY PLA_SELECT_REPEAT
#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 },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_PLUGIN)
};
#endif /* IRIVER_H100_PAD||IRIVER_H300_PAD */
const struct button_mapping *plugin_contexts[] =
{
pla_main_ctx,
#if defined(MET_SYNC)
iriver_syncaction,
#endif
};
#define PLA_ARRAY_COUNT sizeof(plugin_contexts)/sizeof(plugin_contexts[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;
/* 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;
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()
static void callback(const void** start, size_t* size)
{
(void)start; /* unused parameter, avoid warning */
*size = 0; /* end of data */
sound_active = false;
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(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];
/* Convert the mono samples to interleaved stereo */
static void prepare_buffers(void)
{
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, tock_buf, sizeof(tock_buf));
}
#endif /* CONFIG_CODEC != SWCODEC */
/* 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
display->setfont(FONT_SYSFIXED);
#endif
switch(state)
{
#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
{
#ifdef MET_SYNC
display->puts(0, 5, "Rec=TAP Mode=SYNC");
#else
display->puts(0, 5, "Rec=TAP");
#endif
}
#endif
#endif /* HAVE_LCD_BITMAP */
#ifdef HAVE_LCD_BITMAP
rb->snprintf( buffer, sizeof(buffer), "BPM: %d Vol: %d"
, bpm, rb->global_settings->volume );
display->puts(0,3, buffer);
#else
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,"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], 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, +/-
ripped from video.c */
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;
if (vol > maxvol) vol = maxvol;
else if(vol < minvol) vol = minvol;
if(vol != rb->global_settings->volume)
{
rb->global_settings->volume = vol;
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) )
bpm = bpm + direction;
else if(bpm_step_counter < 60)
bpm = bpm + direction * 2;
else
bpm = bpm + direction * 9;
if(bpm > 400) bpm = 400;
if(bpm < 1) bpm = 1;
part->bpm = bpm;
calc_period();
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)
{
++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)
{
sound_trigger = true;
rb->reset_poweroff_timer();
}
}
if(tap_count)
{
tap_time++;
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)
{
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; i<ps->beats_per_bar*ps->bars; ++i)
{
int num;
if(!subtok) return false;
if(subtok != token) ++subtok;
num = rb->atoi(subtok);
if(num < 1) return false;
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; pi<pats; ++pi)
switch(token[pi])
{
case 'X':
case 'x':
case '.':
break;
default: return false;
}
if(!(ps->pattern || (ps->pattern = mem_allocate(pats))))
return false;
/* Now store it. */
memcpy(ps->pattern, token, pats);
return true;
}
static bool parse_volume(char *token, struct part *ps)
{
float factor = rb_atof(token);
ps->volume = fp_rint(fp_decibels(fp_frac(factor > 0.f ? factor : 0.f), 16));
return true;
}
/* Check condition, set error code and bail out if violated. */
#define CHECK(a, c) if(!(a)){ errcode = c; goto parse_part_revert; }
static void parse_part(char *line, unsigned int num)
{
char *saveptr;
char *toktok;
char *token[5];
struct part *ps;
size_t tokens = 0;
unsigned int errcode = MERR_NOTHING;
while (isspace(*line)) line++;
/* Skip comments and empty lines quickly. */
if(line[0] == '#' || line[0] == 0) return;
mem_checkpoint();
CHECK(ps = mem_allocate(sizeof(struct part)), MERR_OOM);
part_init(ps);
/* Check for and store label. */
if( (toktok = rb->strchr(line, ':')) )
{
size_t len = toktok-line;
CHECK(ps->label = mem_allocate(len+1), MERR_OOM);
rb->memcpy(ps->label, line, len);
ps->label[len] = 0;
line = toktok+1;
}
CHECK(token[0] = rb->strtok_r(line, " \t", &saveptr), MERR_MISSING);
tokens = 1;
/* After the optional label, there can be up to 5 tokens of interest.
Collect them in advance to make the parser code more sane. */
while( tokens < 5
&& (token[tokens] = rb->strtok_r(NULL, " \t", &saveptr)) )
{
if(token[tokens][0] == '#')
break;
++tokens;
}
CHECK(tokens >= 2, MERR_MISSING);
/* Now try to be smart about guessing which token can be what value.
Remember: Always parse meter before pattern or tempo! */
ps->bars = (unsigned int) rb->atoi(token[0]);
if(tokens == 2) /* <bars> <tempo> */
{
CHECK(parse_tempo(token[1], ps), MERR_TEMPO);
} else
if(tokens == 3)
{
/* <bars> <meter> <tempo> */
if(parse_meter(token[1], ps))
{
CHECK(parse_tempo(token[2], ps), MERR_TEMPO);
} else
/* <bars> <tempo> <pattern> */
if(parse_pattern(token[2], ps))
{
CHECK(parse_tempo(token[1], ps), MERR_TEMPO);
} else
/* <bars> <tempo> <volume> */
{
CHECK(parse_tempo(token[1], ps), MERR_TEMPO);
CHECK(parse_volume(token[2], ps), MERR_VOLUME);
}
} else
if(tokens == 4)
{
/* <bars> <meter> <tempo> <pattern> */
if(parse_meter(token[1], ps) && parse_pattern(token[3], ps))
{
CHECK(parse_tempo(token[2], ps), MERR_TEMPO);
} else
/* <bars> <tempo> <pattern> <volume> */
if(parse_pattern(token[2], ps))
{
CHECK(parse_tempo(token[1], ps), MERR_TEMPO);
CHECK(parse_volume(token[3], ps), MERR_VOLUME);
} else
/* <bars> <meter> <tempo> <volume> */
{
CHECK(parse_meter(token[1], ps), MERR_METER);
CHECK(parse_tempo(token[2], ps), MERR_TEMPO);
CHECK(parse_volume(token[3], ps), MERR_VOLUME);
}
} else
if(tokens == 5) /* the complete set */
{
/* <bars> <meter> <tempo> <pattern> <volume> */
CHECK(parse_meter(token[1], ps), MERR_METER);
CHECK(parse_tempo(token[2], ps), MERR_TEMPO);
CHECK(parse_pattern(token[3], ps), MERR_PATTERN);
CHECK(parse_volume(token[4], ps), MERR_VOLUME);
}
if(!ps->pattern)
{
/* For parsed parts default to emphasize every first beat. */
CHECK(ps->pattern = mem_allocate(ps->beats_per_bar), MERR_OOM);
memset(ps->pattern, 'x', ps->beats_per_bar);
ps->pattern[0] = 'X';
}
part_add(ps);
return; /* all good */
/* Remove part after some error. */
parse_part_revert:
rb->snprintf(buffer, sizeof(buffer), "ERR %u @line %u", errcode, num);
rb->splash(2*HZ, buffer);
++bad_parts;
mem_reset();
}
#undef CHECK
static void step_back(void)
{
beating = false;
beat = 0;
if(bar)
{
/* Endless parts only know position 0 to step to. */
if(part->bars) --bar;
else bar = 0;
}
else if(part->prev)
{
part = part->prev;
/* This will jump to bar 0 for endless parts. */
bar = positive(part->bars)-1;
tweak_volume(part->volume);
}
/* Always calculate period for acceleration. */
calc_period();
minitick = period;
}
static void step_forw(void)
{
beating = false;
/* Stepping forward in endless part always goes to the next one, if any. */
if(part->bars == 0 || bar+1 == part->bars)
{
if(part->next)
{ /* Advanced one part. */
part = part->next;
bar = 0;
beat = 0;
tweak_volume(part->volume);
}
}
else ++bar;
/* Always calculate period for acceleration. */
calc_period();
minitick = period;
}
static void tap(void)
{
struct part *ps = part;
/* Each tap resets the position. */
beat = 0;
bar = 0;
if(tap_count == 0 || tap_time < tap_count)
tap_time = 0;
else
{
if(tap_time > 0)
{
/* Could use fixed point math and rounding, even. */
ps->bpm = 60*timerfreq_div*tap_count/tap_time;
if(ps->bpm > 400) ps->bpm = 400;
}
tap_timeout = (tap_count+2)*tap_time/tap_count;
}
tap_count++;
minitick = 0; /* sync tock to tapping */
reset_tap = false;
play_ticktock();
}
enum plugin_status plugin_start(const void* file)
{
int button;
static int last_button = BUTTON_NONE;
bool common_action;
atexit(cleanup);
mem_init();
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_buffers();
#if INPUT_SRC_CAPS != 0
/* Select playback */
rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
#endif
rb->pcm_set_frequency(SAMPR_44);
#endif /* CONFIG_CODEC != SWCODEC */
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)
{
reset_tap = true;
button = pluginlib_getaction( TIMEOUT_NOBLOCK, plugin_contexts
, PLA_ARRAY_COUNT );
if(sound_trigger)
{
sound_trigger = false;
play_ticktock(); /* Draws display before playback. */
}
common_action = false;
if(track_mode)
{
switch(button)
{
case METRONOME_START:
if(sound_paused) metronome_unpause();
else metronome_pause();
break;
case METRONOME_PAUSE:
if(!sound_paused) metronome_pause();
break;
case METRONOME_LEFT:
case METRONOME_LEFT_REP:
step_back();
trigger_display(0);
break;
case METRONOME_RIGHT:
case METRONOME_RIGHT_REP:
step_forw();
trigger_display(0);
break;
default:
common_action = true;
}
}
else
{
switch(button)
{
case METRONOME_PAUSE:
if(!sound_paused) metronome_pause();
break;
case METRONOME_PLAY:
if(sound_paused) metronome_unpause();
break;
case METRONOME_TAP:
if(last_button != METRONOME_PLAY)
{
if(sound_paused) metronome_unpause();
tap();
}
break;
case METRONOME_LEFT:
bpm_step_counter = 0;
case METRONOME_LEFT_REP:
change_bpm(-1);
break;
case METRONOME_RIGHT:
bpm_step_counter = 0;
case METRONOME_RIGHT_REP:
change_bpm(1);
break;
#ifdef MET_SYNC
case METRONOME_SYNC:
minitick = period;
break;
#endif
default:
common_action = true;
}
}
if(common_action)
switch(button)
{
case METRONOME_QUIT:
/* get out of here */
return PLUGIN_OK;
case METRONOME_VOL_UP:
case METRONOME_VOL_UP_REP:
change_volume(1);
trigger_display(0);
break;
case METRONOME_VOL_DOWN:
case METRONOME_VOL_DOWN_REP:
change_volume(-1);
trigger_display(0);
break;
default:
exit_on_usb(button);
reset_tap = false;
break;
}
if(button)
last_button = button;
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();
}
}