Index: apps/plugins/midi2wav.c =================================================================== RCS file: /cvsroot/rockbox/apps/plugins/midi2wav.c,v retrieving revision 1.9 diff -u -r1.9 midi2wav.c --- apps/plugins/midi2wav.c 15 Jan 2006 18:20:08 -0000 1.9 +++ apps/plugins/midi2wav.c 10 Feb 2006 00:19:40 -0000 @@ -16,34 +16,18 @@ * ****************************************************************************/ -#define SAMPLE_RATE 22050 -#define MAX_VOICES 100 - - -/* Only define LOCAL_DSP on Simulator or else we're asking for trouble */ -#if defined(SIMULATOR) - /*Enable this to write to the soundcard via a /dsv/dsp symlink in */ - //#define LOCAL_DSP -#endif - - -#if defined(LOCAL_DSP) -/* This is for writing to the DSP directly from the Simulator */ -#include -#include -#include -#include -#endif - -#include "../../firmware/export/system.h" - #include "../../plugin.h" -//#include "../codecs/lib/xxx2wav.h" - PLUGIN_HEADER -int numberOfSamples IDATA_ATTR; +#define SAMPLE_RATE 11025 // 44100 22050 11025 +#define MAX_VOICES 100 // I've found that setting this to 25 doesn't hurt the midi + // files I was testing and significantly reduced the buffer + // misses. +#define BUF_SIZE 256 +#define NBUF 2 + +int numberOfSamples; long bpm; #include "midi/midiutil.c" @@ -53,186 +37,145 @@ #include "midi/midifile.c" #include "midi/synth.c" +int currentSample; +unsigned int *outptr; +int quit=0; +struct MIDIfile * mf; - -int fd=-1; /* File descriptor where the output is written */ - -extern long tempo; /* The sequencer keeps track of this */ - +unsigned int gmbuf[BUF_SIZE*NBUF]; struct plugin_api * rb; - - - +#ifdef USE_IRAM +extern char iramcopy[]; +extern char iramstart[]; +extern char iramend[]; +extern char iedata[]; +extern char iend[]; +#endif enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { - (void)parameter; - rb = api; - - if(parameter == NULL) - { - rb->splash(HZ*2, true, " Play .MID file "); - return PLUGIN_OK; - } - - rb->splash(HZ, true, parameter); - if(midimain(parameter) == -1) - { - return PLUGIN_ERROR; - } - rb->splash(HZ*3, true, "FINISHED PLAYING"); - /* Return PLUGIN_USB_CONNECTED to force a file-tree refresh */ - return PLUGIN_USB_CONNECTED; -} - -signed char outputBuffer[3000] IDATA_ATTR; /* signed char.. gonna run out of iram ... ! */ - + rb = api; -int currentSample IDATA_ATTR; -int outputBufferPosition IDATA_ATTR; -int outputSampleOne IDATA_ATTR; -int outputSampleTwo IDATA_ATTR; - - -int midimain(void * filename) -{ - - printf("\nHello.\n"); - - rb->splash(HZ/5, true, "LOADING MIDI"); - - struct MIDIfile * mf = loadFile(filename); - - rb->splash(HZ/5, true, "LOADING PATCHES"); - if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1) - { - return -1; - } - -/* - * This lets you hear the music through the sound card if you are on Simulator - * Make a symlink, archos/dsp.raw and make it point to /dev/dsp or whatever - * your sound device is. - */ - -#if defined(LOCAL_DSP) - fd=rb->open("/dsp.raw", O_WRONLY); - int arg, status; - int bit, samp, ch; - - arg = 16; /* sample size */ - status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg); - status = ioctl(fd, SOUND_PCM_READ_BITS, &arg); - bit=arg; - - - arg = 2; /* Number of channels, 1=mono */ - status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg); - status = ioctl(fd, SOUND_PCM_READ_CHANNELS, &arg); - ch=arg; - - arg = SAMPLE_RATE; /* Yeah. sampling rate */ - status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg); - status = ioctl(fd, SOUND_PCM_READ_RATE, &arg); - samp=arg; -#else - -/* xxx2wav stuff, removed for now, will move to the real way of outputting sound soon */ -/* - file_info_struct file_info; - file_info.samplerate = SAMPLE_RATE; - file_info.infile = fd; - file_info.channels = 2; - file_info.bitspersample = 16; - local_init("/miditest.tmp", "/miditest.wav", &file_info, rb); - fd = file_info.outfile; -*/ + if(parameter == NULL) + { + rb->splash(HZ*2, true, " Play .MID file "); + return PLUGIN_OK; + } + rb->lcd_setfont(0); + +#ifdef USE_IRAM + rb->memcpy(iramstart, iramcopy, iramend-iramstart); + rb->memset(iedata, 0, iend - iedata); #endif +#if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ) + rb->cpu_boost(true); +#endif - rb->splash(HZ/5, true, " I hope this works... "); - - + rb->splash(HZ, true, parameter); + if(midimain(parameter) == -1) + { + return PLUGIN_ERROR; + } - /* - * tick() will do one MIDI clock tick. Then, there's a loop here that - * will generate the right number of samples per MIDI tick. The whole - * MIDI playback is timed in terms of this value.. there are no forced - * delays or anything. It just produces enough samples for each tick, and - * the playback of these samples is what makes the timings right. - * - * This seems to work quite well. - */ + rb->pcm_play_stop(); + rb->pcm_set_frequency(44100); // 44100 - printf("\nOkay, starting sequencing"); +#if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ) + rb->cpu_boost(false); +#endif + rb->splash(HZ, true, "FINISHED PLAYING"); - currentSample=0; /* Sample counting variable */ - outputBufferPosition = 0; + return PLUGIN_OK; +} +bool swap=0; +bool lastswap=1; - bpm=mf->div*1000000/tempo; - numberOfSamples=SAMPLE_RATE/bpm; +inline void synthbuf(void) +{ + register int i; + + if(lastswap==swap) return; + lastswap=swap; + + outptr=(swap ? gmbuf : gmbuf+BUF_SIZE); + + for(i=0; isplash(HZ/5, true, "LOADING MIDI"); - synthSample(&outputSampleOne, &outputSampleTwo); + mf= loadFile(filename); + rb->splash(HZ/5, true, "LOADING PATCHES"); + if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1) + return -1; - /* - * 16-bit audio because, well, it's better - * But really because ALSA's OSS emulation sounds extremely - * noisy and distorted when in 8-bit mode. I still do not know - * why this happens. - */ + rb->pcm_play_stop(); + + rb->pcm_set_frequency(SAMPLE_RATE); // 44100 22050 11025 - outputBuffer[outputBufferPosition]=outputSampleOne&0XFF; // Low byte first - outputBufferPosition++; - outputBuffer[outputBufferPosition]=outputSampleOne>>8; //High byte second - outputBufferPosition++; + /* + * tick() will do one MIDI clock tick. Then, there's a loop here that + * will generate the right number of samples per MIDI tick. The whole + * MIDI playback is timed in terms of this value.. there are no forced + * delays or anything. It just produces enough samples for each tick, and + * the playback of these samples is what makes the timings right. + * + * This seems to work quite well. + */ - outputBuffer[outputBufferPosition]=outputSampleTwo&0XFF; // Low byte first - outputBufferPosition++; - outputBuffer[outputBufferPosition]=outputSampleTwo>>8; //High byte second - outputBufferPosition++; + printf("\nOkay, starting sequencing"); + bpm=mf->div*1000000/tempo; + numberOfSamples=SAMPLE_RATE/bpm; - /* - * As soon as we produce 2000 bytes of sound, - * write it to the sound card. Why 2000? I have - * no idea. It's 1 AM and I am dead tired. - */ - if(outputBufferPosition>=2000) - { - rb->write(fd, outputBuffer, 2000); - outputBufferPosition=0; - } - } - } + tick(mf); - printf("\n"); + synthbuf(); + rb->pcm_play_data(&get_more, NULL, 0); -#if !defined(LOCAL_DSP) + button=rb->button_status(); -/* again, xxx2wav stuff, removed for now */ + while(!quit){ + synthbuf(); + rb->yield(); + if(rb->button_status()!=button) quit=1; + } - /* close_wav(&file_info); */ -#else - rb->close(fd); -#endif - return 0; + return 0; } Index: apps/plugins/midi/midifile.c =================================================================== RCS file: /cvsroot/rockbox/apps/plugins/midi/midifile.c,v retrieving revision 1.3 diff -u -r1.3 midifile.c --- apps/plugins/midi/midifile.c 20 Apr 2005 21:07:13 -0000 1.3 +++ apps/plugins/midi/midifile.c 10 Feb 2006 00:19:40 -0000 @@ -116,7 +116,6 @@ ev->delta = readVarData(file); - int t=readChar(file); if((t&0x80) == 0x80) /* if not a running status event */ Index: apps/plugins/midi/midiutil.c =================================================================== RCS file: /cvsroot/rockbox/apps/plugins/midi/midiutil.c,v retrieving revision 1.4 diff -u -r1.4 midiutil.c --- apps/plugins/midi/midiutil.c 20 Apr 2005 21:07:13 -0000 1.4 +++ apps/plugins/midi/midiutil.c 10 Feb 2006 00:19:40 -0000 @@ -63,11 +63,11 @@ extern struct plugin_api * rb; -int chVol[16] IDATA_ATTR; /* Channel volume */ -int chPanLeft[16] IDATA_ATTR; /* Channel panning */ -int chPanRight[16] IDATA_ATTR; -int chPat[16]; /* Channel patch */ -int chPW[16]; /* Channel pitch wheel, MSB only */ +int chVol[16] IBSS_ATTR; /* Channel volume */ +int chPanLeft[16] IBSS_ATTR; /* Channel panning */ +int chPanRight[16] IBSS_ATTR; +int chPat[16] IBSS_ATTR; /* Channel patch */ +int chPW[16] IBSS_ATTR; /* Channel pitch wheel, MSB only */ struct GPatch * gusload(char *); @@ -128,9 +128,7 @@ int curPoint; }; -struct SynthObject voices[MAX_VOICES] IDATA_ATTR; - - +struct SynthObject voices[MAX_VOICES] IBSS_ATTR; void sendEvent(struct Event * ev); int tick(struct MIDIfile * mf); @@ -226,7 +224,25 @@ return size+1 == rb->lseek(fd, 0, SEEK_CUR); } -void printf(char *fmt, ...) {fmt=fmt; } +int printf(const char *fmt, ...) +{ + static int p_xtpt; + char p_buf[50]; + bool ok; + va_list ap; + + va_start(ap, fmt); + ok = rb->vsnprintf(p_buf,sizeof(p_buf), fmt, ap); + va_end(ap); + + rb->lcd_putsxy(1,p_xtpt, (unsigned char *)p_buf); + rb->lcd_update(); + + p_xtpt+=8; + if(p_xtpt>160) {p_xtpt=0; rb->lcd_clear_display();} + + return 1; +} void exit(int code) { Index: apps/plugins/midi/sequencer.c =================================================================== RCS file: /cvsroot/rockbox/apps/plugins/midi/sequencer.c,v retrieving revision 1.6 diff -u -r1.6 sequencer.c --- apps/plugins/midi/sequencer.c 7 Aug 2005 23:39:23 -0000 1.6 +++ apps/plugins/midi/sequencer.c 10 Feb 2006 00:19:41 -0000 @@ -22,22 +22,22 @@ long tempo=375000; -void setVol(int ch, int vol) +static inline void setVol(int ch, int vol) { - printf("\nvolume[%d] %d ==> %d", ch, chVol[ch], vol); +// printf("\nvolume[%d] %d ==> %d", ch, chVol[ch], vol); chVol[ch]=vol; } -void setPan(int ch, int pan) +static inline void setPan(int ch, int pan) { - printf("\npanning[%d] %d ==> %d", ch, chPanRight[ch], pan); +// printf("\npanning[%d] %d ==> %d", ch, chPanRight[ch], pan); chPanLeft[ch]=128-pan; chPanRight[ch]=pan; } -void setPatch(int ch, int pat) +inline void setPatch(int ch, int pat) { chPat[ch]=pat; } @@ -62,7 +62,7 @@ 73297,73429 }; */ -long pitchTbl[]={ +long pitchTbl[] ICONST_ATTR ={ 58386,58412,58439,58465,58491,58518,58544,58571,58597,58624,58650,58676,58703,58729,58756,58782,58809,58836,58862,58889,58915,58942,58968,58995,59022,59048,59075,59102,59128,59155,59182,59208,59235,59262,59289,59315,59342,59369,59396,59423,59449,59476,59503,59530,59557,59584,59611,59638,59664,59691,59718,59745,59772,59799,59826,59853,59880,59907,59934,59961,59988,60015,60043,60070,60097,60124,60151,60178,60205,60233,60260,60287,60314,60341,60369,60396,60423,60450,60478,60505,60532,60560,60587,60614,60642,60669,60696,60724,60751,60779,60806,60833,60861,60888,60916,60943,60971,60998,61026,61054,61081,61109,61136,61164,61191,61219,61247,61274,61302,61330,61357,61385,61413,61440,61468,61496,61524,61551,61579,61607,61635,61663,61690,61718,61746,61774,61802,61830,61858,61886,61914,61942,61970,61997,62025,62053,62081,62109,62138,62166,62194,62222,62250,62278,62306,62334,62362,62390,62419,62447,62475,62503,62531,62560,62588,62616,62644,62673,62701,62729,62757,62786,62814,62843,62871,62899,62928,62956,62984,63013,63041,63070,63098,63127,63155,63184,63212,63241,63269,63298,63326,63355,63384,63412,63441,63470,63498,63527,63555,63584,63613,63642,63670,63699,63728,63757,63785,63814,63843,63872,63901,63929,63958,63987,64016,64045,64074,64103,64132,64161,64190,64219,64248,64277,64306,64335,64364,64393,64422,64451,64480,64509,64538,64567,64596,64626,64655,64684,64713,64742,64772,64801,64830,64859,64889,64918,64947,64976,65006,65035,65065,65094,65123,65153,65182,65211,65241,65270,65300,65329,65359,65388,65418,65447,65477,65506,65536,65566,65595,65625,65654,65684,65714,65743,65773,65803,65832,65862,65892,65922,65951,65981,66011,66041,66071,66100,66130,66160,66190,66220,66250,66280,66309,66339,66369,66399,66429,66459,66489,66519,66549,66579,66609,66639,66670,66700,66730,66760,66790,66820,66850,66880,66911,66941,66971,67001,67032,67062,67092,67122,67153,67183,67213,67244,67274,67304,67335,67365,67395,67426,67456,67487,67517,67548,67578,67609,67639,67670,67700,67731,67761,67792,67823,67853,67884,67915,67945,67976,68007,68037,68068,68099,68129,68160,68191,68222,68252,68283,68314,68345,68376,68407,68438,68468,68499,68530,68561,68592,68623,68654,68685,68716,68747,68778,68809,68840,68871,68902,68933,68965,68996,69027,69058,69089,69120,69152,69183,69214,69245,69276,69308,69339,69370,69402,69433,69464,69496,69527,69558,69590,69621,69653,69684,69716,69747,69778,69810,69841,69873,69905,69936,69968,69999,70031,70062,70094,70126,70157,70189,70221,70252,70284,70316,70348,70379,70411,70443,70475,70507,70538,70570,70602,70634,70666,70698,70730,70762,70793,70825,70857,70889,70921,70953,70985,71017,71049,71082,71114,71146,71178,71210,71242,71274,71306,71339,71371,71403,71435,71468,71500,71532,71564,71597,71629,71661,71694,71726,71758,71791,71823,71856,71888,71920,71953,71985,72018,72050,72083,72115,72148,72181,72213,72246,72278,72311,72344,72376,72409,72442,72474,72507,72540,72573,72605,72638,72671,72704,72736,72769,72802,72835,72868,72901,72934,72967,72999,73032,73065,73098,73131,73164,73197,73230,73264,73297,73330,73363,73396,73429,73462,73495,73528 }; @@ -75,9 +75,9 @@ so->delta = (so->delta * pitchTbl[chPW[ch]])>> 16; } -void setPW(int ch, int msb, int lsb) +inline void setPW(int ch, int msb, int lsb) { - printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb); +// printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb); chPW[ch] = msb<<2|lsb>>5; int a=0; @@ -163,8 +163,8 @@ voices[a].wf=wf; voices[a].delta = (((gustable[note]<<10) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE); if(wf->mode & 28) - printf("\nWoah, a drum patch has a loop. Stripping the loop..."); - wf->mode = wf->mode & (255-28); + // printf("\nWoah, a drum patch has a loop. Stripping the loop..."); + wf->mode = wf->mode & (255-28); /* Turn it on */ voices[a].isUsed=1; @@ -244,10 +244,6 @@ } } - - - - int tick(struct MIDIfile * mf) { if(mf==NULL) Index: apps/plugins/midi/synth.c =================================================================== RCS file: /cvsroot/rockbox/apps/plugins/midi/synth.c,v retrieving revision 1.7 diff -u -r1.7 synth.c --- apps/plugins/midi/synth.c 7 Aug 2005 22:20:40 -0000 1.7 +++ apps/plugins/midi/synth.c 10 Feb 2006 00:19:41 -0000 @@ -64,10 +64,10 @@ for(a=0; a<16; a++) { chVol[a]=100; /* Default, not quite full blast.. */ - chPanLeft[a]=64; /* Center */ + chPanLeft[a]=64; /* Center */ chPanRight[a]=64; /* Center */ chPat[a]=0; /* Ac Gr Piano */ - chPW[a]=256; /* .. not .. bent ? */ + chPW[a]=256; /* .. not .. bent ? */ } for(a=0; a<128; a++) { @@ -180,32 +180,27 @@ return 0; } +int currentVoice IBSS_ATTR; +struct SynthObject * so; +struct GWaveform * wf; +int s IBSS_ATTR; +short s1 IBSS_ATTR; +short s2 IBSS_ATTR; +short sample IBSS_ATTR; /* For synthSample */ +unsigned int cpShifted IBSS_ATTR; +unsigned char b1 IBSS_ATTR; +unsigned char b2 IBSS_ATTR; -int currentVoice IDATA_ATTR; -struct SynthObject * so IDATA_ATTR; -struct GWaveform * wf IDATA_ATTR; -int s IDATA_ATTR; -short s1 IDATA_ATTR; -short s2 IDATA_ATTR; -short sample IDATA_ATTR; /* For synthSample */ -unsigned int cpShifted IDATA_ATTR; -unsigned char b1 IDATA_ATTR; -unsigned char b2 IDATA_ATTR; - - -inline int getSample(int s) +inline short getSample(int s) { /* Sign conversion moved to guspat.c */ /* 8bit conversion NOT YET IMPLEMENTED in guspat.c */ return ((short *) wf->data)[s]; } - - - -inline void setPoint(struct SynthObject * so, int pt) +void setPoint(struct SynthObject * so, int pt) { if(so->ch==9) /* Drums, no ADSR */ { @@ -270,7 +265,7 @@ } -inline signed short int synthVoice(void) +signed short int synthVoice(void) { so = &voices[currentVoice]; wf = so->wf; @@ -288,9 +283,9 @@ stopVoice(so); } - s2 = getSample((cpShifted)+1); + s2 = getSample((cpShifted)+1); - /* LOOP_REVERSE|LOOP_PINGPONG = 24 */ + /* LOOP_REVERSE|LOOP_PINGPONG = 24 */ if((wf->mode & (24)) && so->loopState == STATE_LOOPING && (cpShifted <= (wf->startLoop))) { if(wf->mode & LOOP_REVERSE) @@ -378,18 +373,17 @@ return s*((signed short int)so->vol*(signed short int)chVol[so->ch])>>14; } - -inline void synthSample(int * mixL, int * mixR) +// I converted this to handle the mixing all in one int. Seems faster. +inline void synthSample(unsigned int * mixLR) { - *mixL = 0; - *mixR = 0; + *mixLR = 0; for(currentVoice=0; currentVoice>7; - *mixR += (sample*chPanRight[voices[currentVoice].ch])>>7; + *mixLR += ((sample*chPanLeft[voices[currentVoice].ch])>>7) << 16; + *mixLR += (sample*chPanRight[voices[currentVoice].ch])>>7; } }