mirror of
https://github.com/flancian/garden.git
synced 2026-08-07 23:16:21 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e231242f07 | |||
| 32b10da2db |
@@ -6,6 +6,7 @@ import click
|
|||||||
import math
|
import math
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
class AgoraCmd(click.Command):
|
class AgoraCmd(click.Command):
|
||||||
def format_help(self, ctx, formatter):
|
def format_help(self, ctx, formatter):
|
||||||
click.echo("""Usage:
|
click.echo("""Usage:
|
||||||
@@ -27,29 +28,40 @@ class AgoraCmd(click.Command):
|
|||||||
except SystemExit:
|
except SystemExit:
|
||||||
sys.exit(exc.exit_code)
|
sys.exit(exc.exit_code)
|
||||||
|
|
||||||
|
|
||||||
@click.command(cls=AgoraCmd)
|
@click.command(cls=AgoraCmd)
|
||||||
@click.argument('freq', type=click.FLOAT)
|
@click.argument('freq', type=click.FLOAT)
|
||||||
def hz(freq):
|
def hz(freq):
|
||||||
"""Calculates the closest note to input hz :)"""
|
"""Calculates the closest musical note to an input frequency in Hz."""
|
||||||
|
if freq <= 0:
|
||||||
|
click.echo("Frequency must be positive.")
|
||||||
|
return
|
||||||
|
|
||||||
A4 = 440
|
A4 = 440.0
|
||||||
|
|
||||||
# Number of half steps away.
|
# Exact continuous half steps from A4
|
||||||
n = 12 * math.log2(freq / A4)
|
n_exact = 12 * math.log2(freq / A4)
|
||||||
n = round(n)
|
n = round(n_exact)
|
||||||
note_index = n % 12
|
|
||||||
|
# Pitch deviation in cents (100 cents = 1 semitone)
|
||||||
|
cents = round((n_exact - n) * 100)
|
||||||
|
|
||||||
notes = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]
|
notes = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]
|
||||||
|
note_index = n % 12
|
||||||
note = notes[note_index]
|
note = notes[note_index]
|
||||||
|
|
||||||
octave = 4 + (n // 12)
|
octave = 4 + (n // 12)
|
||||||
if note in ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]:
|
if note in ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]:
|
||||||
# compensate for the fact that octaves are counted from C
|
# compensate for octave starting at C
|
||||||
octave += 1
|
octave += 1
|
||||||
|
|
||||||
click.echo(f"hz({freq}) is {note}{str(octave)}.")
|
note_name = f"{note}{octave}"
|
||||||
# click.echo(f"hz({freq}) is {note}.")
|
cents_str = f" ({'+' if cents > 0 else ''}{cents} cents)" if cents != 0 else " (perfect pitch)"
|
||||||
|
|
||||||
|
click.echo(f"[[hz/{freq}]] is closest to [[{note_name}]] at [[{freq}]] Hz{cents_str}.")
|
||||||
|
click.echo(f"Note class: [[{note}]], Octave: [[octave/{octave}]].")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
hz()
|
hz()
|
||||||
|
|
||||||
|
|||||||
+39
-29
@@ -1,20 +1,33 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
#
|
|
||||||
# https://click.palletsprojects.com/en/8.1.x/arguments/
|
# https://click.palletsprojects.com/en/8.1.x/arguments/
|
||||||
# https://click.palletsprojects.com/en/8.1.x/options/
|
# https://click.palletsprojects.com/en/8.1.x/options/
|
||||||
#
|
|
||||||
# boilerplate shamelessly cloned from prime.py :).
|
|
||||||
|
|
||||||
import click
|
import click
|
||||||
import math
|
|
||||||
import random
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def decompose(n):
|
||||||
|
"""Decomposes n into chunks of 7, 4, 3, 2, and 1."""
|
||||||
|
if n <= 0:
|
||||||
|
return []
|
||||||
|
ret = []
|
||||||
|
while n > 7:
|
||||||
|
ret.append(7)
|
||||||
|
n -= 7
|
||||||
|
if n == 6:
|
||||||
|
ret.extend([3, 3])
|
||||||
|
elif n == 5:
|
||||||
|
ret.extend([3, 2])
|
||||||
|
else:
|
||||||
|
ret.append(n)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class AgoraCmd(click.Command):
|
class AgoraCmd(click.Command):
|
||||||
def format_help(self, ctx, formatter):
|
def format_help(self, ctx, formatter):
|
||||||
click.echo("""Usage:
|
click.echo("""Usage:
|
||||||
- Visit anagora.org/tare to execute this file in the Agora of Flancia.
|
- Visit anagora.org/tare to execute this file in the Agora of Flancia.
|
||||||
- Visit e.g. anagora.org/tare/23 to print 23 syllables.
|
- Visit e.g. anagora.org/tare/23 to print 23 syllables of the Tara mantra.
|
||||||
- In general visit anagora.org/foo, anagora.org/foo/bar to execute e.g. <bin/foo.py bar> from your garden.
|
- In general visit anagora.org/foo, anagora.org/foo/bar to execute e.g. <bin/foo.py bar> from your garden.
|
||||||
""")
|
""")
|
||||||
|
|
||||||
@@ -31,35 +44,32 @@ class AgoraCmd(click.Command):
|
|||||||
except SystemExit:
|
except SystemExit:
|
||||||
sys.exit(exc.exit_code)
|
sys.exit(exc.exit_code)
|
||||||
|
|
||||||
def decompose(n, p):
|
|
||||||
ret = []
|
|
||||||
while n > 7:
|
|
||||||
ret.append(7)
|
|
||||||
n -= 7
|
|
||||||
if n == 6:
|
|
||||||
ret.append(3)
|
|
||||||
ret.append(3)
|
|
||||||
elif n == 5:
|
|
||||||
ret.append(3)
|
|
||||||
ret.append(2)
|
|
||||||
else:
|
|
||||||
ret.append(n)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
@click.command(cls=AgoraCmd)
|
@click.command(cls=AgoraCmd)
|
||||||
@click.argument('n', type=click.INT)
|
@click.argument('n', type=click.INT)
|
||||||
def tare(n):
|
def tare(n):
|
||||||
"""Just for fun, as many of these -- partly inspired by an Asimov story :)"""
|
"""Generates [[n]] syllables of the [[Green Tara]] mantra: Om Tare Tuttare Ture Svaha :)"""
|
||||||
parts = {
|
parts = {
|
||||||
1: ['Om'],
|
1: '[[Om]]',
|
||||||
2: ['Tare', 'Ture'],
|
2: '[[Tare]] [[Ture]]',
|
||||||
3: ['Tuttare'],
|
3: '[[Tuttare]]',
|
||||||
4: ['Tare Ture'],
|
4: '[[Tare]] [[Ture]] [[Svaha]]',
|
||||||
7: ['Tare Tuttare Ture'],
|
7: '[[Om]] [[Tare]] [[Tuttare]] [[Ture]] [[Svaha]]',
|
||||||
8: ['Tuttare Tuttare Ture'],
|
|
||||||
}
|
}
|
||||||
click.echo(decompose(n, parts))
|
|
||||||
|
chunks = decompose(n)
|
||||||
|
if not chunks:
|
||||||
|
click.echo("Please provide a positive integer count of syllables.")
|
||||||
|
return
|
||||||
|
|
||||||
|
mantra_lines = [parts.get(c, f"[[syllables/{c}]]") for c in chunks]
|
||||||
|
click.echo(f"[[Green Tara]] mantra breakdown for [[{n}]] syllables:")
|
||||||
|
for i, line in enumerate(mantra_lines, 1):
|
||||||
|
click.echo(f" {i}. {line}")
|
||||||
|
|
||||||
|
click.echo(f"\nTotal syllables: [[{n}]]")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
tare()
|
tare()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user