Created
October 12, 2023 09:32
-
-
Save romilly/e3bb09d0b965fc5c9183f6f696b59425 to your computer and use it in GitHub Desktop.
Convert a note pitch like A#4 to its frequency.
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
# -*- coding: utf-8 -*- | |
""" | |
Convert a note pitch like A#4 to its frequency. | |
""" | |
# Generate a unique pitch for a note based on its pitch class and octave. | |
def name(pitch_class: str, octave: int) -> str: | |
return f"{pitch_class}{octave}" | |
# Define the twelve pitch classes in the Chromatic Octave. | |
CHROMATIC_OCTAVE = "C,C#,D,D#,E,F,F#,G,G#,A,A#,B".split(',') | |
# Define the range of octaves to consider. | |
OCTAVES = range(8) | |
# Generate all possible note names from 'C0' to 'B7'. | |
PITCH_CLASS_NAMES = [name(pitch_class, octave) for octave in OCTAVES for pitch_class in CHROMATIC_OCTAVE] | |
# Calculate the ratio between the frequency of a note and the frequency of the semitone above it. | |
SEMITONE_FACTOR = 2 ** (1 / 12.0) | |
# Convert an index in the list of notes to its frequency. | |
def tone_for(i: int) -> int: | |
return round(440 * SEMITONE_FACTOR ** (i - 57)) | |
# Map each note name to its frequency. | |
NOTE_FREQUENCIES = dict([(name, tone_for(i)) for i, name in enumerate(PITCH_CLASS_NAMES)]) | |
# In music, some notes have two names even though they sound the same, known as enharmonics. | |
# Add the enharmonic notes to the NOTE_FREQUENCIES dictionary for accurate frequency lookups. | |
for octave in OCTAVES: | |
for (first, second) in [("C#", "D♭"), ("D#", "E♭"), ("F#", "G♭"), ("G#", "A♭"), ("A#", "B♭")]: | |
NOTE_FREQUENCIES[name(second, octave)] = NOTE_FREQUENCIES[name(first, octave)] | |
# Convert a note name to its frequency in the well-tempered scale. | |
def frequency_for_note(name: str) -> int: | |
if 'S' in name: | |
name = name.replace('S','#') | |
return -1 if name not in NOTE_FREQUENCIES else NOTE_FREQUENCIES[name] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment