From 8b6d28790ee9e546e48616afbb622246c0962c79 Mon Sep 17 00:00:00 2001 From: Stepan Moskovchenko Date: Thu, 27 Sep 2007 03:59:33 +0000 Subject: Some MIDI changes, and add a new musical plugin I'm working on... Not fully done yet, so commented out of SUBDIRS. (If people are against having half-baked plugins in SVN, please let me know and I will remove it). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14863 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/SOURCES | 2 +- apps/plugins/SUBDIRS | 1 + apps/plugins/beatbox/Makefile | 74 +++++ apps/plugins/beatbox/SOURCES | 6 + apps/plugins/beatbox/beatbox.c | 664 +++++++++++++++++++++++++++++++++++++++++ apps/plugins/midi/synth.c | 41 ++- 6 files changed, 771 insertions(+), 17 deletions(-) create mode 100644 apps/plugins/beatbox/Makefile create mode 100644 apps/plugins/beatbox/SOURCES create mode 100644 apps/plugins/beatbox/beatbox.c (limited to 'apps/plugins') diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index 0c615ef363..7862d554d4 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES @@ -89,7 +89,7 @@ video.c vu_meter.c wormlet.c -#if CONFIG_RTC +#if CONFIG_RTC #if CONFIG_KEYPAD == RECORDER_PAD /* Recorder models only for now */ calendar.c #endif diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS index 5047d617ff..60a5b8a77f 100644 --- a/apps/plugins/SUBDIRS +++ b/apps/plugins/SUBDIRS @@ -43,6 +43,7 @@ doom /* For all the swcodec targets */ #if CONFIG_CODEC == SWCODEC midi +#beatbox mpegplayer #endif diff --git a/apps/plugins/beatbox/Makefile b/apps/plugins/beatbox/Makefile new file mode 100644 index 0000000000..88ed7a4011 --- /dev/null +++ b/apps/plugins/beatbox/Makefile @@ -0,0 +1,74 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id $ +# + +INCLUDES = -I$(APPSDIR) -I.. -I. $(TARGET_INC) -I$(FIRMDIR)/include -I$(FIRMDIR)/export \ + -I$(FIRMDIR)/common -I$(FIRMDIR)/drivers -I$(OUTDIR) -I$(BUILDDIR) +CFLAGS = $(INCLUDES) $(GCCOPTS) $(TARGET) $(EXTRA_DEFINES) \ + -DTARGET_ID=$(TARGET_ID) -DMEM=${MEMORYSIZE} -DPLUGIN -O3 + +ifdef APPEXTRA + INCLUDES += $(patsubst %,-I$(APPSDIR)/%,$(subst :, ,$(APPEXTRA))) +endif + +LINKFILE := $(OBJDIR)/link.lds +DEPFILE = $(OBJDIR)/dep-beatbox + +# This sets up 'SRC' based on the files mentioned in SOURCES +include $(TOOLSDIR)/makesrc.inc + +SOURCES = $(SRC) +OBJS := $(SRC:%.c=$(OBJDIR)/%.o) +DIRS = . + +ifndef SIMVER + LDS := ../plugin.lds + OUTPUT = $(OUTDIR)/beatbox.rock +else ## simulators + OUTPUT = $(OUTDIR)/beatbox.rock +endif + +all: $(OUTPUT) + +ifndef SIMVER +$(OBJDIR)/beatbox.elf: $(OBJS) $(LINKFILE) $(BITMAPLIBS) + $(call PRINTS,LD $(@F))$(CC) $(CFLAGS) -o $@ $(OBJS) -L$(BUILDDIR) -lplugin -lgcc \ + $(LINKBITMAPS) -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/beatbox.map + +$(OUTPUT): $(OBJDIR)/beatbox.elf + $(call PRINTS,OBJCOPY $(@F))$(OC) -O binary $< $@ +else + +################################################### +# This is the SDL simulator version + +$(OUTPUT): $(OBJS) + $(call PRINTS,LD $(@F))$(CC) $(CFLAGS) $(SHARED_FLAG) $(OBJS) -L$(BUILDDIR) -lplugin $(LINKBITMAPS) -o $@ +ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN) +# 'x' must be kept or you'll have "Win32 error 5" +# $ fgrep 5 /usr/include/w32api/winerror.h | head -1 +# #define ERROR_ACCESS_DENIED 5L +else + @chmod -x $@ +endif + +endif # end of simulator section + +include $(TOOLSDIR)/make.inc + +# MEMORYSIZE should be passed on to this makefile with the chosen memory size +# given in number of MB +$(LINKFILE): $(LDS) + $(call PRINTS,build $(@F))cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) \ + $(DEFINES) -E -P - >$@ + +clean: + $(call PRINTS,cleaning beatbox)rm -rf $(OBJDIR)/beatbox + $(SILENT)rm -f $(OBJDIR)/beatbox.* $(DEPFILE) + +-include $(DEPFILE) diff --git a/apps/plugins/beatbox/SOURCES b/apps/plugins/beatbox/SOURCES new file mode 100644 index 0000000000..d56d54d78d --- /dev/null +++ b/apps/plugins/beatbox/SOURCES @@ -0,0 +1,6 @@ +../midi/midifile.c +../midi/midiutil.c +../midi/sequencer.c +../midi/guspat.c +../midi/synth.c +beatbox.c \ No newline at end of file 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 @@ +/*************************************************************************** + * __________ __ ___. + * 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; +} diff --git a/apps/plugins/midi/synth.c b/apps/plugins/midi/synth.c index 917a8ae13d..bcfd79499b 100644 --- a/apps/plugins/midi/synth.c +++ b/apps/plugins/midi/synth.c @@ -88,26 +88,35 @@ int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig) patchUsed[0]=1; /* Scan the file to see what needs to be loaded */ - for(a=0; anumTracks; a++) + if(mf != NULL) { - unsigned int ts=0; - - if(mf->tracks[a] == NULL) + for(a=0; anumTracks; a++) { - printf("NULL TRACK !!!"); - rb->splash(HZ*2, "Null Track in loader."); - return -1; - } + unsigned int ts=0; - for(ts=0; tstracks[a]->numEvents; ts++) - { + if(mf->tracks[a] == NULL) + { + printf("NULL TRACK !!!"); + rb->splash(HZ*2, "Null Track in loader."); + return -1; + } - if((getEvent(mf->tracks[a], ts)->status) == (MIDI_NOTE_ON+9)) - drumUsed[getEvent(mf->tracks[a], ts)->d1]=1; + for(ts=0; tstracks[a]->numEvents; ts++) + { + + if((getEvent(mf->tracks[a], ts)->status) == (MIDI_NOTE_ON+9)) + drumUsed[getEvent(mf->tracks[a], ts)->d1]=1; - if( (getEvent(mf->tracks[a], ts)->status & 0xF0) == MIDI_PRGM) - patchUsed[getEvent(mf->tracks[a], ts)->d1]=1; + if( (getEvent(mf->tracks[a], ts)->status & 0xF0) == MIDI_PRGM) + patchUsed[getEvent(mf->tracks[a], ts)->d1]=1; + } } + } else + { + /* Initialize the whole drum set */ + for(a=0; a<128; a++) + drumUsed[a]=1; + } int file = rb->open(filename, O_RDONLY); @@ -289,7 +298,7 @@ signed short int synthVoice(struct SynthObject * so) s2 = getSample((cpShifted)+1, wf); /* LOOP_REVERSE|LOOP_PINGPONG = 24 */ - if((wf->mode & (24)) && so->loopState == STATE_LOOPING && (cpShifted <= (wf->startLoop))) + if((wf->mode & (24)) && so->loopState == STATE_LOOPING && (cpShifted < (wf->startLoop))) { if(wf->mode & LOOP_REVERSE) { @@ -304,7 +313,7 @@ signed short int synthVoice(struct SynthObject * so) } } - if((wf->mode & 28) && (cpShifted >= wf->endLoop)) + if((wf->mode & 28) && (cpShifted > wf->endLoop)) { so->loopState = STATE_LOOPING; if((wf->mode & (24)) == 0) -- cgit v1.2.3