rm: old poc and image
This commit is contained in:
@@ -1,13 +0,0 @@
|
||||
|
||||
|
||||
class Note:
|
||||
def __init__(self, start_time, data) -> None:
|
||||
|
||||
self.__start_time = start_time
|
||||
self.__data = data
|
||||
|
||||
def get_start_time(self):
|
||||
return self.__start_time
|
||||
|
||||
def get_data(self):
|
||||
return self.__data
|
||||
@@ -1,34 +0,0 @@
|
||||
import asyncio, datetime
|
||||
from typing import Callable
|
||||
|
||||
from .Note import Note
|
||||
|
||||
async def wait_until(dt):
|
||||
# sleep until the specified datetime
|
||||
now = datetime.datetime.now()
|
||||
await asyncio.sleep((dt - now).total_seconds())
|
||||
|
||||
async def run_at(dt, coro):
|
||||
await wait_until(dt)
|
||||
return await coro
|
||||
|
||||
class Partition:
|
||||
|
||||
def __init__(self, name:str, notes:list[Note]) -> None:
|
||||
|
||||
self.__name = name
|
||||
self.__notes = notes
|
||||
|
||||
async def play(self, output_lambda:Callable[[object], None]):
|
||||
now = datetime.datetime.now()
|
||||
tasks_to_wait = []
|
||||
for note in self.__notes:
|
||||
tasks_to_wait.append(
|
||||
asyncio.create_task(
|
||||
run_at(
|
||||
now + datetime.timedelta(milliseconds= note.get_start_time()),
|
||||
output_lambda(note.get_data())
|
||||
)
|
||||
)
|
||||
)
|
||||
await asyncio.wait(tasks_to_wait)
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/usr/bin/zsh
|
||||
|
||||
sudo python3 main.py $1 &!
|
||||
sleep 3.5
|
||||
./tester.py $1 $2
|
||||
@@ -1,56 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import board
|
||||
import neopixel
|
||||
import time
|
||||
import sys
|
||||
import asyncio
|
||||
|
||||
colorToFill = (0, 0, 0)
|
||||
pixels = neopixel.NeoPIxel(board.D18, 20, brightness=0.01)
|
||||
|
||||
notePixels = { 'si': [0, 1],
|
||||
'la#': [2, 3],
|
||||
'la': [4, 5],
|
||||
'sol#':[6],
|
||||
'sol':[7, 8, 9],
|
||||
'fa#':[10],
|
||||
'fa':[11, 12, 13],
|
||||
'mi':[14, 15, 16],
|
||||
're#':[17],
|
||||
're':[18, 19],
|
||||
'do#':[],
|
||||
'do':[]}
|
||||
|
||||
def playNote(color, secondsToStay, pixelsToFill):
|
||||
for pixelIndex in pixelsToFill:
|
||||
pixels[pixelIndex] = color
|
||||
time.sleep(secondsToStay)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def launchMusic(noteList):
|
||||
|
||||
pixels.fill(0,0,0)
|
||||
pixels.write()
|
||||
|
||||
for notes, tempo in noteList:
|
||||
for note in notes:
|
||||
playNote((255, 0, 0), tempo, notePixels[note.lower()])
|
||||
pixels.fill(colorToFill)
|
||||
pixels.write()
|
||||
|
||||
music = [
|
||||
(['sol'], 1),
|
||||
(['sol'], 1),
|
||||
(['sol'], 1),
|
||||
(['re#'], 1),
|
||||
(['la#'], 0.5),
|
||||
(['sol'], 0.5),
|
||||
(['re#'], 1),
|
||||
(['la#'], 0.5),
|
||||
]
|
||||
|
||||
launchMusic(music)
|
||||
@@ -1,166 +0,0 @@
|
||||
from xmlrpc.client import TRANSPORT_ERROR
|
||||
from chroma_case.Partition import Partition
|
||||
from chroma_case.Note import Note
|
||||
import asyncio
|
||||
import sys
|
||||
from mido import MidiFile
|
||||
|
||||
import board, neopixel
|
||||
|
||||
# on octave is 12
|
||||
RATIO = float(sys.argv[2] if len(sys.argv) > 2 else 1)
|
||||
OCTAVE = 5
|
||||
OCTAVE_AMOUNT_KEYS = 12
|
||||
TRANSPOSE_AMOUNT = OCTAVE_AMOUNT_KEYS * OCTAVE
|
||||
|
||||
pixels = neopixel.NeoPixel(board.D18, 20, brightness=0.01)
|
||||
|
||||
notePixels = { 'si': [19],
|
||||
'la#': [18],
|
||||
'la': [17],
|
||||
'sol#':[15],
|
||||
'sol':[13],
|
||||
'fa#':[10],
|
||||
'fa':[9],
|
||||
'mi':[6],
|
||||
're#':[5],
|
||||
're':[3],
|
||||
'do#':[1],
|
||||
'do':[0]}
|
||||
|
||||
|
||||
def hue_to_rgb(t1, t2, hue):
|
||||
if hue < 0: hue += 6
|
||||
if hue >= 6: hue -= 6
|
||||
if hue < 1: return (t2 - t1) * hue + t1
|
||||
if hue < 3: return t2
|
||||
if hue < 4: return (t2 - t1) * (4 - hue) + t1
|
||||
return t1
|
||||
|
||||
def hsl_to_rgb(hue, sat, light):
|
||||
hue /= 60
|
||||
if light <= 0.5:
|
||||
t2 = light * (sat + 1)
|
||||
else:
|
||||
t2 = light + sat - (light * sat)
|
||||
t1 = light * 2 - t2
|
||||
|
||||
r = hue_to_rgb(t1, t2, hue + 2) * 255
|
||||
g = hue_to_rgb(t1, t2, hue) * 255
|
||||
b = hue_to_rgb(t1, t2, hue - 2) * 255
|
||||
return [round(r), round(g), round(b)]
|
||||
|
||||
async def to_chroma_case(data):
|
||||
global pixels
|
||||
|
||||
hsl_starting_color = [100, 100, 50]
|
||||
|
||||
colored_pixels = notePixels[data["key"].lower()]
|
||||
#if "announce" in data:
|
||||
c = data["color"]
|
||||
"""for i in range(5):
|
||||
for pixelId in colored_pixels:
|
||||
pixels[pixelId] = (c[0], int(c[1] * tmp), c[2])
|
||||
tmp -= 0.2
|
||||
await asyncio.sleep(data["duration"] / (5 * 1000))"""
|
||||
"""for i in range(11):
|
||||
for pixelId in colored_pixels:
|
||||
pixels[pixelId] = hsl_to_rgb(hsl_starting_color[0], hsl_starting_color[1], hsl_starting_color[2])
|
||||
hsl_starting_color[2] += 0.01
|
||||
await asyncio.sleep(0.01)"""
|
||||
for pixelId in colored_pixels:
|
||||
pixels[pixelId] = data["color"]
|
||||
await asyncio.sleep(data['duration'] / 1000)
|
||||
for pixelId in colored_pixels:
|
||||
pixels[pixelId] = 0
|
||||
|
||||
|
||||
async def printing(data):
|
||||
print(f"key: {data['key']}, c:{data['color']} for {data['duration'] / 1000}s, time: {data['time']}")
|
||||
await asyncio.sleep(data['duration'] / 1000)
|
||||
print(f"end of {data['key']}")
|
||||
|
||||
|
||||
def midi_key_my_key(midi_key):
|
||||
keys = list(notePixels.keys())
|
||||
|
||||
keys.reverse()
|
||||
|
||||
key_index = midi_key - TRANSPOSE_AMOUNT
|
||||
if key_index >= len(keys):
|
||||
print("key out of leb barre", key_index)
|
||||
return "no_key"
|
||||
|
||||
return keys[key_index]
|
||||
|
||||
|
||||
|
||||
|
||||
async def main():
|
||||
|
||||
default_duration = 900
|
||||
default_color = (255, 0, 0)
|
||||
|
||||
notes = []
|
||||
# notes will start to play at 3500 ms (colors at the start takes this amount of time)
|
||||
s = 3500
|
||||
|
||||
notes_on = {}
|
||||
prev_note_on = {}
|
||||
note_color = {}
|
||||
|
||||
for msg in MidiFile(sys.argv[1]):
|
||||
d = msg.dict()
|
||||
print(msg, s)
|
||||
s += d['time'] * 1000 * RATIO
|
||||
|
||||
if d["type"] == "note_on":
|
||||
prev_note_on[d["note"]] = 0
|
||||
if d["note"] in notes_on:
|
||||
prev_note_on[d["note"]] = notes_on[d["note"]] # 500
|
||||
notes_on[d["note"]] = s # 0
|
||||
if d["note"] not in note_color.keys():
|
||||
note_color[d["note"]] = 1
|
||||
note_color[d["note"]] = not note_color[d["note"]]
|
||||
|
||||
if d["type"] == "note_off":
|
||||
#duration = s - notes_on[d["note"]]
|
||||
duration = s - notes_on[d["note"]]
|
||||
|
||||
"""notes.append(Note(
|
||||
s - min(s - prev_note_on[d["note"]], 500),
|
||||
{
|
||||
"duration": min(s - prev_note_on[d["note"]], 1000) / 2,
|
||||
"color": (255, 255, 0),
|
||||
"key": midi_key_my_key(d["note"]),
|
||||
"announce": True
|
||||
}
|
||||
))"""
|
||||
|
||||
note_start = notes_on[d["note"]]
|
||||
# time value is only used during debug
|
||||
notes.append(Note(note_start, {"time": note_start, "duration": duration - 10, "color": default_color if note_color[d["note"]] else (255, 100, 0), "key": midi_key_my_key(d["note"])}))
|
||||
notes_on[d["note"]] = s # 500
|
||||
|
||||
|
||||
|
||||
starting = []
|
||||
|
||||
for i in notePixels.keys():
|
||||
starting += [
|
||||
Note(000, {"duration": default_duration, "color": (255, 0, 0), "key": i, "time": 0}),
|
||||
Note(1000, {"duration": default_duration, "color": (255, 255, 0), "key": i, "time": 0}),
|
||||
Note(2000, {"duration": default_duration, "color": (0, 255, 0), "key": i, "time": 0}),
|
||||
]
|
||||
|
||||
p = Partition("my_partition",
|
||||
starting + notes
|
||||
)
|
||||
|
||||
await p.play(to_chroma_case)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(asyncio.run(main()))
|
||||
@@ -1,4 +0,0 @@
|
||||
from mido import MidiFile
|
||||
|
||||
for msg in MidiFile('new_song_1.mid'):
|
||||
print(msg)
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
while true
|
||||
do
|
||||
sudo python main.py new_song_2.mid
|
||||
done
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.8 MiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
mido
|
||||
pygame
|
||||
@@ -1,15 +0,0 @@
|
||||
import asyncio
|
||||
|
||||
async def nested():
|
||||
return 42
|
||||
|
||||
async def main():
|
||||
# Schedule nested() to run soon concurrently
|
||||
# with "main()".
|
||||
task = asyncio.create_task(nested())
|
||||
|
||||
# "task" can now be used to cancel "nested()", or
|
||||
# can simply be awaited to wait until it is complete:
|
||||
await task
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -1,146 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
from typing import List
|
||||
|
||||
import pygame as pg
|
||||
from pygame.constants import KEYDOWN
|
||||
import pygame.midi
|
||||
from mido import MidiFile
|
||||
|
||||
# Status definitions
|
||||
TOUCH_DOWN = 144
|
||||
TOUCH_UP = 128
|
||||
|
||||
|
||||
class Key:
|
||||
def __init__(self, key: int, start: int, duration: int):
|
||||
self.key = key
|
||||
self.start = start
|
||||
self.duration = duration
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.key} ({self.start} - {self.duration})"
|
||||
|
||||
|
||||
def read_midi(file):
|
||||
notes = []
|
||||
notes_on = {}
|
||||
s = 0
|
||||
for msg in MidiFile(file):
|
||||
d = msg.dict()
|
||||
s += d['time'] * 1000
|
||||
if d["type"] == "note_on":
|
||||
notes_on[d["note"]] = s
|
||||
if d["type"] == "note_off":
|
||||
duration = s - notes_on[d["note"]]
|
||||
notes_on[d["note"]] = s
|
||||
notes.append(Key(d["note"], s, duration))
|
||||
return notes
|
||||
|
||||
|
||||
keys_to_play = read_midi(sys.argv[1])
|
||||
for i in map(lambda x: str(x), keys_to_play):
|
||||
print(str(i))
|
||||
|
||||
# List of keys currently holded. Format: (key, timestamp)
|
||||
keys_down = []
|
||||
|
||||
points = 0
|
||||
|
||||
|
||||
def print_device_info():
|
||||
pygame.midi.init()
|
||||
_print_device_info()
|
||||
pygame.midi.quit()
|
||||
|
||||
|
||||
def _print_device_info():
|
||||
for i in range(pygame.midi.get_count()):
|
||||
r = pygame.midi.get_device_info(i)
|
||||
(interf, name, input, output, opened) = r
|
||||
|
||||
in_out = ""
|
||||
if input:
|
||||
in_out = "(input)"
|
||||
if output:
|
||||
in_out = "(output)"
|
||||
|
||||
print(
|
||||
"%2i: interface :%s:, name :%s:, opened :%s: %s"
|
||||
% (i, interf, name, opened, in_out)
|
||||
)
|
||||
|
||||
def poll(midi):
|
||||
if midi.poll():
|
||||
[((status, key, intensity, data3), timestamp)] = midi.read(1)
|
||||
# For status, see STATUS DEFINITIONS up there (either TOUCH_DOWN, TOUCH_UP or others for pedals)
|
||||
# The key is between 21 and 108, C5 is 60
|
||||
# The itensity is how strong the key got struck (between 1 and 130ish)
|
||||
# data3 seems to always be 0
|
||||
# timestamp seems to be a unix timestamp since the midi has been oppened.
|
||||
|
||||
# Sometimes, status is always TOUCH_DOWN so if the key is already down, we consider it the same as a key up
|
||||
is_down = any(x[0] == key for x in keys_down)
|
||||
if status == TOUCH_DOWN and not is_down:
|
||||
keys_down.append((key, timestamp))
|
||||
# print(f"Midi: {status} - {key} - {intensity} - {data3} at {timestamp}")
|
||||
elif status == TOUCH_UP or is_down:
|
||||
down_since = next(since for (h_key, since) in keys_down if h_key == key)
|
||||
keys_down.remove((key, down_since))
|
||||
return Key(key, down_since, (timestamp - down_since))
|
||||
|
||||
def is_timing_close(key, i):
|
||||
return abs(i.start - key.start) < 500
|
||||
|
||||
def run(midi):
|
||||
global points
|
||||
clock_now = 0
|
||||
while sorted(keys_to_play, key=lambda x: x.start)[-1].start > clock_now:
|
||||
key = poll(midi)
|
||||
if key is None:
|
||||
continue
|
||||
clock_now = key.start
|
||||
|
||||
to_play = next((i for i in keys_to_play if i.key == key.key and is_timing_close(key, i)), None)
|
||||
if to_play == None:
|
||||
points -= 50
|
||||
print(f"Invalid key.")
|
||||
else:
|
||||
tempo_percent = abs((key.duration / to_play.duration) - 1)
|
||||
points += tempo_percent * 50
|
||||
if tempo_percent < .3 :
|
||||
print("Too short" if key.duration < to_play.duration else "Too long")
|
||||
elif tempo_percent < .5:
|
||||
print(f"GREAT.")
|
||||
else:
|
||||
print(f"EXCELLENT.")
|
||||
points -= len(keys_to_play) * 20
|
||||
|
||||
|
||||
def input_main(device_id=None):
|
||||
pg.init()
|
||||
pygame.midi.init()
|
||||
|
||||
_print_device_info()
|
||||
|
||||
if device_id is None:
|
||||
input_id = pygame.midi.get_default_input_id()
|
||||
else:
|
||||
input_id = device_id
|
||||
|
||||
print("using input_id :%s:" % input_id)
|
||||
i = pygame.midi.Input(input_id)
|
||||
|
||||
pg.display.set_mode((1, 1))
|
||||
try:
|
||||
run(i)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
print(f"You got: {int(points)}pts")
|
||||
pygame.midi.quit()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
exit(input_main(int(sys.argv[2]) if len(sys.argv) == 3 else None))
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.8 MiB |
Reference in New Issue
Block a user