Skip to content

Instantly share code, notes, and snippets.

@cjhanks
Created August 5, 2020 16:14
Show Gist options
  • Save cjhanks/6cebd5ff7a3c248a9d77e95dff7eae8b to your computer and use it in GitHub Desktop.
Save cjhanks/6cebd5ff7a3c248a9d77e95dff7eae8b to your computer and use it in GitHub Desktop.
beat_frequencies
from argparse import ArgumentParser
import sys
import math
import matplotlib.pyplot as plt
import numpy as np
# This variable holds the steps for a minor scale
MinorSteps = [
0, # A
2, # B
3, # C
5, # D
7, # E
8, # F
10, # G
12, # A
]
MinorStepNames = [
'A', 'A#', 'B', 'C', 'C#', 'D', 'D#',
'E', 'F', 'F#', 'G', 'G#'
]
Steps = [ 1, 3, 5, 6, 8, 10, 12,
13, 15, 17, 18, 20, 22, 24]
def notestep_to_frequency(base_frequency, step):
return base_frequency * (2 ** (step / 12))
def frequency_to_notestep(base_frequency, frequency):
# This is a derivation of the above frequency to solve for notestep
if frequency == 0:
return 0
else:
return 17.3123404906676 * math.log(frequency / base_frequency)
def main():
argp = ArgumentParser()
argp.add_argument(
'--base',
type=int,
default=220)
args = argp.parse_args()
# Generate the frequencies of a two octave list of the 12 tone scale.
freq24 = []
for i in range(24):
freq24.append(notestep_to_frequency(args.base, i))
# Generate the frequencies of a minor scale
freq8 = []
for step in MinorSteps:
freq8.append(notestep_to_frequency(args.base, step))
# For each note in the minor scale, compute its beat frequency with
# each note in the 24 tone scale.
beats = []
for freq0 in freq24:
row = []
for freq1 in freq8:
beat = abs(freq1 - freq0)
row.append(beat)
beats.append(row)
#plt.imshow(np.array(beats), cmap='jet')
# Now, derive the number of note steps from the frequency
notes = []
for row in beats:
new_row = []
for freq in row:
note = frequency_to_notestep(args.base, freq)
new_row.append(note)
notes.append(new_row)
#plt.imshow(np.array(beats), cmap='inferno')
# The note numbers can be difficult to interpret, so let's convert them
# into human readable notes.
human = []
for (i, row) in enumerate(notes):
human_row = []
for (j, step) in enumerate(row):
ideal_step = int(step)
ideal_freq = notestep_to_frequency(args.base, ideal_step)
ideal_name = MinorStepNames[ideal_step % 12]
actual_freq = notestep_to_frequency(args.base, step)
octave = ideal_step // 12
freq_shift = ideal_freq - actual_freq
name = '{:+2d}{:2s}{:+6.2f}'.format(octave, ideal_name, freq_shift)
human_row.append(name)
human.append(human_row)
# Print it into a CSV friendly format.
for row in human:
for value in row:
sys.stdout.write('%s,' % value)
sys.stdout.write('\n')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment