[136] | 1 | #include <SquawkSD.h>
|
---|
| 2 |
|
---|
| 3 | SquawkSynthSD SquawkSD;
|
---|
| 4 |
|
---|
| 5 | class StreamFile : public SquawkStream {
|
---|
| 6 | private:
|
---|
| 7 | Fat16 f;
|
---|
| 8 | public:
|
---|
| 9 | StreamFile(Fat16 file = Fat16()) { f = file; }
|
---|
| 10 | uint8_t read() { return f.read(); }
|
---|
| 11 | void seek(size_t offset) { f.seekSet(offset); }
|
---|
| 12 | };
|
---|
| 13 |
|
---|
| 14 | static StreamFile file;
|
---|
| 15 |
|
---|
| 16 | extern const uint16_t period_tbl[84] PROGMEM;
|
---|
| 17 |
|
---|
| 18 | void SquawkSynthSD::play(Fat16 melody) {
|
---|
| 19 | SquawkSynth::pause();
|
---|
| 20 | file = StreamFile(melody);
|
---|
| 21 | SquawkSynth::play(&file);
|
---|
| 22 | }
|
---|
| 23 |
|
---|
| 24 | /*
|
---|
| 25 | void SquawkSynthSD::convert(Fat16 in, Fat16 out) {
|
---|
| 26 | unsigned int n;
|
---|
| 27 | uint8_t patterns = 0, order_count;
|
---|
| 28 | unsigned int ptn, row, chn;
|
---|
| 29 | uint8_t temp;
|
---|
| 30 |
|
---|
| 31 | uint8_t fxc[4], fxp[4], note[4], sample[4];
|
---|
| 32 | uint16_t period;
|
---|
| 33 |
|
---|
| 34 | out.write('S'); // ID
|
---|
| 35 | out.write('Q');
|
---|
| 36 | out.write('M');
|
---|
| 37 | out.write('1');
|
---|
| 38 | out.write((uint8_t)0); // No meta data
|
---|
| 39 | out.write((uint8_t)0);
|
---|
| 40 |
|
---|
| 41 | // Write order list, count patterns
|
---|
| 42 | in.seek(0x3B6);
|
---|
| 43 | order_count = in.read();
|
---|
| 44 | out.write(order_count);
|
---|
| 45 | in.seek(0x3B8);
|
---|
| 46 | for(n = 0; n < order_count; n++) {
|
---|
| 47 | temp = in.read();
|
---|
| 48 | if(temp >= patterns) patterns = temp + 1;
|
---|
| 49 | out.write(temp);
|
---|
| 50 | }
|
---|
| 51 |
|
---|
| 52 | // Write patterns
|
---|
| 53 | in.seek(0x43C);
|
---|
| 54 | for(ptn = 0; ptn < patterns; ptn++) {
|
---|
| 55 | for(row = 0; row < 64; row++) {
|
---|
| 56 | for(chn = 0; chn < 4; chn++) {
|
---|
| 57 |
|
---|
| 58 | // Basic extraction
|
---|
| 59 | temp = in.read(); // sample.msb and period.msb
|
---|
| 60 | period = (temp & 0x0F) << 8;
|
---|
| 61 | sample[chn] = temp & 0xF0;
|
---|
| 62 | period |= in.read(); // period.lsb
|
---|
| 63 | temp = in.read(); // sample.lsb and effect
|
---|
| 64 | sample[chn] |= temp >> 4;
|
---|
| 65 | fxc[chn] = (temp & 0x0F) << 4;
|
---|
| 66 | fxp[chn] = in.read(); // parameters
|
---|
| 67 | if(fxc[chn] == 0xE0) {
|
---|
| 68 | fxc[chn] |= fxp[chn] >> 4; // extended parameters
|
---|
| 69 | fxp[chn] &= 0x0F;
|
---|
| 70 | }
|
---|
| 71 |
|
---|
| 72 | #define DIF(A, B) ((A) > (B) ? ((int32_t)(A) - (int32_t)(B)) : ((int32_t)(B) - (int32_t)(A)))
|
---|
| 73 | // Find closest matching period
|
---|
| 74 | if(period == 0) {
|
---|
| 75 | note[chn] = 0x7F;
|
---|
| 76 | } else {
|
---|
| 77 | int16_t best = DIF(period, pgm_read_word(&period_tbl[0]));
|
---|
| 78 | note[chn] = 0;
|
---|
| 79 | for(n = 0; n < sizeof(period_tbl) / sizeof(uint16_t); n++) {
|
---|
| 80 | if(DIF(period, pgm_read_word(&period_tbl[n])) < best) {
|
---|
| 81 | note[chn] = n;
|
---|
| 82 | best = DIF(period, pgm_read_word(&period_tbl[n]));
|
---|
| 83 | }
|
---|
| 84 | }
|
---|
| 85 | }
|
---|
| 86 |
|
---|
| 87 | // Crunch volume/decimal commands
|
---|
| 88 | if(fxc[chn] == 0x50 || fxc[chn] == 0x60 || fxc[chn] == 0xA0) {
|
---|
| 89 | fxp[chn] = (fxp[chn] >> 1) & 0x77;
|
---|
| 90 | } else if(fxc[chn] == 0x70) {
|
---|
| 91 | fxp[chn] = (fxp[chn] & 0xF0) | ((fxp[chn] & 0x0F) >> 1);
|
---|
| 92 | } else if(fxc[chn] == 0xC0 || fxc[chn] == 0xEA || fxc[chn] == 0xEB) {
|
---|
| 93 | fxp[chn] >>= 1;
|
---|
| 94 | } else if(fxc[chn] == 0xD0) {
|
---|
| 95 | fxp[chn] = ((fxp[chn] >> 4) * 10) | (fxp[chn] & 0x0F);
|
---|
| 96 | }
|
---|
| 97 |
|
---|
| 98 | // Re-nibblify - it's a word!
|
---|
| 99 | if(chn != 3) {
|
---|
| 100 | if((fxc[chn] & 0xF0) == 0xE0) fxp[chn] |= fxc[chn] << 4;
|
---|
| 101 | fxc[chn] >>= 4;
|
---|
| 102 | }
|
---|
| 103 |
|
---|
| 104 | }
|
---|
| 105 |
|
---|
| 106 | // Ghetto crunch the last channel to save a byte
|
---|
| 107 | switch(fxc[3]) {
|
---|
| 108 | case 0x50: case 0x60: case 0xA0:
|
---|
| 109 | fxc[3] = 0x1;
|
---|
| 110 | if((fxp[3] >> 4) >= (fxp[3] & 0x0F)) {
|
---|
| 111 | fxp[3] = 0x80 + ((fxp[3] >> 4) - (fxp[3] & 0x0F));
|
---|
| 112 | } else {
|
---|
| 113 | fxp[3] = ((fxp[3] & 0x0F) - (fxp[3] >> 4));
|
---|
| 114 | }
|
---|
| 115 | break;
|
---|
| 116 | case 0x70:
|
---|
| 117 | fxc[3] = (fxp[3] & 0x4) ? 0x3 : 0x2;
|
---|
| 118 | fxp[3] = (fxp[3] >> 4) | ((fxp[3] & 0x03) << 4);
|
---|
| 119 | break;
|
---|
| 120 | case 0xC0:
|
---|
| 121 | fxc[3] = 0x4;
|
---|
| 122 | fxp[3] &= 0x1F;
|
---|
| 123 | break;
|
---|
| 124 | case 0xB0:
|
---|
| 125 | fxc[3] = 0x5;
|
---|
| 126 | fxp[3] &= 0x1F;
|
---|
| 127 | break;
|
---|
| 128 | case 0xD0:
|
---|
| 129 | fxc[3] = 0x6;
|
---|
| 130 | if(fxp[3] > 63) fxp[3] = 0;
|
---|
| 131 | break;
|
---|
| 132 | case 0xF0:
|
---|
| 133 | if(fxp[3] > 0x20) {
|
---|
| 134 | fxc[3] = 0x0;
|
---|
| 135 | fxp[3] = 0x00;
|
---|
| 136 | } else {
|
---|
| 137 | fxc[3] = 0x7;
|
---|
| 138 | }
|
---|
| 139 | break;
|
---|
| 140 | case 0xE7:
|
---|
| 141 | fxc[3] = 0x8;
|
---|
| 142 | break;
|
---|
| 143 | case 0xE9:
|
---|
| 144 | fxc[3] = 0x9;
|
---|
| 145 | break;
|
---|
| 146 | case 0xEA:
|
---|
| 147 | fxc[3] = 0xA;
|
---|
| 148 | fxp[3] |= 0x08;
|
---|
| 149 | break;
|
---|
| 150 | case 0xEB:
|
---|
| 151 | fxc[3] = 0xA;
|
---|
| 152 | break;
|
---|
| 153 | case 0xEC:
|
---|
| 154 | fxc[3] = 0xB;
|
---|
| 155 | break;
|
---|
| 156 | case 0xED:
|
---|
| 157 | fxc[3] = 0xB;
|
---|
| 158 | fxp[3] |= 0x10;
|
---|
| 159 | break;
|
---|
| 160 | case 0xEE:
|
---|
| 161 | fxc[3] = 0xC;
|
---|
| 162 | break;
|
---|
| 163 | default:
|
---|
| 164 | fxc[3] = 0;
|
---|
| 165 | fxp[3] = 0;
|
---|
| 166 | }
|
---|
| 167 | if(note[3] != 0x7F) fxp[3] |= 0x80;
|
---|
| 168 | if(sample[3]) fxp[3] |= 0x40;
|
---|
| 169 |
|
---|
| 170 | // Write out
|
---|
| 171 | out.write((fxc[0]) | fxc[1] << 4);
|
---|
| 172 | out.write(fxp[0]);
|
---|
| 173 | out.write(fxp[1]);
|
---|
| 174 | out.write((fxc[2]) | fxc[3] << 4);
|
---|
| 175 | out.write(fxp[2]);
|
---|
| 176 | out.write(fxp[3]);
|
---|
| 177 | out.write(note[0] | (sample[0] == 0 ? 0x00 : 0x80));
|
---|
| 178 | out.write(note[1] | (sample[1] == 0 ? 0x00 : 0x80));
|
---|
| 179 | out.write(note[2] | (sample[2] == 0 ? 0x00 : 0x80));
|
---|
| 180 | }
|
---|
| 181 | }
|
---|
| 182 | }*/
|
---|