The problem of finding a string that contains all particular substrings is the "shortest superstring problem"; it is NP-hard and analogous to traveling salesman problem. We use simple greedy search instead of trying to find true optimum. But even with these algorithm, units that use exactly the same delay times will always appear only once in the delay times table.
audio still a bit crackly; should probably decouple actual row ticking and rendering of audio (but how does that work with tempo ops?)
sequencer goroutine is a bit weird, too, should rethink
Delays and samples are not implemented yet and thus the tests are skipped, as these require parsing the delay and sample tables also. Various macronames were changed to be more sensible and consistent i.e. ATTAC was changed to ATTACK. GatesLow and GatesHigh was removed for the time being and the tracker will just have to know they are the SHAPE and COLOR parameters. SU_SPEED was changed to take a parameter so the parser picks it up.
The new format is to give either 5 or 6 parameters to SU_SEND, corresponding to local and global send, respectively. For example, a global send:
SU_SEND MONO,AMOUNT(128),VOICE(2),UNIT(0),PORT(1),FLAGS(SEND_POP)
The SU_SEND macro does the address packing into word.
Specifically, we will soon put the su_sample_offsets and su_delay_times table addresses to stack in the render_samples, to avoid hard coding them in the api call.
Nasm gives warnings about labels without colons in the end; these were particularly prevalent in struc members: ".size" has be ".size:". Nasm also wasn't happy with extra trailing commas when calling macros.
TBD: should the various []bytes be marshaled in a different way? Go defaults to base64-encoded strings but creating just plain JSON arrays with bytes could be more friendly to both humans and computers.
Sointu.asm / lib stuff lives at the root folder. There is a folder called "go4k", which is where
all go stuff lives. Following the ideas from https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1
the go4k folder is the "domain-model" of the go side, and should have no dependencies.
It contains Unit, Instrument, Synth interface etc. Putting go4k under a sub-folder is actually
in the spirit of Ben, as go4k adds dependency to the go language.
Bridge ties the domain-model to the sointulib through cgo. It returns C.Synth, but
makes sure the C.Synth implements the Synth interface, so others are able to use the
Synth no matter how it actually is done. MockSynth and WebProxy synth are good
prospects for other implementations of Synth.
It is a bit fuzzy where methods like "Play" that have no dependencies other than domain
model structs should go. They probably should live in the go4k package as well.
The file-organization on the Go-side is not at all finalized. But how packages are broken
into files is mostly a documentation issue; it does not affect the users of the packages at
all.
BTW: The name go4k was chosen because Ben advocated naming the subpackages
according to the dependency they introduce AND because the prototype of 4klang was
called go4k (there are still some defines in the 4klang source revealing this). go4k thus
honors our roots but is also not so bad name: it's the main package of a 4k synth tracker,
written in go.
This should make testing easier, as Synth can be assumed to stay the same
during each call. Synth is also the part that we can parse from .asm/.json file
and a Patch can be compiled into a synth. Synth can be eventually made
quite opaque to the user. The user should not need to worry about opcodes
etc.
The LOCALPORT and GLOBALPORT just get numeric parameters (unit, port) and (voice, unit, port), respectively, which should be now quite intuitive as most of the time the port index is one of the parameters visible in the .asm file. Only a few units have extra ports beyond transformed variables. Overall, this should make the parsing of the .asm files a lot easier.