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
92 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
93 #define BTN_QUIT BUTTON_REC
94 #define BTN_RIGHT BUTTON_NEXT
95 #define BTN_UP BUTTON_UP
96 #define BTN_DOWN BUTTON_DOWN
106 #if (HW_SAMPR_CAPS & SAMPR_CAP_22)
107 #define SAMPLE_RATE SAMPR_22 // 44100 22050 11025
109 #define SAMPLE_RATE SAMPR_44 // 44100 22050 11025
112 #define MAX_VOICES 20 // Note: 24 midi channels is the minimum general midi
113 // spec implementation
115 #else // Simulator requires 44100, and we can afford to use more voices
117 #define SAMPLE_RATE SAMPR_44
118 #define MAX_VOICES 48
132 struct MIDIfile
* mf IBSS_ATTR
;
134 int numberOfSamples IBSS_ATTR
;
137 const unsigned char * drumNames
[]={
193 long gmbuf
[BUF_SIZE
*NBUF
];
197 #define STATE_STOPPED 0
198 #define STATE_PAUSED 1
199 #define STATE_PLAYING 2
202 #define BEATBOX_UP BUTTON_UP
203 #define BEATBOX_DOWN BUTTON_DOWN
204 #define BEATBOX_LEFT BUTTON_LEFT
205 #define BEATBOX_RIGHT BUTTON_RIGHT
206 #define BEATBOX_SELECT BUTTON_SELECT
209 #define BEATBOX_PLAY BUTTON_ON
210 #define BEATBOX_STOP BUTTON_OFF
214 #define VAL_ENABLED 1
217 #define H_NUMCELLS 24
220 #define HILIGHT_NONE 0
221 #define HILIGHT_PLAY 1
222 #define HILIGHT_USER 2
231 #define COLOR_NAME_TEXT LCD_RGBPACK(0xFF,0xFF,0xFF)
232 #define COLOR_NORMAL LCD_RGBPACK(0xFF,0xFF,0xFF)
233 #define COLOR_PLAY LCD_RGBPACK(0xFF,0xFF,0x00)
234 #define COLOR_DISABLED LCD_RGBPACK(0xA0,0xA0,0xA0)
235 #define COLOR_LOOPCELL LCD_RGBPACK(0xC0,0xC0,0xC0)
236 #define COLOR_EDIT LCD_RGBPACK(0x30,0x30,0xFF)
237 #define COLOR_GRID LCD_RGBPACK(0xD0,0xD0,0xD0)
239 #define EDITSTATE_PATTERN 0
241 int xCursor
=0, yCursor
=0;
243 int editState
=EDITSTATE_PATTERN
;
245 int playState
=STATE_STOPPED
, stepFlag
=0;
248 enum plugin_status
plugin_start(const void* parameter
)
256 #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
261 rb
->profile_thread();
263 if (initSynth(NULL
, ROCKBOX_DIR
"/patchset/patchset.cfg",
264 ROCKBOX_DIR
"/patchset/drums.cfg") == -1)
266 printf("\nINIT ERROR\n");
271 #if INPUT_SRC_CAPS != 0
272 /* Select playback */
273 rb
->audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
274 rb
->audio_set_output_source(AUDIO_SRC_PLAYBACK
);
276 rb
->pcm_set_frequency(SAMPLE_RATE
); // 44100 22050 11025
279 retval
= beatboxmain();
286 rb
->pcm_set_frequency(HW_SAMPR_DEFAULT
);
288 #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
289 rb
->cpu_boost(false);
301 inline void synthbuf(void)
305 static int currentSample
=0;
309 if(lastswap
==swap
) return;
312 outptr
=(swap
? gmbuf
: gmbuf
+BUF_SIZE
);
317 for(i
=0; i
<BUF_SIZE
/2; i
++)
319 synthSample(&synthtemp
[0], &synthtemp
[1]);
321 *outptr
=((synthtemp
[0]&0xFFFF) << 16) | (synthtemp
[1]&0xFFFF);
323 if(currentSample
==numberOfSamples
)
325 if(playState
== STATE_PLAYING
)
339 unsigned char trackPos
[V_NUMCELLS
];
340 unsigned char trackData
[H_NUMCELLS
][V_NUMCELLS
];
341 unsigned char trackMap
[V_NUMCELLS
] = {38, 39, 40, 41, 42, 43, 44, 56};
350 struct Cell pattern
[H_NUMCELLS
][V_NUMCELLS
];
351 struct Cell dispPattern
[H_NUMCELLS
][V_NUMCELLS
];
354 void advancePosition()
357 for(i
=0; i
<V_NUMCELLS
; i
++)
360 if(trackPos
[i
] == H_NUMCELLS
|| trackData
[trackPos
[i
]][i
] == VAL_LOOP
)
369 for(i
=0; i
<V_NUMCELLS
; i
++)
371 if(trackData
[trackPos
[i
]][i
] == VAL_ENABLED
)
372 pressNote(9, trackMap
[i
], 127);
377 #define NAME_POSY 100
378 void showDrumName(int trackNum
)
380 rb
->lcd_set_foreground(COLOR_NAME_TEXT
);
381 rb
->lcd_putsxy(NAME_POSX
, NAME_POSY
, drumNames
[trackMap
[trackNum
]-35]);
389 for(j
=0; j
<V_NUMCELLS
; j
++)
392 for(i
=0; i
<H_NUMCELLS
; i
++)
394 pattern
[i
][j
].color
= COLOR_NORMAL
;
395 pattern
[i
][j
].val
= trackData
[i
][j
];
398 pattern
[i
][j
].color
= COLOR_PLAY
;
401 pattern
[i
][j
].color
= COLOR_DISABLED
;
403 if(trackData
[i
][j
] == VAL_LOOP
)
405 pattern
[i
][j
].color
= COLOR_LOOPCELL
;
409 if(xCursor
== i
&& yCursor
== j
&& editState
== EDITSTATE_PATTERN
)
410 pattern
[i
][j
].color
= COLOR_EDIT
;
419 for(i
=0; i
<V_NUMCELLS
; i
++)
426 for(i
=0; i
<H_NUMCELLS
; i
++)
427 for(j
=0; j
<V_NUMCELLS
; j
++)
429 pattern
[i
][j
].val
=VAL_NONE
;
430 dispPattern
[i
][j
].val
=VAL_NONE
;
431 pattern
[i
][j
].color
= 0;
432 dispPattern
[i
][j
].color
= 0;
443 rb
->lcd_set_foreground(COLOR_GRID
);
445 for(i
=0; i
<H_NUMCELLS
+1; i
++)
446 rb
->lcd_vline(i
*CELL_XSIZE
+GRID_XPOS
, GRID_YPOS
, GRID_YPOS
+CELL_YSIZE
*V_NUMCELLS
);
448 for(i
=0; i
<V_NUMCELLS
+1; i
++)
449 rb
->lcd_hline(GRID_XPOS
, GRID_XPOS
+CELL_XSIZE
*H_NUMCELLS
, GRID_YPOS
+i
*CELL_YSIZE
);
455 void drawCell(int i
, int j
)
459 cellX
= GRID_XPOS
+ CELL_XSIZE
*i
+1;
460 cellY
= GRID_YPOS
+ CELL_YSIZE
*j
+1;
462 rb
->lcd_set_foreground(pattern
[i
][j
].color
);
463 rb
->lcd_fillrect(cellX
, cellY
, CELL_XSIZE
-1, CELL_YSIZE
-1);
465 rb
->lcd_set_foreground(0);
467 if(pattern
[i
][j
].val
== VAL_LOOP
)
469 rb
->lcd_drawline(cellX
, cellY
, cellX
+CELL_XSIZE
-2, cellY
+CELL_YSIZE
-2);
472 if(pattern
[i
][j
].val
== VAL_ENABLED
)
474 rb
->lcd_fillrect(cellX
+1, cellY
+1, CELL_XSIZE
-3, CELL_YSIZE
-3);
479 void redrawScreen(unsigned char force
)
483 for(i
=0; i
<H_NUMCELLS
; i
++)
485 for(j
=0; j
<V_NUMCELLS
; j
++)
487 if(force
|| (pattern
[i
][j
].val
!= dispPattern
[i
][j
].val
|| pattern
[i
][j
].color
!= dispPattern
[i
][j
].color
))
490 dispPattern
[i
][j
].val
= pattern
[i
][j
].val
;
491 dispPattern
[i
][j
].color
= pattern
[i
][j
].color
;
498 void get_more(unsigned char** start
, size_t* size
)
503 // printf("Buffer miss!"); // Comment out the printf to make missses less noticable.
507 synthbuf(); // For some reason midiplayer crashes when an update is forced
510 *size
= BUF_SIZE
*sizeof(short);
512 *start
= (unsigned char*)((swap
? gmbuf
: gmbuf
+ BUF_SIZE
));
515 *start
= (unsigned char*)(gmbuf
);
524 numberOfSamples
=44100/10;
526 rb
->pcm_play_data(&get_more
, NULL
, 0);
528 rb
->lcd_set_background(0x000000);
529 rb
->lcd_clear_display();
535 /* Start at 16 cells/loop for now. User can un-loop if more are needed */
536 for(i
=0; i
<V_NUMCELLS
; i
++)
537 trackData
[16][i
] = VAL_LOOP
;
540 /* Very very rough beat to 'Goodbye Horses'
541 trackData[16][3] = VAL_LOOP;
542 trackData[16][2] = VAL_LOOP;
548 trackData[12][3] = 1;
549 trackData[13][3] = 1;
553 trackData[10][2] = 1;
554 trackData[14][2] = 1;
558 showDrumName(yCursor
);
579 /* Prevent idle poweroff */
580 rb
->reset_poweroff_timer();
582 /* Code taken from Oscilloscope plugin */
583 switch(rb
->button_get(false))
587 case BTN_UP | BUTTON_REPEAT:
588 vol = rb->global_settings->volume;
589 if (vol < rb->sound_max(SOUND_VOLUME))
592 rb->sound_set(SOUND_VOLUME, vol);
593 rb->global_settings->volume = vol;
598 case BTN_DOWN | BUTTON_REPEAT:
599 vol = rb->global_settings->volume;
600 if (vol > rb->sound_min(SOUND_VOLUME))
603 rb->sound_set(SOUND_VOLUME, vol);
604 rb->global_settings->volume = vol;
610 //pressNote(9, 40, 127);
626 //pressNote(9, 39, 127);
632 case BEATBOX_UP
| BUTTON_REPEAT
:
634 if(editState
== EDITSTATE_PATTERN
)
639 showDrumName(yCursor
);
648 case BEATBOX_DOWN
| BUTTON_REPEAT
:
650 if(editState
== EDITSTATE_PATTERN
)
652 if(yCursor
< V_NUMCELLS
-1)
655 showDrumName(yCursor
);
664 case BEATBOX_LEFT
| BUTTON_REPEAT
:
666 if(editState
== EDITSTATE_PATTERN
)
679 case BEATBOX_RIGHT
| BUTTON_REPEAT
:
681 if(editState
== EDITSTATE_PATTERN
)
683 if(xCursor
< H_NUMCELLS
-1)
695 if(editState
== EDITSTATE_PATTERN
)
697 int cv
= trackData
[xCursor
][yCursor
];
702 trackData
[xCursor
][yCursor
] = cv
;
713 if(playState
== STATE_PLAYING
)
714 playState
= STATE_PAUSED
;
720 playState
= STATE_PLAYING
;
727 if(playState
== STATE_STOPPED
)
732 playState
=STATE_STOPPED
;