attempt at tracker style music

Dependencies:   PokittoLib

Committer:
spinal
Date:
Sun Nov 25 08:58:30 2018 +0000
Revision:
14:97a5deea7c94
Parent:
13:8ce494870ba6
A program to play music on pokitto

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"
Pokitto 0:2d2a3994d55d 5
Pokitto 0:2d2a3994d55d 6 Pokitto::Core mygame;
spinal 12:37d999e445ad 7 Pokitto::Display d;
Pokitto 0:2d2a3994d55d 8
spinal 13:8ce494870ba6 9 typedef struct{
spinal 14:97a5deea7c94 10 bool playSample; // should this sound be playing now?
spinal 14:97a5deea7c94 11 int soundPoint; // current position of sound
spinal 14:97a5deea7c94 12 const uint8_t *currentSound; // currend sound array playing
spinal 14:97a5deea7c94 13 uint32_t currentSoundSize; // length of current sound
spinal 14:97a5deea7c94 14 int volume; // volume of sound, best to be 63 or lower
spinal 14:97a5deea7c94 15 int speed; // how fast to play sound, 256 = 100%
spinal 14:97a5deea7c94 16 bool repeat; // 1 to repeat 0 not to
spinal 14:97a5deea7c94 17 int repeat_start; // start point of repeat, default should be 0
spinal 14:97a5deea7c94 18 int repeat_end; // end point of repeate, default should be currentSoundSize
spinal 14:97a5deea7c94 19 char lastSample; // previous sample played
spinal 13:8ce494870ba6 20 } sampletype;
spinal 13:8ce494870ba6 21
spinal 14:97a5deea7c94 22 sampletype snd[4]; // up to 4 sounds at once?
spinal 13:8ce494870ba6 23 int oldQuart;
spinal 13:8ce494870ba6 24
spinal 13:8ce494870ba6 25 int currentLine=0;
spinal 13:8ce494870ba6 26 int mytick=0;
spinal 14:97a5deea7c94 27 int pattern=0;
spinal 11:a573cacdc078 28
spinal 14:97a5deea7c94 29 Ticker soundPlay;
spinal 14:97a5deea7c94 30 Ticker musicTimer;
spinal 13:8ce494870ba6 31
spinal 14:97a5deea7c94 32 const float note_speed[]={
spinal 14:97a5deea7c94 33 // C, C#, D, D#, E, F, F#, G, G#, A, A#, B,
spinal 14:97a5deea7c94 34 16.00, 16.95, 17.96, 19.03, 20.16, 21.36, 22.62, 23.97, 25.40, 26.91, 28.51, 30.21,
spinal 14:97a5deea7c94 35 32.00, 33.90, 35.92, 38.05, 40.31, 42.71, 45.25, 47.95, 50.79, 53.82, 57.02, 60.41,
spinal 14:97a5deea7c94 36 64.00, 67.81, 71.84, 76.11, 80.64, 85.43, 90.51, 95.89, 101.60, 107.63, 114.03, 120.81,
spinal 14:97a5deea7c94 37 128.00, 135.61, 143.67, 152.21, 161.26, 170.85, 181.02, 191.78, 203.18, 215.27, 228.06, 241.63,
spinal 14:97a5deea7c94 38 256.00, 271.22, 287.34, 304.43, 322.54, 341.71, 362.03, 383.56, 406.36, 430.53, 456.13, 483.25,
spinal 14:97a5deea7c94 39 511.99, 542.44, 574.69, 608.86, 645.06, 683.43, 724.07, 767.12, 812.74, 861.06, 912.27, 966.51,
spinal 14:97a5deea7c94 40 1023.98, 1084.87, 1149.38, 1217.73, 1290.14, 1366.85, 1448.13, 1534.24, 1625.47, 1722.13, 1824.53, 1933.02,
spinal 14:97a5deea7c94 41 2047.96, 2169.74, 2298.77, 2435.46, 2580.27, 2733.71, 2896.26, 3068.48, 3250.94, 3444.25, 3649.06, 3866.05,
spinal 14:97a5deea7c94 42 4095.93, 4339.49, 4597.52, 4870.91, 5160.55, 5467.41, 5792.52, 6136.96, 6501.89, 6888.51, 7298.12, 7732.08
spinal 14:97a5deea7c94 43 };
spinal 13:8ce494870ba6 44
spinal 14:97a5deea7c94 45 uint8_t playSound(int channel, const unsigned char *sound, uint32_t soundSize, int volume = 255, int speed=255, int repeat=0){
spinal 14:97a5deea7c94 46
spinal 14:97a5deea7c94 47 // to resample current sample rate to 44100, cheap and probably wrong way
spinal 14:97a5deea7c94 48 float rate1 = 44100 / (float)sampleRates[channel];
spinal 14:97a5deea7c94 49 // speed = 256 / rate1; // playback speed is
spinal 14:97a5deea7c94 50 speed = speed / rate1; // playback speed is
spinal 14:97a5deea7c94 51
spinal 14:97a5deea7c94 52 snd[channel].currentSound = sound; // sound to play
spinal 14:97a5deea7c94 53 snd[channel].currentSoundSize = (soundSize<<8)/speed; // length of sound array adjusted for speed change
spinal 14:97a5deea7c94 54 snd[channel].volume = 63; // volume, best kept below 64 as louder will cause clipping when playing multiple samples
spinal 14:97a5deea7c94 55 snd[channel].speed = speed; // recalculated above
spinal 14:97a5deea7c94 56 snd[channel].repeat = repeat; // 1 to repead, 0 to not
spinal 14:97a5deea7c94 57 snd[channel].soundPoint = 0; // where the current sound is upto
spinal 14:97a5deea7c94 58 snd[channel].playSample = 1; // 1 to play this sound, 0 not to
spinal 12:37d999e445ad 59
spinal 13:8ce494870ba6 60 return channel;
spinal 13:8ce494870ba6 61 }
spinal 13:8ce494870ba6 62
spinal 13:8ce494870ba6 63 uint8_t mixSound(int samplePos)
spinal 13:8ce494870ba6 64 {
spinal 13:8ce494870ba6 65 int temp = 0;
spinal 13:8ce494870ba6 66 int ss[4];
spinal 12:37d999e445ad 67
spinal 13:8ce494870ba6 68 for(int s=0; s<4; s++){
spinal 14:97a5deea7c94 69
spinal 13:8ce494870ba6 70 ss[s] = (snd[s].currentSound[(snd[s].soundPoint*snd[s].speed)>>8]*snd[s].volume>>8) * snd[s].playSample;
spinal 14:97a5deea7c94 71
spinal 13:8ce494870ba6 72 ++snd[s].soundPoint;
spinal 13:8ce494870ba6 73 if(snd[s].soundPoint >= snd[s].currentSoundSize){
spinal 13:8ce494870ba6 74 if(snd[s].repeat){
spinal 13:8ce494870ba6 75 snd[s].soundPoint=0;
spinal 13:8ce494870ba6 76 }else{
spinal 13:8ce494870ba6 77 snd[s].playSample=0;
spinal 13:8ce494870ba6 78 snd[s].soundPoint=0;
spinal 13:8ce494870ba6 79 }
spinal 13:8ce494870ba6 80 }
spinal 13:8ce494870ba6 81 }
spinal 13:8ce494870ba6 82
spinal 14:97a5deea7c94 83 temp = (ss[0] + ss[1] + ss[2] + ss[3]) - ((ss[0] * ss[1] * ss[2] * ss[3])/256);
spinal 13:8ce494870ba6 84
spinal 13:8ce494870ba6 85 return temp;
spinal 13:8ce494870ba6 86 }
spinal 13:8ce494870ba6 87
spinal 14:97a5deea7c94 88
spinal 14:97a5deea7c94 89 void updateAudioBuffer(){
spinal 14:97a5deea7c94 90 // when updating the audio buffer, I split the buffer into 4 and fill
spinal 14:97a5deea7c94 91 // a part that isn't being played, so there are no sync issues
spinal 13:8ce494870ba6 92
spinal 14:97a5deea7c94 93 int quart = soundbufindex / 512;
spinal 14:97a5deea7c94 94 int sndOffset[]={1024,1536,0,512};
spinal 14:97a5deea7c94 95
spinal 14:97a5deea7c94 96 // only update if the current playback pointer is nowhere near where we want to fill
spinal 13:8ce494870ba6 97 if(oldQuart != quart){
spinal 13:8ce494870ba6 98 oldQuart = quart;
spinal 14:97a5deea7c94 99 for(int t=0; t<=SBUFSIZE/4;){
spinal 13:8ce494870ba6 100 uint8_t sample = mixSound(t);
spinal 13:8ce494870ba6 101 soundbuf[t+sndOffset[quart]] = sample;
spinal 13:8ce494870ba6 102 t++;
spinal 13:8ce494870ba6 103 }
spinal 13:8ce494870ba6 104 }
spinal 13:8ce494870ba6 105 }
spinal 13:8ce494870ba6 106
spinal 13:8ce494870ba6 107 void update_tune(){
spinal 12:37d999e445ad 108
spinal 14:97a5deea7c94 109 char pat = my_pattern[pattern];
spinal 14:97a5deea7c94 110
spinal 13:8ce494870ba6 111 for(int t=0; t<4; t++){
spinal 14:97a5deea7c94 112 int note = tune[pat][currentLine][t][0];
spinal 14:97a5deea7c94 113 int octave = tune[pat][currentLine][t][1]; // no longer used
spinal 14:97a5deea7c94 114 int volume = tune[pat][currentLine][t][2];// max volume from xm/mod was 64
spinal 14:97a5deea7c94 115 int instrument = tune[pat][currentLine][t][3];
spinal 13:8ce494870ba6 116
spinal 13:8ce494870ba6 117 if(note > 0){
spinal 14:97a5deea7c94 118 int speed = note_speed[(note-1)+12*octave];
spinal 14:97a5deea7c94 119
spinal 13:8ce494870ba6 120 switch(instrument){
spinal 13:8ce494870ba6 121 case 1:
spinal 13:8ce494870ba6 122 playSound(t, s_01, sizeof(s_01), volume, speed, sampleRepeat[0]);
spinal 13:8ce494870ba6 123 break;
spinal 13:8ce494870ba6 124 case 2:
spinal 13:8ce494870ba6 125 playSound(t, s_02, sizeof(s_02), volume, speed, sampleRepeat[1]);
spinal 13:8ce494870ba6 126 break;
spinal 13:8ce494870ba6 127 case 3:
spinal 13:8ce494870ba6 128 playSound(t, s_03, sizeof(s_03), volume, speed, sampleRepeat[2]);
spinal 13:8ce494870ba6 129 break;
spinal 13:8ce494870ba6 130 case 4:
spinal 13:8ce494870ba6 131 playSound(t, s_04, sizeof(s_04), volume, speed, sampleRepeat[3]);
spinal 13:8ce494870ba6 132 break;
spinal 13:8ce494870ba6 133 }
spinal 14:97a5deea7c94 134
spinal 13:8ce494870ba6 135 }
spinal 14:97a5deea7c94 136 if(volume >= 128){
spinal 14:97a5deea7c94 137 snd[t].volume = volume-128;
spinal 14:97a5deea7c94 138 }
spinal 13:8ce494870ba6 139 }
spinal 13:8ce494870ba6 140
spinal 14:97a5deea7c94 141 if(currentLine++==patternLength){
spinal 13:8ce494870ba6 142 currentLine=0;
spinal 14:97a5deea7c94 143 if(pattern++==sizeof(my_pattern))pattern=loopTo;
spinal 13:8ce494870ba6 144 }
spinal 13:8ce494870ba6 145 }
spinal 12:37d999e445ad 146
spinal 12:37d999e445ad 147
spinal 14:97a5deea7c94 148
spinal 14:97a5deea7c94 149
spinal 12:37d999e445ad 150 int main ()
spinal 12:37d999e445ad 151 {
spinal 12:37d999e445ad 152 mygame.begin();
spinal 13:8ce494870ba6 153 mygame.setFrameRate(255);
spinal 13:8ce494870ba6 154
spinal 13:8ce494870ba6 155 // Init audio stream.
spinal 13:8ce494870ba6 156 pokPlayStream(); // activate stream
spinal 13:8ce494870ba6 157 mygame.sound.ampEnable(true);
spinal 13:8ce494870ba6 158 mygame.sound.playMusicStream();
spinal 14:97a5deea7c94 159
spinal 14:97a5deea7c94 160 // check and update the sound buffer as often as we can
spinal 14:97a5deea7c94 161 soundPlay.attach(&updateAudioBuffer, 0.0001);
spinal 14:97a5deea7c94 162 musicTimer.attach(&update_tune, 0.055);
spinal 13:8ce494870ba6 163
spinal 14:97a5deea7c94 164 d.color = 1;
spinal 11:a573cacdc078 165
spinal 12:37d999e445ad 166 while (mygame.isRunning())
spinal 12:37d999e445ad 167 {
spinal 12:37d999e445ad 168 if (mygame.update())
spinal 12:37d999e445ad 169 {
spinal 14:97a5deea7c94 170
spinal 12:37d999e445ad 171 }
spinal 12:37d999e445ad 172 }
spinal 11:a573cacdc078 173 }
spinal 11:a573cacdc078 174
spinal 11:a573cacdc078 175