attempt at tracker style music

Dependencies:   PokittoLib

Committer:
spinal
Date:
Thu Feb 07 11:02:56 2019 +0000
Revision:
15:209481812170
Parent:
13:8ce494870ba6
ReDo of my music player, with a nice long song.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pokitto 0:2d2a3994d55d 1 #include "Pokitto.h"
spinal 13:8ce494870ba6 2 #include "HWSound.h"
spinal 13:8ce494870ba6 3 #include "snd.h"
spinal 13:8ce494870ba6 4 #include "tune.h"
spinal 15:209481812170 5 #include "gfx.h"
Pokitto 0:2d2a3994d55d 6
Pokitto 0:2d2a3994d55d 7 Pokitto::Core mygame;
spinal 12:37d999e445ad 8 Pokitto::Display d;
Pokitto 0:2d2a3994d55d 9
spinal 12:37d999e445ad 10
spinal 13:8ce494870ba6 11 typedef struct{
spinal 13:8ce494870ba6 12 bool playSample;
spinal 13:8ce494870ba6 13 int soundPoint;
spinal 13:8ce494870ba6 14 const uint8_t *currentSound;
spinal 15:209481812170 15 uint32_t currentSoundSize;
spinal 13:8ce494870ba6 16 int volume;
spinal 13:8ce494870ba6 17 int speed;
spinal 13:8ce494870ba6 18 int repeat;
spinal 13:8ce494870ba6 19 } sampletype;
spinal 13:8ce494870ba6 20
spinal 13:8ce494870ba6 21 sampletype snd[4]; // up to 4 sounds at once?
spinal 13:8ce494870ba6 22 int oldQuart;
spinal 13:8ce494870ba6 23
spinal 13:8ce494870ba6 24 uint32_t nextBufferIndexToFill = 0;
spinal 13:8ce494870ba6 25 uint32_t nextT = 0;
spinal 15:209481812170 26 uint32_t oldBufIndex=0;
spinal 13:8ce494870ba6 27
spinal 13:8ce494870ba6 28 int currentLine=0;
spinal 13:8ce494870ba6 29 int mytick=0;
spinal 15:209481812170 30 int pattern=0;
spinal 15:209481812170 31
spinal 15:209481812170 32 uint32_t myDelay;
spinal 15:209481812170 33 uint32_t tempTime;
spinal 15:209481812170 34 uint32_t sndTime;
spinal 15:209481812170 35
spinal 13:8ce494870ba6 36
spinal 15:209481812170 37 Ticker sounder;
spinal 15:209481812170 38 Ticker sounder1;
spinal 15:209481812170 39
spinal 15:209481812170 40 bool playMusic = 1;
spinal 15:209481812170 41
spinal 15:209481812170 42 const char *noteNames[] = {"--","C ","C#","D ","D#","E ","F ","F#","G ","G#","A ","A#","B "};
spinal 13:8ce494870ba6 43
spinal 15:209481812170 44 const int note_speed[]={
spinal 15:209481812170 45 16,17,18,19,20,21,23,24,25,27,29,30, // C, C#, D, D#, E, F, F#, G, G#, A, A#, B,
spinal 15:209481812170 46 32,34,36,38,40,43,45,48,51,54,57,60,
spinal 15:209481812170 47 64,68,72,76,81,85,91,96,102,108,114,121,
spinal 15:209481812170 48 128,136,144,152,161,171,181,192,203,215,228,242,
spinal 15:209481812170 49 256,271,287,304,323,342,362,384,406,431,456,483,
spinal 15:209481812170 50 512,542,575,609,645,683,724,767,813,861,912,967,
spinal 15:209481812170 51 1024,1085,1149,1218,1290,1367,1448,1534,1625,1722,1825,1933,
spinal 15:209481812170 52 2048,2170,2299,2435,2580,2734,2896,3068,3251,3444,3649,3866,
spinal 15:209481812170 53 4096,4339,4598,4871,5161,5467,5793,6137,6502,6889,7298,7732,};
spinal 11:a573cacdc078 54
spinal 15:209481812170 55 // new playsound function
spinal 15:209481812170 56 uint8_t playSound(int channel, const unsigned char *sound, int volume = 255, int speed=255, int repeat=0){
spinal 15:209481812170 57
spinal 15:209481812170 58 // get sound length
spinal 15:209481812170 59 int soundSize = 0;
spinal 15:209481812170 60 for(int t=0; t<4; t++){
spinal 15:209481812170 61 soundSize <<= 8;
spinal 15:209481812170 62 soundSize |= sound[t] & 0xFF;
spinal 13:8ce494870ba6 63 }
spinal 13:8ce494870ba6 64
spinal 15:209481812170 65 int sampleRate = 0;
spinal 15:209481812170 66 for(int t=0; t<2; t++){
spinal 15:209481812170 67 sampleRate <<= 8;
spinal 15:209481812170 68 sampleRate |= sound[t+4] & 0xFF;
spinal 13:8ce494870ba6 69 }
spinal 13:8ce494870ba6 70
spinal 15:209481812170 71 float spd = (POK_AUD_FREQ / (float)sampleRate);
spinal 15:209481812170 72
spinal 15:209481812170 73 snd[channel].currentSound = sound; // sound to play
spinal 15:209481812170 74 snd[channel].volume = volume; // volume
spinal 15:209481812170 75 snd[channel].speed = (speed/spd); // recalculated above
spinal 15:209481812170 76 snd[channel].currentSoundSize = soundSize; // length of sound array adjusted for speed change
spinal 15:209481812170 77 snd[channel].soundPoint = 0; // where the current sound is upto
spinal 15:209481812170 78 snd[channel].repeat = repeat; // repeat point
spinal 15:209481812170 79 snd[channel].playSample = 1; // trigger sample playing
spinal 15:209481812170 80
spinal 15:209481812170 81 return channel;
spinal 15:209481812170 82
spinal 13:8ce494870ba6 83 }
spinal 13:8ce494870ba6 84
spinal 13:8ce494870ba6 85
spinal 13:8ce494870ba6 86 uint8_t mixSound(int samplePos)
spinal 13:8ce494870ba6 87 {
spinal 13:8ce494870ba6 88 int temp = 0;
spinal 15:209481812170 89 signed int ss[4];
spinal 13:8ce494870ba6 90 for(int s=0; s<4; s++){
spinal 15:209481812170 91 int currentPos = (snd[s].soundPoint*snd[s].speed)>>8;
spinal 15:209481812170 92 ss[s] = snd[s].currentSound[currentPos] -127;
spinal 15:209481812170 93 ss[s] *= snd[s].volume;
spinal 15:209481812170 94 ss[s] /= 256;
spinal 15:209481812170 95 ss[s] *= snd[s].playSample; // will be 1 or 0, if not playing, will silence
spinal 15:209481812170 96 snd[s].soundPoint++;
spinal 15:209481812170 97 if( currentPos >= snd[s].currentSoundSize){
spinal 13:8ce494870ba6 98 if(snd[s].repeat){
spinal 13:8ce494870ba6 99 snd[s].soundPoint=0;
spinal 13:8ce494870ba6 100 }else{
spinal 13:8ce494870ba6 101 snd[s].playSample=0;
spinal 13:8ce494870ba6 102 snd[s].soundPoint=0;
spinal 13:8ce494870ba6 103 }
spinal 13:8ce494870ba6 104 }
spinal 15:209481812170 105 }
spinal 15:209481812170 106 temp = (ss[0] + ss[1] + ss[2] + ss[3])/4;
spinal 15:209481812170 107 return temp +127;
spinal 13:8ce494870ba6 108 }
spinal 13:8ce494870ba6 109
spinal 13:8ce494870ba6 110 void update_tune(){
spinal 12:37d999e445ad 111
spinal 15:209481812170 112 if(playMusic==1){
spinal 15:209481812170 113
spinal 15:209481812170 114 char pat = my_pattern[pattern];
spinal 15:209481812170 115
spinal 15:209481812170 116 int special = 0;
spinal 15:209481812170 117 for(int t=0; t<4; t++){
spinal 15:209481812170 118 int note = tune[pat][currentLine][t][0];
spinal 15:209481812170 119 int octave = tune[pat][currentLine][t][1]; // no longer used
spinal 15:209481812170 120 int volume = tune[pat][currentLine][t][2];// max volume from xm/mod was 64
spinal 15:209481812170 121 int instrument = tune[pat][currentLine][t][3];
spinal 15:209481812170 122 special = tune[pat][currentLine][t][4];
spinal 15:209481812170 123
spinal 15:209481812170 124 if(special == 22){
spinal 15:209481812170 125 // 22 = F in MOD format. 0.02 = 1 'tick'
spinal 15:209481812170 126 sounder.detach();
spinal 15:209481812170 127 sounder.attach(&update_tune, 0.02 * tune[pat][currentLine][t][5]); // speed of song
spinal 15:209481812170 128 }
spinal 15:209481812170 129
spinal 15:209481812170 130
spinal 15:209481812170 131 // if valid volume change, change it, if not use previous
spinal 15:209481812170 132 if(volume >=128){
spinal 15:209481812170 133 volume -=128;
spinal 15:209481812170 134 volume *= 4;
spinal 15:209481812170 135 }else{
spinal 15:209481812170 136 // don't change volume
spinal 15:209481812170 137 volume = snd[t].volume;
spinal 15:209481812170 138 }
spinal 15:209481812170 139
spinal 13:8ce494870ba6 140
spinal 15:209481812170 141 if(note > 0){
spinal 15:209481812170 142
spinal 15:209481812170 143 //int speed = (note_speed[note-1] << octave) /2;
spinal 15:209481812170 144 int speed = note_speed[note-1];
spinal 15:209481812170 145 for(int s=1; s<octave; s++){
spinal 15:209481812170 146 speed *=2;
spinal 15:209481812170 147 }
spinal 15:209481812170 148
spinal 15:209481812170 149 switch(instrument){
spinal 15:209481812170 150 case 1: playSound(t, s_01, volume, speed, sampleRepeat[instrument-1]); break;
spinal 15:209481812170 151 case 2: playSound(t, s_02, volume, speed, sampleRepeat[instrument-1]); break;
spinal 15:209481812170 152 case 3: playSound(t, s_03, volume, speed, sampleRepeat[instrument-1]); break;
spinal 15:209481812170 153 case 4: playSound(t, s_04, volume, speed, sampleRepeat[instrument-1]); break;
spinal 15:209481812170 154 case 5: playSound(t, s_05, volume, speed, sampleRepeat[instrument-1]); break;
spinal 15:209481812170 155 case 6: playSound(t, s_06, volume, speed, sampleRepeat[instrument-1]); break;
spinal 15:209481812170 156 case 7: playSound(t, s_07, volume, speed, sampleRepeat[instrument-1]); break;
spinal 15:209481812170 157 case 8: playSound(t, s_08, volume, speed, sampleRepeat[instrument-1]); break;
spinal 15:209481812170 158 case 9: playSound(t, s_09, volume, speed, sampleRepeat[instrument-1]); break;
spinal 15:209481812170 159 case 10: playSound(t, s_10, volume, speed, sampleRepeat[instrument-1]); break;
spinal 15:209481812170 160 case 11: playSound(t, s_11, volume, speed, sampleRepeat[instrument-1]); break;
spinal 15:209481812170 161 case 12: playSound(t, s_12, volume, speed, sampleRepeat[instrument-1]); break;
spinal 15:209481812170 162 case 13: playSound(t, s_13, volume, speed, sampleRepeat[instrument-1]); break;
spinal 15:209481812170 163 }
spinal 13:8ce494870ba6 164 }
spinal 15:209481812170 165
spinal 15:209481812170 166 snd[t].volume = volume;
spinal 15:209481812170 167
spinal 13:8ce494870ba6 168 }
spinal 15:209481812170 169
spinal 15:209481812170 170 // patterns are 64 lines long, or until special code 20.
spinal 15:209481812170 171 if(currentLine++==63 || special == 20){
spinal 15:209481812170 172 currentLine=0;
spinal 15:209481812170 173 if(++pattern>=sizeof(my_pattern))pattern=0;
spinal 15:209481812170 174 }
spinal 15:209481812170 175
spinal 15:209481812170 176 } // playMusic
spinal 15:209481812170 177 }
spinal 15:209481812170 178
spinal 15:209481812170 179
spinal 15:209481812170 180 int beatCounter;
spinal 15:209481812170 181 void update_buffer(){
spinal 15:209481812170 182
spinal 15:209481812170 183 int quart = soundbufindex / 512;
spinal 15:209481812170 184 int sndOffset[]={1024,1536,0,512};
spinal 15:209481812170 185
spinal 15:209481812170 186 if(oldQuart != quart){
spinal 15:209481812170 187 oldQuart = quart;
spinal 15:209481812170 188 for(int t=0; t<=SBUFSIZE/4;){
spinal 15:209481812170 189 uint8_t sample = mixSound(t);
spinal 15:209481812170 190 soundbuf[t+sndOffset[quart]] = sample;
spinal 15:209481812170 191 t++;
spinal 15:209481812170 192 }
spinal 15:209481812170 193 // if(beatCounter++==3){
spinal 15:209481812170 194 // beatCounter=0;
spinal 15:209481812170 195 // update_tune();
spinal 15:209481812170 196 // }
spinal 13:8ce494870ba6 197 }
spinal 15:209481812170 198
spinal 15:209481812170 199 }
spinal 15:209481812170 200
spinal 15:209481812170 201 // print text
spinal 15:209481812170 202 void print(uint16_t x, uint16_t y, const char* text){
spinal 15:209481812170 203 for(uint8_t t = 0; t < strlen(text); t++){
spinal 15:209481812170 204 uint8_t character = text[t];
spinal 15:209481812170 205 d.drawBitmap(x,y,tinyfont[character]);
spinal 15:209481812170 206 x += 4;
spinal 13:8ce494870ba6 207 }
spinal 13:8ce494870ba6 208 }
spinal 12:37d999e445ad 209
spinal 12:37d999e445ad 210
spinal 12:37d999e445ad 211 int main ()
spinal 12:37d999e445ad 212 {
spinal 12:37d999e445ad 213 mygame.begin();
spinal 15:209481812170 214 mygame.setFrameRate(255);
spinal 13:8ce494870ba6 215
spinal 13:8ce494870ba6 216 // Init audio stream.
spinal 13:8ce494870ba6 217 pokPlayStream(); // activate stream
spinal 13:8ce494870ba6 218 mygame.sound.ampEnable(true);
spinal 13:8ce494870ba6 219 mygame.sound.playMusicStream();
spinal 15:209481812170 220
spinal 15:209481812170 221 sounder.attach(&update_tune, 0.08); // speed of song
spinal 15:209481812170 222
spinal 15:209481812170 223
spinal 15:209481812170 224 d.load565Palette(&tinyfont_pal[0]);
spinal 11:a573cacdc078 225
spinal 12:37d999e445ad 226 while (mygame.isRunning())
spinal 12:37d999e445ad 227 {
spinal 15:209481812170 228 update_buffer();
spinal 15:209481812170 229
spinal 12:37d999e445ad 230 if (mygame.update())
spinal 12:37d999e445ad 231 {
spinal 12:37d999e445ad 232 d.color = 1;
spinal 15:209481812170 233 //d.printf("Pattern %d\n", pattern);
spinal 15:209481812170 234 //d.printf("Line %d\n", currentLine);
spinal 15:209481812170 235
spinal 15:209481812170 236 char pat = my_pattern[pattern];
spinal 15:209481812170 237
spinal 15:209481812170 238 char tempText[20];
spinal 15:209481812170 239
spinal 15:209481812170 240 int s1=currentLine-5;
spinal 15:209481812170 241 if(s1<0)s1=0;
spinal 15:209481812170 242 int s2 = currentLine+5;
spinal 15:209481812170 243 if(s2>63)s2=63;
spinal 15:209481812170 244
spinal 15:209481812170 245 sprintf(tempText,"T[%2d] P[%2d] L[%2d]",pattern,pat,currentLine);
spinal 15:209481812170 246 print(0,0,tempText);
spinal 15:209481812170 247
spinal 15:209481812170 248 int s;
spinal 15:209481812170 249 for(s=s1; s<s2; s++){
spinal 15:209481812170 250
spinal 15:209481812170 251 for(int t=0; t<4; t++){
spinal 15:209481812170 252 int note = tune[pat][s][t][0];
spinal 15:209481812170 253 int octave = tune[pat][s][t][1]; // no longer used
spinal 15:209481812170 254 int volume = tune[pat][s][t][2];// max volume from xm/mod was 64
spinal 15:209481812170 255 int instrument = tune[pat][s][t][3];
spinal 15:209481812170 256 int special = tune[pat][s][t][4];
spinal 15:209481812170 257
spinal 15:209481812170 258 if(volume >=128){
spinal 15:209481812170 259 volume -=128;
spinal 15:209481812170 260 }
spinal 15:209481812170 261
spinal 15:209481812170 262 int x1 = t*27;
spinal 15:209481812170 263 int y1 = ((8-currentLine)+s)*6;
spinal 15:209481812170 264
spinal 15:209481812170 265 if(s == currentLine || s == currentLine+1){
spinal 15:209481812170 266 d.setColor(5);
spinal 15:209481812170 267 d.drawLine(0, y1-1, 219, y1-1);
spinal 15:209481812170 268 }
spinal 15:209481812170 269
spinal 15:209481812170 270 print(x1,y1,noteNames[note]);
spinal 15:209481812170 271 sprintf(tempText,"%d",octave);
spinal 15:209481812170 272 print(x1 + 8,y1,tempText);
spinal 15:209481812170 273 sprintf(tempText,"%d",volume);
spinal 15:209481812170 274 print(x1 + 12,y1,tempText);
spinal 15:209481812170 275 sprintf(tempText,"%2d|",instrument);
spinal 15:209481812170 276 print(x1 + 16,y1,tempText);
spinal 15:209481812170 277
spinal 15:209481812170 278 }
spinal 15:209481812170 279 }
spinal 12:37d999e445ad 280
spinal 12:37d999e445ad 281 }
spinal 12:37d999e445ad 282 }
spinal 11:a573cacdc078 283 }
spinal 11:a573cacdc078 284
spinal 11:a573cacdc078 285