SoundPatch: design a sound where it can be heard, then convert it
The bang was guessed at directly in bytes and came out as a low gurgle, which is what guessing at bytes gets you: a cutoff of 40 looks small and is 57 Hz, so the filter sweep ended almost shut. Voyager's sound device is soundThing's voice engine with the editor taken off, so a patch designed in soundThing - where there is a screen, a keyboard and a pair of ears - makes the same sound here. What differs is only how it arrives. SoundPatch converts one into the other. Every parameter the device takes is a documented function of a natural value and all of them invert: times are squared into four seconds, cutoff and rate are exponential, depths and detune are centred on 128. It writes a table of a count and that many parameter and value pairs, and playPatch hands it to the device - so every sound after this costs a table and a call rather than forty lines of its own. Two things the conversion has to say out loud. soundThing has no field for the level routing, because there it is always the amplitude envelope, so the table says so explicitly - a channel keeps its patch between notes and a leftover from a previous one would otherwise be carried in. And a field the tool does not recognise STOPS it: a patch format that has moved on would otherwise produce a table that quietly means something else. THE BUILD DOES NOT DEPEND ON IT. soundThing lives in its own repository and is not needed to build anything here; the tables are checked in and the tool is for when a sound is being changed. Lander's crash now plays Kick808 as a stand-in until a bang is designed for it, and the difference is the point: the hand-guessed patch wandered between 1600 and 8200 for eight tenths of a second, and this decays 3492, 2743, 2037, 1515, 1040, 614, 87, nothing. The docs check caught the tool count in two manuals, which is what it is for.
This commit is contained in:
@@ -49,6 +49,7 @@ SRC_DIR_EMU = Source/Emulator
|
||||
SRC_DIR_ASM = Source/Assembler
|
||||
SRC_DIR_DSK = Source/DiskTool
|
||||
SRC_DIR_LINT = Source/Linter
|
||||
SRC_DIR_PATCH = Source/Patch
|
||||
OBJ_DIR = Object
|
||||
|
||||
# Source files
|
||||
@@ -63,12 +64,14 @@ VOY_SRCS = voyager.c $(MACHINE_SRCS)
|
||||
ASM_SRCS = Assembler.c assembly.c firstPass.c Assm-util.c secondPass.c
|
||||
DSK_SRCS = SplitDisk.c
|
||||
LINT_SRCS = Linter.c
|
||||
PATCH_SRCS = SoundPatch.c
|
||||
|
||||
EMU_OBJS = $(EMU_SRCS:%.c=$(OBJ_DIR)/%.o)
|
||||
VOY_OBJS = $(VOY_SRCS:%.c=$(OBJ_DIR)/%.o)
|
||||
ASM_OBJS = $(ASM_SRCS:%.c=$(OBJ_DIR)/%.o)
|
||||
DSK_OBJS = $(DSK_SRCS:%.c=$(OBJ_DIR)/%.o)
|
||||
LINT_OBJS = $(LINT_SRCS:%.c=$(OBJ_DIR)/%.o) $(OBJ_DIR)/assembly.o
|
||||
PATCH_OBJS = $(PATCH_SRCS:%.c=$(OBJ_DIR)/%.o)
|
||||
|
||||
# Output binary names
|
||||
EMU_TARGET = SplitBit
|
||||
@@ -76,6 +79,7 @@ VOY_TARGET = Voyager
|
||||
ASM_TARGET = Assembler
|
||||
DSK_TARGET = SplitDisk
|
||||
LINT_TARGET = SplitLint
|
||||
PATCH_TARGET = SoundPatch
|
||||
|
||||
# ---- Whether this machine can build Voyager ----
|
||||
#
|
||||
@@ -147,7 +151,7 @@ DISKTOOL = ./$(DSK_TARGET)
|
||||
|
||||
# Libraries are included by bare name, so the assembler is told where to find them. CosmOS
|
||||
# owns the filesystem library and the service names, so it is a place to look too.
|
||||
INCLUDES = -I $(PROG_DIR)/Libraries -I $(PROG_DIR)/CosmOS/Source
|
||||
INCLUDES = -I $(PROG_DIR)/Sounds -I $(PROG_DIR)/Libraries -I $(PROG_DIR)/CosmOS/Source
|
||||
|
||||
# The programs worth building. Every one lives in a directory that says what kind it is:
|
||||
# Examples/ is what you read to learn, Loader/ is the standalone loader CosmOS grew out of,
|
||||
@@ -208,7 +212,7 @@ SCRATCH_BLOCKS = 2048
|
||||
# linter, the whole test suite - has to build on a machine with no graphics library at all,
|
||||
# because a project about a small understandable CPU should not need OpenGL to run its
|
||||
# tests. Where Raylib is missing, 'make' says so once and builds everything else.
|
||||
TOOLS = $(EMU_TARGET) $(ASM_TARGET) $(DSK_TARGET) $(LINT_TARGET)
|
||||
TOOLS = $(EMU_TARGET) $(ASM_TARGET) $(DSK_TARGET) $(LINT_TARGET) $(PATCH_TARGET)
|
||||
|
||||
# ---- What 'make' builds ----
|
||||
#
|
||||
@@ -291,6 +295,20 @@ $(DSK_TARGET): $(DSK_OBJS)
|
||||
$(LINT_TARGET): $(LINT_OBJS)
|
||||
$(CC) $(CFLAGS) -o $(LINT_TARGET) $(LINT_OBJS)
|
||||
|
||||
# ---- SoundPatch, which needs the maths library and nothing else ----
|
||||
#
|
||||
# It converts a soundThing patch into a table of bytes for the sound device. Nothing in the
|
||||
# build depends on it, and that is deliberate: soundThing lives in another repository and the
|
||||
# tables it produces are CHECKED IN, so this tree builds on a machine that has never heard of
|
||||
# it. The tool is here for when a sound is being changed.
|
||||
$(PATCH_TARGET): $(PATCH_OBJS)
|
||||
$(CC) $(CFLAGS) -o $(PATCH_TARGET) $(PATCH_OBJS) -lm
|
||||
|
||||
# Compile patch tool source files to object files
|
||||
$(OBJ_DIR)/%.o: $(SRC_DIR_PATCH)/%.c
|
||||
@mkdir -p $(OBJ_DIR)
|
||||
$(CC) $(CFLAGS) $(POSIXFLAGS) $(DEPFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJ_DIR)/Linter.o: $(SRC_DIR_LINT)/Linter.c
|
||||
@mkdir -p $(OBJ_DIR)
|
||||
$(CC) $(CFLAGS) $(POSIXFLAGS) $(DEPFLAGS) -c $< -o $@
|
||||
@@ -311,7 +329,7 @@ $(OBJ_DIR)/%.o: $(SRC_DIR_ASM)/%.c
|
||||
# disagreed with everything else about how big the struct was, and smashed its stack on every
|
||||
# run. A clean build hid it, which is why 'make sanitize' would never have found it either.
|
||||
# Tests/voyager.sh did, by failing all 115 tests that start the machine.
|
||||
-include $(EMU_OBJS:.o=.d) $(VOY_OBJS:.o=.d) $(ASM_OBJS:.o=.d) $(DSK_OBJS:.o=.d) $(LINT_OBJS:.o=.d)
|
||||
-include $(EMU_OBJS:.o=.d) $(VOY_OBJS:.o=.d) $(ASM_OBJS:.o=.d) $(DSK_OBJS:.o=.d) $(LINT_OBJS:.o=.d) $(PATCH_OBJS:.o=.d)
|
||||
|
||||
# ---- The strict build the README promises ----
|
||||
#
|
||||
@@ -425,7 +443,7 @@ clean:
|
||||
rm -rf Tests/build
|
||||
rm -rf $(PROG_BUILD)
|
||||
rm -f $(SRC_DIR_EMU)/rom.c
|
||||
rm -f $(EMU_TARGET) $(ASM_TARGET) $(DSK_TARGET) $(LINT_TARGET) $(VOY_TARGET)
|
||||
rm -f $(EMU_TARGET) $(ASM_TARGET) $(DSK_TARGET) $(LINT_TARGET) $(VOY_TARGET) $(PATCH_TARGET)
|
||||
|
||||
# Install compiled binaries
|
||||
install: $(EMU_TARGET) $(ASM_TARGET) $(DSK_TARGET) $(LINT_TARGET)
|
||||
|
||||
Reference in New Issue
Block a user