attempt at tracker style music

Dependencies:   PokittoLib

main.cpp

Committer:
spinal
Date:
2019-02-07
Revision:
15:209481812170
Parent:
13:8ce494870ba6

File content as of revision 15:209481812170:

#include "Pokitto.h"
#include "HWSound.h"
#include "snd.h"
#include "tune.h"
#include "gfx.h"

Pokitto::Core mygame;
Pokitto::Display d;


typedef struct{
    bool playSample;
    int soundPoint;
    const uint8_t *currentSound;
    uint32_t currentSoundSize;
    int volume;
    int speed;
    int repeat;
} sampletype;

sampletype snd[4]; // up to 4 sounds at once?
int oldQuart;

uint32_t nextBufferIndexToFill = 0;
uint32_t nextT = 0;
uint32_t oldBufIndex=0;

int currentLine=0;
int mytick=0;
int pattern=0; 

uint32_t myDelay;
uint32_t tempTime;
uint32_t sndTime;

 
Ticker sounder;
Ticker sounder1;

bool playMusic = 1;

const char *noteNames[] = {"--","C ","C#","D ","D#","E ","F ","F#","G ","G#","A ","A#","B "};

const int note_speed[]={
16,17,18,19,20,21,23,24,25,27,29,30, // C, C#, D, D#, E, F, F#, G, G#, A, A#, B,
32,34,36,38,40,43,45,48,51,54,57,60,
64,68,72,76,81,85,91,96,102,108,114,121,
128,136,144,152,161,171,181,192,203,215,228,242,
256,271,287,304,323,342,362,384,406,431,456,483,
512,542,575,609,645,683,724,767,813,861,912,967,
1024,1085,1149,1218,1290,1367,1448,1534,1625,1722,1825,1933,
2048,2170,2299,2435,2580,2734,2896,3068,3251,3444,3649,3866,
4096,4339,4598,4871,5161,5467,5793,6137,6502,6889,7298,7732,};

// new playsound function
uint8_t playSound(int channel, const unsigned char *sound, int volume = 255, int speed=255, int repeat=0){

    // get sound length
    int soundSize = 0;
    for(int t=0; t<4; t++){
        soundSize <<= 8;
        soundSize |= sound[t] & 0xFF;
    }

    int sampleRate = 0;
    for(int t=0; t<2; t++){
        sampleRate <<= 8;
        sampleRate |= sound[t+4] & 0xFF;
    }

    float spd = (POK_AUD_FREQ / (float)sampleRate);

    snd[channel].currentSound = sound;          // sound to play
    snd[channel].volume = volume;               // volume
    snd[channel].speed = (speed/spd);           // recalculated above
    snd[channel].currentSoundSize = soundSize;  // length of sound array adjusted for speed change
    snd[channel].soundPoint = 0;                // where the current sound is upto
    snd[channel].repeat = repeat;               // repeat point
    snd[channel].playSample = 1;                // trigger sample playing

    return channel;

}


uint8_t mixSound(int samplePos)
{
    int temp = 0;
    signed int ss[4];
    for(int s=0; s<4; s++){
        int currentPos = (snd[s].soundPoint*snd[s].speed)>>8;
        ss[s] = snd[s].currentSound[currentPos] -127;
        ss[s] *= snd[s].volume;
        ss[s] /= 256;
        ss[s] *= snd[s].playSample; // will be 1 or 0, if not playing, will silence
        snd[s].soundPoint++;
        if( currentPos >= snd[s].currentSoundSize){
            if(snd[s].repeat){
                snd[s].soundPoint=0;
            }else{
                snd[s].playSample=0;
                snd[s].soundPoint=0;
            }
        }
     }
    temp = (ss[0] + ss[1] + ss[2] + ss[3])/4;
    return temp +127;
}

