plectrum

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Mapp/src/main/java/com/github/cythara/ListenerFragment.java | 7++++---
Mapp/src/main/java/com/github/cythara/MainActivity.java | 16+++++++---------
Mapp/src/main/java/com/github/cythara/NoteName.java | 10++++++++++
Dapp/src/main/java/com/github/cythara/PitchAdjuster.java | 19-------------------
Mapp/src/main/java/com/github/cythara/PitchComparator.java | 15++++++++++++---
Dapp/src/main/java/com/github/cythara/tuning/NoteFrequency.java | 22----------------------
Aapp/src/main/java/com/github/cythara/tuning/NoteFrequencyCalculator.java | 28++++++++++++++++++++++++++++
Dapp/src/test/java/com/github/cythara/PitchAdjusterTest.java | 57---------------------------------------------------------
Aapp/src/test/java/com/github/cythara/tuning/NoteFrequencyCalculatorTest.java | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dapp/src/test/java/com/github/cythara/tuning/NoteFrequencyTest.java | 44--------------------------------------------
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