-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(Hopefully) improved detection of frequencies.
This scans through several possible harmonics to check if there is a better match than the purely correlation-based approach.
- Loading branch information
Showing
11 changed files
with
781 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
app/src/main/java/de/moekadu/tuner/notedetection/HarmonicPredictor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package de.moekadu.tuner.notedetection | ||
|
||
/** Predict frequency of a given harmonic, based on previous harmonics. | ||
* This class uses the function | ||
* frequency = f1 * harmonic * (1 + beta * harmonic) | ||
* which is the same as | ||
* frequency = f1 * harmonic + alpha * harmonic**2 | ||
* (with alpha = beta * f1) as modelling function and uses a least squares fit on previous | ||
* information to predict new harmonics. | ||
*/ | ||
class HarmonicPredictor { | ||
/** Sum of frequency * harmonicNumber */ | ||
private var sumFh = 0f | ||
/** Sum of frequency * harmonicNumber**2 */ | ||
private var sumFh2 = 0f | ||
/** Sum of harmonicNumber**2 */ | ||
private var sumH2 = 0f | ||
/** Sum of harmonicNumber**3 */ | ||
private var sumH3 = 0f | ||
/** Sum of harmonicNumber**4 */ | ||
private var sumH4 = 0f | ||
/** Alpha factor of modelling function */ | ||
private var alpha = 0f | ||
/** Beta factor of modelling function */ | ||
private var beta = 0f | ||
/** Base frequency of modelling function */ | ||
private var f1 = 0f | ||
|
||
/** Reset predictor. */ | ||
fun clear() { | ||
sumFh = 0f | ||
sumFh2 = 0f | ||
sumH2 = 0f | ||
sumH3 = 0f | ||
sumH4 = 0f | ||
alpha = 0f | ||
beta = 0f | ||
f1 = 0f | ||
} | ||
/** Add new harmonic to the modelling function. | ||
* @param harmonicNumber Harmonic number. | ||
* @param frequency Frequency of harmonic. | ||
*/ | ||
fun add(harmonicNumber: Int, frequency: Float) { | ||
val hSqr = harmonicNumber * harmonicNumber | ||
val hCub = harmonicNumber * hSqr | ||
val hQuad = hSqr * hSqr | ||
|
||
sumFh += frequency * harmonicNumber | ||
sumFh2 += frequency * hSqr | ||
sumH2 += hSqr | ||
sumH3 += hCub | ||
sumH4 += hQuad | ||
if (f1 == 0f) { | ||
f1 = frequency / harmonicNumber | ||
} else { | ||
alpha = (sumFh2 * sumH2 - sumFh * sumH3) / (sumH4 * sumH2 - sumH3 * sumH3) | ||
f1 = (sumFh - alpha * sumH3) / sumH2 | ||
beta = alpha / f1 | ||
} | ||
} | ||
|
||
/** Predict frequency of a given harmonic. | ||
* @param harmonicNumber harmonic number. | ||
* @return Predicted frequency. | ||
*/ | ||
fun predict(harmonicNumber: Int): Float { | ||
return f1 * harmonicNumber * (1 + beta * harmonicNumber) | ||
} | ||
} |
Oops, something went wrong.