______                     
                 /      |       ________     
                /       |____  /        \    
               /        |    \/   _      \   
               \       ___       /_\      \  
                \      \_/          .      \ 
                 \          /\_____/       / 
                  \________/      |       /  
                                  |______/   


Lullaby_in.c Part 3

20140919

Edit: replaced int(reg) with int(round(reg)). Not that it should have any noticeable sound differences, but it’s a bit more accurate.

Resuming.

In order to play a scale, I needed notes. But the GBA sound chip has no clue what a note is, it just want to be fed with the right register value to control the frequency of a specific channel. The register value can be calculated with 2048 – 4194304 / (32 * frequency), then converted to hexadecimal. So far I calculated this manually to get a few octaves of C and G notes.

In order to play several scales, I need now much more notes and I’m not going to calculate them all by hand, nor make the poor GBA CPU do that in real-time every time a note needs to be played.

So it’s time for some high-level laziness:

#!/usr/bin/env python

notes = [["C",65.406],["CH",69.296],["D",73.416],["DH",77.782],
["E",82.407],["F",87.307],["FH",92.499],["G",97.999],
["GH",103.826],["A",110],["AH",116.541],["B",123.471]]

def makeHex(freq):
    reg = 2048-(4194304/(32*freq))
    regHex = "{0:#0{1}x}".format(int(round(reg)),6)
    return regHex

def makeArray(note,freq):
    i = 0
    array = "int "+note+" [6] = {"
    while i < 6:
        array += makeHex(freq*pow(2,i))+","
        i += 1
    return array[:-1]+"};"

for note in notes:
    print makeArray(note[0],note[1])

This thing will produce the following that I can then nicely paste in my C code, Ô pythonesque joy and wonders:

int C [6] = {0x002c,0x0416,0x060b,0x0706,0x0783,0x07c1};
int CH [6] = {0x009d,0x044e,0x0627,0x0714,0x078a,0x07c5};
int D [6] = {0x0107,0x0483,0x0642,0x0721,0x0790,0x07c8};
int DH [6] = {0x016b,0x04b5,0x065b,0x072d,0x0797,0x07cb};
int E [6] = {0x01c9,0x04e5,0x0672,0x0739,0x079d,0x07ce};
int F [6] = {0x0223,0x0511,0x0689,0x0744,0x07a2,0x07d1};
int FH [6] = {0x0277,0x053b,0x069e,0x074f,0x07a7,0x07d4};
int G [6] = {0x02c7,0x0563,0x06b2,0x0759,0x07ac,0x07d6};
int GH [6] = {0x0312,0x0589,0x06c4,0x0762,0x07b1,0x07d9};
int A [6] = {0x0359,0x05ad,0x06d7,0x076c,0x07b6,0x07db};
int AH [6] = {0x039b,0x05ce,0x06e7,0x0773,0x07ba,0x07dd};
int B [6] = {0x03da,0x05ed,0x06f7,0x077b,0x07be,0x07df};

Then I guess I can find a way to assign the tonic and dominant notes on the fly depending on the selected scale… Mmmm… we’ll see about that in the next part I suppose.



Leave a Reply

Your email address will not be published. Required fields are marked *