1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2005 Karl Kurbjun based on midi2wav by Stepan Moskovchenko
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
22 #include "midi/guspat.h"
23 #include "midi/midiutil.h"
24 #include "midi/synth.h"
25 #include "midi/sequencer.h"
26 #include "midi/midifile.h"
31 /* variable button definitions */
32 #if CONFIG_KEYPAD == RECORDER_PAD
33 #define BTN_QUIT BUTTON_OFF
34 #define BTN_RIGHT BUTTON_RIGHT
35 #define BTN_UP BUTTON_UP
36 #define BTN_DOWN BUTTON_DOWN
38 #elif CONFIG_KEYPAD == ONDIO_PAD
39 #define BTN_QUIT BUTTON_OFF
40 #define BTN_RIGHT BUTTON_RIGHT
41 #define BTN_UP BUTTON_UP
42 #define BTN_DOWN BUTTON_DOWN
44 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
45 #define BTN_QUIT BUTTON_OFF
46 #define BTN_RIGHT BUTTON_RIGHT
47 #define BTN_UP BUTTON_UP
48 #define BTN_DOWN BUTTON_DOWN
50 #define BTN_RC_QUIT BUTTON_RC_STOP
52 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
53 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
54 #define BTN_QUIT (BUTTON_SELECT | BUTTON_MENU)
55 #define BTN_RIGHT BUTTON_RIGHT
56 #define BTN_UP BUTTON_SCROLL_FWD
57 #define BTN_DOWN BUTTON_SCROLL_BACK
59 #elif (CONFIG_KEYPAD == GIGABEAT_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
65 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
66 (CONFIG_KEYPAD == SANSA_C200_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
73 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
74 #define BTN_QUIT BUTTON_POWER
75 #define BTN_RIGHT BUTTON_RIGHT
76 #define BTN_UP BUTTON_UP
77 #define BTN_DOWN BUTTON_DOWN
79 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
80 #define BTN_QUIT BUTTON_POWER
81 #define BTN_RIGHT BUTTON_RIGHT
82 #define BTN_UP BUTTON_SCROLL_UP
83 #define BTN_DOWN BUTTON_SCROLL_DOWN
93 #if (HW_SAMPR_CAPS & SAMPR_CAP_22)
94 #define SAMPLE_RATE SAMPR_22 // 44100 22050 11025
96 #define SAMPLE_RATE SAMPR_44 // 44100 22050 11025
99 #define MAX_VOICES 20 // Note: 24 midi channels is the minimum general midi
100 // spec implementation
102 #else // Simulator requires 44100, and we can afford to use more voices
104 #define SAMPLE_RATE SAMPR_44
105 #define MAX_VOICES 48
119 struct MIDIfile
* mf IBSS_ATTR
;
121 int numberOfSamples IBSS_ATTR
;
124 const unsigned char * drumNames
[]={
180 long gmbuf
[BUF_SIZE
*NBUF
];
184 #define STATE_STOPPED 0
185 #define STATE_PAUSED 1
186 #define STATE_PLAYING 2
189 #define BEATBOX_UP BUTTON_UP
190 #define BEATBOX_DOWN BUTTON_DOWN
191 #define BEATBOX_LEFT BUTTON_LEFT
192 #define BEATBOX_RIGHT BUTTON_RIGHT
193 #define BEATBOX_SELECT BUTTON_SELECT
196 #define BEATBOX_PLAY BUTTON_ON
197 #define BEATBOX_STOP BUTTON_OFF
201 #define VAL_ENABLED 1
204 #define H_NUMCELLS 24
207 #define HILIGHT_NONE 0
208 #define HILIGHT_PLAY 1
209 #define HILIGHT_USER 2
218 #define COLOR_NAME_TEXT LCD_RGBPACK(0xFF,0xFF,0xFF)
219 #define COLOR_NORMAL LCD_RGBPACK(0xFF,0xFF,0xFF)
220 #define COLOR_PLAY LCD_RGBPACK(0xFF,0xFF,0x00)
221 #define COLOR_DISABLED LCD_RGBPACK(0xA0,0xA0,0xA0)
222 #define COLOR_LOOPCELL LCD_RGBPACK(0xC0,0xC0,0xC0)
223 #define COLOR_EDIT LCD_RGBPACK(0x30,0x30,0xFF)
224 #define COLOR_GRID LCD_RGBPACK(0xD0,0xD0,0xD0)
226 #define EDITSTATE_PATTERN 0
228 int xCursor
=0, yCursor
=0;
230 int editState
=EDITSTATE_PATTERN
;
232 int playState
=STATE_STOPPED
, stepFlag
=0;
235 enum plugin_status
plugin_start(const void* parameter
)
243 #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
248 rb
->profile_thread();
250 if (initSynth(NULL
, ROCKBOX_DIR
"/patchset/patchset.cfg",
251 ROCKBOX_DIR
"/patchset/drums.cfg") == -1)
253 printf("\nINIT ERROR\n");
258 #if INPUT_SRC_CAPS != 0
259 /* Select playback */
260 rb
->audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
261 rb
->audio_set_output_source(AUDIO_SRC_PLAYBACK
);
263 rb
->pcm_set_frequency(SAMPLE_RATE
); // 44100 22050 11025
266 retval
= beatboxmain();
273 rb
->pcm_set_frequency(HW_SAMPR_DEFAULT
);
275 #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
276 rb
->cpu_boost(false);
288 inline void synthbuf(void)
292 static int currentSample
=0;
296 if(lastswap
==swap
) return;
299 outptr
=(swap
? gmbuf
: gmbuf
+BUF_SIZE
);
304 for(i
=0; i
<BUF_SIZE
/2; i
++)
306 synthSample(&synthtemp
[0], &synthtemp
[1]);
308 *outptr
=((synthtemp
[0]&0xFFFF) << 16) | (synthtemp
[1]&0xFFFF);
310 if(currentSample
==numberOfSamples
)
312 if(playState
== STATE_PLAYING
)
326 unsigned char trackPos
[V_NUMCELLS
];
327 unsigned char trackData
[H_NUMCELLS
][V_NUMCELLS
];
328 unsigned char trackMap
[V_NUMCELLS
] = {38, 39, 40, 41, 42, 43, 44, 56};
337 struct Cell pattern
[H_NUMCELLS
][V_NUMCELLS
];
338 struct Cell dispPattern
[H_NUMCELLS
][V_NUMCELLS
];
341 void advancePosition()
344 for(i
=0; i
<V_NUMCELLS
; i
++)
347 if(trackPos
[i
] == H_NUMCELLS
|| trackData
[trackPos
[i
]][i
] == VAL_LOOP
)
356 for(i
=0; i
<V_NUMCELLS
; i
++)
358 if(trackData
[trackPos
[i
]][i
] == VAL_ENABLED
)
359 pressNote(9, trackMap
[i
], 127);
364 #define NAME_POSY 100
365 void showDrumName(int trackNum
)
367 rb
->lcd_set_foreground(COLOR_NAME_TEXT
);
368 rb
->lcd_putsxy(NAME_POSX
, NAME_POSY
, drumNames
[trackMap
[trackNum
]-35]);
376 for(j
=0; j
<V_NUMCELLS
; j
++)
379 for(i
=0; i
<H_NUMCELLS
; i
++)
381 pattern
[i
][j
].color
= COLOR_NORMAL
;
382 pattern
[i
][j
].val
= trackData
[i
][j
];
385 pattern
[i
][j
].color
= COLOR_PLAY
;
388 pattern
[i
][j
].color
= COLOR_DISABLED
;
390 if(trackData
[i
][j
] == VAL_LOOP
)
392 pattern
[i
][j
].color
= COLOR_LOOPCELL
;
396 if(xCursor
== i
&& yCursor
== j
&& editState
== EDITSTATE_PATTERN
)
397 pattern
[i
][j
].color
= COLOR_EDIT
;
406 for(i
=0; i
<V_NUMCELLS
; i
++)
413 for(i
=0; i
<H_NUMCELLS
; i
++)
414 for(j
=0; j
<V_NUMCELLS
; j
++)
416 pattern
[i
][j
].val
=VAL_NONE
;
417 dispPattern
[i
][j
].val
=VAL_NONE
;
418 pattern
[i
][j
].color
= 0;
419 dispPattern
[i
][j
].color
= 0;
430 rb
->lcd_set_foreground(COLOR_GRID
);
432 for(i
=0; i
<H_NUMCELLS
+1; i
++)
433 rb
->lcd_vline(i
*CELL_XSIZE
+GRID_XPOS
, GRID_YPOS
, GRID_YPOS
+CELL_YSIZE
*V_NUMCELLS
);
435 for(i
=0; i
<V_NUMCELLS
+1; i
++)
436 rb
->lcd_hline(GRID_XPOS
, GRID_XPOS
+CELL_XSIZE
*H_NUMCELLS
, GRID_YPOS
+i
*CELL_YSIZE
);
442 void drawCell(int i
, int j
)
446 cellX
= GRID_XPOS
+ CELL_XSIZE
*i
+1;
447 cellY
= GRID_YPOS
+ CELL_YSIZE
*j
+1;
449 rb
->lcd_set_foreground(pattern
[i
][j
].color
);
450 rb
->lcd_fillrect(cellX
, cellY
, CELL_XSIZE
-1, CELL_YSIZE
-1);
452 rb
->lcd_set_foreground(0);
454 if(pattern
[i
][j
].val
== VAL_LOOP
)
456 rb
->lcd_drawline(cellX
, cellY
, cellX
+CELL_XSIZE
-2, cellY
+CELL_YSIZE
-2);
459 if(pattern
[i
][j
].val
== VAL_ENABLED
)
461 rb
->lcd_fillrect(cellX
+1, cellY
+1, CELL_XSIZE
-3, CELL_YSIZE
-3);
466 void redrawScreen(unsigned char force
)
470 for(i
=0; i
<H_NUMCELLS
; i
++)
472 for(j
=0; j
<V_NUMCELLS
; j
++)
474 if(force
|| (pattern
[i
][j
].val
!= dispPattern
[i
][j
].val
|| pattern
[i
][j
].color
!= dispPattern
[i
][j
].color
))
477 dispPattern
[i
][j
].val
= pattern
[i
][j
].val
;
478 dispPattern
[i
][j
].color
= pattern
[i
][j
].color
;
485 void get_more(unsigned char** start
, size_t* size
)
490 // printf("Buffer miss!"); // Comment out the printf to make missses less noticable.
494 synthbuf(); // For some reason midiplayer crashes when an update is forced
497 *size
= BUF_SIZE
*sizeof(short);
499 *start
= (unsigned char*)((swap
? gmbuf
: gmbuf
+ BUF_SIZE
));
502 *start
= (unsigned char*)(gmbuf
);
511 numberOfSamples
=44100/10;
513 rb
->pcm_play_data(&get_more
, NULL
, 0);
515 rb
->lcd_set_background(0x000000);
516 rb
->lcd_clear_display();
522 /* Start at 16 cells/loop for now. User can un-loop if more are needed */
523 for(i
=0; i
<V_NUMCELLS
; i
++)
524 trackData
[16][i
] = VAL_LOOP
;
527 /* Very very rough beat to 'Goodbye Horses'
528 trackData[16][3] = VAL_LOOP;
529 trackData[16][2] = VAL_LOOP;
535 trackData[12][3] = 1;
536 trackData[13][3] = 1;
540 trackData[10][2] = 1;
541 trackData[14][2] = 1;
545 showDrumName(yCursor
);
566 /* Prevent idle poweroff */
567 rb
->reset_poweroff_timer();
569 /* Code taken from Oscilloscope plugin */
570 switch(rb
->button_get(false))
574 case BTN_UP | BUTTON_REPEAT:
575 vol = rb->global_settings->volume;
576 if (vol < rb->sound_max(SOUND_VOLUME))
579 rb->sound_set(SOUND_VOLUME, vol);
580 rb->global_settings->volume = vol;
585 case BTN_DOWN | BUTTON_REPEAT:
586 vol = rb->global_settings->volume;
587 if (vol > rb->sound_min(SOUND_VOLUME))
590 rb->sound_set(SOUND_VOLUME, vol);
591 rb->global_settings->volume = vol;
597 //pressNote(9, 40, 127);
613 //pressNote(9, 39, 127);
619 case BEATBOX_UP
| BUTTON_REPEAT
:
621 if(editState
== EDITSTATE_PATTERN
)
626 showDrumName(yCursor
);
635 case BEATBOX_DOWN
| BUTTON_REPEAT
:
637 if(editState
== EDITSTATE_PATTERN
)
639 if(yCursor
< V_NUMCELLS
-1)
642 showDrumName(yCursor
);
651 case BEATBOX_LEFT
| BUTTON_REPEAT
:
653 if(editState
== EDITSTATE_PATTERN
)
666 case BEATBOX_RIGHT
| BUTTON_REPEAT
:
668 if(editState
== EDITSTATE_PATTERN
)
670 if(xCursor
< H_NUMCELLS
-1)
682 if(editState
== EDITSTATE_PATTERN
)
684 int cv
= trackData
[xCursor
][yCursor
];
689 trackData
[xCursor
][yCursor
] = cv
;
700 if(playState
== STATE_PLAYING
)
701 playState
= STATE_PAUSED
;
707 playState
= STATE_PLAYING
;
714 if(playState
== STATE_STOPPED
)
719 playState
=STATE_STOPPED
;