1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Karl Kurbjun based on midi2wav by Stepan Moskovchenko
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 #include "midi/guspat.h"
24 #include "midi/midiutil.h"
25 #include "midi/synth.h"
26 #include "midi/sequencer.h"
27 #include "midi/midifile.h"
32 /* variable button definitions */
33 #if CONFIG_KEYPAD == RECORDER_PAD
34 #define BTN_QUIT BUTTON_OFF
35 #define BTN_RIGHT BUTTON_RIGHT
36 #define BTN_UP BUTTON_UP
37 #define BTN_DOWN BUTTON_DOWN
39 #elif CONFIG_KEYPAD == ONDIO_PAD
40 #define BTN_QUIT BUTTON_OFF
41 #define BTN_RIGHT BUTTON_RIGHT
42 #define BTN_UP BUTTON_UP
43 #define BTN_DOWN BUTTON_DOWN
45 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
46 #define BTN_QUIT BUTTON_OFF
47 #define BTN_RIGHT BUTTON_RIGHT
48 #define BTN_UP BUTTON_UP
49 #define BTN_DOWN BUTTON_DOWN
51 #define BTN_RC_QUIT BUTTON_RC_STOP
53 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
54 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
55 #define BTN_QUIT (BUTTON_SELECT | BUTTON_MENU)
56 #define BTN_RIGHT BUTTON_RIGHT
57 #define BTN_UP BUTTON_SCROLL_FWD
58 #define BTN_DOWN BUTTON_SCROLL_BACK
60 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
61 #define BTN_QUIT BUTTON_POWER
62 #define BTN_RIGHT BUTTON_RIGHT
63 #define BTN_UP BUTTON_UP
64 #define BTN_DOWN BUTTON_DOWN
66 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
67 (CONFIG_KEYPAD == SANSA_C200_PAD)
68 #define BTN_QUIT BUTTON_POWER
69 #define BTN_RIGHT BUTTON_RIGHT
70 #define BTN_UP BUTTON_UP
71 #define BTN_DOWN BUTTON_DOWN
74 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
75 #define BTN_QUIT BUTTON_POWER
76 #define BTN_RIGHT BUTTON_RIGHT
77 #define BTN_UP BUTTON_UP
78 #define BTN_DOWN BUTTON_DOWN
80 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
81 #define BTN_QUIT BUTTON_POWER
82 #define BTN_RIGHT BUTTON_RIGHT
83 #define BTN_UP BUTTON_SCROLL_UP
84 #define BTN_DOWN BUTTON_SCROLL_DOWN
86 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
87 #define BTN_QUIT BUTTON_PLAY
88 #define BTN_RIGHT BUTTON_RIGHT
89 #define BTN_UP BUTTON_UP
90 #define BTN_DOWN BUTTON_DOWN
100 #if (HW_SAMPR_CAPS & SAMPR_CAP_22)
101 #define SAMPLE_RATE SAMPR_22 // 44100 22050 11025
103 #define SAMPLE_RATE SAMPR_44 // 44100 22050 11025
106 #define MAX_VOICES 20 // Note: 24 midi channels is the minimum general midi
107 // spec implementation
109 #else // Simulator requires 44100, and we can afford to use more voices
111 #define SAMPLE_RATE SAMPR_44
112 #define MAX_VOICES 48
126 struct MIDIfile
* mf IBSS_ATTR
;
128 int numberOfSamples IBSS_ATTR
;
131 const unsigned char * drumNames
[]={
187 long gmbuf
[BUF_SIZE
*NBUF
];
191 #define STATE_STOPPED 0
192 #define STATE_PAUSED 1
193 #define STATE_PLAYING 2
196 #define BEATBOX_UP BUTTON_UP
197 #define BEATBOX_DOWN BUTTON_DOWN
198 #define BEATBOX_LEFT BUTTON_LEFT
199 #define BEATBOX_RIGHT BUTTON_RIGHT
200 #define BEATBOX_SELECT BUTTON_SELECT
203 #define BEATBOX_PLAY BUTTON_ON
204 #define BEATBOX_STOP BUTTON_OFF
208 #define VAL_ENABLED 1
211 #define H_NUMCELLS 24
214 #define HILIGHT_NONE 0
215 #define HILIGHT_PLAY 1
216 #define HILIGHT_USER 2
225 #define COLOR_NAME_TEXT LCD_RGBPACK(0xFF,0xFF,0xFF)
226 #define COLOR_NORMAL LCD_RGBPACK(0xFF,0xFF,0xFF)
227 #define COLOR_PLAY LCD_RGBPACK(0xFF,0xFF,0x00)
228 #define COLOR_DISABLED LCD_RGBPACK(0xA0,0xA0,0xA0)
229 #define COLOR_LOOPCELL LCD_RGBPACK(0xC0,0xC0,0xC0)
230 #define COLOR_EDIT LCD_RGBPACK(0x30,0x30,0xFF)
231 #define COLOR_GRID LCD_RGBPACK(0xD0,0xD0,0xD0)
233 #define EDITSTATE_PATTERN 0
235 int xCursor
=0, yCursor
=0;
237 int editState
=EDITSTATE_PATTERN
;
239 int playState
=STATE_STOPPED
, stepFlag
=0;
242 enum plugin_status
plugin_start(const void* parameter
)
250 #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
255 rb
->profile_thread();
257 if (initSynth(NULL
, ROCKBOX_DIR
"/patchset/patchset.cfg",
258 ROCKBOX_DIR
"/patchset/drums.cfg") == -1)
260 printf("\nINIT ERROR\n");
265 #if INPUT_SRC_CAPS != 0
266 /* Select playback */
267 rb
->audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
268 rb
->audio_set_output_source(AUDIO_SRC_PLAYBACK
);
270 rb
->pcm_set_frequency(SAMPLE_RATE
); // 44100 22050 11025
273 retval
= beatboxmain();
280 rb
->pcm_set_frequency(HW_SAMPR_DEFAULT
);
282 #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
283 rb
->cpu_boost(false);
295 inline void synthbuf(void)
299 static int currentSample
=0;
303 if(lastswap
==swap
) return;
306 outptr
=(swap
? gmbuf
: gmbuf
+BUF_SIZE
);
311 for(i
=0; i
<BUF_SIZE
/2; i
++)
313 synthSample(&synthtemp
[0], &synthtemp
[1]);
315 *outptr
=((synthtemp
[0]&0xFFFF) << 16) | (synthtemp
[1]&0xFFFF);
317 if(currentSample
==numberOfSamples
)
319 if(playState
== STATE_PLAYING
)
333 unsigned char trackPos
[V_NUMCELLS
];
334 unsigned char trackData
[H_NUMCELLS
][V_NUMCELLS
];
335 unsigned char trackMap
[V_NUMCELLS
] = {38, 39, 40, 41, 42, 43, 44, 56};
344 struct Cell pattern
[H_NUMCELLS
][V_NUMCELLS
];
345 struct Cell dispPattern
[H_NUMCELLS
][V_NUMCELLS
];
348 void advancePosition()
351 for(i
=0; i
<V_NUMCELLS
; i
++)
354 if(trackPos
[i
] == H_NUMCELLS
|| trackData
[trackPos
[i
]][i
] == VAL_LOOP
)
363 for(i
=0; i
<V_NUMCELLS
; i
++)
365 if(trackData
[trackPos
[i
]][i
] == VAL_ENABLED
)
366 pressNote(9, trackMap
[i
], 127);
371 #define NAME_POSY 100
372 void showDrumName(int trackNum
)
374 rb
->lcd_set_foreground(COLOR_NAME_TEXT
);
375 rb
->lcd_putsxy(NAME_POSX
, NAME_POSY
, drumNames
[trackMap
[trackNum
]-35]);
383 for(j
=0; j
<V_NUMCELLS
; j
++)
386 for(i
=0; i
<H_NUMCELLS
; i
++)
388 pattern
[i
][j
].color
= COLOR_NORMAL
;
389 pattern
[i
][j
].val
= trackData
[i
][j
];
392 pattern
[i
][j
].color
= COLOR_PLAY
;
395 pattern
[i
][j
].color
= COLOR_DISABLED
;
397 if(trackData
[i
][j
] == VAL_LOOP
)
399 pattern
[i
][j
].color
= COLOR_LOOPCELL
;
403 if(xCursor
== i
&& yCursor
== j
&& editState
== EDITSTATE_PATTERN
)
404 pattern
[i
][j
].color
= COLOR_EDIT
;
413 for(i
=0; i
<V_NUMCELLS
; i
++)
420 for(i
=0; i
<H_NUMCELLS
; i
++)
421 for(j
=0; j
<V_NUMCELLS
; j
++)
423 pattern
[i
][j
].val
=VAL_NONE
;
424 dispPattern
[i
][j
].val
=VAL_NONE
;
425 pattern
[i
][j
].color
= 0;
426 dispPattern
[i
][j
].color
= 0;
437 rb
->lcd_set_foreground(COLOR_GRID
);
439 for(i
=0; i
<H_NUMCELLS
+1; i
++)
440 rb
->lcd_vline(i
*CELL_XSIZE
+GRID_XPOS
, GRID_YPOS
, GRID_YPOS
+CELL_YSIZE
*V_NUMCELLS
);
442 for(i
=0; i
<V_NUMCELLS
+1; i
++)
443 rb
->lcd_hline(GRID_XPOS
, GRID_XPOS
+CELL_XSIZE
*H_NUMCELLS
, GRID_YPOS
+i
*CELL_YSIZE
);
449 void drawCell(int i
, int j
)
453 cellX
= GRID_XPOS
+ CELL_XSIZE
*i
+1;
454 cellY
= GRID_YPOS
+ CELL_YSIZE
*j
+1;
456 rb
->lcd_set_foreground(pattern
[i
][j
].color
);
457 rb
->lcd_fillrect(cellX
, cellY
, CELL_XSIZE
-1, CELL_YSIZE
-1);
459 rb
->lcd_set_foreground(0);
461 if(pattern
[i
][j
].val
== VAL_LOOP
)
463 rb
->lcd_drawline(cellX
, cellY
, cellX
+CELL_XSIZE
-2, cellY
+CELL_YSIZE
-2);
466 if(pattern
[i
][j
].val
== VAL_ENABLED
)
468 rb
->lcd_fillrect(cellX
+1, cellY
+1, CELL_XSIZE
-3, CELL_YSIZE
-3);
473 void redrawScreen(unsigned char force
)
477 for(i
=0; i
<H_NUMCELLS
; i
++)
479 for(j
=0; j
<V_NUMCELLS
; j
++)
481 if(force
|| (pattern
[i
][j
].val
!= dispPattern
[i
][j
].val
|| pattern
[i
][j
].color
!= dispPattern
[i
][j
].color
))
484 dispPattern
[i
][j
].val
= pattern
[i
][j
].val
;
485 dispPattern
[i
][j
].color
= pattern
[i
][j
].color
;
492 void get_more(unsigned char** start
, size_t* size
)
497 // printf("Buffer miss!"); // Comment out the printf to make missses less noticable.
501 synthbuf(); // For some reason midiplayer crashes when an update is forced
504 *size
= BUF_SIZE
*sizeof(short);
506 *start
= (unsigned char*)((swap
? gmbuf
: gmbuf
+ BUF_SIZE
));
509 *start
= (unsigned char*)(gmbuf
);
518 numberOfSamples
=44100/10;
520 rb
->pcm_play_data(&get_more
, NULL
, 0);
522 rb
->lcd_set_background(0x000000);
523 rb
->lcd_clear_display();
529 /* Start at 16 cells/loop for now. User can un-loop if more are needed */
530 for(i
=0; i
<V_NUMCELLS
; i
++)
531 trackData
[16][i
] = VAL_LOOP
;
534 /* Very very rough beat to 'Goodbye Horses'
535 trackData[16][3] = VAL_LOOP;
536 trackData[16][2] = VAL_LOOP;
542 trackData[12][3] = 1;
543 trackData[13][3] = 1;
547 trackData[10][2] = 1;
548 trackData[14][2] = 1;
552 showDrumName(yCursor
);
573 /* Prevent idle poweroff */
574 rb
->reset_poweroff_timer();
576 /* Code taken from Oscilloscope plugin */
577 switch(rb
->button_get(false))
581 case BTN_UP | BUTTON_REPEAT:
582 vol = rb->global_settings->volume;
583 if (vol < rb->sound_max(SOUND_VOLUME))
586 rb->sound_set(SOUND_VOLUME, vol);
587 rb->global_settings->volume = vol;
592 case BTN_DOWN | BUTTON_REPEAT:
593 vol = rb->global_settings->volume;
594 if (vol > rb->sound_min(SOUND_VOLUME))
597 rb->sound_set(SOUND_VOLUME, vol);
598 rb->global_settings->volume = vol;
604 //pressNote(9, 40, 127);
620 //pressNote(9, 39, 127);
626 case BEATBOX_UP
| BUTTON_REPEAT
:
628 if(editState
== EDITSTATE_PATTERN
)
633 showDrumName(yCursor
);
642 case BEATBOX_DOWN
| BUTTON_REPEAT
:
644 if(editState
== EDITSTATE_PATTERN
)
646 if(yCursor
< V_NUMCELLS
-1)
649 showDrumName(yCursor
);
658 case BEATBOX_LEFT
| BUTTON_REPEAT
:
660 if(editState
== EDITSTATE_PATTERN
)
673 case BEATBOX_RIGHT
| BUTTON_REPEAT
:
675 if(editState
== EDITSTATE_PATTERN
)
677 if(xCursor
< H_NUMCELLS
-1)
689 if(editState
== EDITSTATE_PATTERN
)
691 int cv
= trackData
[xCursor
][yCursor
];
696 trackData
[xCursor
][yCursor
] = cv
;
707 if(playState
== STATE_PLAYING
)
708 playState
= STATE_PAUSED
;
714 playState
= STATE_PLAYING
;
721 if(playState
== STATE_STOPPED
)
726 playState
=STATE_STOPPED
;