1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2014 Franklin Wei
*
* 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.
*
*/
/* Tonebox is a very-simplifed, MIDI-like format for representing music */
/* The extension for a Tonebox file is .tbx */
/* The format is as follows:
Header: <f3> <76> -- a tribute to the Z80 :)
Data:
- a tone is represented like: <ff> <32-bit big-endian frequency> <32-bit big-endian duration in microseconds>
- silence is represented as: <00> <32-bit big-endian duration> <32-bit garbage>
*/
#include "plugin.h"
enum plugin_status plugin_start(const void* param)
{
if(!param)
{
rb->splash(HZ, "No .tbx file given!");
return PLUGIN_ERROR;
}
else
{
char* filename=(char*)param;
if(!rb->file_exists(filename))
{
rb->splash(HZ, "File does not exist!");
return PLUGIN_ERROR;
}
int fd=rb->open(filename, O_RDONLY);
unsigned char header[2];
int ret=rb->read(fd, header, 2);
if(header[0]!=0xf3 || header[1]!=0x76 || ret!=2)
{
rb->splashf(HZ, "Header missing/corrupted!");
return PLUGIN_ERROR;
}
unsigned char buf[9];
do {
ret=rb->read(fd, buf, 9);
if(ret!=9)
break;
switch(buf[0])
{
case 0xff: /* tone */
{
unsigned int freq=(buf[1]<<24)|(buf[2]<<16)|(buf[3]<<8)|buf[4];
unsigned int dur= (buf[5]<<24)|(buf[6]<<16)|(buf[7]<<8)|buf[8];
rb->splashf(0, "Playing %u Hz tone for %u microseconds", freq, dur);
if(freq)
rb->piezo_play(dur, freq, true);
else
#if HZ==100
rb->sleep(dur/10000.0); /* FIXME: Assumes that HZ is 100 */
#else
#error "FIXME: HZ assumed to be 100"
#endif
break;
}
case 0:
{
unsigned int dur=(buf[1]<<24)|(buf[2]<<16)|(buf[3]<<8)|buf[4];
rb->splashf(0, "Sleeping %u microseconds", dur);
rb->sleep(dur/10000.0);
break;
}
default:
rb->splash(HZ, "Unknown tone/silence byte");
return PLUGIN_ERROR;
break;
}
rb->yield();
} while(ret==9);
rb->close(fd);
}
return PLUGIN_OK;
}
|