Skip to content

Commit

Permalink
Merge pull request #438 from shorepine/up-amy-interp
Browse files Browse the repository at this point in the history
Bring in the new C dpwe piano into Tulip
  • Loading branch information
bwhitman authored Jan 6, 2025
2 parents fa29409 + d86df27 commit d714f40
Show file tree
Hide file tree
Showing 15 changed files with 193 additions and 36 deletions.
2 changes: 1 addition & 1 deletion amy
2 changes: 0 additions & 2 deletions tulip/amyboard/boards/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,5 @@
freeze("$(MPY_DIR)/../amy", "amy.py")
freeze("$(MPY_DIR)/../amy", "juno.py")
freeze("$(MPY_DIR)/../amy", "amy_wave.py")
freeze("$(MPY_DIR)/../amy/experiments", "tulip_piano.py")
freeze("$(MPY_DIR)/../amy/experiments", "piano_params.py")

#freeze("$(MPY_DIR)/lib/micropython-lib/micropython/utarfile", "utarfile.py")
2 changes: 0 additions & 2 deletions tulip/amyrepl/variants/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
# core scheduler replaced with a custom scheduler that uses the JavaScript
# runtime (with setTimeout an Promise's) to contrtol the scheduling.
freeze("../../../../amy", "amy.py")
freeze("../../../../amy/experiments", "tulip_piano.py")
freeze("../../../../amy/experiments", "piano_params.py")
freeze("../../../../amy", "juno.py")

