Fix wrong file type.
[kugel-rb.git] / apps / plugins / midiplay.c
blobf8a69296612a39c51a834e067c03bd5f661e2ced
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2005 Karl Kurbjun based on midi2wav by Stepan Moskovchenko
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.
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
17 ****************************************************************************/
19 #include "../../plugin.h"
21 PLUGIN_HEADER
22 PLUGIN_IRAM_DECLARE
24 /* variable button definitions */
25 #if CONFIG_KEYPAD == RECORDER_PAD
26 #define BTN_QUIT BUTTON_OFF
27 #define BTN_RIGHT BUTTON_RIGHT
28 #define BTN_UP BUTTON_UP
29 #define BTN_DOWN BUTTON_DOWN
31 #elif CONFIG_KEYPAD == ONDIO_PAD
32 #define BTN_QUIT BUTTON_OFF
33 #define BTN_RIGHT BUTTON_RIGHT
34 #define BTN_UP BUTTON_UP
35 #define BTN_DOWN BUTTON_DOWN
37 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
38 #define BTN_QUIT BUTTON_OFF
39 #define BTN_RIGHT BUTTON_RIGHT
40 #define BTN_UP BUTTON_UP
41 #define BTN_DOWN BUTTON_DOWN
43 #define BTN_RC_QUIT BUTTON_RC_STOP
45 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
46 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
47 #define BTN_QUIT (BUTTON_SELECT | BUTTON_MENU)
48 #define BTN_RIGHT BUTTON_RIGHT
49 #define BTN_UP BUTTON_SCROLL_FWD
50 #define BTN_DOWN BUTTON_SCROLL_BACK
52 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
53 #define BTN_QUIT BUTTON_POWER
54 #define BTN_RIGHT BUTTON_RIGHT
55 #define BTN_UP BUTTON_UP
56 #define BTN_DOWN BUTTON_DOWN
58 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
59 (CONFIG_KEYPAD == SANSA_C200_PAD)
60 #define BTN_QUIT BUTTON_POWER
61 #define BTN_RIGHT BUTTON_RIGHT
62 #define BTN_UP BUTTON_UP
63 #define BTN_DOWN BUTTON_DOWN
66 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
67 #define BTN_QUIT BUTTON_POWER
68 #define BTN_RIGHT BUTTON_RIGHT
69 #define BTN_UP BUTTON_UP
70 #define BTN_DOWN BUTTON_DOWN
72 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
73 #define BTN_QUIT BUTTON_POWER
74 #define BTN_RIGHT BUTTON_RIGHT
75 #define BTN_UP BUTTON_SCROLL_UP
76 #define BTN_DOWN BUTTON_SCROLL_DOWN
78 #endif
82 #define FRACTSIZE 10
84 #ifndef SIMULATOR
86 #if (HW_SAMPR_CAPS & SAMPR_CAP_22)
87 #define SAMPLE_RATE SAMPR_22 // 44100 22050 11025
88 #else
89 #define SAMPLE_RATE SAMPR_44 // 44100 22050 11025
90 #endif
92 #define MAX_VOICES 20 // Note: 24 midi channels is the minimum general midi
93 // spec implementation
95 #else // Simulator requires 44100, and we can afford to use more voices
97 #define SAMPLE_RATE SAMPR_44
98 #define MAX_VOICES 48
100 #endif
103 #define BUF_SIZE 256
104 #define NBUF 2
106 #undef SYNC
108 #ifdef SIMULATOR
109 #define SYNC
110 #endif
112 struct MIDIfile * mf IBSS_ATTR;
114 int numberOfSamples IBSS_ATTR;
115 long bpm IBSS_ATTR;
117 #include "midi/midiutil.c"
118 #include "midi/guspat.h"
119 #include "midi/guspat.c"
120 #include "midi/sequencer.c"
121 #include "midi/midifile.c"
122 #include "midi/synth.c"
124 long gmbuf[BUF_SIZE*NBUF];
126 int quit=0;
127 struct plugin_api * rb;
129 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
131 int retval = 0;
133 PLUGIN_IRAM_INIT(api)
135 rb = api;
136 if(parameter == NULL)
138 rb->splash(HZ*2, " Play .MID file ");
139 return PLUGIN_OK;
141 rb->lcd_setfont(0);
143 #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
144 rb->cpu_boost(true);
145 #endif
147 printf("%s", parameter);
148 /* rb->splash(HZ, true, parameter); */
150 #ifdef RB_PROFILE
151 rb->profile_thread();
152 #endif
154 retval = midimain(parameter);
156 #ifdef RB_PROFILE
157 rb->profstop();
158 #endif
160 rb->pcm_play_stop();
161 rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
163 #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
164 rb->cpu_boost(false);
165 #endif
167 rb->splash(HZ, "FINISHED PLAYING");
169 if(retval == -1)
170 return PLUGIN_ERROR;
171 return PLUGIN_OK;
174 bool swap=0;
175 bool lastswap=1;
177 inline void synthbuf(void)
179 long *outptr;
180 register int i;
181 static int currentSample=0;
182 int synthtemp[2];
184 #ifndef SYNC
185 if(lastswap==swap) return;
186 lastswap=swap;
188 outptr=(swap ? gmbuf : gmbuf+BUF_SIZE);
189 #else
190 outptr=gmbuf;
191 #endif
193 for(i=0; i<BUF_SIZE/2; i++)
195 synthSample(&synthtemp[0], &synthtemp[1]);
196 currentSample++;
197 *outptr=((synthtemp[0]&0xFFFF) << 16) | (synthtemp[1]&0xFFFF);
198 outptr++;
199 if(currentSample==numberOfSamples)
201 if( tick() == 0 ) quit=1;
202 currentSample=0;
207 void get_more(unsigned char** start, size_t* size)
209 #ifndef SYNC
210 if(lastswap!=swap)
212 printf("Buffer miss!"); // Comment out the printf to make missses less noticable.
215 #else
216 synthbuf(); // For some reason midiplayer crashes when an update is forced
217 #endif
219 *size = BUF_SIZE*sizeof(short);
220 #ifndef SYNC
221 *start = (unsigned char*)((swap ? gmbuf : gmbuf + BUF_SIZE));
222 swap=!swap;
223 #else
224 *start = (unsigned char*)(gmbuf);
225 #endif
228 int midimain(void * filename)
230 int notesUsed = 0;
231 int a=0;
232 printf("Loading file");
233 mf= loadFile(filename);
235 if(mf == NULL)
237 printf("Error loading file.");
238 return -1;
241 if (initSynth(mf, ROCKBOX_DIR "/patchset/patchset.cfg",
242 ROCKBOX_DIR "/patchset/drums.cfg") == -1)
243 return -1;
245 //#ifndef SIMULATOR
246 rb->pcm_play_stop();
247 #if INPUT_SRC_CAPS != 0
248 /* Select playback */
249 rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
250 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
251 #endif
252 rb->pcm_set_frequency(SAMPLE_RATE); // 44100 22050 11025
253 //#endif
256 * tick() will do one MIDI clock tick. Then, there's a loop here that
257 * will generate the right number of samples per MIDI tick. The whole
258 * MIDI playback is timed in terms of this value.. there are no forced
259 * delays or anything. It just produces enough samples for each tick, and
260 * the playback of these samples is what makes the timings right.
262 * This seems to work quite well. On a laptop, anyway.
265 printf("Okay, starting sequencing");
267 bpm=mf->div*1000000/tempo;
268 numberOfSamples=SAMPLE_RATE/bpm;
272 /* Skip over any junk in the beginning of the file, so start playing */
273 /* after the first note event */
276 notesUsed = 0;
277 for(a=0; a<MAX_VOICES; a++)
278 if(voices[a].isUsed == 1)
279 notesUsed++;
280 tick();
281 } while(notesUsed == 0);
283 synthbuf();
284 //#ifndef SIMULATOR
285 rb->pcm_play_data(&get_more, NULL, 0);
286 //#endif
288 int vol=0;
290 while(!quit)
292 #ifndef SYNC
293 synthbuf();
294 #endif
295 rb->yield();
297 /* Prevent idle poweroff */
298 rb->reset_poweroff_timer();
300 /* Code taken from Oscilloscope plugin */
301 switch(rb->button_get(false))
303 case BTN_UP:
304 case BTN_UP | BUTTON_REPEAT:
305 vol = rb->global_settings->volume;
306 if (vol < rb->sound_max(SOUND_VOLUME))
308 vol++;
309 rb->sound_set(SOUND_VOLUME, vol);
310 rb->global_settings->volume = vol;
312 break;
314 case BTN_DOWN:
315 case BTN_DOWN | BUTTON_REPEAT:
316 vol = rb->global_settings->volume;
317 if (vol > rb->sound_min(SOUND_VOLUME))
319 vol--;
320 rb->sound_set(SOUND_VOLUME, vol);
321 rb->global_settings->volume = vol;
323 break;
325 case BTN_RIGHT:
327 /* Skip 3 seconds */
328 /* Should skip length be retrieved from the RB settings? */
329 int samp = 3*SAMPLE_RATE;
330 int tickCount = samp / numberOfSamples;
331 int a=0;
332 for(a=0; a<tickCount; a++)
333 tick();
334 break;
336 #ifdef BTN_RC_QUIT
337 case BTN_RC_QUIT:
338 #endif
339 case BTN_QUIT:
340 quit=1;
346 return 0;