Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Modlus operator for Float (or something). C programming.

Options
  • 21-11-2009 1:53pm
    #1
    Closed Accounts Posts: 6,408 ✭✭✭


    Hi there,
    Still a relative NOOB to this programming lark.

    Here's the deal,
    I'm writing a program to generate random musical tunes with a random number generator writing text files to an application called Csound. The program generates numbers from an array that corresponds to a musical scale.
    eg.
    major_scale[8]= {8.00, 8.02, 8.04, 8.05, 8.07, 8.09, 8.10, 9.00};

    the rest goes a bit like this...

    note=rand()%8;
    if (dursum==(len*sig)-sig) dur=sig;
    printf ("i1\t%d\t%d\t%d\t%.2f\n", start, dur, vol, (scale[note]));
    fprintf(fp, "i1\t%d\t%d\t%d\t%.2f\n", start, dur, vol, (scale[note] ));

    8.00 corresponds to middle C on the piano 8.02 is two semi tones above that going all the way up to 8.11 which is the note below C in the next octave 9.00.

    Hope yer with me so far...
    Here's my problem, I want to add a harmony to this melody, basically pick a
    third or fifth, which for C (8.00) would be 8.04 or 8.07. This is all well and fine until the harmonies go out of the 8.11 range.

    I guess it's a bit like adding hours and minutes in a program...

    So my question is, how would I go about masking the range. If I wanted to write a function that added .04 or .07 onto the number that was picked from the array and if that number went above .11 how would I assign it the correct value. Basically to make 8.13 be equal to 9.01 etc...

    here's the values for a third...
    melody = 8.00, 8.02, 8.04, 8.05, 8.07, 8.09, 8.10, 9.00
    harmony = 8.04, 8.06, 8.08, 8.09, 8.11, 9.01, 9.02, 9.04

    normally I'd just write a harmony array and use the same pointer but there's just too many different scales major minor blah blah to do that, anybody fancy having a go?


Comments

  • Registered Users Posts: 2,141 ✭✭✭eoin5


    So a random note gets picked from the scale, then you want to bump it up the scale to find the harmony.

    The best way I can see is to add 2 (for thirds) and then divide by 8 to the random number you used to select from the array to get the root, then select again.


  • Registered Users Posts: 616 ✭✭✭ogy


    don't really know c, apart from max the only proper programming i've done has been basic/comal stuff, but is some sort of argument like this possible:

    For thirds:
    if note<8.8 then harmony=note+0.04
    if note>8.8 then harmony=(note+1.00)-0.08

    For fifths
    if note<8.5 then harmony=note+0.0
    if note>8.5 then harmony=(note+1.00)-0.05


  • Closed Accounts Posts: 6,408 ✭✭✭studiorat


    eoin5 wrote: »
    So a random note gets picked from the scale, then you want to bump it up the scale to find the harmony.

    The best way I can see is to add 2 (for thirds) and then divide by 8 to the random number you used to select from the array to get the root, then select again.

    I'm not sure I understand. The problem is the intervals in the scale are decimal, it's actually .02
    Hold on...
    Do you mean if I add to the random number and use that as the pointer for the harmony? You could be on to something there. The problem is though that the intervals in the scale aren't uniform. I hadn't thought of modifying the actual random number that's interesting. I might have a little play with that.


  • Closed Accounts Posts: 6,408 ✭✭✭studiorat


    ogy wrote: »
    don't really know c, apart from max the only proper programming i've done has been basic/comal stuff, but is some sort of argument like this possible:

    For thirds:
    if note<8.8 then harmony=note+0.04
    if note>8.8 then harmony=(note+1.00)-0.08

    For fifths
    if note<8.5 then harmony=note+0.0
    if note>8.5 then harmony=(note+1.00)-0.05

    Thanks ogy, it would look something like that alright. I'll have to try it out
    if (note>8.5) {harmony=(note+1.00)-0.05;}
    else {harmony=note+0.0;}

    But I'm kind of liking eoin's (ya legend!) idea idea of actually modifying the random number (pointer) rather than the values in the array. I think I'll write a new array with all the notes in it and then use the scale arrays to point to that. Then add to the random number for my harmony values. What ya think?


  • Registered Users Posts: 1,759 ✭✭✭Neurojazz


    Make a relative note array?

    so if a third of the root scale was randomly chosen you then refer to that thirds array.

    You could even make a matrix later for all the other scales.


  • Advertisement
  • Registered Users Posts: 2,141 ✭✭✭eoin5


    studiorat wrote: »
    Do you mean if I add to the random number and use that as the pointer for the harmony?

    Yep, thats it. You can work in some logic then to check if the number has gone over the number of notes in the scale so you can increment the octave.

    in pseudoish, cant remember c too well

    randnum = randnum +2; //for third harmony

    if(randnum>8){

    randnum = randnum-8; //to bring it back under the max number for the scale

    harmonynote = scale[randnum] + 1; //incrementing the octave.

    }

    Youd need to work in a loop for anything over an octave, ninths or whatever.


  • Registered Users Posts: 3,945 ✭✭✭Anima


    [PHP]
    int key = (int)note;
    float hnote = (note - key) + 0.4; // third
    //hnote = (note - key) + 0.7; // fifth

    if( hnote > 12 ) { nhote %= 12; hnote += ++key; }
    else { hnote += key; }
    [/PHP]

    I think it'd be a lot easier to just do something like above. Maybe I'm missing something from what you said though.


  • Closed Accounts Posts: 1,397 ✭✭✭Herbal Deity


    IMO you should use a different data structure.

    Something like:
    struct note {
       int octave;
       int value;
    };
    
    void add_semitones(note* thenote, int n)
    {
       if ((thenote->value + n) / 12 > 0)
          thenote->octave++;
       
       thenote->value = (thenote->value + n) % 12;
    }
    
    double get_double_value(note* thenote)
    {
       return ((double)(thenote->value) / 100) + thenote->octave;
    }
    

    Much nicer this way. Hell, you could very easily write a "generate_major_scale" function giving the tonic note as a parameter.


  • Closed Accounts Posts: 6,408 ✭✭✭studiorat


    Woah!! Lots of good advice there.

    Muchos gracias...

    Like I said I'm pretty new to this so all the help is appreciated. I'm still very fuzzy on structures, I just about got it together to name the output file with one. And I know there's probably many many simpler ways to go about it.
    I'm going at it again on thursday and friday so if I get it working I'll post the relevant functions so you can all tear it apart.

    Thanks again.


  • Registered Users Posts: 368 ✭✭backboiler


    One thing I notice is that the dot in "8.02" and "9.11" etc. is just a field separator, not a decimal point. It just separates the octave from the semitone, which is always an integer between 0 and 11 inclusive. The dot could as easily be a '-' or a 'T' or any other character. There's no reason to bring floating point types into it. They have their uses but usually just complicate things when used unnecessarily and this is one of these occasions.
    You should pass around pointers to the structure (not the structures themselves!) in Herbal Deity's solution or, failing that if you're not comfortable with structures, as a pair of integral types.
    When you need to export them to the external program just use a "%d.%02d" format specifier to fprintf() instead of the "%.2f" messing.


  • Advertisement
  • Closed Accounts Posts: 1,397 ✭✭✭Herbal Deity


    Yeah, I just read the OP again. I initially thought that he needed to be able to format the notes as doubles/floats, but he doesn't and you're right, he's just writing pairs of numbers separared by "." to a text file.


Advertisement