/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * * Copyright (C) 2005 Karl Kurbjun based on midi2wav by Stepan Moskovchenko * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "../../plugin.h" PLUGIN_HEADER PLUGIN_IRAM_DECLARE /* variable button definitions */ #if CONFIG_KEYPAD == RECORDER_PAD #define BTN_QUIT BUTTON_OFF #define BTN_RIGHT BUTTON_RIGHT #define BTN_UP BUTTON_UP #define BTN_DOWN BUTTON_DOWN #elif CONFIG_KEYPAD == ONDIO_PAD #define BTN_QUIT BUTTON_OFF #define BTN_RIGHT BUTTON_RIGHT #define BTN_UP BUTTON_UP #define BTN_DOWN BUTTON_DOWN #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) #define BTN_QUIT BUTTON_OFF #define BTN_RIGHT BUTTON_RIGHT #define BTN_UP BUTTON_UP #define BTN_DOWN BUTTON_DOWN #define BTN_RC_QUIT BUTTON_RC_STOP #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ (CONFIG_KEYPAD == IPOD_1G2G_PAD) #define BTN_QUIT (BUTTON_SELECT | BUTTON_MENU) #define BTN_RIGHT BUTTON_RIGHT #define BTN_UP BUTTON_SCROLL_FWD #define BTN_DOWN BUTTON_SCROLL_BACK #elif (CONFIG_KEYPAD == GIGABEAT_PAD) #define BTN_QUIT BUTTON_POWER #define BTN_RIGHT BUTTON_RIGHT #define BTN_UP BUTTON_UP #define BTN_DOWN BUTTON_DOWN #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \ (CONFIG_KEYPAD == SANSA_C200_PAD) #define BTN_QUIT BUTTON_POWER #define BTN_RIGHT BUTTON_RIGHT #define BTN_UP BUTTON_UP #define BTN_DOWN BUTTON_DOWN #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD #define BTN_QUIT BUTTON_POWER #define BTN_RIGHT BUTTON_RIGHT #define BTN_UP BUTTON_UP #define BTN_DOWN BUTTON_DOWN #elif CONFIG_KEYPAD == IRIVER_H10_PAD #define BTN_QUIT BUTTON_POWER #define BTN_RIGHT BUTTON_RIGHT #define BTN_UP BUTTON_SCROLL_UP #define BTN_DOWN BUTTON_SCROLL_DOWN #endif #define FRACTSIZE 10 #ifndef SIMULATOR #if (HW_SAMPR_CAPS & SAMPR_CAP_22) #define SAMPLE_RATE SAMPR_22 // 44100 22050 11025 #else #define SAMPLE_RATE SAMPR_44 // 44100 22050 11025 #endif #define MAX_VOICES 20 // Note: 24 midi channels is the minimum general midi // spec implementation #else // Simulator requires 44100, and we can afford to use more voices #define SAMPLE_RATE SAMPR_44 #define MAX_VOICES 48 #endif #define BUF_SIZE 256 #define NBUF 2 #undef SYNC #ifdef SIMULATOR #define SYNC #endif struct MIDIfile * mf IBSS_ATTR; int numberOfSamples IBSS_ATTR; long bpm IBSS_ATTR; #include "plugin.h" #include "midi/guspat.h" #include "midi/midiutil.h" #include "midi/synth.h" #include "midi/sequencer.h" #include "midi/midifile.h" long gmbuf[BUF_SIZE*NBUF]; int quit=0; struct plugin_api * rb; #define STATE_STOPPED 0 #define STATE_PAUSED 1 #define STATE_PLAYING 2 #define BEATBOX_UP BUTTON_UP #define BEATBOX_DOWN BUTTON_DOWN #define BEATBOX_LEFT BUTTON_LEFT #define BEATBOX_RIGHT BUTTON_RIGHT #define BEATBOX_SELECT BUTTON_SELECT #define BEATBOX_PLAY BUTTON_ON #define BEATBOX_STOP BUTTON_OFF #define VAL_NONE 0 #define VAL_ENABLED 1 #define VAL_LOOP 2 #define H_NUMCELLS 24 #define V_NUMCELLS 8 #define HILIGHT_NONE 0 #define HILIGHT_PLAY 1 #define HILIGHT_USER 2 #define CELL_XSIZE 9 #define CELL_YSIZE 9 #define GRID_XPOS 2 #define GRID_YPOS 10 #define COLOR_NORMAL LCD_RGBPACK(0xFF,0xFF,0xFF) #define COLOR_PLAY LCD_RGBPACK(0xFF,0xFF,0x00) #define COLOR_DISABLED LCD_RGBPACK(0xA0,0xA0,0xA0) #define COLOR_LOOPCELL LCD_RGBPACK(0xC0,0xC0,0xC0) #define COLOR_EDIT LCD_RGBPACK(0x30,0x30,0xFF) #define COLOR_GRID LCD_RGBPACK(0xD0,0xD0,0xD0) #define EDITSTATE_PATTERN 0 int xCursor=0, yCursor=0; int editState=EDITSTATE_PATTERN; int playState=STATE_STOPPED, stepFlag=0; enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { int retval = 0; PLUGIN_IRAM_INIT(api) rb = api; rb->lcd_setfont(0); #if defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(true); #endif #ifdef RB_PROFILE rb->profile_thread(); #endif if (initSynth(NULL, ROCKBOX_DIR "/patchset/patchset.cfg", ROCKBOX_DIR "/patchset/drums.cfg") == -1) { printf("\nINIT ERROR\n"); return -1; } //#ifndef SIMULATOR rb->pcm_play_stop(); #if INPUT_SRC_CAPS != 0 /* Select playback */ rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); #endif rb->pcm_set_frequency(SAMPLE_RATE); // 44100 22050 11025 retval = beatboxmain(); #ifdef RB_PROFILE rb->profstop(); #endif rb->pcm_play_stop(); rb->pcm_set_frequency(HW_SAMPR_DEFAULT); #if defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(false); #endif if(retval == -1) return PLUGIN_ERROR; return PLUGIN_OK; } bool swap=0; bool lastswap=1; inline void synthbuf(void) { long *outptr; register int i; static int currentSample=0; int synthtemp[2]; #ifndef SYNC if(lastswap==swap) return; lastswap=swap; outptr=(swap ? gmbuf : gmbuf+BUF_SIZE); #else outptr=gmbuf; #endif for(i=0; ilcd_set_foreground(COLOR_GRID); for(i=0; ilcd_vline(i*CELL_XSIZE+GRID_XPOS, GRID_YPOS, GRID_YPOS+CELL_YSIZE*V_NUMCELLS); for(i=0; ilcd_hline(GRID_XPOS, GRID_XPOS+CELL_XSIZE*H_NUMCELLS, GRID_YPOS+i*CELL_YSIZE); rb->lcd_update(); } void drawCell(int i, int j) { int cellX, cellY; cellX = GRID_XPOS + CELL_XSIZE*i+1; cellY = GRID_YPOS + CELL_YSIZE*j+1; rb->lcd_set_foreground(pattern[i][j].color); rb->lcd_fillrect(cellX, cellY, CELL_XSIZE-1, CELL_YSIZE-1); rb->lcd_set_foreground(0); if(pattern[i][j].val == VAL_LOOP) { rb->lcd_drawline(cellX, cellY, cellX+CELL_XSIZE-2, cellY+CELL_YSIZE-2); } if(pattern[i][j].val == VAL_ENABLED) { rb->lcd_fillrect(cellX+1, cellY+1, CELL_XSIZE-3, CELL_YSIZE-3); } } void redrawScreen(unsigned char force) { int i, j; for(i=0; ilcd_update(); } void get_more(unsigned char** start, size_t* size) { #ifndef SYNC if(lastswap!=swap) { // printf("Buffer miss!"); // Comment out the printf to make missses less noticable. } #else synthbuf(); // For some reason midiplayer crashes when an update is forced #endif *size = BUF_SIZE*sizeof(short); #ifndef SYNC *start = (unsigned char*)((swap ? gmbuf : gmbuf + BUF_SIZE)); swap=!swap; #else *start = (unsigned char*)(gmbuf); #endif } int beatboxmain() { int vol=0; numberOfSamples=44100/10; synthbuf(); rb->pcm_play_data(&get_more, NULL, 0); rb->lcd_set_background(0x000000); rb->lcd_clear_display(); resetPosition(); int i, j; trackData[16][3] = VAL_LOOP; trackData[16][2] = VAL_LOOP; trackData[0][3] = 1; trackData[4][3] = 1; trackData[8][3] = 1; trackData[9][3] = 1; trackData[12][3] = 1; trackData[13][3] = 1; trackData[2][2] = 1; trackData[6][2] = 1; trackData[10][2] = 1; trackData[14][2] = 1; drawGrid(); updateDisplay(); redrawScreen(1); while(!quit) { #ifndef SYNC synthbuf(); #endif rb->yield(); if(stepFlag) { advancePosition(); sendEvents(); updateDisplay(); redrawScreen(0); stepFlag=0; } /* Prevent idle poweroff */ rb->reset_poweroff_timer(); /* Code taken from Oscilloscope plugin */ switch(rb->button_get(false)) { /* case BTN_UP: case BTN_UP | BUTTON_REPEAT: vol = rb->global_settings->volume; if (vol < rb->sound_max(SOUND_VOLUME)) { vol++; rb->sound_set(SOUND_VOLUME, vol); rb->global_settings->volume = vol; } break; case BTN_DOWN: case BTN_DOWN | BUTTON_REPEAT: vol = rb->global_settings->volume; if (vol > rb->sound_min(SOUND_VOLUME)) { vol--; rb->sound_set(SOUND_VOLUME, vol); rb->global_settings->volume = vol; } break; case BTN_RIGHT: { //pressNote(9, 40, 127); // resetPosition(); advancePosition(); sendEvents(); updateDisplay(); redrawScreen(0); break; } case BUTTON_LEFT: { // isPlaying=1; resetPosition(); updateDisplay(); redrawScreen(0); //pressNote(9, 39, 127); break; } */ case BEATBOX_UP: case BEATBOX_UP | BUTTON_REPEAT: { if(editState == EDITSTATE_PATTERN) { if(yCursor > 0) { yCursor--; updateDisplay(); redrawScreen(0); } } break; } case BEATBOX_DOWN: case BEATBOX_DOWN | BUTTON_REPEAT: { if(editState == EDITSTATE_PATTERN) { if(yCursor < V_NUMCELLS-1) { yCursor++; updateDisplay(); redrawScreen(0); } } break; } case BEATBOX_LEFT: case BEATBOX_LEFT | BUTTON_REPEAT: { if(editState == EDITSTATE_PATTERN) { if(xCursor > 0) { xCursor--; updateDisplay(); redrawScreen(0); } } break; } case BEATBOX_RIGHT: case BEATBOX_RIGHT | BUTTON_REPEAT: { if(editState == EDITSTATE_PATTERN) { if(xCursor < H_NUMCELLS-1) { xCursor++; updateDisplay(); redrawScreen(0); } } break; } case BEATBOX_SELECT: { if(editState == EDITSTATE_PATTERN) { int cv = trackData[xCursor][yCursor]; cv++; if(cv > VAL_LOOP) cv = VAL_NONE; trackData[xCursor][yCursor] = cv; updateDisplay(); redrawScreen(0); } break; } case BEATBOX_PLAY: { if(playState == STATE_PLAYING) playState = STATE_PAUSED; else { updateDisplay(); redrawScreen(0); sendEvents(); playState = STATE_PLAYING; } break; } case BEATBOX_STOP: { if(playState == STATE_STOPPED) { quit=1; } else { playState =STATE_STOPPED; resetPosition(); updateDisplay(); redrawScreen(0); } break; } } } return 0; }