summaryrefslogtreecommitdiff
path: root/apps/plugins/midiplay.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/midiplay.c')
-rw-r--r--apps/plugins/midiplay.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/apps/plugins/midiplay.c b/apps/plugins/midiplay.c
new file mode 100644
index 0000000000..f279e72e4e
--- /dev/null
+++ b/apps/plugins/midiplay.c
@@ -0,0 +1,217 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2005 Karl Kurbjun based on midi2wav by Stepan Moskovchenko
10 *
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
13 *
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
16 *
17 ****************************************************************************/
18
19#include "../../plugin.h"
20
21PLUGIN_HEADER
22
23#define SAMPLE_RATE 22050 // 44100 22050 11025
24#define MAX_VOICES 12 // Note: 24 midi channels is the minimum general midi
25 // spec implementation
26#define BUF_SIZE 512
27#define NBUF 2
28
29#undef SYNC
30struct MIDIfile * mf IBSS_ATTR;
31
32int numberOfSamples IBSS_ATTR;
33long bpm IBSS_ATTR;
34
35#include "midi/midiutil.c"
36#include "midi/guspat.h"
37#include "midi/guspat.c"
38#include "midi/sequencer.c"
39#include "midi/midifile.c"
40#include "midi/synth.c"
41
42short gmbuf[BUF_SIZE*NBUF] IBSS_ATTR;
43
44int quit=0;
45struct plugin_api * rb;
46
47#ifdef USE_IRAM
48extern char iramcopy[];
49extern char iramstart[];
50extern char iramend[];
51extern char iedata[];
52extern char iend[];
53#endif
54
55enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
56{
57 rb = api;
58
59 if(parameter == NULL)
60 {
61 rb->splash(HZ*2, true, " Play .MID file ");
62 return PLUGIN_OK;
63 }
64 rb->lcd_setfont(0);
65
66#ifdef USE_IRAM
67 rb->memcpy(iramstart, iramcopy, iramend-iramstart);
68 rb->memset(iedata, 0, iend - iedata);
69#endif
70
71#if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
72 rb->cpu_boost(true);
73#endif
74
75 printf("\n%s", parameter);
76/* rb->splash(HZ, true, parameter); */
77
78#ifdef RB_PROFILE
79 rb->profile_thread();
80#endif
81
82 if(midimain(parameter) == -1)
83 return PLUGIN_ERROR;
84
85#ifdef RB_PROFILE
86 rb->profstop();
87#endif
88
89#ifndef SIMULATOR
90 rb->pcm_play_stop();
91 rb->pcm_set_frequency(44100); // 44100
92#endif
93
94#if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
95 rb->cpu_boost(false);
96#endif
97
98 rb->splash(HZ, true, "FINISHED PLAYING");
99
100 return PLUGIN_OK;
101}
102
103bool swap=0;
104bool lastswap=1;
105
106inline void synthbuf(void)
107{
108 short *outptr;
109 register int i;
110 static int currentSample=0;
111 int synthtemp[2];
112
113#ifndef SYNC
114 if(lastswap==swap) return;
115 lastswap=swap;
116
117 outptr=(swap ? gmbuf : gmbuf+BUF_SIZE);
118#else
119 outptr=gmbuf;
120#endif
121
122 for(i=0; i<BUF_SIZE/2; i++)
123 {
124 synthSample(&synthtemp[0], &synthtemp[1]);
125 currentSample++;
126 *outptr=synthtemp[0]&0xFFFF;
127 outptr++;
128 *outptr=synthtemp[1]&0xFFFF;
129 outptr++;
130 if(currentSample==numberOfSamples)
131 {
132 if( tick() == 0 ) quit=1;
133 currentSample=0;
134 }
135 }
136}
137
138void get_more(unsigned char** start, size_t* size)
139{
140#ifndef SYNC
141 if(lastswap!=swap)
142 {
143 printf("Buffer miss!"); // Comment out the printf to make missses less noticable.
144/*
145 int a=0;
146 for(a=0; a<MAX_VOICES; a++)
147 {
148 voices[a].isUsed=0;
149 }
150*/
151 }
152
153#else
154 synthbuf(); // For some reason midiplayer crashes when an update is forced
155#endif
156
157 *size = BUF_SIZE*sizeof(short);
158#ifndef SYNC
159 *start = (unsigned char*)((swap ? gmbuf : gmbuf + BUF_SIZE));
160 swap=!swap;
161#else
162 *start = (unsigned char*)(gmbuf);
163#endif
164}
165
166int midimain(void * filename)
167{
168 int button;
169
170/* rb->splash(HZ/5, true, "LOADING MIDI"); */
171 printf("\nLoading file");
172 mf= loadFile(filename);
173
174/* rb->splash(HZ/5, true, "LOADING PATCHES"); */
175 if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1)
176 return -1;
177
178#ifndef SIMULATOR
179 rb->pcm_play_stop();
180 rb->pcm_set_frequency(SAMPLE_RATE); // 44100 22050 11025
181#endif
182
183 /*
184 * tick() will do one MIDI clock tick. Then, there's a loop here that
185 * will generate the right number of samples per MIDI tick. The whole
186 * MIDI playback is timed in terms of this value.. there are no forced
187 * delays or anything. It just produces enough samples for each tick, and
188 * the playback of these samples is what makes the timings right.
189 *
190 * This seems to work quite well.
191 */
192
193 printf("\nOkay, starting sequencing");
194
195 bpm=mf->div*1000000/tempo;
196 numberOfSamples=SAMPLE_RATE/bpm;
197
198 tick();
199
200 synthbuf();
201#ifndef SIMULATOR
202 rb->pcm_play_data(&get_more, NULL, 0);
203#endif
204
205 button=rb->button_status();
206
207 while(!quit)
208 {
209#ifndef SYNC
210 synthbuf();
211#endif
212 rb->yield();
213 if(rb->button_status()!=button) quit=1;
214 }
215
216 return 0;
217}