package(
Expand Down
2 changes: 0 additions & 2 deletions tulip/esp32s3/boards/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,4 @@
freeze("$(MPY_DIR)/../amy", "amy.py")
freeze("$(MPY_DIR)/../amy", "juno.py")
freeze("$(MPY_DIR)/../amy", "amy_wave.py")
freeze("$(MPY_DIR)/../amy/experiments", "tulip_piano.py")
freeze("$(MPY_DIR)/../amy/experiments", "piano_params.py")
#freeze("$(MPY_DIR)/lib/micropython-lib/micropython/utarfile", "utarfile.py")
1 change: 1 addition & 0 deletions tulip/esp32s3/esp32_common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ list(APPEND MICROPY_SOURCE_EXTMOD
${AMY_DIR}/src/partials.c
${AMY_DIR}/src/pcm.c
${AMY_DIR}/src/log2_exp2.c
${AMY_DIR}/src/interp_partials.c
${ULAB_DIR}/scipy/integrate/integrate.c
${ULAB_DIR}/scipy/linalg/linalg.c
${ULAB_DIR}/scipy/optimize/optimize.c
Expand Down
2 changes: 0 additions & 2 deletions tulip/linux/variants/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,4 @@
freeze("$(MPY_DIR)/../amy", "amy.py")
freeze("$(MPY_DIR)/../amy", "juno.py")
freeze("$(MPY_DIR)/../amy", "amy_wave.py")
freeze("$(MPY_DIR)/../amy/experiments", "tulip_piano.py")
freeze("$(MPY_DIR)/../amy/experiments", "piano_params.py")

2 changes: 0 additions & 2 deletions tulip/macos/variants/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,4 @@
freeze("$(MPY_DIR)/../amy", "amy.py")
freeze("$(MPY_DIR)/../amy", "juno.py")
freeze("$(MPY_DIR)/../amy", "amy_wave.py")
freeze("$(MPY_DIR)/../amy/experiments", "tulip_piano.py")
freeze("$(MPY_DIR)/../amy/experiments", "piano_params.py")

8 changes: 7 additions & 1 deletion tulip/shared/py/midi.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@ def __init__(self, voices_per_channel, patch_per_channel, show_warnings=True):
patch = patch_per_channel[channel] if channel in patch_per_channel else None
self.add_synth(channel, patch, num_voices)

def add_synth_object(self, channel, synth_object):
def release_synth_for_channel(self, channel):
if channel in self.synth_per_channel:
# Old Synth allocated - Expicitly return the amy_voices to the pool.
self.synth_per_channel[channel].release()
del self.synth_per_channel[channel]
if channel in self.arpeggiator_per_channel:
self.arpeggiator_per_channel[channel].synth = None

def add_synth_object(self, channel, synth_object):
self.release_synth_for_channel(channel)
self.synth_per_channel[channel] = synth_object
if channel in self.arpeggiator_per_channel:
self.arpeggiator_per_channel[channel].synth = synth_object
Expand All @@ -36,6 +41,7 @@ def add_synth(self, channel=1, patch_number=0, num_voices=6):
elif channel == 16:
synth_object = OscSynth(num_voices=1) # the "system bleep" synth
else:
self.release_synth_for_channel(channel)
synth_object = Synth(num_voices=num_voices, patch_number=patch_number)
self.add_synth_object(channel, synth_object)

Expand Down
3 changes: 2 additions & 1 deletion tulip/shared/py/patches.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,8 @@
"OCTAVE WAR",
"GRAND PRIX",
"ST.HELENS ",
"EXPLOSION "
"EXPLOSION ",
"dpwe Piano"


]
2 changes: 1 addition & 1 deletion tulip/shared/py/voices.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ def update_patches(synth):
if(synth=='Custom'):
app.patchlist.replace_items([("Custom %d" % x) for x in range(32)])
if(synth=='Misc'):
app.patchlist.replace_items([])
app.patchlist.replace_items([patches[256]])
app.patchlist.label.set_text("%s patches" % (synth))

def sync_ui_for_channel(channel):
Expand Down
160 changes: 160 additions & 0 deletions tulip/shared/py/world_async.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# world-async.py
# async version of tulip world
# at first for just the web ports

import json
import js
import asyncio
import os
from world import MAX_DESCRIPTION_SIZE, MAX_USERNAME_SIZE, username, _isdir, nice_time, read_in_chunks
from world import ta, tb, text_channel_id, files_channel_id, text_base_url, files_base_url, headers, discord_epoch
from world import unique_files, ls, prompt_username


# get the last n messages
def messages(n=500, chunk_size = 100, mtype='text'):
ret = []
before = None

base_url = files_base_url
if(mtype == 'text'): base_url = text_base_url

# First one is the newest
# https://discord.com/developers/docs/resources/channel#get-channel-messages
if(n<chunk_size): chunk_size = n
response = requests.get(base_url+"messages?limit=%d" % (chunk_size), headers = headers)
# We get a x-ratelimit-reset from the headers here, we can use that to know what time it is
# We have to do it this way because (1) micropython does not have datetime/dateutil
# and (2) we often do not know what time it is on Tulip
server_time_ms = (int(response.headers['x-ratelimit-reset'])-1)*1000

# Pull up to n messages from discord, using paging
all_responses = response.json()
while(len(all_responses)<n and len(response.json())==chunk_size):
oldest_id = response.json()[-1]['id']
response = requests.get(base_url+"messages?limit=%d&before=%s" % (chunk_size, oldest_id), headers=headers)
all_responses = all_responses + response.json()


for i in all_responses[:n]:
try:
# Discord trims spaces at the end of content
if(i['content'].endswith('#')): i['content']=i['content']+' '
(username, content) = i['content'].split(" ### ")
except ValueError: # not a valid TW message / file
continue
r = {
# Discord IDs have epoch ms (since 2015) encoded in them
'age_ms':server_time_ms - ((int(i['id']) >> 22) + discord_epoch),
'time':((int(i['id']) >> 22) + discord_epoch),
'username':username,
'content':content
}
if mtype=='text' and len(i['attachments']) == 0:
ret.append(r)

if mtype=='files' and len(i['attachments']) > 0:
a = i['attachments'][0]
r.update({
'filename':a['filename'],
'size':a['size'],
'url':a['url'],
'content_type':a['content_type']
})
ret.append(r)
return ret

def download(filename, username=None, limit=5000, chunk_size=4096):
got = None
# Check for an extension
if('.' not in filename[-5:]):
filename = filename + ".tar"
for file in messages(n=limit, mtype='files'):
if(file["filename"] == filename):
if username is None or username==file['username']:
got = file
break
if got is not None:
age_nice = nice_time(got["age_ms"])
grab_url = got["url"] # Will get the latest (most recent) file with that name

r = tulip.url_save(got['url'], filename)

print("Downloaded %s by %s [%d bytes, last updated %s] from Tulip World." % (filename,got['username'], got['size'], age_nice.lstrip()))
if(filename.endswith('.tar')):
print("Unpacking %s. Run it with run('%s')" % (filename, filename[:-4]))
tulip.tar_extract(filename, show_progress=False)
os.remove(filename)
else:
if(username is None):
print("Could not find %s on Tulip World" % (filename))
else:
print("Could not find %s by %s on Tulip World" % (filename, username))



# uploads a file
def upload(filename, description=""):
u = prompt_username()
if u is None:
return

tar = False
if(_isdir(filename)):
tar = True
print("Packing %s" % (filename))
tulip.tar_create(filename)
filename += ".tar"

filesize = os.stat(filename)[6]
f = open(filename, 'rb')

# First get the url to upload to
api_response = requests.post(
files_base_url+"attachments",
headers=headers,
json={"files": [{"filename": filename, "file_size": filesize, "id": 1}]},
)

# Then PUT the file to the url
attachment_info = api_response.json()["attachments"][0]
put_url = attachment_info["upload_url"]
put_response = requests.put(
put_url,
headers={
"Authorization": headers['Authorization'],
"User-Agent": headers['User-Agent'],
"Content-Length": str(filesize),
"Content-Type": "application/octet-stream",
},
data=f,
)

# Lastly, post a message with the uploaded filename
payload = {
"content":u + " ### " + description[:MAX_DESCRIPTION_SIZE],
"attachments": [{
"id": attachment_info['id'],
"uploaded_filename":attachment_info['upload_filename'],
"filename":filename
}]
}
r = requests.post(files_base_url+"messages", headers = headers, data = json.dumps(payload))

print("Uploaded %s to Tulip World." % (filename))
if(tar):
os.remove(filename)


def post_message(message):
u = prompt_username()
if u is None:
return
r = requests.post(text_base_url+"messages", headers = headers, data = json.dumps ( {"content":u + " ### " + message} ))







1 change: 1 addition & 0 deletions tulip/shared/tulip.mk
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ EXTMOD_SRC_C += $(addprefix $(TOP)/../amy/src/, \
partials.c \
pcm.c \
log2_exp2.c \
interp_partials.c \
)

EXTMOD_SRC_C += $(addprefix $(TULIP_EXTMOD_DIR)/, \
Expand Down
2 changes: 0 additions & 2 deletions tulip/web/variants/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
freeze("../../../amy", "amy.py")
freeze("../../../amy", "juno.py")
freeze("../../../amy", "amy_wave.py")
freeze("../../../amy/experiments", "tulip_piano.py")
freeze("../../../amy/experiments", "piano_params.py")

package(
"asyncio",
Expand Down
Loading

0 comments on commit d714f40

Please sign in to comment.