summaryrefslogtreecommitdiff
path: root/apps/plugins/midi/midiplay.c
diff options
context:
space:
mode:
authorNils Wallménius <nils@rockbox.org>2007-09-24 15:57:32 +0000
committerNils Wallménius <nils@rockbox.org>2007-09-24 15:57:32 +0000
commit0e49605aaae01722a618dfdc64a328cc0e92bc04 (patch)
treee3241b18fae86271c5f3f9e18f819dc9c2ea29f3 /apps/plugins/midi/midiplay.c
parente24975a35fbf564966b73dbaef766e215f7427d4 (diff)
downloadrockbox-0e49605aaae01722a618dfdc64a328cc0e92bc04.tar.gz
rockbox-0e49605aaae01722a618dfdc64a328cc0e92bc04.zip
Move all of midiplay into its subdir and add a Makefile for it, add header files as necessary.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14841 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/midi/midiplay.c')
-rw-r--r--apps/plugins/midi/midiplay.c318
1 files changed, 318 insertions, 0 deletions
diff --git a/apps/plugins/midi/midiplay.c b/apps/plugins/midi/midiplay.c
new file mode 100644
index 0000000000..7a1176b1c9
--- /dev/null
+++ b/apps/plugins/midi/midiplay.c
@@ -0,0 +1,318 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Karl Kurbjun based on midi2wav by Stepan Moskovchenko
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "plugin.h"
20#include "guspat.h"
21#include "midiutil.h"
22#include "synth.h"
23#include "sequencer.h"
24#include "midifile.h"
25
26PLUGIN_HEADER
27PLUGIN_IRAM_DECLARE
28
29/* variable button definitions */
30#if CONFIG_KEYPAD == RECORDER_PAD
31#define BTN_QUIT BUTTON_OFF
32#define BTN_RIGHT BUTTON_RIGHT
33#define BTN_UP BUTTON_UP
34#define BTN_DOWN BUTTON_DOWN
35
36#elif CONFIG_KEYPAD == ONDIO_PAD
37#define BTN_QUIT BUTTON_OFF
38#define BTN_RIGHT BUTTON_RIGHT
39#define BTN_UP BUTTON_UP
40#define BTN_DOWN BUTTON_DOWN
41
42#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
43#define BTN_QUIT BUTTON_OFF
44#define BTN_RIGHT BUTTON_RIGHT
45#define BTN_UP BUTTON_UP
46#define BTN_DOWN BUTTON_DOWN
47
48#define BTN_RC_QUIT BUTTON_RC_STOP
49
50#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
51 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
52#define BTN_QUIT (BUTTON_SELECT | BUTTON_MENU)
53#define BTN_RIGHT BUTTON_RIGHT
54#define BTN_UP BUTTON_SCROLL_FWD
55#define BTN_DOWN BUTTON_SCROLL_BACK
56
57#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
58#define BTN_QUIT BUTTON_POWER
59#define BTN_RIGHT BUTTON_RIGHT
60#define BTN_UP BUTTON_UP
61#define BTN_DOWN BUTTON_DOWN
62
63#elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
64(CONFIG_KEYPAD == SANSA_C200_PAD)
65#define BTN_QUIT BUTTON_POWER
66#define BTN_RIGHT BUTTON_RIGHT
67#define BTN_UP BUTTON_UP
68#define BTN_DOWN BUTTON_DOWN
69
70#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
71#define BTN_QUIT BUTTON_POWER
72#define BTN_RIGHT BUTTON_RIGHT
73#define BTN_UP BUTTON_UP
74#define BTN_DOWN BUTTON_DOWN
75
76#elif CONFIG_KEYPAD == IRIVER_H10_PAD
77#define BTN_QUIT BUTTON_POWER
78#define BTN_RIGHT BUTTON_RIGHT
79#define BTN_UP BUTTON_SCROLL_UP
80#define BTN_DOWN BUTTON_SCROLL_DOWN
81
82#endif
83
84#undef SYNC
85
86#ifdef SIMULATOR
87 #define SYNC
88#endif
89
90struct MIDIfile * mf IBSS_ATTR;
91
92int numberOfSamples IBSS_ATTR;
93long bpm IBSS_ATTR;
94
95long gmbuf[BUF_SIZE*NBUF];
96
97int quit=0;
98struct plugin_api * rb;
99
100enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
101{
102 int retval = 0;
103
104 PLUGIN_IRAM_INIT(api)
105
106 rb = api;
107 if(parameter == NULL)
108 {
109 rb->splash(HZ*2, " Play .MID file ");
110 return PLUGIN_OK;
111 }
112 rb->lcd_setfont(0);
113
114#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
115 rb->cpu_boost(true);
116#endif
117
118 printf("%s", parameter);
119 /* rb->splash(HZ, true, parameter); */
120
121#ifdef RB_PROFILE
122 rb->profile_thread();
123#endif
124
125 retval = midimain(parameter);
126
127#ifdef RB_PROFILE
128 rb->profstop();
129#endif
130
131 rb->pcm_play_stop();
132 rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
133
134#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
135 rb->cpu_boost(false);
136#endif
137
138 rb->splash(HZ, "FINISHED PLAYING");
139
140 if(retval == -1)
141 return PLUGIN_ERROR;
142 return PLUGIN_OK;
143}
144
145bool swap=0;
146bool lastswap=1;
147
148inline void synthbuf(void)
149{
150 long *outptr;
151 register int i;
152 static int currentSample=0;
153 int synthtemp[2];
154
155#ifndef SYNC
156 if(lastswap==swap) return;
157 lastswap=swap;
158
159 outptr=(swap ? gmbuf : gmbuf+BUF_SIZE);
160#else
161 outptr=gmbuf;
162#endif
163
164 for(i=0; i<BUF_SIZE/2; i++)
165 {
166 synthSample(&synthtemp[0], &synthtemp[1]);
167 currentSample++;
168 *outptr=((synthtemp[0]&0xFFFF) << 16) | (synthtemp[1]&0xFFFF);
169 outptr++;
170 if(currentSample==numberOfSamples)
171 {
172 if( tick() == 0 ) quit=1;
173 currentSample=0;
174 }
175 }
176}
177
178void get_more(unsigned char** start, size_t* size)
179{
180#ifndef SYNC
181 if(lastswap!=swap)
182 {
183 printf("Buffer miss!"); // Comment out the printf to make missses less noticable.
184 }
185
186#else
187 synthbuf(); // For some reason midiplayer crashes when an update is forced
188#endif
189
190 *size = BUF_SIZE*sizeof(short);
191#ifndef SYNC
192 *start = (unsigned char*)((swap ? gmbuf : gmbuf + BUF_SIZE));
193 swap=!swap;
194#else
195 *start = (unsigned char*)(gmbuf);
196#endif
197}
198
199int midimain(void * filename)
200{
201 int notesUsed = 0;
202 int a=0;
203 printf("Loading file");
204 mf= loadFile(filename);
205
206 if(mf == NULL)
207 {
208 printf("Error loading file.");
209 return -1;
210 }
211
212 if (initSynth(mf, ROCKBOX_DIR "/patchset/patchset.cfg",
213 ROCKBOX_DIR "/patchset/drums.cfg") == -1)
214 return -1;
215
216//#ifndef SIMULATOR
217 rb->pcm_play_stop();
218#if INPUT_SRC_CAPS != 0
219 /* Select playback */
220 rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
221 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
222#endif
223 rb->pcm_set_frequency(SAMPLE_RATE); // 44100 22050 11025
224//#endif
225
226 /*
227 * tick() will do one MIDI clock tick. Then, there's a loop here that
228 * will generate the right number of samples per MIDI tick. The whole
229 * MIDI playback is timed in terms of this value.. there are no forced
230 * delays or anything. It just produces enough samples for each tick, and
231 * the playback of these samples is what makes the timings right.
232 *
233 * This seems to work quite well. On a laptop, anyway.
234 */
235
236 printf("Okay, starting sequencing");
237
238 bpm=mf->div*1000000/tempo;
239 numberOfSamples=SAMPLE_RATE/bpm;
240
241
242
243 /* Skip over any junk in the beginning of the file, so start playing */
244 /* after the first note event */
245 do
246 {
247 notesUsed = 0;
248 for(a=0; a<MAX_VOICES; a++)
249 if(voices[a].isUsed == 1)
250 notesUsed++;
251 tick();
252 } while(notesUsed == 0);
253
254 synthbuf();
255//#ifndef SIMULATOR
256 rb->pcm_play_data(&get_more, NULL, 0);
257//#endif
258
259 int vol=0;
260
261 while(!quit)
262 {
263 #ifndef SYNC
264 synthbuf();
265 #endif
266 rb->yield();
267
268 /* Prevent idle poweroff */
269 rb->reset_poweroff_timer();
270
271 /* Code taken from Oscilloscope plugin */
272 switch(rb->button_get(false))
273 {
274 case BTN_UP:
275 case BTN_UP | BUTTON_REPEAT:
276 vol = rb->global_settings->volume;
277 if (vol < rb->sound_max(SOUND_VOLUME))
278 {
279 vol++;
280 rb->sound_set(SOUND_VOLUME, vol);
281 rb->global_settings->volume = vol;
282 }
283 break;
284
285 case BTN_DOWN:
286 case BTN_DOWN | BUTTON_REPEAT:
287 vol = rb->global_settings->volume;
288 if (vol > rb->sound_min(SOUND_VOLUME))
289 {
290 vol--;
291 rb->sound_set(SOUND_VOLUME, vol);
292 rb->global_settings->volume = vol;
293 }
294 break;
295
296 case BTN_RIGHT:
297 {
298 /* Skip 3 seconds */
299 /* Should skip length be retrieved from the RB settings? */
300 int samp = 3*SAMPLE_RATE;
301 int tickCount = samp / numberOfSamples;
302 int a=0;
303 for(a=0; a<tickCount; a++)
304 tick();
305 break;
306 }
307#ifdef BTN_RC_QUIT
308 case BTN_RC_QUIT:
309#endif
310 case BTN_QUIT:
311 quit=1;
312 }
313
314
315 }
316
317 return 0;
318}