Skip to content

Commit

Permalink
Include note name in frequency axis trackers
Browse files Browse the repository at this point in the history
This applies to the FFT Spectrum, 2D Spectrogram, and Octave Spectrogram.
  • Loading branch information
celeste-sinead authored and tlecomte committed May 5, 2024
1 parent 363cf41 commit 32bbd5d
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 25 deletions.
5 changes: 4 additions & 1 deletion friture/histplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def __init__(self, parent, engine):
self._histplot_data.vertical_axis.name = "PSD (dB A)"
self._histplot_data.vertical_axis.setTrackerFormatter(lambda x: "%.1f dB" % (x))
self._histplot_data.horizontal_axis.name = "Frequency (Hz)"
self._histplot_data.horizontal_axis.setTrackerFormatter(lambda x: "%.0f Hz" % (x))
self._histplot_data.horizontal_axis.setTrackerFormatter(self.format_frequency)

self._histplot_data.vertical_axis.setRange(0, 1)
self._histplot_data.horizontal_axis.setRange(44, 22000)
Expand Down Expand Up @@ -89,6 +89,9 @@ def __init__(self, parent, engine):

self.setLayout(plotLayout)

def format_frequency(self, freq: float) -> str:
return f'{freq:.0f} Hz ({fscales.freq_to_note(freq)})'

def on_status_changed(self, status):
if status == QQuickWidget.Error:
for error in self.quickWidget.errors():
Expand Down
5 changes: 4 additions & 1 deletion friture/imageplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def __init__(self, parent):
self.colorScale.setTitle("PSD (dB A)")

self.canvasWidget = CanvasWidget(self, self.verticalScaleTransform, self.horizontalScaleTransform)
self.canvasWidget.setTrackerFormatter(lambda x, y: "%.2f s, %d Hz" % (x, y))
self.canvasWidget.setTrackerFormatter(self.trackerFormatter)

plotLayout = QtWidgets.QGridLayout()
plotLayout.setSpacing(0)
Expand All @@ -221,6 +221,9 @@ def __init__(self, parent):
# need to replot here for the size Hints to be computed correctly (depending on axis scales...)
self.update()

def trackerFormatter(self, x: float, y: float) -> str:
return f'{x:.2f} s, {y:.0f} Hz ({fscales.freq_to_note(y)})'

def addData(self, freq, xyzs, last_data_time):
self.plotImage.addData(freq, xyzs, self.freqscale, last_data_time)

Expand Down
9 changes: 9 additions & 0 deletions friture/plotting/frequency_scales.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,15 @@ def _minorTicks(trueMin, trueMax, firstMajorTick, majorTickInterval) -> list[flo

return ticks

def freq_to_note(freq: float) -> str:
if np.isnan(freq) or freq <= 0:
return ""
# number of semitones from C4
# A4 = 440Hz and is 9 semitones above C4
semitone = round(np.log2(freq/440) * 12) + 9
octave = int(np.floor(semitone / 12)) + 4
notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
return f'{notes[semitone % 12]}{octave}'

class Logarithmic(object):
NAME = 'Logarithmic'
Expand Down
28 changes: 5 additions & 23 deletions friture/spectrumPlotWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from friture.audiobackend import SAMPLING_RATE
from friture.plotting.coordinateTransform import CoordinateTransform
from friture.plotting.frequency_scales import freq_to_note
from friture.spectrum_data import Spectrum_Data
from friture.filled_curve import CurveType, FilledCurve
from friture.store import GetStore
Expand Down Expand Up @@ -49,9 +50,7 @@ def __init__(self, parent, engine):
self._spectrum_data.vertical_axis.name = "PSD (dB)"
self._spectrum_data.vertical_axis.setTrackerFormatter(lambda x: "%.1f dB" % (x))
self._spectrum_data.horizontal_axis.name = "Frequency (Hz)"
self._spectrum_data.horizontal_axis.setTrackerFormatter(
self.trackerFormatterPitch
)
self._spectrum_data.horizontal_axis.setTrackerFormatter(self.format_frequency)

self._spectrum_data.vertical_axis.setRange(0, 1)
self._spectrum_data.horizontal_axis.setRange(0, 22000)
Expand Down Expand Up @@ -143,25 +142,8 @@ def set_baseline_displayUnits(self, baseline):
def set_baseline_dataUnits(self, baseline):
self._baseline = Baseline.DATA_ZERO

def freq_to_note(self, freq: float) -> str:
if freq == 0:
return ""
# number of semitones from C4
# A4 = 440Hz and is 9 semitones above C4
semitone = round(np.log2(freq / 440) * 12) + 9
octave = int(np.floor(semitone / 12)) + 4
notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
return f"{notes[semitone % 12]}{octave}"

def trackerFormatterPitch(self, x):
try:
note = self.freq_to_note(x)
except ValueError:
return ""
if x < 1000:
return "%d Hz (%s)" % (int(x), note)
else:
return "%.1f kHz (%s)" % (x / 1000, note)
def format_frequency(self, freq: float) -> str:
return f'{freq:.0f} Hz ({freq_to_note(freq)})'

def setdata(self, x, y, fmax, fpitch):
if not self.paused:
Expand All @@ -173,7 +155,7 @@ def setdata(self, x, y, fmax, fpitch):
text, self.normHorizontalScaleTransform.toScreen(fmax)
)
self._spectrum_data.setFpitch(
f"{int(fpitch)} Hz ({self.freq_to_note(fpitch)})",
self.format_frequency(fpitch),
self.normHorizontalScaleTransform.toScreen(fpitch),
)

Expand Down

0 comments on commit 32bbd5d

Please sign in to comment.