Search code examples
c#unity-game-enginemathaudiofrequency

Make the distance between neighbor music notes the same (Theremin like app)


I'm making a Theremin-like app in Unity (C#).

I have horizontal Axis X, on which I can click (with a mouse or with a finger on a smartphone). This X-axis determines the frequency, which will be played. The user will specify the frequency range of the board (X-Axis), let's say from frequency 261.63 (note C4) to 523.25 (note C5).

I'll calculate x_position_ratio which is a number between 0 and 1 determining, where did the user click on the X-axis (0 being on the most left (note C4 in this example), 1 on the most right (note C5))

From this, I will calculate the frequency to play by equation

float freqRange = maxFreq - minFreq;
float frequency = (x_position_ratio * freqRange) + minFreq;

And then play the frequency. It works just fine.

If I draw the notes on the board (X-axis), we can see, that the higher is the frequency, the higher is the jump between the 2 notes.

// Drawing just note A4 to demonstrate the code
float a4 = 440.0f //frequency of note A4
float x_position = (a4 - minFreq) / freqRange;

loc_x_position indicating the position of the note on the X-axis between 0 to 1

output

Question:

I would like to make the jump, same, between 2 notes (Make it linear instead of exponential, if you understand what I mean). Found the equation on Wikipedia Piano_key_frequencies but it's for the keys. I want it to every frequency and I cannot figure out how to implement it in my 2 code examples I posted


Solution

  • I figured it out. Tried to plot it logarithmic to at least approximate the result.

    I was inspired by this answer Plotting logarithmic graph Turns out this solution worked

    To draw notes on the x-axis I used this:

    minFreq = Mathf.Log10(minFreq);
    maxFreq = Mathf.Log10(maxFreq);
    float freqRange = maxFreq - minFreq;
    x_position = (Mathf.Log10(frequencyOfNoteToPlot) - minFreq) / freqRange;
    

    and to calculate the frequency I just derived frequency from the equation for the x_position and ended up with this piece of code:

    frequency = Mathf.Pow(10, x_position * freqRange + minFreq);
    

    One thing I still don't get is, why it doesn't matter, which base of the logarithm I use. Is it because I'm always getting ratio (value between 0 to 1)?