summaryrefslogtreecommitdiffstats
path: root/Scripts
diff options
context:
space:
mode:
Diffstat (limited to 'Scripts')
-rw-r--r--Scripts/generate_params.py13
-rw-r--r--Scripts/generate_utils.py38
-rw-r--r--Scripts/libtastt.py42
-rw-r--r--Scripts/osc_ctrl.py40
-rw-r--r--Scripts/transcribe.py9
5 files changed, 91 insertions, 51 deletions
diff --git a/Scripts/generate_params.py b/Scripts/generate_params.py
index 6c189a1..5deb17d 100644
--- a/Scripts/generate_params.py
+++ b/Scripts/generate_params.py
@@ -89,8 +89,8 @@ def generate():
params["PARAM_NAME"] = generate_utils.getSelectParam()
result += generate_utils.replaceMacros(INT_PARAM, params)
- for byte in range(0, generate_utils.BYTES_PER_CHAR):
- for i in range(0, generate_utils.NUM_LAYERS):
+ for byte in range(0, generate_utils.config.BYTES_PER_CHAR):
+ for i in range(0, generate_utils.config.CHARS_PER_SYNC):
params["PARAM_NAME"] = generate_utils.getBlendParam(i, byte)
result += generate_utils.replaceMacros(FLOAT_PARAM, params)
@@ -109,6 +109,8 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--old_params", type=str, help="The parameters to append to")
parser.add_argument("--new_params", type=str, help="The parameters to create")
+ parser.add_argument("--bytes_per_char", type=str, help="The number of bytes to use to represent each character")
+ parser.add_argument("--chars_per_sync", type=str, help="The number of characters to send on each sync event")
args = parser.parse_args()
if not args.old_params or not args.new_params:
@@ -117,5 +119,12 @@ if __name__ == "__main__":
parser.print_help()
parser.exit(1)
+ if not args.bytes_per_char or not args.chars_per_sync:
+ print("--bytes_per_char and --chars_per_sync required", file=sys.stderr)
+ parser.print_help()
+ parser.exit(1)
+ generate_utils.config.BYTES_PER_CHAR = int(args.bytes_per_char)
+ generate_utils.config.CHARS_PER_SYNC = int(args.chars_per_sync)
+
append(args.old_params, generate(), args.new_params)
diff --git a/Scripts/generate_utils.py b/Scripts/generate_utils.py
index e8fcc8b..6930782 100644
--- a/Scripts/generate_utils.py
+++ b/Scripts/generate_utils.py
@@ -6,16 +6,24 @@ def replaceMacros(lines, macro_defs):
lines = lines.replace("%" + k + "%", v)
return lines
-# Note, (BOARD_ROWS * BOARD_COLS % NUM_LAYERS) must equal 0. If not, writing to
-# the last cell will (with the current implementation) wrap around to the front
-# of the board.
-BOARD_ROWS=4
-BOARD_COLS=48
-NUM_REGIONS = 24
-CHARS_PER_CELL=256
-BYTES_PER_CHAR=2
-
-NUM_LAYERS=ceil((BOARD_ROWS * BOARD_COLS) / NUM_REGIONS)
+class Config():
+ def __init__(self):
+ self.BOARD_ROWS=4
+ self.BOARD_COLS=48
+ self.CHARS_PER_CELL=256
+ self.BYTES_PER_CHAR=2
+ self.CHARS_PER_SYNC=10
+
+ def numRegions(self, which_layer):
+ num_cells = self.BOARD_ROWS * self.BOARD_COLS
+ layers_in_last_region = num_cells % self.CHARS_PER_SYNC
+ float_result = num_cells / self.CHARS_PER_SYNC
+ if which_layer > layers_in_last_region:
+ return floor(float_result)
+ else:
+ return ceil(float_result)
+
+config = Config()
# Implementation detail. We use this parameter to return from the terminal
# state of the FX layer to the starting state.
@@ -94,7 +102,7 @@ def getBoardIndex(which_layer, select):
# We work around this by simply wrapping those animations back to the top
# of the board, and rely on the OSC controller to simply not reference
# those cells.
- return (select * NUM_LAYERS + which_layer) % (BOARD_ROWS * BOARD_COLS)
+ return (select * config.CHARS_PER_SYNC + which_layer) % (config.BOARD_ROWS * config.BOARD_COLS)
def getShaderParamByRowColByte(row, col, byte):
return "_Letter_Row%02d_Col%02d_Byte%01d" % (row, col, byte)
@@ -103,8 +111,8 @@ def getShaderParamByRowColByte(row, col, byte):
def getShaderParam(which_layer, select, byte):
index = getBoardIndex(which_layer, select)
- col = index % BOARD_COLS
- row = floor(index / BOARD_COLS)
+ col = index % config.BOARD_COLS
+ row = floor(index / config.BOARD_COLS)
return getShaderParamByRowCol(row, col, byte)
@@ -120,8 +128,8 @@ def getClearAnimationName():
def getAnimationNameByLayerAndIndex(which_layer, select, letter, nth_byte):
index = getBoardIndex(which_layer, select)
- col = index % BOARD_COLS
- row = floor(index / BOARD_COLS)
+ col = index % config.BOARD_COLS
+ row = floor(index / config.BOARD_COLS)
return "R%02dC%02dL%02dB%01d" % (row, col, letter, nth_byte)
diff --git a/Scripts/libtastt.py b/Scripts/libtastt.py
index 9efd0e9..3168517 100644
--- a/Scripts/libtastt.py
+++ b/Scripts/libtastt.py
@@ -165,9 +165,9 @@ def generateClearAnimation(anim_dir, guid_map):
letter = 0
- for byte in range(0, generate_utils.BYTES_PER_CHAR):
- for row in range(0, generate_utils.BOARD_ROWS):
- for col in range(0, generate_utils.BOARD_COLS):
+ for byte in range(0, generate_utils.config.BYTES_PER_CHAR):
+ for row in range(0, generate_utils.config.BOARD_ROWS):
+ for col in range(0, generate_utils.config.BOARD_COLS):
curve = curve_template.copy()
for keyframe in curve.mapping['curve'].mapping['m_Curve'].sequence:
keyframe.mapping['value'] = str(letter +
@@ -294,14 +294,14 @@ def generateAnimations(anim_dir, guid_map):
anim_clip.mapping['m_EditorCurves'].sequence = []
# To support more languages, we use 2 bytes per character, giving us a 64K character set.
- for byte in range(0, generate_utils.BYTES_PER_CHAR):
- for row in range(0, generate_utils.BOARD_ROWS):
+ for byte in range(0, generate_utils.config.BYTES_PER_CHAR):
+ for row in range(0, generate_utils.config.BOARD_ROWS):
print("Generating letter animations (row {}/{}) (byte {}/2)".format(row,
- generate_utils.BOARD_ROWS, byte), file=sys.stderr)
- for col in range(0, generate_utils.BOARD_COLS):
+ generate_utils.config.BOARD_ROWS, byte), file=sys.stderr)
+ for col in range(0, generate_utils.config.BOARD_COLS):
for letter in range(0, 2):
if letter == 1:
- letter = generate_utils.CHARS_PER_CELL - 1
+ letter = generate_utils.config.CHARS_PER_CELL - 1
# Make a deep copy of the templates
node = anim_node.copy()
@@ -348,9 +348,9 @@ def generateFXController(anim: libunity.UnityAnimator) -> typing.Dict[int, libun
anim.addParameter(generate_utils.getScaleParam(), float)
layers = {}
- for byte in range(0, generate_utils.BYTES_PER_CHAR):
+ for byte in range(0, generate_utils.config.BYTES_PER_CHAR):
layers[byte] = {}
- for i in range(0, generate_utils.NUM_LAYERS):
+ for i in range(0, generate_utils.config.CHARS_PER_SYNC):
anim.addParameter(generate_utils.getBlendParam(i, byte), float)
layer = anim.addLayer(generate_utils.getLayerName(i, byte))
@@ -375,7 +375,7 @@ def generateFXLayer(which_layer: int, anim: libunity.UnityAnimator, layer:
enable_param, True)
select_states = {}
- for i in range(0, generate_utils.NUM_REGIONS):
+ for i in range(0, generate_utils.config.numRegions(which_layer)):
dx = i * 200
dy = 200
@@ -387,7 +387,7 @@ def generateFXLayer(which_layer: int, anim: libunity.UnityAnimator, layer:
guid_lo = guid_map[anim_lo_path]
anim_hi_path = os.path.join(gen_anim_dir,
generate_utils.getAnimationNameByLayerAndIndex(
- which_layer, i, generate_utils.CHARS_PER_CELL - 1, byte) + \
+ which_layer, i, generate_utils.config.CHARS_PER_CELL - 1, byte) + \
".anim")
guid_hi = guid_map[anim_hi_path]
@@ -490,7 +490,7 @@ def generateFX(guid_map, gen_anim_dir):
layers = generateFXController(anim)
# TODO(yum) parallelize
- for byte in range(0, generate_utils.BYTES_PER_CHAR):
+ for byte in range(0, generate_utils.config.BYTES_PER_CHAR):
for which_layer, layer in layers[byte].items():
print("Generating layer {}/{}".format(which_layer, len(layers[byte].items())), file=sys.stderr)
generateFXLayer(which_layer, anim, layer, gen_anim_dir, byte)
@@ -547,6 +547,8 @@ def parseArgs():
"which all generated animations are placed.")
parser.add_argument("--guid_map", type=str, help="The path to a file which will store guids")
parser.add_argument("--fx_dest", type=str, help="The path at which to save the generated FX controller")
+ parser.add_argument("--bytes_per_char", type=str, help="The number of bytes to use to represent each character")
+ parser.add_argument("--chars_per_sync", type=str, help="The number of characters to send on each sync event")
args = parser.parse_args()
if not args.gen_dir:
@@ -569,6 +571,13 @@ if __name__ == "__main__":
args = parseArgs()
if args.cmd == "gen_anims":
+ if not args.bytes_per_char or not args.chars_per_sync:
+ print("--bytes_per_char and --chars_per_sync required", file=sys.stderr)
+ sys.exit(1)
+
+ generate_utils.config.BYTES_PER_CHAR = int(args.bytes_per_char)
+ generate_utils.config.CHARS_PER_SYNC = int(args.chars_per_sync)
+
guid_map = {}
with open(args.guid_map, 'rb') as f:
guid_map = pickle.load(f)
@@ -579,6 +588,13 @@ if __name__ == "__main__":
with open(args.guid_map, 'wb') as f:
pickle.dump(guid_map, f)
elif args.cmd == "gen_fx":
+ if not args.bytes_per_char or not args.chars_per_sync:
+ print("--bytes_per_char and --chars_per_sync required", file=sys.stderr)
+ sys.exit(1)
+
+ generate_utils.config.BYTES_PER_CHAR = int(args.bytes_per_char)
+ generate_utils.config.CHARS_PER_SYNC = int(args.chars_per_sync)
+
guid_map = {}
with open(args.guid_map, 'rb') as f:
guid_map = pickle.load(f)
diff --git a/Scripts/osc_ctrl.py b/Scripts/osc_ctrl.py
index a7dcc2b..21c6348 100644
--- a/Scripts/osc_ctrl.py
+++ b/Scripts/osc_ctrl.py
@@ -16,9 +16,7 @@ from generate_utils import getLayerParam
from generate_utils import getSelectParam
from generate_utils import getEnableParam
from generate_utils import getBoardIndex
-from generate_utils import NUM_LAYERS
-from generate_utils import BOARD_ROWS
-from generate_utils import BOARD_COLS
+from generate_utils import config
import emotes
@@ -53,7 +51,7 @@ state.encoding = generateEncoding()
# lines sent is a multiple of the number of rows in the board.
def encodeMessage(lines):
result = []
- lines_tmp = lines + [" "] * ((BOARD_ROWS - len(lines)) % BOARD_ROWS)
+ lines_tmp = lines + [" "] * ((config.BOARD_ROWS - len(lines)) % config.BOARD_ROWS)
for line in lines_tmp:
first_word = True
for word in line.split():
@@ -82,11 +80,11 @@ def encodeMessage(lines):
print("skip unrecognized char {}".format(char))
continue
result.append(state.encoding[char])
- result += [state.encoding[' ']] * (BOARD_COLS - len(line))
+ result += [state.encoding[' ']] * (config.BOARD_COLS - len(line))
return result
def updateCell(client, cell_idx, letter_encoded):
- for byte in range(0, generate_utils.BYTES_PER_CHAR):
+ for byte in range(0, generate_utils.config.BYTES_PER_CHAR):
addr="/avatar/parameters/" + generate_utils.getBlendParam(cell_idx, byte)
letter_remapped = (-127.5 + letter_encoded[byte]) / 127.5
client.send_message(addr, letter_remapped)
@@ -102,14 +100,14 @@ def disable(client):
# Send a cell all at once.
# `which_cell` is an integer in the range [0,NUM_REGIONS)
def sendMessageCellDiscrete(client, msg_cell, which_cell):
- empty_cell = [state.encoding[' ']] * NUM_LAYERS
+ empty_cell = [state.encoding[' ']] * generate_utils.config.CHARS_PER_SYNC
if msg_cell != empty_cell:
addr="/avatar/parameters/" + generate_utils.getSpeechNoiseToggleParam()
client.send_message(addr, True)
# Really long messages just wrap back around.
- which_cell = (which_cell % generate_utils.NUM_REGIONS)
+ which_cell = (which_cell % generate_utils.config.numRegions(0))
enable(client)
@@ -129,7 +127,7 @@ def sendMessageCellDiscrete(client, msg_cell, which_cell):
client.send_message(addr, False)
# The board is broken down into contiguous collections of characters called
-# cells. Each cell contains `NUM_LAYERS` characters. We can update one cell
+# cells. Each cell contains `CHARS_PER_SYNC` characters. We can update one cell
# every ~1.0 seconds. Going faster causes the board to display garbage to
# remote players.
def splitMessage(msg):
@@ -151,13 +149,13 @@ def splitMessage(msg):
print("word align: {}".format(word_align))
word = ' ' * word_align + word
- while len(word) > BOARD_COLS:
+ while len(word) > config.BOARD_COLS:
if len(line) != 0:
lines.append(line)
line = ""
- word_prefix = word[0:BOARD_COLS-1] + "-"
- word_suffix = word[BOARD_COLS-1:]
+ word_prefix = word[0:config.BOARD_COLS-1] + "-"
+ word_suffix = word[config.BOARD_COLS-1:]
#print("append prefix {}".format(word_prefix))
lines.append(word_prefix)
word = word_suffix
@@ -166,7 +164,7 @@ def splitMessage(msg):
line = word
continue
- if len(line) + len(" ") + len(word) <= BOARD_COLS:
+ if len(line) + len(" ") + len(word) <= config.BOARD_COLS:
line += " " + word
continue
@@ -195,7 +193,7 @@ def resizeBoard(num_lines, tx_state, shrink_only):
resize_param0 = None
resize_param1 = None
- if num_lines > BOARD_ROWS / 2:
+ if num_lines > config.BOARD_ROWS / 2:
# Board must be expanded to full size.
if shrink_only:
return
@@ -275,10 +273,10 @@ def sendMessageLazy(client, msg, tx_state):
empty_cells_sent = 0
nonempty_cells_sent = 0
- n_cells = ceil(msg_encoded_len / NUM_LAYERS)
+ n_cells = floor(msg_encoded_len / config.CHARS_PER_SYNC)
for cell in range(0, n_cells):
- cell_begin = cell * NUM_LAYERS
- cell_end = (cell + 1) * NUM_LAYERS
+ cell_begin = cell * config.CHARS_PER_SYNC
+ cell_end = (cell + 1) * config.CHARS_PER_SYNC
cell_msg = msg_encoded[cell_begin:cell_end]
last_cell_msg = []
@@ -289,7 +287,7 @@ def sendMessageLazy(client, msg, tx_state):
if cell_msg == last_cell_msg:
continue
- if cell_msg == [state.encoding[' ']] * NUM_LAYERS:
+ if cell_msg == [state.encoding[' ']] * config.CHARS_PER_SYNC:
if empty_cells_sent >= tx_state.empty_cells_to_send_per_call:
return SEND_MSG_LAZY_SENT_EMPTY
empty_cells_sent += 1
@@ -308,10 +306,10 @@ def sendMessageLazy(client, msg, tx_state):
return SEND_MSG_LAZY_DONE
def sendRawMessage(client, msg):
- n_cells = ceil(len(msg) / NUM_LAYERS)
+ n_cells = ceil(len(msg) / config.CHARS_PER_SYNC)
for cell in range(0, n_cells):
- cell_begin = cell * NUM_LAYERS
- cell_end = (cell + 1) * NUM_LAYERS
+ cell_begin = cell * config.CHARS_PER_SYNC
+ cell_end = (cell + 1) * config.CHARS_PER_SYNC
cell_msg = msg[cell_begin:cell_end]
#print("Send cell {}".format(cell))
sendMessageCellDiscrete(client, cell_msg, cell)
diff --git a/Scripts/transcribe.py b/Scripts/transcribe.py
index e883704..00ab82f 100644
--- a/Scripts/transcribe.py
+++ b/Scripts/transcribe.py
@@ -6,6 +6,7 @@ from datetime import datetime
import os
import osc_ctrl
from functools import partial
+import generate_utils
# python3 -m pip install pyaudio
# License: MIT.
import pyaudio
@@ -400,6 +401,8 @@ if __name__ == "__main__":
parser.add_argument("--mic", type=str, help="Which mic to use. Options: index, focusrite. Default: index")
parser.add_argument("--language", type=str, help="Which language to use. Ex: english, japanese, chinese, french, german.")
parser.add_argument("--model", type=str, help="Which AI model to use. Ex: tiny, base, small, medium")
+ parser.add_argument("--bytes_per_char", type=str, help="The number of bytes to use to represent each character")
+ parser.add_argument("--chars_per_sync", type=str, help="The number of characters to send on each sync event")
args = parser.parse_args()
if not args.mic:
@@ -411,5 +414,11 @@ if __name__ == "__main__":
if not args.model:
args.language = "base"
+ if not args.bytes_per_char or not args.chars_per_sync:
+ print("--bytes_per_char and --chars_per_sync required", file=sys.stderr)
+ sys.exit(1)
+ generate_utils.config.BYTES_PER_CHAR = int(args.bytes_per_char)
+ generate_utils.config.CHARS_PER_SYNC = int(args.chars_per_sync)
+
transcribeLoop(args.mic, args.language, args.model)