be.tarsos.dsp.util.PitchConverter Maven / Gradle / Ivy
/*
* _______ _____ _____ _____
* |__ __| | __ \ / ____| __ \
* | | __ _ _ __ ___ ___ ___| | | | (___ | |__) |
* | |/ _` | '__/ __|/ _ \/ __| | | |\___ \| ___/
* | | (_| | | \__ \ (_) \__ \ |__| |____) | |
* |_|\__,_|_| |___/\___/|___/_____/|_____/|_|
*
* -------------------------------------------------------------
*
* TarsosDSP is developed by Joren Six at IPEM, University Ghent
*
* -------------------------------------------------------------
*
* Info: http://0110.be/tag/TarsosDSP
* Github: https://github.com/JorenSix/TarsosDSP
* Releases: http://0110.be/releases/TarsosDSP/
*
* TarsosDSP includes modified source code by various authors,
* for credits and info, see README.
*
*/
package be.tarsos.dsp.util;
/**
* Converts pitch from one unit to another (and back (and back (and back ...))).
*
* @author Joren Six
*/
public final class PitchConverter {
/**
* Hide the default constructor.
*/
private PitchConverter() {
}
/**
* C-1 = 16.35 / 2 Hz.
*/
private static final double REF_FREQ = 8.17579892;
/**
* Cache LOG 2 calculation.
*/
private static final double LOG_TWO = Math.log(2.0);
/**
* A MIDI key is an integer between 0 and 127, inclusive. Within a certain
* range every pitch is mapped to a MIDI key. If a value outside the range
* is given an IllegalArugmentException is thrown.
*
* @param hertzValue
* The pitch in Hertz.
* @return An integer representing the closest midi key.
* @exception IllegalArgumentException
* if the hertzValue does not fall within the range of valid
* MIDI key frequencies.
*/
public static int hertzToMidiKey(final Double hertzValue) {
final int midiKey = (int) Math.round(hertzToMidiCent(hertzValue));
if (midiKey < 0 || midiKey > 127) {
// TODO
// LOG.warning("MIDI is only defined between [" + midiKeyToHertz(0)
// + ","
// + midiKeyToHertz(127) + "] " + hertzValue +
// "does not map to a MIDI key.");
}
return midiKey;
}
/**
* Calculates the frequency (Hz) for a MIDI key.
*
* @param midiKey
* The MIDI key. A MIDI key is an integer between 0 and 127,
* inclusive.
* @return A frequency in Hz corresponding to the MIDI key.
* @exception IllegalArgumentException
* If midiKey is not in the valid range between 0 and 127,
* inclusive.
*/
public static double midiKeyToHertz(final int midiKey) {
if (midiKey < 0 || midiKey > 127) {
throw new IllegalArgumentException("MIDI keys are values from 0 to 127, inclusive " + midiKey
+ " is invalid.");
}
return midiCentToHertz(midiKey);
}
/**
* Converts a Hertz value to relative cents. E.g. 440Hz is converted to 900
* if the reference is a C.
*
* @param hertzValue
* A value in hertz.
* @return A value in relative cents.
*/
public static double hertzToRelativeCent(final double hertzValue) {
double absoluteCentValue = hertzToAbsoluteCent(hertzValue);
// make absoluteCentValue positive. E.g. -2410 => 1210
if (absoluteCentValue < 0) {
absoluteCentValue = Math.abs(1200 + absoluteCentValue);
}
// so it can be folded to one octave. E.g. 1210 => 10
return absoluteCentValue % 1200.0;
}
/**
* This method is not really practical. Maybe I will need it someday.
*
* @param relativeCent
* @return public static double relativeCentToHertz(double relativeCent){ if
* (relativeCent < 0 || relativeCent >= 1200) throw new
* IllegalArgumentException
* ("Relative cent values are values from 0 to 1199, inclusive " +
* relativeCent + " is invalid."); int defaultOctave = 5; int offset
* = defaultOctave * 1200; return absoluteCentToHertz(relativeCent +
* offset); }
*/
/**
* The reference frequency is configured. The default reference frequency is
* 16.35Hz. This is C0 on a piano keyboard with A4 tuned to 440 Hz. This
* means that 0 cents is C0; 1200 is C1; 2400 is C2; ... also -1200 cents is
* C-1
*
* @param hertzValue
* The pitch in Hertz.
* @return The value in absolute cents using the configured reference
* frequency
*/
public static double hertzToAbsoluteCent(final double hertzValue) {
double pitchInAbsCent = 0.0;
if (hertzValue > 0) {
pitchInAbsCent = 1200 * Math.log(hertzValue / REF_FREQ) / LOG_TWO;
} else {
throw new IllegalArgumentException("Pitch in Hz schould be greater than zero, is " + hertzValue);
}
return pitchInAbsCent;
}
/**
* Returns the frequency (Hz) of an absolute cent value. This calculation
* uses a configured reference frequency.
*
* @param absoluteCent
* The pitch in absolute cent.
* @return A pitch in Hz.
*/
public static double absoluteCentToHertz(final double absoluteCent) {
return REF_FREQ * Math.pow(2, absoluteCent / 1200.0);
}
/**
* Converts a frequency in Hz to a MIDI CENT value using
* (12 * log2 (f / 440)) + 69
* E.g.
* 69.168 MIDI CENTS = MIDI NOTE 69 + 16,8 cents
* 69.168 MIDI CENTS = 440Hz + x Hz
*
* @param hertzValue
* The pitch in Hertz.
* @return The pitch in MIDI cent.
*/
public static double hertzToMidiCent(final double hertzValue) {
double pitchInMidiCent = 0.0;
if (hertzValue != 0) {
pitchInMidiCent = 12 * Math.log(hertzValue / 440) / LOG_TWO + 69;
}
return pitchInMidiCent;
}
/**
* Converts a MIDI CENT frequency to a frequency in Hz.
*
* @param midiCent
* The pitch in MIDI CENT.
* @return The pitch in Hertz.
*/
public static double midiCentToHertz(final double midiCent) {
return 440 * Math.pow(2, (midiCent - 69) / 12d);
}
/**
* Converts cent values to ratios. See
* "Ratios Make Cents: Conversions from ratios to cents and back again" in
* the book "Tuning Timbre Spectrum Scale" William A. Sethares.
*
* @param cent
* A cent value
* @return A ratio containing the same information.
*/
public static double centToRatio(final double cent) {
final double ratio;
ratio = Math.pow(10, Math.log10(2) * cent / 1200.0);
return ratio;
}
/**
* Converts a ratio to cents.
* "Ratios Make Cents: Conversions from ratios to cents and back again" in
* the book "Tuning Timbre Spectrum Scale" William A. Sethares
*
* @param ratio
* A cent value
* @return A ratio containing the same information.
*/
public static double ratioToCent(final double ratio) {
final double cent;
cent = 1200 / Math.log10(2) * Math.log10(ratio);
return cent;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy