summaryrefslogtreecommitdiff
path: root/apps/plugins/beatbox/beatbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/beatbox/beatbox.c')
-rw-r--r--apps/plugins/beatbox/beatbox.c664
1 files changed, 664 insertions, 0 deletions
diff --git a/apps/plugins/beatbox/beatbox.c b/apps/plugins/beatbox/beatbox.c
new file mode 100644
index 0000000000..794d6c1cbe
--- /dev/null
+++ b/apps/plugins/beatbox/beatbox.c
@@ -0,0 +1,664 @@
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
22PLUGIN_IRAM_DECLARE
23
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
30
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
36
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
42
43#define BTN_RC_QUIT BUTTON_RC_STOP
44
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
51
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
57
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
64
65
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
71
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
77
78#endif
79
80
81
82#define FRACTSIZE 10
83
84#ifndef SIMULATOR
85
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
91
92#define MAX_VOICES 20 // Note: 24 midi channels is the minimum general midi
93 // spec implementation
94
95#else // Simulator requires 44100, and we can afford to use more voices
96
97#define SAMPLE_RATE SAMPR_44
98#define MAX_VOICES 48
99
100#endif
101
102
103#define BUF_SIZE 256
104#define NBUF 2
105
106#undef SYNC
107
108#ifdef SIMULATOR
109 #define SYNC
110#endif
111
112struct MIDIfile * mf IBSS_ATTR;
113
114int numberOfSamples IBSS_ATTR;
115long bpm IBSS_ATTR;
116
117
118#include "plugin.h"
119#include "midi/guspat.h"
120#include "midi/midiutil.h"
121#include "midi/synth.h"
122#include "midi/sequencer.h"
123#include "midi/midifile.h"
124
125
126long gmbuf[BUF_SIZE*NBUF];
127
128int quit=0;
129struct plugin_api * rb;
130
131
132#define STATE_STOPPED 0
133#define STATE_PAUSED 1
134#define STATE_PLAYING 2
135
136
137#define BEATBOX_UP BUTTON_UP
138#define BEATBOX_DOWN BUTTON_DOWN
139#define BEATBOX_LEFT BUTTON_LEFT
140#define BEATBOX_RIGHT BUTTON_RIGHT
141#define BEATBOX_SELECT BUTTON_SELECT
142
143
144#define BEATBOX_PLAY BUTTON_ON
145#define BEATBOX_STOP BUTTON_OFF
146
147
148#define VAL_NONE 0
149#define VAL_ENABLED 1
150#define VAL_LOOP 2
151
152#define H_NUMCELLS 24
153#define V_NUMCELLS 8
154
155#define HILIGHT_NONE 0
156#define HILIGHT_PLAY 1
157#define HILIGHT_USER 2
158
159#define CELL_XSIZE 9
160#define CELL_YSIZE 9
161
162#define GRID_XPOS 2
163#define GRID_YPOS 10
164
165
166#define COLOR_NORMAL LCD_RGBPACK(0xFF,0xFF,0xFF)
167#define COLOR_PLAY LCD_RGBPACK(0xFF,0xFF,0x00)
168#define COLOR_DISABLED LCD_RGBPACK(0xA0,0xA0,0xA0)
169#define COLOR_LOOPCELL LCD_RGBPACK(0xC0,0xC0,0xC0)
170#define COLOR_EDIT LCD_RGBPACK(0x30,0x30,0xFF)
171#define COLOR_GRID LCD_RGBPACK(0xD0,0xD0,0xD0)
172
173#define EDITSTATE_PATTERN 0
174
175int xCursor=0, yCursor=0;
176
177int editState=EDITSTATE_PATTERN;
178
179int playState=STATE_STOPPED, stepFlag=0;
180
181
182enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
183{
184 int retval = 0;
185
186 PLUGIN_IRAM_INIT(api)
187
188 rb = api;
189
190 rb->lcd_setfont(0);
191
192#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
193 rb->cpu_boost(true);
194#endif
195
196#ifdef RB_PROFILE
197 rb->profile_thread();
198#endif
199 if (initSynth(NULL, ROCKBOX_DIR "/patchset/patchset.cfg",
200 ROCKBOX_DIR "/patchset/drums.cfg") == -1)
201 {
202 printf("\nINIT ERROR\n");
203 return -1;
204 }
205//#ifndef SIMULATOR
206 rb->pcm_play_stop();
207#if INPUT_SRC_CAPS != 0
208 /* Select playback */
209 rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
210 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
211#endif
212 rb->pcm_set_frequency(SAMPLE_RATE); // 44100 22050 11025
213
214
215 retval = beatboxmain();
216
217#ifdef RB_PROFILE
218 rb->profstop();
219#endif
220
221 rb->pcm_play_stop();
222 rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
223
224#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
225 rb->cpu_boost(false);
226#endif
227
228
229 if(retval == -1)
230 return PLUGIN_ERROR;
231 return PLUGIN_OK;
232}
233
234bool swap=0;
235bool lastswap=1;
236
237inline void synthbuf(void)
238{
239 long *outptr;
240 register int i;
241 static int currentSample=0;
242 int synthtemp[2];
243
244#ifndef SYNC
245 if(lastswap==swap) return;
246 lastswap=swap;
247
248 outptr=(swap ? gmbuf : gmbuf+BUF_SIZE);
249#else
250 outptr=gmbuf;
251#endif
252
253 for(i=0; i<BUF_SIZE/2; i++)
254 {
255 synthSample(&synthtemp[0], &synthtemp[1]);
256 currentSample++;
257 *outptr=((synthtemp[0]&0xFFFF) << 16) | (synthtemp[1]&0xFFFF);
258 outptr++;
259 if(currentSample==numberOfSamples)
260 {
261 if(playState == STATE_PLAYING)
262 {
263 stepFlag=1;
264 }
265
266 currentSample=0;
267 }
268 }
269}
270
271
272
273
274
275unsigned char trackPos[V_NUMCELLS];
276unsigned char trackData[H_NUMCELLS][V_NUMCELLS];
277unsigned char trackMap[V_NUMCELLS] = {38, 39, 40, 41, 42, 43, 44, 45};
278
279
280struct Cell
281{
282 unsigned char val;
283 int color;
284};
285
286struct Cell pattern[H_NUMCELLS][V_NUMCELLS];
287struct Cell dispPattern[H_NUMCELLS][V_NUMCELLS];
288
289
290void advancePosition()
291{
292 int i=0;
293 for(i=0; i<V_NUMCELLS; i++)
294 {
295 trackPos[i]++;
296 if(trackPos[i] == H_NUMCELLS || trackData[trackPos[i]][i] == VAL_LOOP)
297 trackPos[i]=0;
298 }
299}
300
301
302void sendEvents()
303{
304 int i;
305 for(i=0; i<V_NUMCELLS; i++)
306 {
307 if(trackData[trackPos[i]][i] == VAL_ENABLED)
308 pressNote(9, trackMap[i], 127);
309 }
310}
311
312void updateDisplay()
313{
314 int i, j;
315 int grayOut=0;
316
317 for(j=0; j<V_NUMCELLS; j++)
318 {
319 grayOut=0;
320 for(i=0; i<H_NUMCELLS; i++)
321 {
322 pattern[i][j].color = COLOR_NORMAL;
323 pattern[i][j].val = trackData[i][j];
324
325 if(trackPos[j] == i)
326 pattern[i][j].color = COLOR_PLAY;
327
328 if(grayOut)
329 pattern[i][j].color = COLOR_DISABLED;
330
331 if(trackData[i][j] == VAL_LOOP)
332 {
333 pattern[i][j].color = COLOR_LOOPCELL;
334 grayOut=1;
335 }
336
337 if(xCursor == i && yCursor == j && editState == EDITSTATE_PATTERN)
338 pattern[i][j].color = COLOR_EDIT;
339 }
340 }
341
342}
343
344void resetPosition()
345{
346 int i;
347 for(i=0; i<V_NUMCELLS; i++)
348 trackPos[i]=0;
349}
350
351void clearCells()
352{
353 int i,j;
354 for(i=0; i<H_NUMCELLS; i++)
355 for(j=0; j<V_NUMCELLS; j++)
356 {
357 pattern[i][j].val=VAL_NONE;
358 dispPattern[i][j].val=VAL_NONE;
359 pattern[i][j].color = 0;
360 dispPattern[i][j].color = 0;
361 }
362}
363
364
365
366
367void drawGrid()
368{
369 int i, j;
370
371 rb->lcd_set_foreground(COLOR_GRID);
372
373 for(i=0; i<H_NUMCELLS+1; i++)
374 rb->lcd_vline(i*CELL_XSIZE+GRID_XPOS, GRID_YPOS, GRID_YPOS+CELL_YSIZE*V_NUMCELLS);
375
376 for(i=0; i<V_NUMCELLS+1; i++)
377 rb->lcd_hline(GRID_XPOS, GRID_XPOS+CELL_XSIZE*H_NUMCELLS, GRID_YPOS+i*CELL_YSIZE);
378
379
380 rb->lcd_update();
381}
382
383void drawCell(int i, int j)
384{
385 int cellX, cellY;
386
387 cellX = GRID_XPOS + CELL_XSIZE*i+1;
388 cellY = GRID_YPOS + CELL_YSIZE*j+1;
389
390 rb->lcd_set_foreground(pattern[i][j].color);
391 rb->lcd_fillrect(cellX, cellY, CELL_XSIZE-1, CELL_YSIZE-1);
392
393 rb->lcd_set_foreground(0);
394
395 if(pattern[i][j].val == VAL_LOOP)
396 {
397 rb->lcd_drawline(cellX, cellY, cellX+CELL_XSIZE-2, cellY+CELL_YSIZE-2);
398 }
399
400 if(pattern[i][j].val == VAL_ENABLED)
401 {
402 rb->lcd_fillrect(cellX+1, cellY+1, CELL_XSIZE-3, CELL_YSIZE-3);
403 }
404
405}
406
407void redrawScreen(unsigned char force)
408{
409 int i, j;
410
411 for(i=0; i<H_NUMCELLS; i++)
412 {
413 for(j=0; j<V_NUMCELLS; j++)
414 {
415 if(force || (pattern[i][j].val != dispPattern[i][j].val || pattern[i][j].color != dispPattern[i][j].color))
416 {
417 drawCell(i, j);
418 dispPattern[i][j].val = pattern[i][j].val;
419 dispPattern[i][j].color = pattern[i][j].color;
420 }
421 }
422 }
423 rb->lcd_update();
424}
425
426void get_more(unsigned char** start, size_t* size)
427{
428#ifndef SYNC
429 if(lastswap!=swap)
430 {
431// printf("Buffer miss!"); // Comment out the printf to make missses less noticable.
432 }
433
434#else
435 synthbuf(); // For some reason midiplayer crashes when an update is forced
436#endif
437
438 *size = BUF_SIZE*sizeof(short);
439#ifndef SYNC
440 *start = (unsigned char*)((swap ? gmbuf : gmbuf + BUF_SIZE));
441 swap=!swap;
442#else
443 *start = (unsigned char*)(gmbuf);
444#endif
445}
446
447int beatboxmain()
448{
449 int vol=0;
450
451
452 numberOfSamples=44100/10;
453 synthbuf();
454 rb->pcm_play_data(&get_more, NULL, 0);
455
456 rb->lcd_set_background(0x000000);
457 rb->lcd_clear_display();
458
459 resetPosition();
460
461 int i, j;
462
463 trackData[16][3] = VAL_LOOP;
464 trackData[16][2] = VAL_LOOP;
465
466 trackData[0][3] = 1;
467 trackData[4][3] = 1;
468 trackData[8][3] = 1;
469 trackData[9][3] = 1;
470 trackData[12][3] = 1;
471 trackData[13][3] = 1;
472
473 trackData[2][2] = 1;
474 trackData[6][2] = 1;
475 trackData[10][2] = 1;
476 trackData[14][2] = 1;
477
478
479 drawGrid();
480 updateDisplay();
481 redrawScreen(1);
482
483
484 while(!quit)
485 {
486 #ifndef SYNC
487 synthbuf();
488 #endif
489 rb->yield();
490
491 if(stepFlag)
492 {
493 advancePosition();
494 sendEvents();
495 updateDisplay();
496 redrawScreen(0);
497 stepFlag=0;
498 }
499
500 /* Prevent idle poweroff */
501 rb->reset_poweroff_timer();
502
503 /* Code taken from Oscilloscope plugin */
504 switch(rb->button_get(false))
505 {
506 /*
507 case BTN_UP:
508 case BTN_UP | BUTTON_REPEAT:
509 vol = rb->global_settings->volume;
510 if (vol < rb->sound_max(SOUND_VOLUME))
511 {
512 vol++;
513 rb->sound_set(SOUND_VOLUME, vol);
514 rb->global_settings->volume = vol;
515 }
516 break;
517
518 case BTN_DOWN:
519 case BTN_DOWN | BUTTON_REPEAT:
520 vol = rb->global_settings->volume;
521 if (vol > rb->sound_min(SOUND_VOLUME))
522 {
523 vol--;
524 rb->sound_set(SOUND_VOLUME, vol);
525 rb->global_settings->volume = vol;
526 }
527 break;
528
529 case BTN_RIGHT:
530 {
531 //pressNote(9, 40, 127);
532 // resetPosition();
533 advancePosition();
534 sendEvents();
535 updateDisplay();
536 redrawScreen(0);
537 break;
538 }
539
540 case BUTTON_LEFT:
541 {
542
543// isPlaying=1;
544 resetPosition();
545 updateDisplay();
546 redrawScreen(0);
547 //pressNote(9, 39, 127);
548 break;
549 }
550*/
551
552 case BEATBOX_UP:
553 case BEATBOX_UP | BUTTON_REPEAT:
554 {
555 if(editState == EDITSTATE_PATTERN)
556 {
557 if(yCursor > 0)
558 {
559 yCursor--;
560 updateDisplay();
561 redrawScreen(0);
562 }
563 }
564 break;
565 }
566
567 case BEATBOX_DOWN:
568 case BEATBOX_DOWN | BUTTON_REPEAT:
569 {
570 if(editState == EDITSTATE_PATTERN)
571 {
572 if(yCursor < V_NUMCELLS-1)
573 {
574 yCursor++;
575 updateDisplay();
576 redrawScreen(0);
577 }
578 }
579 break;
580 }
581
582 case BEATBOX_LEFT:
583 case BEATBOX_LEFT | BUTTON_REPEAT:
584 {
585 if(editState == EDITSTATE_PATTERN)
586 {
587 if(xCursor > 0)
588 {
589 xCursor--;
590 updateDisplay();
591 redrawScreen(0);
592 }
593 }
594 break;
595 }
596
597 case BEATBOX_RIGHT:
598 case BEATBOX_RIGHT | BUTTON_REPEAT:
599 {
600 if(editState == EDITSTATE_PATTERN)
601 {
602 if(xCursor < H_NUMCELLS-1)
603 {
604 xCursor++;
605 updateDisplay();
606 redrawScreen(0);
607 }
608 }
609 break;
610 }
611
612 case BEATBOX_SELECT:
613 {
614 if(editState == EDITSTATE_PATTERN)
615 {
616 int cv = trackData[xCursor][yCursor];
617 cv++;
618 if(cv > VAL_LOOP)
619 cv = VAL_NONE;
620
621 trackData[xCursor][yCursor] = cv;
622
623 updateDisplay();
624 redrawScreen(0);
625 }
626 break;
627 }
628
629
630 case BEATBOX_PLAY:
631 {
632 if(playState == STATE_PLAYING)
633 playState = STATE_PAUSED;
634 else
635 {
636 updateDisplay();
637 redrawScreen(0);
638 sendEvents();
639 playState = STATE_PLAYING;
640 }
641 break;
642 }
643
644 case BEATBOX_STOP:
645 {
646 if(playState == STATE_STOPPED)
647 {
648 quit=1;
649 } else
650 {
651 playState =STATE_STOPPED;
652 resetPosition();
653 updateDisplay();
654 redrawScreen(0);
655 }
656 break;
657 }
658 }
659
660
661 }
662
663 return 0;
664}