670 Commits

Author SHA1 Message Date
36df18e2ae try making tiny link button next to each parameter 2024-09-22 09:31:13 +03:00
6aa6d8813c draft: move parameter unit conversions to UnitParameter table 2024-09-22 09:31:13 +03:00
964b2adbab further drafting 2024-09-22 09:31:13 +03:00
bd20440661 draft parameteter linking to vst 2024-09-22 09:31:13 +03:00
ce673578fd fix(amd64-386): crash with sample-based oscillator in 32-bit library 2024-09-22 09:30:42 +03:00
0e10cd2ae8 fix(amd64-386): sample oscillator hard crash
The sample-based oscillators converted the samplepos to an integer
and did samplepos < loop_end comparison to check if we are past
looping. Unfortunately, the < comparison was done in signed math.
Normally, this should never happen, but if the x87 FPU stack
overflowed exactly at right position, we then got 0x80000000 in
samplepos, which is equal to -2147483648. Thus, we considered that
sample is not looping and read the sample table at position
-2147483648, well out of bound. TL;DR changing jl to jb makes sure
we always wrap within to sample table, no matter what.

Fixes #149.
2024-09-22 09:04:47 +03:00
4ee355bb45 fix(tracker/gioui): DPI scaling of the numeric updown icons
Closes #150.
2024-09-21 14:01:32 +03:00
7d6daba3d2 fix(vm/compiler/bridge): empty patch should not crash native synth
Fixes #148.
2024-09-16 19:58:23 +03:00
2b38e11643 feat: include version info in the binaries 2024-09-15 19:45:00 +03:00
f8c522873c docs: update CHANGELOG.md for v0.4.1 2024-09-08 19:27:42 +03:00
e49f699f62 feat(tracker/gioui): clicking a parameter slider (etc.) selects it
Closes #112.
2024-09-08 14:46:24 +03:00
6924b63e02 test(vm): disabled units should not affect NecessaryFeatures for vm
Closes #140.
2024-09-08 11:22:05 +03:00
6fc9277113 fix(tracker): unit search gains focus when adding a unit on last row 2024-09-07 21:29:37 +03:00
877556b428 feat(tracker): do not wrap around when playing or moving cursor
The wrapping was usually unwanted behaviour. The user can use the
looping (Ctrl-L) to loop the song forever if this is really desired.
2024-09-07 18:52:52 +03:00
5e65410d27 fix(sointu): use proper modulo in SongPos
The previous implementations used remained, not modulo, which could
cause issues with negative values.
2024-09-07 18:45:14 +03:00
4e1fdf57d9 fix(tracker/gioui): advance row by step when inputting a note
Closes #144.
2024-09-07 17:45:32 +03:00
1daaf1829c fix(tracker): ensure numVoices of loaded instrument is ok 2024-09-07 15:25:06 +03:00
74972b5ff4 fix(tracker): ID collisions in ClearUnit and Instruments.unmarshal 2024-09-07 15:25:06 +03:00
9da6c2216c test(tracker): fuzz testing of ID collisions and file read/writes 2024-09-07 15:16:53 +03:00
61e7da5dab test(tracker): test loading presets in fuzz tests 2024-09-06 22:03:52 +03:00
59fb39d9b3 fix(tracker/gioui): move alert popups north to not overlay buttons
Closes #142.
2024-09-06 22:01:00 +03:00
9cb573d965 feat(tracker/gioui): cursor indicates split bars can be resized
Closes #145.
2024-09-06 20:29:33 +03:00
d46605c638 fix: assign new IDs to loaded instruments
Fixes #146.
2024-09-06 20:19:27 +03:00
569958547e fix(amd64-386): do not optimize away phase modulations with unisons 2024-08-17 11:06:18 +03:00
012ed10851 test: add unit test for unisons with phase = 0
This demonstrates a bug found by Virgill:
the x86 templates optimize away the phase
modulation when all phases are set to 0,
but the unisons need the phase modulation
internally to offset the phase of the different
unison oscillators.
2024-08-17 11:06:17 +03:00
5bc6dc6015 test(vm): test that disabled units do not affect results 2024-08-14 19:43:13 +03:00
350402f8f3 fix(vm): prevent crash when only disabled delay units & test it 2024-08-14 19:41:44 +03:00
75bd9c591e fix: do not include delay times from disabled delay units
Closes #139.
2024-08-14 15:41:13 +03:00
2667c3c72c docs: update CHANGELOG.md for v0.4.0 2024-08-10 15:29:49 +03:00
e09af5ab34 fix(tracker): loading preset did not update the ids
When a preset was loaded, its IDs were not updated,
causing ID collisions in the song and send targets
going wrong.
2024-08-10 15:20:25 +03:00
db2d9cac9d fix(vm): x87 native filter unit was denormalizing and eating up CPU
When voice was silent, the exponential decays in the filter unit
were causing the high pass component to eventually denormalize,
causing high CPU loads. The solution is the same as in the delay
unit: add and subtract a small number from the value, causing
essentially a flush to zero.
https://en.wikipedia.org/wiki/Subnormal_number

Fixes #68.
2024-06-19 18:58:20 +03:00
a14e21dff6 ci: macos-latest is now arm64 and breaks, use macos-12 for now 2024-05-05 13:19:25 +03:00
58916d3c6d docs: update README.md, to recommend using nasm instead of yasm 2024-05-05 11:37:42 +03:00
84d90cf0f3 fix(vm/compiler): use more yasm-compatible syntax
Closes #134.
2024-05-05 11:34:47 +03:00
10d20cd26f fix(vm/compiler): export as su_pow, instead of su_power
The export redefinition of label, even though the labels were on the
same line. This was an issue for yasm.

Related to #134.
2024-05-05 11:33:47 +03:00
4a8d4c5a29 fix(vm/compiler/templates): modulating delaytime in wasm could crash
The modulated delay time was converted to int with i32.trunc_f32_u.
This throws runtime error if the modulations caused the delaytime
to become negative, because _u implied that it should be unsigned
integer and negative numbers were out of range. Using
i32.trunc_f32_s fixed this.
2024-04-08 20:06:20 +03:00
f074c392f6 docs: add anticore to contributors 2024-04-08 19:05:20 +03:00
20fc12c529 feat(examples): add example demonstrating wasm playback in browser 2024-04-08 19:01:39 +03:00
6d4529971c feat(vm/compiler): export su_power function in case user needs it 2024-04-05 15:49:00 +03:00
beb84d7652 fix(tracker/gioui): deleting a cell in the order list did not work 2024-03-14 20:37:09 +02:00
c55b27b23b fix(tracker): recording creates empty track when no notes triggered 2024-03-10 20:01:13 +02:00
e488cd391b fix(gioui): scroll wheel works in tables, not just table row titles 2024-03-02 00:40:06 +02:00
7f20bd8baf fix(tracker): remember to tell player when m.d.Loop is updated 2024-03-01 23:54:19 +02:00
07bf8f6cdf fix(gioui): draw cursor in front of play marker in order editor 2024-03-01 23:31:05 +02:00
f0f391356c fix(gioui): arrow keys leave table row/col titles 2024-03-01 23:25:30 +02:00
b18a284252 feat(gioui): + and - keys add/subtract elements in tables
Closes #65.
2024-03-01 22:43:27 +02:00
1c020fffa3 refactor(gioui): update gioui to v0.5.0 2024-03-01 22:11:44 +02:00
267973e061 build: upgrade deprecated actions and fix warnings 2024-02-24 19:06:42 +02:00
6b3aaf6cc9 docs: update README.md 2024-02-24 15:34:40 +02:00
dfc72cd2c4 build: build VSTi instrument binaries also for linux 2024-02-23 20:15:44 +02:00
8a9cbdea62 build: update vst2 to latest version, because it compiles on linux 2024-02-23 19:56:09 +02:00
edee3452f4 feat(tracker): load presets from os.UserConfigDir()/sointu/presets/
This is related to #125, but is very crude way of implementing it.
2024-02-20 20:17:59 +02:00
b70db4d394 docs: add links to 21 and Tausendeins 2024-02-20 19:39:32 +02:00
d5af39e324 docs: add link to Phosphorescent Purple Pixel Peaks 2024-02-20 19:33:46 +02:00
aa1b4d371b fix(tracker): notify player that loop changed when resetting song 2024-02-20 19:28:59 +02:00
dc12f58082 feat(tracker): add ability to loop part of song during playback
Closes #128.
2024-02-20 19:10:15 +02:00
aa7a2e56fa feat(gioui): flip the unit parameter slider scroll wheel behaviour
Closes #112.
2024-02-19 21:49:51 +02:00
17312bbe4e feat: add ability to disable units temporarily
Quite often the user wants to experiment what particular unit(s) add
to the sound. This commit adds ability to disable any set of units
temporarily, without actually deleting them. Ctrl-D disables and
re-enables the units. Disabled units are considered non-existent in
the patch.

Closes #116.
2024-02-19 21:36:14 +02:00
2b3f6d8200 fix(tracker): unit searching to work more reliably 2024-02-17 20:54:46 +02:00
db6c9f6052 fix: warn user if sample rate other than 44100 Hz
Closes #129.
2024-02-17 19:45:36 +02:00
954b306cc8 docs: update CHANGELOG.md to have links to issues 2024-02-17 19:22:14 +02:00
aec756f921 feat(sointu-track): accept filename as command line parameter
Closes #122.
2024-02-17 19:17:47 +02:00
ca4a98eb50 fix(gioui): reduce the default height of popup menus so they fit
Closes #121.
2024-02-17 19:03:49 +02:00
65cfcb045c build: update setup-go to v5 and ask go version >=1.21.0 2024-02-17 18:28:25 +02:00
bb32403c78 build: require go 1.21 as it is needed by slices package 2024-02-17 18:22:31 +02:00
d92426a100 feat!: rewrote the GUI and model for better testability
The Model was getting unmaintanable mess. This is an attempt to refactor/rewrite the Model so that data of certain type is exposed in standardized way, offering certain standard manipulations for that data type, and on the GUI side, certain standard widgets to tied to that data.

This rewrite closes #72, #106 and #120.
2024-02-17 18:16:06 +02:00
6d3c65e11d fix(templates): avoid clobbering ebx in su_load_gmdls
Fixes #130
2024-02-16 20:09:20 +02:00
c08a319eb7 docs: add link to NR4's tool 2023-11-20 08:55:22 +02:00
8227691523 test: the filenames of test_gain and test_gain_stereo were flipped 2023-10-23 22:05:28 +03:00
04fbc9f6a7 feat(vm): add dbgain unit, where gain is defined in decibels
Closes #78
2023-10-23 21:57:29 +03:00
f698986718 docs: update CHANGELOG.md 2023-10-23 18:22:15 +03:00
a38a0f4235 fix(tracker/gioui): text.Shaper should not be a global variable
text.Shaper is not thread safe, which caused crash when adding
multiple VSTI plugins to a DAW project. This change fixes that
crash. Further refactorings need to consider where that text.Shaper
should actually reside.
2023-10-22 19:10:24 +03:00
3c85f1155c perf(cmd/sointu-vsti): avoid reallocations of events array
Always appending to the end and consuming from the front cause the
capacity of the slice regularly running out, resulting in new
allocation. With this change, we increment index when consuming
events and append to the end, and when we reset, we move index to 0
and empty slice. This way, we always reuse the allocated memory.
2023-10-21 10:47:26 +03:00
1040eb585d build: require go 1.19; did not build on go 1.18 2023-10-21 00:11:58 +03:00
6eb025d7ba refactor(tracker): remove unused variable RECOVERY_FILE 2023-10-20 18:41:21 +03:00
9ec8f48f82 feat(tracker): move unnecessary members from modelData to Model 2023-10-20 17:59:27 +03:00
391b14493c feat(tracker): undo entire modelData, not just Song
The modelData is moving towards clear meaning: it's the part of the
GUI state that is undone and also recovered from disk. This changes
the recovery data so that the undo and redo stacks are not undone,
but that is unlikely a good idea anyway, as it grows the recovery
data into unreasonable sizes.

This has also the nice benefit of undoing the cursor position, which
closes #64.
2023-10-20 17:59:26 +03:00
486bab4185 style(tracker): rename NUM_RENDER_TRIES to numRenderTries 2023-10-20 16:38:44 +03:00
1e47c5004c style(tracker): remove unused PlayerPlayingMessage type 2023-10-20 16:37:19 +03:00
900f1611b1 docs(tracker): add go doc comments to GmDlsEntry/-Entries 2023-10-20 16:36:09 +03:00
beb06727b0 refactor: move UnitNames to top level package 2023-10-20 01:59:30 +03:00
b6ec5d1a04 style(tracker): group code into less number of files 2023-10-20 01:50:38 +03:00
ff8e662857 refactor(tracker): move NoteStr and NoteAsValue to gioui package 2023-10-20 01:40:14 +03:00
a60814bab7 refactor(tracker): make struct to hold all per voice data in Player 2023-10-20 01:26:41 +03:00
0ce5ca3003 refactor(tracker): send Songs/Patches etc. from Model to Player 2023-10-20 00:54:03 +03:00
14a0306064 docs(tracker): add go doc comments to Player 2023-10-19 23:28:57 +03:00
d342fb860b refactor(tracker): put all recording data into struct Recording 2023-10-19 23:28:57 +03:00
453f45c48a refactor(tracker): rename SongPoint to ScorePoint etc. 2023-10-19 22:28:44 +03:00
50ccfe03da refactor(tracker): split Volume to PeakVolume and AverageVolume 2023-10-19 22:28:44 +03:00
1a8a317464 docs(tracker): improve package go doc comments 2023-10-19 22:28:44 +03:00
a9517f1511 docs: make the list of prods using sointu a markdown list 2023-10-19 14:30:01 +03:00
9073adadb3 fix(tracker/gioui): scroll bars move in sync with the cursor 2023-10-19 14:25:03 +03:00
b772940b1f fix(tracker/gioui): preset menu scrollbar fits on screen 2023-10-19 14:22:19 +03:00
d6abb14b08 feat(tracker/gioui): add scrollbars to menus 2023-10-19 14:07:09 +03:00
64270eaf68 refactor: rename FindSendTarget to FindUnit 2023-10-19 13:31:34 +03:00
43707e5fd6 style(vm): group public/private member types; delete unused types 2023-10-19 13:07:24 +03:00
fdad626279 style(vm): replace sointu.Unit{...} with {...} when allowed 2023-10-19 13:00:34 +03:00
960bddfae0 refactor(vm): use vm.GoSynther{}.Synth instead of vm.Synth
vm.Synth was used only in a few places, reduce the number of
exported functions. Also, if we ever add some global configuration
to GoSynther e.g. samplerate, we have a mechanism to do so, instead
of the Synth function.
2023-10-19 12:52:05 +03:00
7675121a78 style(vm): group public/private member types and rename privates 2023-10-19 12:47:38 +03:00
e28891abd5 refactor: move ConstructPatterns into compiler package
ConstructPatterns was never used except during compilation, so it
makes sense to have it closer where it is used. We could consider
making it even private function, as the pattern table construction
is quite specific to how compiler compiles and probably not that
reusable elsewhere.
2023-10-19 12:38:18 +03:00
e010b2da9d docs: improve go doc comments for vm package 2023-10-19 11:54:12 +03:00
98a73795c7 style: move Play and Synth to audio.go
With this grouping, everything that deals with AudioBuffers is in
Audio. song.go and patch.go do not know anything about AudioBuffers
or Synths.
2023-10-19 11:32:30 +03:00
5bbec75120 refactor: rename sointu.Render as AudioBuffer.Fill
The Render name misleading as it did not do the same thing as normal
Synth.Render, because it disregarded time limits. Conceptually, as
the function modifies the state of the synth, it would be better to
be synth.Fill(audioBuffer), but we cannot define methods on
interfaces; therefore, it is audioBuffer.Fill(synth) now.
2023-10-19 11:14:44 +03:00
ff4155a08e fix(tracker): notify player when recovery file is loaded 2023-10-19 10:59:07 +03:00
15a340317f docs: add go doc comments to 4klang conversion functions 2023-10-19 10:52:52 +03:00
b6815f70cb feat: remove unreleased parameter from Play function
The VMs now release all envelopes by default, so this mechanism was
useless / did not actually start them as unreleased even when you
thought they did.
2023-10-19 10:42:20 +03:00
9f7bbce761 refactor(vm): rename Encode to NewBytecode 2023-10-19 10:32:34 +03:00
01bf409929 refactor(vm): rename Commands/Values to Opcodes/Operands
The commands and values were not very good names to what the
byte sequences actually are: opcodes and their operands. In
many other places, we were already calling the byte in the Command
stream as Opcode, so a logical name for a sequence of these is
Opcodes. Values is such a generic name that it's not immediately
clear that this sequence is related to the opcodes. Operands is not
perfect but clearly suggests that this sequence is related to
the Opcodes.
2023-10-18 19:53:47 +03:00
87604dd92e refactor(vm): rename BytePatch to Bytecode 2023-10-18 19:12:34 +03:00
ccd283d2ea docs: update comments 2023-10-18 18:34:14 +03:00
0a67129a0c refactor!: rename SynthService to Synther and related types
The -er suffix is more idiomatic for single method interfaces, and
the interface is not doing much more than converting the patch to a
synth. Names were updated throughout the project to reflect this
change. In particular, the "Service" in SynthService was not telling
anything helpful.
2023-10-18 17:32:13 +03:00
e4a2ed9f32 style: group types into fewer, logical files 2023-10-18 15:02:25 +03:00
0187cc66ec refactor: move Wav and Raw methods as members of AudioBuffer 2023-10-18 14:40:16 +03:00
33625c6f40 fix(vm): stereo delay flipped taps for right and left channel 2023-10-18 13:54:26 +03:00
38e9007bf8 refactor: use [][2] as audio buffers, instead of []float32
Throughout sointu, we assume stereo audiobuffers, but were passing
around []float32. This had several issues, including len(buf)/2 and
numSamples*2 type of length conversion in many places. Also, it
caused one bug in a test case, causing it to succeed when it should
have not (the test had +-1 when it should have had +-2). This
refactoring makes it impossible to have odd length buffer issues.
2023-10-18 13:51:02 +03:00
bb0d4d6800 docs(tracker): update comments 2023-10-17 20:31:57 +03:00
b97d269cc4 build: update Gio to v0.3.1 2023-10-17 20:30:06 +03:00
192b31917a docs: update README.md 2023-10-17 15:07:31 +03:00
462faf5f4e feat: save recovery data to disk and/or DAW project 2023-10-17 10:26:36 +03:00
97a1b2f766 perf(tracker): use json recovery files instead of yaml for less garbage
The yaml marshaling and umarshaling seems to allocate a lot of memory. When saving the recovery file, the memory use jumped up by hundreds of megabytes. Switch to using json marshaling for the recovery file, as it does waste memory so badly. Binary marshaling was also an option, but its nice in emergency situations that the user can glance the recovery file and perhaps, with some effort, recover stuff from it. Json is good enough for manual recovery during emergency situations.
2023-10-15 11:11:26 +03:00
4899b027ff perf(tracker/gioui): use pointer receivers in numericupdown to avoid garbage 2023-10-15 09:49:30 +03:00
1a256b1f01 feat(cmd/sointu-track): add command line parameters for cpu & mem profiling 2023-10-15 09:07:22 +03:00
b455ef0f3c feat(tracker): add reverb presets for delay unit
The options are stereo, left and right. Similar to oscillator sample settings, if you tamper with these, it starts to show "custom". Used some of the generic features of go1.18, so had to update go.mod to require go1.18.
2023-10-14 14:58:38 +03:00
94589eb2eb feat(examples): add example playing sointu tracks from Python (#108)
* Added Python code example.
* Added pyinstaller build.
* Clarified debugging steps in README.md.
* Added linux implementation.
* Cosmetics.
* Updated README with correct steps.
2023-10-11 09:37:00 +03:00
f5eeabe5f3 fix(tracker/gioui): respawn window if VSTI accidentally closes it 2023-10-08 16:27:17 +03:00
61ebd89da0 fix(tracker): set PrevUndoType to "" when undoing and redoing 2023-10-08 15:59:33 +03:00
e5691d670a feat(vm): add frequency modulation for oscillators
Closes #105
2023-10-07 21:48:03 +03:00
12dd3dada0 refactor(vm): rewrote BytePatch Encode to use a builder struct
(cherry picked from commit fdf119e50ce62619f508cc423c2ebaa000a1d540)
2023-10-07 14:07:47 +03:00
8c8232f76e feat(vm)!: implement cross-instrument modulation of all voices
The "auto" was misleading, as it meant self modulation when targetting a unit within instrument itself and just voice 0 when cross-instrument modulation. This feature changes the "auto" meaning "self" for instruments self-modulating, and "all" voices for cross-instrument modulations. "all" is implemented by compiling a single send into multiple repeated sends, with only the last popping the stack (if necessary).

Closes #107
2023-10-07 14:07:39 +03:00
7ee43f199a fix(tracker): make sure undo & redo stack never grow beyond limit 2023-10-02 15:43:52 +03:00
048de55f00 fix(tracker): save recovery in GUI thread and reduce recovery size&frequency 2023-10-02 13:40:26 +03:00
905637eee3 update README.md: add links to prods using sointu 2023-10-02 11:15:15 +03:00
ce7c8a0d3e feat(tracker): add menu to load instrument presets
The presets are embedded in the executable, so there's no additional files.

Closes #91
2023-10-01 18:54:50 +03:00
b65d11cbb7 update CHANGELOG.md and README.md 2023-10-01 15:07:50 +03:00
df2605fddd feat(tracker): save recovery file regularly & load it on startup 2023-10-01 14:45:45 +03:00
12f15d1066 fix(tracker/gioui): make VSTI close event wait that gioui actually quit 2023-10-01 12:42:12 +03:00
e3c7d2cba4 fix(cmd/sointu-vsti): use different name and ID for native vsti plugin 2023-09-24 17:39:30 +03:00
545f32bcc3 release v0.2.0 and add automated releases to CI 2023-09-24 13:11:00 +03:00
ee2c83e2cb update CHANGELOG.md 2023-09-24 11:20:53 +03:00
00850c8001 code/text formatting and cleaning up whitespace 2023-09-24 10:47:54 +03:00
f35f948118 fix(vm/compiler/templates/wasm): add support for mono out
Adds also a test case to make sure mono out also works.
2023-09-24 10:27:34 +03:00
7df8103bf9 fix(vm): change crush resolution to bits (closes #79)
BREAKING CHANGE: The problem with crush was that it had very few usable values. This changes the crush to map the value nonlinearly, so the crush resolution is bits. Still the upper portion of the values is not very usable (bits 12-24 i.e. hardly any crushing), but at least the lower portion is usable. But now crush resolution has slightly different meaning.
2023-09-23 21:23:05 +03:00
1ac2ad3c75 fix(vm/compiler): invert the logic of the release flag in the voices (closes #102)
This makes all envelopes released by default, instead of attacking. Add also test to demonstrate the buggy behaviour.
2023-09-23 15:56:46 +03:00
20b0598a57 upgrade gioui to latest version 2023-09-23 14:43:09 +03:00
14e548c4c1 fix(tracker/gioui): CopyUnitBtn marshaled unit incorrectly 2023-09-20 14:57:23 +03:00
c692ff0f16 build: allow optional use of Crinkler when linking examples 2023-09-02 22:33:48 +03:00
b028fea59a build: make targets properly rebuild when templates or compiler changed 2023-09-02 20:14:52 +03:00
231e055faf fix(gioui/tracker): song files were not truncated when opened for writing (closes #103) 2023-09-02 14:32:23 +03:00
de3f4d987f fix(tracker/gioui): hitting enter/return to focus on the instrument name editor 2023-09-01 22:51:59 +03:00
8c59ea1b4c add ParamHintString for loadval.value showing range [-1,1] 2023-09-01 22:01:53 +03:00
98fedd0ed2 make ParamHintString show range [-1,1] for send.amount 2023-09-01 21:54:55 +03:00
607e5b5da0 Added x86 asm and C wav writer and player examples.
Specifically:
* Added win32, elf32 and elf64 asm player and wav writers using winmm.
* Added dsound player in C.
* Separated the ALL target and the examples; introduced a new examples target.
2023-08-31 14:15:52 +03:00
a439a4fa48 update README.md: credits
(cherry picked from commit 1d89dd0e99fdfce01fbee47e1d409118c4fa1ce2)
2023-08-31 13:06:45 +03:00
29a33a154b update README.md: add prod link for "Physics Girl St." 2023-08-29 09:27:04 +03:00
aba8ff2c85 CI: don't build examples as part of tests 2023-08-29 09:10:57 +03:00
d0efcc3001 Added usage examples in C; Added asm include file with track info to sointu-compile. 2023-08-29 09:09:02 +03:00
dff484739c feat(sointu): add better ParamHintString for in and aux unit channels 2023-08-28 23:10:11 +03:00
7dd2c246a0 feat(vm): add support for gm.dls samples in the go virtual machine (closes #75) 2023-08-28 22:44:37 +03:00
6ec06c760a CI: add builds for linux and macos (closes #82) 2023-08-28 16:26:15 +03:00
4135286ed0 update README.md 2023-08-28 13:42:14 +03:00
c7d79035ce fix: copying and pasting units messed selection and Ctrl-C actually cut 2023-08-27 16:05:11 +03:00
568aa1d76d update README.md 2023-08-27 14:54:14 +03:00
d82d151f49 fix: native synth building on go 1.21
go v1.21 is more strict about giving methods to C.structs and was complaining about "cannot define new methods on non-local type *C.Synth". The solution was a local type alias: type BridgeSynth C.Synth
2023-08-27 12:24:06 +03:00
c040bdedee fix: when just saving a file, open the file in write mode (fixes #99) 2023-08-27 11:29:55 +03:00
a0bcac3904 fix: check that MIDI triggered instrument is within patch limits (#98) 2023-08-27 11:10:54 +03:00
33221b5203 fix: upgrade to latest gioui (closes #97)
Latest gioui has the fix that enter key up event alone does not trigger a button
2023-08-27 10:59:11 +03:00
94926c5596 update README.md - add link to | by epoqe 2023-08-19 20:21:52 +03:00
61776f397a feat: add ability to select & move multiple units (closes #71) 2023-07-21 00:39:45 +03:00
5884a8d195 feat(tracker/gioui): add tooltips
Currently, only iconbtns and numeric updowns have tooltips. Closes #84
2023-07-19 22:31:29 +03:00
cafb43f8c8 feat(tracker/gioui): add ability to scroll parameter values (closes #92) 2023-07-18 23:28:20 +03:00
5a2e87982e feat(tracker): add ability to copy, cut and paste units 2023-07-18 17:17:50 +03:00
338529012a update README.md 2023-07-18 16:22:43 +03:00
ffb2f18c68 fix(cmd/sointu-vsti): upgrade vst2 package & request tempo properly from host 2023-07-18 10:37:32 +03:00
ccc8dc906f fix(tracker): guard for malformed songs in SetSong 2023-07-17 23:51:14 +03:00
c421748db9 fix: if fetching BPM from vsti host fails, keep the previous BPM as defined by the user 2023-07-17 23:26:11 +03:00
9db6ecb3da CI: build sointu-compile.exe as a part of the binaries 2023-07-08 16:44:00 +03:00
8ffe4a70dd feat(vm/compiler): embed templates to executable 2023-07-08 16:39:41 +03:00
d2ddba3944 fix(tracker/gioui): mouse clicks passed through the new unit button. closes #93 2023-07-08 16:07:17 +03:00
7af7d4332d change: do not respect polyphony when importing 4klang patches
Using polyphony 2 gave errors: 16 instruments with polyphony 2 + 1 global was a total of 33 voices and gave errors when sointu compiling. User will set anyway polyphony as needed for every instrument, like 1 for most instruments, so just use NumVoices 1 always.
2023-07-08 15:22:18 +03:00
9d6ca519a2 rename examples/fourklang to examples/fourklang_patches 2023-07-08 15:15:24 +03:00
3da62179e4 refactor(tracker/gioui): use gioui/x/explorer instead of home made file explorer 2023-07-08 15:12:45 +03:00
8c4f7ee61f refactor(tracker/gioui): update gioui to newer version 2023-07-08 11:57:19 +03:00
f5980ecb79 Update README.md 2023-07-07 01:44:01 +03:00
63fc3d0d08 Update CHANGELOG.md 2023-07-07 01:09:29 +03:00
9ef271f1a8 fix(tracker/gioui): display voice states crashed if somehow patch had more than 32 voices 2023-07-06 23:49:40 +03:00
cd00067da8 change(tracker): default delay to use BPM-tracking and make reverb similar to 4klang 2023-07-06 23:49:40 +03:00
248ba483c6 feat: add ability to import 4klang patches and instruments 2023-07-06 23:47:55 +03:00
c06ac6ea5e update README.md 2023-05-15 21:22:27 +03:00
a3dcc829c0 CI: rename binaries-zip to sointu-binaries-<hash>.zip 2023-05-13 18:43:20 +03:00
e7dbb0289c CI: add action to build artifacts 2023-05-13 18:05:52 +03:00
9efddd673d fix(tracker): when reassigning unit IDs, update send targets. fixes instrument loading 2023-05-13 17:56:13 +03:00
cd700ed954 feat!: implement vsti, along with various refactorings and api changes for it
The RPC and sync library mechanisms were removed for now; they never really worked and contained several obvious bugs. Need to consider if syncs are useful at all during the compose time, or just used during intro.
2023-05-13 17:56:13 +03:00
70080c2b9d fix(templates/wasm): $WRK was modified by stereo oscillators, messing up all modulations targeting units after the unit
add also tests to make sure we don't mess it up again
2023-04-06 15:03:16 +03:00
61c2e980a2 fix(templates/wasm): anyfunc should be funcref nowadays in .wat 2023-04-06 14:50:18 +03:00
6129076e97 upgrade ilammy/setup-nasm to v1.4.0 and wat2wasm to v1.0.29
wat2wasm doesn't support --enable-bulk-memory anymore, presumably because it is part of the standard nowadays
2023-04-06 14:50:18 +03:00
e73365b980 Merge pull request #87 from kendfss/master
fix: instrumenteditor starting expansion state
2022-04-07 14:06:58 +03:00
7eb473e67e fix: instrumenteditor starting expansion state 2022-03-23 21:45:09 +01:00
1a5251dbf6 refactor(sointu): change the name of AudioSink into AudioOutput
The interface is never used as anything else as Output so trying to generalize as something more vague like Sink made no sense.
2021-08-30 23:11:33 +03:00
eda48491e2 refactor(sointu): move engineeringTime helper function to the file where it is actually used 2021-08-30 22:27:38 +03:00
a8f8911f03 refactor(sointu): Change the signature of Play to accept SynthService instead of Synth
This is more logical as every single use of Play started with compiling the patch of a song with a SynthService.
2021-08-30 22:24:42 +03:00
a9b90c4db8 style: add comments to the public methods and members in the root package. 2021-08-30 20:34:56 +03:00
60e4518230 feat(tracker, gioui): make + and - keys adjust order numbers
Holding ctrl down while adjusting the order number keeps the song effectively same, but juggles pattern numbers. Useful for reorganizing song.
2021-05-15 14:19:46 +03:00
7885c306ee feat(tracker, gioui): make a Editor for inputting the unit type manually
The keyboard shortcuts were too wonky, so removed them altogether. Had to remove also unit wrapping from model (now it just clamps the parameter to the current units) as it did not play nice with the new editor.

Closes #70.
2021-05-13 19:50:23 +03:00
ede70380f2 feat(tracker, gioui): add menu item to remove all unused data from song
Reorders patterns and cuts them short and the order list short to remove all unused / unuseful (all holds) patterns.
2021-05-13 00:00:54 +03:00
8a94058d44 feat(gioui): make split bars snap to window edges 2021-05-12 23:14:48 +03:00
203e8a3ccc refactor(vm): simplify flattenSequence code 2021-05-12 22:44:03 +03:00
a2723829da refactor: implement Order and Pattern types: slices returning default values for out of bound indices 2021-05-12 12:08:55 +03:00
ce6e5d4942 tracker: move gmdlsentries.go generation under tracker/generate folder 2021-05-12 09:18:48 +03:00
1a89fee665 CI: don't test oto & remove libasound2-dev dependency
Installing this dependency failed in the cloud and caused tests to fail, so for now, we do not install it and do not test oto package.
The tests were actually about some float / int16 conversions, which should not anyway be in oto package, so future solution will be to refactor those functions somewhere else.
2021-05-08 17:34:16 +03:00
e9834110ec fix(bridge): respect the hard limit of 64 delay lines to avoid crashes. 2021-05-08 16:51:45 +03:00
e649b9ec54 fix(gioui): unnamed instruments on tracks with multiple voices crashed.
Closes #62.
2021-05-08 16:40:06 +03:00
d5f413c5dc Update CHANGELOG.md 2021-04-29 14:29:48 +03:00
5aa16b4a97 feat(tracker, gioui): add the ability to reorder / drag tracks in order list 2021-04-24 22:47:45 +03:00
442715334e feat(gioui): add grab cursor to DragList 2021-04-24 22:31:32 +03:00
d55e9e9880 fix(instruments): make transpose neutral in supersaw instrument 2021-04-24 22:10:55 +03:00
15cf8a750c Update README.md 2021-04-24 22:09:30 +03:00
b2b15f825d refactor(tracker, gioui): get rid of EditMode, use gio focus instead 2021-04-24 22:07:56 +03:00
e544e955cb refactor(gioui): move common button code to two functions 2021-04-20 18:21:21 +03:00
c0a0a5d501 refactor(gioui): move common iconbutton code to a function 2021-04-20 17:57:36 +03:00
8ba9fb1f00 fix(gioui): make editors lose focus when Escape is pressed. 2021-04-19 22:46:35 +03:00
56ceafdaa6 tracker: make a slightly more sensible default song 2021-04-19 22:19:51 +03:00
cbc07764a0 feat(instruments): add a few example instruments 2021-04-19 22:00:55 +03:00
40d4d6576e feat(sointu, tracker, gioui): add a comment field to the instrument 2021-04-19 21:24:29 +03:00
147e8a2513 feat(gioui): implement own file save / load dialogs
Removes the dependency on sqweek/dialogs, which was always very buggy.

Closes #12
2021-04-18 19:10:41 +03:00
ac95fb65c4 fix(gioui): prevent crashing when loading malformed song 2021-04-17 23:30:13 +03:00
485b783341 feat(gioui): add buttons to save and load instrument 2021-04-17 23:08:12 +03:00
2a9284473a feat(tracker, gioui): add little "*" symbol to indicate if a pattern is unique 2021-04-17 14:56:05 +03:00
1b4f1a8c5e feat(tracker): add menu item to export .wav
Also refactor the common functions for .wav export into base package so that both sointu-play and tracker can use same functions.
2021-04-17 14:24:05 +03:00
7893c1d1ed feat(tracker, gioui): add confirmation dialogs before quit/new/load song
This should avoid accidentally losing all work by destroying window.
2021-04-16 22:42:51 +03:00
f3cf4a52ce feat(compiler, wasm): do not hard code memory addresses to uninitialized sections
Rather, allocate unitialized segments as needed.
2021-04-15 23:24:58 +03:00
f330ccebf7 Update screenshot. 2021-04-13 13:05:16 +03:00
e9affe31ae Update README.md and screenshot 2021-04-12 20:42:32 +03:00
0767440e60 fix(tracker): kill all notes except effects when starting play / skipping play position
Fixes #45.
2021-04-12 20:15:55 +03:00
ce52aa0ee9 feat(tracker, gioui): add error message if vuanalyzer detects a NaN
Closes #50
2021-04-12 20:05:43 +03:00
68a50247bd feat(tracker): make shift + left/right take 1 octace / 12 semitone steps in oscillator transpose
Closes #37
2021-04-12 19:25:11 +03:00
b4705c941f feat(tracker, gioui): add visual indicators to show which instruments are playing
Closes #44
2021-04-11 17:51:34 +03:00
1eca428801 feat(gioui): add confirmation dialog when deleting instrument
Closes #5
2021-04-11 16:46:07 +03:00
a639e0c5e6 fix(gioui): in note editor, only step when user actually enters a note 2021-04-11 15:54:58 +03:00
8c7349de12 fix(tracker): prevent crashing when deleting notes without order list entry
Closes #59
2021-04-10 19:21:48 +03:00
4ce6abe1e8 fix(tracker): the mod function could return negative values with mod(-1,1)
Never copy-paste code from the internets
2021-04-10 19:17:38 +03:00
d04895144b feat(gioui): add scrollbar to the order list 2021-04-10 19:16:04 +03:00
847967c7b7 feat(gioui): add single letter track titles to order list 2021-04-10 18:09:20 +03:00
a44c27f4bb update gioui to latest version 2021-04-10 17:06:52 +03:00
58d29b19e9 sointu-compile: improve the printed help for command line options 2021-04-10 16:12:00 +03:00
9a6d92eefd feat(cmd): make current directory the default output directory in command line tools 2021-04-10 16:10:27 +03:00
f713133a0a feat(tests): test also gain parameter in envelopes 2021-04-10 15:58:02 +03:00
fc89973848 fix(tests): make test_renderer return 1 if not enough parameters 2021-04-10 15:14:19 +03:00
05e6f6da4e fix(tests): in test_renderer.c, print errors to stderr instead of stdout 2021-04-10 15:13:45 +03:00
f2f54c1579 optimize(templates): Use {{.DI}} consistently in the sinks to improve compression ratio. 2021-03-28 16:52:58 +03:00
9a798df55a optimize(templates): use pushf / popf to save & recall stereo bit, instead of bt [...] 2021-03-28 12:38:09 +03:00
d5d9f48d2d optimize(templates): use workspace instead of stack for filter temp var, results in less bytes & entropy 2021-03-28 12:37:26 +03:00
822cb7bac5 optimize(templates): replace fld / fmulp with a direct fmul 2021-03-27 16:35:58 +02:00
4c04f7a38c optimize(templates): use test ah or test al instead of test {{.AX}} in op_send 2021-03-27 16:03:47 +02:00
9b4608e31e feat(vm): construct minimal delaytime table using greedy matching
The idea is to find a minimal array that contains all the delay times and then point all delay times into this array.
2021-03-26 23:07:20 +02:00
763c4f5136 fix(templates): unison sample oscillators crashed on amd64 2021-03-24 23:49:14 +02:00
b0918e65ff fix(templates): add denormalization to compressor filter 2021-03-24 22:05:43 +02:00
0c2b1a3856 fix(templates): stereo oscillators were messing up WRK 2021-03-24 00:18:12 +02:00
c5972bc023 fix(vm): skip empty units when detecting what units are used 2021-03-24 00:17:10 +02:00
dfc864d131 optimize(templates): allow distort to flow into su_waveshaper (again) 2021-03-23 15:07:45 +02:00
8e55132ddd fix(tracker): the tracker has been displaying the musical names for notes incorrectly 2021-03-22 19:36:00 +02:00
cce99e6508 feat(vm): make the all empty pattern the zero pattern
Perhaps helps compression
2021-03-21 13:30:16 +02:00
4b90c1c50a optimize(templates): don't call compressor_mono if only using stereo compressor 2021-03-21 12:14:28 +02:00
d2f4d5d851 optimize(templates): only include lfo if it's actually used 2021-03-21 12:06:58 +02:00
3cbc500361 optimize(templates): don't use LEA in player, use MOV
Compresses better.
2021-03-21 11:46:51 +02:00
c28bacdfc7 feat(templates): remove clipping from waveshaper; user can clip manually if needed 2021-03-21 11:28:03 +02:00
452a2f6f04 feat(vm): reuse delaytimes if one has already been used before 2021-03-21 10:22:47 +02:00
eb61fcb130 fix(vm): parameters with default values (no key in the unit parameter map) were not considered to be used in featureset 2021-03-20 18:46:10 +02:00
42c9e045b7 feat: change the compressor unit to apply post-gain instead of pregain.
Pregaining ran into trouble: could not bring the signal level back to near 0dB. For example, with infinite ratio in the pre-gain system, the signal level was capped at threshold, which in turn ran into trouble with stereo signals.
2021-03-20 17:01:04 +02:00
76cf47a070 optimize(templates): inline calls to __imp__*File on x86
(cherry picked from commit e8bf9cb6467686ba35895094ab804360ab736b5f)
2021-03-20 16:24:53 +02:00
0f34674d7f feat(templates): remove etc/drivers from gm.dls to optimize size 2021-03-20 16:24:43 +02:00
38c0cea40f refactor(templates,tests): make sync an extern instead of parameter to render
This is to be able to use CreateThread with su_render_song; let's worry about multicore rendering sometime in the future.
2021-03-20 16:23:51 +02:00
8ef6de7ffd feat(tracker): add titles showing which instrument(s) belong to a track
Refer #43
2021-03-14 21:14:48 +02:00
5daf81f331 fix(tracker): avoid NaNs in volume analyzer better 2021-03-14 18:19:13 +02:00
b6283cd13e feat(tracker): add button to make note off and use "1" also as the key event
Closes #54
2021-03-14 18:10:29 +02:00
01226a2910 feat(tracker, gioui): add ability & button to delete tracks.
Refer #46.
2021-03-11 22:26:42 +02:00
87f373370e feat(gioui): add empty cell grid lines to order list
Refer #48.
2021-03-11 22:14:33 +02:00
8a5d337775 feat(tracker): auto-create patterns when adding notes to empty area
Closes #53.
2021-03-11 21:58:56 +02:00
adc12dde4f fix(tracker): when creating a new track, a pattern full of noteoffs was created
Creating such patterns is unnecessary and was a relic of the past. We can leave the order completely uninitialized and let the user fill it as needed.

Related to #54.
2021-03-11 21:45:00 +02:00
f9225d70a9 refactor(vm): extract polyphony bitmask calculation to its own function & document better 2021-03-10 09:34:23 +02:00
43ef6fa72c fix(sointu): fix sync data getting output from play & test it 2021-03-10 09:06:42 +02:00
df9713865f Update README.md 2021-03-10 00:08:09 +02:00
99dbdfe223 feat: add the ability to use Sointu as a sync-tracker
There is a new "sync" opcode that saves the top-most signal every 256 samples to the new "syncBuffer" output. Additionally, you can enable saving the current fractional row as sync[0], avoiding calculating the beat in the shader, but also calculating the beat correctly when the beat is modulated.
2021-03-09 23:52:33 +02:00
a3bdf565fd feat(templates/amd64-386): add define to tell if we are using float samples 2021-03-05 20:50:43 +02:00
b15de7f54a fix(templates): the polyphonic player forgot about one push and read stack wrongly 2021-03-05 09:07:47 +02:00
062180db1e update README 2021-03-04 18:05:18 +02:00
b7c326a0a7 update README & screenshot 2021-03-04 17:53:19 +02:00
185173c821 fix(vm): the tests were broken, but not code 2021-03-04 14:37:57 +02:00
cc80fe7317 fix(vm): patterns encoding was broken by the non-standard pattern lengths 2021-03-04 14:33:09 +02:00
c7448699b6 fix(gioui): disable file load / save dialogs in browser
This at least gets the program to compile into js as sqweek does not work in browser, but we really need to look for a long term solution. How to load & save songs in browser?
2021-03-04 11:21:20 +02:00
079d5a9ef1 feat(tracker): wrap cursor in the song instead of clamping it
Closes #49
2021-03-04 11:21:19 +02:00
0f942f73d9 fix(sointu): NumDelayLines did not take polyphony into account, resulting in panic 2021-03-04 11:16:05 +02:00
6d2b63a5e9 feat(sointu, vm): implement pure-Go interpreter for bytecode
The old "native" compiler bridged version is now started with cmd/sointu-nativetrack,
while the new pure-Go bytecode implemented bytecode interpreter is started with
cmd/sointu-track

Thus, you do not need any of the CMake / cgo stuff to run cmd/sointu-track
2021-03-03 23:55:58 +02:00
a035845b81 reorganize things into different packages 2021-03-02 17:19:45 +02:00
e46ece3648 feat(tracker): add rudimentary GUI for adjusting delay times 2021-03-01 20:42:37 +02:00
3e7064e166 refactor(templates, tests): rename C-header defines consistently with Score.go 2021-02-28 16:07:55 +02:00
048b36324c fix(tests): test_render_samples_api forgot to initialize struct
Sometimes crashed, if the unitialized struct happened to contain garbage.
2021-02-28 15:40:06 +02:00
248ca6e30b templates: optimize sources.asm size 2021-02-28 15:14:06 +02:00
adcf3ebce8 feat(sointu, tracker,...): restructure domain & tracker models
send targets are now by ID and Song has "Score" part, which is the notes for it. also, moved the model part separate of the actual gioui dependend stuff.

sorry to my future self about the code bomb; ended up too far and did not find an easy way to rewrite the history to make the steps smaller, so in the end, just squashed everything.
2021-02-28 14:24:54 +02:00
fd1d018e82 feat(tracker): adding and deleting order rows, also backward and forward deletes 2021-02-18 22:48:48 +02:00
a27494e17d feat(tracker): implement alerts that display useful notifications / errors
In particular, we show notification after the user has copied something to clipboard (#34) and when there is a patch compile error (#38).
2021-02-17 23:30:07 +02:00
319fc5e853 fix(tracker): stack labels display error whenever the stack is not exactly 0 2021-02-17 17:51:06 +02:00
18d466803f fix(sointu): fix StackUse calculation for empty unit (unit.Type == "") 2021-02-17 17:49:53 +02:00
2f0c9a9f04 tracker: improve the layout of unit editing buttons 2021-02-17 17:42:21 +02:00
692615c76d feat(tracker): add scroll bars to lists
Closes #8
2021-02-17 17:10:38 +02:00
12d5d392c5 tracker: only one "hex" checkbox in the tracker title bar
Closes #28
2021-02-17 17:10:38 +02:00
da6cc0a2b8 fix(tracker): only add NoteOffs when keyjazz key is released during notetracking 2021-02-16 23:30:59 +02:00
b095b799a0 feat(tracker): clicking on the parameter label when the parameter is already selected resets the parameter
Closes #17
2021-02-16 23:25:21 +02:00
d49e0a6bc8 fix(tracker): accept '<' and '>' keycodes for changing octave too
Probably fixes issue #13, but cannot test as I don't have a Mac.
2021-02-16 22:53:19 +02:00
b21bade6b5 tracker: make key.DeleteForward & key.DeleteBackward do same thing
Closes #9
2021-02-16 22:45:30 +02:00
c3788e1a24 feat(tracker): highlight beats / every second beat in the tracker
Closes #30
2021-02-16 22:42:32 +02:00
2853509d1d fix(tracker): CurrenParam / CurrentUnit were incorrectly updated
Closes #21, #20
2021-02-16 22:04:15 +02:00
09a9f072cc feat(tracker): copy instrument to & paste from clipboard
Closes #25
2021-02-16 21:45:25 +02:00
088bbc6c58 feat(tracker): add a rudimentary VU-meter to show master volume, peaks & clipping
Closes #16
2021-02-16 17:27:21 +02:00
962d0f1152 fix(tracker): when the track editor was scrolled, the jump pointer event regions were wrong 2021-02-16 17:27:21 +02:00
0377cd4287 fix(cmd/sointu-play): accidentally used := in inner scope, leading to nil error 2021-02-16 17:27:21 +02:00
803184cbe7 feat(tracker): add step parameter to advance cursor after edit
The step is currently in the song panel; might consider putting it somewhere else.

Closes #6
2021-02-16 17:27:21 +02:00
366a05c766 tracker: remove old unused code 2021-02-16 08:47:48 +02:00
f8ec857c16 CI: fix the wabt version to 1.0.20 2021-02-16 00:29:05 +02:00
c781c24ae6 feat(tracker): add F1-F8 shortcut keys for changing editmode / playing
Related to #14
2021-02-15 23:57:35 +02:00
25a4bfd5ac tracker: adjust the default split ratio to be more sensible
Closes #23
2021-02-15 23:31:00 +02:00
94205b9ab2 feat(tracker): implement more proper menus, with Undo&Redo
Closes #24
2021-02-15 23:05:06 +02:00
a470452e99 feat(tracker): add menu button for Paste
Closes #26
2021-02-15 19:30:18 +02:00
712a4c927b fix(tracker): clicking anywhere outside a menu closes it but does not trigger other action
Closes #27
2021-02-15 19:21:54 +02:00
070833ed9c feat(tracker): shortcut-N starts a new song project
Closes #29
2021-02-15 19:15:05 +02:00
83d6277ae6 feat(sointu, tracker): find the send targets ports easily and use this to figure slider maximums dynamically
There is a new helper function in Sointu to find the target of a send. In future, compiler and others should be refactored to use this function to find send targets.

Closes #31
2021-02-15 19:11:13 +02:00
0f136d544c fix(tracker): when instrument panel is clicked, only change EditMode when instruments
Changing to always EditUnits was causing unnecessarily going back from EditParameters.
2021-02-15 18:14:59 +02:00
e93190892b fix(tracker): reduce visual jitter when adjusting unit parameter sliders
The solution is not to force the slider value when the user is dragging it.

Closes #33
2021-02-15 18:11:36 +02:00
024245b780 fix(tracker): the unit type chooser list expands to the right
Also add helpful title label to explain what the unit type chooser does.

Closes #35
2021-02-15 17:57:04 +02:00
5f7eed4194 fix(templates/amd64-386, tests): fix global stereo sends and add regression test for future
the send asm code is quite ugly atm (pushf & popf to save stereo flag), but the new regression test should ensure we don't break it again if we eventually refactor it
2021-02-15 14:48:16 +02:00
c60f6e0f0e feat(tracker): make clicks change the focused panel 2021-02-14 21:32:27 +02:00
07052f2530 refactor(tracker): delete unused constants from theme.go 2021-02-14 20:35:38 +02:00
99d83472cc refactor(tracker): remove panels.go; panels are not used anymore 2021-02-14 20:21:17 +02:00
394e2834e9 refactor(tracker): make NumericUpDown use widgetForIcon instead loading icons by itself 2021-02-14 20:20:40 +02:00
24ebc99b92 refactor(tracker): move instrument related stuff from layout.go to instruments.go
the code related to handling instrument button actions definitely should be in instruments.go, not layout.go
2021-02-14 20:13:15 +02:00
7c810ac052 refactor(tracker): delete old unused code for making buttons 2021-02-14 20:10:02 +02:00
e2fcfbbc4a refactor(tracker): move C & D type shortcuts for layout.Context and layout.Dimensions to layout.go
layout.go is where the basic core of the layout should reside
2021-02-14 19:59:08 +02:00
cece2d77d4 feat(tracker): go generate parses gm.dls and show slightly more sane gui for them 2021-02-14 19:54:30 +02:00
4da225ec33 feat(tracker): allow copying and pasting songs to/from the window 2021-02-13 01:59:10 +02:00
11b5b5b322 fix(compiler): calculate unit target correctly in case there are missing units (type == "") 2021-02-13 00:29:15 +02:00
49456cb270 fix(tracker): update send targets when instruments/units are added/deleted/swapped 2021-02-13 00:28:06 +02:00
4ed259ff17 fix(tracker): voices are now released when the synth is recompiled
fixes nasty noises from all voices being triggered with note 0
2021-02-12 09:14:57 +02:00
d01657ab83 feat(tracker): add numeric up down to adjust number of voices per track 2021-02-12 08:43:27 +02:00
10f53bdbf7 feat(sointu): rewrote sequencer to add support for keyjazzing 2021-02-11 23:20:13 +02:00
b9c8218ca4 fix(tracker): numeric up down crashed when its height was small 2021-02-11 10:58:41 +02:00
8cfd915311 feat(sointu): add functions to figure out the stack use and need of a unit 2021-02-10 22:39:08 +02:00
35d2ff6308 feat(tracker): add panic button to quickly disable the sound & show when synth crashes 2021-02-10 21:59:29 +02:00
33bf5ebd49 feat(tracker): make + and - adjust the note pitch also 2021-02-10 18:51:03 +02:00
8f89bf7361 fix(tracker): show note octaves with letters in case the notes are out of numeric range 2021-02-10 18:44:29 +02:00
38008bdb87 feat(tracker): implement edit modes, resembling tab stops 2021-02-10 18:26:58 +02:00
7408956f77 fix(tests): update sample tests to use "samplestart" instead of "start" parameter 2021-02-08 20:21:26 +02:00
1d6a18a74c fix(sointu): fix the incorrect parameter ranges for samplestart and looplength 2021-02-08 19:30:53 +02:00
482dd614c9 fix(sointu): the parameter name should have been "samplestart", not "start" 2021-02-08 19:24:27 +02:00
de402eaece make sequencer use up all space available 2021-02-08 19:07:24 +02:00
bb43bf61a8 fix(tracker): the hit rects in Split had X and Y mixed up 2021-02-08 17:18:14 +02:00
cc2a5f3ad9 fix(tracker): "send" was missing from defaultUnits 2021-02-07 23:26:04 +02:00
4e1731f6e3 refactor(sointu): move parameter string conversion to song level
Some parameter values need the whole song or at least the unit to give accurate hint what the parameter means. For example: send needs to know the entire song to know what the target unit refers to.
2021-02-07 23:25:15 +02:00
af52aa9e51 feat(sointu): add functions to convert unit parameter values into human readable strings 2021-02-07 19:57:01 +02:00
56d8ca574e feat(tracker): improve unit parameter sliders: align, scrollable list & show values 2021-02-07 14:28:57 +02:00
5588d7ca7d feat(tracker): make instrument name editable 2021-02-06 23:39:58 +02:00
6c0cf6832e fix(tracker): clamp CurrentUnit to valid values when instrument changes 2021-02-06 19:15:06 +02:00
ef59c4a61a feat(sointu): add instrument name field and use it to name more sensible defaults 2021-02-06 19:10:37 +02:00
b34161b173 feat(tracker): make instrument names use draglist 2021-02-06 18:35:42 +02:00
73cbc4314f fix(tracker): clamp CurrentInstrument and CurrentUnit when song is loaded 2021-02-06 17:12:53 +02:00
207ae5195d feat(tracker): implement draggable list and make unit list use such 2021-02-06 16:28:32 +02:00
68fbb914cd add screenshot 2021-02-05 22:40:17 +02:00
c574b27d34 fix(tracker): when changing unit type, use tracker.SetUnit 2021-02-05 22:28:04 +02:00
5e7bd75b36 feat(sointu): add SynthService for recompiling the synth when needed 2021-02-05 22:21:46 +02:00
6307dd51de feat(tracker): adding, setting, unsetting and deleting units 2021-02-05 21:32:21 +02:00
29b289d2fb refactor(tracker): remove Contents from PopupStyle; pass it to Layout instead 2021-02-03 16:34:22 +02:00
21b620c824 feat(tracker): add numeric updown to choose number of voices for instrument 2021-02-03 14:53:12 +02:00
e25015a60b fix(tracker): update sequencer rowlength when entire song is set 2021-02-03 13:29:42 +02:00
b0dac8454d feat(tracker): add some shadow to popups 2021-02-03 13:25:45 +02:00
fc9a6b6517 fix(tracker): remove unnecessary go func(){...}() 2021-02-02 22:56:23 +02:00
14d4521f40 feat(tracker): move reset and load song into popup menu 2021-02-02 22:44:27 +02:00
95054c1877 upgrade to latest gio 2021-02-02 21:42:18 +02:00
9b160153c1 ignore debug file 2021-02-02 09:08:42 +02:00
3f494661e3 feat(sointu): add RowsPerBeat so non-power of 2 beat divisions are easier 2021-02-01 18:33:52 +02:00
3cf2fc70a8 refactor(tracker): change so that all icon initialization is a lazy & cache in iconcache 2021-02-01 17:57:13 +02:00
c667ffb4e1 feat(tracker): remove axis from NumericUpDown, allow dragging either Y or X 2021-02-01 13:53:10 +02:00
98c8d18a3e feat(tracker): add numeric updown to adjust RowsPerPattern 2021-01-30 23:22:31 +02:00
f3b21cc75f fix(tracker): update sequencer patch when instrument deleted 2021-01-30 23:03:44 +02:00
5033e8fa8e fix(sointu): remember to copy song.RowsPerPattern in .copy method 2021-01-30 22:59:03 +02:00
22c433b3e4 feat(tracker): add button for deleting instrument 2021-01-30 22:55:27 +02:00
6c97b5e736 feat(sointu): update synth instead of recompiling if no commands (units) change
this avoids the nasty clicking resulting from complete reset / recompilation of the synth, which was the previous case
2021-01-28 22:35:27 +02:00
61437db0d6 refactor(sointu): add explicit RowsPerPattern to the song 2021-01-21 13:16:41 +02:00
08dcbb9edb feat(tracker): add semitone & octave up/down buttons 2021-01-17 17:13:42 +02:00
eb36a96e29 feat(tracker): implement selecting a range in the tracker
also refactored a location in song to SongPoint, and a particular row in song into SongRow
2021-01-16 21:11:08 +02:00
8f9bf75613 feat(tracker): move track editor controls to top of the track editors 2021-01-16 14:45:05 +02:00
80d87dea8c feat(tracker): implement a numeric up down widget and use that for the numbers 2021-01-16 13:05:40 +02:00
f665a529e5 feat(tracker): add adjustable vertical split between top and bottom 2021-01-15 12:42:06 +02:00
c90f8efbdc feat(tracker): make clear song button to reset to default song 2021-01-15 08:17:10 +02:00
2378be5021 feat(tracker): change unit list into labels 2021-01-15 08:17:09 +02:00
a29f34734b feat(tracker): move new instrument button to the top right 2021-01-14 00:44:33 +02:00
ed67408d6e upgrade to slightly newer gioui, one before the breaking NRGBA API change 2021-01-13 22:55:24 +02:00
5124e0bf74 feat(tracker): move song related buttons to top and make the panel sizes adjustable 2021-01-13 18:37:20 +02:00
62ea87c709 feat(tracker): move the pattern sequencer to bottom left 2021-01-13 18:36:38 +02:00
5a69c14f61 feat(tracker): only show either notes or hex for a track + checkbox to toggle 2021-01-12 18:52:15 +02:00
dcb0877c71 feat(tracker): add buttons for increasing and decreasing song length 2021-01-11 21:19:27 +02:00
8b666064b2 feat(tracker): implement saving and loading a song file 2021-01-10 17:20:42 +02:00
5e76fabf21 feat(tracker): ctrl + number change the current pattern in sequencer 2021-01-10 16:38:53 +02:00
33bd91764c feat(tracker): make sequencer show properly cursor, current playing row & pattern marker 2021-01-10 16:11:29 +02:00
37185c98b3 feat(tracker): add surface color to instrument editor 2021-01-10 15:24:20 +02:00
fa893c94f1 feat(tracker): add simple instrument editor 2021-01-10 01:51:16 +02:00
e62fe85867 feat(tracker): disable buttons when they are not clickable 2021-01-09 23:06:16 +02:00
41cd1d21f6 feat(tracker): add thin line separating the controls from the tracker 2021-01-09 22:55:03 +02:00
6bdd212336 feat(tracker): move octave buttons to the bottom right 2021-01-09 22:37:25 +02:00
82771832ed feat(tracker): change tracker to more material.io style 2021-01-09 21:26:40 +02:00
eb25ddd864 feat(tracker): implement simple undo / redo 2021-01-08 22:00:15 +02:00
b1df5bb4d5 feat(sointu): add copy methods to structs 2021-01-08 21:37:31 +02:00
cbf9d34738 feat(tracker): add new instrument & new track buttons 2021-01-08 18:55:02 +02:00
e480622f57 feat(tracker): make color scheme dark gray 2021-01-08 16:11:18 +02:00
92ab035101 feat(tracker): add row number markers to the left 2021-01-08 15:36:11 +02:00
82d26b79a4 feat(tracker): add simple BPM & octave buttons 2021-01-07 19:25:16 +02:00
1d524b5815 fix(tracker): deleting and note off keyevents trigger redraw 2021-01-07 15:05:47 +02:00
148bea2827 feat(tracker): draw a slightly more reasonable cursor 2021-01-07 15:02:29 +02:00
f8103af43c feat(tracker): adjust color theme to purple 2021-01-07 14:31:50 +02:00
804b4e9c50 feat(tracker): add some inset border around the whole GUI 2021-01-07 14:15:14 +02:00
c032978f05 feat(tracker): make beveling follow tightly the edges of widgets, instead of maximum 2021-01-07 14:03:55 +02:00
8b23fb5c05 feat(tracker): hide playing row indicator when not playing 2021-01-07 13:15:57 +02:00
e7cd1b295b feat(tracker): allow user to move rows through song using arrows 2021-01-06 18:50:07 +02:00
492b2252bf feat(tracker): add pattern marks to tracker 2021-01-06 16:45:26 +02:00
91766e198d feat(tracker): show currently active pattern notes with lighter text 2021-01-06 15:35:14 +02:00
12e1bde2a2 feat(tracker): show notes for whole song, instead of single pattern 2021-01-06 15:14:48 +02:00
76dfd103e7 feat(tracker): ctrl + arrow move cursor entire pattern 2021-01-06 15:04:32 +02:00
37c09030bc feat(tracker): add dark lines separating UI elements 2021-01-06 14:52:36 +02:00
2b38297da2 feat(tracker): layout patterns in the top left 2021-01-06 14:25:17 +02:00
34eecd59f5 fix(CI): run tests on all packages that have tests 2021-01-05 19:47:58 +02:00
f88a74e44a fix(compiler): fix bss section macros on linux 2021-01-05 19:36:42 +02:00
1187c2a200 refactor(compiler): remove EncodedSong and pass patterns & sequences separately 2021-01-05 19:25:46 +02:00
69f236dbd3 fix(tests): wat-compilation was missing correct output filename 2021-01-05 18:30:47 +02:00
1be75362d0 refactor(tests): remove copying files to output directory; tests accept path to expected instead 2021-01-05 18:18:48 +02:00
588488ce54 feat(sointu): remove 16-bit output toggle from song; make it compile time option 2021-01-05 18:08:13 +02:00
30379c981d feat: remove hold from song
assume songs code it as 1 always; implementations are free to change this during compilation, but this should be a compile time flag / optimization; not a concern of song.
2021-01-05 15:50:27 +02:00
994c11e8db refactor(bridge_test): make all tests use the same functions to compare buffers 2021-01-04 18:02:54 +02:00
ccae4325c3 reformat .yml files 2021-01-04 17:51:28 +02:00
8b572515e0 refactor(sointu): in yaml, use flow formatting for Unit.Varargs 2021-01-04 17:51:12 +02:00
d328192834 refactor(compiler): split song encoding logic into smaller reusable functions 2021-01-04 13:57:01 +02:00
5dd81430b7 feat(sointu): make patterns local to track
The global pattern table is constructed only during compilation. At this point, we can do also all sorts of optimizations / changes e.g. remove unnecessary releases and reuse patterns if there's a pattern already that could be used.
2021-01-03 01:06:59 +02:00
06c006086b feat(tracker): Add a matrix showing track sequences 2021-01-02 17:40:53 +02:00
c68d9d3bf5 refactor(oto): reuse temp buffers for repeated calls to convert buffer 2020-12-31 16:24:34 +02:00
1d91603e36 feat(tracker): add keys to adjust current octave 2020-12-31 00:01:54 +02:00
2e2b5261ae feat(tracker): indicate release and hold with better symbols 2020-12-30 23:32:20 +02:00
c02c5c3c3d fix(asm/wasm): oscillator phase was causing rounding errors once large enough
gopher had fixed this, but we foolishly removed it. reintroducing fix, although this could be optional only for those who really care. ultimate size optimizers could still want to get rid of it.
2020-12-30 21:19:27 +02:00
7974f0ff82 fix(x86): denormalize delay damp filters
the damp filters, after input was switched off, cause the CPU to spike up and causing the tracker audio to start chopping
2020-12-30 19:50:38 +02:00
a69f0a1924 feat(tracker): Add keys for holding & releasing a note 2020-12-29 16:32:14 +02:00
29ba6b3658 feat(tracker): use slightly more interesting default instruments 2020-12-29 16:31:28 +02:00
cd498e775b refactor(tracker): Rewrote the sequencer loop to use simple mutex 2020-12-29 16:30:44 +02:00
8029dbd1a8 feat(CI): setup Webassembly Binary Toolkit in cloud to run wasm tests 2020-12-27 15:45:31 +02:00
e4490faa2e feat(compiler): Add support for targeting WebAssembly.
The working principle is similar as before with x86, but instead of outputting .asm, it outputs .wat. This can be compiled into .wasm by using the wat2wasm assembler.
2020-12-26 23:16:18 +02:00
7e4bcf18e4 Update README.md. 2020-12-18 22:51:32 +02:00
7f049acf88 feat(cli): Re-engineer CLIs, split play & compile
Play depends on bridge and compile on compiler package. Before, the compiler depended on bridge, but we could not use the compiler to build the library, as the bridge depends on the library. Also, play can now start having slightly more options e.g. wav out etc.
2020-12-18 20:25:49 +02:00
2d00640e06 Update README.md 2020-12-17 00:01:27 +02:00
358db1ca46 Update README.md 2020-12-16 23:56:07 +02:00
e6feed1e26 fix(go): Remove remaining references to go4k. 2020-12-16 21:39:23 +02:00
224b8dcb70 refactor(go): Move everything from go4k to root package sointu 2020-12-16 21:35:53 +02:00
d0bd877b3f feat(asm&go4k): Rewrote both library & player to use text/template compiler
There is no more plain .asms, both library & player are created from the templates using go text/template package.
2020-12-16 17:23:50 +02:00
2ad61ff6b2 feat(asm&go4k): Preprocess asm code using go text/template
The preprocessing is done sointu-cli and (almost) nothing is done by the NASM preprocessor anymore (some .strucs are still there.
Now, sointu-cli loads the .yml song, defines bunch of macros (go functions / variables) and passes the struct to text/template parses.
This a lot more powerful way to generate .asm code than trying to fight with the nasm preprocessor.

At the moment, tests pass but the repository is a bit of monster, as the library is still compiled using the old approach. Go should
generate the library also from the templates.
2020-12-14 15:44:16 +02:00
92c8b70fd2 refactor(tests): Save .yml in the repo; auto-generate .asm when needed 2020-12-09 13:48:19 +02:00
a03d46284c refactor(asm): Put a high alignment on the uninitialized sections so the pointers have less entropy. 2020-12-08 10:58:32 +02:00
41fa46e954 fix(asm/RECEIVE): Enabling stereo receive broke mono receive versions. 2020-12-08 10:58:01 +02:00
8ec3a1208b refactor(asm): Implement the Stereo IN opcode with less bytes & entropy. 2020-12-08 10:57:48 +02:00
2106ebde56 feat(sointu-cli): Support importing/exporting in YAML 2020-12-08 10:57:23 +02:00
fa163b3884 feat(sointu-cli): Add ability to adjust HOLD value of the patterns 2020-12-07 11:47:17 +02:00
fee637b02a refactor(go4k): Rename DeserializeAsm & SerializeAsm to ParseAsm & FormatAsm
Following the naming in strconv.
2020-12-07 11:14:46 +02:00
c75e54212b refactor(asmformat): Rewrite DeserializeAsm to take advantage of the consistent syntax in the .asm file.
It is now much shorter, which is probably a good thing.
2020-12-07 11:08:42 +02:00
1a633778bc feat(Song): Support HOLD definition, allowing using other values than 1 as the hold. 2020-12-07 09:01:53 +02:00
975a171d8c feat(sointu-cli): Glob directories also for .json songs. 2020-12-06 20:08:25 +02:00
9e4bee1b67 feat(asmformat): Remove special treatment of oscillator types to ease the parsing of asmformat
BREAKING CHANGE: They are now numeric values like all the rest macro parameters, instead of %defined constants.
2020-12-06 15:05:12 +02:00
1b1a4af5ea refactor(asmformat): .asm starts and stops with BEGIN_SONG and END_SONG which define all the magic defines and BPMs.
Now, every setting is visible to the user, so no need to guess magic defines.
2020-12-06 01:35:54 +02:00
e1e8d8cae3 refactor(asm): Remove unused MAX_SAMPLES macro 2020-12-05 23:19:59 +02:00
50ca02442d feat(bridge): Return sensible error messages from bridge and test that patches that should fail actually do. 2020-12-05 21:55:49 +02:00
cd95c5ae37 fix(libsointu): Return error as soon as possible, exiting the rendering loop immediately on error. 2020-12-05 20:53:22 +02:00
7bb60de74e feat(libsointu): make su_render return some error codes, typically due to FPU stack errors. 2020-12-05 16:41:07 +02:00
83937bb2ee fix(sointulib): Reset the FPU on each call to render, seems to take away the undeterministic behaviour. 2020-12-05 14:21:53 +02:00
e7ae775842 refactor(test_renderer): Allocate buffers statically instead of dynamically, so the tests are closer how Sointu will be eventually used. 2020-12-05 01:06:04 +02:00
06cb4c521c refactor(asm): Remove introspection.inc, it is not needed anymore. 2020-12-05 00:40:25 +02:00
6b67d6b544 feat(CI): Fix alsa.pc not found on ubuntu-latest. 2020-12-05 00:29:10 +02:00
d19d513ea8 feat(sointu-cli): Merge the asmfmt and sointuplayer to generic command line utility for processing song files.
Currently supports: playing, exporting .asm (reformatting), exporting .h, exporting .raw (raw float32 buffer), exporting .json.
2020-12-05 00:01:24 +02:00
726e79809d feat(sointu-player): If json parsing fails, try parsing it as .asm song. 2020-12-04 00:11:35 +02:00
efbcf1454e feat(go4k&sointu): Export .h C header files from the songs using go, also automatically during build for the tests.
The header files are automatically generated during build. No need to #define anything; everything is fixed by the .asm file. This adds go as a dependency to run the unit tests, but this is probably not a bad thing, as go is probably needed anyway if one wants to actually start developing Sointu.
2020-12-03 23:43:39 +02:00
a1e7e82d6d refactor(song): Remove song length from Song and assume the user knows MAX_SAMPLES
Trying to force a specific song length other than the default never quite worked, so we'll only support the default MAX_SAMPLES & will calculate it for the user in the user in the exported .h header file.
2020-11-29 22:12:29 +02:00
e2c6d4b70c fix(CI): Cgo linker flags stopped working.
They caused the tests to fail completely, but without them, the builds only give some warnings. So disabling them for now.
2020-11-20 22:54:33 +02:00
95c8c9c2b7 refactor(go4k): Remove all special treatment from samples and map Song 1-1 to what's in the .asm file.
Whoever uses it, probably wants their own Patch format, as now it is pretty cumbersome to work with sampleoffsets and delays, as the user needs to construct the delaytimes tables and sampleoffset tables.
2020-11-20 22:21:21 +02:00
f076409eb1 Update CHANGELOG.md 2020-11-17 00:12:10 +02:00
725f2096fe Commit go.sum to repository. 2020-11-16 23:59:30 +02:00
335d2af05b feat(asm&CI): Add support for macho-formats to header.inc and run tests also on MacOS.
Mac was giving errors about position dependent code, so had to add linker flag -Wl,-no_pie to ld & cgo.
2020-11-16 23:59:13 +02:00
bca34febcb feat(CI): Also run tests on win64.
win32 builds were giving errors so the tests are only ran on win64.
2020-11-12 21:26:24 +02:00
6d883f43ab fix(test_renderer): Add include <string.h> as linux builds were giving warnings for implicit declaration of memset. 2020-11-12 19:50:59 +02:00
1b1dabafb8 fix(asm): Change the scaling to 29 in the speed unti (29 increments = double speed).
The old speed scaling of 24 was ill-chosen so that triplets resulted in a minor buffer overflow error. This was never caught by anyone until Visual Studio 2019 in debug mode. Presumably all compilers allocate some extra space so this didn't matter. Now 29 increments = double speed and speeds with alternating 52 and 81 result in triplets that are just slightly faster then ordinary bpm i.e. the buffer will be slightly underrun, which probably is unnoticable to the user.
2020-11-12 19:46:37 +02:00
c39f434c6b feat(CI&go4k): Run go tests in cloud, skipping sample tests if on another platform than Windows. 2020-11-12 13:29:30 +02:00
a799ee2b6d Update README.md: add Tests/Passing badge. 2020-11-12 13:05:05 +02:00
68f97d301d feat(CI): Run ctests in the cloud during push. 2020-11-12 12:59:14 +02:00
cf6a5f6c0d fix(libsointu): Do not include samples at all when building on other than windows. 2020-11-12 12:58:50 +02:00
f7017892a5 refactor(asm&go4k): Remove special treatment from stereo parameters; it's now just one parameter in the Unit map. 2020-11-10 20:45:41 +02:00
01c39ffc15 format(tests): Autoformat all tests using the new asmfmt command. 2020-11-10 20:08:13 +02:00
90bb1aa61f feat(cmd/asmfmt): Implement a command line utility to import and re-export a song, effectively formatting it always identically. 2020-11-10 20:05:16 +02:00
377132321f feat(go4k): Implement .asm exporting. 2020-11-10 20:05:03 +02:00
5ceab766cc refactor(asm&go4k): Remove double SU_SEND macros, voice(0) corresponding to local send and voice(n) corresponding to global. 2020-11-10 00:53:06 +02:00
1c0ac08450 refactor(asm&go4k): Rename OSCILLAT and COMPRES macros to OSCILLATOR and COMPRESS.
Now the macro names correspond 1 - 1 to the unit names in go-side, allowing easier parsing.
2020-11-10 00:29:35 +02:00
788b3721fd Add missing sendpop to UnitTypes. 2020-11-10 00:20:57 +02:00
ae334a5dfe refactor(asm&go4k): Remove FLAGS from all units; they were the source of difficulty in parsing and fragile.
All units now take parameters according to flags. Only non-numeric parameter anymore is oscillator type.
2020-11-10 00:18:56 +02:00
e36aea59a5 feat(go4k): Algorithm to construct small delay times tables by abusing overlapping of different delay times.
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.
2020-11-09 22:29:10 +02:00
c153239710 feat(go4k): Document all the UnitTypes in a 'constant' table. Tells what parameters each unit takes. 2020-11-08 20:49:38 +02:00
bcbb5aaf19 feat: Delays and samples are now working through the bridge.
One should call bridge.Init() once during the initialization of the program to load the static sample table. On linux, bridge.Init() does nothing.
2020-11-08 16:03:10 +02:00
e65b08d2b3 fix(tracker): Change the "flags" parameter to "type", because this is what the bridge nowadays expects. 2020-11-08 14:19:54 +02:00
05899fc185 Merge branch 'draft/go-tracker' 2020-11-08 14:15:29 +02:00
d5886c0920 Change unison to be in the range of 0 - 3.
With this change, forgetting to initialize unison results in the default behaviour: 0 means one oscillator, 3 means four oscillators in unison.
2020-11-08 10:17:43 +02:00
b1ac141ea5 fix(tracker/sequencer): add a way to exit the sequencer loop 2020-11-08 04:27:52 +02:00
d30388a09a fix(tracker): fix invalid println 2020-11-08 04:22:00 +02:00
5e45e4f1f4 feat(tracker): hook up audio to tracker, we have liftoff
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
2020-11-08 04:17:21 +02:00
175bbb7743 fix(tracker/track): re-enable clipping of tracks 2020-11-08 02:48:52 +02:00
7a434f69fd fix(go/audio): fix audio.Player interface to have erroring Close()
not sure if this is actually required, though? shouldn't we just try to close and disregard errors?
2020-11-08 02:41:42 +02:00
9b6249a1a7 feat(tracker): implement basic tracker keys 2020-11-08 02:36:24 +02:00
77949bdc17 feat(tracker): implement basic track display 2020-11-08 02:24:27 +02:00
90c3536f3e feat(tracker): implement some basic styled ui building blocks 2020-11-08 01:20:53 +02:00
910bf42da9 Update README.md 2020-11-07 21:31:24 +02:00
9209aa1cba Implement .asm parsing in go4k, and run succesfully almost all tests/ through the bridge.
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.
2020-11-07 21:05:55 +02:00
64fe28a240 feat(tracker): create initial tracker skeleton using Gio 2020-11-07 19:50:37 +02:00
5eb7cef889 style(go/audio/oto): change error messages to be consistent 2020-11-07 19:38:58 +02:00
6e141f36c7 fix(go/audio/oto): clean up forgotten debug prints 2020-11-07 19:37:33 +02:00
551a7cb6c0 feat(sointu-player): implement a basic commandline tool to play songs 2020-11-07 19:34:46 +02:00
fa772ddd77 feat(go/audio): implement basic audio output with oto
splitting implementation into a separate package to potentially allow for other sorts of output, too.
2020-11-07 19:33:39 +02:00
41ce5d1efe Merge remote-tracking branch 'upstream/master' into draft/go-tracker 2020-11-07 17:27:11 +02:00
f584138572 Remove expressions from parameters, so the future .asm parser does not need expression evaluator. 2020-11-04 23:31:08 +02:00
df83001a64 Change delay macros to use FLAGS(NOTETRACKING) and FLAGS(NONE)
Previously it was + NOTETRACKING. This new way of using FLAGS(...) is more consistent with other macros, making the .asm format easier to parse.
2020-11-04 23:29:16 +02:00
d99cfd92d9 Change LOCALPORT and GLOBALPORT macros so that SU_SEND commands are easier to parse.
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.
2020-11-04 23:11:51 +02:00
4eaa54ecee Update LICENSE: Fix whitespace. 2020-11-02 23:14:01 +02:00
ccb6434fac Implement compile definition RUNTIME_TABLES, which enables putting the pointers to delay and sample tables to stack.
Useful for the eventual API to be able to modify the delay and sample tables during runtime.
2020-11-02 23:10:33 +02:00
c7c752cd73 Change the stack rewind in the end of render to be slightly less fragile, anticipating putting more stuff in the stack.
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.
2020-11-02 23:10:33 +02:00
b94bb79366 Update README.md 2020-11-02 22:43:15 +02:00
dc88b885e9 Fix warnings when built using nasm.
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.
2020-11-02 22:31:22 +02:00
eb37d8123d Change include path in CMake file to point to include/ instead of include/sointu/ 2020-11-02 21:37:22 +02:00
9544a130ab feat(song): add basic JSON marshaling/unmarshaling tests to make sure everything gets marshalled properly
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.
2020-11-02 16:36:54 +02:00
e0a793ea6d Reorganize the project folder structure and how go packages are organized.
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.
2020-10-31 22:05:47 +02:00
23e8bc0c5f Remove bridge.newSynthState & add 1 to RandSeed during Render calls, so now an empty struct corresponds to the Sointu default behavior. 2020-10-28 20:03:21 +02:00
8183c698da Separate Synth and SynthState: SynthState is the part that Render changes.
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.
2020-10-28 19:47:59 +02:00
64afa9fb48 Change the C-API to roughly match the new Go-API.
The parameter order is now so that all the in/out int parameters are in the end of the signature.
2020-10-27 21:58:56 +02:00
5f4b85b0a4 Change the Go API to have two versions: Render(buffer []float32), which always fill the whole buffer, and RenderTime(buffer []float32,int maxtime), which ends either when the buffer is full, or modulated time is reached. 2020-10-27 17:26:08 +02:00
7a9ac3489b Add polyphonism support to bridge.go 2020-10-26 13:06:50 +02:00
1d07b4f192 Change the .asm song format so it's a bit easier to parse, by replacing PORT and GLOBALPORT macros with LOCALPORT and GLOBALPORT.
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.
2020-10-26 12:55:15 +02:00
f495b0575a Fix bug in song.go: the note was pulled from the song data incorrectly. 2020-10-26 12:55:14 +02:00
debeaa181c Fix bug in song.go: len(s.Patterns) should have been len(s.Tracks). 2020-10-26 12:55:14 +02:00
470ba28592 Change the Render function in bridge.go to return a tuple of: number of samples rendered; bool indicating if rowend was reached; and a possible error.
The callbacks are gone; the row looping is the job of the user which is probably better for everyone.
2020-10-26 08:30:43 +02:00
acab824523 Update README.md 2020-10-24 23:36:56 +03:00
6c90ba2067 Implement a song struct to hold all the information of a single song (corresponding one .asm file) and Render function for it. 2020-10-24 23:25:23 +03:00
be7a4e21f3 Optimize asm player size, removing one unnecessary instruction. 2020-10-24 22:07:58 +03:00
3bb3e5c88e Fix su_render_samples to return correct values when built in 32-bit. 2020-10-24 17:04:27 +03:00
aa133b4606 Change bridge.go so that there is just SetPatch(...) function, instead of having to SetCommands, SetValues etc.
Now the patch definition in bridge_test.go and test_envelope.asm appear quite similar, so it's clear how they are related.
2020-10-24 16:15:15 +03:00
1abc6f22d5 Change the Go bridge API to more idiomatic Go, offering a callback when the row advances. 2020-10-24 14:39:10 +03:00
6e85ff674a Change the sointu.h api to return -1, 0 or n>0 depending if buffer is full and/or row ended.
test_render_samples_api.c was added to test the api. bridge.go was modified to reflect that there is no need to check for row manually; su_render_samples already returns the information if a row has ended.
2020-10-24 13:00:08 +03:00
c9e8000c5f Remove the cmake magic to create bridge.go from bridge.go.in.
The bridge.go now just assumes that the library you want is built in the build/ directory. It's probably a lot better idea than using wherever the latest build was; this way the same build is always used for the library.
2020-10-23 00:04:54 +03:00
163af33c9b Add .cache/ to .gitignore. 2020-10-22 23:31:05 +03:00
896e7e70b1 Add Opcode type to bridge, and pull the opcodes from the cgo side. 2020-10-22 23:29:37 +03:00
af75dd38aa Add common build folder names to .gitignore. 2020-10-22 21:19:14 +03:00
95b70018cc Fix all CMake tests passing on MinGW: consider minor (< 1e-6) errors in waveform shape successes.
Such errors are due to floating point rounding errors.
2020-10-22 21:19:14 +03:00
b9ec015b4a Document MinGW build commands in README.md. 2020-10-22 21:19:14 +03:00
7aac3917b7 Implement a bridge to call Sointu from Go language.
The main interface is render_samples function, which renders several samples in one call,
to limit the number of calls from Go to C. This is compiled into a library, which is then
linked and called from bridge.go.
2020-10-22 21:19:13 +03:00
af14cd310b Change .asm files that are actually only ever included into .inc-files, and rename all files as _header.inc & _footer.inc, depending where they are included. 2020-10-21 11:01:09 +03:00
06e8365c06 Update README.md 2020-10-21 09:50:19 +03:00
7e3dc19c83 Add inverse gain to compressor. The inverse gain is applied to the signal before any compressor calculations. 2020-05-27 18:54:37 +03:00
c5b6e6e28c Move su_load_gmdls into the responsibility of the intro to call, anticipating multicore rendering so it is called once before all the cores are spun up. 2020-05-27 18:54:34 +03:00
200937aa50 Fix single shot samples: only first half of them was getting played. 2020-05-27 16:21:49 +03:00
8956f524c9 Only compile introspection.asm when SU_USE_INTROSPECTION is defined. 2020-05-27 16:04:52 +03:00
45e554a9f9 Fix yasm warnings about flags being ignored on section redeclaration. 2020-05-27 13:17:28 +03:00
5e05057240 Fix builds and tests to pass on Linux.
Builds on both 32-bit and 64-bit executables and all tests (except gm.dls stuff obviously, which was excluded) pass on 64-bit Linux. Cannot test the 32-bit executables, as WSL does not support running 32-bit.
2020-05-27 10:54:37 +03:00
b64723323f Move player.asm back to sointu.asm, as they were getting again pretty intertwined. 2020-05-26 21:36:06 +03:00
e049bf2dce Change loadnote to load values from [-1,1], to allow using notes for both positive and negative modulations.
Also change SPEED to take this change into account.
2020-05-26 19:21:35 +03:00
3cdada41e0 Rename labels in envelope into more sensible. 2020-05-26 18:34:47 +03:00
ceae6ffcba Clean up the op_advance code&comments and remove one unnecessary jump. 2020-05-26 18:13:16 +03:00
91b8912015 Rename all SU_BEGIN_* macros into BEGIN_*; there's no real risk of nameclash and makes the code more readable. 2020-05-26 17:45:37 +03:00
efc6db71ab Reverse the logic of USE_SECTIONS (it's now DISABLE_SECTIONS) and then remove unnecessary defines. 2020-05-26 17:30:50 +03:00
3b10476dc2 Remove unused strucs / struc members; in particular: .params /.ports. 2020-05-26 16:35:19 +03:00
cf86a951f5 Move all constants into the end of sointu.asm, littering them around started getting messy. 2020-05-26 16:30:57 +03:00
35b8253776 Delete CONCATENATE macro - it is not used anymore. 2020-05-26 14:25:15 +03:00
dac5afea60 Implement IN, OUTAUX and AUX opcodes, to conveniently input from or output to global ports. 2020-05-25 23:23:24 +03:00
17c6afceb4 Fix bug that su_env_map was not compiled when using only compressor, and rename it to su_nonlinear_map. 2020-05-25 20:45:36 +03:00
1f92373a63 Limit compressor stack use. 2020-05-25 20:39:10 +03:00
1eb6974d5d Optimize compressor size. 2020-05-25 20:29:34 +03:00
55d9ca0ffc Reverse the voiceno counter: now it starts from MAX_VOICES and decrements until 0. This way, the VM needs not know anything about MAX_VOICES. 2020-05-25 17:23:54 +03:00
a193b8b1ef Inline transform_values into the VM, leading to a slightly more efficient register use. 2020-05-25 16:59:15 +03:00
3198452b9c Add a change log. 2020-05-25 14:14:13 +03:00
33d83d29a5 Update project description & version. 2020-05-25 13:58:29 +03:00
8d0ae21fb6 Remove separate playerstack and clean up the code. 2020-05-25 13:44:30 +03:00
7de7b49e24 Change apply to "do" and add brackets. 2020-05-25 13:44:29 +03:00
2c6f4f44d5 Use some of the unused space of synth object for curvoices. 2020-05-25 13:44:28 +03:00
457c1fdc32 Move things to stack, anticipating support for multicore rendering. 2020-05-25 13:44:28 +03:00
5c25eacd08 Optimize delay for better register use. 2020-05-23 21:06:58 +03:00
da52c10f7f Get rid of transformed values and use the header of the voice for that; saves _CX completely for the opcode. 2020-05-23 21:06:57 +03:00
79b384a0d6 Clean up comments and some defines. 2020-05-23 16:02:29 +03:00
bd005d52a7 Clean up whitespace. 2020-05-23 15:09:32 +03:00
6f06306f0c Re-engineer delay, to use stack for the delay WRK pointer and to support note-syncing transpose. 2020-05-23 15:05:38 +03:00
afbff66e36 Use strucs for stack locations, instead of hard-coding them everywhere. 2020-05-23 14:56:06 +03:00
654e5868bc Implement support for 64-bit builds.
The implentation is through a few macros to handle the fact in 64-bit, all addresses have to be loaded first to register and only offsets are ok. Also, push only supports 64-bit registers in 64-bit, so we have _AX, _BX, _CX etc. defines, which are eax, ebx and ecx on 32bit and rax, rbx and rcx on 64bit.
2020-05-21 17:18:18 +03:00
6f7fed4c6b Move jnc *_mono, ..., *_mono: code from function bodies to the stereofilter helper. 2020-05-20 08:49:23 +03:00
dc99157fbb Implement unison oscillators: multiple versions of slightly detuned oscillators that are added up to make a signal. 2020-05-19 22:52:21 +03:00
adc4a6e45f Implement sample-based oscillators, with sample import from gm.dls. 2020-05-19 18:29:47 +03:00
77b989d88d Optimize size. 2020-05-18 16:25:20 +03:00
666fd385d1 Fix bug in SEND STEREO. 2020-05-18 16:23:49 +03:00
5d1145be39 Improve README. 2020-05-17 16:48:28 +03:00
fc0ad4c011 Implement compressor. 2020-05-17 16:37:08 +03:00
71a5a18257 Implement player speed modulation opcode for triplets and such. 2020-05-17 09:51:20 +03:00
15717557f1 Split polyphony test into two tests. 2020-05-17 08:32:35 +03:00
f06810d956 Optimize size. 2020-05-17 01:24:38 +03:00
3b33b4e4d2 Improve README. 2020-05-16 23:27:30 +03:00
d87d2e22cf Implement new effect: bit-crusher.
Maybe a combined hold/bit-crusher effect is needed someday.
2020-05-16 23:27:29 +03:00
6a0a2fc36c Optimize the implementations of gain and invgain. 2020-05-16 23:23:05 +03:00
ac5b4dd496 Make clip opcode working and add regression tests to it. 2020-05-16 22:49:59 +03:00
5760f78201 Implement gain and inverse gain effects, for the moments when you just need them. 2020-05-16 22:29:08 +03:00
e966bc0084 Improve README. 2020-05-16 21:57:32 +03:00
87264c443c Add tests for opcode stereo variants, squashing several bugs in the process. Implement receive opcode to test stereo sending. 2020-05-16 21:23:41 +03:00
f9388b028a Rename test files to represent better the new opcodes they correspond to. 2020-05-16 18:32:56 +03:00
42ebc52c96 Remove trailing spaces and convert tabs to spaces. 2020-05-16 09:16:23 +03:00
d328431413 Improve README. 2020-05-16 08:54:55 +03:00
78d4cd50e8 Rewrote most of the synth to better support stereo signals and polyphony. VSTi removed as there is no plan to update the VSTi to support the new features.
The stereo opcode variants have bit 1 of the command stream set. The polyphony is split into two parts: 1) polyphony, meaning that voices reuse the same opcodes; 2) multitrack voices, meaning that a track triggers more than voice. They both can be flexible defined in any combinations: for example voice 1 and 2 can be triggered by track 1 and use instrument 1, and voice 3 by track 2/instrument 2 and voice 4 by track 3/instrument 2. This is achieved through the use of bitmasks: in the aforementioned example, bit 1 of su_voicetrack_bitmask would be set, meaning "the voice after voice #1 will be triggered by the same track". On the other hand, bits 1 and 3 of su_polyphony_bitmask would be set to indicate that "the voices after #1 and #3 will reuse the same instruments".
2020-05-16 08:25:52 +03:00
5c1b87f254 Improve comments for UpdateInstrument 2020-05-04 20:19:58 +03:00
6be7959cd1 Refactor the waveshaper function to save some bytes. 2020-05-03 17:02:08 +03:00
3c3fe6caf8 Improve comments and formatting. 2020-05-03 16:34:39 +03:00
212951c75d Make tests rebuild when 4klang.asm and 4klang.inc are changed. 2020-05-03 12:50:42 +03:00
9546574f13 Add regression test for AUX output. 2020-05-03 11:21:09 +03:00
c63dfd74f9 Make transform macro definition slightly more readable. 2020-05-03 11:12:53 +03:00
53a1be9b61 Refactor all values to have a universal support for modulations.
The modulation is now always added during value transformation.
With this, a lot of *_MOD defines could be removed.
The waveform for some tests changed slightly, because when the
value is saved to memory after modulating it, there is some
rounding errors.
2020-05-03 10:41:24 +03:00
0c08f3d41c Remove unnecessary short jump. 2020-05-01 09:34:17 +03:00
8dc7a9b5a0 Fix some name manglings. 2020-05-01 09:31:36 +03:00
405ef66b31 Remove unnecessary code from Power-function.
Also, improve comments.
2020-05-01 09:18:10 +03:00
660da68a48 Add regression test for polyphony (MAX_VOICES = 2). 2020-05-01 08:51:43 +03:00
f97cea2a17 Refactor 4klang to use cross-platform defines and 4klang.asm & .inc to work more like .c and .h. 2020-04-30 13:36:22 +03:00
771c0b96e3 Put back 8klang builds. 2020-04-30 13:08:37 +03:00
09c497fef6 Add regression tests for delay modulations. 2020-04-25 11:29:14 +03:00
7170b049d3 Add regression tests for VCF opcode and its modulations. 2020-04-24 22:51:42 +03:00
4b9b1710eb Add regression tests for delay (DLL) opcode. 2020-04-23 20:06:41 +03:00
a49fba060c Add regression tests for distortion, including sample-and-hold and modulations. 2020-04-18 21:21:21 +03:00
41222b09a7 Move all raw audio files related to tests into subfolders, to have slightly more clean folder structure and to avoid mixing source files and data files. 2020-04-18 19:47:16 +03:00
886ee85a09 Improve CMakeLists.txt for tests, so it is easier to define test prerequirements.
Also added a few missing prerequirements.
2020-04-18 13:16:33 +03:00
d9f4def1d4 Add regression tests for vco modulations (cm, dm, fm, gm, pm, sm and tm) 2020-04-17 19:36:09 +03:00
cc2babde9c Add regression test for envelope modulation. 2020-04-17 18:21:37 +03:00
462521518f Add regression tests for FST and FSTG opcodes. 2020-04-16 22:05:50 +03:00
9c7db45a46 Rewrote parts of the test renderer to read the whole data from disk in one fread. 2020-04-16 14:05:17 +03:00
374be5256e Add regression test for VCO opcode, lfo variant. 2020-04-16 13:37:30 +03:00
83e3ab165e Add test for 16-bit output, also moving the testname for test_renderer into compiler definition to avoid rewriting it everytime. 2020-04-15 23:17:03 +03:00
cff4538b8c Make the CMakeLists.txt for the tests a slightly more sensible; the data files are copied after every build if they are newer. 2020-04-15 21:43:22 +03:00
d6798bdae3 Add regression test for VCO opcode (oscillator) for testing stereo sound creation. 2020-04-14 23:37:15 +03:00
34a98ebc4a Add regression test for VCO opcode (oscillator): gate, noise, pulse and trisaw variants. 2020-04-14 23:11:10 +03:00
38499e01bb Add regression test for VCO opcode (oscillator), sine wave variant. 2020-04-14 22:23:09 +03:00
35b2df2a2f Require CMake version 3.15, as the Visual Studio statically linking runtime policy was introduced in it. 2020-04-14 21:44:45 +03:00
ce81ef5ef9 Add regression test for FOP opcode, loadnote variant. 2020-04-14 21:44:05 +03:00
398543d67c Add regression tests for FOP opcode: add, addp2, mul, mulp2, push and xchg variants. 2020-04-14 18:08:57 +03:00
e790549d27 Add regression test to test fop opcode / addp, mulp and pop variants. 2020-04-13 19:10:46 +03:00
08518a9527 Add regression test to test multiple instruments. 2020-04-13 17:50:09 +03:00
b1ba5e9e6b Add regression test to test panning opcode. 2020-04-13 17:34:46 +03:00
f33da76d1e Add regression test to test load opcode. 2020-04-13 17:18:26 +03:00
1f0fdfc30e Improve and rename envelope test. The test focuses on GO4k_ENV opcode only and does not use panning. 2020-04-13 16:53:11 +03:00
2bee9edd0b Quick fix so that global store opcode is exported as 12 when glitch is not used. 2020-04-12 22:14:28 +03:00
8d984cbc38 Implement ctest unit test, first test simply testing that envelope works as it used to. 2020-04-12 22:05:39 +03:00
e180694d9e Switch to CMake for builds and reorganize the source directories. 2020-04-12 22:05:38 +03:00
e285541203 Merge pull request #3 from kebby/master
Added getChunk/setChunk to VSTi so patches are stored with the project
2019-08-17 20:23:53 +02:00
175b49bc3a Merge pull request #1 from petersalomonsen/petersalomonsen/osxplayer_rendersingletickwithauthoringflag
Mac OSX player and Single tick rendering
2019-08-17 20:17:56 +02:00
391f826de9 Added getChunk/setChunk to VSTi so patches are stored with the project 2019-08-17 17:16:05 +02:00
ccecfc1898 Mac OSX player and Single tick rendering
- Use SINGLE_TICK_RENDERING mode for rendering one tick per invocation of
 _4klang_render
- Example for running player on Mac OSX
2018-12-03 14:22:43 +01:00
b06829eab1 Update README.md 2018-10-29 08:55:57 +01:00
449801b85b Merge branch 'master' of https://github.com/hzdgopher/4klang 2018-10-28 22:18:39 +01:00
7d758d6d66 version 3.2.2
- legacy fix for global sections save/load memory out of bounds access
- fixed delay index fuckup during export when skipping instruments with delay mode "note sync"
2018-10-28 22:18:13 +01:00
86828062e8 Create LICENSE 2018-04-02 22:48:13 +02:00
d1f776b473 Merge branch 'master' of https://github.com/hzdgopher/4klang 2018-03-16 19:18:56 +01:00
ced4a2b7b9 fixed bug in distortion when using stereo and sample&hold. 2018-03-16 19:18:41 +01:00
de562f8785 updated readme with screenshot 2018-03-14 22:30:45 +01:00
10457b31ec added image 2018-03-14 22:09:19 +01:00
85f963720a Merge branch 'master' of https://github.com/hzdgopher/4klang 2018-03-11 13:46:38 +01:00
ed24e757e5 batch commit version 3.2.1:
- fixed crash in player when when not using s&h in distortion, but using stereo
- changes for instrument link when loading patches
- fixed link detection for patches, optional stayalive recording noise
- new glitch unit
- micro fix for crash with local stores in global channel
- fix for using distortion with stereo and s&h
2018-03-11 13:46:23 +01:00
e14aefaa8e Update README.md 2018-03-11 13:40:21 +01:00
45a35d8772 retro commit for released version 3.11 2018-03-10 00:14:40 +01:00
522 changed files with 28259 additions and 16945 deletions

4
.gitattributes vendored Normal file
View File

@ -0,0 +1,4 @@
# Declare files that will always have LF line endings on checkout.
# Necessary on windows, as the sointu-compiler formats .yml using only lf so
# this would trigger changes in the files, even when they didn't really change.
*.yml text eol=lf

167
.github/workflows/binaries.yml vendored Normal file
View File

@ -0,0 +1,167 @@
name: Binaries
on:
push:
branches:
- master
- dev
tags:
- 'v*'
pull_request:
branches:
- master
- dev
jobs:
create_release:
name: Create release
runs-on: ubuntu-latest
# Note this. We are going to use that in further jobs.
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- uses: actions/checkout@v4
- name: Create release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref_name }}
body_path: CHANGELOG.md
draft: false
prerelease: false
if: startsWith(github.ref, 'refs/tags/')
binaries:
needs: create_release # we need to know the upload URL
runs-on: ${{ matrix.config.os }}
strategy:
matrix:
config:
- os: windows-latest
asmnasm: C:\Users\runneradmin\nasm\nasm
output: sointu-track.exe
params: cmd/sointu-track/main.go
ldflags: -H=windowsgui
- os: windows-latest
asmnasm: C:\Users\runneradmin\nasm\nasm
output: sointu-compile.exe
params: cmd/sointu-compile/main.go
- os: windows-latest
asmnasm: C:\Users\runneradmin\nasm\nasm
output: sointu-track-native.exe
params: -tags=native cmd/sointu-track/main.go
ldflags: -H=windowsgui
- os: windows-latest
asmnasm: C:\Users\runneradmin\nasm\nasm
output: sointu-vsti.dll
params: -buildmode=c-shared -tags=plugin ./cmd/sointu-vsti/
- os: windows-latest
asmnasm: C:\Users\runneradmin\nasm\nasm
output: sointu-vsti-native.dll
params: -buildmode=c-shared -tags="plugin,native" ./cmd/sointu-vsti/
- os: ubuntu-latest
asmnasm: /home/runner/nasm/nasm
output: sointu-track
params: cmd/sointu-track/main.go
packages: libegl-dev libvulkan-dev libxkbcommon-x11-dev libwayland-dev libasound2-dev libx11-xcb-dev libxcursor-dev libxfixes-dev
- os: ubuntu-latest
asmnasm: /home/runner/nasm/nasm
output: sointu-compile
params: cmd/sointu-compile/main.go
packages: libegl-dev libvulkan-dev libxkbcommon-x11-dev libwayland-dev libasound2-dev libx11-xcb-dev libxcursor-dev libxfixes-dev
- os: ubuntu-latest
asmnasm: /home/runner/nasm/nasm
output: sointu-track-native
params: -tags=native cmd/sointu-track/main.go
packages: libegl-dev libvulkan-dev libxkbcommon-x11-dev libwayland-dev libasound2-dev libx11-xcb-dev libxcursor-dev libxfixes-dev
- os: ubuntu-latest
asmnasm: /home/runner/nasm/nasm
output: sointu-vsti.so
params: -buildmode=c-shared -tags=plugin ./cmd/sointu-vsti/
packages: libegl-dev libvulkan-dev libxkbcommon-x11-dev libwayland-dev libasound2-dev libx11-xcb-dev libxcursor-dev libxfixes-dev
- os: ubuntu-latest
asmnasm: /home/runner/nasm/nasm
output: sointu-vsti-native.so
params: -buildmode=c-shared -tags="plugin,native" ./cmd/sointu-vsti/
packages: libegl-dev libvulkan-dev libxkbcommon-x11-dev libwayland-dev libasound2-dev libx11-xcb-dev libxcursor-dev libxfixes-dev
- os: macos-latest
asmnasm: /Users/runner/nasm/nasm
output: sointu-track
params: cmd/sointu-track/main.go
- os: macos-latest
asmnasm: /Users/runner/nasm/nasm
output: sointu-compile
params: cmd/sointu-compile/main.go
- os: macos-12 # this is intel still
asmnasm: /Users/runner/nasm/nasm
output: sointu-track-native
params: -tags=native cmd/sointu-track/main.go
steps:
- uses: benjlevesque/short-sha@v3.0
id: short-sha
with:
length: 7
- uses: lukka/get-cmake@latest
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-go@v5 # has to be after checkout, see https://medium.com/@s0k0mata/github-actions-and-go-the-new-cache-feature-in-actions-setup-go-v4-and-what-to-watch-out-for-aeea373ed07d
with:
go-version: '>=1.21.0'
- uses: ilammy/setup-nasm@v1.5.1
- uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: ${{ matrix.config.packages }}
version: 1.0
if: runner.os == 'Linux'
- name: Build library
env:
ASM_NASM: ${{ matrix.config.asmnasm }}
run: |
mkdir build
cd build
cmake -GNinja ..
ninja sointu
- name: Build binary
run: |
go build -ldflags "-X github.com/vsariola/sointu/version.Version=$(git describe) ${{ matrix.config.ldflags}}" -o ${{ matrix.config.output }} ${{ matrix.config.params }}
- name: Upload binary
uses: actions/upload-artifact@v4
with:
name: ${{ runner.os }}-${{ steps.short-sha.outputs.sha }}-${{ matrix.config.output }}
path: ${{ matrix.config.output }}
upload_release_asset:
needs: [create_release, binaries]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
strategy:
matrix:
config:
- os: Windows
- os: Linux
- os: macOS
steps:
- uses: benjlevesque/short-sha@v2.2
id: short-sha
with:
length: 7
- name: Download artifacts
uses: actions/download-artifact@v4
with:
pattern: ${{ matrix.config.os }}-${{ steps.short-sha.outputs.sha }}-*
merge-multiple: true
path: sointu-${{ matrix.config.os }}
- name: Zip binaries
run: |
zip ./sointu-${{ matrix.config.os }}.zip sointu-${{ matrix.config.os }}/*
- name: Upload release assets
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create_release.outputs.upload_url }}
asset_name: sointu-${{ matrix.config.os }}.zip
asset_path: ./sointu-${{ matrix.config.os }}.zip
asset_content_type: application/octet-stream

63
.github/workflows/tests.yml vendored Normal file
View File

@ -0,0 +1,63 @@
# Run unit tests using CTest and go tests
name: Tests
on:
push:
branches:
- master
- dev
pull_request:
branches:
- master
- dev
jobs:
test:
runs-on: ${{ matrix.config.os }}
strategy:
matrix:
config:
- os: ubuntu-latest
asmnasm: /home/runner/nasm/nasm
gotests: yes
cgo_ldflags:
- os: windows-latest
asmnasm: C:\Users\runneradmin\nasm\nasm
gotests: yes
cgo_ldflags:
- os: macos-12 # this is intel still
asmnasm: /Users/runner/nasm/nasm
gotests: yes
cgo_ldflags: # -Wl,-no_pie
# ld on mac is complaining about position dependent code so this would take the errors away, BUT
# suddenly this causes an error, even though worked last week. Let's accept the warnings rather
# than let the tests fail because of this.
# TODO: win32 builds didn't quite work out, complains gcc broken
steps:
- uses: lukka/get-cmake@latest
- uses: vsariola/setup-wabt@v1.0.2
with:
version: 1.0.29
- uses: actions/checkout@v4
- uses: actions/setup-go@v5 # has to be after checkout, see https://medium.com/@s0k0mata/github-actions-and-go-the-new-cache-feature-in-actions-setup-go-v4-and-what-to-watch-out-for-aeea373ed07d
with:
go-version: '>=1.21.0'
- uses: actions/setup-node@v4
with:
node-version: '15'
- uses: ilammy/setup-nasm@v1.5.1
- name: Run ctest
env:
ASM_NASM: ${{ matrix.config.asmnasm }}
run: |
mkdir build
cd build
cmake -GNinja ..
ninja tests/all sointu
ctest --output-on-failure
- name: Run go test
if: ${{ matrix.config.gotests == 'yes' }}
env:
CGO_LDFLAGS: ${{ matrix.config.cgo_ldflags }}
run: |
go test ./vm ./vm/compiler/bridge ./vm/compiler

22
.gitignore vendored
View File

@ -11,4 +11,26 @@
[Bb]in/
[Oo]bj/
# CMake
build/
# Project specific
old/
# VS Code
.vscode/
# project specific
# this is autogenerated from bridge.go.in
build/
build32/
build64/
out/
.cache/
actual_output/
**/__debug_bin
*.exe
*.dll
**/testdata/fuzz/
.DS_Store

522
4klang.go Normal file
View File

@ -0,0 +1,522 @@
package sointu
import (
"bytes"
"encoding/binary"
"fmt"
"io"
)
// Read4klangPatch reads a 4klang patch (a file usually with .4kp extension)
// from r and returns a Patch, making best attempt to convert 4klang file to a
// sointu Patch. It returns an error if the file is malformed or if the 4kp file
// version is not supported.
func Read4klangPatch(r io.Reader) (patch Patch, err error) {
var versionTag uint32
var version int
var polyphonyUint32 uint32
var instrumentNames [_4KLANG_MAX_INSTRS]string
patch = make(Patch, 0)
if err := binary.Read(r, binary.LittleEndian, &versionTag); err != nil {
return nil, fmt.Errorf("binary.Read: %w", err)
}
var ok bool
if version, ok = _4klangVersionTags[versionTag]; !ok {
return nil, fmt.Errorf("unknown 4klang version tag: %d", versionTag)
}
if err := binary.Read(r, binary.LittleEndian, &polyphonyUint32); err != nil {
return nil, fmt.Errorf("binary.Read: %w", err)
}
for i := range instrumentNames {
instrumentNames[i], err = read4klangName(r)
if err != nil {
return nil, fmt.Errorf("read4klangName: %w", err)
}
}
m := make(_4klangTargetMap)
id := 1
for instrIndex := 0; instrIndex < _4KLANG_MAX_INSTRS; instrIndex++ {
var units []Unit
if units, err = read4klangUnits(r, version, instrIndex, m, &id); err != nil {
return nil, fmt.Errorf("read4klangUnits: %w", err)
}
if len(units) > 0 {
patch = append(patch, Instrument{Name: instrumentNames[instrIndex], NumVoices: 1, Units: units})
}
}
var units []Unit
if units, err = read4klangUnits(r, version, _4KLANG_MAX_INSTRS, m, &id); err != nil {
return nil, fmt.Errorf("read4klangUnits: %w", err)
}
if len(units) > 0 {
patch = append(patch, Instrument{Name: "Global", NumVoices: 1, Units: units})
}
for i, instr := range patch {
fix4klangTargets(i, instr, m)
}
return
}
// Read4klangInstrument reads a 4klang instrument (a file usually with .4ki
// extension) from r and returns an Instrument, making best attempt to convert
// 4ki file to a sointu Instrument. It returns an error if the file is malformed
// or if the 4ki file version is not supported.
func Read4klangInstrument(r io.Reader) (instr Instrument, err error) {
var versionTag uint32
var version int
var name string
if err := binary.Read(r, binary.LittleEndian, &versionTag); err != nil {
return Instrument{}, fmt.Errorf("binary.Read: %w", err)
}
var ok bool
if version, ok = _4klangVersionTags[versionTag]; !ok {
return Instrument{}, fmt.Errorf("unknown 4klang version tag: %d", versionTag)
}
if name, err = read4klangName(r); err != nil {
return Instrument{}, fmt.Errorf("read4klangName: %w", err)
}
var units []Unit
id := 1
m := make(_4klangTargetMap)
if units, err = read4klangUnits(r, version, 0, m, &id); err != nil {
return Instrument{}, fmt.Errorf("read4klangUnits: %w", err)
}
ret := Instrument{Name: name, NumVoices: 1, Units: units}
fix4klangTargets(0, ret, m)
return ret, nil
}
type (
_4klangStackUnit struct {
stack, unit int
}
_4klangTargetMap map[_4klangStackUnit]int
_4klangPorts struct {
UnitType string
PortName [8]string
}
)
const (
_4KLANG_MAX_INSTRS = 16
_4KLANG_MAX_UNITS = 64
_4KLANG_MAX_SLOTS = 16
_4KLANG_MAX_NAME_LEN = 64
)
var (
_4klangVersionTags map[uint32]int = map[uint32]int{
0x31316b34: 11, // 4k11
0x32316b34: 12, // 4k12
0x33316b34: 13, // 4k13
0x34316b34: 14, // 4k14
}
_4klangDelays []int = []int{ // these are the numerators, if denominator is 48, fraction of beat time
4, // 0 = 4.0f * (1.0f/32.0f) * (2.0f/3.0f)
6, // 1 = 4.0f * (1.0f/32.0f),
9, // 2 = 4.0f * (1.0f/32.0f) * (3.0f/2.0f),
8, // 3 = 4.0f * (1.0f/16.0f) * (2.0f/3.0f),
12, // 4 = 4.0f * (1.0f/16.0f),
18, // 5 = 4.0f * (1.0f/16.0f) * (3.0f/2.0f),
16, // 6 = 4.0f * (1.0f/8.0f) * (2.0f/3.0f),
24, // 7 = 4.0f * (1.0f/8.0f),
36, // 8 = 4.0f * (1.0f/8.0f) * (3.0f/2.0f),
32, // 9 = 4.0f * (1.0f/4.0f) * (2.0f/3.0f),
48, // 10 = 4.0f * (1.0f/4.0f),
72, // 11 = 4.0f * (1.0f/4.0f) * (3.0f/2.0f),
64, // 12 = 4.0f * (1.0f/2.0f) * (2.0f/3.0f),
96, // 13 = 4.0f * (1.0f/2.0f),
144, // 14 = 4.0f * (1.0f/2.0f) * (3.0f/2.0f),
128, // 15 = 4.0f * (1.0f) * (2.0f/3.0f),
192, // 16 = 4.0f * (1.0f),
288, // 17 = 4.0f * (1.0f) * (3.0f/2.0f),
256, // 18 = 4.0f * (2.0f) * (2.0f/3.0f),
384, // 19 = 4.0f * (2.0f),
576, // 20 = 4.0f * (2.0f) * (3.0f/2.0f),
72, // 21 = 4.0f * (3.0f/8.0f),
120, // 22 = 4.0f * (5.0f/8.0f),
168, // 23 = 4.0f * (7.0f/8.0f),
216, // 24 = 4.0f * (9.0f/8.0f),
264, // 25 = 4.0f * (11.0f/8.0f),
312, // 26 = 4.0f * (13.0f/8.0f),
360, // 27 = 4.0f * (15.0f/8.0f),
144, // 28 = 4.0f * (3.0f/4.0f),
240, // 29 = 4.0f * (5.0f/4.0f),
336, // 30 = 4.0f * (7.0f/4.0f),
288, // 31 = 4.0f * (3.0f/2.0f),
288, // 32 = 4.0f * (3.0f/2.0f),
}
_4klangUnitPorts []_4klangPorts = []_4klangPorts{
{"", [8]string{"", "", "", "", "", "", "", ""}},
{"envelope", [8]string{"", "", "gain", "attack", "decay", "", "release", ""}},
{"oscillator", [8]string{"", "transpose", "detune", "", "phase", "color", "shape", "gain"}},
{"filter", [8]string{"", "", "", "", "frequency", "resonance", "", ""}},
{"envelope", [8]string{"", "", "drive", "frequency", "", "", "", ""}},
{"delay", [8]string{"pregain", "feedback", "dry", "damp", "", "", "", ""}},
{"", [8]string{"", "", "", "", "", "", "", ""}},
{"", [8]string{"", "", "", "", "", "", "", ""}},
{"pan", [8]string{"panning", "", "", "", "", "", "", ""}},
{"outaux", [8]string{"auxgain", "outgain", "", "", "", "", "", ""}},
{"", [8]string{"", "", "", "", "", "", "", ""}},
{"load", [8]string{"value", "", "", "", "", "", "", ""}},
}
)
func read4klangName(r io.Reader) (string, error) {
var name [_4KLANG_MAX_NAME_LEN]byte
if err := binary.Read(r, binary.LittleEndian, &name); err != nil {
return "", fmt.Errorf("binary.Read: %w", err)
}
n := bytes.IndexByte(name[:], 0)
if n == -1 {
n = _4KLANG_MAX_NAME_LEN
}
return string(name[:n]), nil
}
func read4klangUnits(r io.Reader, version, instrIndex int, m _4klangTargetMap, id *int) (units []Unit, err error) {
numUnits := _4KLANG_MAX_UNITS
if version <= 13 {
numUnits = 32
}
units = make([]Unit, 0, numUnits)
for unitIndex := 0; unitIndex < numUnits; unitIndex++ {
var u []Unit
if u, err = read4klangUnit(r, version); err != nil {
return nil, fmt.Errorf("read4klangUnit: %w", err)
}
if u == nil {
continue
}
m[_4klangStackUnit{instrIndex, unitIndex}] = *id
for i := range u {
u[i].ID = *id
*id++
}
units = append(units, u...)
}
return
}
func read4klangUnit(r io.Reader, version int) ([]Unit, error) {
var unitType byte
if err := binary.Read(r, binary.LittleEndian, &unitType); err != nil {
return nil, fmt.Errorf("binary.Read: %w", err)
}
var vals [15]byte
if err := binary.Read(r, binary.LittleEndian, &vals); err != nil {
return nil, fmt.Errorf("binary.Read: %w", err)
}
if version <= 13 {
// versions <= 13 had 16 unused slots for each unit
if written, err := io.CopyN(io.Discard, r, 16); err != nil || written < 16 {
return nil, fmt.Errorf("io.CopyN: %w", err)
}
}
switch unitType {
case 1:
return read4klangENV(vals, version), nil
case 2:
return read4klangVCO(vals, version), nil
case 3:
return read4klangVCF(vals, version), nil
case 4:
return read4klangDST(vals, version), nil
case 5:
return read4klangDLL(vals, version), nil
case 6:
return read4klangFOP(vals, version), nil
case 7:
return read4klangFST(vals, version), nil
case 8:
return read4klangPAN(vals, version), nil
case 9:
return read4klangOUT(vals, version), nil
case 10:
return read4klangACC(vals, version), nil
case 11:
return read4klangFLD(vals, version), nil
default:
return nil, nil
}
}
func read4klangENV(vals [15]byte, version int) []Unit {
return []Unit{{
Type: "envelope",
Parameters: map[string]int{
"stereo": 0,
"attack": int(vals[0]),
"decay": int(vals[1]),
"sustain": int(vals[2]),
"release": int(vals[3]),
"gain": int(vals[4]),
},
}}
}
func read4klangVCO(vals [15]byte, version int) []Unit {
v := vals[:8]
var transpose, detune, phase, color, gate, shape, gain, flags, stereo, typ, lfo int
transpose, v = int(v[0]), v[1:]
detune, v = int(v[0]), v[1:]
phase, v = int(v[0]), v[1:]
if version <= 11 {
gate = 0x55
} else {
gate, v = int(v[0]), v[1:]
}
color, v = int(v[0]), v[1:]
shape, v = int(v[0]), v[1:]
gain, v = int(v[0]), v[1:]
flags, v = int(v[0]), v[1:]
if flags&0x10 == 0x10 {
lfo = 1
}
if flags&0x40 == 0x40 {
stereo = 1
}
switch {
case flags&0x01 == 0x01: // Sine
typ = Sine
if version <= 13 {
color = 128
}
case flags&0x02 == 0x02: // Trisaw
typ = Trisaw
case flags&0x04 == 0x04: // Pulse
typ = Pulse
case flags&0x08 == 0x08: // Noise is handled differently in sointu
return []Unit{{
Type: "noise",
Parameters: map[string]int{
"stereo": stereo,
"shape": shape,
"gain": gain,
},
}}
case flags&0x20 == 0x20: // Gate
color = gate
}
return []Unit{{
Type: "oscillator",
Parameters: map[string]int{
"stereo": stereo,
"transpose": transpose,
"detune": detune,
"phase": phase,
"color": color,
"shape": shape,
"gain": gain,
"type": typ,
"lfo": lfo,
},
}}
}
func read4klangVCF(vals [15]byte, version int) []Unit {
flags := vals[2]
var stereo, lowpass, bandpass, highpass, neghighpass int
if flags&0x01 == 0x01 {
lowpass = 1
}
if flags&0x02 == 0x02 {
highpass = 1
}
if flags&0x04 == 0x04 {
bandpass = 1
}
if flags&0x08 == 0x08 {
lowpass = 1
neghighpass = 1
}
if flags&0x10 == 0x10 {
stereo = 1
}
return []Unit{{
Type: "filter",
Parameters: map[string]int{
"stereo": stereo,
"frequency": int(vals[0]),
"resonance": int(vals[1]),
"lowpass": lowpass,
"bandpass": bandpass,
"highpass": highpass,
"negbandpass": 0,
"neghighpass": neghighpass,
}},
}
}
func read4klangDST(vals [15]byte, version int) []Unit {
return []Unit{
{Type: "distort", Parameters: map[string]int{"drive": int(vals[0]), "stereo": int(vals[2])}},
{Type: "hold", Parameters: map[string]int{"holdfreq": int(vals[1]), "stereo": int(vals[2])}},
}
}
func read4klangDLL(vals [15]byte, version int) []Unit {
var delaytimes []int
var notetracking int
if vals[11] > 0 {
if vals[10] > 0 { // left reverb
delaytimes = []int{1116, 1188, 1276, 1356, 1422, 1492, 1556, 1618}
} else { // right reverb
delaytimes = []int{1140, 1212, 1300, 1380, 1446, 1516, 1580, 1642}
}
} else {
synctype := vals[9]
switch synctype {
case 0:
delaytimes = []int{int(vals[8]) * 16}
case 1: // relative to BPM
notetracking = 2
index := vals[8] >> 2
delaytime := 48
if int(index) < len(_4klangDelays) {
delaytime = _4klangDelays[index]
}
delaytimes = []int{delaytime}
case 2: // notetracking
notetracking = 1
delaytimes = []int{10787}
}
}
return []Unit{{
Type: "delay",
Parameters: map[string]int{
"stereo": 0,
"pregain": int(vals[0]),
"dry": int(vals[1]),
"feedback": int(vals[2]),
"damp": int(vals[3]),
"notetracking": notetracking,
},
VarArgs: delaytimes,
}}
}
func read4klangFOP(vals [15]byte, version int) []Unit {
var t string
var stereo int
switch vals[0] {
case 1:
t, stereo = "pop", 0
case 2:
t, stereo = "addp", 0
case 3:
t, stereo = "mulp", 0
case 4:
t, stereo = "push", 0
case 5:
t, stereo = "xch", 0
case 6:
t, stereo = "add", 0
case 7:
t, stereo = "mul", 0
case 8:
t, stereo = "addp", 1
case 9:
return []Unit{{Type: "loadnote", Parameters: map[string]int{"stereo": stereo}}, // 4klang loadnote gives 0..1, sointu gives -1..1
{Type: "loadval", Parameters: map[string]int{"value": 128, "stereo": stereo}},
{Type: "addp", Parameters: map[string]int{"stereo": stereo}},
{Type: "gain", Parameters: map[string]int{"stereo": stereo, "gain": 64}}}
default:
t, stereo = "mulp", 1
}
return []Unit{{
Type: t,
Parameters: map[string]int{"stereo": stereo},
}}
}
func read4klangFST(vals [15]byte, version int) []Unit {
sendpop := 0
if vals[1]&0x40 == 0x40 {
sendpop = 1
}
return []Unit{{
Type: "send",
Parameters: map[string]int{
"amount": int(vals[0]),
"sendpop": sendpop,
"dest_stack": int(vals[2]),
"dest_unit": int(vals[3]),
"dest_slot": int(vals[4]),
"dest_id": int(vals[5]),
}}}
}
func fix4klangTargets(instrIndex int, instr Instrument, m _4klangTargetMap) {
for _, u := range instr.Units {
if u.Type == "send" {
destStack := u.Parameters["dest_stack"]
if destStack == 255 {
destStack = instrIndex
}
fourKlangTarget := _4klangStackUnit{
destStack,
u.Parameters["dest_unit"]}
u.Parameters["target"] = m[fourKlangTarget]
if u.Parameters["dest_id"] < len(_4klangUnitPorts) && u.Parameters["dest_slot"] < 8 {
if u.Parameters["dest_id"] == 4 && u.Parameters["dest_slot"] == 3 { // distortion is split into 2 units
u.Parameters["target"]++
u.Parameters["port"] = 0
} else {
modTarget := _4klangUnitPorts[u.Parameters["dest_id"]]
for i, s := range Ports[modTarget.UnitType] {
if s == modTarget.PortName[u.Parameters["dest_slot"]] {
u.Parameters["port"] = i
break
}
}
}
}
delete(u.Parameters, "dest_stack")
delete(u.Parameters, "dest_unit")
delete(u.Parameters, "dest_slot")
delete(u.Parameters, "dest_id")
}
}
}
func read4klangPAN(vals [15]byte, version int) []Unit {
return []Unit{{
Type: "pan",
Parameters: map[string]int{
"stereo": 0,
"panning": int(vals[0]),
}}}
}
func read4klangOUT(vals [15]byte, version int) []Unit {
return []Unit{{
Type: "outaux",
Parameters: map[string]int{
"stereo": 1,
"outgain": int(vals[0]),
"auxgain": int(vals[1])},
}}
}
func read4klangACC(vals [15]byte, version int) []Unit {
c := 0
if vals[0] != 0 {
c = 2
}
return []Unit{{
Type: "in",
Parameters: map[string]int{"stereo": 1, "channel": c},
}}
}
func read4klangFLD(vals [15]byte, version int) []Unit {
return []Unit{{
Type: "loadval",
Parameters: map[string]int{"stereo": 0, "value": int(vals[0])},
}}
}

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.

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.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,898 +0,0 @@
; //----------------------------------------------------------------------------------------
; // useful macros
; //----------------------------------------------------------------------------------------
; // export function (make it accessable from main.cpp)
; //----------------------------------------------------------------------------------------
%macro export_func 1
global _%1
_%1:
%endmacro
%define USE_SECTIONS
; //----------------------------------------------------------------------------------------
; // basic defines for the song/synth
; //----------------------------------------------------------------------------------------
%define SAMPLE_RATE 44100
%define MAX_INSTRUMENTS 9
%define MAX_VOICES 1
%define HLD 1 ; // can be adjusted to give crinkler some other possibilities
%define BPM 100
%define MAX_PATTERNS 62
%define PATTERN_SIZE_SHIFT 4
%define PATTERN_SIZE (1 << PATTERN_SIZE_SHIFT)
%define MAX_TICKS (MAX_PATTERNS*PATTERN_SIZE)
%define SAMPLES_PER_TICK (SAMPLE_RATE*4*60/(BPM*16))
%define DEF_LFO_NORMALIZE 0.000038
%define MAX_SAMPLES (SAMPLES_PER_TICK*MAX_TICKS)
; //----------------------------------------------------------------------------------------
; // some defines for unit usage, which reduce synth code size
; //----------------------------------------------------------------------------------------
;%define GO4K_USE_16BIT_OUTPUT ; // removing this will output to 32bit floating point buffer
;%define GO4K_USE_GROOVE_PATTERN ; // removing this skips groove pattern code
;%define GO4K_USE_ENVELOPE_RECORDINGS ; // removing this skips envelope recording code
;%define GO4K_USE_NOTE_RECORDINGS ; // removing this skips note recording code
%define GO4K_USE_UNDENORMALIZE ; // removing this skips denormalization code in the units
%define GO4K_CLIP_OUTPUT ; // removing this skips clipping code for the final output
%define GO4K_USE_DST ; // removing this will skip DST unit
%define GO4K_USE_DLL ; // removing this will skip DLL unit
%define GO4K_USE_PAN ; // removing this will skip PAN unit
%define GO4K_USE_GLOBAL_DLL ; // removing this will skip global dll processing
%define GO4K_USE_FSTG ; // removing this will skip global store unit
%define GO4K_USE_FLD ; // removing this will skip float load unit
%define GO4K_USE_ENV_CHECK ; // removing this skips checks if processing is needed
%define GO4K_USE_ENV_MOD_GM ; // removing this will skip env gain modulation code
%define GO4K_USE_ENV_MOD_ADR ; // removing this will skip env attack/decay/release modulation code
%define GO4K_USE_VCO_CHECK ; // removing this skips checks if processing is needed
%define GO4K_USE_VCO_PHASE_OFFSET ; // removing this will skip initial phase offset code
%define GO4K_USE_VCO_SHAPE ; // removing this skips waveshaping code
%define GO4K_USE_VCO_GATE ; // removing this skips gate code
%define GO4K_USE_VCO_MOD_FM ; // removing this skips frequency modulation code
%define GO4K_USE_VCO_MOD_PM ; // removing this skips phase modulation code
%define GO4K_USE_VCO_MOD_TM ; // removing this skips transpose modulation code
%define GO4K_USE_VCO_MOD_DM ; // removing this skips detune modulation code
%define GO4K_USE_VCO_MOD_CM ; // removing this skips color modulation code
%define GO4K_USE_VCO_MOD_GM ; // removing this skips gain modulation code
%define GO4K_USE_VCO_MOD_SM ; // removing this skips shaping modulation code
%define GO4K_USE_VCF_CHECK ; // removing this skips checks if processing is needed
%define GO4K_USE_VCF_MOD_FM ; // removing this skips frequency modulation code
%define GO4K_USE_VCF_MOD_RM ; // removing this skips resonance modulation code
%define GO4K_USE_VCF_HIGH ; // removing this skips code for high output
%define GO4K_USE_VCF_BAND ; // removing this skips code for band output
%define GO4K_USE_VCF_PEAK ; // removing this skips code for peak output
%define GO4K_USE_DST_CHECK ; // removing this skips checks if processing is needed
%define GO4K_USE_DST_SH ; // removing this skips sample and hold code
%define GO4K_USE_DST_MOD_DM ; // removing this skips distortion modulation code
%define GO4K_USE_DST_MOD_SH ; // removing this skips sample and hold modulation code
%define GO4K_USE_DLL_NOTE_SYNC ; // removing this will skip delay length adjusting code (karplus strong)
%define GO4K_USE_DLL_CHORUS ; // removing this will skip delay chorus/flanger code
%define GO4K_USE_DLL_CHORUS_CLAMP ; // removing this will skip chorus lfo phase clamping
%define GO4K_USE_DLL_DAMP ; // removing this will skip dll damping code
%define GO4K_USE_DLL_DC_FILTER ; // removing this will skip dll dc offset removal code
%define GO4K_USE_FOP_LOADNOTE ; // removing this will skip load note code
%define GO4K_USE_FSTG_CHECK ; // removing this skips checks if processing is needed
%define GO4K_USE_PAN_MOD ; // removing this will skip panning modulation code
%define GO4K_USE_OUT_MOD_AM ; // removing this skips output aux send modulation code
%define GO4K_USE_OUT_MOD_GM ; // removing this skips output gain modulation code
%define GO4K_USE_WAVESHAPER_CLIP ; // removing this will skip clipping code
%define GO4K_USE_FLD_MOD_VM ; // removing this will skip float load modulation code
%define GO4K_USE_DLL_MOD ; // define this to enable modulations for delay line
%define GO4K_USE_DLL_MOD_PM ; // define this to enable pregain modulation for delay line
%define GO4K_USE_DLL_MOD_FM ; // define this to enable feebback modulation for delay line
%define GO4K_USE_DLL_MOD_IM ; // define this to enable dry modulation for delay line
%define GO4K_USE_DLL_MOD_DM ; // define this to enable damping modulation for delay line
%define GO4K_USE_DLL_MOD_SM ; // define this to enable lfo freq modulation for delay line
%define GO4K_USE_DLL_MOD_AM ; // define this to enable lfo depth modulation for delay line
; //----------------------------------------------------------------------------------------
; // synth defines
; //----------------------------------------------------------------------------------------
%define MAX_DELAY 65536
%define MAX_WORKSPACE_SLOTS 8
%define GO4K_BEGIN_CMDDEF(def_name)
%define GO4K_END_CMDDEF db 0
%define GO4K_BEGIN_PARAMDEF(def_name)
%define GO4K_END_PARAMDEF
; //----------------------------------------------------------------------------------------
; // ENV structs
; //----------------------------------------------------------------------------------------
GO4K_ENV_ID equ 1
%macro GO4K_ENV 5
db %1
db %2
db %3
db %4
db %5
%endmacro
%define ATTAC(val) val
%define DECAY(val) val
%define SUSTAIN(val) val
%define RELEASE(val) val
%define GAIN(val) val
struc go4kENV_val
;// unit paramters
.attac resd 1
.decay resd 1
.sustain resd 1
.release resd 1
.gain resd 1
.size
endstruc
struc go4kENV_wrk
;// work variables
.state resd 1
.level resd 1
;// modulation targets
.gm resd 1
.am resd 1
.dm resd 1
.sm resd 1
.rm resd 1
.size
endstruc
%define ENV_STATE_ATTAC 0
%define ENV_STATE_DECAY 1
%define ENV_STATE_SUSTAIN 2
%define ENV_STATE_RELEASE 3
%define ENV_STATE_OFF 4
; //----------------------------------------------------------------------------------------
; // VCO structs
; //----------------------------------------------------------------------------------------
GO4K_VCO_ID equ 2
%macro GO4K_VCO 8
db %1
db %2
%ifdef GO4K_USE_VCO_PHASE_OFFSET
db %3
%endif
%ifdef GO4K_USE_VCO_GATE
db %4
%endif
db %5
%ifdef GO4K_USE_VCO_SHAPE
db %6
%else
%endif
db %7
db %8
%endmacro
%define TRANSPOSE(val) val
%define DETUNE(val) val
%define PHASE(val) val
%define GATES(val) val
%define COLOR(val) val
%define SHAPE(val) val
%define FLAGS(val) val
%define SINE 0x01
%define TRISAW 0x02
%define PULSE 0x04
%define NOISE 0x08
%define LFO 0x10
%define GATE 0x20
struc go4kVCO_val
;// unit paramters
.transpose resd 1
.detune resd 1
%ifdef GO4K_USE_VCO_PHASE_OFFSET
.phaseofs resd 1
%endif
%ifdef GO4K_USE_VCO_GATE
.gate resd 1
%endif
.color resd 1
%ifdef GO4K_USE_VCO_SHAPE
.shape resd 1
%endif
.gain resd 1
.flags resd 1
.size
endstruc
struc go4kVCO_wrk
;// work variables
.phase resd 1
;// modulation targets
.tm resd 1
.dm resd 1
.fm resd 1
.pm resd 1
.cm resd 1
.sm resd 1
.gm resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // VCF structs
; //----------------------------------------------------------------------------------------
GO4K_VCF_ID equ 3
%macro GO4K_VCF 3
db %1
db %2
db %3
%endmacro
%define LOWPASS 0x1
%define HIGHPASS 0x2
%define BANDPASS 0x4
%define BANDSTOP 0x3
%define ALLPASS 0x7
%define PEAK 0x8
%define FREQUENCY(val) val
%define RESONANCE(val) val
%define VCFTYPE(val) val
struc go4kVCF_val
;// unit paramters
.freq resd 1
.res resd 1
.type resd 1
.size
endstruc
struc go4kVCF_wrk
;// work variables
.low resd 1
.high resd 1
.band resd 1
.freq resd 1
;// modulation targets
.fm resd 1
.rm resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // DST structs
; //----------------------------------------------------------------------------------------
GO4K_DST_ID equ 4
%macro GO4K_DST 2
db %1
%ifdef GO4K_USE_DST_SH
db %2
%endif
%endmacro
%define DRIVE(val) val
%define SNHFREQ(val) val
struc go4kDST_val
;// unit paramters
.drive resd 1
%ifdef GO4K_USE_DST_SH
.snhfreq resd 1
%endif
.size
endstruc
struc go4kDST_wrk
.out resd 1
.snhphase resd 1
;// modulation targets
.dm resd 1
.sm resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // DLL structs
; //----------------------------------------------------------------------------------------
GO4K_DLL_ID equ 5
%macro GO4K_DLL 8
db %1
db %2
db %3
%ifdef GO4K_USE_DLL_DAMP
db %4
%endif
%ifdef GO4K_USE_DLL_CHORUS
db %5
db %6
%endif
db %7
db %8
%endmacro
%define PREGAIN(val) val
%define DRY(val) val
%define FEEDBACK(val) val
%define DEPTH(val) val
%define DAMP(val) val
%define DELAY(val) val
%define COUNT(val) val
struc go4kDLL_val
;// unit paramters
.pregain resd 1
.dry resd 1
.feedback resd 1
%ifdef GO4K_USE_DLL_DAMP
.damp resd 1
%endif
%ifdef GO4K_USE_DLL_CHORUS
.freq resd 1
.depth
%endif
.delay resd 1
.count resd 1
.size
endstruc
struc go4kDLL_wrk
;// work variables
.index resd 1
.store resd 1
.dcin resd 1
.dcout resd 1
.phase resd 1
;// the delay buffer
.buffer resd MAX_DELAY
.size
endstruc
struc go4kDLL_wrk2
;// modulation targets
.pm resd 1
.fm resd 1
.im resd 1
.dm resd 1
.sm resd 1
.am resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // FOP structs
; //----------------------------------------------------------------------------------------
GO4K_FOP_ID equ 6
%macro GO4K_FOP 1
db %1
%endmacro
%define OP(val) val
%define FOP_POP 0x1
%define FOP_ADDP 0x2
%define FOP_MULP 0x3
%define FOP_PUSH 0x4
%define FOP_XCH 0x5
%define FOP_ADD 0x6
%define FOP_MUL 0x7
%define FOP_ADDP2 0x8
%define FOP_LOADNOTE 0x9
struc go4kFOP_val
.flags resd 1
.size
endstruc
struc go4kFOP_wrk
.size
endstruc
; //----------------------------------------------------------------------------------------
; // FST structs
; //----------------------------------------------------------------------------------------
GO4K_FST_ID equ 7
%macro GO4K_FST 2
db %1
db %2
%endmacro
%define AMOUNT(val) val
%define DEST(val) val
struc go4kFST_val
.amount resd 1
.op1 resd 1
.size
endstruc
struc go4kFST_wrk
.size
endstruc
; //----------------------------------------------------------------------------------------
; // PAN structs
; //----------------------------------------------------------------------------------------
GO4K_PAN_ID equ 8
%macro GO4K_PAN 1
%ifdef GO4K_USE_PAN
db %1
%endif
%endmacro
%define PANNING(val) val
struc go4kPAN_val
%ifdef GO4K_USE_PAN
.panning resd 1
%endif
.size
endstruc
struc go4kPAN_wrk
;// modulation targets
.pm resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // OUT structs
; //----------------------------------------------------------------------------------------
GO4K_OUT_ID equ 9
%macro GO4K_OUT 2
db %1
%ifdef GO4K_USE_GLOBAL_DLL
db %2
%endif
%endmacro
%define AUXSEND(val) val
struc go4kOUT_val
.gain resd 1
%ifdef GO4K_USE_GLOBAL_DLL
.auxsend resd 1
%endif
.size
endstruc
struc go4kOUT_wrk
;// modulation targets
.am resd 1
.gm resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // ACC structs (this is for the synth def only)
; //----------------------------------------------------------------------------------------
GO4K_ACC_ID equ 10
%macro GO4K_ACC 1
db %1
%endmacro
%define OUTPUT 0
%define AUX 8
%define ACCTYPE(val) val
struc go4kACC_val
.acctype resd 1
.size
endstruc
struc go4kACC_wrk
.size
endstruc
%ifdef GO4K_USE_FLD
; //----------------------------------------------------------------------------------------
; // FLD structs
; //----------------------------------------------------------------------------------------
GO4K_FLD_ID equ 11
%macro GO4K_FLD 1
db %1
%endmacro
%define VALUE(val) val
struc go4kFLD_val
.value resd 1
.size
endstruc
struc go4kFLD_wrk
;// modulation targets
.vm resd 1
.size
endstruc
%endif
%ifdef GO4K_USE_FSTG
; //----------------------------------------------------------------------------------------
; // FSTG structs
; //----------------------------------------------------------------------------------------
GO4K_FSTG_ID equ 12
%macro GO4K_FSTG 2
db %1
dd %2
%endmacro
struc go4kFSTG_val
.amount resd 1
.op1 resd 1
.size
endstruc
struc go4kFSTG_wrk
.size
endstruc
%endif
; //----------------------------------------------------------------------------------------
; // Voice struct
; //----------------------------------------------------------------------------------------
struc go4k_instrument
.release resd 1
.note resd 1
.workspace resd 256
.dlloutl resd 1
.dlloutr resd 1
.outl resd 1
.outr resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // Synth struct
; //----------------------------------------------------------------------------------------
struc go4k_synth
.instruments resb go4k_instrument.size * MAX_INSTRUMENTS * MAX_VOICES
.global resb go4k_instrument.size * MAX_VOICES
.size
endstruc
; //----------------------------------------------------------------------------------------
; // Pattern Data, reduced by 967 patterns
; //----------------------------------------------------------------------------------------
%ifdef USE_SECTIONS
section .g4kmuc1 data align=1
%else
section .data align=1
%endif
go4k_patterns
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
db 76, HLD, HLD, HLD, 0, 0, 0, 0, 79, HLD, HLD, HLD, 0, 0, 0, 0,
db 69, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0,
db 76, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 81, HLD, HLD, HLD, 0, 0, 0, 0, 79, HLD, HLD, HLD, 0, 0, 0, 0,
db 84, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0,
db 76, HLD, HLD, HLD, 0, 0, 0, 0, 88, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0,
db 76, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0,
db 52, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 57, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 60, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 69, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 72, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 40, 52, HLD, 64, HLD, 40, 52, 64, 52, HLD, HLD, HLD, 0, 0, 0, 0,
db 57, 0, 0, 57, 0, 0, 69, 0, 0, 69, 0, 0, 57, HLD, HLD, HLD,
db 52, 64, 0, 57, 0, 69, 48, 0, 48, HLD, HLD, HLD, 0, 0, 0, 0,
db 40, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 40, 52, HLD, 40, HLD, 40, 40, 40, 52, HLD, HLD, HLD, 0, 0, 0, 0,
db 40, 0, 0, 52, 0, 0, 40, 0, 52, 40, 0, 52, 0, 40, 0, 0,
db 45, 0, 0, 57, 0, 0, 45, 0, 57, 45, 0, 57, 0, 45, 0, 0,
db 48, 0, 0, 60, 0, 0, 48, 0, 60, 48, 0, 60, 0, 48, 0, 0,
db 40, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0,
db 45, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0,
db 36, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0,
db 0, 0, 0, 0, 60, HLD, 0, 0, 0, 0, 0, 0, 60, HLD, 0, 0,
db 60, HLD, 0, 0, 0, 0, 60, HLD, 0, 0, 60, HLD, 60, HLD, 0, 0,
db 0, 0, 0, 0, 60, HLD, 0, 0, 0, 0, 0, 0, 60, HLD, 60, HLD,
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, HLD, 0, 0,
db 60, HLD, 60, HLD, 0, 0, 60, HLD, 0, 0, 0, 0, 60, HLD, 0, 0,
db 0, 0, 60, HLD, 0, 0, 0, 0, 60, HLD, 0, 0, 0, 0, 0, 0,
db 0, 0, 60, HLD, 0, 0, 0, 0, 60, HLD, 0, 0, 60, HLD, 0, 0,
db 0, 0, 0, 60, HLD, 0, 0, 0, 0, 0, 0, 0, 60, HLD, 0, 0,
db 0, 0, 0, 60, HLD, 0, 0, 0, 0, 60, HLD, 60, 60, HLD, 0, 0,
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0,
db 91, 0, 0, 88, 0, 0, 76, 0, 81, 0, 0, 0, 0, 0, 0, 0,
db 81, 0, 0, 84, 0, 0, 86, 0, 88, 0, 0, 0, 0, 0, 0, 0,
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0,
db 81, 0, 0, 84, 0, 0, 86, 0, 81, 0, 0, 0, 0, 0, 0, 0,
db 84, 0, 0, 86, 0, 0, 88, 0, 0, 91, 0, 0, 84, 0, 0, 0,
db HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
go4k_patterns_end
; //----------------------------------------------------------------------------------------
; // Pattern Index List
; //----------------------------------------------------------------------------------------
%ifdef USE_SECTIONS
section .g4kmuc2 data align=1
%else
section .data
%endif
go4k_pattern_lists
Instrument0List db 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4, 5, 6, 7, 1, 2, 3, 0, 4, 5, 6, 7, 8, 2, 9, 0, 0, 0,
Instrument1List db 9, 7, 10, 7, 11, 7, 12, 7, 9, 7, 10, 7, 11, 7, 12, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 7, 13, 7, 14, 7, 3, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 7, 0, 0,
Instrument2List db 15, 0, 16, 0, 17, 0, 18, 0, 19, 0, 16, 0, 17, 0, 18, 0, 20, 20, 21, 21, 22, 22, 20, 20, 20, 20, 21, 21, 22, 22, 20, 20, 23, 15, 24, 16, 25, 17, 18, 0, 20, 20, 21, 21, 22, 22, 20, 20, 20, 20, 21, 21, 22, 22, 20, 20, 20, 20, 0, 0, 0, 0,
Instrument3List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0,
Instrument4List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 26, 27, 26, 27, 26, 27, 28, 27, 26, 27, 26, 27, 26, 27, 28, 27, 29, 27, 29, 27, 29, 27, 29, 27, 26, 27, 26, 27, 26, 27, 28, 27, 26, 27, 26, 27, 26, 27, 28, 27, 26, 27, 0, 0, 0,
Instrument5List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 0, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 32, 0, 0,
Instrument6List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 0, 0, 0, 0,
Instrument7List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 36, 0, 37, 38, 36, 0, 39, 35, 36, 0, 37, 38, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Instrument8List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 41, 0,
go4k_pattern_lists_end
; //----------------------------------------------------------------------------------------
; // Instrument Commands
; //----------------------------------------------------------------------------------------
%ifdef USE_SECTIONS
section .g4kmuc3 data align=1
%else
section .data
%endif
go4k_synth_instructions
GO4K_BEGIN_CMDDEF(Instrument0)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_FST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_VCF_ID
db GO4K_DST_ID
db GO4K_PAN_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument1)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_FST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_VCF_ID
db GO4K_DST_ID
db GO4K_PAN_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument2)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_FST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_VCF_ID
db GO4K_DST_ID
db GO4K_PAN_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument3)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_PAN_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument4)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_ENV_ID
db GO4K_DST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_PAN_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument5)
db GO4K_ENV_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_PAN_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument6)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCF_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_PAN_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument7)
db GO4K_ENV_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_PAN_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument8)
db GO4K_ENV_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_FSTG_ID
db GO4K_FSTG_ID
db GO4K_FOP_ID
GO4K_END_CMDDEF
;// global commands
GO4K_BEGIN_CMDDEF(Global)
db GO4K_ACC_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_ACC_ID
db GO4K_FOP_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
go4k_synth_instructions_end
; //----------------------------------------------------------------------------------------
; // Intrument Data
; //----------------------------------------------------------------------------------------
%ifdef USE_SECTIONS
section .g4kmuc4 data align=1
%else
section .data
%endif
go4k_synth_parameter_values
GO4K_BEGIN_PARAMDEF(Instrument0)
GO4K_ENV ATTAC(72),DECAY(96),SUSTAIN(96),RELEASE(88),GAIN(128)
GO4K_FST AMOUNT(64),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_VCO TRANSPOSE(64),DETUNE(60),PHASE(32),GATES(0),COLOR(80),SHAPE(64),GAIN(128),FLAGS(PULSE)
GO4K_VCO TRANSPOSE(64),DETUNE(72),PHASE(32),GATES(0),COLOR(96),SHAPE(64),GAIN(128),FLAGS(TRISAW)
GO4K_VCO TRANSPOSE(32),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(96),GAIN(128),FLAGS(SINE|LFO)
GO4K_FST AMOUNT(68),DEST(2*MAX_WORKSPACE_SLOTS+2)
GO4K_FST AMOUNT(61),DEST(3*MAX_WORKSPACE_SLOTS+2)
GO4K_FOP OP(FOP_POP)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(26),RESONANCE(128),VCFTYPE(PEAK)
GO4K_VCF FREQUENCY(64),RESONANCE(64),VCFTYPE(LOWPASS)
GO4K_DST DRIVE(104), SNHFREQ(128)
GO4K_PAN PANNING(64)
GO4K_DLL PREGAIN(96),DRY(128),FEEDBACK(96),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(16),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_DLL PREGAIN(96),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(17),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_OUT GAIN(0), AUXSEND(32)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument1)
GO4K_ENV ATTAC(72),DECAY(96),SUSTAIN(96),RELEASE(88),GAIN(128)
GO4K_FST AMOUNT(64),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_VCO TRANSPOSE(64),DETUNE(60),PHASE(32),GATES(0),COLOR(80),SHAPE(64),GAIN(128),FLAGS(TRISAW)
GO4K_VCO TRANSPOSE(64),DETUNE(72),PHASE(32),GATES(0),COLOR(96),SHAPE(112),GAIN(64),FLAGS(SINE)
GO4K_VCO TRANSPOSE(80),DETUNE(112),PHASE(0),GATES(0),COLOR(64),SHAPE(16),GAIN(128),FLAGS(PULSE|LFO)
GO4K_FST AMOUNT(68),DEST(2*MAX_WORKSPACE_SLOTS+2)
GO4K_FST AMOUNT(60),DEST(3*MAX_WORKSPACE_SLOTS+2)
GO4K_FOP OP(FOP_POP)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(80),RESONANCE(24),VCFTYPE(LOWPASS)
GO4K_VCF FREQUENCY(48),RESONANCE(24),VCFTYPE(HIGHPASS)
GO4K_DST DRIVE(64), SNHFREQ(128)
GO4K_PAN PANNING(64)
GO4K_DLL PREGAIN(96),DRY(128),FEEDBACK(96),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(16),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_DLL PREGAIN(96),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(17),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_OUT GAIN(0), AUXSEND(32)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument2)
GO4K_ENV ATTAC(32),DECAY(64),SUSTAIN(64),RELEASE(64),GAIN(64)
GO4K_FST AMOUNT(120),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(32),GATES(0),COLOR(80),SHAPE(64),GAIN(128),FLAGS(PULSE)
GO4K_VCO TRANSPOSE(64),DETUNE(72),PHASE(32),GATES(0),COLOR(96),SHAPE(64),GAIN(128),FLAGS(TRISAW)
GO4K_VCO TRANSPOSE(32),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(96),GAIN(128),FLAGS(SINE|LFO)
GO4K_FST AMOUNT(68),DEST(2*MAX_WORKSPACE_SLOTS+2)
GO4K_FST AMOUNT(60),DEST(3*MAX_WORKSPACE_SLOTS+2)
GO4K_FOP OP(FOP_POP)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(18),RESONANCE(64),VCFTYPE(PEAK)
GO4K_VCF FREQUENCY(32),RESONANCE(48),VCFTYPE(LOWPASS)
GO4K_DST DRIVE(88), SNHFREQ(128)
GO4K_PAN PANNING(64)
GO4K_DLL PREGAIN(64),DRY(128),FEEDBACK(96),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(16),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_DLL PREGAIN(64),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(17),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_OUT GAIN(64), AUXSEND(64)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument3)
GO4K_ENV ATTAC(0),DECAY(76),SUSTAIN(0),RELEASE(0),GAIN(32)
GO4K_FST AMOUNT(128),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(64),GATES(0),COLOR(64),SHAPE(64),GAIN(128),FLAGS(NOISE)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(80),RESONANCE(128),VCFTYPE(LOWPASS)
GO4K_PAN PANNING(64)
GO4K_OUT GAIN(64), AUXSEND(0)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument4)
GO4K_ENV ATTAC(0),DECAY(64),SUSTAIN(96),RELEASE(64),GAIN(128)
GO4K_FST AMOUNT(128),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_ENV ATTAC(0),DECAY(70),SUSTAIN(0),RELEASE(0),GAIN(128)
GO4K_DST DRIVE(32), SNHFREQ(128)
GO4K_FST AMOUNT(80),DEST(6*MAX_WORKSPACE_SLOTS+1)
GO4K_FOP OP(FOP_POP)
GO4K_VCO TRANSPOSE(46),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(64),GAIN(128),FLAGS(TRISAW)
GO4K_FOP OP(FOP_MULP)
GO4K_PAN PANNING(64)
GO4K_OUT GAIN(128), AUXSEND(0)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument5)
GO4K_ENV ATTAC(0),DECAY(64),SUSTAIN(0),RELEASE(0),GAIN(128)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(64),GATES(0),COLOR(64),SHAPE(64),GAIN(128),FLAGS(NOISE)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(128),RESONANCE(128),VCFTYPE(BANDPASS)
GO4K_PAN PANNING(64)
GO4K_DLL PREGAIN(64),DRY(128),FEEDBACK(96),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(16),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_DLL PREGAIN(64),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(17),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_OUT GAIN(64), AUXSEND(0)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument6)
GO4K_ENV ATTAC(0),DECAY(72),SUSTAIN(0),RELEASE(72),GAIN(128)
GO4K_FST AMOUNT(128),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_ENV ATTAC(0),DECAY(56),SUSTAIN(0),RELEASE(0),GAIN(128)
GO4K_FST AMOUNT(108),DEST(6*MAX_WORKSPACE_SLOTS+1)
GO4K_FST AMOUNT(72),DEST(7*MAX_WORKSPACE_SLOTS+1)
GO4K_FOP OP(FOP_POP)
GO4K_VCO TRANSPOSE(32),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(32),GAIN(64),FLAGS(SINE)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(80),GAIN(64),FLAGS(SINE)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(64),GAIN(64),FLAGS(NOISE)
GO4K_VCF FREQUENCY(104),RESONANCE(128),VCFTYPE(LOWPASS)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(22),RESONANCE(32),VCFTYPE(HIGHPASS)
GO4K_PAN PANNING(64)
GO4K_OUT GAIN(64), AUXSEND(0)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument7)
GO4K_ENV ATTAC(0),DECAY(0),SUSTAIN(96),RELEASE(32),GAIN(128)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(0),COLOR(80),SHAPE(64),GAIN(128),FLAGS(PULSE)
GO4K_FOP OP(FOP_MULP)
GO4K_PAN PANNING(64)
GO4K_DLL PREGAIN(96),DRY(128),FEEDBACK(96),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(16),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_DLL PREGAIN(96),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(17),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_OUT GAIN(0), AUXSEND(64)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument8)
GO4K_ENV ATTAC(0),DECAY(0),SUSTAIN(128),RELEASE(0),GAIN(128)
GO4K_VCO TRANSPOSE(48),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(64),GAIN(128),FLAGS(TRISAW|LFO)
GO4K_FOP OP(FOP_MULP)
GO4K_FSTG AMOUNT(72),DEST(2*go4k_instrument.size*MAX_VOICES+10*MAX_WORKSPACE_SLOTS*4+4*4+go4k_instrument.workspace)
GO4K_FSTG AMOUNT(66),DEST(1*go4k_instrument.size*MAX_VOICES+10*MAX_WORKSPACE_SLOTS*4+4*4+go4k_instrument.workspace)
GO4K_FOP OP(FOP_POP)
GO4K_END_PARAMDEF
;// global parameters
GO4K_BEGIN_PARAMDEF(Global)
GO4K_ACC ACCTYPE(AUX)
GO4K_DLL PREGAIN(40),DRY(128),FEEDBACK(125),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(0),COUNT(8)
GO4K_FOP OP(FOP_XCH)
GO4K_DLL PREGAIN(40),DRY(128),FEEDBACK(125),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(8),COUNT(8)
GO4K_FOP OP(FOP_XCH)
GO4K_ACC ACCTYPE(OUTPUT)
GO4K_FOP OP(FOP_ADDP2)
GO4K_OUT GAIN(64), AUXSEND(0)
GO4K_END_PARAMDEF
go4k_synth_parameter_values_end
; //----------------------------------------------------------------------------------------
; // Delay/Reverb Times
; //----------------------------------------------------------------------------------------
%ifdef USE_SECTIONS
section .g4kmuc5 data align=1
%else
section .data
%endif
%ifdef GO4K_USE_DLL
global _go4k_delay_times
_go4k_delay_times
dw 0
dw 1116
dw 1188
dw 1276
dw 1356
dw 1422
dw 1492
dw 1556
dw 1618
dw 1140
dw 1212
dw 1300
dw 1380
dw 1446
dw 1516
dw 1580
dw 1642
times 100 dw 0
%endif

View File

@ -1,131 +0,0 @@
#include <stdio.h>
#include <windows.h>
#ifndef __Go4kVSTi__
#include "Go4kVSTi.h"
#endif
//-----------------------------------------------------------------------------------------
// Go4kVSTi
//-----------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------
Go4kVSTi::Go4kVSTi (audioMasterCallback audioMaster) : AudioEffectX (audioMaster, 0, 0)
{
if (audioMaster)
{
setNumInputs (0); // no inputs
setNumOutputs (2); // 2 outputs, stereo
canProcessReplacing ();
hasVu (false);
hasClip (false);
isSynth ();
setUniqueID ('4klg');
}
initProcess ();
suspend ();
}
//-----------------------------------------------------------------------------------------
Go4kVSTi::~Go4kVSTi ()
{
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::setProgram (long program)
{
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::setProgramName (char *name)
{
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::getProgramName (char *name)
{
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::getParameterLabel (long index, char *label)
{
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::getParameterDisplay (long index, char *text)
{
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::getParameterName (long index, char *label)
{
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::setParameter (long index, float value)
{
}
//-----------------------------------------------------------------------------------------
float Go4kVSTi::getParameter (long index)
{
return 0;
}
//-----------------------------------------------------------------------------------------
bool Go4kVSTi::getOutputProperties (long index, VstPinProperties* properties)
{
if (index < 2)
{
sprintf (properties->label, "Vstx %1d", index + 1);
properties->flags = kVstPinIsActive;
properties->flags |= kVstPinIsStereo; // test, make channel 1+2 stereo
return true;
}
return false;
}
//-----------------------------------------------------------------------------------------
bool Go4kVSTi::getProgramNameIndexed (long category, long index, char* text)
{
return false;
}
//-----------------------------------------------------------------------------------------
bool Go4kVSTi::copyProgram (long destination)
{
return false;
}
//-----------------------------------------------------------------------------------------
bool Go4kVSTi::getEffectName (char* name)
{
strcpy (name, "4klang");
return true;
}
//-----------------------------------------------------------------------------------------
bool Go4kVSTi::getVendorString (char* text)
{
strcpy (text, "Alcatraz");
return true;
}
//-----------------------------------------------------------------------------------------
bool Go4kVSTi::getProductString (char* text)
{
strcpy (text, "4klang");
return true;
}
//-----------------------------------------------------------------------------------------
long Go4kVSTi::canDo (char* text)
{
if (!strcmp (text, "receiveVstEvents"))
return 1;
if (!strcmp (text, "receiveVstMidiEvent"))
return 1;
if (!strcmp (text, "receiveVstTimeInfo"))
return 1;
return -1; // explicitly can't do; 0 => don't know
}

View File

@ -1,51 +0,0 @@
#ifndef __Go4kVSTi__
#define __Go4kVSTi__
#include <string.h>
#include <vector>
#ifndef __AudioEffectX__
#include "audioeffectx.h"
#endif
//------------------------------------------------------------------------------------------
class Go4kVSTi : public AudioEffectX
{
public:
Go4kVSTi(audioMasterCallback audioMaster);
~Go4kVSTi();
virtual void process(float **inputs, float **outputs, long sampleframes);
virtual void processReplacing(float **inputs, float **outputs, long sampleframes);
void processAnyhow(float **inputs, float **outputs, long sampleFrames);
virtual long processEvents(VstEvents* events);
virtual void setProgram(long program);
virtual void setProgramName(char *name);
virtual void getProgramName(char *name);
virtual void setParameter(long index, float value);
virtual float getParameter(long index);
virtual void getParameterLabel(long index, char *label);
virtual void getParameterDisplay(long index, char *text);
virtual void getParameterName(long index, char *text);
virtual void setSampleRate(float sampleRate);
virtual void setBlockSize(long blockSize);
virtual void suspend();
virtual void resume();
virtual bool getOutputProperties (long index, VstPinProperties* properties);
virtual bool getProgramNameIndexed (long category, long index, char* text);
virtual bool copyProgram (long destination);
virtual bool getEffectName (char* name);
virtual bool getVendorString (char* text);
virtual bool getProductString (char* text);
virtual long getVendorVersion () {return 1;}
virtual long canDo (char* text);
private:
void initProcess();
void ApplyEvent(VstMidiEvent *event);
std::vector<VstMidiEvent*> m_currentEvents;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,294 +0,0 @@
#include "windows.h"
// init synth
void Go4kVSTi_Init();
// clear instrument slot
void Go4kVSTi_ClearInstrumentSlot(char channel, int slot);
// clear instrument workspace
void Go4kVSTi_ClearInstrumentWorkspace(char channel);
// clear global slot
void Go4kVSTi_ClearGlobalSlot(int slot);
// clear global workspace
void Go4kVSTi_ClearGlobalWorkspace();
// reset instrument to default values
void Go4kVSTi_ResetInstrument(char channel);
// reset global to default values
void Go4kVSTi_ResetGlobal();
// reset the synth to default values
void Go4kVSTi_ResetPatch();
// flip 2 neighbour instrument slots
void Go4kVSTi_FlipInstrumentSlots(char channel, int a, int b);
// flip 2 neighbour global slots
void Go4kVSTi_FlipGlobalSlots(int a, int b);
// init a slot with given type with default values
void Go4kVSTi_InitSlot(BYTE* slot, int channel, int type);
// init a instrument slot
void Go4kVSTi_InitInstrumentSlot(char channel, int s, int type);
// init a global slot
void Go4kVSTi_InitGlobalSlot(int s, int type);
// set global bpm
void Go4kVSTi_SetBPM(float bpm);
float Go4kVSTi_GetBPM();
// activate solo mode
void Go4kVSTi_Solo(int channel, int solo);
// stream recording activation/deactivation
void Go4kVSTi_Record(bool record, int patternsize, float patternquant);
// panic
void Go4kVSTi_Panic();
// update dll times (e.g. sync to current bpm)
void Go4kVSTi_UpdateDelayTimes();
// clear delay lines
void Go4kVSTi_ClearDelayLines();
// one tick the whole synth pipeline. results are left and right output sample
void Go4kVSTi_Tick(float *oleft, float *oright, int samples);
// add a voice with given parameters to synth
void Go4kVSTi_AddVoice(int channel, int note);
// stop a voice with given parameters in synth
void Go4kVSTi_StopVoice(int channel, int note);
// load binary patch data
void Go4kVSTi_LoadPatch(char *filename);
// save binary patch data
void Go4kVSTi_SavePatch(char *filename);
// load instrumen data to specified channel
void Go4kVSTi_LoadInstrument(char* filename, char channel);
// save instrument data from current channel
void Go4kVSTi_SaveInstrument(char* filename, char channel);
// load unit data into specified slot
void Go4kVSTi_LoadUnit(char* filename, BYTE* slot);
// save unit date from specified slot
void Go4kVSTi_SaveUnit(char* filename, BYTE* slot);
#define EXPORT_OBJECT_FILE_
void Go4kVSTi_SaveByteStream(HINSTANCE hInst, char* filename, int useenvlevels, int useenotevalues, int clipoutput, int undenormalize, int objformat, int output16);
#define MAX_POLYPHONY 2
#define MAX_INSTRUMENTS 16
#define MAX_SLOT_VALUES 32
#define MAX_SLOTS 32
enum UnitID
{
M_NONE = 0,
M_ENV,
M_VCO,
M_VCF,
M_DST,
M_DLL,
M_FOP,
M_FST,
M_PAN,
M_OUT,
M_ACC,
M_FLD,
NUM_MODULES
};
/////////////////////////////////////////////////////////////////////////////////////
// value definitions
/////////////////////////////////////////////////////////////////////////////////////
#define ENV_STATE_ATTAC 0
#define ENV_STATE_DECAY 1
#define ENV_STATE_SUSTAIN 2
#define ENV_STATE_RELEASE 3
#define ENV_STATE_OFF 4
typedef struct ENV_val
{
BYTE id;
BYTE attac;
BYTE decay;
BYTE sustain;
BYTE release;
BYTE gain;
// GUI STUFF
} *ENV_valP;
#define VCO_SINE 0x01
#define VCO_TRISAW 0x02
#define VCO_PULSE 0x04
#define VCO_NOISE 0x08
#define VCO_LFO 0x10
#define VCO_GATE 0x20
typedef struct VCO_val
{
BYTE id;
BYTE transpose;
BYTE detune;
BYTE phaseofs;
BYTE gate;
BYTE color;
BYTE shape;
BYTE gain;
BYTE flags;
// GUI STUFF
} *VCO_valP;
typedef struct VCO11_val
{
BYTE id;
BYTE transpose;
BYTE detune;
BYTE phaseofs;
BYTE color;
BYTE shape;
BYTE gain;
BYTE flags;
// GUI STUFF
} *VCO11_valP;
#define VCF_LOWPASS 0x1
#define VCF_HIGHPASS 0x2
#define VCF_BANDPASS 0x4
#define VCF_BANDSTOP 0x3
#define VCF_ALLPASS 0x7
#define VCF_PEAK 0x8
typedef struct VCF_val
{
BYTE id;
BYTE freq;
BYTE res;
BYTE type;
// GUI STUFF
} *VCF_valP;
typedef struct DST_val
{
BYTE id;
BYTE drive;
BYTE snhfreq;
// GUI STUFF
} *DST_valP;
typedef struct DLL_val
{
BYTE id;
BYTE pregain;
BYTE dry;
BYTE feedback;
BYTE damp;
BYTE freq;
BYTE depth;
BYTE delay;
BYTE count;
// GUI STUFF
BYTE guidelay;
BYTE synctype;
BYTE leftreverb;
BYTE reverb;
} *DLL_valP;
typedef struct DLL10_val
{
BYTE id;
BYTE pregain;
BYTE dry;
BYTE feedback;
BYTE damp;
BYTE delay;
BYTE count;
// GUI STUFF
BYTE guidelay;
BYTE synctype;
BYTE leftreverb;
BYTE reverb;
} *DLL10_valP;
#define FOP_POP 0x1
#define FOP_ADDP 0x2
#define FOP_MULP 0x3
#define FOP_PUSH 0x4
#define FOP_XCH 0x5
#define FOP_ADD 0x6
#define FOP_MUL 0x7
#define FOP_ADDP2 0x8
#define FOP_LOADNOTE 0x9
typedef struct FOP_val
{
BYTE id;
BYTE flags;
} *FOP_valP;
typedef struct FST_val
{
BYTE id;
BYTE amount;
BYTE dest;
// GUI STUFF
char dest_stack;
char dest_unit;
char dest_slot;
char dest_id;
} *FST_valP;
typedef struct PAN_val
{
BYTE id;
BYTE panning;
// GUI STUFF
} *PAN_valP;
typedef struct OUT_val
{
BYTE id;
BYTE gain;
BYTE auxsend;
// GUI STUFF
} *OUT_valP;
#define ACC_OUT 0
#define ACC_AUX 8
typedef struct ACC_val
{
BYTE id;
BYTE flags;
} *ACC_valP;
typedef struct FLD_val
{
BYTE id;
BYTE value;
// GUI STUFF
} *FLD_valP;
/////////////////////////////////////////////////////////////////////////////////////
// workspace definitions
/////////////////////////////////////////////////////////////////////////////////////
typedef struct InstrumentWorkspace
{
DWORD release;
DWORD note;
float workspace[256];
float dlloutl;
float dlloutr;
float outl;
float outr;
} *InstrumentWorkspaceP;
typedef struct SynthObject
{
DWORD Polyphony;
char InstrumentNames[MAX_INSTRUMENTS][64];
BYTE InstrumentValues[MAX_INSTRUMENTS][MAX_SLOTS][MAX_SLOT_VALUES]; // 16 instruments a 32 slots a 32 dowrds
BYTE GlobalValues[MAX_SLOTS][MAX_SLOT_VALUES]; // 32 slots a 32 dwords
InstrumentWorkspace InstrumentWork[MAX_INSTRUMENTS*MAX_POLYPHONY];
InstrumentWorkspace GlobalWork;
DWORD InstrumentSignalValid[MAX_INSTRUMENTS];
DWORD GlobalSignalValid;
float SignalTrace[MAX_INSTRUMENTS];
int ControlInstrument[MAX_INSTRUMENTS];
int VoiceIndex[MAX_INSTRUMENTS];
} *SynthObjectP;
SynthObjectP Go4kVSTi_GetSynthObject();

File diff suppressed because it is too large Load Diff

View File

@ -1,182 +0,0 @@
#include <windows.h>
#define ButtonGroupChanged(btn_firstid, btn_lastid, test_id, seltab, result_index) \
{ \
result_index = 0; \
if (LOWORD(test_id) >= btn_firstid && \
LOWORD(test_id) <= btn_lastid) \
{ \
for (WORD bgci = btn_firstid; bgci <= btn_lastid; bgci++) \
{ \
if (LOWORD(test_id) == bgci) \
{ \
EnableWindow(GetDlgItem(ModuleWnd[seltab], bgci), false); \
result_index = bgci; \
} \
else \
{ \
EnableWindow(GetDlgItem(ModuleWnd[seltab], bgci), true); \
} \
} \
} \
}
#define EnableButtonGroup(btn_firstid, btn_lastid, seltab, btn_show) \
{ \
for (WORD bgci = btn_firstid; bgci <= btn_lastid; bgci++) \
{ \
EnableWindow(GetDlgItem(ModuleWnd[seltab], bgci), btn_show); \
} \
}
#define SetCheckboxGroupBitmask(btn_firstid, btn_lastid, seltab, input_bits) \
{ \
WORD curbitsel = 0x0001; \
for (WORD bgci = btn_firstid; bgci <= btn_lastid; bgci++,curbitsel*=2) \
{ \
SendDlgItemMessage(ModuleWnd[seltab], bgci, BM_SETCHECK, input_bits & curbitsel, 0); \
} \
}
#define GetCheckboxGroupBitmask(btn_firstid, btn_lastid, test_id, seltab, result_bits, result_index) \
{ \
result_index = 0; \
result_bits = 0; \
WORD curbitsel = 0x0001; \
if (LOWORD(test_id) >= btn_firstid && \
LOWORD(test_id) <= btn_lastid) \
{ \
for (WORD bgci = btn_firstid; bgci <= btn_lastid; bgci++,curbitsel*=2) \
{ \
if (LOWORD(test_id) == bgci) \
{ \
result_index = bgci; \
} \
if (SendDlgItemMessage(ModuleWnd[seltab], bgci, BM_GETCHECK, 0, 0)==BST_CHECKED) \
{ \
result_bits |= curbitsel; \
} \
else \
{ \
result_bits &= ~curbitsel; \
} \
} \
} \
}
#define InitSlider(tab_id, slider_id, slider_low, slider_hi, slider_pos) \
{ \
SendDlgItemMessage(tab_id, slider_id, TBM_SETRANGE, true, MAKELONG(slider_low, slider_hi)); \
SendDlgItemMessage(tab_id, slider_id, TBM_SETPOS, true, slider_pos); \
SendDlgItemMessage(tab_id, slider_id, TBM_SETLINESIZE, 0, 1); \
SendDlgItemMessage(tab_id, slider_id, TBM_SETPAGESIZE, 0, 1); \
sprintf(SliderValTxt, "%d", slider_pos); \
SetWindowText(GetDlgItem(tab_id, slider_id ## _VAL), SliderValTxt); \
}
#define InitSliderCenter(tab_id, slider_id, slider_low, slider_hi, slider_pos) \
{ \
SendDlgItemMessage(tab_id, slider_id, TBM_SETRANGE, true, MAKELONG(slider_low, slider_hi)); \
SendDlgItemMessage(tab_id, slider_id, TBM_SETPOS, true, slider_pos); \
SendDlgItemMessage(tab_id, slider_id, TBM_SETLINESIZE, 0, 1); \
SendDlgItemMessage(tab_id, slider_id, TBM_SETPAGESIZE, 0, 1); \
sprintf(SliderValTxt, "%d", slider_pos-64); \
SetWindowText(GetDlgItem(tab_id, slider_id ## _VAL), SliderValTxt); \
}
#define InitSliderCenter2(tab_id, slider_id, slider_low, slider_hi, slider_pos) \
{ \
SendDlgItemMessage(tab_id, slider_id, TBM_SETRANGE, true, MAKELONG(slider_low, slider_hi)); \
SendDlgItemMessage(tab_id, slider_id, TBM_SETPOS, true, slider_pos); \
SendDlgItemMessage(tab_id, slider_id, TBM_SETLINESIZE, 0, 1); \
SendDlgItemMessage(tab_id, slider_id, TBM_SETPAGESIZE, 0, 1); \
sprintf(SliderValTxt, "%d", (slider_pos-64)*2); \
SetWindowText(GetDlgItem(tab_id, slider_id ## _VAL), SliderValTxt); \
}
#define InitSliderNoGUI(tab_id, slider_id, slider_low, slider_hi, slider_pos) \
{ \
SendDlgItemMessage(tab_id, slider_id, TBM_SETRANGE, true, MAKELONG(slider_low, slider_hi)); \
SendDlgItemMessage(tab_id, slider_id, TBM_SETPOS, true, slider_pos); \
SendDlgItemMessage(tab_id, slider_id, TBM_SETLINESIZE, 0, 1); \
SendDlgItemMessage(tab_id, slider_id, TBM_SETPAGESIZE, 0, 1); \
}
#define DisableButtonGroup(btn_firstid, btn_lastid, seltab) \
{ \
for (WORD bgci = btn_firstid; bgci <= btn_lastid; bgci++) \
{ \
EnableWindow(GetDlgItem(ModuleWnd[seltab], bgci), true); \
} \
}
#define InterleavedButtonGroupChanged(btn_firstid, btn_count, test_id, result_index)\
{ \
result_index = -1; \
if (((LOWORD(test_id)-btn_firstid) % 6) == 0) \
{ \
for (WORD bgci = 0; bgci < btn_count; bgci++) \
{ \
WORD ibtn = btn_firstid+bgci*6; \
if (LOWORD(test_id) == ibtn) \
{ \
EnableWindow(GetDlgItem(TabWnd[SelectedTab], ibtn), false); \
result_index = bgci; \
} \
else \
{ \
EnableWindow(GetDlgItem(TabWnd[SelectedTab], ibtn), true); \
} \
} \
} \
}
#define DisableInterleavedButtonGroup(btn_firstid, btn_count, seltab) \
{ \
for (WORD bgci = 0; bgci < btn_count; bgci++) \
{ \
EnableWindow(GetDlgItem(TabWnd[seltab], btn_firstid+bgci*6), true); \
} \
}
#define UpdateSliderValue(usv_id, usv_v) \
{ \
usv_v = SendMessage(GetDlgItem(ModuleWnd[uid], usv_id), TBM_GETPOS, 0, 0); \
sprintf(SliderValTxt, "%d", usv_v); \
SetWindowText(GetDlgItem(ModuleWnd[uid], usv_id ## _VAL), SliderValTxt); \
}
#define UpdateSliderValueCenter(usv_id, usv_v) \
{ \
usv_v = SendMessage(GetDlgItem(ModuleWnd[uid], usv_id), TBM_GETPOS, 0, 0); \
sprintf(SliderValTxt, "%d", usv_v-64); \
SetWindowText(GetDlgItem(ModuleWnd[uid], usv_id ## _VAL), SliderValTxt); \
}
#define UpdateSliderValueCenter2(usv_id, usv_v) \
{ \
usv_v = SendMessage(GetDlgItem(ModuleWnd[uid], usv_id), TBM_GETPOS, 0, 0); \
sprintf(SliderValTxt, "%d", (usv_v-64)*2); \
SetWindowText(GetDlgItem(ModuleWnd[uid], usv_id ## _VAL), SliderValTxt); \
}
void Go4kVSTiGUI_Create(HINSTANCE hInst);
void Go4kVSTiGUI_Show(int showCommand);
void Go4kVSTiGUI_Destroy();
bool InitTabDlg();
bool ButtonPressed(WPARAM id, LPARAM lParam);
bool ScrollbarChanged(HWND hwndDlg, WPARAM wParam, LPARAM lParam);
bool StackButtonPressed(WPARAM id);
void TabChanged(int index);
void UpdateSignalCount(int channel);
void UpdateControls(int channel);
void UpdateModuleParamWindow(int tab, int unit);
void UpdateVoiceDisplay(int i);
void GetStreamFileName();

View File

@ -1,60 +0,0 @@
#include <windows.h>
#include <stddef.h>
#include "Go4kVSTi.h"
#include "Go4kVSTiGUI.h"
static AudioEffect *effect = 0;
bool oome = false;
//------------------------------------------------------------------------
// prototype of the export function main
int main (audioMasterCallback audioMaster);
int main (audioMasterCallback audioMaster)
{
// get vst version
if(!audioMaster (0, audioMasterVersion, 0, 0, 0, 0))
return 0; // old version
effect = new Go4kVSTi (audioMaster);
if (!effect)
return 0;
if (oome)
{
delete effect;
return 0;
}
return (int)effect->getAeffect();
}
void* hInstance;
BOOL WINAPI DllMain (HINSTANCE hInst, DWORD dwReason, LPVOID lpvReserved)
{
switch (dwReason)
{
// wird aufgerufen, wenn zum ersten mal das plugin aktiviert wird
// also hier init f<>r den synth
case DLL_PROCESS_ATTACH:
//MessageBox(NULL, "DLL_PROCESS_ATTACH", "DllMain", MB_OK);
Go4kVSTiGUI_Create(hInst);
Go4kVSTiGUI_Show(SW_SHOW);
break;
// wird aufgerufen, wenn das plugin nicht mehr verwendet wird
// entweder bei entfernen des letzten, schliessen des songs oder
// des programms. Also hier Deinit und zerst<73>rung des Synths
case DLL_PROCESS_DETACH:
//MessageBox(NULL, "DLL_PROCESS_DETACH", "DllMain", MB_OK);
Go4kVSTiGUI_Destroy();
effect = 0;
break;
// die beiden brauchts wohl nicht
case DLL_THREAD_ATTACH:
//MessageBox(NULL, "DLL_THREAD_ATTACH", "DllMain", MB_OK);
break;
case DLL_THREAD_DETACH:
//MessageBox(NULL, "DLL_THREAD_DETACH", "DllMain", MB_OK);
break;
}
hInstance = hInst;
return 1;
}

View File

@ -1,158 +0,0 @@
#ifndef __Go4kVSTi__
#include "Go4kVSTi.h"
#include "Go4kVSTiCore.h"
#include "stdio.h"
#endif
#include "math.h"
//-----------------------------------------------------------------------------------------
void Go4kVSTi::setSampleRate (float sampleRate)
{
AudioEffectX::setSampleRate (sampleRate);
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::setBlockSize (long blockSize)
{
AudioEffectX::setBlockSize (blockSize);
// you may need to have to do something here...
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::suspend ()
{
m_currentEvents.clear();
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::resume ()
{
wantEvents ();
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::initProcess ()
{
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::process (float **inputs, float **outputs, long sampleFrames)
{
processAnyhow(inputs, outputs, sampleFrames);
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::processReplacing (float **inputs, float **outputs, long sampleFrames)
{
processAnyhow(inputs, outputs, sampleFrames);
}
void Go4kVSTi::processAnyhow(float **inputs, float **outputs, long sampleFrames)
{
float* outl = outputs[0];
float* outr = outputs[1];
static int bpmCheck = 0;
if ( bpmCheck <= 0 )
{
VstTimeInfo* myTime = getTimeInfo ( kVstTempoValid );
Go4kVSTi_SetBPM(myTime->tempo);
bpmCheck = 20; // only check every 20th call of this function (bpm shouldnt change that often)
}
bpmCheck--;
int start = 0;
// midi events will occur this frame, so render partially
if (m_currentEvents.size() > 0)
{
// for all events
for (unsigned int i = 0; i < m_currentEvents.size(); i++)
{
// process samples until next event
int todo = m_currentEvents[i]->deltaFrames - start;
Go4kVSTi_Tick(outl+start, outr+start, todo);
start = m_currentEvents[i]->deltaFrames;
// apply changes due to event
ApplyEvent(m_currentEvents[i]);
}
}
Go4kVSTi_Tick(outl+start, outr+start, sampleFrames - start);
// clear event list (old event pointer wont be valid next frame anyway)
m_currentEvents.clear();
}
//-----------------------------------------------------------------------------------------
long Go4kVSTi::processEvents(VstEvents* ev)
{
for (long i = 0; i < ev->numEvents; i++)
{
if ((ev->events[i])->type != kVstMidiType)
continue;
VstMidiEvent* event = (VstMidiEvent*)ev->events[i];
m_currentEvents.push_back(event);
}
return 1; // want more
}
//-----------------------------------------------------------------------------------------
void Go4kVSTi::ApplyEvent(VstMidiEvent *event)
{
char* midiData = event->midiData;
byte status = midiData[0] & 0xf0; // status
byte channel = midiData[0] & 0x0f; // channel
// note on/off events
if (status == 0x90 || status == 0x80)
{
byte note = midiData[1] & 0x7f;
byte velocity = midiData[2] & 0x7f;
if (status == 0x80)
velocity = 0;
// note off
if (!velocity)
{
Go4kVSTi_StopVoice(channel, note);
}
// note on
else
{
Go4kVSTi_AddVoice(channel, note);
}
}
/* // polyphonic aftertouch
else if (status == 0xA)
{
byte note = midiData[1] & 0x7f;
byte pressure = midiData[2] & 0x7f;
Go4kVSTi_PolyAftertouch(channel, note, pressure);
}
// channel aftertouch
else if (status == 0xD)
{
byte pressure = midiData[1] & 0x7f;
Go4kVSTi_ChannelAftertouch(channel, pressure);
}
// Controller Change
else if (status == 0xB0)
{
byte number = midiData[1] & 0x7f;
byte value = midiData[2] & 0x7f;
// Go4kVSTi_ControllerChange(channel, number, value, event->deltaFrames);
}
// Pitch Bend
else if (status == 0xE0)
{
byte lsb = midiData[1] & 0x7f;
byte msb = midiData[2] & 0x7f;
int value = (((int)(msb)) << 7) + lsb;
// Go4kVSTi_PitchBend(channel, value); // 0 - 16383, center 8192
// dont use full precision for the sake of equally sized streams
// Go4kVSTi_PitchBend(channel, value >> 7, event->deltaFrames); // 0 - 127, center 64
}*/
// all notes off (dont seem to come anyway
else if (status == 0xb0 && midiData[1] == 0x7e) // all notes off
{
Go4kVSTi_StopVoice(channel, 0);
}
}

View File

@ -1,44 +0,0 @@
#ifndef __AEffEditor__
#define __AEffEditor__
class AudioEffect;
struct ERect
{
short top;
short left;
short bottom;
short right;
};
class AEffEditor
{
public:
AEffEditor (AudioEffect *effect) {this->effect = effect; updateFlag = 0; }
virtual ~AEffEditor() {}
virtual long getRect(ERect **rect) {*rect = 0; return 0;}
virtual long open(void *ptr) {systemWindow = ptr; return 0;}
virtual void close() {}
virtual void idle() { if(updateFlag) {updateFlag = 0; update();} }
#if MAC
virtual void draw(ERect *rect) {rect = rect;}
virtual long mouse(long x, long y) {x = x; y = y; return 0;}
virtual long key(long keyCode) {keyCode = keyCode; return 0;}
virtual void top() {}
virtual void sleep() {}
#endif
virtual void update() {}
virtual void postUpdate() {updateFlag = 1;}
protected:
AEffEditor () {};
AudioEffect *effect;
void *systemWindow;
long updateFlag;
};
#endif

View File

@ -1,172 +0,0 @@
#ifndef __AEffect__
#define __AEffect__
/*
to create an Audio Effect for power pc's, create a
code resource
file type: 'aPcs'
resource type: 'aEff'
ppc header: none (raw pef)
for windows, it's a .dll
the only symbol searched for is:
AEffect *main(float (*audioMaster)(AEffect *effect, long opcode, long index,
long value, void *ptr, float opt));
*/
#if PRAGMA_ALIGN_SUPPORTED || __MWERKS__
#pragma options align=mac68k
#elif defined CBUILDER
#pragma -a8
#elif defined(WIN32) || defined(__FLAT__)
#pragma pack(push)
#pragma pack(8)
#endif
#if defined(WIN32) || defined(__FLAT__) || defined CBUILDER
#define VSTCALLBACK __cdecl
#else
#define VSTCALLBACK
#endif
//---------------------------------------------------------------------------------------------
// misc def's
//---------------------------------------------------------------------------------------------
typedef struct AEffect AEffect;
typedef long (VSTCALLBACK *audioMasterCallback)(AEffect *effect, long opcode, long index,
long value, void *ptr, float opt);
// prototype for plug-in main
// AEffect *main(audioMasterCallback audioMaster);
#ifdef CBUILDER
#define kEffectMagic 'PtsV'
#else
#define kEffectMagic 'VstP'
#endif
//---------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------
struct AEffect
{
long magic; // must be kEffectMagic ('VstP')
long (VSTCALLBACK *dispatcher)(AEffect *effect, long opCode, long index, long value,
void *ptr, float opt);
void (VSTCALLBACK *process)(AEffect *effect, float **inputs, float **outputs, long sampleframes);
void (VSTCALLBACK *setParameter)(AEffect *effect, long index, float parameter);
float (VSTCALLBACK *getParameter)(AEffect *effect, long index);
long numPrograms;
long numParams; // all programs are assumed to have numParams parameters
long numInputs; //
long numOutputs; //
long flags; // see constants
long resvd1; // reserved, must be 0
long resvd2; // reserved, must be 0
long initialDelay; // for algorithms which need input in the first place
long realQualities; // number of realtime qualities (0: realtime)
long offQualities; // number of offline qualities (0: realtime only)
float ioRatio; // input samplerate to output samplerate ratio, not used yet
void *object; // for class access (see AudioEffect.hpp), MUST be 0 else!
void *user; // user access
long uniqueID; // pls choose 4 character as unique as possible.
// this is used to identify an effect for save+load
long version; //
void (VSTCALLBACK *processReplacing)(AEffect *effect, float **inputs, float **outputs, long sampleframes);
char future[60]; // pls zero
};
//---------------------------------------------------------------------------------------------
// flags bits
//---------------------------------------------------------------------------------------------
#define effFlagsHasEditor 1 // if set, is expected to react to editor messages
#define effFlagsHasClip 2 // return > 1. in getVu() if clipped
#define effFlagsHasVu 4 // return vu value in getVu(); > 1. means clipped
#define effFlagsCanMono 8 // if numInputs == 2, makes sense to be used for mono in
#define effFlagsCanReplacing 16 // supports in place output (processReplacing() exsists)
#define effFlagsProgramChunks 32 // program data are handled in formatless chunks
//---------------------------------------------------------------------------------------------
// dispatcher opCodes
//---------------------------------------------------------------------------------------------
enum
{
effOpen = 0, // initialise
effClose, // exit, release all memory and other resources!
effSetProgram, // program no in <value>
effGetProgram, // return current program no.
effSetProgramName, // user changed program name (max 24 char + 0) to as passed in string
effGetProgramName, // stuff program name (max 24 char + 0) into string
effGetParamLabel, // stuff parameter <index> label (max 8 char + 0) into string
// (examples: sec, dB, type)
effGetParamDisplay, // stuff parameter <index> textual representation into string
// (examples: 0.5, -3, PLATE)
effGetParamName, // stuff parameter <index> label (max 8 char + 0) into string
// (examples: Time, Gain, RoomType)
effGetVu, // called if (flags & (effFlagsHasClip | effFlagsHasVu))
// system
effSetSampleRate, // in opt (float)
effSetBlockSize, // in value
effMainsChanged, // the user has switched the 'power on' button to
// value (0 off, else on). This only switches audio
// processing; you should flush delay buffers etc.
// editor
effEditGetRect, // stuff rect (top, left, bottom, right) into ptr
effEditOpen, // system dependant Window pointer in ptr
effEditClose, // no arguments
effEditDraw, // draw method, ptr points to rect
effEditMouse, // index: x, value: y
effEditKey, // system keycode in value
effEditIdle, // no arguments. Be gentle!
effEditTop, // window has topped, no arguments
effEditSleep, // window goes to background
// new
effIdentify, // returns 'NvEf'
effGetChunk, // host requests pointer to chunk into (void**)ptr, byteSize returned
effSetChunk, // plug-in receives saved chunk, byteSize passed
effNumOpcodes
};
//---------------------------------------------------------------------------------------------
// audioMaster opCodes
//---------------------------------------------------------------------------------------------
enum
{
audioMasterAutomate = 0, // index, value, returns 0
audioMasterVersion, // vst version, currently 2 (0 for older)
audioMasterCurrentId, // returns the unique id of a plug that's currently
// loading
audioMasterIdle, // call application idle routine (this will
// call effEditIdle for all open editors too)
audioMasterPinConnected // inquire if an input or output is beeing connected;
// index enumerates input or output counting from zero,
// value is 0 for input and != 0 otherwise. note: the
// return value is 0 for <true> such that older versions
// will always return true.
};
#if PRAGMA_ALIGN_SUPPORTED || __MWERKS__
#pragma options align=reset
#elif defined(WIN32) || defined(__FLAT__)
#pragma pack(pop)
#elif defined CBUILDER
#pragma -a-
#endif
#endif // __AEffect__

View File

@ -1,382 +0,0 @@
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include "AudioEffect.hpp"
#include "AEffEditor.hpp"
//-----------------------------------------------------------------------------
long dispatchEffectClass (AEffect *e, long opCode,
long index, long value, void *ptr, float opt)
{
AudioEffect *ae = (AudioEffect *)(e->object);
if(opCode == effClose)
{
ae->dispatcher(opCode, index, value, ptr, opt);
delete ae;
return 1;
}
return ae->dispatcher(opCode, index, value, ptr, opt);
}
//-----------------------------------------------------------------------------
float getParameterClass(AEffect *e, long index)
{
AudioEffect *ae = (AudioEffect *)(e->object);
return ae->getParameter(index);
}
//-----------------------------------------------------------------------------
void setParameterClass(AEffect *e, long index, float value)
{
AudioEffect *ae = (AudioEffect *)(e->object);
ae->setParameter(index, value);
}
//-----------------------------------------------------------------------------
void processClass(AEffect *e, float **inputs, float **outputs, long sampleFrames)
{
AudioEffect *ae = (AudioEffect *)(e->object);
ae->process(inputs, outputs, sampleFrames);
}
//-----------------------------------------------------------------------------
void processClassReplacing(AEffect *e, float **inputs, float **outputs, long sampleFrames)
{
AudioEffect *ae = (AudioEffect *)(e->object);
ae->processReplacing(inputs, outputs, sampleFrames);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
AudioEffect::AudioEffect(audioMasterCallback audioMaster, long numPrograms, long numParams)
{
this->audioMaster = audioMaster;
editor = 0;
this->numPrograms = numPrograms;
this->numParams = numParams;
curProgram = 0;
memset(&cEffect, 0, sizeof(cEffect));
cEffect.magic = kEffectMagic;
cEffect.dispatcher = dispatchEffectClass;
cEffect.process = processClass;
cEffect.setParameter = setParameterClass;
cEffect.getParameter = getParameterClass;
cEffect.numPrograms = numPrograms;
cEffect.numParams = numParams;
cEffect.numInputs = 1;
cEffect.numOutputs = 2;
cEffect.flags = 0;
cEffect.resvd1 = 0;
cEffect.resvd2 = 0;
cEffect.initialDelay = 0;
cEffect.realQualities = 0;
cEffect.offQualities = 0;
cEffect.ioRatio = 1.f;
cEffect.object = this;
cEffect.user = 0;
cEffect.uniqueID = 'NoEf'; // you must set this!
cEffect.version = 1;
cEffect.processReplacing = processClassReplacing;
sampleRate = 44100.f;
blockSize = 1024L;
}
//-----------------------------------------------------------------------------
AudioEffect::~AudioEffect()
{
if(editor)
delete editor;
}
//-----------------------------------------------------------------------------
long AudioEffect::dispatcher(long opCode, long index, long value, void *ptr, float opt)
{
long v = 0;
switch(opCode)
{
case effOpen: open(); break;
case effClose: close(); break;
case effSetProgram: if(value < numPrograms) setProgram(value); break;
case effGetProgram: v = getProgram(); break;
case effSetProgramName: setProgramName((char *)ptr); break;
case effGetProgramName: getProgramName((char *)ptr); break;
case effGetParamLabel: getParameterLabel(index, (char *)ptr); break;
case effGetParamDisplay: getParameterDisplay(index, (char *)ptr); break;
case effGetParamName: getParameterName(index, (char *)ptr); break;
case effSetSampleRate: setSampleRate(opt); break;
case effSetBlockSize: setBlockSize(value); break;
case effMainsChanged: if(!value) suspend(); else resume(); break;
case effGetVu: v = (long)(getVu() * 32767.); break;
// editor
case effEditGetRect: if(editor) v = editor->getRect((ERect **)ptr); break;
case effEditOpen: if(editor) v = editor->open(ptr); break;
case effEditClose: if(editor) editor->close(); break;
case effEditIdle: if(editor) editor->idle(); break;
#if MAC
case effEditDraw: if(editor) editor->draw((ERect *)ptr); break;
case effEditMouse: if(editor) v = editor->mouse(index, value); break;
case effEditKey: if(editor) v = editor->key(value); break;
case effEditTop: if(editor) editor->top(); break;
case effEditSleep: if(editor) editor->sleep(); break;
#endif
// new
case effIdentify: v = 'NvEf'; break;
case effGetChunk: v = getChunk((void**)ptr, index ? true : false); break;
case effSetChunk: v = setChunk(ptr, value, index ? true : false); break;
}
return v;
}
//-----------------------------------------------------------------------------
long AudioEffect::getMasterVersion()
{
long version = 1;
if(audioMaster)
{
version = audioMaster(&cEffect, audioMasterVersion, 0, 0, 0, 0);
if(!version) // old
version = 1;
}
return version;
}
//-----------------------------------------------------------------------------
long AudioEffect::getCurrentUniqueId()
{
long id = 0;
if(audioMaster)
id = audioMaster(&cEffect, audioMasterCurrentId, 0, 0, 0, 0);
return id;
}
//-----------------------------------------------------------------------------
void AudioEffect::masterIdle()
{
if(audioMaster)
audioMaster(&cEffect, audioMasterIdle, 0, 0, 0, 0);
}
//-----------------------------------------------------------------------------
bool AudioEffect::isInputConnected(long input)
{
long ret = 0;
if(audioMaster)
ret = audioMaster(&cEffect, audioMasterPinConnected, input, 0, 0, 0);
return ret ? false : true; // return value is 0 for true
}
//-----------------------------------------------------------------------------
bool AudioEffect::isOutputConnected(long output)
{
long ret = 0;
if(audioMaster)
ret = audioMaster(&cEffect, audioMasterPinConnected, output, 1, 0, 0);
return ret ? false : true; // return value is 0 for true
}
//-----------------------------------------------------------------------------
// flags
//-----------------------------------------------------------------------------
void AudioEffect::hasVu(bool state)
{
if(state)
cEffect.flags |= effFlagsHasVu;
else
cEffect.flags &= ~effFlagsHasVu;
}
//-----------------------------------------------------------------------------
void AudioEffect::hasClip(bool state)
{
if(state)
cEffect.flags |= effFlagsHasClip;
else
cEffect.flags &= ~effFlagsHasClip;
}
//-----------------------------------------------------------------------------
void AudioEffect::canMono(bool state)
{
if(state)
cEffect.flags |= effFlagsCanMono;
else
cEffect.flags &= ~effFlagsCanMono;
}
//-----------------------------------------------------------------------------
void AudioEffect::canProcessReplacing(bool state)
{
if(state)
cEffect.flags |= effFlagsCanReplacing;
else
cEffect.flags &= ~effFlagsCanReplacing;
}
//-----------------------------------------------------------------------------
void AudioEffect::programsAreChunks(bool state)
{
if(state)
cEffect.flags |= effFlagsProgramChunks;
else
cEffect.flags &= ~effFlagsProgramChunks;
}
//-----------------------------------------------------------------------------
void AudioEffect::setRealtimeQualities(long qualities)
{
cEffect.realQualities = qualities;
}
//-----------------------------------------------------------------------------
void AudioEffect::setOfflineQualities(long qualities)
{
cEffect.offQualities = qualities;
}
//-----------------------------------------------------------------------------
void AudioEffect::setInitialDelay(long delay)
{
cEffect.initialDelay = delay;
}
//-----------------------------------------------------------------------------
// string
//-----------------------------------------------------------------------------
void AudioEffect::dB2string(float value, char *text)
{
if(value <= 0)
#if MAC
strcpy(text, " -<2D> ");
#else
strcpy(text, " -oo ");
#endif
else
float2string((float)(20. * log10(value)), text);
}
//-----------------------------------------------------------------------------
void AudioEffect::Hz2string(float samples, char *text)
{
float sampleRate = getSampleRate();
if(!samples)
float2string(0, text);
else
float2string(sampleRate / samples, text);
}
//-----------------------------------------------------------------------------
void AudioEffect::ms2string(float samples, char *text)
{
float2string((float)(samples * 1000. / getSampleRate()), text);
}
//-----------------------------------------------------------------------------
void AudioEffect::float2string(float value, char *text)
{
long c = 0, neg = 0;
char string[32];
char *s;
double v, integ, i10, mantissa, m10, ten = 10.;
v = (double)value;
if(v < 0)
{
neg = 1;
value = -value;
v = -v;
c++;
if(v > 9999999.)
{
strcpy(string, " Huge! ");
return;
}
}
else if(v > 99999999.)
{
strcpy(string, " Huge! ");
return;
}
s = string + 31;
*s-- = 0;
*s-- = '.';
c++;
integ = floor(v);
i10 = fmod(integ, ten);
*s-- = (long)i10 + '0';
integ /= ten;
c++;
while(integ >= 1. && c < 8)
{
i10 = fmod(integ, ten);
*s-- = (long)i10 + '0';
integ /= ten;
c++;
}
if(neg)
*s-- = '-';
strcpy(text, s + 1);
if(c >= 8)
return;
s = string + 31;
*s-- = 0;
mantissa = fmod(v, 1.);
mantissa *= pow(ten, (double)(8 - c));
while(c < 8)
{
if(mantissa <= 0)
*s-- = '0';
else
{
m10 = fmod(mantissa, ten);
*s-- = (long)m10 + '0';
mantissa /= 10.;
}
c++;
}
strcat(text, s + 1);
}
//-----------------------------------------------------------------------------
void AudioEffect::long2string(long value, char *text)
{
char string[32];
if(value >= 100000000)
{
strcpy(text, " Huge! ");
return;
}
sprintf(string, "%7d", value);
string[8] = 0;
strcpy(text, (char *)string);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void AudioEffect::setParameterAutomated(long index, float value)
{
setParameter(index, value);
if(audioMaster)
audioMaster(&cEffect, audioMasterAutomate, index, 0, 0, value); // value is in opt
}

View File

@ -1,109 +0,0 @@
#ifndef __AudioEffect__
#define __AudioEffect__
#include "AEffect.h" // "c" interface
#include <string.h>
class AEffEditor;
class AudioEffect;
// Needs to be defined by the audio effect and is
// called to create the audio effect object instance.
AudioEffect* createEffectInstance (audioMasterCallback audioMaster);
long dispatchEffectClass(AEffect *e,
long opCode, long index, long value, void *ptr, float opt);
float getParameterClass(long index);
void setParameterClass(long index, float value);
void processClass(AEffect *e, float **inputs, float **outputs, long sampleFrames);
void processClassReplacing(AEffect *e, float **inputs, float **outputs, long sampleFrames);
class AudioEffect
{
friend class AEffEditor;
friend long dispatchEffectClass(AEffect *e, long opCode, long index, long value, void *ptr, float opt);
friend float getParameterClass(AEffect *e, long index);
friend void setParameterClass(AEffect *e, long index, float value);
friend void processClass(AEffect *e, float **inputs, float **outputs, long sampleFrames);
friend void processClassReplacing(AEffect *e, float **inputs, float **outputs, long sampleFrames);
public:
AudioEffect(audioMasterCallback audioMaster, long numPrograms, long numParams);
virtual ~AudioEffect();
virtual void setParameter(long index, float value) {index = index; value = value;}
virtual float getParameter(long index) {index = index; return 0;}
virtual void setParameterAutomated(long index, float value);
AEffect *getAeffect() {return &cEffect;}
void setEditor(AEffEditor *editor)
{ this->editor = editor;
if(editor) cEffect.flags |= effFlagsHasEditor;
else cEffect.flags &= ~effFlagsHasEditor;}
// called from audio master
virtual void process(float **inputs, float **outputs, long sampleFrames) = 0;
virtual void processReplacing(float **inputs, float **outputs, long sampleFrames)
{inputs = inputs; outputs = outputs; sampleFrames = sampleFrames;}
virtual long dispatcher(long opCode, long index, long value, void *ptr, float opt);
virtual void open() {}
virtual void close() {}
virtual long getProgram() {return curProgram;}
virtual void setProgram(long program) {curProgram = program;} // don't forget to set curProgram
virtual void setProgramName(char *name) {*name = 0;} // all following refer to curProgram
virtual void getProgramName(char *name) {*name = 0;}
virtual void getParameterLabel(long index, char *label) {index = index; *label = 0;}
virtual void getParameterDisplay(long index, char *text) {index = index; *text = 0;}
virtual void getParameterName(long index, char *text) {index = index; *text = 0;}
virtual float getVu() {return 0;}
virtual long getChunk(void** data, bool isPreset = false) {return 0;} // returns byteSize
virtual long setChunk(void* data, long byteSize, bool isPreset = false) {return 0;}
virtual void setSampleRate(float sampleRate) {this->sampleRate = sampleRate;}
virtual void setBlockSize(long blockSize) {this->blockSize = blockSize;}
virtual void suspend() {}
virtual void resume() {}
// setup
virtual void setUniqueID(long iD) {cEffect.uniqueID = iD;} // must call this!
virtual void setNumInputs(long inputs) {cEffect.numInputs = inputs;}
virtual void setNumOutputs(long outputs) {cEffect.numOutputs = outputs;}
virtual void hasVu(bool state = true);
virtual void hasClip(bool state = true);
virtual void canMono(bool state = true);
virtual void canProcessReplacing(bool state = true);
virtual void programsAreChunks(bool state = true);
virtual void setRealtimeQualities(long qualities);
virtual void setOfflineQualities(long qualities);
virtual void setInitialDelay(long delay);
// inquiry
virtual float getSampleRate() {return sampleRate;}
virtual long getBlockSize() {return blockSize;}
// host communication
virtual long getMasterVersion();
virtual long getCurrentUniqueId();
virtual void masterIdle();
virtual bool isInputConnected(long input);
virtual bool isOutputConnected(long output);
// tools
virtual void dB2string(float value, char *text);
virtual void Hz2string(float samples, char *text);
virtual void ms2string(float samples, char *text);
virtual void float2string(float value, char *string);
virtual void long2string(long value, char *text);
protected:
// members
float sampleRate;
AEffEditor *editor;
audioMasterCallback audioMaster;
long numPrograms;
long numParams;
long curProgram;
long blockSize;
AEffect cEffect;
};
#endif

View File

@ -1,534 +0,0 @@
#ifndef __aeffectx__
#define __aeffectx__
#ifndef __AEffect__
#include "AEffect.h"
#endif
//-------------------------------------------------------------------------------------------------------
// VST Plug-Ins SDK
// version 2.0 extension
// (c)1999 Steinberg Soft+Hardware GmbH
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
// VstEvent
//-------------------------------------------------------------------------------------------------------
typedef struct VstEvent VstEvent;
typedef struct VstMidiEvent VstMidiEvent;
typedef struct VstEvents VstEvents;
struct VstEvent // a generic timestamped event
{
long type; // see enum below
long byteSize; // of this event, excl. type and byteSize
long deltaFrames; // sample frames related to the current block start sample position
long flags; // generic flags, none defined yet (0)
char data[16]; // size may vary but is usually 16
};
enum // VstEvent types
{
kVstMidiType = 1, // midi event, can be cast as VstMidiEvent (see below)
kVstAudioType, // audio
kVstVideoType, // video
kVstParameterType, // parameter
kVstTriggerType // trigger
// ...etc
};
struct VstMidiEvent // to be casted from a VstEvent
{
long type; // kVstMidiType
long byteSize; // 24
long deltaFrames; // sample frames related to the current block start sample position
long flags; // none defined yet
long noteLength; // (in sample frames) of entire note, if available, else 0
long noteOffset; // offset into note from note start if available, else 0
char midiData[4]; // 1 thru 3 midi bytes; midiData[3] is reserved (zero)
char detune; // -64 to +63 cents; for scales other than 'well-tempered' ('microtuning')
char noteOffVelocity;
char reserved1; // zero
char reserved2; // zero
};
struct VstEvents // a block of events for the current audio block
{
long numEvents;
long reserved; // zero
VstEvent* events[2]; // variable
};
//-------------------------------------------------------------------------------------------------------
// VstTimeInfo
//-------------------------------------------------------------------------------------------------------
typedef struct VstTimeInfo VstTimeInfo;
// VstTimeInfo as requested via audioMasterGetTime (getTimeInfo())
// refers to the current time slice. note the new slice is
// already started when processEvents() is called
struct VstTimeInfo
{
double samplePos; // current location
double sampleRate;
double nanoSeconds; // system time
double ppqPos; // 1 ppq
double tempo; // in bpm
double barStartPos; // last bar start, in 1 ppq
double cycleStartPos; // 1 ppq
double cycleEndPos; // 1 ppq
long timeSigNumerator; // time signature
long timeSigDenominator;
long smpteOffset;
long smpteFrameRate; // 0:24, 1:25, 2:29.97, 3:30, 4:29.97 df, 5:30 df
long samplesToNextClock; // midi clock resolution (24 ppq), can be negative
long flags; // see below
};
enum
{
kVstTransportChanged = 1,
kVstTransportPlaying = 1 << 1,
kVstTransportCycleActive = 1 << 2,
kVstAutomationWriting = 1 << 6,
kVstAutomationReading = 1 << 7,
// flags which indicate which of the fields in this VstTimeInfo
// are valid; samplePos and sampleRate are always valid
kVstNanosValid = 1 << 8,
kVstPpqPosValid = 1 << 9,
kVstTempoValid = 1 << 10,
kVstBarsValid = 1 << 11,
kVstCyclePosValid = 1 << 12, // start and end
kVstTimeSigValid = 1 << 13,
kVstSmpteValid = 1 << 14,
kVstClockValid = 1 << 15
};
//-------------------------------------------------------------------------------------------------------
// VarIo
//-------------------------------------------------------------------------------------------------------
typedef struct VstVariableIo VstVariableIo;
struct VstVariableIo
{
float **inputs;
float **outputs;
long numSamplesInput;
long numSamplesOutput;
long *numSamplesInputProcessed;
long *numSamplesOutputProcessed;
};
//---------------------------------------------------------------------------------------------
// new audioMaster opCodes
//---------------------------------------------------------------------------------------------
enum
{
// VstEvents + VstTimeInfo
audioMasterWantMidi = audioMasterPinConnected + 2, // <value> is a filter which is currently ignored
audioMasterGetTime, // returns const VstTimeInfo* (or 0 if not supported)
// <value> should contain a mask indicating which fields are required
// (see valid masks above), as some items may require extensive
// conversions
audioMasterProcessEvents, // VstEvents* in <ptr>
audioMasterSetTime, // VstTimenfo* in <ptr>, filter in <value>, not supported
audioMasterTempoAt, // returns tempo (in bpm * 10000) at sample frame location passed in <value>
// parameters
audioMasterGetNumAutomatableParameters,
audioMasterGetParameterQuantization, // returns the integer value for +1.0 representation,
// or 1 if full single float precision is maintained
// in automation. parameter index in <value> (-1: all, any)
// connections, configuration
audioMasterIOChanged, // numInputs and/or numOutputs has changed
audioMasterNeedIdle, // plug needs idle calls (outside its editor window)
audioMasterSizeWindow, // index: width, value: height
audioMasterGetSampleRate,
audioMasterGetBlockSize,
audioMasterGetInputLatency,
audioMasterGetOutputLatency,
audioMasterGetPreviousPlug, // input pin in <value> (-1: first to come), returns cEffect*
audioMasterGetNextPlug, // output pin in <value> (-1: first to come), returns cEffect*
// realtime info
audioMasterWillReplaceOrAccumulate, // returns: 0: not supported, 1: replace, 2: accumulate
audioMasterGetCurrentProcessLevel, // returns: 0: not supported,
// 1: currently in user thread (gui)
// 2: currently in audio thread (where process is called)
// 3: currently in 'sequencer' thread (midi, timer etc)
// 4: currently offline processing and thus in user thread
// other: not defined, but probably pre-empting user thread.
audioMasterGetAutomationState, // returns 0: not supported, 1: off, 2:read, 3:write, 4:read/write
// offline
audioMasterOfflineStart,
audioMasterOfflineRead, // ptr points to offline structure, see below. return 0: error, 1 ok
audioMasterOfflineWrite, // same as read
audioMasterOfflineGetCurrentPass,
audioMasterOfflineGetCurrentMetaPass,
// other
audioMasterSetOutputSampleRate, // for variable i/o, sample rate in <opt>
audioMasterGetSpeakerArrangement, // (long)input in <value>, output in <ptr>
audioMasterGetVendorString, // fills <ptr> with a string identifying the vendor (max 64 char)
audioMasterGetProductString, // fills <ptr> with a string with product name (max 64 char)
audioMasterGetVendorVersion, // returns vendor-specific version
audioMasterVendorSpecific, // no definition, vendor specific handling
audioMasterSetIcon, // void* in <ptr>, format not defined yet
audioMasterCanDo, // string in ptr, see below
audioMasterGetLanguage, // see enum
audioMasterOpenWindow, // returns platform specific ptr
audioMasterCloseWindow, // close window, platform specific handle in <ptr>
audioMasterGetDirectory, // get plug directory, FSSpec on MAC, else char*
audioMasterUpdateDisplay // something has changed, update 'multi-fx' display
};
enum VstHostLanguage
{
kVstLangEnglish = 1,
kVstLangGerman,
kVstLangFrench,
kVstLangItalian,
kVstLangSpanish,
kVstLangJapanese
};
//---------------------------------------------------------------------------------------------
// dispatcher opCodes
//---------------------------------------------------------------------------------------------
enum
{
// VstEvents
effProcessEvents = effSetChunk + 1, // VstEvents* in <ptr>
// parameters and programs
effCanBeAutomated, // parameter index in <index>
effString2Parameter, // parameter index in <index>, string in <ptr>
effGetNumProgramCategories, // no arguments. this is for dividing programs into groups (like GM)
effGetProgramNameIndexed, // get program name of category <value>, program <index> into <ptr>.
// category (that is, <value>) may be -1, in which case program indices
// are enumerated linearily (as usual); otherwise, each category starts
// over with index 0.
effCopyProgram, // copy current program to destination <index>
// note: implies setParameter
// connections, configuration
effConnectInput, // input at <index> has been (dis-)connected;
// <value> == 0: disconnected, else connected
effConnectOutput, // same as input
effGetInputProperties, // <index>, VstPinProperties* in ptr, return != 0 => true
effGetOutputProperties, // dto
effGetPlugCategory, // no parameter, return value is category
// realtime
effGetCurrentPosition, // for external dsp, see flag bits below
effGetDestinationBuffer, // for external dsp, see flag bits below. returns float*
// offline
effOfflineNotify, // ptr = VstAudioFile array, value = count, index = start flag
effOfflinePrepare, // ptr = VstOfflineTask array, value = count
effOfflineRun, // dto
// other
effProcessVarIo, // VstVariableIo* in <ptr>
effSetSpeakerArrangement, // VstSpeakerArrangement* pluginInput in <value>
// VstSpeakerArrangement* pluginOutput in <ptr>
effSetBlockSizeAndSampleRate, // block size in <value>, sampleRate in <opt>
effSetBypass, // onOff in <value> (0 = off)
effGetEffectName, // char* name (max 32 bytes) in <ptr>
effGetErrorText, // char* text (max 256 bytes) in <ptr>
effGetVendorString, // fills <ptr> with a string identifying the vendor (max 64 char)
effGetProductString, // fills <ptr> with a string with product name (max 64 char)
effGetVendorVersion, // returns vendor-specific version
effVendorSpecific, // no definition, vendor specific handling
effCanDo, // <ptr>
effGetTailSize, // returns tail size; 0 is default (return 1 for 'no tail')
effIdle, // idle call in response to audioMasterneedIdle. must
// return 1 to keep idle calls beeing issued
// gui
effGetIcon, // void* in <ptr>, not yet defined
effSetViewPosition, // set view position (in window) to x <index> y <value>
// and...
effGetParameterProperties, // of param <index>, VstParameterProperties* in <ptr>
effKeysRequired, // returns 0: needs keys (default for 1.0 plugs), 1: don't need
effGetVstVersion, // returns 2; older versions return 0
effNumV2Opcodes
// note that effNumOpcodes doesn't apply anymore
};
typedef struct VstParameterProperties VstParameterProperties;
typedef struct VstPinProperties VstPinProperties;
struct VstParameterProperties
{
float stepFloat;
float smallStepFloat;
float largeStepFloat;
char label[64];
long flags;
long minInteger;
long maxInteger;
long stepInteger;
long largeStepInteger;
char shortLabel[8]; // recommended: 6 + delimiter
char future[48];
};
// parameter properties flags
enum
{
kVstParameterIsSwitch = 1 << 0,
kVstParameterUsesIntegerMinMax = 1 << 1,
kVstParameterUsesFloatStep = 1 << 2,
kVstParameterUsesIntStep = 1 << 3
};
struct VstPinProperties
{
char label[64];
long flags;
long reserved;
char shortLabel[8]; // recommended: 6 + delimiter
char future[48];
};
// pin properties flags
enum
{
kVstPinIsActive = 1 << 0,
kVstPinIsStereo = 1 << 1
};
// category
enum VstPlugCategory
{
kPlugCategUnknown = 0,
kPlugCategEffect,
kPlugCategSynth,
kPlugCategAnalysis,
kPlugCategMastering,
kPlugCategSpacializer, // 'panners'
kPlugCategRoomFx, // delays and reverbs
kPlugSurroundFx // dedicated surround processor
};
//---------------------------------------------------------------------------------------------
// flags bits
//---------------------------------------------------------------------------------------------
enum
{
effFlagsIsSynth = 1 << 8, // host may assign mixer channels for its outputs
effFlagsNoSoundInStop = 1 << 9, // does not produce sound when input is all silence
effFlagsExtIsAsync = 1 << 10, // for external dsp; plug returns immedeately from process()
// host polls plug position (current block) via effGetCurrentPosition
effFlagsExtHasBuffer = 1 << 11 // external dsp, may have their own output buffe (32 bit float)
// host then requests this via effGetDestinationBuffer
};
//---------------------------------------------------------------------------------------------
// surround setup
//---------------------------------------------------------------------------------------------
typedef struct VstSpeakerProperties VstSpeakerProperties;
typedef struct VstSpeakerArrangement VstSpeakerArrangement;
struct VstSpeakerProperties
{ // units: range: except:
float azimuth; // rad -PI...PI 10.f for LFE channel
float elevation; // rad -PI/2...PI/2 10.f for LFE channel
float radius; // meter 0.f for LFE channel
float reserved; // 0.
char name[64]; // for new setups, new names should be given (L/R/C... won't do)
char future[32];
};
// note: the origin for azimuth is right (as by math conventions dealing with radians);
// the elevation origin is also right, visualizing a rotation of a circle across the
// -pi/pi axis of the horizontal circle. thus, an elevation of -pi/2 corresponds
// to bottom, and a speaker standing on the left, and 'beaming' upwards would have
// an azimuth of -pi, and an elevation of pi/2.
// for user interface representation, grads are more likely to be used, and the
// origins will obviously 'shift' accordingly.
struct VstSpeakerArrangement
{
float lfeGain; // LFE channel gain is adjusted [dB] higher than other channels
long numChannels; // number of channels in this speaker arrangement
VstSpeakerProperties speakers[8]; // variable
};
//---------------------------------------------------------------------------------------------
// offline
//---------------------------------------------------------------------------------------------
typedef struct VstOfflineTask VstOfflineTask;
typedef struct VstAudioFile VstAudioFile;
typedef struct VstAudioFileMarker VstAudioFileMarker;
struct VstOfflineTask
{
char processName[96]; // set by plug
// audio access
double readPosition; // set by plug/host
double writePosition; // set by plug/host
long readCount; // set by plug/host
long writeCount; // set by plug
long sizeInputBuffer; // set by host
long sizeOutputBuffer; // set by host
void* inputBuffer; // set by host
void* outputBuffer; // set by host
double positionToProcessFrom; // set by host
double numFramesToProcess; // set by host
double maxFramesToWrite; // set by plug
// other data access
void* extraBuffer; // set by plug
long value; // set by host or plug
long index; // set by host or plug
// file attributes
double numFramesInSourceFile; // set by host
double sourceSampleRate; // set by host or plug
double destinationSampleRate; // set by host or plug
long numSourceChannels; // set by host or plug
long numDestinationChannels; // set by host or plug
long sourceFormat; // set by host
long destinationFormat; // set by plug
char outputText[512]; // set by plug or host
// progress notification
double progress; // set by plug
long progressMode; // reserved for future
char progressText[100]; // set by plug
long flags; // set by host and plug; see VstOfflineTaskFlags
long returnValue; // reserved for future
void* hostOwned; // set by host
void* plugOwned; // set by plug
char future[1024];
};
enum VstOfflineTaskFlags
{
// set by host
kVstOfflineUnvalidParameter = 1 << 0,
kVstOfflineNewFile = 1 << 1,
// set by plug
kVstOfflinePlugError = 1 << 10,
kVstOfflineInterleavedAudio = 1 << 11,
kVstOfflineTempOutputFile = 1 << 12,
kVstOfflineFloatOutputFile = 1 << 13,
kVstOfflineRandomWrite = 1 << 14,
kVstOfflineStretch = 1 << 15,
kVstOfflineNoThread = 1 << 16
};
// option passed to offlineRead/offlineWrite
enum VstOfflineOption
{
kVstOfflineAudio, // reading/writing audio samples
kVstOfflinePeaks, // reading graphic representation
kVstOfflineParameter, // reading/writing parameters
kVstOfflineMarker, // reading/writing marker
kVstOfflineCursor, // reading/moving edit cursor
kVstOfflineSelection, // reading/changing selection
kVstOfflineQueryFiles // to request the host to call asynchronously offlineNotify
};
// structure passed to offlineNotify and offlineStart
struct VstAudioFile
{
long flags; // see enum VstAudioFileFlags
void* hostOwned; // any data private to host
void* plugOwned; // any data private to plugin
char name[100]; // file title
long uniqueId; // uniquely identify a file during a session
double sampleRate; // file sample rate
long numChannels; // number of channels (1 for mono, 2 for stereo...)
double numFrames; // number of frames in the audio file
long format; // reserved for future
double editCursorPosition; // -1 if no such cursor
double selectionStart; // frame index of first selected frame, or -1
double selectionSize; // number of frames in selection, or 0
long selectedChannelsMask; // 1 bit per channel
long numMarkers; // number of markers in the file
long timeRulerUnit; // see doc for possible values
double timeRulerOffset; // offset in time ruler (positive or negative)
double tempo; // as bpm
long timeSigNumerator; // time signature numerator
long timeSigDenominator; // time signature denominator
long ticksPerBlackNote; // resolution
long smpteFrameRate; // smpte rate (set as in VstTimeInfo)
char future[64];
};
enum VstAudioFileFlags
{
// set by host (in call offlineNotify)
kVstOfflineReadOnly = 1 << 0,
kVstOfflineNoRateConversion = 1 << 1,
kVstOfflineNoChannelChange = 1 << 2,
// Set by plug (in function offlineStart)
kVstOfflineCanProcessSelection = 1 << 10,
kVstOfflineNoCrossfade = 1 << 11,
kVstOfflineWantRead = 1 << 12,
kVstOfflineWantWrite = 1 << 13,
kVstOfflineWantWriteMarker = 1 << 14,
kVstOfflineWantMoveCursor = 1 << 15,
kVstOfflineWantSelect = 1 << 16
};
struct VstAudioFileMarker
{
double position;
char name[32];
long type;
long id;
long reserved;
};
//---------------------------------------------------------------------------------------------
// others
//---------------------------------------------------------------------------------------------
// structure passed to openWindow and closeWindow
struct VstWindow
{
char title[128]; // title
short xPos; // position and size
short yPos;
short width;
short height;
long style; // 0: with title, 1: without title
void *parent; // parent of this window
void *userHandle; // reserved
void *winHandle; // reserved
char future[104];
};
#endif

View File

@ -1,558 +0,0 @@
#ifndef __audioeffectx__
#include "audioeffectx.h"
#endif
// *** steinberg developers: this is a public file, *do not edit!*
//-------------------------------------------------------------------------------------------------------
// VST Plug-Ins SDK
// version 2.0 extension
// (c)1999 Steinberg Soft+Hardware GmbH
//
// you should not have to edit this file
// use override methods instead, as suggested in the class declaration (audioeffectx.h)
//-------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------
// 'canDo' strings. note other 'canDos' can be evaluated by calling the according
// function, for instance if getSampleRate returns 0, you
// will certainly want to assume that this selector is not supported.
//---------------------------------------------------------------------------------------------
const char* hostCanDos [] =
{
"sendVstEvents",
"sendVstMidiEvent",
"sendVstTimeInfo",
"receiveVstEvents",
"receiveVstMidiEvent",
"receiveVstTimeInfo",
"reportConnectionChanges",
"acceptIOChanges",
"sizeWindow",
"asyncProcessing",
"offline",
"supplyIdle",
"supportShell" // 'shell' handling via uniqueID as suggested by Waves
};
const char* plugCanDos [] =
{
"sendVstEvents",
"sendVstMidiEvent",
"sendVstTimeInfo",
"receiveVstEvents",
"receiveVstMidiEvent",
"receiveVstTimeInfo",
"offline",
"plugAsChannelInsert",
"plugAsSend",
"mixDryWet",
"noRealTime",
"multipass",
"metapass",
"1in1out",
"1in2out",
"2in1out",
"2in2out",
"2in4out",
"4in2out",
"4in4out",
"4in8out", // 4:2 matrix to surround bus
"8in4out", // surround bus to 4:2 matrix
"8in8out"
};
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
// AudioEffectX extends AudioEffect with the new features. so you should derive
// your plug from AudioEffectX
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
// VstEvents + VstTimeInfo
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
AudioEffectX::AudioEffectX (audioMasterCallback audioMaster, long numPrograms, long numParams)
: AudioEffect (audioMaster, numPrograms, numParams)
{
}
//-------------------------------------------------------------------------------------------------------
AudioEffectX::~AudioEffectX ()
{
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::dispatcher (long opCode, long index, long value, void *ptr, float opt)
{
long v = 0;
switch(opCode)
{
// VstEvents
case effProcessEvents:
v = processEvents ((VstEvents*)ptr);
break;
// parameters and programs
case effCanBeAutomated:
v = canParameterBeAutomated (index) ? 1 : 0;
break;
case effString2Parameter:
v = string2parameter (index, (char*)ptr) ? 1 : 0;
break;
case effGetNumProgramCategories:
v = getNumCategories ();
break;
case effGetProgramNameIndexed:
v = getProgramNameIndexed (value, index, (char*)ptr) ? 1 : 0;
break;
case effCopyProgram:
v = copyProgram (index) ? 1 : 0;
break;
// connections, configuration
case effConnectInput:
inputConnected (index, value ? true : false);
v = 1;
break;
case effConnectOutput:
outputConnected (index, value ? true : false);
v = 1;
break;
case effGetInputProperties:
v = getInputProperties (index, (VstPinProperties*)ptr) ? 1 : 0;
break;
case effGetOutputProperties:
v = getOutputProperties (index, (VstPinProperties*)ptr) ? 1 : 0;
break;
case effGetPlugCategory:
v = (long)getPlugCategory ();
break;
// realtime
case effGetCurrentPosition:
v = reportCurrentPosition ();
break;
case effGetDestinationBuffer:
v = (long)reportDestinationBuffer ();
break;
// offline
case effOfflineNotify:
v = offlineNotify ((VstAudioFile*)ptr, value, index != 0);
break;
case effOfflinePrepare:
v = offlinePrepare ((VstOfflineTask*)ptr, value);
break;
case effOfflineRun:
v = offlineRun ((VstOfflineTask*)ptr, value);
break;
// other
case effSetSpeakerArrangement:
v = setSpeakerArrangement ((VstSpeakerArrangement*)value, (VstSpeakerArrangement*)ptr) ? 1 : 0;
break;
case effProcessVarIo:
v = processVariableIo ((VstVariableIo*)ptr) ? 1 : 0;
break;
case effSetBlockSizeAndSampleRate:
setBlockSizeAndSampleRate (value, opt);
v = 1;
break;
case effSetBypass:
v = setBypass (value ? true : false) ? 1 : 0;
break;
case effGetEffectName:
v = getEffectName ((char *)ptr) ? 1 : 0;
break;
case effGetErrorText:
v = getErrorText ((char *)ptr) ? 1 : 0;
break;
case effGetVendorString:
v = getVendorString ((char *)ptr) ? 1 : 0;
break;
case effGetProductString:
v = getProductString ((char *)ptr) ? 1 : 0;
break;
case effGetVendorVersion:
v = getVendorVersion ();
break;
case effVendorSpecific:
v = vendorSpecific (index, value, ptr, opt);
break;
case effCanDo:
v = canDo ((char*)ptr);
break;
case effGetIcon:
v = (long)getIcon ();
break;
case effSetViewPosition:
v = setViewPosition (index, value) ? 1 : 0;
break;
case effGetTailSize:
v = getGetTailSize ();
break;
case effIdle:
v = fxIdle ();
break;
case effGetParameterProperties:
v = getParameterProperties (index, (VstParameterProperties*)ptr) ? 1 : 0;
break;
case effKeysRequired:
v = (keysRequired () ? 0 : 1); // reversed to keep v1 compatibility
break;
case effGetVstVersion:
v = getVstVersion ();
break;
// version 1.0 or unknown
default:
v = AudioEffect::dispatcher (opCode, index, value, ptr, opt);
}
return v;
}
//-------------------------------------------------------------------------------------------------------
void AudioEffectX::wantEvents (long filter)
{
if (audioMaster)
audioMaster (&cEffect, audioMasterWantMidi, 0, filter, 0, 0);
}
//-------------------------------------------------------------------------------------------------------
VstTimeInfo* AudioEffectX::getTimeInfo (long filter)
{
if (audioMaster)
return (VstTimeInfo*) audioMaster (&cEffect, audioMasterGetTime, 0, filter, 0, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::tempoAt (long pos)
{
if (audioMaster)
return audioMaster (&cEffect, audioMasterTempoAt, 0, pos, 0, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
bool AudioEffectX::sendVstEventsToHost (VstEvents* events)
{
if (audioMaster)
return audioMaster (&cEffect, audioMasterProcessEvents, 0, 0, events, 0) == 1;
return 0;
}
//-------------------------------------------------------------------------------------------------------
// parameters
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::getNumAutomatableParameters ()
{
if (audioMaster)
return audioMaster (&cEffect, audioMasterGetNumAutomatableParameters, 0, 0, 0, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::getParameterQuantization ()
{
if (audioMaster)
return audioMaster (&cEffect, audioMasterGetParameterQuantization, 0, 0, 0, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
// configuration
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
bool AudioEffectX::ioChanged ()
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterIOChanged, 0, 0, 0, 0) != 0);
return false;
}
//-------------------------------------------------------------------------------------------------------
bool AudioEffectX::needIdle ()
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterNeedIdle, 0, 0, 0, 0) != 0);
return false;
}
//-------------------------------------------------------------------------------------------------------
bool AudioEffectX::sizeWindow (long width, long height)
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterSizeWindow, width, height, 0, 0) != 0);
return false;
}
//-------------------------------------------------------------------------------------------------------
double AudioEffectX::updateSampleRate ()
{
if (audioMaster)
audioMaster (&cEffect, audioMasterGetSampleRate, 0, 0, 0, 0); // calls setSampleRate if implemented
return sampleRate;
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::updateBlockSize ()
{
if (audioMaster)
audioMaster (&cEffect, audioMasterGetBlockSize, 0, 0, 0, 0); // calls setBlockSize if implemented
return blockSize;
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::getInputLatency ()
{
if (audioMaster)
return audioMaster (&cEffect, audioMasterGetInputLatency, 0, 0, 0, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::getOutputLatency ()
{
if (audioMaster)
return audioMaster (&cEffect, audioMasterGetOutputLatency, 0, 0, 0, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
AEffect* AudioEffectX::getPreviousPlug (long input)
{
if (audioMaster)
return (AEffect*) audioMaster (&cEffect, audioMasterGetPreviousPlug, 0, 0, 0, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
AEffect* AudioEffectX::getNextPlug (long output)
{
if (audioMaster)
return (AEffect*) audioMaster (&cEffect, audioMasterGetNextPlug, 0, 0, 0, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
// configuration
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::willProcessReplacing ()
{
if (audioMaster)
return audioMaster (&cEffect, audioMasterWillReplaceOrAccumulate, 0, 0, 0, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::getCurrentProcessLevel ()
{
if (audioMaster)
return audioMaster (&cEffect, audioMasterGetCurrentProcessLevel, 0, 0, 0, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::getAutomationState ()
{
if (audioMaster)
return audioMaster (&cEffect, audioMasterGetAutomationState, 0, 0, 0, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
void AudioEffectX::wantAsyncOperation (bool state)
{
if (state)
cEffect.flags |= effFlagsExtIsAsync;
else
cEffect.flags &= ~effFlagsExtIsAsync;
}
//-------------------------------------------------------------------------------------------------------
void AudioEffectX::hasExternalBuffer (bool state)
{
if (state)
cEffect.flags |= effFlagsExtHasBuffer;
else
cEffect.flags &= ~effFlagsExtHasBuffer;
}
//-------------------------------------------------------------------------------------------------------
// offline
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
bool AudioEffectX::offlineRead (VstOfflineTask* offline, VstOfflineOption option, bool readSource)
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterOfflineRead, readSource, option, offline, 0) != 0);
return false;
}
//-------------------------------------------------------------------------------------------------------
bool AudioEffectX::offlineWrite (VstOfflineTask* offline, VstOfflineOption option)
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterOfflineWrite, 0, option, offline, 0) != 0);
return false;
}
//-------------------------------------------------------------------------------------------------------
bool AudioEffectX::offlineStart (VstAudioFile* audioFiles, long numAudioFiles, long numNewAudioFiles)
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterOfflineStart, numNewAudioFiles, numAudioFiles, audioFiles, 0) != 0);
return false;
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::offlineGetCurrentPass ()
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterOfflineGetCurrentPass, 0, 0, 0, 0) != 0);
return false;
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::offlineGetCurrentMetaPass ()
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterOfflineGetCurrentMetaPass, 0, 0, 0, 0) != 0);
return false;
}
//-------------------------------------------------------------------------------------------------------
// other
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
void AudioEffectX::setOutputSamplerate (float sampleRate)
{
if (audioMaster)
audioMaster (&cEffect, audioMasterSetOutputSampleRate, 0, 0, 0, sampleRate);
}
//-------------------------------------------------------------------------------------------------------
bool AudioEffectX::getSpeakerArrangement (VstSpeakerArrangement* pluginInput, VstSpeakerArrangement* pluginOutput)
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterGetSpeakerArrangement, 0, (long)pluginInput, pluginOutput, 0) != 0);
return false;
}
//-------------------------------------------------------------------------------------------------------
bool AudioEffectX::getHostVendorString (char* text)
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterGetVendorString, 0, 0, text, 0) != 0);
return false;
}
//-------------------------------------------------------------------------------------------------------
bool AudioEffectX::getHostProductString (char* text)
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterGetProductString, 0, 0, text, 0) != 0);
return false;
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::getHostVendorVersion ()
{
if (audioMaster)
return audioMaster (&cEffect, audioMasterGetVendorVersion, 0, 0, 0, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::hostVendorSpecific (long lArg1, long lArg2, void* ptrArg, float floatArg)
{
if (audioMaster)
return audioMaster (&cEffect, audioMasterVendorSpecific, lArg1, lArg2, ptrArg, floatArg);
return 0;
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::canHostDo (char* text)
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterCanDo, 0, 0, text, 0) != 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
void AudioEffectX::isSynth (bool state)
{
if (state)
cEffect.flags |= effFlagsIsSynth;
else
cEffect.flags &= ~effFlagsIsSynth;
}
//-------------------------------------------------------------------------------------------------------
void AudioEffectX::noTail (bool state)
{
if (state)
cEffect.flags |= effFlagsNoSoundInStop;
else
cEffect.flags &= ~effFlagsNoSoundInStop;
}
//-------------------------------------------------------------------------------------------------------
long AudioEffectX::getHostLanguage ()
{
if (audioMaster)
return audioMaster (&cEffect, audioMasterGetLanguage, 0, 0, 0, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
void* AudioEffectX::openWindow (VstWindow* window)
{
if (audioMaster)
return (void*)audioMaster (&cEffect, audioMasterOpenWindow, 0, 0, window, 0);
return 0;
}
//-------------------------------------------------------------------------------------------------------
bool AudioEffectX::closeWindow (VstWindow* window)
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterCloseWindow, 0, 0, window, 0) != 0);
return false;
}
//-------------------------------------------------------------------------------------------------------
void* AudioEffectX::getDirectory ()
{
if (audioMaster)
return (void*)(audioMaster (&cEffect, audioMasterGetDirectory, 0, 0, 0, 0));
return 0;
}
//-------------------------------------------------------------------------------------------------------
bool AudioEffectX::updateDisplay()
{
if (audioMaster)
return (audioMaster (&cEffect, audioMasterUpdateDisplay, 0, 0, 0, 0)) ? true : false;
return 0;
}

View File

@ -1,185 +0,0 @@
#ifndef __audioeffectx__
#define __audioeffectx__
//----------------------------------------------------------------------------------------------------------------------------
// VST Plug-Ins SDK
// version 2.0 extension
// (c)1999 Steinberg Soft+Hardware GmbH
//----------------------------------------------------------------------------------------------------------------------------
#ifndef __AudioEffect__
#include "AudioEffect.hpp" // version 1.0 base class AudioEffect
#endif
#ifndef __aeffectx__
#include "aeffectx.h" // version 2.0 'C' extensions and structures
#endif
//----------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------
// AudioEffectX extends AudioEffect with the new features. so you should derive
// your plug from AudioEffectX
//----------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------
class AudioEffectX : public AudioEffect
{
public:
AudioEffectX (audioMasterCallback audioMaster, long numPrograms, long numParams);
virtual ~AudioEffectX ();
virtual long dispatcher (long opCode, long index, long value, void *ptr, float opt);
// 'host' are methods which go from plug to host, and are usually not overridden
// 'plug' are methods which you may override to implement the according functionality (to host)
//----------------------------------------------------------------------------------------------------------------------------
// events + time
//----------------------------------------------------------------------------------------------------------------------------
// host
virtual void wantEvents (long filter = 1); // filter is currently ignored, midi channel data only (default)
virtual VstTimeInfo* getTimeInfo (long filter);
// returns const VstTimeInfo* (or 0 if not supported)
// filter should contain a mask indicating which fields are requested
// (see valid masks in aeffectx.h), as some items may require extensive
// conversions
virtual long tempoAt (long pos); // returns tempo (in bpm * 10000) at sample frame location <pos>
bool sendVstEventsToHost (VstEvents* events); // true:success
// plug
virtual long processEvents (VstEvents* events) {return 0;} // wants no more...else return 1!
// VstEvents and VstMidiEvents are declared in aeffectx.h
//----------------------------------------------------------------------------------------------------------------------------
// parameters and programs
//----------------------------------------------------------------------------------------------------------------------------
// host
virtual long getNumAutomatableParameters ();
virtual long getParameterQuantization (); // returns the integer value for +1.0 representation,
// or 1 if full single float precision is maintained
// in automation. parameter index in <value> (-1: all, any)
// plug
virtual bool canParameterBeAutomated (long index) { return true; }
virtual bool string2parameter (long index, char* text) {return false;} // note: implies setParameter. text==0 is to be
// expected to check the capability (returns true).
virtual float getChannelParameter (long channel, long index) {return 0;}
virtual long getNumCategories () {return 1L;}
virtual bool getProgramNameIndexed (long category, long index, char* text) {return false;}
virtual bool copyProgram (long destination) {return false;}
//----------------------------------------------------------------------------------------------------------------------------
// connections, configuration
//----------------------------------------------------------------------------------------------------------------------------
// host
virtual bool ioChanged (); // tell host numInputs and/or numOutputs and/or numParameters has changed
virtual bool needIdle (); // plug needs idle calls (outside its editor window)
virtual bool sizeWindow (long width, long height);
virtual double updateSampleRate (); // gets and returns sample rate from host (may issue setSampleRate() )
virtual long updateBlockSize (); // same for block size
virtual long getInputLatency ();
virtual long getOutputLatency ();
virtual AEffect* getPreviousPlug (long input); // input can be -1 in which case the first found is returned
virtual AEffect* getNextPlug (long output); // output can be -1 in which case the first found is returned
// plug
virtual void inputConnected (long index, bool state) {} // input at <index> has been (dis-)connected,
virtual void outputConnected (long index, bool state) {} // same as input; state == true: connected
virtual bool getInputProperties (long index, VstPinProperties* properties) {return false;}
virtual bool getOutputProperties (long index, VstPinProperties* properties) {return false;}
virtual VstPlugCategory getPlugCategory()
{ if (cEffect.flags & effFlagsIsSynth) return kPlugCategSynth; return kPlugCategUnknown; }
//----------------------------------------------------------------------------------------------------------------------------
// realtime
//----------------------------------------------------------------------------------------------------------------------------
// host
virtual long willProcessReplacing (); // returns 0: not implemented, 1: replacing, 2: accumulating
virtual long getCurrentProcessLevel (); // returns: 0: not supported,
// 1: currently in user thread (gui)
// 2: currently in audio thread or irq (where process is called)
// 3: currently in 'sequencer' thread or irq (midi, timer etc)
// 4: currently offline processing and thus in user thread
// other: not defined, but probably pre-empting user thread.
virtual long getAutomationState (); // returns 0: not supported, 1: off, 2:read, 3:write, 4:read/write
virtual void wantAsyncOperation (bool state = true); // notify host that we want to operate asynchronously.
// process() will return immedeately; host will poll getCurrentPosition
// to see if data are available in time.
virtual void hasExternalBuffer (bool state = true); // external dsp, may have their own output buffe (32 bit float)
// host then requests this via effGetDestinationBuffer
// plug
virtual long reportCurrentPosition () {return 0;} // for external dsp, see wantAsyncOperation ()
virtual float* reportDestinationBuffer () {return 0;} // for external dsp (dma option)
//----------------------------------------------------------------------------------------------------------------------------
// offline
//----------------------------------------------------------------------------------------------------------------------------
// host
virtual bool offlineRead (VstOfflineTask* offline, VstOfflineOption option, bool readSource = true);
virtual bool offlineWrite (VstOfflineTask* offline, VstOfflineOption option);
virtual bool offlineStart (VstAudioFile* ptr, long numAudioFiles, long numNewAudioFiles);
virtual long offlineGetCurrentPass ();
virtual long offlineGetCurrentMetaPass ();
// plug
virtual bool offlineNotify (VstAudioFile* ptr, long numAudioFiles, bool start) { return false; }
virtual bool offlinePrepare (VstOfflineTask* offline, long count) {return false;}
virtual bool offlineRun (VstOfflineTask* offline, long count) {return false;}
virtual long offlineGetNumPasses () {return 0;}
virtual long offlineGetNumMetaPasses () {return 0;}
//----------------------------------------------------------------------------------------------------------------------------
// other
//----------------------------------------------------------------------------------------------------------------------------
// host
virtual void setOutputSamplerate (float samplerate);
virtual bool getSpeakerArrangement (VstSpeakerArrangement* pluginInput, VstSpeakerArrangement* pluginOutput);
virtual bool getHostVendorString (char* text); // fills <text> with a string identifying the vendor (max 64 char)
virtual bool getHostProductString (char* text); // fills <text> with a string with product name (max 64 char)
virtual long getHostVendorVersion (); // returns vendor-specific version
virtual long hostVendorSpecific (long lArg1, long lArg2, void* ptrArg, float floatArg); // no definition
virtual long canHostDo (char* text); // see 'hostCanDos' in audioeffectx.cpp
// returns 0: don't know (default), 1: yes, -1: no
virtual void isSynth (bool state = true); // will call wantEvents if true
virtual void noTail (bool state = true); // true: tells host we produce no output when silence comes in
// enables host to omit process() when no data are present
// on any one input.
virtual long getHostLanguage (); // returns VstHostLanguage
virtual void* openWindow (VstWindow*); // create new window
virtual bool closeWindow (VstWindow*); // close a newly created window
virtual void* getDirectory (); // get the plug's directory, FSSpec on mac, else char*
virtual bool updateDisplay(); // something has changed, update 'multi-fx' display
// returns true if supported
// plug
virtual bool processVariableIo (VstVariableIo* varIo) {return false;}
virtual bool setSpeakerArrangement (VstSpeakerArrangement* pluginInput, VstSpeakerArrangement* pluginOutput) {return false;}
virtual void setBlockSizeAndSampleRate (long blockSize, float sampleRate)
{this->blockSize = blockSize; this->sampleRate = sampleRate;}
virtual bool setBypass(bool onOff) {return false;} // for 'soft-bypass; process() still called
virtual bool getEffectName (char* name) {return false;} // name max 32 char
virtual bool getErrorText (char* text) {return false;} // max 256 char
virtual bool getVendorString (char* text) {return false;} // fill text with a string identifying the vendor (max 64 char)
virtual bool getProductString (char* text) {return false;} // fill text with a string identifying the product name (max 64 char) // fills <ptr> with a string with product name (max 64 char)
virtual long getVendorVersion () {return 0;} // return vendor-specific version
virtual long vendorSpecific (long lArg, long lArg2, void* ptrArg, float floatArg) {return 0;}
// no definition, vendor specific handling
virtual long canDo (char* text) {return 0;} // see 'plugCanDos' in audioeffectx.cpp. return values:
// 0: don't know (default), 1: yes, -1: no
virtual void* getIcon () {return 0;} // not yet defined
virtual bool setViewPosition (long x, long y) {return false;}
virtual long getGetTailSize () {return 0; }
virtual long fxIdle () {return 0;}
virtual bool getParameterProperties (long index, VstParameterProperties* p) {return false;}
virtual bool keysRequired () {return false;} // version 1 plugs will return true
virtual long getVstVersion () {return 2;}
};
#endif

View File

@ -1,628 +0,0 @@
//-----------------------------------------------------------------------------
// VST Plug-Ins SDK
// Simple user interface framework for VST plugins
// Standard control objects
//
// Version 1.0
//
// First version : Wolfgang Kundrus
// Added new objects : Michael Schmidt 08.97
// Added new objects : Yvan Grabit 01.98
//
// (c)1999 Steinberg Soft+Hardware GmbH
//-----------------------------------------------------------------------------
#ifndef __vstcontrols__
#define __vstcontrols__
#ifndef __vstgui__
#include "vstgui.h"
#endif
//------------------
// defines
//------------------
#ifndef kPI
#define kPI 3.14159265358979323846
#endif
#ifndef k2PI
#define k2PI 6.28318530717958647692
#endif
#ifndef kPI_2
#define kPI_2 1.57079632679489661923f
#endif
#ifndef kPI_4
#define kPI_4 0.78539816339744830962
#endif
#ifndef kE
#define kE 2.7182818284590452354
#endif
#ifndef kLN2
#define kLN2 0.69314718055994530942
#endif
//------------------
// CControlEnum type
//------------------
enum CControlEnum
{
kHorizontal = 1 << 0,
kVertical = 1 << 1,
kShadowText = 1 << 2,
kLeft = 1 << 3,
kRight = 1 << 4,
kTop = 1 << 5,
kBottom = 1 << 6,
k3DIn = 1 << 7,
k3DOut = 1 << 8,
kPopupStyle = 1 << 9,
kCheckStyle = 1 << 10
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CControlListener
{
public:
virtual void valueChanged (CDrawContext *context, CControl *control) = 0;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CControl : public CView
{
public:
CControl (CRect &size, CControlListener *listener, int tag);
virtual ~CControl ();
virtual void draw (CDrawContext *context) = 0;
virtual void update (CDrawContext *context);
virtual void doIdleStuff () { if (parent) parent->doIdleStuff (); }
virtual void setValue (float val) { value = val; }
virtual float getValue () { return value; };
virtual void setMin (float val) { vmin = val; }
virtual float getMin () { return vmin; }
virtual void setMax (float val) { vmax = val; }
virtual float getMax () { return vmax; }
virtual void setOldValue (float val) { oldValue = val; }
virtual float getOldValue (void) { return oldValue; }
virtual void setDefaultValue (float val) { defaultValue = val; }
virtual float getDefaultValue (void) { return defaultValue; }
inline int getTag () { return tag; }
virtual void setMouseEnabled (bool bEnable = true) { bMouseEnabled = bEnable; }
virtual bool getMouseEnabled () { return bMouseEnabled; }
protected:
CControlListener *listener;
long tag;
bool dirty;
bool bMouseEnabled;
float oldValue;
float defaultValue;
float value;
float vmin;
float vmax;
float step;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class COnOffButton : public CControl
{
public:
COnOffButton (CRect &size, CControlListener *listener, int tag,
CBitmap *handle);
virtual ~COnOffButton ();
virtual void draw (CDrawContext*);
virtual void mouse (CDrawContext *context, CPoint &where);
protected:
CBitmap *handle;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CParamDisplay : public CControl
{
public:
CParamDisplay (CRect &size, CBitmap *background = 0, int style = 0);
virtual ~CParamDisplay ();
virtual void setFont (CFont fontID);
virtual void setFontColor (CColor color);
virtual void setBackColor (CColor color);
virtual void setFrameColor (CColor color);
virtual void setShadowColor (CColor color);
virtual void setHoriAlign (CHoriTxtAlign hAlign);
virtual void setBackOffset (CPoint &offset);
virtual void setStringConvert (void (*stringConvert) (float value, char *string));
virtual void draw (CDrawContext *context);
protected:
void drawText (CDrawContext *context, char *string, CBitmap *newBack = 0);
CHoriTxtAlign horiTxtAlign;
int style;
CFont fontID;
CColor fontColor;
CColor backColor;
CColor frameColor;
CColor shadowColor;
CPoint offset;
CBitmap *background;
private:
void (*stringConvert) (float value, char *string);
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CTextEdit : public CParamDisplay
{
public:
CTextEdit (CRect &size, CControlListener *listener, int tag, const char *txt = 0,
CBitmap *background = 0,
int style = 0);
~CTextEdit ();
virtual void setText (char *txt);
virtual void getText (char *txt);
virtual void draw (CDrawContext *context);
virtual void mouse (CDrawContext *context, CPoint &where);
virtual void setTextEditConvert (void (*stringConvert) (char *input, char *string));
virtual void takeFocus ();
virtual void looseFocus ();
protected:
void *platformControl;
void *platformFont;
char text[256];
private:
void (*stringConvert) (char *input, char *string);
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#define MAX_ENTRY 128
class COptionMenu : public CParamDisplay
{
public:
COptionMenu (CRect &size, CControlListener *listener, int tag,
CBitmap *background = 0, CBitmap *bgWhenClick = 0,
int style = 0);
~COptionMenu ();
virtual bool addEntry (char *txt, int index = -1);
virtual int getCurrent (char *txt = 0);
virtual bool setCurrent (int index);
virtual bool getEntry (int index, char *txt);
virtual bool removeEntry (int index);
virtual bool removeAllEntry ();
virtual int getNbEntries () { return nbEntries; }
virtual void draw (CDrawContext *context);
virtual void mouse (CDrawContext *context, CPoint &where);
virtual void takeFocus ();
virtual void looseFocus ();
#if MOTIF
void setCurrentSelected (void *itemSelected);
#endif
protected:
void *platformControl;
char *entry[MAX_ENTRY];
#if MOTIF
void *itemWidget[MAX_ENTRY];
#endif
int nbEntries;
int currentIndex;
CBitmap *bgWhenClick;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CKnob : public CControl
{
public:
CKnob (CRect &size, CControlListener *listener, int tag,
CBitmap *background,
CBitmap *handle, CPoint &offset);
virtual ~CKnob ();
virtual void draw (CDrawContext*);
virtual void mouse (CDrawContext *context, CPoint &where);
virtual void valueToPoint (CPoint &point);
virtual float valueFromPoint (CPoint &point);
virtual void setBackground (CBitmap* background);
virtual CBitmap *getBackground () { return background; }
protected:
int inset;
CBitmap *background;
CBitmap *handle;
CPoint offset;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CAnimKnob : public CKnob
{
public:
CAnimKnob (CRect &size, CControlListener *listener, int tag,
int subPixmaps, // number of subPixmaps
int heightOfOneImage, // pixel
CBitmap *handle, CPoint &offset);
virtual ~CAnimKnob ();
virtual void draw (CDrawContext*);
protected:
int subPixmaps; // number of subPixmaps
int heightOfOneImage;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CVerticalSwitch : public CControl
{
public:
CVerticalSwitch (CRect &size, CControlListener *listener, int tag,
int subPixmaps, // number of subPixmaps
int heightOfOneImage, // pixel
int iMaxPositions,
CBitmap *handle, CPoint &offset);
virtual ~CVerticalSwitch ();
virtual void draw (CDrawContext*);
virtual void mouse (CDrawContext *context, CPoint &where);
protected:
CBitmap *handle;
CPoint offset;
int subPixmaps; // number of subPixmaps
int heightOfOneImage;
int iMaxPositions;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CHorizontalSwitch : public CControl
{
public:
CHorizontalSwitch (CRect &size, CControlListener *listener, int tag,
int subPixmaps, // number of subPixmaps
int heightOfOneImage, // pixel
int iMaxPositions,
CBitmap *handle,
CPoint &offset);
virtual ~CHorizontalSwitch ();
virtual void draw (CDrawContext*);
virtual void mouse (CDrawContext *context, CPoint &where);
protected:
CBitmap *handle;
CPoint offset;
int subPixmaps; // number of subPixmaps
int heightOfOneImage;
int iMaxPositions;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CRockerSwitch : public CControl
{
public:
CRockerSwitch (CRect &size, CControlListener *listener, int tag,
int heightOfOneImage, // pixel
CBitmap *handle, CPoint &offset);
virtual ~CRockerSwitch ();
virtual void draw (CDrawContext*);
virtual void mouse (CDrawContext *context, CPoint &where);
protected:
CBitmap *handle;
CPoint offset;
int heightOfOneImage;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CMovieBitmap : public CControl
{
public:
CMovieBitmap (CRect &size, CControlListener *listener, int tag,
int subPixmaps, // number of subPixmaps
int heightOfOneImage, // pixel
CBitmap *handle, CPoint &offset);
virtual ~CMovieBitmap ();
virtual void draw (CDrawContext*);
protected:
CBitmap *handle;
CPoint offset;
int subPixmaps; // number of subPixmaps
int heightOfOneImage;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CMovieButton : public CControl
{
public:
CMovieButton (CRect &size, CControlListener *listener, int tag,
int heightOfOneImage, // pixel
CBitmap *handle, CPoint &offset);
virtual ~CMovieButton ();
virtual void draw (CDrawContext*);
virtual void mouse (CDrawContext *context, CPoint &where);
protected:
CBitmap *handle;
CPoint offset;
int heightOfOneImage;
float buttonState;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// displays bitmaps within a (child-) window
class CAutoAnimation : public CControl
{
public:
CAutoAnimation (CRect &size, CControlListener *listener, int tag,
int subPixmaps, // number of subPixmaps...
int heightOfOneImage, // pixel
CBitmap *handle, CPoint &offset);
virtual ~CAutoAnimation ();
virtual void draw (CDrawContext*);
virtual void mouse (CDrawContext *context, CPoint &where);
virtual void openWindow (void);
virtual void closeWindow (void);
virtual void nextPixmap (void);
virtual void previousPixmap (void);
bool isWindowOpened () { return windowOpened; }
protected:
CBitmap *handle;
CPoint offset;
int subPixmaps;
int heightOfOneImage;
bool windowOpened;
int totalHeightOfBitmap;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Vertical Slider
class CVerticalSlider : public CControl
{
public:
CVerticalSlider (CRect &size, CControlListener *listener, int tag,
int iMinYPos, // min Y position in pixel
int iMaxYPos, // max Y position in pixel
CBitmap *handle, // bitmap slider
CBitmap *background, // bitmap background
CPoint &offset,
int style = kBottom); // style (kBottom, kTop))
virtual ~CVerticalSlider ();
virtual void draw (CDrawContext*);
virtual void mouse (CDrawContext *context, CPoint &where);
virtual void setDrawTransparentHandle (bool val) { drawTransparentEnabled = val; }
virtual void setOffsetHandle (CPoint &val) { offsetHandle = val; }
protected:
CBitmap *handle;
CBitmap *background;
int widthOfSlider; // size of the handle-slider
int heightOfSlider;
CPoint offset;
CPoint offsetHandle;
int iMinYPos; // min Y position in pixel
int iMaxYPos; // max Y position in pixel
int style;
int actualYPos;
bool drawTransparentEnabled;
int minTmp;
int maxTmp;
int widthControl;
int heightControl;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Horizontal Slider
class CHorizontalSlider : public CControl
{
public:
CHorizontalSlider (CRect &size, CControlListener *listener, int tag,
int iMinXPos, // min X position in pixel
int iMaxXPos, // max X position in pixel
CBitmap *handle, // bitmap slider
CBitmap *background, // bitmap background
CPoint &offset,
int style = kRight); // style (kRight, kLeft));
virtual ~CHorizontalSlider ();
virtual void draw (CDrawContext*);
virtual void mouse (CDrawContext *context, CPoint &where);
virtual void setDrawTransparentHandle (bool val) { drawTransparentEnabled = val; }
virtual void setOffsetHandle (CPoint &val) { offsetHandle = val; }
protected:
CBitmap *handle;
CBitmap *background;
int widthOfSlider; // size of the handle-slider
int heightOfSlider;
CPoint offset;
CPoint offsetHandle;
int iMinXPos; // min X position in pixel
int iMaxXPos; // max X position in pixel
int style;
int actualXPos;
bool drawTransparentEnabled;
int minTmp;
int maxTmp;
int widthControl;
int heightControl;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// special display with custom numbers (0...9)
class CSpecialDigit : public CControl
{
public:
CSpecialDigit (CRect &size, CControlListener *listener, int tag, // tag identifier
long dwPos, // actual value
int iNumbers, // amount of numbers (max 7)
int *xpos, // array of all XPOS
int *ypos, // array of all YPOS
int width, // width of ONE number
int height, // height of ONE number
CBitmap *handle); // bitmap numbers
virtual ~CSpecialDigit ();
virtual void draw (CDrawContext*);
virtual float getNormValue (void);
protected:
CBitmap *handle;
int iNumbers; // amount of numbers
int xpos[7]; // array of all XPOS, max 7 possible
int ypos[7]; // array of all YPOS, max 7 possible
int width; // width of ONE number
int height; // height of ONE number
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CKickButton : public CControl
{
public:
CKickButton (CRect &size, CControlListener *listener, int tag,
int heightOfOneImage, // pixel
CBitmap *handle, CPoint &offset);
virtual ~CKickButton ();
virtual void draw (CDrawContext*);
virtual void mouse (CDrawContext *context, CPoint &where);
protected:
CBitmap *handle;
CPoint offset;
int heightOfOneImage;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CSplashScreen : public CControl
{
public:
CSplashScreen (CRect &size, CControlListener *listener, int tag,
CBitmap *handle,
CRect &toDisplay,
CPoint &offset);
virtual ~CSplashScreen ();
virtual void draw (CDrawContext*);
virtual void mouse (CDrawContext *context, CPoint &where);
protected:
CRect toDisplay;
CRect keepSize;
CBitmap *handle;
CPoint offset;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CVuMeter : public CControl
{
public:
CVuMeter (CRect& size, CBitmap *onBitmap, CBitmap *offBitmap,
int nbLed, const int style = kVertical);
virtual ~CVuMeter ();
virtual void setDecreaseStepValue (float value) { decreaseValue = value; }
virtual void draw (CDrawContext *context);
protected:
CBitmap *onBitmap;
CBitmap *offBitmap;
int nbLed;
int style;
float decreaseValue;
CRect rectOn;
CRect rectOff;
};
#endif

View File

@ -1,621 +0,0 @@
//-----------------------------------------------------------------------------
// VST Plug-Ins SDK
// User interface framework for VST plugins
//
// Version 1.0
//
// First version : Wolfgang Kundrus
// Added Motif/Windows version : Yvan Grabit 01.98
// Added Mac version : Charlie Steinberg 02.98
// Added BeOS version : Georges-Edouard Berenger 05.99
//
// (c)1999 Steinberg Soft+Hardware GmbH
//-----------------------------------------------------------------------------
#ifndef __vstgui__
#define __vstgui__
// define global defines
#if WIN32
#define WINDOWS 1
#elif SGI | SUN
#define MOTIF 1
#elif __MWERKS__
#define MAC 1
#endif
#ifndef __AEffEditor__
#include "AEffEditor.hpp"
#endif
//----------------------------------------------------
#if WINDOWS
#include <windows.h>
//----------------------------------------------------
#elif MOTIF
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#ifdef NOBOOL
#ifndef bool
typedef short bool;
#endif
#ifndef false
static const bool false = 0;
#endif
#ifndef true
static const bool true = 1;
#endif
#endif
// definition of struct for XPixmap resources
struct CResTableEntry {
int id;
char **xpm;
};
typedef CResTableEntry CResTable[];
extern CResTable xpmResources;
//----------------------------------------------------
#elif MAC
#include <Quickdraw.h>
class CCashedPict;
//----------------------------------------------------
#elif BEOS
#include <View.h>
class PlugView;
class BBitmap;
class BResources;
#endif
//----------------------------------------------------
//----------------------------------------------------
class CFrame;
class CDrawContext;
class COffscreenContext;
class CControl;
class CBitmap;
//-----------------------------------------------------------------------------
// AEffGUIEditor Declaration
//-----------------------------------------------------------------------------
class AEffGUIEditor : public AEffEditor
{
public :
AEffGUIEditor (AudioEffect *effect);
virtual ~AEffGUIEditor ();
virtual void setParameter (long index, float value) { postUpdate (); }
virtual long getRect (ERect **rect);
virtual long open (void *ptr);
virtual void idle ();
virtual void draw (ERect *rect);
#if MAC
virtual long mouse (long x, long y);
#endif
// get the current time (in ms)
long getTicks ();
// feedback to appli.
void doIdleStuff ();
// get the effect attached to this editor
AudioEffect *getEffect () { return effect; }
//---------------------------------------
protected:
ERect rect;
CFrame *frame;
unsigned long lLastTicks;
private:
short sInControlLoop;
};
//-----------------------------------------------------------------------------
// Structure CRect
//-----------------------------------------------------------------------------
struct CRect
{
CRect (long left = 0, long top = 0, long right = 0, long bottom = 0)
: left (left), top (top), right (right), bottom (bottom) {}
CRect (const CRect& r)
: left (r.left), top (r.top), right (r.right), bottom (r.bottom) {}
CRect& operator () (long left, long top, long right, long bottom)
{
if (left < right)
this->left = left, this->right = right;
else
this->left = right, this->right = left;
if (top < bottom)
this->top = top, this->bottom = bottom;
else
this->top = bottom, this->bottom = top;
return *this;
}
long left;
long top;
long right;
long bottom;
inline long width () { return right - left; }
inline long height () { return bottom - top; }
void offset (long x, long y) { left += x; right += x;
top += y; bottom += y; }
};
//-----------------------------------------------------------------------------
// Structure CPoint
//-----------------------------------------------------------------------------
struct CPoint
{
CPoint (long h = 0, long v = 0) : h (h), v (v) {}
CPoint& operator () (long h, long v)
{ this->h = h; this->v = v;
return *this; }
bool isInside (CRect& r)
{ return h >= r.left && h <= r.right && v >= r.top && v <= r.bottom; }
long h;
long v;
};
//-----------------------------------------------------------------------------
// Structure CColor
//-----------------------------------------------------------------------------
struct CColor
{
CColor& operator () (unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char unused)
{
this->red = red;
this->green = green;
this->blue = blue;
this->unused = unused;
return *this;
}
CColor& operator = (CColor newColor)
{
red = newColor.red;
green = newColor.green;
blue = newColor.blue;
unused = newColor.unused;
return *this;
}
bool operator != (CColor newColor)
{
return (red != newColor.red ||
green != newColor.green ||
blue != newColor.blue);
}
bool operator == (CColor newColor)
{
return (red == newColor.red &&
green == newColor.green &&
blue == newColor.blue);
}
unsigned char red;
unsigned char green;
unsigned char blue;
unsigned char unused;
};
// define some basic colors
static CColor kTransparentCColor = {255, 255, 255, 0};
static CColor kBlackCColor = {0, 0, 0, 0};
static CColor kWhiteCColor = {255, 255, 255, 0};
static CColor kGreyCColor = {127, 127, 127, 0};
static CColor kRedCColor = {255, 0, 0, 0};
static CColor kGreenCColor = {0 , 255, 0, 0};
static CColor kBlueCColor = {0 , 0, 255, 0};
static CColor kYellowCColor = {255, 255, 0, 0};
static CColor kCyanCColor = {255, 0, 255, 0};
static CColor kMagentaCColor= {0 , 255, 255, 0};
//-----------------------------------------------------------------------------
//-----------
// Font type
//-----------
enum CFont
{
kSystemFont = 0,
kNormalFontVeryBig,
kNormalFontBig,
kNormalFont,
kNormalFontSmall,
kNormalFontVerySmall,
kSymbolFont,
kNumStandardFonts
};
//-----------
// Line style
//-----------
enum CLineStyle
{
kLineSolid = 0,
kLineOnOffDash
};
//----------------------------
// Text alignment (Horizontal)
//----------------------------
enum CHoriTxtAlign
{
kLeftText = 0,
kCenterText,
kRightText
};
//----------------------------
// Buttons Type (+modifiers)
//----------------------------
enum CButton
{
kLButton = 1,
kMButton = 2,
kRButton = 4,
kShift = 8,
kControl = 16,
kAlt = 32,
kApple = 64
};
//-----------------------------------------------------------------------------
// CDrawContext Declaration
//-----------------------------------------------------------------------------
class CDrawContext
{
public:
CDrawContext (CFrame *frame, void *systemContext, void *window = 0);
virtual ~CDrawContext ();
void moveTo (CPoint &point);
void lineTo (CPoint &point);
void polyLine (CPoint *point, int numberOfPoints);
void fillPolygon (CPoint *point, int numberOfPoints);
void drawRect (CRect &rect);
void fillRect (CRect &rect);
void drawArc (CRect &rect, CPoint &point1, CPoint &point2);
void fillArc (CRect &rect, CPoint &point1, CPoint &point2);
void drawEllipse (CRect &rect);
void fillEllipse (CRect &rect);
void drawPoint (CPoint &point, CColor color);
void setLineStyle (CLineStyle style);
CLineStyle getLineStyle () { return lineStyle; }
void setLineWidth (int width);
int getLineWidth () { return frameWidth; }
void setFillColor (CColor color);
CColor getFillColor () { return fillColor; }
void setFrameColor (CColor color);
CColor getFrameColor () { return frameColor; }
void setFontColor (CColor color);
CColor getFontColor () { return fontColor; }
void setFont (CFont fontID, const int size = 0);
void drawString (const char *string, CRect &rect, const short opaque = false,
const CHoriTxtAlign hAlign = kCenterText);
int getMouseButtons ();
void getMouseLocation (CPoint &point);
#if MOTIF
int getIndexColor (CColor color);
Colormap getColormap ();
Visual *getVisual ();
unsigned int getDepth ();
static int nbNewColor;
#endif
void *getWindow () { return window; }
void setWindow (void *ptr) { window = ptr; }
void getLoc (CPoint &where) { where = penLoc; }
//-------------------------------------------
protected:
friend class CBitmap;
friend class COffscreenContext;
void *getSystemContext () { return systemContext; }
void *systemContext;
void *window;
CFrame *frame;
int fontSize;
CColor fontColor;
CPoint penLoc;
int frameWidth;
CColor frameColor;
CColor fillColor;
CLineStyle lineStyle;
#if WINDOWS
void *brush;
void *pen;
void *font;
void *oldbrush;
void *oldpen;
void *oldfont;
int iPenStyle;
#elif MAC
FontInfo fontInfoStruct;
Pattern fillPattern;
#elif MOTIF
Display *display;
XFontStruct *fontInfoStruct;
CFont fontInfoId;
#elif BEOS
BView* plugView;
BFont font;
void lineFromTo (CPoint& cstart, CPoint& cend);
#endif
};
//-----------------------------------------------------------------------------
// COffscreenContext Declaration
//-----------------------------------------------------------------------------
class COffscreenContext : public CDrawContext
{
public:
COffscreenContext (CDrawContext *context, CBitmap *bitmap);
COffscreenContext (CFrame *frame, long width, long height, const CColor backgroundColor = kBlackCColor);
virtual ~COffscreenContext ();
void transfert (CDrawContext *context, CRect destRect, CPoint srcOffset = CPoint (0, 0));
inline int getWidth () { return width; }
inline int getHeight () { return height; }
//-------------------------------------------
protected:
bool destroyPixmap;
CBitmap *bitmap;
long height;
long width;
CColor backgroundColor;
#if MOTIF
Display *xdisplay;
#elif BEOS
BBitmap *offscreenBitmap;
#endif
};
//-----------------------------------------------------------------------------
// CBitmap Declaration
//-----------------------------------------------------------------------------
class CBitmap
{
public:
CBitmap (int resourceID);
CBitmap (CFrame &frame, int width, int height);
~CBitmap ();
void draw (CDrawContext*, CRect &rect, const CPoint &offset = CPoint (0, 0));
void drawTransparent (CDrawContext *context, CRect &rect, const CPoint &offset = CPoint (0, 0));
inline int getWidth () { return width; }
inline int getHeight () { return height; }
void forget ();
void remember ();
void *getHandle () { return handle; }
#if BEOS
static void closeResource ();
#endif
//-------------------------------------------
protected:
int resourceID;
void *handle;
void *mask;
int width;
int height;
int nbReference;
#if MOTIF
void *createPixmapFromXpm (CDrawContext *context);
char **dataXpm;
Display *xdisplay;
#elif MAC
CCashedPict *pPict;
#elif BEOS
static BResources *resourceFile;
BBitmap *bbitmap;
bool transparencySet;
#endif
};
//-----------------------------------------------------------------------------
// CView Declaration
//-----------------------------------------------------------------------------
class CView
{
public:
CView (CRect &size);
virtual ~CView ();
void redraw ();
virtual void draw (CDrawContext *context);
virtual void mouse (CDrawContext *context, CPoint &where);
virtual void update (CDrawContext *context);
virtual void looseFocus ();
virtual void takeFocus ();
virtual void setTempOffscreen (COffscreenContext *tempOffscr);
int getHeight () { return size.height (); }
int getWidth () { return size.width (); }
CFrame *getParent () { return parent; }
//-------------------------------------------
protected:
friend class CControl;
friend class CFrame;
CRect size;
CFrame *parent;
COffscreenContext *tempOffscreen;
};
//-----------------------------------------------------------------------------
// CFrame Declaration
//-----------------------------------------------------------------------------
class CFrame : public CView
{
public:
CFrame (CRect &size, void *systemWindow, AEffGUIEditor *editor);
CFrame (CRect &size, char *title, AEffGUIEditor *editor, const int style = 0);
~CFrame ();
bool open (CPoint *point = 0);
bool close ();
bool isOpen () { return openFlag; }
void draw (CDrawContext *context);
void draw (CView *view = 0);
void mouse (CDrawContext *context, CPoint &where);
void update (CDrawContext *context);
void idle ();
void doIdleStuff () { if (editor) editor->doIdleStuff (); }
bool getPosition (int &x, int &y);
bool setSize (int width, int height);
bool getSize (CRect *size);
void setBackground (CBitmap *background);
CBitmap *getBackground () { return background; }
virtual bool addView (CView *view);
virtual bool removeView (CView *view);
int setModalView (CView *view);
#if WINDOWS
void *getSystemWindow () { return hwnd;}
#elif BEOS
void *getSystemWindow () { return plugView;}
#else
void *getSystemWindow () { return systemWindow;}
#endif
AEffGUIEditor *getEditor () { return editor; }
void setEditView (CView *view) { editView = view; }
CView *getEditView () { return editView; }
#if MOTIF
Colormap getColormap () { return colormap; }
Visual *getVisual () { return visual; }
unsigned int getDepth () { return depth; }
Display *getDisplay () { return display; }
Window getWindow () { return window; }
void freeGc ();
Region region;
GC gc;
GC getGC () { return gc; }
#else
void *getGC () { return 0; }
#endif
//-------------------------------------------
protected:
bool initFrame (void *systemWin);
AEffGUIEditor *editor;
void *systemWindow;
CBitmap *background;
int viewCount;
int maxViews;
CView **views;
CView *modalView;
CView *editView;
bool firstDraw;
bool openFlag;
#if WINDOWS
void *hwnd;
friend LONG WINAPI WindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
#elif MOTIF
Colormap colormap;
Display *display;
Visual *visual;
Window window;
unsigned int depth;
friend void _destroyCallback (Widget, XtPointer, XtPointer);
#elif BEOS
PlugView *plugView;
#endif
//-------------------------------------------
private:
bool addedWindow;
void *vstWindow;
};
// include the control object
#ifndef __vstcontrols__
#include "vstcontrols.h"
#endif
//-End--------------------------------------
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,898 +0,0 @@
; //----------------------------------------------------------------------------------------
; // useful macros
; //----------------------------------------------------------------------------------------
; // export function (make it accessable from main.cpp)
; //----------------------------------------------------------------------------------------
%macro export_func 1
global _%1
_%1:
%endmacro
;%define USE_SECTIONS
; //----------------------------------------------------------------------------------------
; // basic defines for the song/synth
; //----------------------------------------------------------------------------------------
%define SAMPLE_RATE 44100
%define MAX_INSTRUMENTS 9
%define MAX_VOICES 1
%define HLD 1 ; // can be adjusted to give crinkler some other possibilities
%define BPM 100
%define MAX_PATTERNS 62
%define PATTERN_SIZE_SHIFT 4
%define PATTERN_SIZE (1 << PATTERN_SIZE_SHIFT)
%define MAX_TICKS (MAX_PATTERNS*PATTERN_SIZE)
%define SAMPLES_PER_TICK (SAMPLE_RATE*4*60/(BPM*16))
%define DEF_LFO_NORMALIZE 0.000038
%define MAX_SAMPLES (SAMPLES_PER_TICK*MAX_TICKS)
; //----------------------------------------------------------------------------------------
; // some defines for unit usage, which reduce synth code size
; //----------------------------------------------------------------------------------------
;%define GO4K_USE_16BIT_OUTPUT ; // removing this will output to 32bit floating point buffer
;%define GO4K_USE_GROOVE_PATTERN ; // removing this skips groove pattern code
;%define GO4K_USE_ENVELOPE_RECORDINGS ; // removing this skips envelope recording code
;%define GO4K_USE_NOTE_RECORDINGS ; // removing this skips note recording code
%define GO4K_USE_UNDENORMALIZE ; // removing this skips denormalization code in the units
%define GO4K_CLIP_OUTPUT ; // removing this skips clipping code for the final output
%define GO4K_USE_DST ; // removing this will skip DST unit
%define GO4K_USE_DLL ; // removing this will skip DLL unit
%define GO4K_USE_PAN ; // removing this will skip PAN unit
%define GO4K_USE_GLOBAL_DLL ; // removing this will skip global dll processing
%define GO4K_USE_FSTG ; // removing this will skip global store unit
%define GO4K_USE_FLD ; // removing this will skip float load unit
%define GO4K_USE_ENV_CHECK ; // removing this skips checks if processing is needed
%define GO4K_USE_ENV_MOD_GM ; // removing this will skip env gain modulation code
%define GO4K_USE_ENV_MOD_ADR ; // removing this will skip env attack/decay/release modulation code
%define GO4K_USE_VCO_CHECK ; // removing this skips checks if processing is needed
%define GO4K_USE_VCO_PHASE_OFFSET ; // removing this will skip initial phase offset code
%define GO4K_USE_VCO_SHAPE ; // removing this skips waveshaping code
%define GO4K_USE_VCO_GATE ; // removing this skips gate code
%define GO4K_USE_VCO_MOD_FM ; // removing this skips frequency modulation code
%define GO4K_USE_VCO_MOD_PM ; // removing this skips phase modulation code
%define GO4K_USE_VCO_MOD_TM ; // removing this skips transpose modulation code
%define GO4K_USE_VCO_MOD_DM ; // removing this skips detune modulation code
%define GO4K_USE_VCO_MOD_CM ; // removing this skips color modulation code
%define GO4K_USE_VCO_MOD_GM ; // removing this skips gain modulation code
%define GO4K_USE_VCO_MOD_SM ; // removing this skips shaping modulation code
%define GO4K_USE_VCF_CHECK ; // removing this skips checks if processing is needed
%define GO4K_USE_VCF_MOD_FM ; // removing this skips frequency modulation code
%define GO4K_USE_VCF_MOD_RM ; // removing this skips resonance modulation code
%define GO4K_USE_VCF_HIGH ; // removing this skips code for high output
%define GO4K_USE_VCF_BAND ; // removing this skips code for band output
%define GO4K_USE_VCF_PEAK ; // removing this skips code for peak output
%define GO4K_USE_DST_CHECK ; // removing this skips checks if processing is needed
%define GO4K_USE_DST_SH ; // removing this skips sample and hold code
%define GO4K_USE_DST_MOD_DM ; // removing this skips distortion modulation code
%define GO4K_USE_DST_MOD_SH ; // removing this skips sample and hold modulation code
%define GO4K_USE_DLL_NOTE_SYNC ; // removing this will skip delay length adjusting code (karplus strong)
%define GO4K_USE_DLL_CHORUS ; // removing this will skip delay chorus/flanger code
%define GO4K_USE_DLL_CHORUS_CLAMP ; // removing this will skip chorus lfo phase clamping
%define GO4K_USE_DLL_DAMP ; // removing this will skip dll damping code
%define GO4K_USE_DLL_DC_FILTER ; // removing this will skip dll dc offset removal code
%define GO4K_USE_FOP_LOADNOTE ; // removing this will skip load note code
%define GO4K_USE_FSTG_CHECK ; // removing this skips checks if processing is needed
%define GO4K_USE_PAN_MOD ; // removing this will skip panning modulation code
%define GO4K_USE_OUT_MOD_AM ; // removing this skips output aux send modulation code
%define GO4K_USE_OUT_MOD_GM ; // removing this skips output gain modulation code
%define GO4K_USE_WAVESHAPER_CLIP ; // removing this will skip clipping code
%define GO4K_USE_FLD_MOD_VM ; // removing this will skip float load modulation code
%define GO4K_USE_DLL_MOD ; // define this to enable modulations for delay line
%define GO4K_USE_DLL_MOD_PM ; // define this to enable pregain modulation for delay line
%define GO4K_USE_DLL_MOD_FM ; // define this to enable feebback modulation for delay line
%define GO4K_USE_DLL_MOD_IM ; // define this to enable dry modulation for delay line
%define GO4K_USE_DLL_MOD_DM ; // define this to enable damping modulation for delay line
%define GO4K_USE_DLL_MOD_SM ; // define this to enable lfo freq modulation for delay line
%define GO4K_USE_DLL_MOD_AM ; // define this to enable lfo depth modulation for delay line
; //----------------------------------------------------------------------------------------
; // synth defines
; //----------------------------------------------------------------------------------------
%define MAX_DELAY 65536
%define MAX_WORKSPACE_SLOTS 8
%define GO4K_BEGIN_CMDDEF(def_name)
%define GO4K_END_CMDDEF db 0
%define GO4K_BEGIN_PARAMDEF(def_name)
%define GO4K_END_PARAMDEF
; //----------------------------------------------------------------------------------------
; // ENV structs
; //----------------------------------------------------------------------------------------
GO4K_ENV_ID equ 1
%macro GO4K_ENV 5
db %1
db %2
db %3
db %4
db %5
%endmacro
%define ATTAC(val) val
%define DECAY(val) val
%define SUSTAIN(val) val
%define RELEASE(val) val
%define GAIN(val) val
struc go4kENV_val
;// unit paramters
.attac resd 1
.decay resd 1
.sustain resd 1
.release resd 1
.gain resd 1
.size
endstruc
struc go4kENV_wrk
;// work variables
.state resd 1
.level resd 1
;// modulation targets
.gm resd 1
.am resd 1
.dm resd 1
.sm resd 1
.rm resd 1
.size
endstruc
%define ENV_STATE_ATTAC 0
%define ENV_STATE_DECAY 1
%define ENV_STATE_SUSTAIN 2
%define ENV_STATE_RELEASE 3
%define ENV_STATE_OFF 4
; //----------------------------------------------------------------------------------------
; // VCO structs
; //----------------------------------------------------------------------------------------
GO4K_VCO_ID equ 2
%macro GO4K_VCO 8
db %1
db %2
%ifdef GO4K_USE_VCO_PHASE_OFFSET
db %3
%endif
%ifdef GO4K_USE_VCO_GATE
db %4
%endif
db %5
%ifdef GO4K_USE_VCO_SHAPE
db %6
%else
%endif
db %7
db %8
%endmacro
%define TRANSPOSE(val) val
%define DETUNE(val) val
%define PHASE(val) val
%define GATES(val) val
%define COLOR(val) val
%define SHAPE(val) val
%define FLAGS(val) val
%define SINE 0x01
%define TRISAW 0x02
%define PULSE 0x04
%define NOISE 0x08
%define LFO 0x10
%define GATE 0x20
struc go4kVCO_val
;// unit paramters
.transpose resd 1
.detune resd 1
%ifdef GO4K_USE_VCO_PHASE_OFFSET
.phaseofs resd 1
%endif
%ifdef GO4K_USE_VCO_GATE
.gate resd 1
%endif
.color resd 1
%ifdef GO4K_USE_VCO_SHAPE
.shape resd 1
%endif
.gain resd 1
.flags resd 1
.size
endstruc
struc go4kVCO_wrk
;// work variables
.phase resd 1
;// modulation targets
.tm resd 1
.dm resd 1
.fm resd 1
.pm resd 1
.cm resd 1
.sm resd 1
.gm resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // VCF structs
; //----------------------------------------------------------------------------------------
GO4K_VCF_ID equ 3
%macro GO4K_VCF 3
db %1
db %2
db %3
%endmacro
%define LOWPASS 0x1
%define HIGHPASS 0x2
%define BANDPASS 0x4
%define BANDSTOP 0x3
%define ALLPASS 0x7
%define PEAK 0x8
%define FREQUENCY(val) val
%define RESONANCE(val) val
%define VCFTYPE(val) val
struc go4kVCF_val
;// unit paramters
.freq resd 1
.res resd 1
.type resd 1
.size
endstruc
struc go4kVCF_wrk
;// work variables
.low resd 1
.high resd 1
.band resd 1
.freq resd 1
;// modulation targets
.fm resd 1
.rm resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // DST structs
; //----------------------------------------------------------------------------------------
GO4K_DST_ID equ 4
%macro GO4K_DST 2
db %1
%ifdef GO4K_USE_DST_SH
db %2
%endif
%endmacro
%define DRIVE(val) val
%define SNHFREQ(val) val
struc go4kDST_val
;// unit paramters
.drive resd 1
%ifdef GO4K_USE_DST_SH
.snhfreq resd 1
%endif
.size
endstruc
struc go4kDST_wrk
.out resd 1
.snhphase resd 1
;// modulation targets
.dm resd 1
.sm resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // DLL structs
; //----------------------------------------------------------------------------------------
GO4K_DLL_ID equ 5
%macro GO4K_DLL 8
db %1
db %2
db %3
%ifdef GO4K_USE_DLL_DAMP
db %4
%endif
%ifdef GO4K_USE_DLL_CHORUS
db %5
db %6
%endif
db %7
db %8
%endmacro
%define PREGAIN(val) val
%define DRY(val) val
%define FEEDBACK(val) val
%define DEPTH(val) val
%define DAMP(val) val
%define DELAY(val) val
%define COUNT(val) val
struc go4kDLL_val
;// unit paramters
.pregain resd 1
.dry resd 1
.feedback resd 1
%ifdef GO4K_USE_DLL_DAMP
.damp resd 1
%endif
%ifdef GO4K_USE_DLL_CHORUS
.freq resd 1
.depth
%endif
.delay resd 1
.count resd 1
.size
endstruc
struc go4kDLL_wrk
;// work variables
.index resd 1
.store resd 1
.dcin resd 1
.dcout resd 1
.phase resd 1
;// the delay buffer
.buffer resd MAX_DELAY
.size
endstruc
struc go4kDLL_wrk2
;// modulation targets
.pm resd 1
.fm resd 1
.im resd 1
.dm resd 1
.sm resd 1
.am resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // FOP structs
; //----------------------------------------------------------------------------------------
GO4K_FOP_ID equ 6
%macro GO4K_FOP 1
db %1
%endmacro
%define OP(val) val
%define FOP_POP 0x1
%define FOP_ADDP 0x2
%define FOP_MULP 0x3
%define FOP_PUSH 0x4
%define FOP_XCH 0x5
%define FOP_ADD 0x6
%define FOP_MUL 0x7
%define FOP_ADDP2 0x8
%define FOP_LOADNOTE 0x9
struc go4kFOP_val
.flags resd 1
.size
endstruc
struc go4kFOP_wrk
.size
endstruc
; //----------------------------------------------------------------------------------------
; // FST structs
; //----------------------------------------------------------------------------------------
GO4K_FST_ID equ 7
%macro GO4K_FST 2
db %1
db %2
%endmacro
%define AMOUNT(val) val
%define DEST(val) val
struc go4kFST_val
.amount resd 1
.op1 resd 1
.size
endstruc
struc go4kFST_wrk
.size
endstruc
; //----------------------------------------------------------------------------------------
; // PAN structs
; //----------------------------------------------------------------------------------------
GO4K_PAN_ID equ 8
%macro GO4K_PAN 1
%ifdef GO4K_USE_PAN
db %1
%endif
%endmacro
%define PANNING(val) val
struc go4kPAN_val
%ifdef GO4K_USE_PAN
.panning resd 1
%endif
.size
endstruc
struc go4kPAN_wrk
;// modulation targets
.pm resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // OUT structs
; //----------------------------------------------------------------------------------------
GO4K_OUT_ID equ 9
%macro GO4K_OUT 2
db %1
%ifdef GO4K_USE_GLOBAL_DLL
db %2
%endif
%endmacro
%define AUXSEND(val) val
struc go4kOUT_val
.gain resd 1
%ifdef GO4K_USE_GLOBAL_DLL
.auxsend resd 1
%endif
.size
endstruc
struc go4kOUT_wrk
;// modulation targets
.am resd 1
.gm resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // ACC structs (this is for the synth def only)
; //----------------------------------------------------------------------------------------
GO4K_ACC_ID equ 10
%macro GO4K_ACC 1
db %1
%endmacro
%define OUTPUT 0
%define AUX 8
%define ACCTYPE(val) val
struc go4kACC_val
.acctype resd 1
.size
endstruc
struc go4kACC_wrk
.size
endstruc
%ifdef GO4K_USE_FLD
; //----------------------------------------------------------------------------------------
; // FLD structs
; //----------------------------------------------------------------------------------------
GO4K_FLD_ID equ 11
%macro GO4K_FLD 1
db %1
%endmacro
%define VALUE(val) val
struc go4kFLD_val
.value resd 1
.size
endstruc
struc go4kFLD_wrk
;// modulation targets
.vm resd 1
.size
endstruc
%endif
%ifdef GO4K_USE_FSTG
; //----------------------------------------------------------------------------------------
; // FSTG structs
; //----------------------------------------------------------------------------------------
GO4K_FSTG_ID equ 12
%macro GO4K_FSTG 2
db %1
dd %2
%endmacro
struc go4kFSTG_val
.amount resd 1
.op1 resd 1
.size
endstruc
struc go4kFSTG_wrk
.size
endstruc
%endif
; //----------------------------------------------------------------------------------------
; // Voice struct
; //----------------------------------------------------------------------------------------
struc go4k_instrument
.release resd 1
.note resd 1
.workspace resd 256
.dlloutl resd 1
.dlloutr resd 1
.outl resd 1
.outr resd 1
.size
endstruc
; //----------------------------------------------------------------------------------------
; // Synth struct
; //----------------------------------------------------------------------------------------
struc go4k_synth
.instruments resb go4k_instrument.size * MAX_INSTRUMENTS * MAX_VOICES
.global resb go4k_instrument.size * MAX_VOICES
.size
endstruc
; //----------------------------------------------------------------------------------------
; // Pattern Data, reduced by 967 patterns
; //----------------------------------------------------------------------------------------
%ifdef USE_SECTIONS
section .g4kmuc1 data align=1
%else
section .data align=1
%endif
go4k_patterns
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
db 76, HLD, HLD, HLD, 0, 0, 0, 0, 79, HLD, HLD, HLD, 0, 0, 0, 0,
db 69, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0,
db 76, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 81, HLD, HLD, HLD, 0, 0, 0, 0, 79, HLD, HLD, HLD, 0, 0, 0, 0,
db 84, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0,
db 76, HLD, HLD, HLD, 0, 0, 0, 0, 88, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0,
db 76, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0,
db 52, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 57, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 60, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 69, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 72, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 40, 52, HLD, 64, HLD, 40, 52, 64, 52, HLD, HLD, HLD, 0, 0, 0, 0,
db 57, 0, 0, 57, 0, 0, 69, 0, 0, 69, 0, 0, 57, HLD, HLD, HLD,
db 52, 64, 0, 57, 0, 69, 48, 0, 48, HLD, HLD, HLD, 0, 0, 0, 0,
db 40, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 40, 52, HLD, 40, HLD, 40, 40, 40, 52, HLD, HLD, HLD, 0, 0, 0, 0,
db 40, 0, 0, 52, 0, 0, 40, 0, 52, 40, 0, 52, 0, 40, 0, 0,
db 45, 0, 0, 57, 0, 0, 45, 0, 57, 45, 0, 57, 0, 45, 0, 0,
db 48, 0, 0, 60, 0, 0, 48, 0, 60, 48, 0, 60, 0, 48, 0, 0,
db 40, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0,
db 45, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0,
db 36, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0,
db 0, 0, 0, 0, 60, HLD, 0, 0, 0, 0, 0, 0, 60, HLD, 0, 0,
db 60, HLD, 0, 0, 0, 0, 60, HLD, 0, 0, 60, HLD, 60, HLD, 0, 0,
db 0, 0, 0, 0, 60, HLD, 0, 0, 0, 0, 0, 0, 60, HLD, 60, HLD,
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, HLD, 0, 0,
db 60, HLD, 60, HLD, 0, 0, 60, HLD, 0, 0, 0, 0, 60, HLD, 0, 0,
db 0, 0, 60, HLD, 0, 0, 0, 0, 60, HLD, 0, 0, 0, 0, 0, 0,
db 0, 0, 60, HLD, 0, 0, 0, 0, 60, HLD, 0, 0, 60, HLD, 0, 0,
db 0, 0, 0, 60, HLD, 0, 0, 0, 0, 0, 0, 0, 60, HLD, 0, 0,
db 0, 0, 0, 60, HLD, 0, 0, 0, 0, 60, HLD, 60, 60, HLD, 0, 0,
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0,
db 91, 0, 0, 88, 0, 0, 76, 0, 81, 0, 0, 0, 0, 0, 0, 0,
db 81, 0, 0, 84, 0, 0, 86, 0, 88, 0, 0, 0, 0, 0, 0, 0,
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0,
db 81, 0, 0, 84, 0, 0, 86, 0, 81, 0, 0, 0, 0, 0, 0, 0,
db 84, 0, 0, 86, 0, 0, 88, 0, 0, 91, 0, 0, 84, 0, 0, 0,
db HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
go4k_patterns_end
; //----------------------------------------------------------------------------------------
; // Pattern Index List
; //----------------------------------------------------------------------------------------
%ifdef USE_SECTIONS
section .g4kmuc2 data align=1
%else
section .data
%endif
go4k_pattern_lists
Instrument0List db 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4, 5, 6, 7, 1, 2, 3, 0, 4, 5, 6, 7, 8, 2, 9, 0, 0, 0,
Instrument1List db 9, 7, 10, 7, 11, 7, 12, 7, 9, 7, 10, 7, 11, 7, 12, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 7, 13, 7, 14, 7, 3, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 7, 0, 0,
Instrument2List db 15, 0, 16, 0, 17, 0, 18, 0, 19, 0, 16, 0, 17, 0, 18, 0, 20, 20, 21, 21, 22, 22, 20, 20, 20, 20, 21, 21, 22, 22, 20, 20, 23, 15, 24, 16, 25, 17, 18, 0, 20, 20, 21, 21, 22, 22, 20, 20, 20, 20, 21, 21, 22, 22, 20, 20, 20, 20, 0, 0, 0, 0,
Instrument3List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0,
Instrument4List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 26, 27, 26, 27, 26, 27, 28, 27, 26, 27, 26, 27, 26, 27, 28, 27, 29, 27, 29, 27, 29, 27, 29, 27, 26, 27, 26, 27, 26, 27, 28, 27, 26, 27, 26, 27, 26, 27, 28, 27, 26, 27, 0, 0, 0,
Instrument5List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 0, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 32, 30, 31, 30, 32, 0, 0,
Instrument6List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 33, 34, 33, 33, 0, 0, 0, 0,
Instrument7List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 36, 0, 37, 38, 36, 0, 39, 35, 36, 0, 37, 38, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Instrument8List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 11, 41, 41, 41, 41, 0,
go4k_pattern_lists_end
; //----------------------------------------------------------------------------------------
; // Instrument Commands
; //----------------------------------------------------------------------------------------
%ifdef USE_SECTIONS
section .g4kmuc3 data align=1
%else
section .data
%endif
go4k_synth_instructions
GO4K_BEGIN_CMDDEF(Instrument0)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_FST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_VCF_ID
db GO4K_DST_ID
db GO4K_PAN_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument1)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_FST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_VCF_ID
db GO4K_DST_ID
db GO4K_PAN_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument2)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_FST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_VCF_ID
db GO4K_DST_ID
db GO4K_PAN_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument3)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_PAN_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument4)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_ENV_ID
db GO4K_DST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_PAN_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument5)
db GO4K_ENV_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_PAN_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument6)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCF_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_PAN_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument7)
db GO4K_ENV_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_PAN_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument8)
db GO4K_ENV_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_FSTG_ID
db GO4K_FSTG_ID
db GO4K_FOP_ID
GO4K_END_CMDDEF
;// global commands
GO4K_BEGIN_CMDDEF(Global)
db GO4K_ACC_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_ACC_ID
db GO4K_FOP_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
go4k_synth_instructions_end
; //----------------------------------------------------------------------------------------
; // Intrument Data
; //----------------------------------------------------------------------------------------
%ifdef USE_SECTIONS
section .g4kmuc4 data align=1
%else
section .data
%endif
go4k_synth_parameter_values
GO4K_BEGIN_PARAMDEF(Instrument0)
GO4K_ENV ATTAC(72),DECAY(96),SUSTAIN(96),RELEASE(88),GAIN(128)
GO4K_FST AMOUNT(64),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_VCO TRANSPOSE(64),DETUNE(60),PHASE(32),GATES(0),COLOR(80),SHAPE(64),GAIN(128),FLAGS(PULSE)
GO4K_VCO TRANSPOSE(64),DETUNE(72),PHASE(32),GATES(0),COLOR(96),SHAPE(64),GAIN(128),FLAGS(TRISAW)
GO4K_VCO TRANSPOSE(32),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(96),GAIN(128),FLAGS(SINE|LFO)
GO4K_FST AMOUNT(68),DEST(2*MAX_WORKSPACE_SLOTS+2)
GO4K_FST AMOUNT(61),DEST(3*MAX_WORKSPACE_SLOTS+2)
GO4K_FOP OP(FOP_POP)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(26),RESONANCE(128),VCFTYPE(PEAK)
GO4K_VCF FREQUENCY(64),RESONANCE(64),VCFTYPE(LOWPASS)
GO4K_DST DRIVE(104), SNHFREQ(128)
GO4K_PAN PANNING(64)
GO4K_DLL PREGAIN(96),DRY(128),FEEDBACK(96),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(16),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_DLL PREGAIN(96),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(17),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_OUT GAIN(0), AUXSEND(32)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument1)
GO4K_ENV ATTAC(72),DECAY(96),SUSTAIN(96),RELEASE(88),GAIN(128)
GO4K_FST AMOUNT(64),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_VCO TRANSPOSE(64),DETUNE(60),PHASE(32),GATES(0),COLOR(80),SHAPE(64),GAIN(128),FLAGS(TRISAW)
GO4K_VCO TRANSPOSE(64),DETUNE(72),PHASE(32),GATES(0),COLOR(96),SHAPE(112),GAIN(64),FLAGS(SINE)
GO4K_VCO TRANSPOSE(80),DETUNE(112),PHASE(0),GATES(0),COLOR(64),SHAPE(16),GAIN(128),FLAGS(PULSE|LFO)
GO4K_FST AMOUNT(68),DEST(2*MAX_WORKSPACE_SLOTS+2)
GO4K_FST AMOUNT(60),DEST(3*MAX_WORKSPACE_SLOTS+2)
GO4K_FOP OP(FOP_POP)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(80),RESONANCE(24),VCFTYPE(LOWPASS)
GO4K_VCF FREQUENCY(48),RESONANCE(24),VCFTYPE(HIGHPASS)
GO4K_DST DRIVE(64), SNHFREQ(128)
GO4K_PAN PANNING(64)
GO4K_DLL PREGAIN(96),DRY(128),FEEDBACK(96),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(16),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_DLL PREGAIN(96),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(17),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_OUT GAIN(0), AUXSEND(32)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument2)
GO4K_ENV ATTAC(32),DECAY(64),SUSTAIN(64),RELEASE(64),GAIN(64)
GO4K_FST AMOUNT(120),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(32),GATES(0),COLOR(80),SHAPE(64),GAIN(128),FLAGS(PULSE)
GO4K_VCO TRANSPOSE(64),DETUNE(72),PHASE(32),GATES(0),COLOR(96),SHAPE(64),GAIN(128),FLAGS(TRISAW)
GO4K_VCO TRANSPOSE(32),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(96),GAIN(128),FLAGS(SINE|LFO)
GO4K_FST AMOUNT(68),DEST(2*MAX_WORKSPACE_SLOTS+2)
GO4K_FST AMOUNT(60),DEST(3*MAX_WORKSPACE_SLOTS+2)
GO4K_FOP OP(FOP_POP)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(18),RESONANCE(64),VCFTYPE(PEAK)
GO4K_VCF FREQUENCY(32),RESONANCE(48),VCFTYPE(LOWPASS)
GO4K_DST DRIVE(88), SNHFREQ(128)
GO4K_PAN PANNING(64)
GO4K_DLL PREGAIN(64),DRY(128),FEEDBACK(96),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(16),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_DLL PREGAIN(64),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(17),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_OUT GAIN(64), AUXSEND(64)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument3)
GO4K_ENV ATTAC(0),DECAY(76),SUSTAIN(0),RELEASE(0),GAIN(32)
GO4K_FST AMOUNT(128),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(64),GATES(0),COLOR(64),SHAPE(64),GAIN(128),FLAGS(NOISE)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(80),RESONANCE(128),VCFTYPE(LOWPASS)
GO4K_PAN PANNING(64)
GO4K_OUT GAIN(64), AUXSEND(0)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument4)
GO4K_ENV ATTAC(0),DECAY(64),SUSTAIN(96),RELEASE(64),GAIN(128)
GO4K_FST AMOUNT(128),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_ENV ATTAC(0),DECAY(70),SUSTAIN(0),RELEASE(0),GAIN(128)
GO4K_DST DRIVE(32), SNHFREQ(128)
GO4K_FST AMOUNT(80),DEST(6*MAX_WORKSPACE_SLOTS+1)
GO4K_FOP OP(FOP_POP)
GO4K_VCO TRANSPOSE(46),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(64),GAIN(128),FLAGS(TRISAW)
GO4K_FOP OP(FOP_MULP)
GO4K_PAN PANNING(64)
GO4K_OUT GAIN(128), AUXSEND(0)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument5)
GO4K_ENV ATTAC(0),DECAY(64),SUSTAIN(0),RELEASE(0),GAIN(128)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(64),GATES(0),COLOR(64),SHAPE(64),GAIN(128),FLAGS(NOISE)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(128),RESONANCE(128),VCFTYPE(BANDPASS)
GO4K_PAN PANNING(64)
GO4K_DLL PREGAIN(64),DRY(128),FEEDBACK(96),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(16),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_DLL PREGAIN(64),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(17),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_OUT GAIN(64), AUXSEND(0)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument6)
GO4K_ENV ATTAC(0),DECAY(72),SUSTAIN(0),RELEASE(72),GAIN(128)
GO4K_FST AMOUNT(128),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_ENV ATTAC(0),DECAY(56),SUSTAIN(0),RELEASE(0),GAIN(128)
GO4K_FST AMOUNT(108),DEST(6*MAX_WORKSPACE_SLOTS+1)
GO4K_FST AMOUNT(72),DEST(7*MAX_WORKSPACE_SLOTS+1)
GO4K_FOP OP(FOP_POP)
GO4K_VCO TRANSPOSE(32),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(32),GAIN(64),FLAGS(SINE)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(80),GAIN(64),FLAGS(SINE)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(64),GAIN(64),FLAGS(NOISE)
GO4K_VCF FREQUENCY(104),RESONANCE(128),VCFTYPE(LOWPASS)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(22),RESONANCE(32),VCFTYPE(HIGHPASS)
GO4K_PAN PANNING(64)
GO4K_OUT GAIN(64), AUXSEND(0)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument7)
GO4K_ENV ATTAC(0),DECAY(0),SUSTAIN(96),RELEASE(32),GAIN(128)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(0),COLOR(80),SHAPE(64),GAIN(128),FLAGS(PULSE)
GO4K_FOP OP(FOP_MULP)
GO4K_PAN PANNING(64)
GO4K_DLL PREGAIN(96),DRY(128),FEEDBACK(96),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(16),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_DLL PREGAIN(96),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(17),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_OUT GAIN(0), AUXSEND(64)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument8)
GO4K_ENV ATTAC(0),DECAY(0),SUSTAIN(128),RELEASE(0),GAIN(128)
GO4K_VCO TRANSPOSE(48),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(64),GAIN(128),FLAGS(TRISAW|LFO)
GO4K_FOP OP(FOP_MULP)
GO4K_FSTG AMOUNT(72),DEST(2*go4k_instrument.size*MAX_VOICES+10*MAX_WORKSPACE_SLOTS*4+4*4+go4k_instrument.workspace)
GO4K_FSTG AMOUNT(66),DEST(1*go4k_instrument.size*MAX_VOICES+10*MAX_WORKSPACE_SLOTS*4+4*4+go4k_instrument.workspace)
GO4K_FOP OP(FOP_POP)
GO4K_END_PARAMDEF
;// global parameters
GO4K_BEGIN_PARAMDEF(Global)
GO4K_ACC ACCTYPE(AUX)
GO4K_DLL PREGAIN(40),DRY(128),FEEDBACK(125),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(0),COUNT(8)
GO4K_FOP OP(FOP_XCH)
GO4K_DLL PREGAIN(40),DRY(128),FEEDBACK(125),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(8),COUNT(8)
GO4K_FOP OP(FOP_XCH)
GO4K_ACC ACCTYPE(OUTPUT)
GO4K_FOP OP(FOP_ADDP2)
GO4K_OUT GAIN(64), AUXSEND(0)
GO4K_END_PARAMDEF
go4k_synth_parameter_values_end
; //----------------------------------------------------------------------------------------
; // Delay/Reverb Times
; //----------------------------------------------------------------------------------------
%ifdef USE_SECTIONS
section .g4kmuc5 data align=1
%else
section .data
%endif
%ifdef GO4K_USE_DLL
global _go4k_delay_times
_go4k_delay_times
dw 0
dw 1116
dw 1188
dw 1276
dw 1356
dw 1422
dw 1492
dw 1556
dw 1618
dw 1140
dw 1212
dw 1300
dw 1380
dw 1446
dw 1516
dw 1580
dw 1642
times 100 dw 0
%endif

View File

@ -1,2 +0,0 @@
LIBRARY 4klang
EXPORTS main

View File

@ -1,918 +0,0 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// German (Germany) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
#ifdef _WIN32
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// BINARY
//
IDR_COMP_RES BINARY "nasmw.bin"
IDR_ASM_RES BINARY "4klang.bin"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_GO4KVSTIDIALOG DIALOGEX 0, 0, 594, 341
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Alcatraz - 4klang Synth Plugin - Version 3.0.1"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Load Patch Data",IDC_LOAD_PATCH,13,13,70,14
PUSHBUTTON "Save Patch Data",IDC_SAVE_PATCH,85,13,70,14
PUSHBUTTON "Reset Patch Data",IDC_RESET_PATCH,157,13,70,14
PUSHBUTTON "Load Instrument",IDC_LOAD_INSTRUMENT,13,31,70,14
PUSHBUTTON "Save Instrument",IDC_SAVE_INSTRUMENT,85,31,70,14
PUSHBUTTON "Reset Instrument",IDC_RESET_INSTRUMENT,157,31,70,14
LTEXT "Instrument Name",IDC_STATIC,242,33,56,8
LTEXT "Instrument",IDC_STATIC,242,17,36,8
EDITTEXT IDC_INSTRUMENT_NAME,301,30,84,14,ES_AUTOHSCROLL
COMBOBOX IDC_INSTRUMENT,301,14,85,184,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
LTEXT "0",IDC_VOICECOUNT1,333,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT2,349,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT3,365,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT4,381,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT5,397,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT6,413,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT7,429,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT8,445,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT9,461,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT10,477,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT11,493,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT12,509,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT13,525,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT14,541,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT15,557,322,14,12,0,WS_EX_STATICEDGE
LTEXT "0",IDC_VOICECOUNT16,573,322,14,12,0,WS_EX_STATICEDGE
LTEXT "Activated Voices",IDC_STATIC,278,324,54,8
PUSHBUTTON "Record",IDC_RECORD_BUTTON,449,10,62,14
PUSHBUTTON "Stop",IDC_STOP_BUTTON,449,24,62,14,WS_DISABLED
CONTROL "Solo",IDC_SOLO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,398,24,29,10
GROUPBOX "4k Export",IDC_STATIC,437,0,150,66
COMBOBOX IDC_PATTERN_SIZE,479,38,33,94,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
GROUPBOX "Current Unit",IDC_MODULE_SETTINGS,277,61,310,202
CONTROL "",IDC_MAINTAB,"SysTabControl32",0x0,7,53,266,281
GROUPBOX "Load/Save",IDC_STATIC,7,3,225,47
PUSHBUTTON "PANIC!",IDC_PANIC,278,288,309,29
GROUPBOX "Instrument Properties",IDC_STATIC,237,3,195,47
COMBOBOX IDC_POLYPHONY,333,270,71,97,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
LTEXT "Polyphony",IDC_STATIC,278,272,34,8
LTEXT "Pattern",IDC_STATIC,450,41,25,8
PUSHBUTTON "Reset",IDC_UNIT_RESET,303,72,50,14
PUSHBUTTON "Copy",IDC_UNIT_COPY,355,72,50,14
PUSHBUTTON "Paste",IDC_UNIT_PASTE,407,72,50,14
PUSHBUTTON "Load",IDC_UNIT_LOAD,459,72,50,14
PUSHBUTTON "Save",IDC_UNIT_SAVE,511,72,50,14
CONTROL "Always on top",IDC_ALWAYSONTOP,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,527,267,64,20
CONTROL "Record Notes",IDC_NOTEVALUES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,516,32,57,10
CONTROL "Undenormalize",IDC_UNDENORMALIZE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,516,14,61,10
CONTROL "Clip Output",IDC_CLIPOUTPUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,516,5,52,10
CONTROL "Record Envs",IDC_ENVLEVELS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,516,23,57,10
CONTROL "16Bit Output",IDC_16BIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,516,41,57,10
CTEXT "Static",IDC_ISTACK_VALID,11,321,241,9
CTEXT "Static",IDC_GSTACK_VALID,11,321,241,9
COMBOBOX IDC_PATTERN_QUANT,479,51,33,94,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
LTEXT "Quant.",IDC_STATIC,449,54,24,8
COMBOBOX IDC_OBJFORMAT,515,51,66,72,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
END
IDD_VCO DIALOGEX 0, 0, 300, 170
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Oscillator",IDC_STATIC,0,0,300,170
PUSHBUTTON "Sine",IDC_VCO_SINE,6,27,50,14,WS_DISABLED
PUSHBUTTON "Tri/Saw",IDC_VCO_TRISAW,56,27,50,14
PUSHBUTTON "Pulse",IDC_VCO_PULSE,106,27,50,14
PUSHBUTTON "Noise",IDC_VCO_NOISE,156,27,50,14
CONTROL "",IDC_VCO_GAIN,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,127,200,15
CONTROL "",IDC_VCO_TRANSPOSE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,47,200,15
CONTROL "",IDC_VCO_DETUNE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,63,200,15
CONTROL "",IDC_VCO_PHASE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,79,200,15
CONTROL "",IDC_VCO_COLOR,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,95,200,15
LTEXT "Transpose",IDC_STATIC,4,51,34,8
LTEXT "Phase",IDC_STATIC,4,82,20,8
LTEXT "Detune",IDC_STATIC,4,67,24,8
LTEXT "Color",IDC_STATIC,4,98,18,8
LTEXT "Gain",IDC_STATIC,4,130,15,8
CONTROL "",IDC_VCO_SHAPE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,111,200,15
LTEXT "Shape",IDC_STATIC,4,114,21,8
CTEXT " ",IDC_VCO_TRANSPOSE_VAL,242,48,48,12,SS_SUNKEN
CTEXT " ",IDC_VCO_DETUNE_VAL,242,64,48,12,SS_SUNKEN
CTEXT " ",IDC_VCO_PHASE_VAL,242,80,48,12,SS_SUNKEN
CTEXT " ",IDC_VCO_COLOR_VAL,242,96,48,12,SS_SUNKEN
CTEXT " ",IDC_VCO_SHAPE_VAL,242,112,48,12,SS_SUNKEN
CTEXT " ",IDC_VCO_GAIN_VAL,242,128,48,12,SS_SUNKEN
CONTROL "LFO",IDC_VCO_LFO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,262,29,29,10
PUSHBUTTON "Gate",IDC_VCO_GATE,206,27,50,14
CONTROL " ",IDC_VCO_GATE1,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,43,147,8,10
CONTROL " ",IDC_VCO_GATE2,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,55,147,8,10
CONTROL " ",IDC_VCO_GATE3,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,67,147,8,10
CONTROL " ",IDC_VCO_GATE4,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,79,147,8,10
CONTROL " ",IDC_VCO_GATE5,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,91,147,8,10
CONTROL " ",IDC_VCO_GATE6,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,103,147,8,10
CONTROL " ",IDC_VCO_GATE7,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,115,147,8,10
CONTROL " ",IDC_VCO_GATE8,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,127,147,8,10
CONTROL " ",IDC_VCO_GATE9,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,139,147,8,10
CONTROL " ",IDC_VCO_GATE10,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,151,147,8,10
CONTROL " ",IDC_VCO_GATE11,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,163,147,8,10
CONTROL " ",IDC_VCO_GATE12,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,175,147,8,10
CONTROL " ",IDC_VCO_GATE13,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,187,147,8,10
CONTROL " ",IDC_VCO_GATE14,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,199,147,8,10
CONTROL " ",IDC_VCO_GATE15,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,211,147,8,10
CONTROL " ",IDC_VCO_GATE16,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,223,147,8,10
LTEXT "Gate",IDC_STATIC,4,147,16,8
END
IDD_VCF DIALOGEX 0, 0, 300, 170
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Filter",IDC_STATIC,0,0,299,170
PUSHBUTTON "Low",IDC_VCF_LOW,24,59,42,14,WS_DISABLED
PUSHBUTTON "High",IDC_VCF_HIGH,66,59,41,14
PUSHBUTTON "Band",IDC_VCF_BAND,108,59,41,14
PUSHBUTTON "Notch",IDC_VCF_NOTCH,150,59,41,14
PUSHBUTTON "Peak",IDC_VCF_PEAK,192,59,41,14
PUSHBUTTON "All",IDC_VCF_ALL,234,59,41,14
CONTROL "",IDC_VCF_FREQUENCY,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,79,200,15
CONTROL "",IDC_VCF_RESONANCE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,95,200,15
LTEXT "Frequency",IDC_STATIC,4,82,35,8
LTEXT "Resonance",IDC_STATIC,4,99,36,8
CTEXT " ",IDC_VCF_FREQUENCY_VAL,242,80,48,12,SS_SUNKEN
CTEXT " ",IDC_VCF_RESONANCE_VAL,242,96,48,12,SS_SUNKEN
END
IDD_ENV DIALOGEX 0, 0, 300, 170
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Envelope",IDC_STATIC,0,0,300,170
CONTROL "",IDC_ENV_GAIN,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,109,200,15
CONTROL "",IDC_ENV_ATTACK,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,46,200,15
CONTROL "",IDC_ENV_DECAY,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,61,200,15
CONTROL "",IDC_ENV_SUSTAIN,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,77,200,15
CONTROL "",IDC_ENV_RELEASE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,93,200,15
LTEXT "Attack",IDC_STATIC,4,49,22,8
LTEXT "Sustain",IDC_STATIC,4,80,24,8
LTEXT "Decay",IDC_STATIC,4,65,21,8
LTEXT "Release",IDC_STATIC,4,96,26,8
LTEXT "Gain",IDC_STATIC,4,112,15,8
CTEXT " ",IDC_ENV_ATTACK_VAL,242,46,48,12,SS_SUNKEN
CTEXT " ",IDC_ENV_DECAY_VAL,242,62,48,12,SS_SUNKEN
CTEXT " ",IDC_ENV_SUSTAIN_VAL,242,78,48,12,SS_SUNKEN
CTEXT " ",IDC_ENV_RELEASE_VAL,242,94,48,12,SS_SUNKEN
CTEXT " ",IDC_ENV_GAIN_VAL,242,110,48,12,SS_SUNKEN
END
IDD_DLL DIALOGEX 0, 0, 300, 170
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Delay/Reverb",IDC_STATIC,0,0,300,170
CONTROL "",IDC_DLL_DRY,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,73,200,15
CONTROL "",IDC_DLL_PREGAIN,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,42,200,15
CONTROL "",IDC_DLL_FEEDBACK,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,57,200,15
LTEXT "Pregain",IDC_STATIC,4,45,25,8
LTEXT "Feedback",IDC_STATIC,4,61,32,8
LTEXT "Dry",IDC_STATIC,4,76,12,8
CTEXT " ",IDC_DLL_PREGAIN_VAL,242,42,48,12,SS_SUNKEN
CTEXT " ",IDC_DLL_FEEDBACK_VAL,242,58,48,12,SS_SUNKEN
CTEXT " ",IDC_DLL_DRY_VAL,242,74,48,12,SS_SUNKEN
CONTROL "",IDC_DLL_DAMP,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,90,200,15
LTEXT "Damp",IDC_STATIC,4,93,19,8
CTEXT " ",IDC_DLL_DAMP_VAL,242,90,48,12,SS_SUNKEN
PUSHBUTTON "Delay",IDC_DLL_DELAY,134,13,50,14
PUSHBUTTON "Reverb",IDC_DLL_REVERB,184,13,50,14
CONTROL "",IDC_DLL_DTIME,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,106,200,15
LTEXT "Delay",IDC_STATIC,4,110,19,8
PUSHBUTTON "BPM",IDC_DLL_BPMSYNC,47,15,40,10
PUSHBUTTON "Note",IDC_DLL_NOTESYNC,87,15,40,10
CTEXT " ",IDC_DLL_DTIME_VAL,242,106,48,12,SS_SUNKEN
CONTROL "Left Reverb",IDC_DLL_LEFTREVERB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,16,54,10
PUSHBUTTON "No Sync",IDC_DLL_NOSYNC,7,15,40,10
CONTROL "",IDC_DLL_FREQUENCY,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,122,200,15
LTEXT "Frequency",IDC_STATIC,4,127,35,8
CTEXT " ",IDC_DLL_FREQUENCY_VAL,242,122,48,12,SS_SUNKEN
CONTROL "",IDC_DLL_DEPTH,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,138,200,15
LTEXT "Depth",IDC_STATIC,4,143,20,8
CTEXT " ",IDC_DLL_DEPTH_VAL,242,138,48,12,SS_SUNKEN
END
IDD_DST DIALOGEX 0, 0, 300, 170
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Distortion",IDC_STATIC,0,0,299,170
CONTROL "",IDC_DST_DRIVE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,69,200,15
LTEXT "Drive",IDC_STATIC,4,73,18,8
LTEXT "S&&H",IDC_STATIC,4,89,14,8
CONTROL "",IDC_DST_SNH,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,85,200,15
CTEXT " ",IDC_DST_DRIVE_VAL,242,70,48,12,SS_SUNKEN
CTEXT " ",IDC_DST_SNH_VAL,242,86,48,12,SS_SUNKEN
END
IDD_INSTRUMENT_STACK DIALOGEX 0, 0, 247, 320
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPCHILDREN | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON " ",IDC_ISTACK_UNIT1,15,0,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP1,165,0,25,10,NOT WS_VISIBLE
PUSHBUTTON "Down",IDC_ISTACK_DOWN1,191,0,25,10,NOT WS_VISIBLE
CTEXT "1",IDC_ISTACK_SIGNALCOUNT1,225,0,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT2,15,10,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP2,165,10,25,10,NOT WS_VISIBLE
PUSHBUTTON "Down",IDC_ISTACK_DOWN2,191,10,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT2,225,10,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT3,15,20,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP3,165,20,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN3,191,20,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT3,225,20,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT4,15,30,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP4,165,30,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN4,191,30,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT4,225,30,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT5,15,40,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP5,165,40,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN5,191,40,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT5,225,40,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT6,15,50,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP6,165,50,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN6,191,50,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT6,225,50,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT7,15,60,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP7,165,60,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN7,191,60,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT7,225,60,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT8,15,70,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP8,165,70,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN8,191,70,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT8,225,70,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT9,15,80,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP9,165,80,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN9,191,80,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT9,225,80,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT10,15,90,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP10,165,90,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN10,191,90,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT10,225,90,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT11,15,100,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP11,165,100,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN11,191,100,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT11,225,100,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT12,15,110,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP12,165,110,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN12,191,110,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT12,225,110,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT13,15,120,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP13,165,120,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN13,191,120,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT13,225,120,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT14,15,130,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP14,165,130,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN14,191,130,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT14,225,130,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT15,15,140,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP15,165,140,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN15,191,140,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT15,225,140,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT16,15,150,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP16,165,150,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN16,191,150,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT16,225,150,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT17,15,160,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP17,165,160,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN17,191,160,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT17,225,160,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT18,15,170,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP18,165,170,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN18,191,170,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT18,225,170,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT19,15,180,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP19,165,180,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN19,191,180,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT19,225,180,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT20,15,190,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP20,165,190,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN20,191,190,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT20,225,190,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT21,15,200,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP21,165,200,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN21,191,200,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT21,225,200,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT22,15,210,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP22,165,210,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN22,191,210,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT22,225,210,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT23,15,220,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP23,165,220,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN23,191,220,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT23,225,220,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT24,15,230,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP24,165,230,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN24,191,230,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT24,225,230,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT25,15,240,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP25,165,240,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN25,191,240,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT25,225,240,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT26,15,250,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP26,165,250,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN26,191,250,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT26,225,250,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT27,15,260,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP27,165,260,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN27,191,260,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT27,225,260,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT28,15,270,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP28,165,270,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN28,191,270,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT28,225,270,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT29,15,280,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP29,165,280,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN29,191,280,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT29,225,280,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT30,15,290,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP30,165,290,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN30,191,290,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT30,225,290,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT31,15,300,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP31,165,300,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN31,191,300,25,10
CTEXT "1",IDC_ISTACK_SIGNALCOUNT31,225,300,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_ISTACK_UNIT32,15,310,83,10
PUSHBUTTON "Up",IDC_ISTACK_UP32,165,310,25,10
PUSHBUTTON "Down",IDC_ISTACK_DOWN32,191,310,25,10,NOT WS_VISIBLE
CTEXT "1",IDC_ISTACK_SIGNALCOUNT32,225,310,16,10,SS_SUNKEN
PUSHBUTTON "Set",IDC_ISTACK_SET1,106,0,25,10,NOT WS_VISIBLE
PUSHBUTTON "Clear",IDC_ISTACK_RESET1,132,0,25,10,NOT WS_VISIBLE
PUSHBUTTON "Set",IDC_ISTACK_SET2,106,10,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET2,132,10,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET3,106,20,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET3,132,20,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET4,106,30,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET4,132,30,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET5,106,40,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET5,132,40,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET6,106,50,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET6,132,50,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET7,106,60,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET7,132,60,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET8,106,70,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET8,132,70,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET9,106,80,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET9,132,80,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET10,106,90,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET10,132,90,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET11,106,100,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET11,132,100,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET12,106,110,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET12,132,110,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET13,106,120,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET13,132,120,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET14,106,130,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET14,132,130,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET15,106,140,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET15,132,140,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET16,106,150,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET16,132,150,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET17,106,160,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET17,132,160,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET18,106,170,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET18,132,170,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET19,106,180,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET19,132,180,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET20,106,190,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET20,132,190,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET21,106,200,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET21,132,200,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET22,106,210,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET22,132,210,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET23,106,220,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET23,132,220,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET24,106,230,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET24,132,230,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET25,106,240,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET25,132,240,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET26,106,250,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET26,132,250,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET27,106,260,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET27,132,260,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET28,106,270,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET28,132,270,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET29,106,280,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET29,132,280,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET30,106,290,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET30,132,290,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET31,106,300,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET31,132,300,25,10
PUSHBUTTON "Set",IDC_ISTACK_SET32,106,310,25,10
PUSHBUTTON "Clear",IDC_ISTACK_RESET32,132,310,25,10
LTEXT "1:",IDC_STATIC,2,1,10,8
LTEXT "2:",IDC_STATIC,2,11,10,8
LTEXT "3:",IDC_STATIC,2,21,10,8
LTEXT "4:",IDC_STATIC,2,31,10,8
LTEXT "5:",IDC_STATIC,2,41,10,8
LTEXT "6:",IDC_STATIC,2,51,10,8
LTEXT "7:",IDC_STATIC,2,61,10,8
LTEXT "8:",IDC_STATIC,2,71,10,8
LTEXT "9:",IDC_STATIC,2,81,10,8
LTEXT "10:",IDC_STATIC,2,91,10,8
LTEXT "11:",IDC_STATIC,2,101,10,8
LTEXT "12:",IDC_STATIC,2,111,10,8
LTEXT "13:",IDC_STATIC,2,121,10,8
LTEXT "14:",IDC_STATIC,2,131,10,8
LTEXT "15:",IDC_STATIC,2,141,10,8
LTEXT "16:",IDC_STATIC,2,151,10,8
LTEXT "17:",IDC_STATIC,2,161,10,8
LTEXT "18:",IDC_STATIC,2,171,10,8
LTEXT "19:",IDC_STATIC,2,181,10,8
LTEXT "20:",IDC_STATIC,2,191,10,8
LTEXT "21:",IDC_STATIC,2,201,10,8
LTEXT "22:",IDC_STATIC,2,211,10,8
LTEXT "23:",IDC_STATIC,2,221,10,8
LTEXT "24:",IDC_STATIC,2,231,10,8
LTEXT "25:",IDC_STATIC,2,241,10,8
LTEXT "26:",IDC_STATIC,2,251,10,8
LTEXT "27:",IDC_STATIC,2,261,10,8
LTEXT "28:",IDC_STATIC,2,271,10,8
LTEXT "29:",IDC_STATIC,2,281,10,8
LTEXT "30:",IDC_STATIC,2,291,10,8
LTEXT "31:",IDC_STATIC,2,301,10,8
LTEXT "32:",IDC_STATIC,2,311,10,8
END
IDD_FOP DIALOGEX 0, 0, 300, 170
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Floating Point Operation",IDC_STATIC,0,0,299,170
PUSHBUTTON "POP",IDC_FOP_POP,3,50,42,14
PUSHBUTTON "PUSH",IDC_FOP_PUSH,3,33,42,14
PUSHBUTTON "XCH",IDC_FOP_XCH,3,67,42,14
PUSHBUTTON "+",IDC_FOP_ADD,3,84,42,14
PUSHBUTTON "+/POP",IDC_FOP_ADDP,3,101,42,14
PUSHBUTTON "*",IDC_FOP_MUL,3,118,42,14
PUSHBUTTON "*/POP",IDC_FOP_MULP,3,135,42,14
LTEXT "IN: a b c d -> OUT: a a b c d",IDC_STATIC,50,35,232,8
LTEXT "IN: a b c d -> OUT: b c d",IDC_STATIC,50,52,196,8
LTEXT "IN: a b c d -> OUT: b a c d",IDC_STATIC,50,69,214,8
LTEXT "IN: a b c d -> OUT: a+b b c d",IDC_STATIC,50,86,216,8
LTEXT "IN: a b c d -> OUT: a+b c d",IDC_STATIC,50,103,198,8
LTEXT "IN: a b c d -> OUT: a*b b c d",IDC_STATIC,50,120,216,8
LTEXT "IN: a b c d -> OUT: a*b c d",IDC_STATIC,50,137,198,8
PUSHBUTTON "2+/POP",IDC_FOP_ADDP2,3,152,42,14
LTEXT "IN: a b c d -> OUT: a+c b+d",IDC_STATIC,50,155,193,8
GROUPBOX "",IDC_STATIC,0,27,299,22
GROUPBOX "",IDC_STATIC,0,61,299,22
GROUPBOX "",IDC_STATIC,0,95,299,22
GROUPBOX "",IDC_STATIC,0,129,299,23
GROUPBOX "",IDC_STATIC,0,147,299,21
PUSHBUTTON "Load Note",IDC_FOP_LOADNOTE,3,16,42,14
LTEXT "IN: a b c d -> OUT: note a b c d",IDC_STATIC,50,18,233,8
GROUPBOX "",IDC_STATIC,0,10,299,22
END
IDD_FST DIALOGEX 0, 0, 300, 170
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Store Signal",IDC_STATIC,0,0,299,170
CONTROL "",IDC_FST_AMOUNT,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,36,101,200,15
LTEXT "Amount",IDC_STATIC,3,104,26,8
CTEXT " ",IDC_FST_AMOUNT_VAL,242,102,48,12,SS_SUNKEN
COMBOBOX IDC_FST_DESTINATION_INSTRUMENT,43,53,249,177,CBS_DROPDOWN | CBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP
LTEXT "Stack",IDC_STATIC,5,55,18,8
COMBOBOX IDC_FST_DESTINATION_UNIT,43,69,249,157,CBS_DROPDOWN | CBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP
LTEXT "Unit",IDC_STATIC,6,71,14,8
COMBOBOX IDC_FST_DESTINATION_SLOT,43,85,249,110,CBS_DROPDOWN | CBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP
LTEXT "Slot",IDC_STATIC,5,87,13,8
END
IDD_NONE DIALOGEX 0, 0, 300, 170
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "",-1,0,0,299,170
LTEXT "Nothing selected",-1,123,80,54,8
END
IDD_OUT DIALOGEX 0, 0, 300, 170
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Instrument Output",IDC_STATIC,0,0,299,170
CONTROL "",IDC_OUT_GAIN,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,37,70,200,15
LTEXT "Gain",IDC_STATIC,6,73,15,8
LTEXT "AUX Send",IDC_STATIC,6,89,32,8
CONTROL "",IDC_OUT_AUXSEND,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,37,85,200,15
CTEXT " ",IDC_OUT_GAIN_VAL,242,70,48,12,SS_SUNKEN
CTEXT " ",IDC_OUT_AUXSEND_VAL,242,86,48,12,SS_SUNKEN
END
IDD_GLOBAL_STACK DIALOGEX 0, 0, 247, 320
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPCHILDREN
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON " ",IDC_GSTACK_UNIT1,15,0,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP1,165,0,25,10,NOT WS_VISIBLE
PUSHBUTTON "Down",IDC_GSTACK_DOWN1,191,0,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT1,225,0,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT2,15,10,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP2,165,10,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN2,191,10,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT2,225,10,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT3,15,20,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP3,165,20,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN3,191,20,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT3,225,20,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT4,15,30,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP4,165,30,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN4,191,30,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT4,225,30,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT5,15,40,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP5,165,40,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN5,191,40,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT5,225,40,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT6,15,50,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP6,165,50,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN6,191,50,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT6,225,50,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT7,15,60,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP7,165,60,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN7,191,60,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT7,225,60,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT8,15,70,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP8,165,70,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN8,191,70,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT8,225,70,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT9,15,80,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP9,165,80,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN9,191,80,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT9,225,80,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT10,15,90,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP10,165,90,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN10,191,90,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT10,225,90,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT11,15,100,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP11,165,100,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN11,191,100,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT11,225,100,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT12,15,110,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP12,165,110,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN12,191,110,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT12,225,110,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT13,15,120,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP13,165,120,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN13,191,120,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT13,225,120,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT14,15,130,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP14,165,130,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN14,191,130,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT14,225,130,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT15,15,140,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP15,165,140,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN15,191,140,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT15,225,140,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT16,15,150,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP16,165,150,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN16,191,150,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT16,225,150,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT17,15,160,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP17,165,160,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN17,191,160,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT17,225,160,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT18,15,170,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP18,165,170,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN18,191,170,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT18,225,170,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT19,15,180,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP19,165,180,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN19,191,180,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT19,225,180,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT20,15,190,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP20,165,190,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN20,191,190,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT20,225,190,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT21,15,200,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP21,165,200,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN21,191,200,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT21,225,200,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT22,15,210,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP22,165,210,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN22,191,210,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT22,225,210,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT23,15,220,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP23,165,220,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN23,191,220,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT23,225,220,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT24,15,230,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP24,165,230,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN24,191,230,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT24,225,230,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT25,15,240,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP25,165,240,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN25,191,240,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT25,225,240,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT26,15,250,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP26,165,250,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN26,191,250,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT26,225,250,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT27,15,260,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP27,165,260,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN27,191,260,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT27,225,260,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT28,15,270,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP28,165,270,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN28,191,270,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT28,225,270,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT29,15,280,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP29,165,280,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN29,191,280,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT29,225,280,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT30,15,290,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP30,165,290,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN30,191,290,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT30,225,290,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT31,15,300,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP31,165,300,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN31,191,300,25,10
CTEXT "1",IDC_GSTACK_SIGNALCOUNT31,225,300,16,10,SS_SUNKEN
PUSHBUTTON " ",IDC_GSTACK_UNIT32,15,310,83,10
PUSHBUTTON "Up",IDC_GSTACK_UP32,165,310,25,10
PUSHBUTTON "Down",IDC_GSTACK_DOWN32,191,310,25,10,NOT WS_VISIBLE
CTEXT "1",IDC_GSTACK_SIGNALCOUNT32,225,310,16,10,SS_SUNKEN
PUSHBUTTON "Set",IDC_GSTACK_SET1,106,0,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET1,132,0,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET2,106,10,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET2,132,10,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET3,106,20,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET3,132,20,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET4,106,30,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET4,132,30,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET5,106,40,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET5,132,40,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET6,106,50,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET6,132,50,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET7,106,60,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET7,132,60,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET8,106,70,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET8,132,70,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET9,106,80,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET9,132,80,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET10,106,90,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET10,132,90,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET11,106,100,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET11,132,100,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET12,106,110,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET12,132,110,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET13,106,120,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET13,132,120,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET14,106,130,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET14,132,130,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET15,106,140,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET15,132,140,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET16,106,150,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET16,132,150,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET17,106,160,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET17,132,160,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET18,106,170,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET18,132,170,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET19,106,180,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET19,132,180,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET20,106,190,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET20,132,190,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET21,106,200,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET21,132,200,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET22,106,210,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET22,132,210,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET23,106,220,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET23,132,220,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET24,106,230,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET24,132,230,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET25,106,240,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET25,132,240,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET26,106,250,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET26,132,250,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET27,106,260,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET27,132,260,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET28,106,270,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET28,132,270,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET29,106,280,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET29,132,280,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET30,106,290,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET30,132,290,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET31,106,300,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET31,132,300,25,10
PUSHBUTTON "Set",IDC_GSTACK_SET32,106,310,25,10
PUSHBUTTON "Clear",IDC_GSTACK_RESET32,132,310,25,10
LTEXT "1:",IDC_STATIC,2,1,10,8
LTEXT "2:",IDC_STATIC,2,11,10,8
LTEXT "3:",IDC_STATIC,2,21,10,8
LTEXT "4:",IDC_STATIC,2,31,10,8
LTEXT "5:",IDC_STATIC,2,41,10,8
LTEXT "6:",IDC_STATIC,2,51,10,8
LTEXT "7:",IDC_STATIC,2,61,10,8
LTEXT "8:",IDC_STATIC,2,71,10,8
LTEXT "9:",IDC_STATIC,2,81,10,8
LTEXT "10:",IDC_STATIC,2,91,10,8
LTEXT "11:",IDC_STATIC,2,101,10,8
LTEXT "12:",IDC_STATIC,2,111,10,8
LTEXT "13:",IDC_STATIC,2,121,10,8
LTEXT "14:",IDC_STATIC,2,131,10,8
LTEXT "15:",IDC_STATIC,2,141,10,8
LTEXT "16:",IDC_STATIC,2,151,10,8
LTEXT "17:",IDC_STATIC,2,161,10,8
LTEXT "18:",IDC_STATIC,2,171,10,8
LTEXT "19:",IDC_STATIC,2,181,10,8
LTEXT "20:",IDC_STATIC,2,191,10,8
LTEXT "21:",IDC_STATIC,2,201,10,8
LTEXT "22:",IDC_STATIC,2,211,10,8
LTEXT "23:",IDC_STATIC,2,221,10,8
LTEXT "24:",IDC_STATIC,2,231,10,8
LTEXT "25:",IDC_STATIC,2,241,10,8
LTEXT "26:",IDC_STATIC,2,251,10,8
LTEXT "27:",IDC_STATIC,2,261,10,8
LTEXT "28:",IDC_STATIC,2,271,10,8
LTEXT "29:",IDC_STATIC,2,281,10,8
LTEXT "30:",IDC_STATIC,2,291,10,8
LTEXT "31:",IDC_STATIC,2,301,10,8
LTEXT "32:",IDC_STATIC,2,311,10,8
END
IDD_PAN DIALOGEX 0, 0, 300, 170
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Panning",-1,0,0,299,170
CONTROL "",IDC_PAN_PANNING,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,77,200,15
LTEXT "Panning",-1,6,80,26,8
CTEXT " ",IDC_PAN_PANNING_VAL,242,77,48,12,SS_SUNKEN
END
IDD_SET_DIALOG DIALOGEX 0, 0, 186, 44
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Set"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,129,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,129,21,50,14
COMBOBOX IDC_SET_UNIT,7,23,92,121,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
LTEXT "Select Unit",IDC_STATIC,7,7,36,8
END
IDD_ACC DIALOGEX 0, 0, 300, 170
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Accumulate Signals",-1,0,0,299,170
PUSHBUTTON "Output",IDC_ACC_OUT,99,77,50,14,WS_DISABLED
PUSHBUTTON "AUX",IDC_ACC_AUX,149,77,50,14
END
IDD_FLD DIALOGEX 0, 0, 300, 170
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Load Signal",-1,0,0,299,170
CONTROL "",IDC_FLD_VALUE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,77,200,15
LTEXT "Value",-1,6,80,26,8
CTEXT " ",IDC_FLD_VALUE_VAL,242,77,48,12,SS_SUNKEN
END
IDD_SCROLLWINDOW DIALOGEX 0, 0, 263, 258
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_SYSMENU
EXSTYLE WS_EX_CLIENTEDGE
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_GO4KVSTIDIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 587
TOPMARGIN, 7
BOTTOMMARGIN, 334
END
IDD_SET_DIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 35
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog Info
//
IDD_GO4KVSTIDIALOG DLGINIT
BEGIN
IDC_PATTERN_SIZE, 0x403, 12, 0
0x6538, 0x2072, 0x6150, 0x7474, 0x7265, 0x006e,
IDC_PATTERN_SIZE, 0x403, 13, 0
0x3631, 0x7265, 0x5020, 0x7461, 0x6574, 0x6e72, "\000"
IDC_PATTERN_SIZE, 0x403, 13, 0
0x3233, 0x7265, 0x5020, 0x7461, 0x6574, 0x6e72, "\000"
IDC_PATTERN_SIZE, 0x403, 13, 0
0x3436, 0x7265, 0x5020, 0x7461, 0x6574, 0x6e72, "\000"
IDC_PATTERN_QUANT, 0x403, 12, 0
0x6538, 0x2072, 0x6150, 0x7474, 0x7265, 0x006e,
IDC_PATTERN_QUANT, 0x403, 13, 0
0x3631, 0x7265, 0x5020, 0x7461, 0x6574, 0x6e72, "\000"
IDC_PATTERN_QUANT, 0x403, 13, 0
0x3233, 0x7265, 0x5020, 0x7461, 0x6574, 0x6e72, "\000"
IDC_PATTERN_QUANT, 0x403, 13, 0
0x3436, 0x7265, 0x5020, 0x7461, 0x6574, 0x6e72, "\000"
0
END
#endif // German (Germany) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -1,19 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "4klang", "Go4kVSTi.vcproj", "{107757EA-2FE1-4C5E-964F-DE7E482E253F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{107757EA-2FE1-4C5E-964F-DE7E482E253F}.Debug|Win32.ActiveCfg = Debug|Win32
{107757EA-2FE1-4C5E-964F-DE7E482E253F}.Debug|Win32.Build.0 = Debug|Win32
{107757EA-2FE1-4C5E-964F-DE7E482E253F}.Release|Win32.ActiveCfg = Release|Win32
{107757EA-2FE1-4C5E-964F-DE7E482E253F}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -1,361 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="4klang"
ProjectGUID="{107757EA-2FE1-4C5E-964F-DE7E482E253F}"
RootNamespace="Go4kVSTi"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Debug/vstxsynth.tlb"
/>
<Tool
Name="VCCLCompilerTool"
UseUnicodeResponseFiles="false"
Optimization="0"
AdditionalIncludeDirectories="..\source\common"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;WINDOWS=1;_CRT_SECURE_NO_DEPRECATE"
ExceptionHandling="1"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
StructMemberAlignment="1"
BufferSecurityCheck="true"
FloatingPointModel="2"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=".\Debug/Go4kVSTi.pch"
AssemblerOutput="0"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib"
OutputFile="$(OutDir)\$(ProjectName).dll"
LinkIncremental="2"
SuppressStartupBanner="true"
ModuleDefinitionFile=".\Go4kVSTi.def"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug/Go4kVSTi.pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Debug/Go4kVSTi.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Release/vstxsynth.tlb"
/>
<Tool
Name="VCCLCompilerTool"
UseUnicodeResponseFiles="false"
Optimization="0"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
WholeProgramOptimization="false"
AdditionalIncludeDirectories="..\source\common"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINDOWS=1;_CRT_SECURE_NO_DEPRECATE"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
StructMemberAlignment="1"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
EnableEnhancedInstructionSet="0"
FloatingPointModel="2"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=".\Release/Go4kVSTi.pch"
AssemblerOutput="0"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="0"
CallingConvention="0"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib"
OutputFile="$(OutDir)\$(ProjectName).dll"
LinkIncremental="1"
SuppressStartupBanner="true"
GenerateManifest="false"
ModuleDefinitionFile=".\Go4kVSTi.def"
ProgramDatabaseFile=".\Release/Go4kVSTi.pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Release/Go4kVSTi.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
EmbedManifest="false"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath="..\source\common\AudioEffect.cpp"
>
</File>
<File
RelativePath="..\source\common\audioeffectx.cpp"
>
</File>
<File
RelativePath="..\source\GoSynth\Go4kVSTi.cpp"
>
</File>
<File
RelativePath="Go4kVSTi.rc"
>
</File>
<File
RelativePath="..\source\GoSynth\Go4kVSTiCore.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
CallingConvention="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\source\GoSynth\Go4kVSTiGUI.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
CallingConvention="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\source\GoSynth\Go4kVSTimain.cpp"
>
</File>
<File
RelativePath="..\source\GoSynth\Go4kVSTiproc.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath="..\source\common\AEffect.h"
>
</File>
<File
RelativePath="..\source\common\aeffectx.h"
>
</File>
<File
RelativePath="..\source\common\AEffEditor.hpp"
>
</File>
<File
RelativePath="..\source\common\AudioEffect.hpp"
>
</File>
<File
RelativePath="..\source\common\audioeffectx.h"
>
</File>
<File
RelativePath="..\source\GoSynth\Go4kVSTi.h"
>
</File>
<File
RelativePath="..\source\GoSynth\Go4kVSTiCore.h"
>
</File>
<File
RelativePath="..\source\GoSynth\Go4kVSTiGUI.h"
>
</File>
<File
RelativePath="resource.h"
>
</File>
</Filter>
<File
RelativePath=".\4klang.asm"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="d:\code\nasm\nasmw -fwin32 -o&quot;$(IntDir)\4klang.obj&quot; 4klang.asm&#x0D;&#x0A;"
Outputs="$(IntDir)\4klang.obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="d:\code\nasm\nasmw -fwin32 -o&quot;$(IntDir)\4klang.obj&quot; 4klang.asm&#x0D;&#x0A;"
Outputs="$(IntDir)\4klang.obj"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\4klang.bin"
>
</File>
<File
RelativePath=".\4klang.inc"
>
</File>
<File
RelativePath=".\nasmw.bin"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -1,2 +0,0 @@
SimpleCrypt.exe 4klang.asm 4klang.bin
SimpleCrypt.exe nasmw.exe nasmw.bin

Binary file not shown.

Binary file not shown.

View File

@ -1,594 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Go4kVSTi.rc
//
#define IDD_NONE 100
#define IDD_ENV 101
#define IDD_VCO 102
#define IDD_VCF 103
#define IDD_DST 104
#define IDD_DLL 105
#define IDD_FOP 106
#define IDD_FST 107
#define IDD_PAN 108
#define IDD_OUT 109
#define IDD_ACC 110
#define IDD_FLD 111
#define IDD_GO4KVSTIDIALOG 115
#define IDD_INSTRUMENT_STACK 120
#define IDD_GLOBAL_STACK 121
#define IDD_SET_DIALOG 122
#define IDD_SCROLLWINDOW 123
#define IDR_COMP_RES 130
#define IDR_ASM_RES 131
#define IDC_SET_UNIT 1000
#define IDC_MAINTAB 1001
#define IDC_LOAD_PATCH 1002
#define IDC_SAVE_PATCH 1003
#define IDC_RESET_PATCH 1004
#define IDC_LOAD_INSTRUMENT 1005
#define IDC_SAVE_INSTRUMENT 1006
#define IDC_RESET_INSTRUMENT 1007
#define IDC_INSTRUMENT_NAME 1008
#define IDC_INSTRUMENT 1009
#define IDC_SOLO 1010
#define IDC_RECORD_BUTTON 1011
#define IDC_STOP_BUTTON 1012
#define IDC_PATTERN_SIZE 1013
#define IDC_PANIC 1014
#define IDC_MODULE_SETTINGS 1015
#define IDC_POLYPHONY 1016
#define IDC_ENVLEVELS 1017
#define IDC_NOTEVALUES 1018
#define IDC_OBJFORMAT 1019
#define IDC_VOICECOUNT1 1020
#define IDC_VOICECOUNT2 1021
#define IDC_VOICECOUNT3 1022
#define IDC_VOICECOUNT4 1023
#define IDC_VOICECOUNT5 1024
#define IDC_VOICECOUNT6 1025
#define IDC_VOICECOUNT7 1026
#define IDC_VOICECOUNT8 1027
#define IDC_VOICECOUNT9 1028
#define IDC_VOICECOUNT10 1029
#define IDC_VOICECOUNT11 1030
#define IDC_VOICECOUNT12 1031
#define IDC_VOICECOUNT13 1032
#define IDC_VOICECOUNT14 1033
#define IDC_VOICECOUNT15 1034
#define IDC_VOICECOUNT16 1035
#define IDC_UNDENORMALIZE 1036
#define IDC_CLIPOUTPUT 1037
#define IDC_16BIT 1038
#define IDC_ALWAYSONTOP 1039
#define IDC_ISTACK_VALID 1040
#define IDC_GSTACK_VALID 1041
#define IDC_PATTERN_QUANT 1042
#define IDC_UNIT_RESET 1050
#define IDC_UNIT_COPY 1051
#define IDC_UNIT_PASTE 1052
#define IDC_UNIT_LOAD 1053
#define IDC_UNIT_SAVE 1054
#define IDC_ENV_ATTACK 1100
#define IDC_ENV_ATTACK_VAL 1101
#define IDC_ENV_ATTACK_QUANT 1102
#define IDC_ENV_DECAY 1103
#define IDC_ENV_DECAY_VAL 1104
#define IDC_ENV_DECAY_QUANT 1105
#define IDC_ENV_SUSTAIN 1106
#define IDC_ENV_SUSTAIN_VAL 1107
#define IDC_ENV_SUSTAIN_QUANT 1108
#define IDC_ENV_RELEASE_VAL 1110
#define IDC_ENV_RELEASE_QUANT 1111
#define IDC_ENV_GAIN 1112
#define IDC_ENV_GAIN_VAL 1113
#define IDC_ENV_GAIN_QUANT 1114
#define IDC_ENV_RELEASE 1119
#define IDC_VCO_SINE 1150
#define IDC_VCO_TRISAW 1151
#define IDC_VCO_PULSE 1152
#define IDC_VCO_NOISE 1153
#define IDC_VCO_GATE 1154
#define IDC_VCO_TRANSPOSE 1160
#define IDC_VCO_TRANSPOSE_VAL 1161
#define IDC_VCO_TRANSPOSE_QUANT 1162
#define IDC_VCO_DETUNE 1163
#define IDC_VCO_DETUNE_VAL 1164
#define IDC_VCO_DETUNE_QUANT 1165
#define IDC_VCO_PHASE 1166
#define IDC_VCO_PHASE_VAL 1167
#define IDC_VCO_PHASE_QUANT 1168
#define IDC_VCO_COLOR 1169
#define IDC_VCO_COLOR_VAL 1170
#define IDC_VCO_COLOR_QUANT 1171
#define IDC_VCO_SHAPE 1172
#define IDC_VCO_SHAPE_VAL 1173
#define IDC_VCO_GAIN_VAL 1174
#define IDC_VCO_GAIN_QUANT 1175
#define IDC_VCO_LFO 1176
#define IDC_VCO_SHAPE_QUANT 1177
#define IDC_VCO_GAIN 1178
#define IDC_VCO_GATE1 1180
#define IDC_VCO_GATE2 1181
#define IDC_VCO_GATE3 1182
#define IDC_VCO_GATE4 1183
#define IDC_VCO_GATE5 1184
#define IDC_VCO_GATE6 1185
#define IDC_VCO_GATE7 1186
#define IDC_VCO_GATE8 1187
#define IDC_VCO_GATE9 1188
#define IDC_VCO_GATE10 1189
#define IDC_VCO_GATE11 1190
#define IDC_VCO_GATE12 1191
#define IDC_VCO_GATE13 1192
#define IDC_VCO_GATE14 1193
#define IDC_VCO_GATE15 1194
#define IDC_VCO_GATE16 1195
#define IDC_VCF_OFF 1200
#define IDC_VCF_LOW 1201
#define IDC_VCF_HIGH 1202
#define IDC_VCF_BAND 1203
#define IDC_VCF_NOTCH 1204
#define IDC_VCF_PEAK 1205
#define IDC_VCF_ALL 1206
#define IDC_VCF_FREQUENCY 1207
#define IDC_VCF_FREQUENCY_VAL 1208
#define IDC_VCF_FREQUENCY_QUANT 1209
#define IDC_VCF_RESONANCE 1210
#define IDC_VCF_RESONANCE_VAL 1211
#define IDC_VCF_RESONANCE_QUANT 1212
#define IDC_DST_DRIVE 1250
#define IDC_DST_DRIVE_VAL 1251
#define IDC_DST_DRIVE_QUANT 1252
#define IDC_DST_SNH 1253
#define IDC_DST_SNH_VAL 1254
#define IDC_DST_SNH_QUANT 1255
#define IDC_DLL_OFF 1300
#define IDC_DLL_DELAY 1301
#define IDC_DLL_REVERB 1302
#define IDC_DLL_PREGAIN 1303
#define IDC_DLL_PREGAIN_VAL 1304
#define IDC_DLL_PREGAIN_QUANT 1305
#define IDC_DLL_FEEDBACK 1306
#define IDC_DLL_FEEDBACK_VAL 1307
#define IDC_DLL_FEEDBACK_QUANT 1308
#define IDC_DLL_DRY 1309
#define IDC_DLL_DRY_VAL 1310
#define IDC_DLL_DRY_QUANT 1311
#define IDC_DLL_DAMP 1312
#define IDC_DLL_DAMP_VAL 1313
#define IDC_DLL_DAMP_QUANT 1314
#define IDC_DLL_DTIME 1315
#define IDC_DLL_DTIME_VAL 1316
#define IDC_DLL_NOSYNC 1317
#define IDC_DLL_BPMSYNC 1318
#define IDC_DLL_NOTESYNC 1319
#define IDC_DLL_LEFTREVERB 1320
#define IDC_DLL_FREQUENCY 1321
#define IDC_DLL_FREQUENCY_VAL 1322
#define IDC_DLL_DEPTH 1323
#define IDC_DLL_DEPTH_VAL 1324
#define IDC_FOP_POP 1351
#define IDC_FOP_ADDP 1352
#define IDC_FOP_MULP 1353
#define IDC_FOP_PUSH 1354
#define IDC_FOP_XCH 1355
#define IDC_FOP_ADD 1356
#define IDC_FOP_MUL 1357
#define IDC_FOP_ADDP2 1358
#define IDC_FOP_LOADNOTE 1359
#define IDC_FST_AMOUNT 1400
#define IDC_FST_AMOUNT_VAL 1401
#define IDC_FST_AMOUNT_QUANT 1402
#define IDC_FST_DESTINATION_INSTRUMENT 1403
#define IDC_FST_DESTINATION_UNIT 1404
#define IDC_FST_DESTINATION_SLOT 1405
#define IDC_PAN_PANNING 1450
#define IDC_PAN_PANNING_VAL 1451
#define IDC_PAN_PANNING_QUANT 1452
#define IDC_OUT_GAIN 1500
#define IDC_OUT_GAIN_VAL 1501
#define IDC_OUT_GAIN_QUANT 1502
#define IDC_OUT_AUXSEND 1503
#define IDC_OUT_AUXSEND_QUANT 1504
#define IDC_OUT_AUXSEND_VAL 1505
#define IDC_ACC_OUT 1550
#define IDC_ACC_AUX 1551
#define IDC_FLD_VALUE 1552
#define IDC_FLD_VALUE_VAL 1553
#define IDC_FLD_VALUE_QUANT 1554
#define IDC_ISTACK_UNIT1 1600
#define IDC_ISTACK_UP1 1601
#define IDC_ISTACK_DOWN1 1602
#define IDC_ISTACK_SIGNALCOUNT1 1603
#define IDC_ISTACK_SET1 1604
#define IDC_ISTACK_RESET1 1605
#define IDC_ISTACK_UNIT2 1606
#define IDC_ISTACK_UP2 1607
#define IDC_ISTACK_DOWN2 1608
#define IDC_ISTACK_SIGNALCOUNT2 1609
#define IDC_ISTACK_SET2 1610
#define IDC_ISTACK_RESET2 1611
#define IDC_ISTACK_UNIT3 1612
#define IDC_ISTACK_UP3 1613
#define IDC_ISTACK_DOWN3 1614
#define IDC_ISTACK_SIGNALCOUNT3 1615
#define IDC_ISTACK_SET3 1616
#define IDC_ISTACK_RESET3 1617
#define IDC_ISTACK_UNIT4 1618
#define IDC_ISTACK_UP4 1619
#define IDC_ISTACK_DOWN4 1620
#define IDC_ISTACK_SIGNALCOUNT4 1621
#define IDC_ISTACK_SET4 1622
#define IDC_ISTACK_RESET4 1623
#define IDC_ISTACK_UNIT5 1624
#define IDC_ISTACK_UP5 1625
#define IDC_ISTACK_DOWN5 1626
#define IDC_ISTACK_SIGNALCOUNT5 1627
#define IDC_ISTACK_SET5 1628
#define IDC_ISTACK_RESET5 1629
#define IDC_ISTACK_UNIT6 1630
#define IDC_ISTACK_UP6 1631
#define IDC_ISTACK_DOWN6 1632
#define IDC_ISTACK_SIGNALCOUNT6 1633
#define IDC_ISTACK_SET6 1634
#define IDC_ISTACK_RESET6 1635
#define IDC_ISTACK_UNIT7 1636
#define IDC_ISTACK_UP7 1637
#define IDC_ISTACK_DOWN7 1638
#define IDC_ISTACK_SIGNALCOUNT7 1639
#define IDC_ISTACK_SET7 1640
#define IDC_ISTACK_RESET7 1641
#define IDC_ISTACK_UNIT8 1642
#define IDC_ISTACK_UP8 1643
#define IDC_ISTACK_DOWN8 1644
#define IDC_ISTACK_SIGNALCOUNT8 1645
#define IDC_ISTACK_SET8 1646
#define IDC_ISTACK_RESET8 1647
#define IDC_ISTACK_UNIT9 1648
#define IDC_ISTACK_UP9 1649
#define IDC_ISTACK_DOWN9 1650
#define IDC_ISTACK_SIGNALCOUNT9 1651
#define IDC_ISTACK_SET9 1652
#define IDC_ISTACK_RESET9 1653
#define IDC_ISTACK_UNIT10 1654
#define IDC_ISTACK_UP10 1655
#define IDC_ISTACK_DOWN10 1656
#define IDC_ISTACK_SIGNALCOUNT10 1657
#define IDC_ISTACK_SET10 1658
#define IDC_ISTACK_RESET10 1659
#define IDC_ISTACK_UNIT11 1660
#define IDC_ISTACK_UP11 1661
#define IDC_ISTACK_DOWN11 1662
#define IDC_ISTACK_SIGNALCOUNT11 1663
#define IDC_ISTACK_SET11 1664
#define IDC_ISTACK_RESET11 1665
#define IDC_ISTACK_UNIT12 1666
#define IDC_ISTACK_UP12 1667
#define IDC_ISTACK_DOWN12 1668
#define IDC_ISTACK_SIGNALCOUNT12 1669
#define IDC_ISTACK_SET12 1670
#define IDC_ISTACK_RESET12 1671
#define IDC_ISTACK_UNIT13 1672
#define IDC_ISTACK_UP13 1673
#define IDC_ISTACK_DOWN13 1674
#define IDC_ISTACK_SIGNALCOUNT13 1675
#define IDC_ISTACK_SET13 1676
#define IDC_ISTACK_RESET13 1677
#define IDC_ISTACK_UNIT14 1678
#define IDC_ISTACK_UP14 1679
#define IDC_ISTACK_DOWN14 1680
#define IDC_ISTACK_SIGNALCOUNT14 1681
#define IDC_ISTACK_SET14 1682
#define IDC_ISTACK_RESET14 1683
#define IDC_ISTACK_UNIT15 1684
#define IDC_ISTACK_UP15 1685
#define IDC_ISTACK_DOWN15 1686
#define IDC_ISTACK_SIGNALCOUNT15 1687
#define IDC_ISTACK_SET15 1688
#define IDC_ISTACK_RESET15 1689
#define IDC_ISTACK_UNIT16 1690
#define IDC_ISTACK_UP16 1691
#define IDC_ISTACK_DOWN16 1692
#define IDC_ISTACK_SIGNALCOUNT16 1693
#define IDC_ISTACK_SET16 1694
#define IDC_ISTACK_RESET16 1695
#define IDC_ISTACK_UNIT17 1696
#define IDC_ISTACK_UP17 1697
#define IDC_ISTACK_DOWN17 1698
#define IDC_ISTACK_SIGNALCOUNT17 1699
#define IDC_ISTACK_SET17 1700
#define IDC_ISTACK_RESET17 1701
#define IDC_ISTACK_UNIT18 1702
#define IDC_ISTACK_UP18 1703
#define IDC_ISTACK_DOWN18 1704
#define IDC_ISTACK_SIGNALCOUNT18 1705
#define IDC_ISTACK_SET18 1706
#define IDC_ISTACK_RESET18 1707
#define IDC_ISTACK_UNIT19 1708
#define IDC_ISTACK_UP19 1709
#define IDC_ISTACK_DOWN19 1710
#define IDC_ISTACK_SIGNALCOUNT19 1711
#define IDC_ISTACK_SET19 1712
#define IDC_ISTACK_RESET19 1713
#define IDC_ISTACK_UNIT20 1714
#define IDC_ISTACK_UP20 1715
#define IDC_ISTACK_DOWN20 1716
#define IDC_ISTACK_SIGNALCOUNT20 1717
#define IDC_ISTACK_SET20 1718
#define IDC_ISTACK_RESET20 1719
#define IDC_ISTACK_UNIT21 1720
#define IDC_ISTACK_UP21 1721
#define IDC_ISTACK_DOWN21 1722
#define IDC_ISTACK_SIGNALCOUNT21 1723
#define IDC_ISTACK_SET21 1724
#define IDC_ISTACK_RESET21 1725
#define IDC_ISTACK_UNIT22 1726
#define IDC_ISTACK_UP22 1727
#define IDC_ISTACK_DOWN22 1728
#define IDC_ISTACK_SIGNALCOUNT22 1729
#define IDC_ISTACK_SET22 1730
#define IDC_ISTACK_RESET22 1731
#define IDC_ISTACK_UNIT23 1732
#define IDC_ISTACK_UP23 1733
#define IDC_ISTACK_DOWN23 1734
#define IDC_ISTACK_SIGNALCOUNT23 1735
#define IDC_ISTACK_SET23 1736
#define IDC_ISTACK_RESET23 1737
#define IDC_ISTACK_UNIT24 1738
#define IDC_ISTACK_UP24 1739
#define IDC_ISTACK_DOWN24 1740
#define IDC_ISTACK_SIGNALCOUNT24 1741
#define IDC_ISTACK_SET24 1742
#define IDC_ISTACK_RESET24 1743
#define IDC_ISTACK_UNIT25 1744
#define IDC_ISTACK_UP25 1745
#define IDC_ISTACK_DOWN25 1746
#define IDC_ISTACK_SIGNALCOUNT25 1747
#define IDC_ISTACK_SET25 1748
#define IDC_ISTACK_RESET25 1749
#define IDC_ISTACK_UNIT26 1750
#define IDC_ISTACK_UP26 1751
#define IDC_ISTACK_DOWN26 1752
#define IDC_ISTACK_SIGNALCOUNT26 1753
#define IDC_ISTACK_SET26 1754
#define IDC_ISTACK_RESET26 1755
#define IDC_ISTACK_UNIT27 1756
#define IDC_ISTACK_UP27 1757
#define IDC_ISTACK_DOWN27 1758
#define IDC_ISTACK_SIGNALCOUNT27 1759
#define IDC_ISTACK_SET27 1760
#define IDC_ISTACK_RESET27 1761
#define IDC_ISTACK_UNIT28 1762
#define IDC_ISTACK_UP28 1763
#define IDC_ISTACK_DOWN28 1764
#define IDC_ISTACK_SIGNALCOUNT28 1765
#define IDC_ISTACK_SET28 1766
#define IDC_ISTACK_RESET28 1767
#define IDC_ISTACK_UNIT29 1768
#define IDC_ISTACK_UP29 1769
#define IDC_ISTACK_DOWN29 1770
#define IDC_ISTACK_SIGNALCOUNT29 1771
#define IDC_ISTACK_SET29 1772
#define IDC_ISTACK_RESET29 1773
#define IDC_ISTACK_UNIT30 1774
#define IDC_ISTACK_UP30 1775
#define IDC_ISTACK_DOWN30 1776
#define IDC_ISTACK_SIGNALCOUNT30 1777
#define IDC_ISTACK_SET30 1778
#define IDC_ISTACK_RESET30 1779
#define IDC_ISTACK_UNIT31 1780
#define IDC_ISTACK_UP31 1781
#define IDC_ISTACK_DOWN31 1782
#define IDC_ISTACK_SIGNALCOUNT31 1783
#define IDC_ISTACK_SET31 1784
#define IDC_ISTACK_RESET31 1785
#define IDC_ISTACK_UNIT32 1786
#define IDC_ISTACK_UP32 1787
#define IDC_ISTACK_DOWN32 1788
#define IDC_ISTACK_SIGNALCOUNT32 1789
#define IDC_ISTACK_SET32 1790
#define IDC_ISTACK_RESET32 1791
#define IDC_GSTACK_UNIT1 3600
#define IDC_GSTACK_UP1 3601
#define IDC_GSTACK_DOWN1 3602
#define IDC_GSTACK_SIGNALCOUNT1 3603
#define IDC_GSTACK_SET1 3604
#define IDC_GSTACK_RESET1 3605
#define IDC_GSTACK_UNIT2 3606
#define IDC_GSTACK_UP2 3607
#define IDC_GSTACK_DOWN2 3608
#define IDC_GSTACK_SIGNALCOUNT2 3609
#define IDC_GSTACK_SET2 3610
#define IDC_GSTACK_RESET2 3611
#define IDC_GSTACK_UNIT3 3612
#define IDC_GSTACK_UP3 3613
#define IDC_GSTACK_DOWN3 3614
#define IDC_GSTACK_SIGNALCOUNT3 3615
#define IDC_GSTACK_SET3 3616
#define IDC_GSTACK_RESET3 3617
#define IDC_GSTACK_UNIT4 3618
#define IDC_GSTACK_UP4 3619
#define IDC_GSTACK_DOWN4 3620
#define IDC_GSTACK_SIGNALCOUNT4 3621
#define IDC_GSTACK_SET4 3622
#define IDC_GSTACK_RESET4 3623
#define IDC_GSTACK_UNIT5 3624
#define IDC_GSTACK_UP5 3625
#define IDC_GSTACK_DOWN5 3626
#define IDC_GSTACK_SIGNALCOUNT5 3627
#define IDC_GSTACK_SET5 3628
#define IDC_GSTACK_RESET5 3629
#define IDC_GSTACK_UNIT6 3630
#define IDC_GSTACK_UP6 3631
#define IDC_GSTACK_DOWN6 3632
#define IDC_GSTACK_SIGNALCOUNT6 3633
#define IDC_GSTACK_SET6 3634
#define IDC_GSTACK_RESET6 3635
#define IDC_GSTACK_UNIT7 3636
#define IDC_GSTACK_UP7 3637
#define IDC_GSTACK_DOWN7 3638
#define IDC_GSTACK_SIGNALCOUNT7 3639
#define IDC_GSTACK_SET7 3640
#define IDC_GSTACK_RESET7 3641
#define IDC_GSTACK_UNIT8 3642
#define IDC_GSTACK_UP8 3643
#define IDC_GSTACK_DOWN8 3644
#define IDC_GSTACK_SIGNALCOUNT8 3645
#define IDC_GSTACK_SET8 3646
#define IDC_GSTACK_RESET8 3647
#define IDC_GSTACK_UNIT9 3648
#define IDC_GSTACK_UP9 3649
#define IDC_GSTACK_DOWN9 3650
#define IDC_GSTACK_SIGNALCOUNT9 3651
#define IDC_GSTACK_SET9 3652
#define IDC_GSTACK_RESET9 3653
#define IDC_GSTACK_UNIT10 3654
#define IDC_GSTACK_UP10 3655
#define IDC_GSTACK_DOWN10 3656
#define IDC_GSTACK_SIGNALCOUNT10 3657
#define IDC_GSTACK_SET10 3658
#define IDC_GSTACK_RESET10 3659
#define IDC_GSTACK_UNIT11 3660
#define IDC_GSTACK_UP11 3661
#define IDC_GSTACK_DOWN11 3662
#define IDC_GSTACK_SIGNALCOUNT11 3663
#define IDC_GSTACK_SET11 3664
#define IDC_GSTACK_RESET11 3665
#define IDC_GSTACK_UNIT12 3666
#define IDC_GSTACK_UP12 3667
#define IDC_GSTACK_DOWN12 3668
#define IDC_GSTACK_SIGNALCOUNT12 3669
#define IDC_GSTACK_SET12 3670
#define IDC_GSTACK_RESET12 3671
#define IDC_GSTACK_UNIT13 3672
#define IDC_GSTACK_UP13 3673
#define IDC_GSTACK_DOWN13 3674
#define IDC_GSTACK_SIGNALCOUNT13 3675
#define IDC_GSTACK_SET13 3676
#define IDC_GSTACK_RESET13 3677
#define IDC_GSTACK_UNIT14 3678
#define IDC_GSTACK_UP14 3679
#define IDC_GSTACK_DOWN14 3680
#define IDC_GSTACK_SIGNALCOUNT14 3681
#define IDC_GSTACK_SET14 3682
#define IDC_GSTACK_RESET14 3683
#define IDC_GSTACK_UNIT15 3684
#define IDC_GSTACK_UP15 3685
#define IDC_GSTACK_DOWN15 3686
#define IDC_GSTACK_SIGNALCOUNT15 3687
#define IDC_GSTACK_SET15 3688
#define IDC_GSTACK_RESET15 3689
#define IDC_GSTACK_UNIT16 3690
#define IDC_GSTACK_UP16 3691
#define IDC_GSTACK_DOWN16 3692
#define IDC_GSTACK_SIGNALCOUNT16 3693
#define IDC_GSTACK_SET16 3694
#define IDC_GSTACK_RESET16 3695
#define IDC_GSTACK_UNIT17 3696
#define IDC_GSTACK_UP17 3697
#define IDC_GSTACK_DOWN17 3698
#define IDC_GSTACK_SIGNALCOUNT17 3699
#define IDC_GSTACK_SET17 3700
#define IDC_GSTACK_RESET17 3701
#define IDC_GSTACK_UNIT18 3702
#define IDC_GSTACK_UP18 3703
#define IDC_GSTACK_DOWN18 3704
#define IDC_GSTACK_SIGNALCOUNT18 3705
#define IDC_GSTACK_SET18 3706
#define IDC_GSTACK_RESET18 3707
#define IDC_GSTACK_UNIT19 3708
#define IDC_GSTACK_UP19 3709
#define IDC_GSTACK_DOWN19 3710
#define IDC_GSTACK_SIGNALCOUNT19 3711
#define IDC_GSTACK_SET19 3712
#define IDC_GSTACK_RESET19 3713
#define IDC_GSTACK_UNIT20 3714
#define IDC_GSTACK_UP20 3715
#define IDC_GSTACK_DOWN20 3716
#define IDC_GSTACK_SIGNALCOUNT20 3717
#define IDC_GSTACK_SET20 3718
#define IDC_GSTACK_RESET20 3719
#define IDC_GSTACK_UNIT21 3720
#define IDC_GSTACK_UP21 3721
#define IDC_GSTACK_DOWN21 3722
#define IDC_GSTACK_SIGNALCOUNT21 3723
#define IDC_GSTACK_SET21 3724
#define IDC_GSTACK_RESET21 3725
#define IDC_GSTACK_UNIT22 3726
#define IDC_GSTACK_UP22 3727
#define IDC_GSTACK_DOWN22 3728
#define IDC_GSTACK_SIGNALCOUNT22 3729
#define IDC_GSTACK_SET22 3730
#define IDC_GSTACK_RESET22 3731
#define IDC_GSTACK_UNIT23 3732
#define IDC_GSTACK_UP23 3733
#define IDC_GSTACK_DOWN23 3734
#define IDC_GSTACK_SIGNALCOUNT23 3735
#define IDC_GSTACK_SET23 3736
#define IDC_GSTACK_RESET23 3737
#define IDC_GSTACK_UNIT24 3738
#define IDC_GSTACK_UP24 3739
#define IDC_GSTACK_DOWN24 3740
#define IDC_GSTACK_SIGNALCOUNT24 3741
#define IDC_GSTACK_SET24 3742
#define IDC_GSTACK_RESET24 3743
#define IDC_GSTACK_UNIT25 3744
#define IDC_GSTACK_UP25 3745
#define IDC_GSTACK_DOWN25 3746
#define IDC_GSTACK_SIGNALCOUNT25 3747
#define IDC_GSTACK_SET25 3748
#define IDC_GSTACK_RESET25 3749
#define IDC_GSTACK_UNIT26 3750
#define IDC_GSTACK_UP26 3751
#define IDC_GSTACK_DOWN26 3752
#define IDC_GSTACK_SIGNALCOUNT26 3753
#define IDC_GSTACK_SET26 3754
#define IDC_GSTACK_RESET26 3755
#define IDC_GSTACK_UNIT27 3756
#define IDC_GSTACK_UP27 3757
#define IDC_GSTACK_DOWN27 3758
#define IDC_GSTACK_SIGNALCOUNT27 3759
#define IDC_GSTACK_SET27 3760
#define IDC_GSTACK_RESET27 3761
#define IDC_GSTACK_UNIT28 3762
#define IDC_GSTACK_UP28 3763
#define IDC_GSTACK_DOWN28 3764
#define IDC_GSTACK_SIGNALCOUNT28 3765
#define IDC_GSTACK_SET28 3766
#define IDC_GSTACK_RESET28 3767
#define IDC_GSTACK_UNIT29 3768
#define IDC_GSTACK_UP29 3769
#define IDC_GSTACK_DOWN29 3770
#define IDC_GSTACK_SIGNALCOUNT29 3771
#define IDC_GSTACK_SET29 3772
#define IDC_GSTACK_RESET29 3773
#define IDC_GSTACK_UNIT30 3774
#define IDC_GSTACK_UP30 3775
#define IDC_GSTACK_DOWN30 3776
#define IDC_GSTACK_SIGNALCOUNT30 3777
#define IDC_GSTACK_SET30 3778
#define IDC_GSTACK_RESET30 3779
#define IDC_GSTACK_UNIT31 3780
#define IDC_GSTACK_UP31 3781
#define IDC_GSTACK_DOWN31 3782
#define IDC_GSTACK_SIGNALCOUNT31 3783
#define IDC_GSTACK_SET31 3784
#define IDC_GSTACK_RESET31 3785
#define IDC_GSTACK_UNIT32 3786
#define IDC_GSTACK_UP32 3787
#define IDC_GSTACK_DOWN32 3788
#define IDC_GSTACK_SIGNALCOUNT32 3789
#define IDC_GSTACK_SET32 3790
#define IDC_GSTACK_RESET32 3791
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 124
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 5000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -1 +0,0 @@
cmd.exe

223
CHANGELOG.md Normal file
View File

@ -0,0 +1,223 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Added
- Include version info in the binaries, as given be `git describe`. This version
info is shown as a label in the tracker and can be checked with `-v` flag in
the command line tools.
### Fixed
- Crashes with sample-based oscillators in the 32-bit library, as the pointer to
sample-table (edi) got accidentally overwritten by detune
- Sample-based oscillators could hard crash if a x87 stack overflow happened
when calculating the current position in the sample ([#149][i149])
- Numeric updown widget calculated dp-to-px conversion incorrectly, resulting in
wrong scaling ([#150][i150])
- Empty patch should not crash the native synth ([#148][i148])
## [0.4.1]
### Added
- Clicking the parameter slider also selects that parameter ([#112][i112])
- The vertical and horizontal split bars indicate with a cursor that they can be
resized ([#145][i145])
### Fixed
- When adding a unit on the last row of the unit list, the editor for entering
the type of the unit by text did gain focus.
- When inputting a note to the note editor, advance the cursor by step
([#144][i144])
- When loading an instrument, make sure the total number of voices does not go
over the maximum number allowed by vm, and make sure a loaded instrument has
at least 1 voice
- Potential ID collisions when clearing unit or pasteing instruments
- Assign new IDs to loaded instruments, and fix ID collisions in case they
somehow still appear ([#146][i146])
- In x86 templates, do not optimize away phase modulations when unisons are used
even if all phase inputs are zeros, as unisons use the phase modulation
mechanism to offset the different oscillators
- Do not include delay times in the delay time table if the delay unit is
disabled ([#139][i139])
- Moved the error and warning popups slightly up so they don't block the unit
control buttons ([#142][i142])
### Changed
- Do not automatically wrap around the song when playing as it was usually
unwanted behaviour. There is already the looping mechanism if the user really
wants to loop the song forever.
## [0.4.0]
### Added
- User can drop preset instruments into `os.UserConfigDir()/sointu/presets/` and
they appear in the list of presets next time sointu is started.
([#125][i125])
- Ability to loop certain section of the song when playing. The loop can be set
by using the toggle button in the song panel, or by hitting Ctrl+L.
([#128][i128])
- Disable units temporarily. The disabled units are shown in gray and are not
compiled into the patch and are considered for all purposes non-existent.
Hitting Ctrl-D disables/re-enables the selected unit(s). The yaml file has
field `disabled: true` for the unit. ([#116][i116])
- Passing a file name on command line immediately tries loading that file ([#122][i122])
- Massive rewrite of the GUI, in particular allowing better copying, pasting and
scrolling of table-based data (order list and note data).
- Dbgain unit, which allows defining the gain in decibels (-40 dB to +40dB)
- `+` and `-` keys add/subtract values in order editor and pattern editor
([#65][i65])
- The function `su_power` is exported so people can reuse it in the main code;
however, as it assumes the parameter passed in st0 on the x87 stack and
similarly returns it value in st0 on the x87 stack, to my knowledge there is
no calling convention that would correspond this behaviour, so you need to
define a header for it yourself and take care of putting the float value on
x87 stack.
### Fixed
- Loading a preset did not update the IDs of the newly loaded instrument,
causing ID collisions and sends target wrong units.
- The x87 native filter unit was denormalizing and eating up a lot of CPU ([#68][i68])
- Modulating delaytime in wasm could crash, because delay time was converted to
int with i32.trunc_f32_u. Using i32.trunc_f32_s fixed this.
- When recording notes from VSTI, no track was created for instruments that had
no notes triggered, resulting in misalignment of the tracks from instruments.
- 32-bit su_load_gmdls clobbered ebx, even though __stdcall demands it to be not
touched ([#130][i130])
- Spaces are allowed in instrument names ([#120][i120])
- Fixed the dropdown for targeting sends making it impossible to choose certain
ops. This was done just by reducing the default height of popup menus so they
fit on screen ([#121][i121])
- Warn user about sample rate being other than 44100 Hz, as this lead to weird
behaviour. Sointu assumes the samplerate always to be 44100 Hz. ([#129][i129])
### Changed
- The scroll wheel behavior for unit integer parameters was flipped: scrolling
up now increases the value, while scrolling down decreases the value. It was
vice versa. ([#112][i112])
## [0.3.0]
### Added
- Scroll bars to menus, shown when a menu is too long to fit.
- Save the GUI state periodically to a recovery file and load it on
startup of the app, if present. The recovery files are located in the
app config directory (e.g. AppData/Roaming/Sointu on Windows).
- Save the VSTI GUI state to the DAW project file, through GetChunk /
SetChunk mechanisms.
- Instrument presets. The presets are embedded in the executable and
there's a button to open a menu to load one of the presets.
- Frequency modulation target for oscillator, as it was in 4klang
- Reverb preset settings for a delay unit, with stereo, left and right
options
### Fixed
- Crash when running more than one sointu VSTI plugins in parallel
- The scroll bars move in sync with the cursor.
- The stereo version of delay in the go virtual machine (executables / plugins
not ending with -native) applied the left delay taps on the right channel, and
the right delay taps on the left channel.
- The sointu-vsti-native plugin has different plugin ID and plugin name
to not confuse it with the non-native one
- The VSTI waits for the gioui actually have quit when closing the
plugin
### Changed
- BREAKING CHANGE: The meaning of default modulation mode ("auto") has
been changed for cross-instrument modulations: it now means "all"
voices, instead of first voice (which was redundant, as it was same as
defining voice = 0). This means that for cross-instrument modulations,
one "all vocies" send gets actually compiled into multiple sends, one
for each targeted voice. For intra-instrument modulations, the meaning
stays the same, but the label was changed to "self", to highlight that
this means the voice modulates only itself and not other voices.
## [0.2.0]
### Added
- Saving and loading instruments
- Comment field to instruments
- Ability to reorder tracks
- Add menu command to delete all unused data from song file
- Ability to search a unit by typing its name
- Ability to run sointu as a vsti plugin, inside vsti host
- Ability to lock delay relative to beat duration
- Ability to import 4klang patches (.4kp) and instruments (.4ki)
- The repository has example instruments, including all patches and
instruments from 4klang
- The compiler templates are embedded in the sointu-compile, so no
installation is needed beyond copying sointu-compile to PATH
- Ability to select multiple units and cut, copy & paste them
- Mousewheel adjusts unit parameters
- Tooltips to many buttons
- Support for gm.dls samples in the go-written virtual machine
- x86 and C written examples how to play a sointu song on various
platforms. On Windows, the examples can optionally be linked with
Crinkler to get Crinkler reports.
### Fixed
- Unnamed instruments with multiple voices caused crashes
- In the native version, exceeding the 64 delaylines caused crashes
- wat2wasm nowadays uses funcref instead of anyfunc
- In the WebAssembly core, $WRK was messed after stereo oscillators,
making modulations not work
- The Webassembly implementation of mono version of the "out" unit
### Changed
- The release flag in the voice is now a sustain flag i.e. the logic has
been inverted. This was done so that when the synth is initialized
with zeros, all voices start with sustain = 0 i.e. in released state.
- The crush resolution is now in bits instead of linear range; this is a
breaking change and changes the meaning of the resolution values. But
now there are more usable values in the resolution.
## [0.1.0]
### Added
- An instrument (set of opcodes & accompanying values) can have any
number of voices.
- A track can trigger any number of voices, releasing the previous when
new one is triggered.
- Pattern length does not have to be a power of 2.
- Only the necessary opcodes and functions of the synth are compiled in the final executable.
- Harmonized support for stereo signals: every opcode supports stereo
variant.
- New opcodes: crush, gain, inverse gain, clip, speed (bpm modulation),
compressor.
- Support for sample-based oscillators (samples loaded from gm.dls).
- Unison oscillators: multiple copies of the oscillator running with
different detuning and added up to together.
- Support for 32 and 64 bit builds.
- Support different platforms: Windows, Linux and Mac (Intel).
- Experimental support for compiling songs into WebAssembly.
- Switch to CMake for builds.
- Regression tests for every VM instruction, using CTests.
- Compiling as a static library & an API to call Sointu
- Running all tests (win/linux/mac/wasm) in the cloud, using Github
workflows
- Tools written in Go-lang:
- a tracker for composing songs as .yml
- a command line utility to convert .yml songs to .asm
- a command line utility to play the songs on command line
[Unreleased]: https://github.com/vsariola/sointu/compare/v0.4.1...HEAD
[0.4.1]: https://github.com/vsariola/sointu/compare/v0.4.0...v0.4.1
[0.4.0]: https://github.com/vsariola/sointu/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/vsariola/sointu/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/vsariola/sointu/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/vsariola/sointu/compare/4klang-3.11...v0.1.0
[i65]: https://github.com/vsariola/sointu/issues/65
[i68]: https://github.com/vsariola/sointu/issues/68
[i112]: https://github.com/vsariola/sointu/issues/112
[i116]: https://github.com/vsariola/sointu/issues/116
[i120]: https://github.com/vsariola/sointu/issues/120
[i121]: https://github.com/vsariola/sointu/issues/121
[i122]: https://github.com/vsariola/sointu/issues/122
[i125]: https://github.com/vsariola/sointu/issues/125
[i128]: https://github.com/vsariola/sointu/issues/128
[i129]: https://github.com/vsariola/sointu/issues/129
[i130]: https://github.com/vsariola/sointu/issues/130
[i139]: https://github.com/vsariola/sointu/issues/139
[i142]: https://github.com/vsariola/sointu/issues/142
[i144]: https://github.com/vsariola/sointu/issues/144
[i145]: https://github.com/vsariola/sointu/issues/145
[i146]: https://github.com/vsariola/sointu/issues/146
[i148]: https://github.com/vsariola/sointu/issues/148
[i149]: https://github.com/vsariola/sointu/issues/149
[i150]: https://github.com/vsariola/sointu/issues/150

118
CMakeLists.txt Normal file
View File

@ -0,0 +1,118 @@
cmake_minimum_required(VERSION 3.10)
# This policy is needed so that we can set the MSVC_RUNTIME to statically linked
# i.e. set_property(TARGET 4klang PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
cmake_policy(SET CMP0091 NEW)
project(sointu
VERSION 0.0.0
DESCRIPTION "A modular synthesizer for 4k/8k/64k intros"
LANGUAGES C CXX)
# Only do these if this is the main project, and not if it is included through add_subdirectory
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
# Let's ensure -std=c++xx instead of -std=g++xx
set(CMAKE_CXX_EXTENSIONS OFF)
# Let's nicely support folders in IDE's
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Testing only available if this is the main app
# Note this needs to be done in the main CMakeLists
# since it calls enable_testing, which must be in the
# main CMakeLists.
include(CTest)
endif()
IF(APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-no_pie")
# https://stackoverflow.com/questions/69803659/what-is-the-proper-way-to-build-for-macos-x86-64-using-cmake-on-apple-m1-arm
set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE INTERNAL "" FORCE)
endif()
find_program(GO NAMES go)
if(NOT GO)
message(FATAL_ERROR "go not found. Get it from: https://golang.org")
else()
message("go found at: ${GO}")
endif()
find_program(NODE NAMES node)
if(NOT NODE)
message( WARNING "node not found, cannot run WebAssembly tests. Get it from: https://nodejs.org/" )
else()
message("node found at: ${NODE}")
endif()
find_program(WAT2WASM NAMES wat2wasm)
if(NOT WAT2WASM )
message( WARNING "wat2wasm not found, cannot build wasm tests. Get it from: https://github.com/WebAssembly/wabt)" )
else()
message("wat2wasm found at: ${WAT2WASM}")
endif()
enable_language(ASM_NASM)
# The normal NASM compile object does not include <DEFINES>
# By putting them there, we can pass the same compile definitions to C and ASM
set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <DEFINES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
if(WIN32)
set(compilecmd ${CMAKE_CURRENT_BINARY_DIR}/sointu-compile.exe)
else()
set(compilecmd ${CMAKE_CURRENT_BINARY_DIR}/sointu-compile)
endif()
# the tests include the entire ASM but we still want to rebuild when they change
file(GLOB x86templates "${PROJECT_SOURCE_DIR}/vm/compiler/templates/amd64-386/*.asm")
file(GLOB wasmtemplates "${PROJECT_SOURCE_DIR}/vm/compiler/templates/wasm/*.wat")
file(GLOB sointusrc "${PROJECT_SOURCE_DIR}/*.go")
file(GLOB compilersrc "${PROJECT_SOURCE_DIR}/compiler/*.go")
file(GLOB compilecmdsrc "${PROJECT_SOURCE_DIR}/cmd/sointu-compile/*.go")
if(DEFINED CMAKE_C_SIZEOF_DATA_PTR AND CMAKE_C_SIZEOF_DATA_PTR EQUAL 8)
set(arch "amd64")
elseif(DEFINED CMAKE_CXX_SIZEOF_DATA_PTR AND CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8)
set(arch "amd64")
else()
set(arch "386")
endif()
# Sointu as static library
set(STATICLIB sointu)
set(sointuasm sointu.asm)
# Build sointu-cli only once because go run has everytime quite a bit of delay when
# starting
add_custom_command(
OUTPUT
"${compilecmd}"
COMMAND
${GO} build -o "${compilecmd}" ${PROJECT_SOURCE_DIR}/cmd/sointu-compile/main.go
DEPENDS ${x86templates} ${wasmtemplates} ${sointusrc} ${compilersrc} ${compilecmdsrc}
)
add_custom_target(
sointu-compiler
DEPENDS ${compilecmd}
)
add_custom_command(
OUTPUT ${sointuasm}
COMMAND ${compilecmd} -arch=${arch} -a -o ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${compilecmd}
)
add_library(${STATICLIB} ${sointuasm})
set_target_properties(${STATICLIB} PROPERTIES LINKER_LANGUAGE C)
target_include_directories(${STATICLIB} INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
# Examples are now available.
add_subdirectory(examples)
# Testing only available if this is the main app
# Emergency override 4KLANG_CMAKE_BUILD_TESTING provided as well
if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR SOINTU_CMAKE_BUILD_TESTING) AND BUILD_TESTING)
add_subdirectory(tests)
endif()

52
CMakeSettings.json Normal file
View File

@ -0,0 +1,52 @@
{
"configurations": [
{
"name": "x86-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x86" ],
"variables": []
},
{
"name": "x86-Release",
"generator": "Ninja",
"configurationType": "RelWithDebInfo",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x86" ],
"variables": []
},
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x64_x64" ],
"variables": []
},
{
"name": "x64-Release",
"generator": "Ninja",
"configurationType": "RelWithDebInfo",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x64_x64" ],
"variables": []
}
]
}

22
LICENSE Normal file
View File

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2018 Dominik Ries
(c) 2020 Veikko Sariola
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

542
README.md
View File

@ -1,2 +1,540 @@
# 4klang
Official 4klang repository
# Sointu
![Tests](https://github.com/vsariola/sointu/workflows/Tests/badge.svg)
![Binaries](https://github.com/vsariola/sointu/workflows/Binaries/badge.svg)
A cross-architecture and cross-platform modular software synthesizer for small
intros, forked from [4klang](https://github.com/hzdgopher/4klang). Targetable
architectures include 386, amd64, and WebAssembly; targetable platforms include
Windows, Mac, Linux (and related) + browser.
User manual will be in the [Wiki](https://github.com/vsariola/sointu/wiki).
Installation
------------
You can either 1) download the prebuilt release binaries from the
[releases](https://github.com/vsariola/sointu/releases); or 2) download the
latest build from the master branch from the
[actions](https://github.com/vsariola/sointu/actions) (find workflow "Binaries"
and scroll down for .zip files containing the artifacts). Then just run one of
the executables or, in the case of the VST plugins library files, copy them
wherever you keep you VST2 plugins.
The pre 1.0 version tags are mostly for reference: no backwards
compatibility will be guaranteed while upgrading to a newer version.
Backwards compatibility will be attempted from 1.0 onwards.
**Uninstallation**: Sointu stores recovery data in OS-specific folders
e.g. `AppData/Roaming/Sointu` on Windows. For clean uninstall, delete
also this folder. See [here](https://pkg.go.dev/os#UserConfigDir) where
to find those folders on other platforms.
Summary
-------
Sointu is work-in-progress. It is a fork and an evolution of
[4klang](https://github.com/hzdgopher/4klang), a modular software synthesizer
intended to easily produce music for 4k intros &mdash; small executables with a
maximum filesize of 4096 bytes containing realtime audio and visuals. Like
4klang, the sound is produced by a virtual machine that executes small bytecode
to produce the audio; however, by now the internal virtual machine has been
heavily rewritten and extended. It is actually extended so much that you will
never fit all the features at the same time in a 4k intro, but a fairly capable
synthesis engine can already be fitted in 600 bytes (386, compressed), with
another few hundred bytes for the patch and pattern data.
Sointu consists of two core elements:
- A cross-platform synth-tracker that runs as either VSTi or stand-alone
app for composing music, written in [go](https://golang.org/). The app
is still heavily work in progress. The app exports the projects as
.yml files.
- A compiler, likewise written in go, which can be invoked from the command line
to compile these .yml files into .asm or .wat code. For x86/amd64, the
resulting .asm can be then compiled by [nasm](https://www.nasm.us/). For
browsers, the resulting .wat can be compiled by
[wat2wasm](https://github.com/WebAssembly/wabt).
This is how the current prototype app looks like:
![Screenshot of the tracker](screenshot.png)
Building
--------
Various aspects of the project have different tool dependencies, which are
listed below.
### Sointu-track
This is the stand-alone version of the synth-tracker. Sointu-track uses
the [gioui](https://gioui.org/) for the GUI and [oto](https://github.com/hajimehoshi/oto)
for the audio, so the portability is currently limited by these.
#### Prerequisites
- [go](https://golang.org/)
- If you want to use the faster x86 assembly written synthesizer:
- Follow the instructions to build the [x86 native virtual machine](#native-virtual-machine)
before building the tracker.
- cgo compatible compiler e.g. [gcc](https://gcc.gnu.org/). On
windows, you best bet is [MinGW](http://www.mingw.org/). We use the [tdm-gcc](https://jmeubank.github.io/tdm-gcc/).
The compiler can be in PATH or you can use the environment variable
`CC` to help go find the compiler.
- Setting environment variable `CGO_ENABLED=1` is a good idea,
because if it is not set and go fails to find the compiler, go just
excludes all files with `import "C"` from the build, resulting in
lots of errors about missing types.
#### Running
```
go run cmd/sointu-track/main.go
```
#### Building an executable
```
go build -o sointu-track.exe cmd/sointu-track/main.go
```
On other platforms than Windows, replace `-o sointu-track.exe` with
`-o sointu-track`.
If you want to use the [x86 native virtual machine](#native-virtual-machine),
add `-tags=native` to all the commands e.g.
```
go build -o sointu-track.exe -tags=native cmd/sointu-track/main.go
```
### Sointu-vsti
This is the VST instrument plugin version of the tracker, compiled into
a dynamically linked library and ran inside a VST host.
#### Prerequisites
- [go](https://golang.org/)
- cgo compatible compiler e.g. [gcc](https://gcc.gnu.org/). On windows,
you best bet is [MinGW](http://www.mingw.org/). We use the [tdm-gcc](https://jmeubank.github.io/tdm-gcc/).
The compiler can be in PATH or you can use the environment variable
`CC` to help go find the compiler.
- Setting environment variable `CGO_ENABLED=1` is a good idea, because
if it is not set and go fails to find the compiler, go just excludes
all files with `import "C"` from the build, resulting in lots of
errors about missing types.
- If you want to use the faster x86 assembly written synthesizer:
- Follow the instructions to build the [x86 native virtual machine](#native-virtual-machine)
before building the plugin itself
#### Building
```
go build -buildmode=c-shared -tags=plugin -o sointu-vsti.dll .\cmd\sointu-vsti\
```
On other platforms than Windows, replace `-o sointu-vsti.dll` appropriately e.g.
`-o sointu-vsti.so`; so far, the VST instrument has been built & tested on
Windows and Linux.
Notice the `-tags=plugin` build tag definition. This is required by the [vst2
library](https://github.com/pipelined/vst2); otherwise, you will get a lot of
build errors.
Add `-tags=native,plugin` to use the [x86 native virtual
machine](#native-virtual-machine) instead of the virtual machine written in Go.
### Sointu-compile
The command line interface to it is [sointu-compile](cmd/sointu-compile/main.go)
and the actual code resides in the [compiler](vm/compiler/) package, which is an
ordinary [go](https://golang.org/) package with no other tool dependencies.
#### Running
```
go run cmd/sointu-compile/main.go
```
#### Building an executable
```
go build -o sointu-compile.exe cmd/sointu-compile/main.go
```
On other platforms than Windows, replace `-o sointu-compile.exe` with
`-o sointu-compile`.
#### Usage
The compiler can then be used to compile a .yml song into .asm and .h files. For
example:
```
sointu-compile -o . -arch=386 tests/test_chords.yml
nasm -f win32 test_chords.asm
```
WebAssembly example:
```
sointu-compile -o . -arch=wasm tests/test_chords.yml
wat2wasm --enable-bulk-memory test_chords.wat
```
If you are looking for an easy way to compile an executable from a Sointu song
(e.g. for a executable music compo), take a look at [NR4's Python-based
tool](https://github.com/LeStahL/sointu-executable-msx) for it.
#### Examples
The folder `examples/code` contains usage examples for Sointu with winmm and
dsound playback under Windows and asound playback under Unix. Source code is
available in C and x86 assembly (win32, elf32 and elf64 versions).
To build the examples, use `ninja examples`.
If you want to target smaller executable sizes, using a compressing linker like
[Crinkler](https://github.com/runestubbe/Crinkler) on Windows is recommended.
The linux examples use ALSA and need libasound2-dev (or libasound2-dev:386)
installed. The 386 version also needs pipewire-alsa:386 installed, which is not
there by default.
### Native virtual machine
The native bridge allows Go to call the sointu compiled x86 native virtual
machine, through cgo, instead of using the Go written bytecode interpreter. It's
likely slightly faster than the interpreter. Before you can actually run it, you
need to build the bridge using CMake (thus, ***this will not work with go
get***).
#### Prerequisites
- [CMake](https://cmake.org)
- [nasm](https://www.nasm.us/)
- *cgo compatible compiler* e.g. [gcc](https://gcc.gnu.org/). On windows, you
best bet is [MinGW](http://www.mingw.org/). We use the
[tdm-gcc](https://jmeubank.github.io/tdm-gcc/)
The last point is because the command line player and the tracker use
[cgo](https://golang.org/cmd/cgo/) to interface with the synth core, which is
compiled into a library. The cgo bridge resides in the package
[bridge](vm/compiler/bridge/).
#### Building
Assuming you are using [ninja](https://ninja-build.org/):
```
mkdir build
cd build
cmake .. -GNinja
ninja sointu
```
> :warning: *you must build the library inside a directory called 'build' at the
> root of the project*. This is because the path where cgo looks for the library
> is hard coded to point to build/ in the go files.
Running `ninja sointu` only builds the static library that Go needs. This is a
lot faster than building all the CTests.
You and now run all the Go tests, even the ones that test the native bridge.
From the project root folder, run:
```
go test ./...
```
Play a song from the command line:
```
go run -tags=native cmd/sointu-play/main.go tests/test_chords.yml
```
> :warning: Unlike the x86/amd64 VM compiled by Sointu, the Go written VM
> bytecode interpreter uses a software stack. Thus, unlike x87 FPU stack, it is
> not limited to 8 items. If you intent to compile the patch to x86/amd64
> targets, make sure not to use too much stack. Keeping at most 5 signals in the
> stack is presumably fine (reserving 3 for the temporary variables of the
> opcodes). In future, the app should give warnings if the user is about to
> exceed the capabilities of a target platform.
> :warning: **If you are using Yasm instead of Nasm, and you are using MinGW**:
> Yasm 1.3.0 (currently still the latest stable release) and GNU linker do not
> play nicely along, trashing the BSS layout. The linker had placed our synth
> object overlapping with DLL call addresses; very funny stuff to debug. See
> [here](https://tortall.lighthouseapp.com/projects/78676/tickets/274-bss-problem-with-windows-win64)
> and the fix
> [here](https://github.com/yasm/yasm/commit/1910e914792399137dec0b047c59965207245df5).
> Since Nasm is nowadays under BSD license, there is absolutely no reason to use
> Yasm. However, if you do, use a newer nightly build of Yasm that includes the
> fix.
### Tests
There are [regression tests](tests/) that are built as executables,
testing that they work the same way when you would link them in an
intro.
#### Prerequisites
- [go](https://golang.org/)
- [CMake](https://cmake.org) with CTest
- [nasm](https://www.nasm.us/)
- Your favorite CMake compatible c-compiler & build tool. Results have been
obtained using Visual Studio 2019, gcc&make on linux, MinGW&mingw32-make, and
ninja&AppleClang.
#### Building and running
Assuming you are using [ninja](https://ninja-build.org/):
```
mkdir build
cd build
cmake .. -GNinja
ninja
ninja test
```
Note that this builds 64-bit binaries on 64-bit Windows. To build 32-bit
binaries on 64-bit Windows, replace in above:
```
cmake .. -DCMAKE_C_FLAGS="-m32" -DCMAKE_ASM_NASM_OBJECT_FORMAT="win32" -GNinja
```
Another example: on Visual Studio 2019 Community, just open the folder, choose
either Debug or Release and either x86 or x64 build, and hit build all.
### WebAssembly tests
These are automatically invoked by CTest if [node](https://nodejs.org) and
[wat2wasm](https://github.com/WebAssembly/wabt) are found in the path.
New features since fork
-----------------------
- **New units**. For example: bit-crusher, gain, inverse gain, clip, modulate
bpm (proper triplets!), compressor (can be used for side-chaining).
- **Compiler**. Written in go. The input is a .yml file and the output is an
.asm. It works by inputting the song data to the excellent go
`text/template` package, effectively working as a preprocessor. This allows
quite powerful combination: we can handcraft the assembly code to keep the
entropy as low as possible, yet we can call arbitrary go functions as
"macros". The templates are [here](templates/) and the compiler lives
[here](vm/compiler/).
- **Tracker**. Written in go. Can run either as a stand-alone app or a vsti
plugin.
- **Supports 32 and 64 bit builds**. The 64-bit version is done with minimal
changes to get it work, using template macros to change the lines between
32-bit and 64-bit modes. Mostly, it's as easy as writing {{.AX}} instead of
eax; the macro {{.AX}} compiles to eax in 32-bit and rax in 64-bit.
- **Supports compiling into WebAssembly**. This is a complete reimplementation
of the core, written in WebAssembly text format (.wat).
- **Supports Windows, Linux and MacOS**. On all three 64-bit platforms, all
tests are passing. Additionally, all tests are passing on windows 32.
- **Per instrument polyphonism**. An instrument has the possibility to have
any number of voices, meaning that multiple voices can reuse the same
opcodes. So, you can have a single instrument with three voices, and three
tracks that use this instrument, to make chords. See
[here](tests/test_chords.yml) for an example and
[here](templates/amd64-386/patch.asm) for the implementation. The maximum
total number of voices is 32: you can have 32 monophonic instruments or any
combination of polyphonic instruments adding up to 32.
- **Any number of voices per track**. A single track can trigger more than one
voice. At every note, a new voice from the assigned voices is triggered and
the previous released. Combined with the previous, you can have a single
track trigger 3 voices and all these three voices use the same instrument,
useful to do polyphonic arpeggios (see [here](tests/test_polyphony.yml)).
Not only that, a track can even trigger voices of different instruments,
alternating between these two; maybe useful for example as an easy way to
alternate between an open and a closed hihat.
- **Easily extensible**. Instead of %ifdef hell, the primary extension
mechanism is through new opcodes for the virtual machine. Only the opcodes
actually used in a song are compiled into the virtual machine. The goal is
to try to write the code so that if two similar opcodes are used, the common
code in both is reused by moving it to a function. Macro and linker magic
ensure that also helper functions are only compiled in if they are actually
used.
- **Songs are YAML files**. These markup files are simple data files,
describing the tracks, patterns and patch structure (see
[here](tests/test_oscillat_trisaw.yml) for an example). The sointu-compile
then reads these files and compiles them into .asm code. This has the nice
implication that, in future, there will be no need for a binary format to
save patches, nor should you need to commit .o or .asm to repo: just put the
.yml in the repo and automate the .yml -> .asm -> .o steps using
sointu-compile & nasm.
- **Harmonized support for stereo signals**. Every opcode supports a stereo
variant: the stereo bit is hidden in the least significant bit of the
command stream and passed in carry to the opcode. This has several nice
advantages: 1) the opcodes that don't need any parameters do not need an
entire byte in the value stream to define whether it is stereo; 2) stereo
variants of opcodes can be implemented rather efficiently; in some cases,
the extra cost of stereo variant is only 5 bytes (uncompressed). 3) Since
stereo opcodes usually follow stereo opcodes (and mono opcodes follow mono
opcodes), the stereo bits of the command bytes will be highly correlated and
if crinkler or any other modeling compressor is doing its job, that should
make them highly predictable i.e. highly compressable.
- **Test-driven development**. Given that 4klang was already a mature project,
the first thing actually implemented was a set of regression tests to avoid
breaking everything beyond any hope of repair. Done, using go test (runs the
.yml regression tests through the library) and CTest (compiles each .yml
into executable and ensures that when run like this, the test case produces
identical output). The tests are also ran in the cloud using github actions.
- **Arbitrary signal routing**. SEND (used to be called FST in 4klang) opcode
normally sends the signal as a modulation to another opcode. But with the
new RECEIVE opcode, you just receive the plain signal there. So you can
connect signals in an arbitrary way. Actually, 4klang could already do this
but in a very awkward way: it had FLD (load value) opcode that could be
modulated; FLD 0 with modulation basically achieved what RECEIVE does,
except that RECEIVE can also handle stereo signals. Additionally, we have
OUTAUX, AUX and IN opcodes, which route the signals through global main or
aux ports, more closer to how 4klang does. But this time we have 8 mono
ports / 4 stereo ports, so even this method of routing is unlikely to run
out of ports in small intros.
- **Pattern length does not have to be a power of 2**.
- **Sample-based oscillators, with samples imported from gm.dls**. The
gm.dls is available from system folder only on Windows, but the
non-native tracker looks for it also in the current folder, so
should you somehow magically get hold of gm.dls on Linux or Mac, you
can drop it in the same folder with the tracker. See [this example](tests/test_oscillat_sample.yml),
and this go generate [program](cmd/sointu-generate/main.go) parses
the gm.dls file and dumps the sample offsets from it.
- **Unison oscillators**. Multiple copies of the oscillator running slightly
detuned and added up to together. Great for trance leads (supersaw). Unison
of up to 4, or 8 if you make stereo unison oscillator and add up both left
and right channels. See [this example](tests/test_oscillat_unison.yml).
- **Compiling as a library**. The API is very rudimentary, a single function
render, and between calls, the user is responsible for manipulating the
synth state in a similar way as the actual player does (e.g. triggering/
releasing voices etc.)
- **Calling Sointu as a library from Go language**. The Go API is slighty more
sane than the low-level library API, offering more Go-like experience.
- **A bytecode interpreter written in pure go**. It's slightly slower than the
hand-written assembly code by sointu compiler, but with this, the tracker is
ultraportable and does not need cgo calls.
Future goals
------------
- **Find a more general solution for skipping opcodes / early outs**. It might
be a new opcode "skip" that skips from the opcode to the next out in case
the signal entering skip and the signal leaving out are both close to zero.
Need to investigate the best way to implement this.
- **Even more opcodes**. Some potentially useful additions could be:
- Equalizer / more flexible filters
- Very slow filters (~ DC-offset removal). Can be implemented using a single
bit flag in the existing filter
- Arbitrary envelopes; for easier automation.
- **MIDI support for the tracker**.
- **Find a solution for denormalized signals**. Denormalized floating point
numbers (floating point numbers that are very very small) can result in 100x
CPU slow down. We got hit by this already: the damp filters in delay units
were denormalizing, resulting in the synth being unusable in real time. Need
to investigate a) where denormalization can happen; b) how to prevent it:
add & substract value; c) make this optional to the user. For quick
explanation about the potential massive CPU hit, see
https://stackoverflow.com/questions/36781881/why-denormalized-floats-are-so-much-slower-than-other-floats-from-hardware-arch
Long-shot ideas
-----------
- **Hack deeper into audio sources from the OS**. Speech synthesis, I'm eyeing
at you.
Design philosophy
-----------------
- Make sure the assembly code is readable after compiling: it should have
liberally comments *in the outputted .asm file*. This allows humans to study
the outputted code and figure out more easily if there's still way to
squeeze out instructions from the code.
- Instead of prematurely adding %ifdef toggles to optimize away unused
features, start with the most advanced featureset and see if you can
implement it in a generalized way. For example, all the modulations are now
added into the values when they are converted from integers, in a
standardized way. This got rid of most of the %ifdefs in 4klang. Also, with
no %ifdefs cluttering the view, many opportunities to shave away
instructions became apparent. Also, by making the most advanced synth
cheaply available to the scene, we promote better music in future 4ks :)
- Size first, speed second. Speed will only considered if the situation
becomes untolerable.
- Benchmark optimizations. Compression results are sometimes slightly
nonintuitive so alternative implementations should always be benchmarked
e.g. by compiling and linking a real-world song with
[Leviathan](https://github.com/armak/Leviathan-2.0) and observing how the
optimizations affect the byte size.
Background and history
----------------------
[4klang](https://github.com/hzdgopher/4klang) development was started in 2007 by
Dominik Ries (gopher) and Paul Kraus (pOWL) of Alcatraz. The
[write-up](http://zine.bitfellas.org/article.php?zine=14&id=35) will still be
helpful for anyone looking to understand how 4klang and Sointu use the FPU stack
to manipulate the signals. Since then, 4klang has been used in countless of
scene productions and people use it even today.
However, 4klang seems not to be actively developed anymore and polyphonism was
implemented only in a rather limited way (you could have exactly 2 voices per
instrument if you enable it). Also, reading through the code, I spotted several
avenues to squeeze away more bytes. These observations triggered project Sointu.
That, and I just wanted to learn x86 assembly, and needed a real-world project
to work on.
What's with the name
--------------------
"Sointu" means a chord, in Finnish; a reference to the polyphonic capabilities
of the synth. I assume we have all learned by now what "klang" means in German,
so I thought it would fun to learn some Finnish for a change. And
[there's](https://www.pouet.net/prod.php?which=53398)
[enough](https://www.pouet.net/prod.php?which=75814)
[klangs](https://www.pouet.net/prod.php?which=85351) already.
Prods using Sointu
------------------
- [Adam](https://github.com/vsariola/adam) by brainlez Coders! My first
test-driving of Sointu. The repository has some ideas how to integrate
Sointu to the build chain.
- [Roadtrip](https://www.pouet.net/prod.php?which=94105) by LJ & Virgill
- [|](https://www.pouet.net/prod.php?which=94721) by epoqe. Likely the first
Linux 4k intro using sointu.
- [Physics Girl St.](https://www.pouet.net/prod.php?which=94890) by Team210
- [Delusions of mediocrity](https://www.pouet.net/prod.php?which=95222) by
mrange & Virgill
- [Xorverse](https://www.pouet.net/prod.php?which=95221) by Alcatraz
- [l'enveloppe](https://www.pouet.net/prod.php?which=95215) by Team210 & epoqe
- [Phosphorescent Purple Pixel Peaks](https://www.pouet.net/prod.php?which=96198) by mrange & Virgill
- [21](https://demozoo.org/music/338597/) by NR4 / Team210
- [Tausendeins](https://www.pouet.net/prod.php?which=96192) by epoqe & Team210
Contributing
------------
Pull requests / suggestions / issues welcome, through Github! Or just DM
me on Discord (see contact information below).
License
-------
Distributed under the MIT License. See [LICENSE](LICENSE) for more information.
Contact
-------
Veikko Sariola - pestis_bc on Demoscene discord - firstname.lastname@gmail.com
Project Link: [https://github.com/vsariola/sointu](https://github.com/vsariola/sointu)
Credits
-------
The original 4klang: Dominik Ries ([gopher/Alcatraz](https://github.com/hzdgopher/4klang))
& Paul Kraus (pOWL/Alcatraz) :heart:
Sointu: Veikko Sariola (pestis/bC!), [Apollo/bC!](https://github.com/moitias),
[NR4/Team210](https://github.com/LeStahL/), [PoroCYon](https://github.com/PoroCYon/4klang),
[kendfss](https://github.com/kendfss), [anticore](https://github.com/anticore)

250
audio.go Normal file
View File

@ -0,0 +1,250 @@
package sointu
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"math"
)
type (
// AudioBuffer is a buffer of stereo audio samples of variable length, each
// sample represented by [2]float32. [0] is left channel, [1] is right
AudioBuffer [][2]float32
// AudioOutput represents something where we can send audio e.g. audio output.
// WriteAudio should block if not ready to accept audio e.g. buffer full.
AudioOutput interface {
WriteAudio(buffer AudioBuffer) error
Close() error
}
// AudioContext represents the low-level audio drivers. There should be at most
// one AudioContext at a time. The interface is implemented at least by
// oto.OtoContext, but in future we could also mock it.
//
// AudioContext is used to create one or more AudioOutputs with Output(); each
// can be used to output separate sound & closed when done.
AudioContext interface {
Output() AudioOutput
Close() error
}
// Synth represents a state of a synthesizer, compiled from a Patch.
Synth interface {
// Render tries to fill a stereo signal buffer with sound from the
// synthesizer, until either the buffer is full or a given number of
// timesteps is advanced. Normally, 1 sample = 1 unit of time, but speed
// modulations may change this. It returns the number of samples filled (in
// stereo samples i.e. number of elements of AudioBuffer filled), the
// number of sync outputs written, the number of time steps time advanced,
// and a possible error.
Render(buffer AudioBuffer, maxtime int) (sample int, time int, err error)
// Update recompiles a patch, but should maintain as much as possible of its
// state as reasonable. For example, filters should keep their state and
// delaylines should keep their content. Every change in the Patch triggers
// an Update and if the Patch would be started fresh every time, it would
// lead to very choppy audio.
Update(patch Patch, bpm int) error
// Trigger triggers a note for a given voice. Called between synth.Renders.
Trigger(voice int, note byte)
// Release releases the currently playing note for a given voice. Called
// between synth.Renders.
Release(voice int)
}
// Synther compiles a given Patch into a Synth, throwing errors if the
// Patch is malformed.
Synther interface {
Synth(patch Patch, bpm int) (Synth, error)
}
)
// Play plays the Song by first compiling the patch with the given Synther,
// returning the stereo audio buffer as a result (and possible errors).
func Play(synther Synther, song Song, progress func(float32)) (AudioBuffer, error) {
err := song.Validate()
if err != nil {
return nil, err
}
synth, err := synther.Synth(song.Patch, song.BPM)
if err != nil {
return nil, fmt.Errorf("sointu.Play failed: %v", err)
}
curVoices := make([]int, len(song.Score.Tracks))
for i := range curVoices {
curVoices[i] = song.Score.FirstVoiceForTrack(i)
}
initialCapacity := song.Score.LengthInRows() * song.SamplesPerRow()
buffer := make(AudioBuffer, 0, initialCapacity)
rowbuffer := make(AudioBuffer, song.SamplesPerRow())
for row := 0; row < song.Score.LengthInRows(); row++ {
patternRow := row % song.Score.RowsPerPattern
pattern := row / song.Score.RowsPerPattern
for t := range song.Score.Tracks {
order := song.Score.Tracks[t].Order
if pattern < 0 || pattern >= len(order) {
continue
}
patternIndex := song.Score.Tracks[t].Order[pattern]
patterns := song.Score.Tracks[t].Patterns
if patternIndex < 0 || int(patternIndex) >= len(patterns) {
continue
}
pattern := patterns[patternIndex]
if patternRow < 0 || patternRow >= len(pattern) {
continue
}
note := pattern[patternRow]
if note > 0 && note <= 1 { // anything but hold causes an action.
continue
}
synth.Release(curVoices[t])
if note > 1 {
curVoices[t]++
first := song.Score.FirstVoiceForTrack(t)
if curVoices[t] >= first+song.Score.Tracks[t].NumVoices {
curVoices[t] = first
}
synth.Trigger(curVoices[t], note)
}
}
tries := 0
for rowtime := 0; rowtime < song.SamplesPerRow(); {
samples, time, err := synth.Render(rowbuffer, song.SamplesPerRow()-rowtime)
if err != nil {
return buffer, fmt.Errorf("render failed: %v", err)
}
rowtime += time
buffer = append(buffer, rowbuffer[:samples]...)
if tries > 100 {
return nil, fmt.Errorf("Song speed modulation likely so slow that row never advances; error at pattern %v, row %v", pattern, patternRow)
}
}
if progress != nil {
progress(float32(row+1) / float32(song.Score.LengthInRows()))
}
}
return buffer, nil
}
// Fill fills the AudioBuffer using a Synth, disregarding all syncs and time
// limits. Note that this will change the state of the Synth.
func (buffer AudioBuffer) Fill(synth Synth) error {
s, _, err := synth.Render(buffer, math.MaxInt32)
if err != nil {
return fmt.Errorf("synth.Render failed: %v", err)
}
if s != len(buffer) {
return errors.New("in AudioBuffer.Fill, synth.Render should have filled the whole buffer but did not")
}
return nil
}
// Wav converts an AudioBuffer into a valid WAV-file, returned as a []byte
// array.
//
// If pcm16 is set to true, the samples in the WAV-file will be 16-bit signed
// integers; otherwise the samples will be 32-bit floats
func (buffer AudioBuffer) Wav(pcm16 bool) ([]byte, error) {
buf := new(bytes.Buffer)
wavHeader(len(buffer)*2, pcm16, buf)
err := buffer.rawToBuffer(pcm16, buf)
if err != nil {
return nil, fmt.Errorf("Wav failed: %v", err)
}
return buf.Bytes(), nil
}
// Raw converts an AudioBuffer into a raw audio file, returned as a []byte
// array.
//
// If pcm16 is set to true, the samples will be 16-bit signed integers;
// otherwise the samples will be 32-bit floats
func (buffer AudioBuffer) Raw(pcm16 bool) ([]byte, error) {
buf := new(bytes.Buffer)
err := buffer.rawToBuffer(pcm16, buf)
if err != nil {
return nil, fmt.Errorf("Raw failed: %v", err)
}
return buf.Bytes(), nil
}
func (data AudioBuffer) rawToBuffer(pcm16 bool, buf *bytes.Buffer) error {
var err error
if pcm16 {
int16data := make([][2]int16, len(data))
for i, v := range data {
int16data[i][0] = int16(clamp(int(v[0]*math.MaxInt16), math.MinInt16, math.MaxInt16))
int16data[i][1] = int16(clamp(int(v[1]*math.MaxInt16), math.MinInt16, math.MaxInt16))
}
err = binary.Write(buf, binary.LittleEndian, int16data)
} else {
err = binary.Write(buf, binary.LittleEndian, data)
}
if err != nil {
return fmt.Errorf("could not binary write data to binary buffer: %v", err)
}
return nil
}
// wavHeader writes a wave header for either float32 or int16 .wav file into the
// bytes.buffer. It needs to know the length of the buffer and assumes stereo
// sound, so the length in stereo samples (L + R) is bufferlength / 2. If pcm16
// = true, then the header is for int16 audio; pcm16 = false means the header is
// for float32 audio. Assumes 44100 Hz sample rate.
func wavHeader(bufferLength int, pcm16 bool, buf *bytes.Buffer) {
// Refer to: http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
numChannels := 2
sampleRate := 44100
var bytesPerSample, chunkSize, fmtChunkSize, waveFormat int
var factChunk bool
if pcm16 {
bytesPerSample = 2
chunkSize = 36 + bytesPerSample*bufferLength
fmtChunkSize = 16
waveFormat = 1 // PCM
factChunk = false
} else {
bytesPerSample = 4
chunkSize = 50 + bytesPerSample*bufferLength
fmtChunkSize = 18
waveFormat = 3 // IEEE float
factChunk = true
}
buf.Write([]byte("RIFF"))
binary.Write(buf, binary.LittleEndian, uint32(chunkSize))
buf.Write([]byte("WAVE"))
buf.Write([]byte("fmt "))
binary.Write(buf, binary.LittleEndian, uint32(fmtChunkSize))
binary.Write(buf, binary.LittleEndian, uint16(waveFormat))
binary.Write(buf, binary.LittleEndian, uint16(numChannels))
binary.Write(buf, binary.LittleEndian, uint32(sampleRate))
binary.Write(buf, binary.LittleEndian, uint32(sampleRate*numChannels*bytesPerSample)) // avgBytesPerSec
binary.Write(buf, binary.LittleEndian, uint16(numChannels*bytesPerSample)) // blockAlign
binary.Write(buf, binary.LittleEndian, uint16(8*bytesPerSample)) // bits per sample
if fmtChunkSize > 16 {
binary.Write(buf, binary.LittleEndian, uint16(0)) // size of extension
}
if factChunk {
buf.Write([]byte("fact"))
binary.Write(buf, binary.LittleEndian, uint32(4)) // fact chunk size
binary.Write(buf, binary.LittleEndian, uint32(bufferLength)) // sample length
}
buf.Write([]byte("data"))
binary.Write(buf, binary.LittleEndian, uint32(bytesPerSample*bufferLength))
}
func clamp(value, min, max int) int {
if value < min {
return min
}
if value > max {
return max
}
return value
}

View File

@ -0,0 +1,7 @@
//go:build native
package cmd
import "github.com/vsariola/sointu/vm/compiler/bridge"
var MainSynther = bridge.NativeSynther{}

View File

@ -0,0 +1,7 @@
//go:build !native
package cmd
import "github.com/vsariola/sointu/vm"
var MainSynther = vm.GoSynther{}

233
cmd/sointu-compile/main.go Normal file
View File

@ -0,0 +1,233 @@
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
"gopkg.in/yaml.v3"
"github.com/vsariola/sointu"
"github.com/vsariola/sointu/version"
"github.com/vsariola/sointu/vm/compiler"
)
func filterExtensions(input map[string]string, extensions []string) map[string]string {
ret := map[string]string{}
for _, ext := range extensions {
extWithDot := "." + ext
if inputVal, ok := input[extWithDot]; ok {
ret[extWithDot] = inputVal
}
}
return ret
}
func main() {
safe := flag.Bool("n", false, "Never overwrite files; if file already exists and would be overwritten, give an error.")
list := flag.Bool("l", false, "Do not write files; just list files that would change instead.")
stdout := flag.Bool("s", false, "Do not write files; write to standard output instead.")
help := flag.Bool("h", false, "Show help.")
rowsync := flag.Bool("r", false, "Write the current fractional row as sync #0")
library := flag.Bool("a", false, "Compile Sointu into a library. Input files are not needed.")
jsonOut := flag.Bool("j", false, "Output the song as .json file instead of compiling.")
yamlOut := flag.Bool("y", false, "Output the song as .yml file instead of compiling.")
tmplDir := flag.String("t", "", "When compiling, use the templates in this directory instead of the standard templates.")
outPath := flag.String("o", "", "Directory or filename where to write compiled code. Extension is ignored. Directory and its parents are created if needed. By default, everything is placed in the same directory where the original song file is.")
extensionsOut := flag.String("e", "", "Output only the compiled files with these comma separated extensions. For example: h,asm")
targetArch := flag.String("arch", runtime.GOARCH, "Target architecture. Defaults to OS architecture. Possible values: 386, amd64, wasm")
output16bit := flag.Bool("i", false, "Compiled song should output 16-bit integers, instead of floats.")
targetOs := flag.String("os", runtime.GOOS, "Target OS. Defaults to current OS. Possible values: windows, darwin, linux. Anything else is assumed linuxy. Ignored when targeting wasm.")
versionFlag := flag.Bool("v", false, "Print version.")
flag.Usage = printUsage
flag.Parse()
if *versionFlag {
fmt.Println(version.VersionOrHash)
os.Exit(0)
}
if (flag.NArg() == 0 && !*library) || *help {
flag.Usage()
os.Exit(0)
}
compile := !*jsonOut && !*yamlOut // if the user gives nothing to output, then the default behaviour is to compile the file
var comp *compiler.Compiler
if compile || *library {
var err error
if *tmplDir != "" {
comp, err = compiler.NewFromTemplates(*targetOs, *targetArch, *output16bit, *rowsync, *tmplDir)
} else {
comp, err = compiler.New(*targetOs, *targetArch, *output16bit, *rowsync)
}
if err != nil {
fmt.Fprintf(os.Stderr, `error creating compiler: %v`, err)
os.Exit(1)
}
}
output := func(filename string, extension string, contents []byte) error {
if *stdout {
fmt.Print(string(contents))
return nil
}
_, name := filepath.Split(filename)
var dir string
if *outPath != "" {
// check if it's an already existing directory and the user just forgot trailing slash
if info, err := os.Stat(*outPath); err == nil && info.IsDir() {
dir = *outPath
} else {
outdir, outname := filepath.Split(*outPath)
if outdir != "" {
dir = outdir
}
if outname != "" {
name = outname
}
}
}
if dir == "" {
var err error
dir, err = os.Getwd()
if err != nil {
return fmt.Errorf("could not get working directory, specify the output directory explicitly: %v", err)
}
}
name = strings.TrimSuffix(name, filepath.Ext(name)) + extension
f := filepath.Join(dir, name)
original, err := ioutil.ReadFile(f)
if err == nil {
if bytes.Compare(original, contents) == 0 {
return nil // no need to update
}
if !*list && *safe {
return fmt.Errorf("file %v would be overwritten by compiler", f)
}
}
if *list {
fmt.Println(f)
} else {
if dir != "" {
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
return fmt.Errorf("could not create output directory %v: %v", dir, err)
}
}
err := ioutil.WriteFile(f, contents, 0644)
if err != nil {
return fmt.Errorf("could not write file %v: %v", f, err)
}
}
return nil
}
process := func(filename string) error {
inputBytes, err := ioutil.ReadFile(filename)
if err != nil {
return fmt.Errorf("could not read file %v: %v", filename, err)
}
var song sointu.Song
if errJSON := json.Unmarshal(inputBytes, &song); errJSON != nil {
if errYaml := yaml.Unmarshal(inputBytes, &song); errYaml != nil {
return fmt.Errorf("song could not be unmarshaled as a .json (%v) or .yml (%v)", errJSON, errYaml)
}
}
if song.RowsPerBeat == 0 {
song.RowsPerBeat = 4
}
if song.Score.Length == 0 {
song.Score.Length = len(song.Score.Tracks[0].Patterns)
}
var compiledPlayer map[string]string
if compile {
var err error
compiledPlayer, err = comp.Song(&song)
if err != nil {
return fmt.Errorf("compiling player failed: %v", err)
}
if len(*extensionsOut) > 0 {
compiledPlayer = filterExtensions(compiledPlayer, strings.Split(*extensionsOut, ","))
}
for extension, code := range compiledPlayer {
if err := output(filename, extension, []byte(code)); err != nil {
return fmt.Errorf("error outputting %v file: %v", extension, err)
}
}
}
if *jsonOut {
jsonSong, err := json.Marshal(song)
if err != nil {
return fmt.Errorf("could not marshal the song as json file: %v", err)
}
if err := output(filename, ".json", jsonSong); err != nil {
return fmt.Errorf("error outputting json file: %v", err)
}
}
if *yamlOut {
yamlSong, err := yaml.Marshal(song)
if err != nil {
return fmt.Errorf("could not marshal the song as yaml file: %v", err)
}
if err := output(filename, ".yml", yamlSong); err != nil {
return fmt.Errorf("error outputting yaml file: %v", err)
}
}
return nil
}
retval := 0
if *library {
compiledLibrary, err := comp.Library()
if err != nil {
fmt.Fprintf(os.Stderr, "compiling library failed: %v\n", err)
retval = 1
} else {
if len(*extensionsOut) > 0 {
compiledLibrary = filterExtensions(compiledLibrary, strings.Split(*extensionsOut, ","))
}
for extension, code := range compiledLibrary {
if err := output("sointu", extension, []byte(code)); err != nil {
fmt.Fprintf(os.Stderr, "error outputting %v file: %v", extension, err)
retval = 1
}
}
}
}
for _, param := range flag.Args() {
if info, err := os.Stat(param); err == nil && info.IsDir() {
jsonfiles, err := filepath.Glob(filepath.Join(param, "*.json"))
if err != nil {
fmt.Fprintf(os.Stderr, "could not glob the path %v for json files: %v\n", param, err)
retval = 1
continue
}
ymlfiles, err := filepath.Glob(filepath.Join(param, "*.yml"))
if err != nil {
fmt.Fprintf(os.Stderr, "could not glob the path %v for yml files: %v\n", param, err)
retval = 1
continue
}
files := append(ymlfiles, jsonfiles...)
for _, file := range files {
err := process(file)
if err != nil {
fmt.Fprintf(os.Stderr, "could not process file %v: %v\n", file, err)
retval = 1
}
}
} else {
err := process(param)
if err != nil {
fmt.Fprintf(os.Stderr, "could not process file %v: %v\n", param, err)
retval = 1
}
}
}
os.Exit(retval)
}
func printUsage() {
fmt.Fprintf(os.Stderr, "Sointu compiler. Input .yml or .json songs, outputs compiled songs (e.g. .asm and .h files).\nUsage: %s [flags] [path ...]\n", os.Args[0])
flag.PrintDefaults()
}

164
cmd/sointu-play/main.go Normal file
View File

@ -0,0 +1,164 @@
package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"gopkg.in/yaml.v3"
"github.com/vsariola/sointu"
"github.com/vsariola/sointu/oto"
"github.com/vsariola/sointu/version"
"github.com/vsariola/sointu/vm/compiler/bridge"
)
func main() {
stdout := flag.Bool("s", false, "Do not write files; write to standard output instead.")
help := flag.Bool("h", false, "Show help.")
directory := flag.String("o", "", "Directory where to output all files. The directory and its parents are created if needed. By default, everything is placed in the same directory where the original song file is.")
play := flag.Bool("p", false, "Play the input songs (default behaviour when no other output is defined).")
//start := flag.Float64("start", 0, "Start playing from part; given in the units defined by parameter `unit`.")
//stop := flag.Float64("stop", -1, "Stop playing at part; given in the units defined by parameter `unit`. Negative values indicate render until end.")
//units := flag.String("unit", "pattern", "Units for parameters start and stop. Possible values: second, sample, pattern, beat. Warning: beat and pattern do not take SPEED modulations into account.")
rawOut := flag.Bool("r", false, "Output the rendered song as .raw file. By default, saves stereo float32 buffer to disk.")
wavOut := flag.Bool("w", false, "Output the rendered song as .wav file. By default, saves stereo float32 buffer to disk.")
pcm := flag.Bool("c", false, "Convert audio to 16-bit signed PCM when outputting.")
versionFlag := flag.Bool("v", false, "Print version.")
flag.Usage = printUsage
flag.Parse()
if *versionFlag {
fmt.Println(version.VersionOrHash)
os.Exit(0)
}
if flag.NArg() == 0 || *help {
flag.Usage()
os.Exit(0)
}
if !*rawOut && !*wavOut {
*play = true // if the user gives nothing to output, then the default behaviour is just to play the file
}
var audioContext sointu.AudioContext
if *play {
var err error
audioContext, err = oto.NewContext()
if err != nil {
fmt.Fprintf(os.Stderr, "could not acquire oto AudioContext: %v\n", err)
os.Exit(1)
}
defer audioContext.Close()
}
process := func(filename string) error {
output := func(extension string, contents []byte) error {
if *stdout {
fmt.Print(contents)
return nil
}
_, name := filepath.Split(filename)
var dir string
if *directory != "" {
dir = *directory
}
if dir == "" {
var err error
dir, err = os.Getwd()
if err != nil {
return fmt.Errorf("could not get working directory, specify the output directory explicitly: %v", err)
}
}
name = strings.TrimSuffix(name, filepath.Ext(name)) + extension
f := filepath.Join(dir, name)
if dir != "" {
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
return fmt.Errorf("could not create output directory %v: %v", dir, err)
}
}
err := ioutil.WriteFile(f, contents, 0644)
if err != nil {
return fmt.Errorf("could not write file %v: %v", f, err)
}
return nil
}
inputBytes, err := ioutil.ReadFile(filename)
if err != nil {
return fmt.Errorf("could not read file %v: %v", filename, err)
}
var song sointu.Song
if errJSON := json.Unmarshal(inputBytes, &song); errJSON != nil {
if errYaml := yaml.Unmarshal(inputBytes, &song); errYaml != nil {
return fmt.Errorf("the song could not be parsed as .json (%v) or .yml (%v)", errJSON, errYaml)
}
}
buffer, err := sointu.Play(bridge.NativeSynther{}, song, nil) // render the song to calculate its length
if err != nil {
return fmt.Errorf("sointu.Play failed: %v", err)
}
if *play {
output := audioContext.Output()
defer output.Close()
if err := output.WriteAudio(buffer); err != nil {
return fmt.Errorf("error playing: %v", err)
}
}
if *rawOut {
raw, err := buffer.Raw(*pcm)
if err != nil {
return fmt.Errorf("could not generate .raw file: %v", err)
}
if err := output(".raw", raw); err != nil {
return fmt.Errorf("error outputting .raw file: %v", err)
}
}
if *wavOut {
wav, err := buffer.Wav(*pcm)
if err != nil {
return fmt.Errorf("could not generate .wav file: %v", err)
}
if err := output(".wav", wav); err != nil {
return fmt.Errorf("error outputting .wav file: %v", err)
}
}
return nil
}
retval := 0
for _, param := range flag.Args() {
if info, err := os.Stat(param); err == nil && info.IsDir() {
jsonfiles, err := filepath.Glob(filepath.Join(param, "*.json"))
if err != nil {
fmt.Fprintf(os.Stderr, "could not glob the path %v for json files: %v\n", param, err)
retval = 1
continue
}
ymlfiles, err := filepath.Glob(filepath.Join(param, "*.yml"))
if err != nil {
fmt.Fprintf(os.Stderr, "could not glob the path %v for yml files: %v\n", param, err)
retval = 1
continue
}
files := append(ymlfiles, jsonfiles...)
for _, file := range files {
err := process(file)
if err != nil {
fmt.Fprintf(os.Stderr, "could not process file %v: %v\n", file, err)
retval = 1
}
}
} else {
err := process(param)
if err != nil {
fmt.Fprintf(os.Stderr, "could not process file %v: %v\n", param, err)
retval = 1
}
}
}
os.Exit(retval)
}
func printUsage() {
fmt.Fprintf(os.Stderr, "Sointu command line utility for playing .asm/.json song files.\nUsage: %s [flags] [path ...]\n", os.Args[0])
flag.PrintDefaults()
}

104
cmd/sointu-track/main.go Normal file
View File

@ -0,0 +1,104 @@
package main
import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"runtime"
"runtime/pprof"
"gioui.org/app"
"github.com/vsariola/sointu"
"github.com/vsariola/sointu/cmd"
"github.com/vsariola/sointu/oto"
"github.com/vsariola/sointu/tracker"
"github.com/vsariola/sointu/tracker/gioui"
)
type NullContext struct {
}
func (NullContext) NextEvent() (event tracker.MIDINoteEvent, ok bool) {
return tracker.MIDINoteEvent{}, false
}
func (NullContext) BPM() (bpm float64, ok bool) {
return 0, false
}
func (NullContext) Params() (ret tracker.ExtValueArray, ok bool) {
return tracker.ExtValueArray{}, false
}
func (NullContext) SetParams(params tracker.ExtParamArray) bool {
return false
}
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to `file`")
func main() {
flag.Parse()
var f *os.File
if *cpuprofile != "" {
var err error
f, err = os.Create(*cpuprofile)
if err != nil {
log.Fatal("could not create CPU profile: ", err)
}
if err := pprof.StartCPUProfile(f); err != nil {
log.Fatal("could not start CPU profile: ", err)
}
}
audioContext, err := oto.NewContext()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer audioContext.Close()
recoveryFile := ""
if configDir, err := os.UserConfigDir(); err == nil {
recoveryFile = filepath.Join(configDir, "Sointu", "sointu-track-recovery")
}
model, player := tracker.NewModelPlayer(cmd.MainSynther, recoveryFile)
if a := flag.Args(); len(a) > 0 {
f, err := os.Open(a[0])
if err == nil {
model.ReadSong(f)
}
f.Close()
}
tracker := gioui.NewTracker(model)
output := audioContext.Output()
defer output.Close()
go func() {
buf := make(sointu.AudioBuffer, 1024)
ctx := NullContext{}
for {
player.Process(buf, ctx)
output.WriteAudio(buf)
}
}()
go func() {
tracker.Main()
if *cpuprofile != "" {
pprof.StopCPUProfile()
f.Close()
}
if *memprofile != "" {
f, err := os.Create(*memprofile)
if err != nil {
log.Fatal("could not create memory profile: ", err)
}
defer f.Close() // error handling omitted for example
runtime.GC() // get up-to-date statistics
if err := pprof.WriteHeapProfile(f); err != nil {
log.Fatal("could not write memory profile: ", err)
}
}
os.Exit(0)
}()
app.Main()
}

186
cmd/sointu-vsti/main.go Normal file
View File

@ -0,0 +1,186 @@
//go:build plugin
package main
import (
"crypto/rand"
"encoding/hex"
"fmt"
"math"
"os"
"path/filepath"
"strconv"
"time"
"github.com/vsariola/sointu"
"github.com/vsariola/sointu/cmd"
"github.com/vsariola/sointu/tracker"
"github.com/vsariola/sointu/tracker/gioui"
"pipelined.dev/audio/vst2"
)
type VSTIProcessContext struct {
events []vst2.MIDIEvent
eventIndex int
host vst2.Host
parameters []*vst2.Parameter
}
func (c *VSTIProcessContext) NextEvent() (event tracker.MIDINoteEvent, ok bool) {
for c.eventIndex < len(c.events) {
ev := c.events[c.eventIndex]
c.eventIndex++
switch {
case ev.Data[0] >= 0x80 && ev.Data[0] < 0x90:
channel := ev.Data[0] - 0x80
note := ev.Data[1]
return tracker.MIDINoteEvent{Frame: int(ev.DeltaFrames), On: false, Channel: int(channel), Note: note}, true
case ev.Data[0] >= 0x90 && ev.Data[0] < 0xA0:
channel := ev.Data[0] - 0x90
note := ev.Data[1]
return tracker.MIDINoteEvent{Frame: int(ev.DeltaFrames), On: true, Channel: int(channel), Note: note}, true
default:
// ignore all other MIDI messages
}
}
return tracker.MIDINoteEvent{}, false
}
func (c *VSTIProcessContext) BPM() (bpm float64, ok bool) {
timeInfo := c.host.GetTimeInfo(vst2.TempoValid)
if timeInfo == nil || timeInfo.Flags&vst2.TempoValid == 0 || timeInfo.Tempo == 0 {
return 0, false
}
return timeInfo.Tempo, true
}
func (c *VSTIProcessContext) Params() (ret tracker.ExtValueArray, ok bool) {
for i, p := range c.parameters {
ret[i] = p.Value
}
return ret, true
}
func (c *VSTIProcessContext) SetParams(a tracker.ExtParamArray) bool {
changed := false
for i, p := range c.parameters {
i := i
name := a[i].Param.Name
if name == "" {
name = fmt.Sprintf("P%d", i)
}
if p.Value != a[i].Val || p.Name != name {
p.Value = a[i].Val
p.Name = name
p.GetValueFunc = func(value float32) float32 {
return float32(a[i].Param.MinValue) + value*float32(a[i].Param.MaxValue-a[i].Param.MinValue)
}
p.GetValueLabelFunc = func(v float32) string {
if f := a[i].Param.DisplayFunc; f != nil {
s, u := a[i].Param.DisplayFunc(int(v + .5))
c.parameters[i].Unit = u
return s
}
c.parameters[i].Unit = ""
return strconv.Itoa(int(v + .5))
}
changed = true
}
}
if changed {
c.host.UpdateDisplay()
}
return true
}
func init() {
var (
version = int32(100)
)
vst2.PluginAllocator = func(h vst2.Host) (vst2.Plugin, vst2.Dispatcher) {
recoveryFile := ""
if configDir, err := os.UserConfigDir(); err == nil {
randBytes := make([]byte, 16)
rand.Read(randBytes)
recoveryFile = filepath.Join(configDir, "sointu", "sointu-vsti-recovery-"+hex.EncodeToString(randBytes))
}
model, player := tracker.NewModelPlayer(cmd.MainSynther, recoveryFile)
t := gioui.NewTracker(model)
tracker.Bool{BoolData: (*tracker.InstrEnlarged)(model)}.Set(true)
if s := h.GetSampleRate(); math.Abs(float64(h.GetSampleRate()-44100.0)) > 1e-6 {
model.Alerts().AddAlert(tracker.Alert{
Message: fmt.Sprintf("VSTi host sample rate is %.0f Hz; sointu supports 44100 Hz only", s),
Priority: tracker.Error,
Duration: 10 * time.Second,
})
}
go t.Main()
parameters := make([]*vst2.Parameter, 0, tracker.ExtParamCount)
for i := 0; i < tracker.ExtParamCount; i++ {
parameters = append(parameters,
&vst2.Parameter{
Name: fmt.Sprintf("P%d", i),
NotAutomated: true,
})
}
context := VSTIProcessContext{host: h, parameters: parameters}
buf := make(sointu.AudioBuffer, 1024)
return vst2.Plugin{
UniqueID: PLUGIN_ID,
Version: version,
InputChannels: 0,
OutputChannels: 2,
Name: PLUGIN_NAME,
Vendor: "vsariola/sointu",
Category: vst2.PluginCategorySynth,
Flags: vst2.PluginIsSynth,
Parameters: parameters,
ProcessFloatFunc: func(in, out vst2.FloatBuffer) {
left := out.Channel(0)
right := out.Channel(1)
if len(buf) < out.Frames {
buf = append(buf, make(sointu.AudioBuffer, out.Frames-len(buf))...)
}
buf = buf[:out.Frames]
player.Process(buf, &context)
for i := 0; i < out.Frames; i++ {
left[i], right[i] = buf[i][0], buf[i][1]
}
context.events = context.events[:0] // reset buffer, but keep the allocated memory
context.eventIndex = 0
},
}, vst2.Dispatcher{
CanDoFunc: func(pcds vst2.PluginCanDoString) vst2.CanDoResponse {
switch pcds {
case vst2.PluginCanReceiveEvents, vst2.PluginCanReceiveMIDIEvent, vst2.PluginCanReceiveTimeInfo:
return vst2.YesCanDo
}
return vst2.NoCanDo
},
ProcessEventsFunc: func(ev *vst2.EventsPtr) {
for i := 0; i < ev.NumEvents(); i++ {
a := ev.Event(i)
switch v := a.(type) {
case *vst2.MIDIEvent:
context.events = append(context.events, *v)
}
}
},
CloseFunc: func() {
t.Exec() <- func() { t.ForceQuit().Do() }
t.WaitQuitted()
},
GetChunkFunc: func(isPreset bool) []byte {
retChn := make(chan []byte)
t.Exec() <- func() { retChn <- t.MarshalRecovery() }
return <-retChn
},
SetChunkFunc: func(data []byte, isPreset bool) {
t.Exec() <- func() { t.UnmarshalRecovery(data) }
},
}
}
}
func main() {}

View File

@ -0,0 +1,6 @@
//go:build native
package main
var PLUGIN_ID = [4]byte{'S', 'n', 't', 'N'}
var PLUGIN_NAME = "Sointu Native"

View File

@ -0,0 +1,6 @@
//go:build !native
package main
var PLUGIN_ID = [4]byte{'S', 'n', 't', 'u'}
var PLUGIN_NAME = "Sointu"

1
examples/CMakeLists.txt Normal file
View File

@ -0,0 +1 @@
add_subdirectory(code)

View File

@ -0,0 +1,68 @@
# this fixes a bug in creating a static library from asm, similar to
# https://discourse.cmake.org/t/building-lib-file-from-asm-cmake-bug/1959
# but for NASM
if(MSVC)
set(CMAKE_ASM_NASM_CREATE_STATIC_LIBRARY "<CMAKE_AR> /OUT:<TARGET> <LINK_FLAGS> <OBJECTS>")
endif()
add_custom_command(
COMMAND
${compilecmd} -arch=${arch} -o physics_girl_st.asm "${PROJECT_SOURCE_DIR}/examples/patches/physics_girl_st.yml"
WORKING_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}
DEPENDS
"${PROJECT_SOURCE_DIR}/examples/patches/physics_girl_st.yml"
${compilecmd}
OUTPUT
physics_girl_st.asm
physics_girl_st.h
physics_girl_st.inc
COMMENT
"Compiling ${PROJECT_SOURCE_DIR}/examples/patches/physics-girl-st.yml..."
)
add_library(physics_girl_st physics_girl_st.asm)
if(WIN32)
add_executable(cplay-winmm
cplay.windows.winmm.c
physics_girl_st.h
)
target_link_libraries(cplay-winmm PRIVATE winmm)
target_link_libraries(cplay-winmm PRIVATE physics_girl_st)
target_include_directories(cplay-winmm PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
add_dependencies(examples cplay-winmm)
add_executable(cplay-directsound
cplay.windows.directsound.c
physics_girl_st.h
)
target_link_libraries(cplay-directsound PRIVATE dsound ws2_32 ucrt)
target_link_libraries(cplay-directsound PRIVATE physics_girl_st)
target_include_directories(cplay-directsound PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
add_dependencies(examples cplay-directsound)
elseif(UNIX)
add_executable(cplay
cplay.unix.c
physics_girl_st.h
)
target_link_libraries(cplay PRIVATE asound pthread)
target_link_options(cplay PRIVATE -z noexecstack -no-pie)
target_link_libraries(cplay PRIVATE physics_girl_st)
target_include_directories(cplay PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
add_dependencies(examples cplay)
endif()
add_executable(cwav
cwav.c
physics_girl_st.h
)
if(WIN32)
target_compile_definitions(cwav PRIVATE _CRT_SECURE_NO_WARNINGS)
elseif(UNIX)
target_link_options(cwav PRIVATE -z noexecstack -no-pie)
endif()
target_link_libraries(cwav PRIVATE physics_girl_st)
target_include_directories(cwav PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
add_dependencies(examples cwav)

View File

@ -0,0 +1,39 @@
#include <alsa/asoundlib.h>
#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
#include "physics_girl_st.h"
static SUsample sound_buffer[SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT];
static snd_pcm_t *pcm_handle;
static pthread_t render_thread;
static uint32_t render_thread_handle;
int main(int argc, char **args) {
// Unix does not have gm.dls, no need to ifdef and setup here.
// We render in the background while playing already.
render_thread_handle = pthread_create(&render_thread, 0, (void * (*)(void *))su_render_song, sound_buffer);
// We can't start playing too early or the missing samples will be audible.
sleep(2.);
// Play the track.
snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
snd_pcm_set_params(
pcm_handle,
#ifdef SU_SAMPLE_FLOAT
SND_PCM_FORMAT_FLOAT,
#else // SU_SAMPLE_FLOAT
SND_PCM_FORMAT_S16_LE,
#endif // SU_SAMPLE_FLOAT
SND_PCM_ACCESS_RW_INTERLEAVED,
SU_CHANNEL_COUNT,
SU_SAMPLE_RATE,
0,
SU_LENGTH_IN_SAMPLES
);
snd_pcm_writei(pcm_handle, sound_buffer, SU_LENGTH_IN_SAMPLES);
return 0;
}

View File

@ -0,0 +1,75 @@
#include <stdio.h>
#include <stdint.h>
#include "physics_girl_st.h"
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#include <Windows.h>
#include "mmsystem.h"
#include "mmreg.h"
#define CINTERFACE
#include <dsound.h>
#ifndef DSBCAPS_TRUEPLAYPOSITION // Not defined in MinGW dsound headers, so let's add it
#define DSBCAPS_TRUEPLAYPOSITION 0x00080000
#endif
SUsample sound_buffer[SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT];
WAVEFORMATEX wave_format = {
#ifdef SU_SAMPLE_FLOAT
WAVE_FORMAT_IEEE_FLOAT,
#else
WAVE_FORMAT_PCM,
#endif
SU_CHANNEL_COUNT,
SU_SAMPLE_RATE,
SU_SAMPLE_RATE * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT,
SU_SAMPLE_SIZE * SU_CHANNEL_COUNT,
SU_SAMPLE_SIZE*8,
0
};
DSBUFFERDESC buffer_description = {
sizeof(DSBUFFERDESC),
DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS | DSBCAPS_TRUEPLAYPOSITION,
SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT,
0,
&wave_format,
0
};
int main(int argc, char **args) {
// Load gm.dls if necessary.
#ifdef SU_LOAD_GMDLS
su_load_gmdls();
#endif // SU_LOAD_GMDLS
HWND hWnd = GetForegroundWindow();
if(hWnd == NULL) {
hWnd = GetDesktopWindow();
}
LPDIRECTSOUND direct_sound;
LPDIRECTSOUNDBUFFER direct_sound_buffer;
DirectSoundCreate(0, &direct_sound, 0);
IDirectSound_SetCooperativeLevel(direct_sound, hWnd, DSSCL_PRIORITY);
IDirectSound_CreateSoundBuffer(direct_sound, &buffer_description, &direct_sound_buffer, NULL);
LPVOID p1;
DWORD l1;
IDirectSoundBuffer_Lock(direct_sound_buffer, 0, SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT * SU_SAMPLE_SIZE, &p1, &l1, NULL, NULL, 0);
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)su_render_song, p1, 0, 0);
IDirectSoundBuffer_Play(direct_sound_buffer, 0, 0, 0);
// We need to handle windows messages properly while playing, as waveOutWrite is async.
MSG msg = {0};
DWORD last_play_cursor = 0;
for(DWORD play_cursor = 0; play_cursor >= last_play_cursor; IDirectSoundBuffer_GetCurrentPosition(direct_sound_buffer, (DWORD*)&play_cursor, NULL)) {
while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
last_play_cursor = play_cursor;
}
return 0;
}

View File

@ -0,0 +1,63 @@
#include <stdio.h>
#include <stdint.h>
#include "physics_girl_st.h"
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#include <Windows.h>
#include "mmsystem.h"
#include "mmreg.h"
SUsample sound_buffer[SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT];
HWAVEOUT wave_out_handle;
WAVEFORMATEX wave_format = {
#ifdef SU_SAMPLE_FLOAT
WAVE_FORMAT_IEEE_FLOAT,
#else
WAVE_FORMAT_PCM,
#endif
SU_CHANNEL_COUNT,
SU_SAMPLE_RATE,
SU_SAMPLE_RATE * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT,
SU_SAMPLE_SIZE * SU_CHANNEL_COUNT,
SU_SAMPLE_SIZE*8,
0
};
WAVEHDR wave_header = {
(LPSTR)sound_buffer,
SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT,
0,
0,
WHDR_PREPARED,
0,
0,
0
};
MMTIME mmtime = {
TIME_SAMPLES,
0
};
int main(int argc, char **args) {
// Load gm.dls if necessary.
#ifdef SU_LOAD_GMDLS
su_load_gmdls();
#endif // SU_LOAD_GMDLS
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)su_render_song, sound_buffer, 0, 0);
// We render in the background while playing already. Fortunately,
// Windows is slow with the calls below, so we're not worried that
// we don't have enough samples ready before the track starts.
waveOutOpen(&wave_out_handle, WAVE_MAPPER, &wave_format, 0, 0, CALLBACK_NULL);
waveOutWrite(wave_out_handle, &wave_header, sizeof(wave_header));
// We need to handle windows messages properly while playing, as waveOutWrite is async.
for(MSG msg = {0}; mmtime.u.sample != SU_LENGTH_IN_SAMPLES; waveOutGetPosition(wave_out_handle, &mmtime, sizeof(MMTIME))) {
while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
}
return 0;
}

72
examples/code/C/cwav.c Normal file
View File

@ -0,0 +1,72 @@
#include <stdio.h>
#include <stdint.h>
#include "physics_girl_st.h"
#define WAVE_FORMAT_PCM 0x1
#define WAVE_FORMAT_IEEE_FLOAT 0x3
static SUsample sound_buffer[SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT];
#pragma pack(push, 1)
typedef struct {
char riff[4];
uint32_t file_size;
char wavefmt[8];
} riff_header_t;
typedef struct {
char data[4];
uint32_t data_size;
} data_header_t;
typedef struct {
riff_header_t riff_header;
uint32_t riff_header_size;
uint16_t sample_type;
uint16_t channel_count;
uint32_t sample_rate;
uint32_t bytes_per_second;
uint16_t bytes_per_channel;
uint16_t bits_per_sample;
data_header_t data_header;
} wave_header_t;
#pragma pack(pop)
int main(int argc, char **args) {
wave_header_t wave_header = {
.riff_header = (riff_header_t) {
.riff = "RIFF",
.file_size = sizeof(wave_header_t) + SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT,
.wavefmt = "WAVEfmt ",
},
.riff_header_size = sizeof(riff_header_t),
#ifdef SU_SAMPLE_FLOAT
.sample_type = WAVE_FORMAT_IEEE_FLOAT,
#else // SU_SAMPLE_FLOAT
.sample_type = WAVE_FORMAT_PCM,
#endif // SU_SAMPLE_FLOAT
.channel_count = SU_CHANNEL_COUNT,
.sample_rate = SU_SAMPLE_RATE,
.bytes_per_second = SU_SAMPLE_SIZE * SU_SAMPLE_RATE * SU_CHANNEL_COUNT,
.bytes_per_channel = SU_SAMPLE_SIZE * SU_CHANNEL_COUNT,
.bits_per_sample = SU_SAMPLE_SIZE * 8,
.data_header = (data_header_t) {
.data = "data",
.data_size = sizeof(data_header_t) + SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
}
};
// Load gm.dls if necessary.
#ifdef SU_LOAD_GMDLS
su_load_gmdls();
#endif // SU_LOAD_GMDLS
su_render_song(sound_buffer);
FILE *file = fopen("physics_girl_st.wav", "wb");
fwrite(&wave_header, sizeof(wave_header_t), 1, file);
fwrite((uint8_t *)sound_buffer, 1, SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT, file);
fclose(file);
return 0;
}

View File

@ -0,0 +1,34 @@
if(("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") AND MSVC)
# in 32-bit mode with MSVC toolset, we can use Crinkler to compress the executable
set(CRINKLER_LEVEL "off" CACHE STRING "Crinkler compression level: off, light, medium, heavy")
if(NOT CRINKLER_LEVEL STREQUAL OFF)
find_program(CRINKLER NAMES Crinkler)
if (NOT CRINKLER)
message(WARNING "Crinkler not found. Cannot compress executable; using default linker. Get Crinkler from https://github.com/runestubbe/Crinkler & put it in path (as Crinkler.exe)")
set(CRINKLER_LEVEL OFF)
endif()
endif()
if (NOT CRINKLER_LEVEL STREQUAL OFF)
message(STATUS "Crinkler found at: ${CRINKLER}")
set(CRINKLER_FLAGS "/PROGRESSGUI /UNSAFEIMPORT /UNALIGNCODE /HASHSIZE:1000 /REPORT:<TARGET>.report.html")
# TBD: do we add /SATURATE
if (CRINKLER_LEVEL STREQUAL LIGHT)
set(CRINKLER_FLAGS "${CRINKLER_FLAGS} /HASHTRIES:100 /COMPMODE:INSTANT /ORDERTRIES:2000")
elseif (CRINKLER_LEVEL STREQUAL HEAVY)
set(CRINKLER_FLAGS "${CRINKLER_FLAGS} /HASHTRIES:1000 /COMPMODE:VERYSLOW /ORDERTRIES:30000")
else()
set(CRINKLER_FLAGS "${CRINKLER_FLAGS} /HASHTRIES:300 /COMPMODE:SLOW /ORDERTRIES:9000")
endif()
# we drop the whole manifest creation from the front; did not find a way to disable it from CMake otherwise
set (CMAKE_C_LINK_EXECUTABLE "${CRINKLER} <OBJECTS> /out:<TARGET> ${CRINKLER_FLAGS} <LINK_LIBRARIES>")
endif()
endif()
set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
add_custom_target(examples)
add_subdirectory(asm)
add_subdirectory(C)

7
examples/code/Python/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
.venv
build
dist
__pycache__
setup.py
*.egg-info
*.so

View File

@ -0,0 +1,18 @@
# Embed Sointu in Python
This is an example for embedding Sointu into Python code.
# Configure the track
Edit the `track` variable in `build.py` according to your needs.
# Build
* Install Python 3.11 and poetry.
* Download nasm and golang; place both of them in your system `PATH`.
* Enable cgo by downloading a gcc and placing it into your system `PATH`.
* Get the dependencies with `poetry install`.
* Run the player using `poetry run python -m sointu_python`.
* Pack everything into an executable using `poetry run pyinstaller sointu_python/sointu_python.spec`. The executable will be built in the `dist` subfolder.
# Rebuild after changes
* Rebuild the example track bindings with `poetry build`.
* Update the bindings module with `poetry install`.
* Proceed iteration.

View File

@ -0,0 +1,149 @@
from distutils.command.build_ext import build_ext
from distutils.errors import (
CCompilerError,
DistutilsExecError,
DistutilsPlatformError,
)
from distutils.core import Extension
from os.path import (
dirname,
join,
abspath,
exists,
basename,
splitext,
)
from os import mkdir
from subprocess import run
from platform import system
from sys import exit
track = "../../patches/physics_girl_st.yml"
class BuildFailed(Exception):
pass
class ExtBuilder(build_ext):
def run(self):
try:
build_ext.run(self)
except (DistutilsPlatformError, FileNotFoundError):
raise BuildFailed('File not found. Could not compile C extension.')
def build_extension(self, ext):
try:
build_ext.build_extension(self, ext)
except (CCompilerError, DistutilsExecError, DistutilsPlatformError, ValueError):
raise BuildFailed('Could not compile C extension.')
def build(setup_kwargs):
# Make sure the build directory exists and setup the
# relative paths correctly.
cwd = abspath(".")
print("Running from:", cwd)
current_source_dir = abspath(dirname(__file__))
project_source_dir = abspath(join(current_source_dir, "..", "..", ".."))
current_binary_dir = join(current_source_dir, 'build')
if not exists(current_binary_dir):
mkdir(current_binary_dir)
host_is_windows = system() == "Windows"
executable_suffix = ".exe" if host_is_windows else ""
object_suffix = ".obj" if host_is_windows else ".o"
# Build the sointu compiler first.
compiler_executable = join(current_binary_dir, "sointu-compile{}".format(executable_suffix))
result = run(
args=[
"go", "build",
"-o", compiler_executable,
"cmd/sointu-compile/main.go",
],
cwd=project_source_dir,
shell=True if host_is_windows else False,
)
if result.returncode != 0:
print("sointu-compile build process exited with:", result.returncode)
print(result.stdout)
exit(1)
track_file_name = abspath(join(current_source_dir, track))
(track_name_base, _) = splitext(basename(track_file_name))
print("Compiling track:", track_file_name)
# Compile the track.
sointu_compiler_arch = "amd64"
track_asm_file = join(current_binary_dir, '{}.asm'.format(track_name_base))
result = run(
args=[
compiler_executable,
"-o", track_asm_file,
"-arch={}".format(sointu_compiler_arch),
track_file_name,
],
)
if result.returncode != 0:
print("sointu-compile process exited with:", result.returncode)
print(result.stdout)
exit(1)
# Assemble the track.
nasm_abi = "Win64" if host_is_windows else "Elf64"
track_object_file = join(current_binary_dir, '{}{}'.format(track_name_base, object_suffix))
print("Assembling track asm source:", track_asm_file)
result = run(
args=[
'nasm',
'-o', track_object_file,
'-f', nasm_abi,
track_asm_file,
],
)
if result.returncode != 0:
print("nasm process exited with:", result.returncode)
print(result.stdout)
exit(1)
# Export the plugin.
print("Linking object file into Python extension module:", track_object_file)
setup_kwargs.update({
"ext_modules": [
Extension(
"sointu",
include_dirs=[
current_binary_dir,
current_source_dir,
],
sources=[
"sointu.c",
],
extra_compile_args=[
"-DTRACK_HEADER=\"{}.h\"".format(track_name_base),
] + ([
"-DWIN32",
] if host_is_windows else [
"-DUNIX",
"-fPIC",
]),
extra_objects=[
track_object_file,
],
extra_link_args=[
"dsound.lib",
"ws2_32.lib",
"ucrt.lib",
"user32.lib",
] if host_is_windows else [
"-z", "noexecstack",
"--no-pie",
"-lasound",
"-lpthread",
"-lpython3.11",
],
),
],
"cmdclass": {
"build_ext": ExtBuilder,
},
})

132
examples/code/Python/poetry.lock generated Normal file
View File

@ -0,0 +1,132 @@
# This file is automatically @generated by Poetry and should not be changed by hand.
[[package]]
name = "altgraph"
version = "0.17.4"
description = "Python graph (network) package"
category = "dev"
optional = false
python-versions = "*"
files = [
{file = "altgraph-0.17.4-py2.py3-none-any.whl", hash = "sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff"},
{file = "altgraph-0.17.4.tar.gz", hash = "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406"},
]
[[package]]
name = "macholib"
version = "1.16.3"
description = "Mach-O header analysis and editing"
category = "dev"
optional = false
python-versions = "*"
files = [
{file = "macholib-1.16.3-py2.py3-none-any.whl", hash = "sha256:0e315d7583d38b8c77e815b1ecbdbf504a8258d8b3e17b61165c6feb60d18f2c"},
{file = "macholib-1.16.3.tar.gz", hash = "sha256:07ae9e15e8e4cd9a788013d81f5908b3609aa76f9b1421bae9c4d7606ec86a30"},
]
[package.dependencies]
altgraph = ">=0.17"
[[package]]
name = "packaging"
version = "23.2"
description = "Core utilities for Python packages"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
{file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
]
[[package]]
name = "pefile"
version = "2023.2.7"
description = "Python PE parsing module"
category = "dev"
optional = false
python-versions = ">=3.6.0"
files = [
{file = "pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6"},
{file = "pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc"},
]
[[package]]
name = "pyinstaller"
version = "6.0.0"
description = "PyInstaller bundles a Python application and all its dependencies into a single package."
category = "dev"
optional = false
python-versions = "<3.13,>=3.8"
files = [
{file = "pyinstaller-6.0.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:d84b06fb9002109bfc542e76860b81459a8585af0bbdabcfc5dcf272ef230de7"},
{file = "pyinstaller-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:aa922d1d73881d0820a341d2c406a571cc94630bdcdc275427c844a12e6e376e"},
{file = "pyinstaller-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:52e5b3a2371d7231de17515c7c78d8d4a39d70c8c095e71d55b3b83434a193a8"},
{file = "pyinstaller-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:4a75bde5cda259bb31f2294960d75b9d5c148001b2b0bd20a91f9c2116675a6c"},
{file = "pyinstaller-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:5314f6f08d2bcbc031778618ba97d9098d106119c2e616b3b081171fe42f5415"},
{file = "pyinstaller-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:0ad7cc3776ca17d0bededcc352cba2b1c89eb4817bfabaf05972b9da8c424935"},
{file = "pyinstaller-6.0.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:cccdad6cfe7a5db7d7eb8df2e5678f8375268739d5933214e180da300aa54e37"},
{file = "pyinstaller-6.0.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:fb6af82989dac7c58bd25ed9ba3323bc443f8c1f03804f69c9f5e363bf4a021c"},
{file = "pyinstaller-6.0.0-py3-none-win32.whl", hash = "sha256:68769f5e6722474bb1038e35560444659db8b951388bfe0c669bb52a640cd0eb"},
{file = "pyinstaller-6.0.0-py3-none-win_amd64.whl", hash = "sha256:438a9e0d72a57d5bba4f112d256e39ea4033c76c65414c0693d8311faa14b090"},
{file = "pyinstaller-6.0.0-py3-none-win_arm64.whl", hash = "sha256:16a473065291dd7879bf596fa20e65bd9d1e8aafc2cef1bffa3e42e707e2e68e"},
{file = "pyinstaller-6.0.0.tar.gz", hash = "sha256:d702cff041f30e7a53500b630e07b081e5328d4655023319253d73935e75ade2"},
]
[package.dependencies]
altgraph = "*"
macholib = {version = ">=1.8", markers = "sys_platform == \"darwin\""}
packaging = ">=20.0"
pefile = {version = ">=2022.5.30", markers = "sys_platform == \"win32\""}
pyinstaller-hooks-contrib = ">=2021.4"
pywin32-ctypes = {version = ">=0.2.1", markers = "sys_platform == \"win32\""}
setuptools = ">=42.0.0"
[package.extras]
hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"]
[[package]]
name = "pyinstaller-hooks-contrib"
version = "2023.9"
description = "Community maintained hooks for PyInstaller"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "pyinstaller-hooks-contrib-2023.9.tar.gz", hash = "sha256:76084b5988e3957a9df169d2a935d65500136967e710ddebf57263f1a909cd80"},
{file = "pyinstaller_hooks_contrib-2023.9-py2.py3-none-any.whl", hash = "sha256:f34f4c6807210025c8073ebe665f422a3aa2ac5f4c7ebf4c2a26cc77bebf63b5"},
]
[[package]]
name = "pywin32-ctypes"
version = "0.2.2"
description = "A (partial) reimplementation of pywin32 using ctypes/cffi"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "pywin32-ctypes-0.2.2.tar.gz", hash = "sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60"},
{file = "pywin32_ctypes-0.2.2-py3-none-any.whl", hash = "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7"},
]
[[package]]
name = "setuptools"
version = "68.2.2"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
{file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"},
{file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"},
]
[package.extras]
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.11,<3.13"
content-hash = "797bde9c30c55b3ddb24b1d3eceedd093d8a89eb934e6fe8fe7191dc9247224d"

View File

@ -0,0 +1,27 @@
[tool.poetry]
name = "sointu-python"
version = "0.1.0"
description = "Play back Sointu tracks in Python."
authors = ["Alexander Kraus <nr4@z10.info>"]
license = "MIT"
readme = "README.md"
packages = [
{ include = "sointu_python" },
]
include = [
{ path = "sointu*.so", format="wheel" }
]
[tool.poetry.build]
script = "build.py"
generate-setup-file = true
[tool.poetry.dependencies]
python = ">=3.11,<3.13"
[tool.poetry.group.dev.dependencies]
pyinstaller = "^6.0.0"
[build-system]
requires = ["poetry-core>=1.0.0a3", "poetry>=0.12", "setuptools", "wheel"]
build-backend = "poetry.core.masonry.api"

View File

@ -0,0 +1,212 @@
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include TRACK_HEADER
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
SUsample sound_buffer[SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT];
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#include <Windows.h>
#include "mmsystem.h"
#include "mmreg.h"
#define CINTERFACE
#include <dsound.h>
static WAVEFORMATEX wave_format = {
#ifdef SU_SAMPLE_FLOAT
WAVE_FORMAT_IEEE_FLOAT,
#else
WAVE_FORMAT_PCM,
#endif
SU_CHANNEL_COUNT,
SU_SAMPLE_RATE,
SU_SAMPLE_RATE * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT,
SU_SAMPLE_SIZE * SU_CHANNEL_COUNT,
SU_SAMPLE_SIZE*8,
0
};
DSBUFFERDESC buffer_description = {
sizeof(DSBUFFERDESC),
DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS | DSBCAPS_TRUEPLAYPOSITION,
SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT,
0,
&wave_format,
0
};
static HWND hWnd;
static LPDIRECTSOUND direct_sound;
static LPDIRECTSOUNDBUFFER direct_sound_buffer;
static LPVOID p1;
static DWORD l1;
static DWORD last_play_cursor = 0;
#endif /* WIN32 */
#ifdef UNIX
#include <alsa/asoundlib.h>
#include <pthread.h>
#include <time.h>
static snd_pcm_t *pcm_handle;
static pthread_t render_thread;
static uint32_t render_thread_handle;
static pthread_t playback_thread;
static uint32_t playback_thread_handle;
snd_htimestamp_t start_ts;
static int _snd_pcm_writei(void *params) {
(void) params;
snd_pcm_writei(pcm_handle, sound_buffer, SU_LENGTH_IN_SAMPLES);
return 0;
}
#endif /* UNIX */
static PyObject *sointuError;
static PyObject *sointu_play_song(PyObject *self, PyObject *args) {
#ifdef WIN32
#ifdef SU_LOAD_GMDLS
su_load_gmdls();
#endif // SU_LOAD_GMDLS
hWnd = GetForegroundWindow();
if(hWnd == NULL) {
hWnd = GetDesktopWindow();
}
DirectSoundCreate(0, &direct_sound, 0);
IDirectSound_SetCooperativeLevel(direct_sound, hWnd, DSSCL_PRIORITY);
IDirectSound_CreateSoundBuffer(direct_sound, &buffer_description, &direct_sound_buffer, NULL);
IDirectSoundBuffer_Lock(direct_sound_buffer, 0, SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT * SU_SAMPLE_SIZE, &p1, &l1, NULL, NULL, 0);
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)su_render_song, p1, 0, 0);
IDirectSoundBuffer_Play(direct_sound_buffer, 0, 0, 0);
#endif /* WIN32 */
#ifdef UNIX
render_thread_handle = pthread_create(&render_thread, 0, (void * (*)(void *))su_render_song, sound_buffer);
// We can't start playing too early or the missing samples will be audible.
sleep(2.);
// Play the track.
snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
snd_pcm_set_params(
pcm_handle,
#ifdef SU_SAMPLE_FLOAT
SND_PCM_FORMAT_FLOAT,
#else // SU_SAMPLE_FLOAT
SND_PCM_FORMAT_S16_LE,
#endif // SU_SAMPLE_FLOAT
SND_PCM_ACCESS_RW_INTERLEAVED,
SU_CHANNEL_COUNT,
SU_SAMPLE_RATE,
0,
SU_LENGTH_IN_SAMPLES
);
// Enable playback time querying.
snd_pcm_sw_params_t *swparams;
snd_pcm_sw_params_alloca(&swparams);
snd_pcm_sw_params_current(pcm_handle, swparams);
snd_pcm_sw_params_set_tstamp_mode(pcm_handle, swparams, SND_PCM_TSTAMP_ENABLE);
snd_pcm_sw_params_set_tstamp_type(pcm_handle, swparams, SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY);
snd_pcm_sw_params(pcm_handle, swparams);
playback_thread_handle = pthread_create(&playback_thread, 0, (void *(*)(void *))_snd_pcm_writei, 0);
// Get the start time stamp.
snd_pcm_uframes_t avail;
snd_pcm_htimestamp(pcm_handle, &avail, &start_ts);
#endif /* UNIX */
return PyLong_FromLong(0);
}
static PyObject *sointu_playback_position(PyObject *self, PyObject *args) {
#ifdef WIN32
DWORD play_cursor = 0;
IDirectSoundBuffer_GetCurrentPosition(direct_sound_buffer, (DWORD*)&play_cursor, NULL);
return Py_BuildValue("i", play_cursor / SU_CHANNEL_COUNT / sizeof(SUsample));
#endif /* WIN32 */
#ifdef UNIX
snd_htimestamp_t ts;
snd_pcm_uframes_t avail;
snd_pcm_htimestamp(pcm_handle, &avail, &ts);
return Py_BuildValue("i", (int)((ts.tv_sec - start_ts.tv_sec + 1.e-9 * (ts.tv_nsec - start_ts.tv_nsec)) * SU_SAMPLE_RATE));
#endif /* UNIX */
}
static PyObject *sointu_playback_finished(PyObject *self, PyObject *args) {
bool result = false;
#ifdef WIN32
DWORD play_cursor = 0;
IDirectSoundBuffer_GetCurrentPosition(direct_sound_buffer, (DWORD*)&play_cursor, NULL);
result = play_cursor < last_play_cursor;
last_play_cursor = play_cursor;
#endif /* WIN32 */
#ifdef UNIX
snd_htimestamp_t ts;
snd_pcm_uframes_t avail;
snd_pcm_htimestamp(pcm_handle, &avail, &ts);
result = ts.tv_sec - start_ts.tv_sec < 0;
#endif /* UNIX */
return PyBool_FromLong(result);
}
static PyObject *sointu_sample_rate(PyObject *self, PyObject *args) {
return Py_BuildValue("i", SU_SAMPLE_RATE);
}
static PyObject *sointu_track_length(PyObject *self, PyObject *args) {
return Py_BuildValue("i", SU_LENGTH_IN_SAMPLES);
}
static PyMethodDef sointuMethods[] = {
{"play_song", sointu_play_song, METH_VARARGS, "Play sointu track."},
{"playback_position", sointu_playback_position, METH_VARARGS, "Get playback position of sointu track currently playing."},
{"playback_finished", sointu_playback_finished, METH_VARARGS, "Check if currently playing sointu track has finished playing."},
{"sample_rate", sointu_sample_rate, METH_VARARGS, "Return the sample rate of the track compiled into this module."},
{"track_length", sointu_track_length, METH_VARARGS, "Return the track length in samples."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
static struct PyModuleDef sointumodule = {
PyModuleDef_HEAD_INIT,
"sointu",
NULL,
-1,
sointuMethods
};
PyMODINIT_FUNC PyInit_sointu(void) {
PyObject *module = PyModule_Create(&sointumodule);
if(module == NULL) {
return NULL;
}
sointuError = PyErr_NewException("sointu.sointuError", NULL, NULL);
Py_XINCREF(sointuError);
if(PyModule_AddObject(module, "error", sointuError) < 0) {
Py_XDECREF(sointuError);
Py_CLEAR(sointuError);
Py_DECREF(module);
return NULL;
}
return module;
}

View File

@ -0,0 +1,16 @@
from sointu import (
play_song,
playback_position,
playback_finished,
sample_rate,
track_length,
)
from sys import exit
if __name__ == '__main__':
play_song()
while not playback_finished():
print("Playback time:", playback_position() / sample_rate())
exit(0)

View File

@ -0,0 +1,58 @@
# -*- mode: python ; coding: utf-8 -*-
from os.path import abspath, join
from zipfile import ZipFile
from platform import system
moduleName = 'sointu_python'
rootPath = abspath('.')
buildPath = join(rootPath, 'build')
distPath = join(rootPath, 'dist')
sourcePath = join(rootPath, moduleName)
block_cipher = None
a = Analysis(
[
join(sourcePath, '__main__.py'),
],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='{}'.format(moduleName),
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=None,
)
exeFileName = '{}{}'.format(moduleName, '.exe' if system() == 'Windows' else '')
zipFileName = '{}-{}.zip'.format(moduleName, 'windows' if system() == 'Windows' else 'linux')
ZipFile(join(distPath, zipFileName), mode='w').write(join(distPath, exeFileName), arcname=exeFileName)

View File

@ -0,0 +1,10 @@
if(WIN32)
set(CMAKE_ASM_NASM_OBJECT_FORMAT win32)
elseif(UNIX)
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf32)
endif()
set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <DEFINES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
add_asm_example(asmplay "${PROJECT_SOURCE_DIR}/examples/patches/physics_girl_st.yml" 386 32 "winmm" "asound;pthread")
add_asm_example(asmwav "${PROJECT_SOURCE_DIR}/examples/patches/physics_girl_st.yml" 386 32 "" "")
target_compile_definitions(asmwav-386 PRIVATE FILENAME="physics_girl_st.wav")

View File

@ -0,0 +1,81 @@
%include TRACK_INCLUDE
%define SND_PCM_FORMAT_S16_LE 0x2
%define SND_PCM_FORMAT_FLOAT 0xE
%define SND_PCM_ACCESS_RW_INTERLEAVED 0x3
%define SND_PCM_STREAM_PLAYBACK 0x0
section .bss
sound_buffer:
resb SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
render_thread:
resd 1
pcm_handle:
resd 1
section .data
default_device:
db "default", 0
section .text
symbols:
extern pthread_create
extern sleep
extern snd_pcm_open
extern snd_pcm_set_params
extern snd_pcm_writei
global main
main:
; elf32 uses the cdecl calling convention. This is more readable imo ;)
; Prologue
push ebp
mov ebp, esp
sub esp, 0x10
; Unix does not have gm.dls, no need to ifdef and setup here.
; We render in the background while playing already.
push sound_buffer
lea eax, su_render_song
push eax
push 0
push render_thread
call pthread_create
; We can't start playing too early or the missing samples will be audible.
push 0x2
call sleep
; Play the track.
push 0x0
push SND_PCM_STREAM_PLAYBACK
push default_device
push pcm_handle
call snd_pcm_open
push SU_LENGTH_IN_SAMPLES
push 0
push SU_SAMPLE_RATE
push SU_CHANNEL_COUNT
push SND_PCM_ACCESS_RW_INTERLEAVED
%ifdef SU_SAMPLE_FLOAT
push SND_PCM_FORMAT_FLOAT
%else ; SU_SAMPLE_FLOAT
push SND_PCM_FORMAT_S16_LE
%endif ; SU_SAMPLE_FLOAT
push dword [pcm_handle]
call snd_pcm_set_params
push SU_LENGTH_IN_SAMPLES
push sound_buffer
push dword [pcm_handle]
call snd_pcm_writei
exit:
; At least we can skip the epilogue :)
leave
ret

View File

@ -0,0 +1,120 @@
%define MANGLED
%include TRACK_INCLUDE
%define WAVE_FORMAT_PCM 0x1
%define WAVE_FORMAT_IEEE_FLOAT 0x3
%define WHDR_PREPARED 0x2
%define WAVE_MAPPER 0xFFFFFFFF
%define TIME_SAMPLES 0x2
%define PM_REMOVE 0x1
section .bss
sound_buffer:
resb SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
wave_out_handle:
resd 1
msg:
resd 1
message:
resd 7
section .data
wave_format:
%ifdef SU_SAMPLE_FLOAT
dw WAVE_FORMAT_IEEE_FLOAT
%else ; SU_SAMPLE_FLOAT
dw WAVE_FORMAT_PCM
%endif ; SU_SAMPLE_FLOAT
dw SU_CHANNEL_COUNT
dd SU_SAMPLE_RATE
dd SU_SAMPLE_SIZE * SU_SAMPLE_RATE * SU_CHANNEL_COUNT
dw SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
dw SU_SAMPLE_SIZE * 8
dw 0
wave_header:
dd sound_buffer
dd SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
times 2 dd 0
dd WHDR_PREPARED
times 4 dd 0
wave_header_end:
mmtime:
dd TIME_SAMPLES
sample:
times 2 dd 0
mmtime_end:
section .text
symbols:
extern _CreateThread@24
extern _waveOutOpen@24
extern _waveOutWrite@12
extern _waveOutGetPosition@12
extern _PeekMessageA@20
extern _TranslateMessage@4
extern _DispatchMessageA@4
global _mainCRTStartup
_mainCRTStartup:
; win32 uses the cdecl calling convention. This is more readable imo ;)
; We can also skip the prologue; Windows doesn't mind.
%ifdef SU_LOAD_GMDLS
call _su_load_gmdls
%endif ; SU_LOAD_GMDLS
times 2 push 0
push sound_buffer
lea eax, _su_render_song@4
push eax
times 2 push 0
call _CreateThread@24
; We render in the background while playing already. Fortunately,
; Windows is slow with the calls below, so we're not worried that
; we don't have enough samples ready before the track starts.
times 3 push 0
push wave_format
push WAVE_MAPPER
push wave_out_handle
call _waveOutOpen@24
push wave_header_end - wave_header
push wave_header
push dword [wave_out_handle]
call _waveOutWrite@12
; We need to handle windows messages properly while playing, as waveOutWrite is async.
mainloop:
dispatchloop:
push PM_REMOVE
times 3 push 0
push msg
call _PeekMessageA@20
jz dispatchloop_end
push msg
call _TranslateMessage@4
push msg
call _DispatchMessageA@4
jmp dispatchloop
dispatchloop_end:
push mmtime_end - mmtime
push mmtime
push dword [wave_out_handle]
call _waveOutGetPosition@12
cmp dword [sample], SU_LENGTH_IN_SAMPLES
jne mainloop
exit:
; At least we can skip the epilogue :)
leave
ret

View File

@ -0,0 +1,91 @@
%include TRACK_INCLUDE
%define WAVE_FORMAT_PCM 0x1
%define WAVE_FORMAT_IEEE_FLOAT 0x3
section .bss
sound_buffer:
resb SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
file:
resd 1
section .data
; Change the filename over -DFILENAME="yourfilename.wav"
filename:
db FILENAME, 0
format:
db "wb", 0
; This is the wave file header.
wave_file:
db "RIFF"
dd wave_file_end + SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT - wave_file
db "WAVE"
db "fmt "
wave_format_end:
dd wave_format_end - wave_file
%ifdef SU_SAMPLE_FLOAT
dw WAVE_FORMAT_IEEE_FLOAT
%else ; SU_SAMPLE_FLOAT
dw WAVE_FORMAT_PCM
%endif ; SU_SAMPLE_FLOAT
dw SU_CHANNEL_COUNT
dd SU_SAMPLE_RATE
dd SU_SAMPLE_SIZE * SU_SAMPLE_RATE * SU_CHANNEL_COUNT
dw SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
dw SU_SAMPLE_SIZE * 8
wave_header_end:
db "data"
dd wave_file_end + SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT - wave_header_end
wave_file_end:
section .text
symbols:
extern fopen
extern fwrite
extern fclose
global main
main:
; elf32 uses the cdecl calling convention. This is more readable imo ;)
; Prologue
push ebp
mov ebp, esp
sub esp, 0x10
; Unix does not have gm.dls, no need to ifdef and setup here.
; We render the complete track here.
push sound_buffer
call su_render_song
; Now we open the file and save the track.
push format
push filename
call fopen
mov dword [file], eax
; Write header
push dword [file]
push 0x1
push wave_file_end - wave_file
push wave_file
call fwrite
; write data
push dword [file]
push 0x1
push SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
push sound_buffer
call fwrite
push dword [file]
call fclose
exit:
; At least we can skip the epilogue :)
leave
ret

View File

@ -0,0 +1,102 @@
%define MANGLED
%include TRACK_INCLUDE
%define WAVE_FORMAT_PCM 0x1
%define WAVE_FORMAT_IEEE_FLOAT 0x3
%define FILE_ATTRIBUTE_NORMAL 0x00000080
%define CREATE_ALWAYS 2
%define GENERIC_WRITE 0x40000000
section .bss
sound_buffer:
resb SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
file:
resd 1
bytes_written:
resd 1
section .data
; Change the filename over -DFILENAME="yourfilename.wav"
filename:
db FILENAME, 0
; This is the wave file header.
wave_file:
db "RIFF"
dd wave_file_end + SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT - wave_file
db "WAVE"
db "fmt "
wave_format_end:
dd wave_format_end - wave_file
%ifdef SU_SAMPLE_FLOAT
dw WAVE_FORMAT_IEEE_FLOAT
%else ; SU_SAMPLE_FLOAT
dw WAVE_FORMAT_PCM
%endif ; SU_SAMPLE_FLOAT
dw SU_CHANNEL_COUNT
dd SU_SAMPLE_RATE
dd SU_SAMPLE_SIZE * SU_SAMPLE_RATE * SU_CHANNEL_COUNT
dw SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
dw SU_SAMPLE_SIZE * 8
wave_header_end:
db "data"
dd wave_file_end + SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT - wave_header_end
wave_file_end:
section .text
symbols:
extern _CreateFileA@28
extern _WriteFile@20
extern _CloseHandle@4
global _mainCRTStartup
_mainCRTStartup:
; Prologue
push ebp
mov ebp, esp
sub esp, 0x10
%ifdef SU_LOAD_GMDLS
call _su_load_gmdls
%endif ; SU_LOAD_GMDLS
; We render the complete track here.
push sound_buffer
call _su_render_song@4
; Now we open the file and save the track.
push 0x0
push FILE_ATTRIBUTE_NORMAL
push CREATE_ALWAYS
push 0x0
push 0x0
push GENERIC_WRITE
push filename
call _CreateFileA@28
mov dword [file], eax
; This is the WAV header
push 0x0
push bytes_written
push wave_file_end - wave_file
push wave_file
push dword [file]
call _WriteFile@20
; There we write the actual samples
push 0x0
push bytes_written
push SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT * SU_SAMPLE_SIZE
push sound_buffer
push dword [file]
call _WriteFile@20
push dword [file]
call _CloseHandle@4
exit:
; At least we can skip the epilogue :)
leave
ret

View File

@ -0,0 +1,58 @@
# identifier: Name of the example
# songfile: File path of the song YAML file.
# architecture: 386 or amd64
# abi: 32 or 64
# windows_libraries: All libraries that you need to link on Windows
# unix_libraries: All libraries that you need to link on unix
function(add_asm_example identifier songfile architecture sizeof_void_ptr windows_libraries unix_libraries)
get_filename_component(songprefix ${songfile} NAME_WE)
# Generate the song assembly file
add_custom_command(
COMMAND
${compilecmd} -arch=${architecture} -o ${songprefix}_${architecture}.asm ${songfile}
WORKING_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}
DEPENDS
${songfile}
${compilecmd}
OUTPUT
${songprefix}_${architecture}.asm
${songprefix}_${architecture}.h
${songprefix}_${architecture}.inc
COMMENT
"Compiling ${PROJECT_SOURCE_DIR}/examples/patches/physics-girl-st.yml..."
)
# Platform dependent options
if(WIN32)
set(abi win)
set(libraries ${windows_libraries})
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(link_options -nostartfiles)
endif()
elseif(UNIX)
set(abi elf)
set(link_options -z noexecstack -no-pie)
set(libraries ${unix_libraries})
endif()
# Add target
add_executable(${identifier}-${architecture}
${identifier}.${abi}${sizeof_void_ptr}.asm
${songprefix}_${architecture}.asm
${songprefix}_${architecture}.inc
)
set_target_properties(${identifier}-${architecture} PROPERTIES ASM_NASM_COMPILE_OPTIONS -f${abi}${sizeof_void_ptr})
target_include_directories(${identifier}-${architecture} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
set_target_properties(${identifier}-${architecture} PROPERTIES LINKER_LANGUAGE C)
target_link_options(${identifier}-${architecture} PRIVATE -m${sizeof_void_ptr} ${link_options})
target_link_libraries(${identifier}-${architecture} PRIVATE ${libraries})
target_compile_definitions(${identifier}-${architecture} PRIVATE TRACK_INCLUDE="${songprefix}_${architecture}.inc")
# Set up dependencies
add_dependencies(examples ${identifier}-${architecture})
endfunction()
add_subdirectory(386)
add_subdirectory(amd64)

View File

@ -0,0 +1,12 @@
if(WIN32)
set(CMAKE_ASM_NASM_OBJECT_FORMAT win64)
elseif(UNIX)
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
endif()
set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <DEFINES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
if(UNIX)
add_asm_example(asmplay "${PROJECT_SOURCE_DIR}/examples/patches/physics_girl_st.yml" amd64 64 "winmm" "asound;pthread")
add_asm_example(asmwav "${PROJECT_SOURCE_DIR}/examples/patches/physics_girl_st.yml" amd64 64 "" "")
target_compile_definitions(asmwav-amd64 PRIVATE FILENAME="physics_girl_st.wav")
endif()

View File

@ -0,0 +1,81 @@
%include TRACK_INCLUDE
%define SND_PCM_FORMAT_S16_LE 0x2
%define SND_PCM_FORMAT_FLOAT 0xE
%define SND_PCM_ACCESS_RW_INTERLEAVED 0x3
%define SND_PCM_STREAM_PLAYBACK 0x0
section .bss
sound_buffer:
resb SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
render_thread:
resq 1
pcm_handle:
resq 1
section .data
default_device:
db "default", 0
section .text
symbols:
extern pthread_create
extern sleep
extern snd_pcm_open
extern snd_pcm_set_params
extern snd_pcm_writei
global main
main:
; Prologue
push rbp
mov rbp, rsp
sub rsp, 0x10
; Unix does not have gm.dls, no need to ifdef and setup here.
; We render in the background while playing already.
mov rcx, sound_buffer
lea rdx, su_render_song
mov rsi, 0x0
mov rdi, render_thread
call pthread_create
; We can't start playing too early or the missing samples will be audible.
mov edi, 0x2
call sleep
; Play the track.
mov rdi, pcm_handle
mov rsi, default_device
mov rdx, SND_PCM_STREAM_PLAYBACK
mov rcx, 0x0
call snd_pcm_open
; This is unfortunate. amd64 ABI calling convention kicks in.
; now we have to maintain the stack pointer :/
mov rdi, qword [pcm_handle]
sub rsp, 0x8
push SU_LENGTH_IN_SAMPLES
%ifdef SU_SAMPLE_FLOAT
mov rsi, SND_PCM_FORMAT_FLOAT
%else ; SU_SAMPLE_FLOAT
mov rsi, SND_PCM_FORMAT_S16_LE
%endif ; SU_SAMPLE_FLOAT
mov rdx, SND_PCM_ACCESS_RW_INTERLEAVED
mov rcx, SU_CHANNEL_COUNT
mov r8d, SU_SAMPLE_RATE
mov r9d, 0x0
call snd_pcm_set_params
mov rdi, qword [pcm_handle]
mov rsi, sound_buffer
mov rdx, SU_LENGTH_IN_SAMPLES
call snd_pcm_writei
exit:
; At least we can skip the epilogue :)
leave
ret

View File

@ -0,0 +1,91 @@
%include TRACK_INCLUDE
%define WAVE_FORMAT_PCM 0x1
%define WAVE_FORMAT_IEEE_FLOAT 0x3
section .bss
sound_buffer:
resb SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
file:
resq 1
section .data
; Change the filename over -DFILENAME="yourfilename.wav"
filename:
db FILENAME, 0
format:
db "wb", 0
; This is the wave file header.
wave_file:
db "RIFF"
dd wave_file_end + SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT - wave_file
db "WAVE"
db "fmt "
wave_format_end:
dd wave_format_end - wave_file
%ifdef SU_SAMPLE_FLOAT
dw WAVE_FORMAT_IEEE_FLOAT
%else ; SU_SAMPLE_FLOAT
dw WAVE_FORMAT_PCM
%endif ; SU_SAMPLE_FLOAT
dw SU_CHANNEL_COUNT
dd SU_SAMPLE_RATE
dd SU_SAMPLE_SIZE * SU_SAMPLE_RATE * SU_CHANNEL_COUNT
dw SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
dw SU_SAMPLE_SIZE * 8
wave_header_end:
db "data"
dd wave_file_end + SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT - wave_header_end
wave_file_end:
section .text
symbols:
extern fopen
extern fwrite
extern fclose
global main
main:
; elf32 uses the cdecl calling convention. This is more readable imo ;)
; Prologue
push rbp
mov rbp, rsp
sub rsp, 0x10
; Unix does not have gm.dls, no need to ifdef and setup here.
; We render the complete track here.
mov rdi, sound_buffer
call su_render_song
; Now we open the file and save the track.
mov rsi, format
mov rdi, filename
call fopen
mov qword [file], rax
; Write header
mov rcx, qword [file]
mov rdx, 0x1
mov rsi, wave_file_end - wave_file
mov rdi, wave_file
call fwrite
; write data
mov rcx, qword [file]
mov rdx, 0x1
mov rsi, SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT
mov rdi, sound_buffer
call fwrite
mov rdi, qword [file]
call fclose
exit:
; At least we can skip the epilogue :)
leave
ret

View File

@ -0,0 +1,14 @@
Requirements: sointu binaries, `wabt`
To generate the .wasm file:
```
sointu-compile -o . -arch=wasm tests/test_chords.yml
wat2wasm --enable-bulk-memory test_chords.wat
```
To run the example:
```
npx serve examples/code/wasm
```

View File

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<title>sointu WASM example</title>
</head>
<body>
<script type="module">
// button to start audio context
const button = document.createElement("button");
button.innerHTML = "start";
document.body.appendChild(button);
button.onclick = () => {
document.body.removeChild(button);
fetch("test_chords.wasm")
.then((response) => response.arrayBuffer())
.then((bytes) => WebAssembly.instantiate(bytes, { m: Math }))
.then(({ instance }) => {
const context = new AudioContext({ sampleRate: 44100 });
let frames = instance.exports.t.value
? instance.exports.l.value / 4
: instance.exports.l.value / 8;
let wasmBuffer = new Float32Array(
instance.exports.m.buffer,
instance.exports.s.value,
frames * 2
);
const buffer = context.createBuffer(2, frames, context.sampleRate);
// convert wasm buffer to audio buffer
for (let channel = 0; channel < 2; channel++) {
const buffering = buffer.getChannelData(channel);
for (let i = 0; i < frames; i++) {
buffering[i] = wasmBuffer[i * 2 + channel];
}
}
// connect to output and start playing
const src = context.createBufferSource();
src.buffer = buffer;
src.connect(context.destination);
src.start();
});
};
</script>
</body>
</html>

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More