Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * |
| 9 | * Copyright (C) 2005 Stepan Moskovchenko |
| 10 | * |
| 11 | * All files in this archive are subject to the GNU General Public License. |
| 12 | * See the file COPYING in the source tree root for full license agreement. |
| 13 | * |
| 14 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 15 | * KIND, either express or implied. |
| 16 | * |
| 17 | ****************************************************************************/ |
| 18 | |
| 19 | |
| 20 | #define BYTE unsigned char |
| 21 | |
| 22 | //Data chunk ID types, returned by readID() |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 23 | #define ID_UNKNOWN -1 |
| 24 | #define ID_MTHD 1 |
| 25 | #define ID_MTRK 2 |
| 26 | #define ID_EOF 3 |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 27 | |
| 28 | //MIDI Commands |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 29 | #define MIDI_NOTE_OFF 128 |
| 30 | #define MIDI_NOTE_ON 144 |
| 31 | #define MIDI_AFTERTOUCH 160 |
| 32 | #define MIDI_CONTROL 176 |
| 33 | #define MIDI_PRGM 192 |
| 34 | #define MIDI_PITCHW 224 |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 35 | |
| 36 | |
| 37 | //MIDI Controllers |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 38 | #define CTRL_VOLUME 7 |
| 39 | #define CTRL_BALANCE 8 |
| 40 | #define CTRL_PANNING 10 |
| 41 | #define CHANNEL 1 |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 42 | |
Stepan Moskovchenko | 5811214 | 2005-04-15 20:27:04 +0000 | [diff] [blame] | 43 | //Most of these are deprecated.. rampdown is used, maybe one other one too |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 44 | #define STATE_ATTACK 1 |
| 45 | #define STATE_DECAY 2 |
| 46 | #define STATE_SUSTAIN 3 |
| 47 | #define STATE_RELEASE 4 |
| 48 | #define STATE_RAMPDOWN 5 |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 49 | |
Stepan Moskovchenko | 5811214 | 2005-04-15 20:27:04 +0000 | [diff] [blame] | 50 | //Loop states |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 51 | #define STATE_LOOPING 7 |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 52 | #define STATE_NONLOOPING 8 |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 53 | |
Stepan Moskovchenko | 5811214 | 2005-04-15 20:27:04 +0000 | [diff] [blame] | 54 | //Various bits in the GUS mode byte |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 55 | #define LOOP_ENABLED 4 |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 56 | #define LOOP_PINGPONG 8 |
| 57 | #define LOOP_REVERSE 16 |
| 58 | |
| 59 | #define LOOPDIR_FORWARD 0 |
| 60 | #define LOOPDIR_REVERSE 1 |
| 61 | |
| 62 | |
| 63 | extern struct plugin_api * rb; |
| 64 | |
| 65 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 66 | int chVol[16] IDATA_ATTR; /* Channel volume */ |
| 67 | int chPanLeft[16] IDATA_ATTR; /* Channel panning */ |
Stepan Moskovchenko | 1f5fb99 | 2005-04-19 15:57:07 +0000 | [diff] [blame] | 68 | int chPanRight[16] IDATA_ATTR; |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 69 | int chPat[16]; /* Channel patch */ |
| 70 | int chPW[16]; /* Channel pitch wheel, MSB only */ |
Stepan Moskovchenko | 1f5fb99 | 2005-04-19 15:57:07 +0000 | [diff] [blame] | 71 | |
| 72 | |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 73 | struct GPatch * gusload(char *); |
| 74 | struct GPatch * patchSet[128]; |
| 75 | struct GPatch * drumSet[128]; |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 76 | |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 77 | struct Event |
| 78 | { |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 79 | unsigned int delta; |
| 80 | unsigned char status, d1, d2; |
| 81 | unsigned int len; |
| 82 | unsigned char * evData; |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 83 | }; |
| 84 | |
| 85 | struct Track |
| 86 | { |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 87 | unsigned int size; |
| 88 | unsigned int numEvents; |
| 89 | unsigned int delta; /* For sequencing */ |
| 90 | unsigned int pos; /* For sequencing */ |
| 91 | void * dataBlock; |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 92 | }; |
| 93 | |
| 94 | |
| 95 | struct MIDIfile |
| 96 | { |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 97 | int Length; |
| 98 | unsigned short numTracks; |
| 99 | unsigned short div; /* Time division, X ticks per millisecond */ |
| 100 | struct Track * tracks[48]; |
| 101 | unsigned char patches[128]; |
| 102 | int numPatches; |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 103 | }; |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 104 | |
Stepan Moskovchenko | 1f5fb99 | 2005-04-19 15:57:07 +0000 | [diff] [blame] | 105 | /* |
| 106 | struct SynthObject |
| 107 | { |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 108 | struct GWaveform * wf; |
| 109 | unsigned int delta; |
| 110 | unsigned int decay; |
| 111 | unsigned int cp; |
| 112 | unsigned char state, loopState, loopDir; |
| 113 | unsigned char note, vol, ch, isUsed; |
| 114 | int curRate, curOffset, targetOffset; |
| 115 | unsigned int curPoint; |
Stepan Moskovchenko | 1f5fb99 | 2005-04-19 15:57:07 +0000 | [diff] [blame] | 116 | }; |
| 117 | */ |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 118 | |
Stepan Moskovchenko | 1f5fb99 | 2005-04-19 15:57:07 +0000 | [diff] [blame] | 119 | struct SynthObject |
| 120 | { |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 121 | struct GWaveform * wf; |
| 122 | int delta; |
| 123 | int decay; |
| 124 | unsigned int cp; |
| 125 | int state, loopState, loopDir; |
| 126 | int note, vol, ch, isUsed; |
| 127 | int curRate, curOffset, targetOffset; |
| 128 | int curPoint; |
Stepan Moskovchenko | 1f5fb99 | 2005-04-19 15:57:07 +0000 | [diff] [blame] | 129 | }; |
| 130 | |
| 131 | struct SynthObject voices[MAX_VOICES] IDATA_ATTR; |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 132 | |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 133 | |
Stepan Moskovchenko | 5811214 | 2005-04-15 20:27:04 +0000 | [diff] [blame] | 134 | |
| 135 | void sendEvent(struct Event * ev); |
| 136 | int tick(struct MIDIfile * mf); |
| 137 | inline void setPoint(struct SynthObject * so, int pt); |
| 138 | struct Event * getEvent(struct Track * tr, int evNum); |
| 139 | int readTwoBytes(int file); |
| 140 | int readFourBytes(int file); |
| 141 | int readVarData(int file); |
| 142 | int midimain(void * filename); |
| 143 | |
| 144 | |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 145 | void *alloc(int size) |
| 146 | { |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 147 | static char *offset = NULL; |
| 148 | static int totalSize = 0; |
| 149 | char *ret; |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 150 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 151 | int remainder = size % 4; |
Stepan Moskovchenko | 1f5fb99 | 2005-04-19 15:57:07 +0000 | [diff] [blame] | 152 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 153 | size = size + 4-remainder; |
Stepan Moskovchenko | 1f5fb99 | 2005-04-19 15:57:07 +0000 | [diff] [blame] | 154 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 155 | if (offset == NULL) |
| 156 | { |
| 157 | offset = rb->plugin_get_audio_buffer(&totalSize); |
| 158 | } |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 159 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 160 | if (size + 4 > totalSize) |
| 161 | { |
| 162 | return NULL; |
| 163 | } |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 164 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 165 | ret = offset + 4; |
| 166 | *((unsigned int *)offset) = size; |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 167 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 168 | offset += size + 4; |
| 169 | totalSize -= size + 4; |
| 170 | return ret; |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 171 | } |
Stepan Moskovchenko | 1f5fb99 | 2005-04-19 15:57:07 +0000 | [diff] [blame] | 172 | |
| 173 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 174 | /* Rick's code */ |
Stepan Moskovchenko | 5811214 | 2005-04-15 20:27:04 +0000 | [diff] [blame] | 175 | /* |
Stepan Moskovchenko | 1f5fb99 | 2005-04-19 15:57:07 +0000 | [diff] [blame] | 176 | void *alloc(int size) |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 177 | { |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 178 | static char *offset = NULL; |
| 179 | static int totalSize = 0; |
| 180 | char *ret; |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 181 | |
Stepan Moskovchenko | 1f5fb99 | 2005-04-19 15:57:07 +0000 | [diff] [blame] | 182 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 183 | if (offset == NULL) |
| 184 | { |
| 185 | offset = rb->plugin_get_audio_buffer(&totalSize); |
| 186 | } |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 187 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 188 | if (size + 4 > totalSize) |
| 189 | { |
| 190 | return NULL; |
| 191 | } |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 192 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 193 | ret = offset + 4; |
| 194 | *((unsigned int *)offset) = size; |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 195 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 196 | offset += size + 4; |
| 197 | totalSize -= size + 4; |
| 198 | return ret; |
Stepan Moskovchenko | 1f5fb99 | 2005-04-19 15:57:07 +0000 | [diff] [blame] | 199 | }*/ |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 200 | void * allocate(int size) |
| 201 | { |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 202 | return alloc(size); |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 203 | } |
| 204 | |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 205 | unsigned char readChar(int file) |
| 206 | { |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 207 | char buf[2]; |
| 208 | rb->read(file, &buf, 1); |
| 209 | return buf[0]; |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 210 | } |
| 211 | |
| 212 | unsigned char * readData(int file, int len) |
| 213 | { |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 214 | unsigned char * dat = allocate(len); |
| 215 | rb->read(file, dat, len); |
| 216 | return dat; |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 217 | } |
| 218 | |
| 219 | int eof(int fd) |
| 220 | { |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 221 | int curPos = rb->lseek(fd, 0, SEEK_CUR); |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 222 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 223 | int size = rb->lseek(fd, 0, SEEK_END); |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 224 | |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 225 | rb->lseek(fd, curPos, SEEK_SET); |
| 226 | return size+1 == rb->lseek(fd, 0, SEEK_CUR); |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 227 | } |
| 228 | |
Stepan Moskovchenko | 5811214 | 2005-04-15 20:27:04 +0000 | [diff] [blame] | 229 | void printf(char *fmt, ...) {fmt=fmt; } |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 230 | |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 231 | void exit(int code) |
| 232 | { |
Stepan Moskovchenko | 9ec1ff8 | 2005-04-20 21:07:13 +0000 | [diff] [blame^] | 233 | code = code; /* Stub function, kill warning for now */ |
Stepan Moskovchenko | 215e492 | 2005-04-15 06:08:55 +0000 | [diff] [blame] | 234 | } |