diff options
author | Nils Wallménius <nils@rockbox.org> | 2007-09-24 15:57:32 +0000 |
---|---|---|
committer | Nils Wallménius <nils@rockbox.org> | 2007-09-24 15:57:32 +0000 |
commit | 0e49605aaae01722a618dfdc64a328cc0e92bc04 (patch) | |
tree | e3241b18fae86271c5f3f9e18f819dc9c2ea29f3 /apps/plugins/midi/midiplay.c | |
parent | e24975a35fbf564966b73dbaef766e215f7427d4 (diff) | |
download | rockbox-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.c | 318 |
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 | |||
26 | PLUGIN_HEADER | ||
27 | PLUGIN_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 | |||
90 | struct MIDIfile * mf IBSS_ATTR; | ||
91 | |||
92 | int numberOfSamples IBSS_ATTR; | ||
93 | long bpm IBSS_ATTR; | ||
94 | |||
95 | long gmbuf[BUF_SIZE*NBUF]; | ||
96 | |||
97 | int quit=0; | ||
98 | struct plugin_api * rb; | ||
99 | |||
100 | enum 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 | |||
145 | bool swap=0; | ||
146 | bool lastswap=1; | ||
147 | |||
148 | inline 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 | |||
178 | void 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 | |||
199 | int 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 | } | ||