commit f420eeacb8cf7ef230d61c09ebb7ee8c7af6c0ad
parent 298a83d3c0e79d621a81402dbccdaae0135e093a
Author: gstraube <gstraube@mailbox.org>
Date: Sun, 14 Jun 2020 18:50:12 +0200
Use note frequency calculator (issue #30)
Diffstat:
10 files changed, 137 insertions(+), 157 deletions(-)
diff --git a/app/src/main/java/com/github/cythara/ListenerFragment.java b/app/src/main/java/com/github/cythara/ListenerFragment.java
@@ -10,6 +10,7 @@ import java.util.ArrayList;
import java.util.List;
import androidx.fragment.app.Fragment;
+
import be.tarsos.dsp.AudioDispatcher;
import be.tarsos.dsp.io.android.AudioDispatcherFactory;
import be.tarsos.dsp.pitch.PitchDetectionHandler;
@@ -105,8 +106,7 @@ public class ListenerFragment extends Fragment {
float pitch = pitchDetectionResult.getPitch();
if (pitch != -1) {
- float adjustedPitch = MainActivity.adjustPitch(pitch);
- PitchDifference pitchDifference = PitchComparator.retrieveNote(adjustedPitch);
+ PitchDifference pitchDifference = PitchComparator.retrieveNote(pitch);
pitchDifferences.add(pitchDifference);
@@ -121,7 +121,8 @@ public class ListenerFragment extends Fragment {
}
};
- PitchProcessor pitchProcessor = new PitchProcessor(PitchEstimationAlgorithm.FFT_YIN, SAMPLE_RATE,
+ PitchProcessor pitchProcessor = new PitchProcessor(PitchEstimationAlgorithm.FFT_YIN,
+ SAMPLE_RATE,
BUFFER_SIZE, pitchDetectionHandler);
audioDispatcher = AudioDispatcherFactory.fromDefaultMicrophone(SAMPLE_RATE,
diff --git a/app/src/main/java/com/github/cythara/MainActivity.java b/app/src/main/java/com/github/cythara/MainActivity.java
@@ -43,7 +43,7 @@ public class MainActivity extends AppCompatActivity implements TaskCallbacks,
private static final String USE_DARK_MODE = "use_dark_mode";
private static int tuningPosition = 0;
private static boolean isDarkModeEnabled;
- private static PitchAdjuster pitchAdjuster;
+ private static int referencePitch;
public static Tuning getCurrentTuning() {
return TuningMapper.getTuningFromPosition(tuningPosition);
@@ -53,8 +53,8 @@ public class MainActivity extends AppCompatActivity implements TaskCallbacks,
return isDarkModeEnabled;
}
- public static float adjustPitch(float pitch) {
- return pitchAdjuster.adjustPitch(pitch);
+ public static int getReferencePitch() {
+ return referencePitch;
}
@Override
@@ -76,7 +76,7 @@ public class MainActivity extends AppCompatActivity implements TaskCallbacks,
setContentView(R.layout.activity_main);
setTuning();
- setPitchAdjuster();
+ setReferencePitch();
getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
@@ -224,7 +224,7 @@ public class MainActivity extends AppCompatActivity implements TaskCallbacks,
editor.putInt(REFERENCE_PITCH, newValue);
editor.apply();
- setPitchAdjuster();
+ setReferencePitch();
TunerView tunerView = this.findViewById(R.id.pitch);
tunerView.invalidate();
@@ -280,12 +280,10 @@ public class MainActivity extends AppCompatActivity implements TaskCallbacks,
AppCompatDelegate.setDefaultNightMode(mode);
}
- private void setPitchAdjuster() {
+ private void setReferencePitch() {
final SharedPreferences preferences = getSharedPreferences(PREFS_FILE,
MODE_PRIVATE);
- int referencePitch = preferences.getInt(REFERENCE_PITCH, 440);
-
- pitchAdjuster = new PitchAdjuster(referencePitch);
+ referencePitch = preferences.getInt(REFERENCE_PITCH, 440);
}
private void requestRecordAudioPermission() {
diff --git a/app/src/main/java/com/github/cythara/NoteName.java b/app/src/main/java/com/github/cythara/NoteName.java
@@ -25,4 +25,14 @@ public enum NoteName {
public String getSol() {
return sol;
}
+
+ public static NoteName fromScientificName(String scientificName) {
+ for (NoteName noteName : NoteName.values()) {
+ if (noteName.getScientific().equalsIgnoreCase(scientificName)) {
+ return noteName;
+ }
+ }
+
+ throw new IllegalArgumentException("Could not convert from name: " + scientificName);
+ }
}
diff --git a/app/src/main/java/com/github/cythara/PitchAdjuster.java b/app/src/main/java/com/github/cythara/PitchAdjuster.java
@@ -1,19 +0,0 @@
-package com.github.cythara;
-
-class PitchAdjuster {
-
- private static final float A440 = 440f;
- private final float adjustmentFactor;
-
- PitchAdjuster() {
- adjustmentFactor = 1f;
- }
-
- PitchAdjuster(float referencePitch) {
- adjustmentFactor = referencePitch / A440;
- }
-
- float adjustPitch(float pitch) {
- return pitch / adjustmentFactor;
- }
-}
diff --git a/app/src/main/java/com/github/cythara/PitchComparator.java b/app/src/main/java/com/github/cythara/PitchComparator.java
@@ -1,19 +1,28 @@
package com.github.cythara;
+import com.github.cythara.tuning.NoteFrequencyCalculator;
+
import java.util.Arrays;
class PitchComparator {
static PitchDifference retrieveNote(float pitch) {
Tuning tuning = MainActivity.getCurrentTuning();
+ int referencePitch = MainActivity.getReferencePitch();
Note[] notes = tuning.getNotes();
- Arrays.sort(notes, (o1, o2) -> Float.compare(o1.getFrequency(), o2.getFrequency()));
+ NoteFrequencyCalculator noteFrequencyCalculator =
+ new NoteFrequencyCalculator(referencePitch);
+
+ Arrays.sort(notes, (o1, o2) ->
+ Double.compare(noteFrequencyCalculator.getFrequency(o1),
+ noteFrequencyCalculator.getFrequency(o2)));
double minCentDifference = Float.POSITIVE_INFINITY;
Note closest = notes[0];
for (Note note : notes) {
- double centDifference = 1200d * log2(pitch / note.getFrequency());
+ double frequency = noteFrequencyCalculator.getFrequency(note);
+ double centDifference = 1200d * log2(pitch / frequency);
if (Math.abs(centDifference) < Math.abs(minCentDifference)) {
minCentDifference = centDifference;
@@ -24,7 +33,7 @@ class PitchComparator {
return new PitchDifference(closest, minCentDifference);
}
- private static double log2(float number) {
+ private static double log2(double number) {
return Math.log(number) / Math.log(2);
}
}
diff --git a/app/src/main/java/com/github/cythara/tuning/NoteFrequency.java b/app/src/main/java/com/github/cythara/tuning/NoteFrequency.java
@@ -1,21 +0,0 @@
-package com.github.cythara.tuning;
-
-import java.util.Arrays;
-import java.util.List;
-
-public class NoteFrequency {
-
- private static List<String> notes =
- Arrays.asList("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B");
-
- public static double getFrequency(String note, int octave) {
- int semitonesPerOctave = 12;
- int referenceOctave = 4;
- double distance = semitonesPerOctave * (octave - referenceOctave);
-
- distance += notes.indexOf(note) - notes.indexOf("A");
-
- float referenceFrequency = 440;
- return referenceFrequency * Math.pow(2, distance / 12);
- }
-}
-\ No newline at end of file
diff --git a/app/src/main/java/com/github/cythara/tuning/NoteFrequencyCalculator.java b/app/src/main/java/com/github/cythara/tuning/NoteFrequencyCalculator.java
@@ -0,0 +1,27 @@
+package com.github.cythara.tuning;
+
+import com.github.cythara.Note;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class NoteFrequencyCalculator {
+
+ private static List<String> notes =
+ Arrays.asList("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B");
+ private float referenceFrequency;
+
+ public NoteFrequencyCalculator(float referenceFrequency) {
+ this.referenceFrequency = referenceFrequency;
+ }
+
+ public double getFrequency(Note note) {
+ int semitonesPerOctave = 12;
+ int referenceOctave = 4;
+ double distance = semitonesPerOctave * (note.getOctave() - referenceOctave);
+
+ distance += notes.indexOf(note.getName() + note.getSign()) - notes.indexOf("A");
+
+ return referenceFrequency * Math.pow(2, distance / 12);
+ }
+}
+\ No newline at end of file
diff --git a/app/src/test/java/com/github/cythara/PitchAdjusterTest.java b/app/src/test/java/com/github/cythara/PitchAdjusterTest.java
@@ -1,57 +0,0 @@
-package com.github.cythara;
-
-import com.github.cythara.tuning.GuitarTuning;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import static com.github.cythara.NoteName.E;
-import static com.github.cythara.NoteName.G;
-import static com.github.cythara.tuning.GuitarTuning.Pitch;
-import static org.hamcrest.Matchers.is;
-
-public class PitchAdjusterTest {
-
- @Test
- public void pitch_is_unchanged_for_A440() {
- PitchAdjuster pitchAdjuster = new PitchAdjuster();
-
- for (Pitch pitch : GuitarTuning.Pitch.values()) {
- Assert.assertThat(pitchAdjuster.adjustPitch(pitch.getFrequency()),
- is(pitch.getFrequency()));
- }
- }
-
- @Test
- public void pitch_is_adjusted() {
- PitchAdjuster pitchAdjuster = new PitchAdjuster(442f);
- Assert.assertThat(pitchAdjuster.adjustPitch(662.25f), is(659.2534f));
-
- pitchAdjuster = new PitchAdjuster(434f);
- Assert.assertThat(pitchAdjuster.adjustPitch(172.23f), is(174.61105f));
- }
-
- @Test
- public void correct_note_is_retrieved_for_adjusted_pitch() {
- PitchAdjuster pitchAdjuster = new PitchAdjuster(446f);
- float adjustedPitch = pitchAdjuster.adjustPitch(198.67f);
-
- Assert.assertThat(PitchComparator.retrieveNote(adjustedPitch).closest.getName(),
- is(G));
- Assert.assertThat(PitchComparator.retrieveNote(adjustedPitch).closest.getSign(),
- is(""));
- Assert.assertThat(PitchComparator.retrieveNote(adjustedPitch).closest.getOctave(),
- is(3));
-
- pitchAdjuster = new PitchAdjuster(432f);
- adjustedPitch = pitchAdjuster.adjustPitch(80.91f);
-
-
- Assert.assertThat(PitchComparator.retrieveNote(adjustedPitch).closest.getName(),
- is(E));
- Assert.assertThat(PitchComparator.retrieveNote(adjustedPitch).closest.getSign(),
- is(""));
- Assert.assertThat(PitchComparator.retrieveNote(adjustedPitch).closest.getOctave(),
- is(2));
- }
-}
diff --git a/app/src/test/java/com/github/cythara/tuning/NoteFrequencyCalculatorTest.java b/app/src/test/java/com/github/cythara/tuning/NoteFrequencyCalculatorTest.java
@@ -0,0 +1,75 @@
+package com.github.cythara.tuning;
+
+import com.github.cythara.Note;
+import com.github.cythara.NoteName;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class NoteFrequencyCalculatorTest {
+
+ @Test
+ public void TestCalc() {
+
+ InputStream resourceAsStream = getClass().getResourceAsStream("note_frequencies.csv");
+ try (BufferedReader reader =
+ new BufferedReader(new InputStreamReader(resourceAsStream))) {
+ while (reader.ready()) {
+ String line = reader.readLine();
+ String[] components = line.split(",");
+ String noteWithOctave = components[0].split("/")[0];
+ String frequency = components[1];
+
+ String noteName = noteWithOctave.substring(0, 1);
+ String octave = noteWithOctave.substring(1);
+ String sign = "";
+ if (noteWithOctave.contains("#")) {
+ noteName = noteWithOctave.substring(0, 1);
+ octave = noteWithOctave.substring(2);
+ sign = "#";
+ }
+
+ String finalNoteName = noteName;
+ String finalOctave = octave;
+ String finalSign = sign;
+ Note note = new Note() {
+ @Override
+ public NoteName getName() {
+ return NoteName.fromScientificName(finalNoteName);
+ }
+
+ @Override
+ public int getOctave() {
+ return Integer.parseInt(finalOctave);
+ }
+
+ @Override
+ public String getSign() {
+ return finalSign;
+ }
+
+ @Override
+ public float getFrequency() {
+ return 0;
+ }
+ };
+
+ NoteFrequencyCalculator noteFrequencyCalculator =
+ new NoteFrequencyCalculator(440);
+ double expectedFrequency = Double.parseDouble(frequency);
+ double actualFrequency = noteFrequencyCalculator.getFrequency(note);
+ Assert.assertEquals(expectedFrequency, actualFrequency, 0.01);
+
+ }
+ } catch (IOException e) {
+ Assert.fail(e.getMessage());
+ }
+
+ }
+
+}
+\ No newline at end of file
diff --git a/app/src/test/java/com/github/cythara/tuning/NoteFrequencyTest.java b/app/src/test/java/com/github/cythara/tuning/NoteFrequencyTest.java
@@ -1,43 +0,0 @@
-package com.github.cythara.tuning;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-
-public class NoteFrequencyTest {
-
- @Test
- public void TestCalc() {
-
- InputStream resourceAsStream = getClass().getResourceAsStream("note_frequencies.csv");
- try (BufferedReader reader =
- new BufferedReader(new InputStreamReader(resourceAsStream))) {
- while (reader.ready()) {
- String line = reader.readLine();
- String[] components = line.split(",");
- String noteWithOctave = components[0].split("/")[0];
- String frequency = components[1];
-
- String note = noteWithOctave.substring(0, 1);
- String octave = noteWithOctave.substring(1);
- if (noteWithOctave.contains("#")) {
- note = noteWithOctave.substring(0, 2);
- octave = noteWithOctave.substring(2);
- }
-
- double expectedFrequency = Double.parseDouble(frequency);
- double actualFrequency = NoteFrequency.getFrequency(note, Integer.parseInt(octave));
- Assert.assertEquals(expectedFrequency, actualFrequency, 0.01);
-
- }
- } catch (IOException e) {
- Assert.fail(e.getMessage());
- }
-
- }
-
-}
-\ No newline at end of file