/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * * Copyright (C) 2005 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. * ****************************************************************************/ #define SAMPLE_RATE 48000 #define MAX_VOICES 100 /* This is for writing to the DSP directly from the Simulator #include #include #include #include */ #include "../../plugin.h" #include "midi/midiutil.c" #include "midi/guspat.h" #include "midi/guspat.c" #include "midi/sequencer.c" #include "midi/midifile.c" #include "midi/synth.c" //#include "lib/xxx2wav.h" int fd=-1; //File descriptor, for opening /dev/dsp and writing to it extern long tempo; //The sequencer keeps track of this struct plugin_api * rb; enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { TEST_PLUGIN_API(api); (void)parameter; rb = api; rb->splash(HZ*2, true, "MIDI"); midimain(); rb->splash(HZ*2, true, "FINISHED PLAYING"); return PLUGIN_OK; } int midimain() { rb->splash(HZ*2, true, "OPENED DSP"); fd=rb->open("/dsp.raw", O_WRONLY|O_CREAT); /* 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; */ printf("\nHello.\n"); // initSound(); //Open the computer's sound card int a=0; rb->splash(HZ*2, true, "LOADING MIDI"); struct MIDIfile * mf = loadFile("/test.mid"); rb->splash(HZ*2, true, "LOADED MIDI"); long bpm, nsmp, l; int bp=0; rb->splash(HZ*2, true, "LOADING PATCHES"); initSynth(mf, "/iriver2.cfg", "/drums.cfg"); //Initialize the MIDI syntehsizer rb->splash(HZ*2, true, "START PLAYING"); signed char buf[3000]; // 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. printf("\nOkay, starting sequencing"); //Tick() will return 0 if there are no more events left to play while(tick(mf)) { //Some annoying math to compute the number of samples //to syntehsize per each MIDI tick. bpm=mf->div*1000000/tempo; nsmp=SAMPLE_RATE/bpm; //Yes we need to do this math each time because the tempo //could have changed. // On second thought, this can be moved to the event that //recalculates the tempo, to save a little bit of CPU time. for(l=0; l>8; //High byte second bp++; buf[bp]=s2&0XFF; // Low byte first bp++; buf[bp]=s2>>8; //High byte second bp++; //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(bp>=2000) { rb->write(fd, buf, 2000); bp=0; } } } // unloadFile(mf); printf("\n"); rb->close(fd); return 0; }