Midi and Hertz conversions

The following calculations for finding a Hertz value from a given MIDI note value, and a MIDI note value from a given Hertz value make use of known values for the note A above middle C (aka A4), which has the frequency of 440 Hz and a MIDI# of 69.

Note that a MIDI step of 1 is the equivalent of 1/12th of an octave, where an octave represents a doubling or halving of frequencies.

I would be most grateful for improvements or to learn of faster running alternatives to these functions!

public class MIDIHertzConversionFunctions
{
	public static double getHertzFromMidi(double midiVal)
	{
		return 440 * Math.pow(2, (midiVal - 69) / 12.0);
	}

	public static double log2(double n)
	{
		return Math.log(n) / Math.log(2);
	}

	public static double getMidiFromHertz(double hertz)
	{
		return ((12 * log2(hertz / 440.0)) + 69);
	}
}

I ran a bunch of tests of the following nature:


	System.out.println("circular, midi 69: " + PitchFunctions.getMidiFromHertz(
			PitchFunctions.getHertzFromMidi(69)));
		
	System.out.println("circular, hz 440: " + PitchFunctions.getHertzFromMidi(
			PitchFunctions.getMidiFromHertz(440)));

As long as the Hertz value is positive (negative Hertz values produce NaN), the results match with a reasonably tiny amount of error.

It took me a long while to figure out getting MIDI from Hertz, due to a general weakness in mathematics (I was a Music Major in college) and the need to concoct a log2 function from Java’s existing log functions. I’ve relied on workarounds up to now. The impetus to finally get this working came from wanting to store Hz values as frequency settings in XML rather than numbers that were dependent upon the specifics of associated GUI Sliders with discrete, linear granularity.

[EDIT: correction made, thank you KaiHH! Can’t believe I was off by two octaves.]

The MIDI number of A4 is 96, not 45. Therefore:


public static double getHertzFromMidi(int midiVal) {
	return 440.0 * Math.pow(2.0, (midiVal - 69) / 12.0); // <- use 69 and not 45
}

See: https://newt.phys.unsw.edu.au/jw/notes.html, https://en.wikipedia.org/wiki/MIDI_Tuning_Standard#Frequency_values

I’m using the code as @KaiHH posted. While it might be possible to optimize it, I highly doubt it’s worth it.

The class with this in also has some code I ported from Frinika that converts note names to MIDI number to feed into this. That might be useful for what you’re doing?

https://github.com/praxis-live/praxis/blob/master/praxis.audio.code/src/net/neilcsmith/praxis/audio/code/NoteUtils.java