void update_tune(){

    if(playMusic==1){

        char pat = my_pattern[pattern];
    
        int special = 0;
        for(int t=0; t<4; t++){
            int note =       tune[pat][currentLine][t][0];
            int octave =     tune[pat][currentLine][t][1]; // no longer used
            int volume =     tune[pat][currentLine][t][2];// max volume from xm/mod was 64
            int instrument = tune[pat][currentLine][t][3];
            special =    tune[pat][currentLine][t][4];

            if(special == 22){
                // 22 = F in MOD format. 0.02 = 1 'tick'
                sounder.detach();
                sounder.attach(&update_tune, 0.02 * tune[pat][currentLine][t][5]); // speed of song
            }


        // if valid volume change, change it, if not use previous
        if(volume >=128){
            volume -=128;
            volume *= 4;
        }else{
            // don't change volume
            volume = snd[t].volume;
        }

                        
            if(note > 0){
                
                //int speed = (note_speed[note-1] << octave) /2;
                int speed = note_speed[note-1];
                for(int s=1; s<octave; s++){
                    speed *=2;
                }
                            
                switch(instrument){
                    case 1: playSound(t, s_01, volume, speed, sampleRepeat[instrument-1]);  break;
                    case 2: playSound(t, s_02, volume, speed, sampleRepeat[instrument-1]);  break;
                    case 3: playSound(t, s_03, volume, speed, sampleRepeat[instrument-1]);  break;
                    case 4: playSound(t, s_04, volume, speed, sampleRepeat[instrument-1]);  break;
                    case 5: playSound(t, s_05, volume, speed, sampleRepeat[instrument-1]);  break;
                    case 6: playSound(t, s_06, volume, speed, sampleRepeat[instrument-1]);  break;
                    case 7: playSound(t, s_07, volume, speed, sampleRepeat[instrument-1]);  break;
                    case 8: playSound(t, s_08, volume, speed, sampleRepeat[instrument-1]);  break;
                    case 9: playSound(t, s_09, volume, speed, sampleRepeat[instrument-1]);  break;
                    case 10: playSound(t, s_10, volume, speed, sampleRepeat[instrument-1]);  break;
                    case 11: playSound(t, s_11, volume, speed, sampleRepeat[instrument-1]);  break;
                    case 12: playSound(t, s_12, volume, speed, sampleRepeat[instrument-1]);  break;
                    case 13: playSound(t, s_13, volume, speed, sampleRepeat[instrument-1]);  break;
                }
            }
                                
            snd[t].volume = volume;
                    
        }
     
        // patterns are 64 lines long, or until special code 20.
        if(currentLine++==63 || special == 20){
            currentLine=0;
            if(++pattern>=sizeof(my_pattern))pattern=0;
        }

    } // playMusic
}


int beatCounter;
void update_buffer(){

 int quart = soundbufindex / 512;
 int sndOffset[]={1024,1536,0,512};

    if(oldQuart != quart){
        oldQuart = quart;
        for(int t=0; t<=SBUFSIZE/4;){
            uint8_t sample = mixSound(t);
            soundbuf[t+sndOffset[quart]] = sample;
            t++;
        }
//        if(beatCounter++==3){
//            beatCounter=0;
//            update_tune();            
//        }
    }
    
}

// print text
void print(uint16_t x, uint16_t y, const char* text){
    for(uint8_t t = 0; t < strlen(text); t++){
        uint8_t character = text[t];
        d.drawBitmap(x,y,tinyfont[character]);
        x += 4;
    }
}


int main ()
{
    mygame.begin();
    mygame.setFrameRate(255);    

    // Init audio stream.
    pokPlayStream(); // activate stream
    mygame.sound.ampEnable(true);
    mygame.sound.playMusicStream();

    sounder.attach(&update_tune, 0.08); // speed of song


    d.load565Palette(&tinyfont_pal[0]);

    while (mygame.isRunning())
    {
        update_buffer();
        
        if (mygame.update())
        {
            d.color = 1;
            //d.printf("Pattern %d\n", pattern);
            //d.printf("Line %d\n", currentLine);

        char pat = my_pattern[pattern];
    
        char tempText[20];

        int s1=currentLine-5;
        if(s1<0)s1=0;
        int s2 = currentLine+5;
        if(s2>63)s2=63;

        sprintf(tempText,"T[%2d] P[%2d] L[%2d]",pattern,pat,currentLine);
        print(0,0,tempText);

        int s;
        for(s=s1; s<s2; s++){

            for(int t=0; t<4; t++){
                int note =       tune[pat][s][t][0];
                int octave =     tune[pat][s][t][1]; // no longer used
                int volume =     tune[pat][s][t][2];// max volume from xm/mod was 64
                int instrument = tune[pat][s][t][3];
                int special =    tune[pat][s][t][4];

                if(volume >=128){
                    volume -=128;
                }
            
                int x1 = t*27;
                int y1 = ((8-currentLine)+s)*6;

                if(s == currentLine || s == currentLine+1){
                    d.setColor(5);
                    d.drawLine(0, y1-1, 219, y1-1); 
                }
                
                print(x1,y1,noteNames[note]);
                sprintf(tempText,"%d",octave);
                print(x1 + 8,y1,tempText);
                sprintf(tempText,"%d",volume);
                print(x1 + 12,y1,tempText);
                sprintf(tempText,"%2d|",instrument);
                print(x1 + 16,y1,tempText);
                
            }
        }

        }
    }
}