Browse Source

add Alikins and BaconMusic modules

pull/1639/head
bsp2 6 years ago
parent
commit
537b44cf3c
100 changed files with 27839 additions and 67 deletions
  1. +24
    -4
      README.md
  2. +1
    -0
      makefile.msvc
  3. +27
    -0
      plugins/community/repos/Alikins/LICENSE.txt
  4. +32
    -0
      plugins/community/repos/Alikins/Makefile
  5. +153
    -0
      plugins/community/repos/Alikins/README.md
  6. +203
    -0
      plugins/community/repos/Alikins/TODO.txt
  7. +8
    -0
      plugins/community/repos/Alikins/make.objects
  8. +7
    -0
      plugins/community/repos/Alikins/makefile.msvc
  9. +2006
    -0
      plugins/community/repos/Alikins/res/BigMuteButton.svg
  10. +3669
    -0
      plugins/community/repos/Alikins/res/BigMuteButtonMute.svg
  11. +2090
    -0
      plugins/community/repos/Alikins/res/BigMuteButtonUnmute.svg
  12. +1954
    -0
      plugins/community/repos/Alikins/res/GateLength.svg
  13. +3002
    -0
      plugins/community/repos/Alikins/res/IdleSwitch.svg
  14. +151
    -0
      plugins/community/repos/Alikins/res/MomentaryOnButtons.svg
  15. +99
    -0
      plugins/community/repos/Alikins/res/PurpleTrimpot.svg
  16. BIN
      plugins/community/repos/Alikins/res/Segment7Standard.ttf
  17. +94
    -0
      plugins/community/repos/Alikins/res/SmallPurpleTrimpot.svg
  18. +2458
    -0
      plugins/community/repos/Alikins/res/SpecificValue.svg
  19. BIN
      plugins/community/repos/Alikins/screenshots/modules.png
  20. +167
    -0
      plugins/community/repos/Alikins/src/BigMuteButton.cpp
  21. +359
    -0
      plugins/community/repos/Alikins/src/ColorPanel.cpp
  22. +140
    -0
      plugins/community/repos/Alikins/src/GateLength.cpp
  23. +328
    -0
      plugins/community/repos/Alikins/src/IdleSwitch.cpp
  24. +152
    -0
      plugins/community/repos/Alikins/src/MomentaryOnButtons.cpp
  25. +49
    -0
      plugins/community/repos/Alikins/src/MsDisplayWidget.hpp
  26. +653
    -0
      plugins/community/repos/Alikins/src/SpecificValue.cpp
  27. +22
    -0
      plugins/community/repos/Alikins/src/alikins.cpp
  28. +12
    -0
      plugins/community/repos/Alikins/src/alikins.hpp
  29. +20
    -0
      plugins/community/repos/BaconMusic/BaconMusic.json
  30. +26
    -0
      plugins/community/repos/BaconMusic/LICENSE.txt
  31. +45
    -0
      plugins/community/repos/BaconMusic/Makefile
  32. +286
    -0
      plugins/community/repos/BaconMusic/README.md
  33. BIN
      plugins/community/repos/BaconMusic/docs/ALingADing.png
  34. BIN
      plugins/community/repos/BaconMusic/docs/Bitulator.png
  35. +18
    -0
      plugins/community/repos/BaconMusic/docs/CODE_OF_CONDUCT.md
  36. +19
    -0
      plugins/community/repos/BaconMusic/docs/CONTRIBUTING.md
  37. BIN
      plugins/community/repos/BaconMusic/docs/ChipNoise.png
  38. BIN
      plugins/community/repos/BaconMusic/docs/ChipWaves.png
  39. BIN
      plugins/community/repos/BaconMusic/docs/ChipYourWaves.png
  40. BIN
      plugins/community/repos/BaconMusic/docs/Glissinator.png
  41. BIN
      plugins/community/repos/BaconMusic/docs/HarMoNee.png
  42. BIN
      plugins/community/repos/BaconMusic/docs/KarplusStrongPoly.png
  43. BIN
      plugins/community/repos/BaconMusic/docs/PolyGnome.png
  44. BIN
      plugins/community/repos/BaconMusic/docs/QuantEyes.png
  45. BIN
      plugins/community/repos/BaconMusic/docs/SampleDelay.png
  46. BIN
      plugins/community/repos/BaconMusic/docs/SpeakerIcon.png
  47. BIN
      plugins/community/repos/BaconMusic/docs/SpeakerIconSmall.png
  48. +14
    -0
      plugins/community/repos/BaconMusic/docs/release_notes/future_releases.md
  49. +34
    -0
      plugins/community/repos/BaconMusic/docs/release_notes/release_v0.6.2.md
  50. +16
    -0
      plugins/community/repos/BaconMusic/make.objects
  51. +9
    -0
      plugins/community/repos/BaconMusic/makefile.msvc
  52. +422
    -0
      plugins/community/repos/BaconMusic/pynb/KarplusStrong.ipynb
  53. +505
    -0
      plugins/community/repos/BaconMusic/res/BaconSliderHandle.svg
  54. +360
    -0
      plugins/community/repos/BaconMusic/res/HelpActive.svg
  55. +249
    -0
      plugins/community/repos/BaconMusic/res/HelpActiveSmall.svg
  56. +249
    -0
      plugins/community/repos/BaconMusic/res/HelpGraySmall.svg
  57. +669
    -0
      plugins/community/repos/BaconMusic/res/Keypunch029.json
  58. BIN
      plugins/community/repos/BaconMusic/res/Monitorica-Bd.ttf
  59. +3
    -0
      plugins/community/repos/BaconMusic/res/README.md
  60. +115
    -0
      plugins/community/repos/BaconMusic/src/ALingADing.cpp
  61. +45
    -0
      plugins/community/repos/BaconMusic/src/BaconPlugs.cpp
  62. +23
    -0
      plugins/community/repos/BaconMusic/src/BaconPlugs.hpp
  63. +155
    -0
      plugins/community/repos/BaconMusic/src/Bitulator.cpp
  64. +45
    -0
      plugins/community/repos/BaconMusic/src/BlankWidget.cpp
  65. +70
    -0
      plugins/community/repos/BaconMusic/src/BufferedDrawFunction.hpp
  66. +177
    -0
      plugins/community/repos/BaconMusic/src/ChipNoise.cpp
  67. +391
    -0
      plugins/community/repos/BaconMusic/src/ChipSym.hpp
  68. +128
    -0
      plugins/community/repos/BaconMusic/src/ChipWaves.cpp
  69. +108
    -0
      plugins/community/repos/BaconMusic/src/ChipYourWave.cpp
  70. +295
    -0
      plugins/community/repos/BaconMusic/src/Components.cpp
  71. +592
    -0
      plugins/community/repos/BaconMusic/src/Components.hpp
  72. +58
    -0
      plugins/community/repos/BaconMusic/src/Glissinator.cpp
  73. +119
    -0
      plugins/community/repos/BaconMusic/src/Glissinator.hpp
  74. +87
    -0
      plugins/community/repos/BaconMusic/src/GraduatedFader.hpp
  75. +217
    -0
      plugins/community/repos/BaconMusic/src/HarMoNee.cpp
  76. +217
    -0
      plugins/community/repos/BaconMusic/src/KSSynth.hpp
  77. +411
    -0
      plugins/community/repos/BaconMusic/src/KarplusStrongPoly.cpp
  78. +179
    -0
      plugins/community/repos/BaconMusic/src/PolyGnome.cpp
  79. +193
    -0
      plugins/community/repos/BaconMusic/src/QuantEyes.cpp
  80. +60
    -0
      plugins/community/repos/BaconMusic/src/SampleDelay.cpp
  81. +62
    -0
      plugins/community/repos/BaconMusic/src/SampleDelay.hpp
  82. +67
    -0
      plugins/community/repos/BaconMusic/src/SizeTable.hpp
  83. +141
    -0
      plugins/community/repos/BaconMusic/src/SortaChorus.cpp
  84. +128
    -0
      plugins/community/repos/BaconMusic/standalone/GlissinatorTest.cpp
  85. +21
    -0
      plugins/community/repos/BaconMusic/standalone/Makefile
  86. +27
    -0
      plugins/community/repos/BaconMusic/standalone/SampleDelayTest.cpp
  87. +116
    -0
      plugins/community/repos/BaconMusic/standalone/chipNoisePeriod.cpp
  88. +87
    -0
      plugins/community/repos/BaconMusic/standalone/chipTester.cpp
  89. +34
    -0
      plugins/community/repos/BaconMusic/standalone/docsaw.cpp
  90. +44
    -0
      plugins/community/repos/BaconMusic/standalone/kssynthDemo.cpp
  91. +123
    -0
      plugins/community/repos/BaconMusic/standalone/standalone_helpers.hpp
  92. +4
    -0
      plugins/makefile.msvc
  93. +4
    -0
      src/plugin.cpp
  94. +20
    -0
      vst2_bin/CHANGELOG_VST.txt
  95. +19
    -1
      vst2_bin/README_vst2.txt
  96. +64
    -62
      vst2_bin/log.txt
  97. +27
    -0
      vst2_bin/plugins/Alikins/LICENSE.txt
  98. +153
    -0
      vst2_bin/plugins/Alikins/README.md
  99. +203
    -0
      vst2_bin/plugins/Alikins/TODO.txt
  100. +2006
    -0
      vst2_bin/plugins/Alikins/res/BigMuteButton.svg

+ 24
- 4
README.md View File

@@ -22,7 +22,13 @@ Tested in
# Downloads
The current release can be found in the [vst2_bin/](vst2_bin/) folder.

Here's a snapshot of it: [veeseevstrack_0_6_1_win64_bin-08Jul2018b.7z](dist/veeseevstrack_0_6_1_win64_bin-08Jul2018b.7z) (64bit)
Here's a snapshot of it: [veeseevstrack_0_6_1_win64_bin-09Jul2018.7z](dist/veeseevstrack_0_6_1_win64_bin-09Jul2018.7z) (64bit)
**WARNING** DON'T TRY TO USE THE INSTRUMENT AND EFFECT PLUGINS IN THE SAME PROJECT OR YOUR DAW WILL CRASH.**
(the effect plugin can used be as an instrument, you just have to send it MIDI events)


# Changelog
see [vst2_bin/CHANGELOG_VST.txt](vst2_bin/CHANGELOG_VST.txt)


# Demo Video
@@ -33,6 +39,12 @@ Here's a demo video of it: https://vimeo.com/277703414
# Add-on modules

The following add-on modules are statically linked with the VST plugin:
- Alikins.IdleSwitch
- Alikins.MomentaryOnButtons
- Alikins.BigMuteButton
- Alikins.ColorPanel
- Alikins.GateLength
- Alikins.SpecificValue
- AS.ADSR
- AS.AtNuVrTr
- AS.BPMCalc
@@ -82,6 +94,17 @@ The following add-on modules are statically linked with the VST plugin:
- AudibleInstruments.Blinds
- AudibleInstruments.Veils
- AudibleInstruments.Frames
- BaconMusic.Glissinator
- BaconMusic.PolyGnome
- BaconMusic.QuantEyes
- BaconMusic.SampleDelay
- BaconMusic.SortaChorus
- BaconMusic.ChipNoise
- BaconMusic.ChipWaves
- BaconMusic.ChipYourWave
- BaconMusic.KarplusStrongPoly
- BaconMusic.ALingADing
- BaconMusic.Bitulator
- Befaco.ABC
- Befaco.DualAtenuverter
- Befaco.EvenVCO
@@ -458,9 +481,6 @@ It is not permitted to redistribute it and Steinberg has discontinued it.
I heard that the `aeffect.h` / `aeffectx.h` files are still included in the VST3 SDK.


# Changelog
see [vst2_bin/CHANGELOG_VST.txt](vst2_bin/CHANGELOG_VST.txt)

# VCV Rack

For more info about VCV rack, see https://vcvrack.com/


+ 1
- 0
makefile.msvc View File

@@ -14,6 +14,7 @@ lib:

.PHONY:
vst: lib
rm -f src/vst2_main.o
make -f makefile_vst_instr.msvc bin -j $(NUM_JOBS)
rm -f src/vst2_main.o
make -f makefile_vst_effect.msvc bin -j $(NUM_JOBS)


+ 27
- 0
plugins/community/repos/Alikins/LICENSE.txt View File

@@ -0,0 +1,27 @@
BSD 3-Clause License

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


+ 32
- 0
plugins/community/repos/Alikins/Makefile View File

@@ -0,0 +1,32 @@
SLUG = Alikins
VERSION = 0.6.0

RACK_DIR ?= ../..

# FLAGS will be passed to both the C and C++ compiler
FLAGS +=
CFLAGS +=
CXXFLAGS +=

# Careful about linking to libraries, since you can't assume much about the user's environment and library search path.
# Static libraries are fine.
LDFLAGS +=

# Add .cpp and .c files to the build
SOURCES = $(wildcard src/*.cpp)

# Must include the VCV plugin Makefile framework
include $(RACK_DIR)/plugin.mk

# http://cppcheck.sourceforge.net/
cppcheck:
cppcheck -i$(RACK_DIR)/dep/include -i$(RACK_DIR)/include --enable=style -DVERSION=0.5.1 --quiet src/

# https://github.com/google/styleguide
cpplint:
cpplint --headers=hpp --filter=-whitespace/line_length,-legal/copyright,-whitespace/blank_line src/*.cpp src/*.hpp


DISTRIBUTABLES += $(wildcard LICENSE*) res

.PHONY: cppcheck cpplint

+ 153
- 0
plugins/community/repos/Alikins/README.md View File

@@ -0,0 +1,153 @@

# VCV Rack plugin

Plugins for use with VCV Rack virtual module synthesizer (https://github.com/VCVRack/Rack)

![screenshot](./screenshots/modules.png)

## Modules

### IdleSwitch

#### What

An 'idle loop' inspired module for detecting when an input
is idle and turns on a gate until it sees activity again.

If no input events are seen at "Input Source" within the timeout period
emit a gate on "Idle Gate Output" that lasts until there are input events
again. Then reset the timeout period.

Sort of metaphoricaly like an idle handler or timeout in event based
programming like GUI main loops.

The timeout period is set by the value
of the "Time before idle" param.

##### Input event

An "Input event" is a gate or trigger (or a CV or audio signal
that looks sufficently like a gate or trigger).

After a input event, the Idle Gate Output will remain on until
an input event is seen at Input Source. When there is an input event, the Idle
Gate Output is turned off until the expiration of the "Time before idle" or
the next "Reset idle".

##### Reset timer

If there is a "Reset timer" source, when it gets an event, the timeout period
is reset. But unlike an "Input event", a "Reset timer" event does does not
reset the idle status.

After "Reset time" event, the "Idle Gate Output" will remain on until
an input event is seen at Input Source. When there is an input event, the Idle
Gate Output is turned off until the expiration of the "Time before idle" or
the next "Reset idle".

To use the eventloop/gui main loop analogy, a "Reset idle" event is equilivent to
running an idle handler directly (or running a mainloop iteration with no non-idle
events pending).

##### Clock input

If a cable is hooked to the "Clock Input" then the pulse from the clock
will determine with the idle time expires. When there is a clock pulse,
if there were no input events since the previous clock pulse that is
considered idle.

The "Time before idle" display will reflect the time since the last
clock pulse. The "Time remaining" display will always show 0 for now,
at least until it can predict the future.

##### Time input and output

The "Time input" expects a CV output between 0 and 10V. The voltage
maps directly do the number of seconds for the idle timeout.
Eg. a 5.0V CV to "Time input" sets "Time before idle" to 5000ms (5.0 seconds)

The "Time output" sends a CV output between 0 and 10V indicating
the "Time before idle" value.

The "Time output" can be used to connect one or more IdleSwitch modules
together so they share the same "Time before idle".

In "Clock input" mode, the "Time Output" will correspond with the
"Time before idle" display until the time is over 10s, then the
"Time output" will max out at 10V.

##### Gate Output and idle start and end trigger outputs

Once the idle timeout has expired, the "gate output" output
will go high (+10V) and stay high until there are new input
source events. ie, it turns on when there is no actively for
the "Time before idle" length of time.

The "start out" output will send a +10V trigger at the start
of idle, at the start of the "gate out" gate.

The "end out" output will send a +10V trigger at the end of
idle, at the end of the "gate out" gate. This also corresponds
to the same time as when a new "Input source" event is detected.

"start of" trigger == "we have gone idle"
"end of" trigger == "we got input source events (activity) and am no
longer idle.

##### Switched input and output

The "Input" is switched between "When idle" and
"Off idle" outputs based on idle state.

The "Input" port on the bottom left can be any input.

The "Input" will be routed to the "When idle" output if idle.
Otherwise, the "Input" is routed to the "Off idle" output.

Note the "Input" does not have to be related to the input connected
to the "Input source". "Input source" typically needs to be triggers
or gates, but "Input" can be any signal.

#### Why

Original intentional was to use in combo with a human player and midi/cv keyboard.
As long as the human is playing, the IdleSwitch output is 'off', but if they go
idle for some time period the output is turned on. For example, a patch may plain
loud drone when idle, but would turn the drone off or down when the human played
and then turn it back on when it stopped. Or maybe it could be used to start an
drum fill...

The "Reset idle" input allows this be kind of synced to a clock, beat, or sequence.
In the dronevexample above, the drone would then only come back in on a beat.

And perhaps most importantly, it can be used to do almost random output and
make weird noises.

### ColorPanel

A CV controlled RGB/HSL color "blank" panel.

Supports selectable input ranges (0V to 10V or -5V to 5V) via right click context menu
The color input mode is also selectable via the context menu.

Module is resizable.

### BigMuteButton

A big mute button.

Use just before output to the audio interface module.

When clicked, will mute the output output. Will unmute on next
click.

Easier/quicker than adjusting mixer levels, or system volume, or finding
the tiny mute button on mixers.

### MomentaryOnButtons

A set of GUI buttons that send a +10V output while pressed.

## License

BSD 3-clause. See LICENSE.txt

+ 203
- 0
plugins/community/repos/Alikins/TODO.txt View File

@@ -0,0 +1,203 @@
plugin ideas:
- Mult with labels
- so I can route a distance output to mult and label
it as 'main seq gate output' to avoid tracing cables
- seq with start/stop/reset triggers (ie, one shot sequencer)
(or 'play', 'pause', 'go to begin')
- solve 'how do I run a sequence once?' FAQ
- event log
- visualization of past triggers/gates
- time series or sparkline-ish
- more or less a scope but without y values and
a very long time
- could do diff colors for gates/triggers
- or gates up and triggers down
- wide module
- multiple time view zooms
- 1x, 2x, 5x, 10, 20x, 50x, etc
- mostly for appearance or troubleshooting/debugging event stuff
- could evolve to supporting playing the the history back
- 1x speed or faster/slower
- scrubbing?
- multiple channels of events
- table module
- "an oscillator is a phasor and a table"
- phasor input (0.0 -> 1.0) or other scaled
- value output
- on step, read phasor value, look for a match
in the table, output the value
- ui
- just a scrollable list?
- columns
- phasor
- start range
- end range
- output value
- buttons to add delete entry
- load table from json in context menu
- uses:
- feed a sawtooth osc output into it to
create rudimentary wave table
- arbitrary quantizer
- building block
- fancy options
- entries that map a range of phasor input
values to a range of output values
- map ranges could be linear/log etc
- linear
- slope
- offset
- sub ranges could be cos/sine/exp/some distribution etc
- (similar to the old GIMP color gradient editor)
- likely could use gimp gradient (ggr) files as a type of table
- modulating the table offset or value amplitudes
- credits module
- widget that shows author, create/mod date, urls, license, other metainfo
- would save into vcv file as module json data
- use a rack_credits.json in ~/ or rack doc root to set the default
- list of author/credit metadata
- would get appended to if modified by new author
- how to only update on 'save' or 'save as' ?
- don't want to append on every autosave.vcv write
- track a single 'last_edit' to persist on every toJson
- then on load/fromJSON, add last_edit to author list
- if there is a way for plugin to distinquish a 'real save' vs
an 'autosave', then could use that.
- how to tell when a patch has been 'modified'?
- needed to avoid adding info on every save or autosave
- slightly klugey way:
- if plugin knows the patch it is in, could load patch .vcv/json
data and compare to 'previous'.
- chksum would be simplest
- but could do a smarter/deeper compare diving into the data
- uses:
- a patch with the module includes the author info
- if patch is shared (via patchstorage for ex), and modified
by a different author, the module json would include info
for the original author and modification author
- just as a display widget when sharing a screen capture
- concerns:
- could probably be better implemented as a feature of the core vcv serialization
- 'Equal and opposite'
- two eqs with 'opposite' settings and an effects loop in between
- before eq, after eq
- same bands and q's, but opposite gain
- ie, if 'before eq' boosts bass and treble by 10db and cuts mids by 12db
then the 'after eq' would cut bass and treble by 10db and boost mids by 12db
- an effects send and return in between
- munge audio signal, send it to effect (a distortion for ex) and unmunge on the way out
- the before/after transforms would automatically mirror each other
- otherwise pointless since it could be done with other modules
- other variations could exist for other reversible-ish transforms
- dont have to be perfect or lossless
- compress/expand
- bitcrush / 'bit extropalate' (is that a thing?)
- forward/reverse delay?
- pitch shift (probably most interesting, but
- transport gui module
- play/stop/pause/fast forward/reverse/record buttons
- gate and trig outputs for them
- just buttons, but with a explicit purpose
- uses
- generative patches that need a 'press play to start'
- specific values
- module with just text entrie fields for entering a float value
and an output for that value
- possibly with text widget in combo with a dial or inc/dec
buttons (spinbox widget)
- or 'click and drag to change value'
- up/down for small value
- left/right for multiplier (middle = 1x, left = 0..1.0x, right >1.0x multi)
- 'up and to the left' for fine grained adjustments
- fancy
- maybe automatically also show CV v/oct freq or note equiv
- maybe gate out and button to click to send value and gate output together
- Seq with per step gate length and rest length between steps
- 'rest' steps basically
- A cv 1v/oct display -> freq hz -> period secs -> bpm.
- ( could display v passed through and/or let you specify as text)
- CV out
- button to send gate
- basically a keyboard with text/entry widgets to let you specify
CV voltage/hz/period/note name
- other possible things to display/select
- midi note number
- # of steps from a root
- interval from a root ( third, flat fifth, etc)
- staff / note
- bpm (for a LFO or general nerdery)
- generic voltage quantizer
- based on 'table' module
- except input CV is 'rounded' to edge of maps
- see 'fancy options' for table module above
- 'Attached file' module.
- GUI file picker
- add base64 of file to data to store in plugin Json.
- Could be a list
- 'Maze Table'
- wave table, but with a maze
- instead of phasor indexing an array, would "index" into
a path along the maze graph
- could have breath first and depth first paths as options
- use DAG style mazes (one and only one path out, no loops or cycles)
- though cycles in maze could be analog for loops in waveform playback
- maybe something hilbert curve esque?
- scmhidtt trigger / pulse generator banks
- just ui to a set of SchmittTriggers
- each strip
- input
- attentuator for process()'ed value
- output trigger
- for generator strip
- trigger input
- knob/cv in/param for duration
- gate output
- Matrix clock
- N x N matrix
- each row defaults to a clock division
- each column defaults to clock multiply
- 0,0 defaults to 1x1 quarter note for tempo
- rows default to 1,2,3,4,6,8,12,16, division
- ditto for columns multi
- but row/columns mult/div could be changed to anything
- XY pad matrix mixer
- matrix mixer with a JL-Modules/kaosspad/reactor style XY pad
at each cross point
- 1,1 -> top output and right output
- 1,0 -> just top output
- -1,-1 -> inverted output to top and right output
- Matrix Mixer with multiple scenes that morph/interpolate
- more or less like Bidoo ACNE except values morph
between scenes insted of
- 2.5 dimension matrix / mixer
- 8x8 matrix but with an output at
each crossing point
- possibly with knob/param for output level
of each output
- maybe a per cross mute/solo
- Much like the movies, the first one was the best.
- Notes module with CV/trigger control and multiple messages
- like a plain notes module, but can react to input from
patch
- use case would be describing stages of a generative patch
- or for adding info to screencast videos
- Gate Divider
- like gate length, but instead of generating one gate, it
generates multiple gates that add up to gate length
- how to seperate?
- some fixed inbetween interval ("kerf")
- divide into on and off gates
- divide a 1s gate by 1 -> one .5s gate then a .5s 'rest'
(and vice versa / inverse 10 or 01)
- divide by 3 -> one .3333s gate, one .3333s rest, one .3333 gate
( ie, 101 or 010)
- divide by 4 -> .25 gate, .25 rest, .25 gate, .25rest
(1010, 0101)
- divide by 5 -> .20 on, .20 off, .20 on, .20 off, .20 on
(10101, 01010)
- kind of similar to Walsh codes
" Experimental Electronic Music Devices Employing Walsh Functions",
"BERNARD A. HUTCHINS, JR"
"JOURNAL OF THE AUDIO ENGINEERING SOCIETY, October 1973"
(https://pdfs.semanticscholar.org/6b9c/30f94551aaf05f077aa491f31b196898cd90.pdf)
- "Sequency" - theres a module name if I ever heard one.

+ 8
- 0
plugins/community/repos/Alikins/make.objects View File

@@ -0,0 +1,8 @@
ALL_OBJ= \
./src/alikins.o \
./src/BigMuteButton.o \
./src/ColorPanel.o \
./src/GateLength.o \
./src/IdleSwitch.o \
./src/MomentaryOnButtons.o \
./src/SpecificValue.o

+ 7
- 0
plugins/community/repos/Alikins/makefile.msvc View File

@@ -0,0 +1,7 @@
SLUG=Alikins

include ../../../../dep/yac/install_msvc.mk

include make.objects

include ../../../build_plugin.mk

+ 2006
- 0
plugins/community/repos/Alikins/res/BigMuteButton.svg
File diff suppressed because it is too large
View File


+ 3669
- 0
plugins/community/repos/Alikins/res/BigMuteButtonMute.svg
File diff suppressed because it is too large
View File


+ 2090
- 0
plugins/community/repos/Alikins/res/BigMuteButtonUnmute.svg
File diff suppressed because it is too large
View File


+ 1954
- 0
plugins/community/repos/Alikins/res/GateLength.svg
File diff suppressed because it is too large
View File


+ 3002
- 0
plugins/community/repos/Alikins/res/IdleSwitch.svg
File diff suppressed because it is too large
View File


+ 151
- 0
plugins/community/repos/Alikins/res/MomentaryOnButtons.svg View File

@@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="75"
height="380"
viewBox="0 0 19.843751 100.54167"
version="1.1"
id="svg8"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="MomentaryOnButtons.svg"
style="enable-background:new">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.6921053"
inkscape:cx="37.5"
inkscape:cy="190"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="false"
inkscape:snap-page="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:window-width="1440"
inkscape:window-height="856"
inkscape:window-x="11"
inkscape:window-y="2"
inkscape:window-maximized="0"
inkscape:measure-start="0,0"
inkscape:measure-end="0,0"
inkscape:snap-text-baseline="true"
inkscape:snap-nodes="false"
inkscape:snap-others="false"
inkscape:snap-grids="true" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-196.45832)"
style="opacity:0.81999966">
<path
style="opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
d="M 0,196.45831 H 15.875 V 296.99999 H 0 Z"
id="rect817"
inkscape:connector-curvature="0" />
<rect
style="fill:#99ff55;fill-opacity:0.36097562;stroke:#000000;stroke-width:0.22707526;stroke-miterlimit:4;stroke-dasharray:0, 2.49782804;stroke-dashoffset:0;stroke-opacity:0.00485439"
id="rect4596"
width="6.5781407"
height="96.39846"
x="6.7771721"
y="196.41748" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="2.0959258"
y="199.32983"
id="text4602"><tspan
sodipodi:role="line"
id="tspan4600"
x="2.0959258"
y="208.6936"
style="stroke-width:0.26458332" /></text>
<rect
style="opacity:1;fill:#e08976;fill-opacity:0.37931034;stroke:#000000;stroke-width:0.24057104;stroke-miterlimit:4;stroke-dasharray:0, 2.64628129;stroke-dashoffset:0;stroke-opacity:0"
id="rect4598"
width="5.266654"
height="96.089233"
x="1.639776"
y="196.67091" />
<g
aria-label="Momentary"
transform="matrix(0.76786881,0,0,1.3023058,0.9381804,0)"
style="font-style:normal;font-weight:normal;font-size:3.08836555px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#e08934;fill-opacity:0.97647059;stroke:none;stroke-width:0.07720914"
id="text4606">
<path
d="m 1.7166386,151.74845 h 0.4539053 l 0.5745445,1.53212 0.5775606,-1.53212 h 0.4539053 v 2.25143 H 3.47948 v -1.97698 l -0.5805765,1.54418 H 2.5927813 L 2.0122048,152.0229 v 1.97698 H 1.7166386 Z"
style="fill:#e08934;fill-opacity:0.97647059;stroke-width:0.07720914"
id="path4608"
inkscape:connector-curvature="0" />
<path
d="m 5.0251709,152.50546 q -0.2231827,0 -0.3528699,0.17493 -0.1296872,0.17341 -0.1296872,0.47652 0,0.30311 0.1281792,0.47803 0.1296872,0.17342 0.3543779,0.17342 0.2216747,0 0.3513619,-0.17492 0.1296872,-0.17493 0.1296872,-0.47653 0,-0.30009 -0.1296872,-0.47502 -0.1296872,-0.17643 -0.3513619,-0.17643 z m 0,-0.23525 q 0.3619178,0 0.5685126,0.23525 0.2065948,0.23525 0.2065948,0.65145 0,0.4147 -0.2065948,0.65145 -0.2065948,0.23525 -0.5685126,0.23525 -0.3634258,0 -0.5700206,-0.23525 -0.2050868,-0.23675 -0.2050868,-0.65145 0,-0.4162 0.2050868,-0.65145 0.2065948,-0.23525 0.5700206,-0.23525 z"
style="fill:#e08934;fill-opacity:0.97647059;stroke-width:0.07720914"
id="path4610"
inkscape:connector-curvature="0" />
<path
d="m 7.5736757,152.63515 q 0.1040514,-0.18699 0.2488185,-0.27597 0.1447672,-0.089 0.340806,-0.089 0.2638984,0 0.4071576,0.18549 0.1432591,0.18397 0.1432591,0.52478 v 1.0194 H 8.4347386 v -1.01036 q 0,-0.24278 -0.085955,-0.36041 -0.085956,-0.11762 -0.2623904,-0.11762 -0.2156428,0 -0.340806,0.14326 -0.1251633,0.14326 -0.1251633,0.39057 v 0.95456 H 7.3414451 v -1.01036 q 0,-0.24429 -0.085955,-0.36041 -0.085955,-0.11762 -0.2654064,-0.11762 -0.2126267,0 -0.33779,0.14477 -0.1251632,0.14326 -0.1251632,0.38906 v 0.95456 H 6.2481516 V 152.3109 H 6.52713 v 0.26239 q 0.095003,-0.15532 0.2277066,-0.22922 0.1327032,-0.0739 0.3151701,-0.0739 0.1839749,0 0.3121542,0.0935 0.1296872,0.0935 0.1915148,0.27144 z"
style="fill:#e08934;fill-opacity:0.97647059;stroke-width:0.07720914"
id="path4612"
inkscape:connector-curvature="0" />
<path
d="m 10.713313,153.08604 v 0.13571 H 9.4375527 q 0.018096,0.28652 0.171911,0.43732 0.1553231,0.14929 0.4312853,0.14929 0.159847,0 0.309138,-0.0392 0.150799,-0.0392 0.298582,-0.11763 v 0.26239 q -0.149291,0.0633 -0.306122,0.0965 -0.156831,0.0332 -0.318186,0.0332 -0.4041414,0 -0.6408959,-0.23525 -0.2352466,-0.23524 -0.2352466,-0.63637 0,-0.4147 0.2231826,-0.65748 0.2246907,-0.2443 0.6047044,-0.2443 0.3408055,0 0.5383525,0.22017 0.199055,0.21866 0.199055,0.59566 z m -0.27747,-0.0814 q -0.003,-0.2277 -0.128179,-0.36342 -0.123656,-0.13572 -0.3287425,-0.13572 -0.2322306,0 -0.3724738,0.13119 -0.1387352,0.1312 -0.159847,0.36946 z"
style="fill:#e08934;fill-opacity:0.97647059;stroke-width:0.07720914"
id="path4614"
inkscape:connector-curvature="0" />
<path
d="m 12.572666,152.98048 v 1.0194 h -0.277471 v -1.01036 q 0,-0.23977 -0.09349,-0.3589 -0.0935,-0.11913 -0.280486,-0.11913 -0.224691,0 -0.354378,0.14326 -0.129688,0.14326 -0.129688,0.39057 v 0.95456 H 11.15817 v -1.68895 h 0.278978 v 0.26239 q 0.09953,-0.15231 0.233739,-0.22771 0.135719,-0.0754 0.312154,-0.0754 0.291042,0 0.440334,0.18096 0.149291,0.17945 0.149291,0.52931 z"
style="fill:#e08934;fill-opacity:0.97647059;stroke-width:0.07720914"
id="path4616"
inkscape:connector-curvature="0" />
<path
d="m 13.403569,151.83139 v 0.47954 h 0.571528 v 0.21564 h -0.571528 v 0.91686 q 0,0.20659 0.0558,0.26541 0.0573,0.0588 0.230723,0.0588 h 0.28501 v 0.23223 h -0.28501 q -0.321202,0 -0.443349,-0.11913 -0.122148,-0.12064 -0.122148,-0.43732 v -0.91686 h -0.203579 v -0.21564 h 0.203579 v -0.47954 z"
style="fill:#e08934;fill-opacity:0.97647059;stroke-width:0.07720914"
id="path4618"
inkscape:connector-curvature="0" />
<path
d="m 15.109107,153.15088 q -0.336282,0 -0.465969,0.0769 -0.129688,0.0769 -0.129688,0.26239 0,0.14778 0.09651,0.23524 0.09802,0.086 0.265406,0.086 0.230723,0 0.369458,-0.16286 0.140243,-0.16437 0.140243,-0.43581 v -0.0618 z m 0.553433,-0.11461 v 0.96361 h -0.277471 v -0.25636 q -0.095,0.15381 -0.236754,0.22771 -0.141752,0.0724 -0.346838,0.0724 -0.259375,0 -0.41319,-0.14477 -0.152307,-0.14627 -0.152307,-0.39057 0,-0.28501 0.190007,-0.42977 0.191515,-0.14477 0.570021,-0.14477 h 0.389061 v -0.0272 q 0,-0.19151 -0.126671,-0.29556 -0.125163,-0.10556 -0.35287,-0.10556 -0.144767,0 -0.281994,0.0347 -0.137227,0.0347 -0.263899,0.10405 v -0.25635 q 0.152307,-0.0588 0.295567,-0.0875 0.143259,-0.0302 0.278978,-0.0302 0.366442,0 0.547401,0.19001 0.180959,0.19001 0.180959,0.57605 z"
style="fill:#e08934;fill-opacity:0.97647059;stroke-width:0.07720914"
id="path4620"
inkscape:connector-curvature="0" />
<path
d="m 17.214262,152.5703 q -0.04675,-0.0271 -0.102544,-0.0392 -0.05429,-0.0136 -0.120639,-0.0136 -0.235246,0 -0.361918,0.15382 -0.125163,0.1523 -0.125163,0.43882 v 0.88972 H 16.22502 v -1.68895 h 0.278978 v 0.26239 q 0.08746,-0.15382 0.227707,-0.22771 0.140243,-0.0754 0.340806,-0.0754 0.02865,0 0.06334,0.005 0.03468,0.003 0.07691,0.0105 z"
style="fill:#e08934;fill-opacity:0.97647059;stroke-width:0.07720914"
id="path4622"
inkscape:connector-curvature="0" />
<path
d="m 18.211044,154.15671 q -0.117624,0.3016 -0.229215,0.39358 -0.111591,0.092 -0.298582,0.092 h -0.221675 v -0.23223 h 0.162863 q 0.114608,0 0.177943,-0.0543 0.06334,-0.0543 0.140243,-0.25635 l 0.04976,-0.12668 -0.68312,-1.6618 h 0.294058 l 0.527797,1.321 0.527797,-1.321 h 0.294058 z"
style="fill:#e08934;fill-opacity:0.97647059;stroke-width:0.07720914"
id="path4624"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

+ 99
- 0
plugins/community/repos/Alikins/res/PurpleTrimpot.svg View File

@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg1383"
version="1.1"
viewBox="0 0 13.758334 13.758334"
height="52"
width="52"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="PurpleTrimpot.svg">
<sodipodi:namedview
inkscape:window-maximized="0"
inkscape:window-y="4"
inkscape:window-x="-9"
inkscape:window-height="851"
inkscape:window-width="1440"
units="px"
showgrid="false"
inkscape:current-layer="layer1"
inkscape:document-units="px"
inkscape:cy="32.696773"
inkscape:cx="-11.691577"
inkscape:zoom="6.6458333"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base" />
<defs
id="defs1377" />
<metadata
id="metadata1380">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-283.24164)"
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1"
style="display:inline">
<g
id="g3842"
transform="matrix(1.0833334,0,0,1.0833334,1.3314724e-8,-24.750039)">
<circle
style="opacity:0.86499999;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.28937858;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:54.20000076;stroke-opacity:0.83009709"
id="path1928"
cx="6.3499999"
cy="290.64999"
r="6.3499999" />
<rect
y="0.67853534"
x="5.7470388"
height="5.1807055"
width="1.2059226"
id="rect2030"
style="display:inline;opacity:0.86499999;fill:#cf57ff;fill-opacity:1;fill-rule:evenodd;stroke:#351313;stroke-width:0.05291667;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:54.20000076;stroke-opacity:0.98173517"
transform="translate(0,284.29998)" />
</g>
</g>
<g
transform="translate(6.35,7.4083334)"
inkscape:label="Gear16"
id="g1991"
style="display:none">
<path
d="m 4.68617,-0.53218 0.34647,-0.03934 0.33145,0.0432 0.69557,0.30411 V 0.22421 L 5.36409,0.52832 5.03264,0.57152 4.68617,0.53218 4.53311,1.30165 4.86827,1.39789 5.15795,1.56465 5.68419,2.11179 5.51259,2.52607 4.7536,2.54085 4.43084,2.45393 4.1258,2.28499 3.68993,2.93732 3.96274,3.15448 4.16656,3.41941 4.44336,4.12628 4.12628,4.44336 3.41941,4.16656 3.15448,3.96274 2.93732,3.68993 2.28499,4.1258 2.45393,4.43084 2.54085,4.7536 2.52607,5.51259 2.11179,5.68419 1.56465,5.15795 1.39789,4.86827 1.30165,4.53311 0.53218,4.68617 0.57152,5.03264 0.52832,5.36409 0.22421,6.05966 H -0.22421 L -0.52832,5.36409 -0.57152,5.03264 -0.53218,4.68617 -1.30165,4.53311 -1.39789,4.86827 -1.56465,5.15795 -2.11179,5.68419 -2.52607,5.51259 -2.54085,4.7536 -2.45393,4.43084 -2.28499,4.1258 -2.93732,3.68993 -3.15448,3.96274 -3.41941,4.16656 -4.12628,4.44336 -4.44336,4.12628 -4.16656,3.41941 -3.96274,3.15448 -3.68993,2.93732 -4.1258,2.28499 -4.43084,2.45393 -4.7536,2.54085 -5.51259,2.52607 -5.68419,2.11179 -5.15795,1.56465 -4.86827,1.39789 -4.53311,1.30165 -4.68617,0.53218 -5.03264,0.57152 -5.36409,0.52832 -6.05966,0.22421 v -0.44842 l 0.69557,-0.30411 0.33145,-0.0432 0.34647,0.03934 0.15306,-0.76947 -0.33516,-0.09624 -0.28968,-0.16676 -0.52624,-0.54714 0.1716,-0.41428 0.75899,-0.01478 0.32276,0.08692 0.30504,0.16894 0.43587,-0.65233 -0.27281,-0.21716 -0.20382,-0.26493 -0.2768,-0.70687 0.31708,-0.31708 0.70687,0.2768 0.26493,0.20382 0.21716,0.27281 0.65233,-0.43587 -0.16894,-0.30504 -0.08692,-0.32276 0.01478,-0.75899 0.41428,-0.1716 0.54714,0.52624 0.16676,0.28968 0.09624,0.33516 0.76947,-0.15306 -0.03934,-0.34647 0.0432,-0.33145 0.30411,-0.69557 h 0.44842 l 0.30411,0.69557 0.0432,0.33145 -0.03934,0.34647 0.76947,0.15306 0.09624,-0.33516 0.16676,-0.28968 0.54714,-0.52624 0.41428,0.1716 0.01478,0.75899 -0.08692,0.32276 -0.16894,0.30504 0.65233,0.43587 0.21716,-0.27281 0.26493,-0.20382 0.70687,-0.2768 0.31708,0.31708 -0.2768,0.70687 -0.20382,0.26493 -0.27281,0.21716 0.43587,0.65233 0.30504,-0.16894 0.32276,-0.08692 0.75899,0.01478 0.1716,0.41428 -0.52624,0.54714 -0.28968,0.16676 -0.33516,0.09624 z"
style="fill:none;stroke:#000000;stroke-width:0.26458332"
id="path1989"
inkscape:connector-curvature="0" />
</g>
<g
id="g2015"
inkscape:label="Gear16"
transform="rotate(-164.64789,3.6742468,3.2762409)"
style="display:none">
<path
id="path2013"
style="fill:none;stroke:#000000;stroke-width:0.26458332"
d="m 4.4731195,-1.4948601 0.3307196,-0.1105155 0.3331888,-0.026656 0.7435981,0.1528474 0.093232,0.4386209 -0.6171421,0.44208162 -0.3152253,0.11116831 -0.347078,0.0335548 0.010267,0.7844782 L 5.0525243,0.3551725 5.3705454,0.45806054 5.9990426,0.88383277 5.9173262,1.3247374 5.1779949,1.4969973 4.8442163,1.4790823 4.5107175,1.3772554 4.2199993,2.1059529 4.5319979,2.2616471 4.786446,2.4784112 5.2041638,3.1122844 4.9599374,3.4883601 4.2109642,3.3645754 3.909447,3.2202914 3.6403121,2.998593 3.0928595,3.5605652 3.3215292,3.8238148 3.4736553,4.12145 3.6170012,4.8669272 3.2474519,5.120911 2.6028567,4.7199274 2.379513,4.4712489 2.2156924,4.1634224 1.4948601,4.4731195 1.6053756,4.8038391 1.632032,5.1370279 1.4791846,5.880626 1.0405637,5.9738578 0.59848208,5.3567157 0.48731377,5.0414904 0.45375894,4.6944124 -0.33071926,4.7046789 -0.3551725,5.0525243 -0.45806054,5.3705454 -0.88383277,5.9990426 -1.3247374,5.9173262 -1.4969973,5.1779949 -1.4790823,4.8442163 -1.3772554,4.5107175 -2.1059529,4.2199993 -2.2616471,4.5319979 -2.4784112,4.786446 -3.1122844,5.2041638 -3.4883601,4.9599374 -3.3645754,4.2109642 -3.2202914,3.909447 -2.998593,3.6403121 -3.5605652,3.0928595 -3.8238148,3.3215292 -4.12145,3.4736553 -4.8669272,3.6170012 -5.120911,3.2474519 -4.7199274,2.6028567 -4.4712489,2.379513 -4.1634224,2.2156924 -4.4731195,1.4948601 -4.8038391,1.6053756 -5.1370279,1.632032 -5.880626,1.4791846 -5.973858,1.0405637 l 0.6171421,-0.44208162 0.3152253,-0.11116831 0.347078,-0.0335548 -0.010267,-0.7844782 -0.3478454,-0.0244532 -0.3180211,-0.10288804 -0.6284972,-0.42577223 0.081716,-0.4409046 0.7393313,-0.1722599 0.3337786,0.017915 0.3334988,0.1018269 0.2907182,-0.7286975 -0.3119986,-0.1556942 -0.2544481,-0.2167641 -0.4177178,-0.6338732 0.2442264,-0.3760757 0.7489732,0.1237847 0.3015172,0.144284 0.2691349,0.2216984 0.5474526,-0.5619722 -0.2286697,-0.2632496 -0.1521261,-0.2976352 -0.1433459,-0.7454772 0.3695493,-0.2539838 0.6445952,0.4009836 0.2233437,0.2486785 0.1638206,0.3078265 0.7208323,-0.3096971 -0.1105155,-0.3307196 -0.026656,-0.3331888 0.1528474,-0.7435981 0.4386209,-0.093232 0.44208162,0.6171421 0.11116831,0.3152253 0.0335548,0.347078 0.7844782,-0.010267 0.0244532,-0.3478454 0.10288804,-0.3180211 0.42577223,-0.6284972 0.4409046,0.081716 0.1722599,0.7393313 -0.017915,0.3337786 -0.1018269,0.3334988 0.7286975,0.2907182 0.155695,-0.3119976 L 2.4784112,-4.786446 3.1122844,-5.2041638 3.4883601,-4.9599374 3.3645754,-4.2109642 3.2202914,-3.909447 2.998593,-3.6403121 3.5605652,-3.0928595 3.8238148,-3.3215292 4.12145,-3.4736553 4.8669272,-3.6170012 5.120911,-3.2474519 4.7199274,-2.6028567 4.4712489,-2.379513 4.1634224,-2.2156924 Z"
inkscape:connector-curvature="0" />
</g>
</svg>

BIN
plugins/community/repos/Alikins/res/Segment7Standard.ttf View File


+ 94
- 0
plugins/community/repos/Alikins/res/SmallPurpleTrimpot.svg View File

@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg1383"
version="1.1"
viewBox="0 0 4.7624999 4.7624999"
height="18"
width="18"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="SmallPurpleTrimpot.svg">
<sodipodi:namedview
inkscape:window-maximized="0"
inkscape:window-y="0"
inkscape:window-x="7"
inkscape:window-height="851"
inkscape:window-width="1440"
units="px"
showgrid="false"
inkscape:current-layer="layer1"
inkscape:document-units="px"
inkscape:cy="32.696773"
inkscape:cx="15.994944"
inkscape:zoom="6.6458333"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base" />
<defs
id="defs1377" />
<metadata
id="metadata1380">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-292.23748)"
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1"
style="display:inline">
<circle
r="2.3812499"
cy="294.61871"
cx="2.3812499"
id="path1928"
style="opacity:0.86499999;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10851697;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:54.20000076;stroke-opacity:0.83009709" />
<rect
style="display:inline;opacity:0.86499999;fill:#cf57ff;fill-opacity:1;fill-rule:evenodd;stroke:#351313;stroke-width:0.01984375;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:54.20000076;stroke-opacity:0.98173517"
id="rect2030"
width="0.45222098"
height="1.9427645"
x="2.1551394"
y="292.49191" />
</g>
<g
transform="translate(6.35,-1.5875)"
inkscape:label="Gear16"
id="g1991"
style="display:none">
<path
d="m 4.68617,-0.53218 0.34647,-0.03934 0.33145,0.0432 0.69557,0.30411 V 0.22421 L 5.36409,0.52832 5.03264,0.57152 4.68617,0.53218 4.53311,1.30165 4.86827,1.39789 5.15795,1.56465 5.68419,2.11179 5.51259,2.52607 4.7536,2.54085 4.43084,2.45393 4.1258,2.28499 3.68993,2.93732 3.96274,3.15448 4.16656,3.41941 4.44336,4.12628 4.12628,4.44336 3.41941,4.16656 3.15448,3.96274 2.93732,3.68993 2.28499,4.1258 2.45393,4.43084 2.54085,4.7536 2.52607,5.51259 2.11179,5.68419 1.56465,5.15795 1.39789,4.86827 1.30165,4.53311 0.53218,4.68617 0.57152,5.03264 0.52832,5.36409 0.22421,6.05966 H -0.22421 L -0.52832,5.36409 -0.57152,5.03264 -0.53218,4.68617 -1.30165,4.53311 -1.39789,4.86827 -1.56465,5.15795 -2.11179,5.68419 -2.52607,5.51259 -2.54085,4.7536 -2.45393,4.43084 -2.28499,4.1258 -2.93732,3.68993 -3.15448,3.96274 -3.41941,4.16656 -4.12628,4.44336 -4.44336,4.12628 -4.16656,3.41941 -3.96274,3.15448 -3.68993,2.93732 -4.1258,2.28499 -4.43084,2.45393 -4.7536,2.54085 -5.51259,2.52607 -5.68419,2.11179 -5.15795,1.56465 -4.86827,1.39789 -4.53311,1.30165 -4.68617,0.53218 -5.03264,0.57152 -5.36409,0.52832 -6.05966,0.22421 v -0.44842 l 0.69557,-0.30411 0.33145,-0.0432 0.34647,0.03934 0.15306,-0.76947 -0.33516,-0.09624 -0.28968,-0.16676 -0.52624,-0.54714 0.1716,-0.41428 0.75899,-0.01478 0.32276,0.08692 0.30504,0.16894 0.43587,-0.65233 -0.27281,-0.21716 -0.20382,-0.26493 -0.2768,-0.70687 0.31708,-0.31708 0.70687,0.2768 0.26493,0.20382 0.21716,0.27281 0.65233,-0.43587 -0.16894,-0.30504 -0.08692,-0.32276 0.01478,-0.75899 0.41428,-0.1716 0.54714,0.52624 0.16676,0.28968 0.09624,0.33516 0.76947,-0.15306 -0.03934,-0.34647 0.0432,-0.33145 0.30411,-0.69557 h 0.44842 l 0.30411,0.69557 0.0432,0.33145 -0.03934,0.34647 0.76947,0.15306 0.09624,-0.33516 0.16676,-0.28968 0.54714,-0.52624 0.41428,0.1716 0.01478,0.75899 -0.08692,0.32276 -0.16894,0.30504 0.65233,0.43587 0.21716,-0.27281 0.26493,-0.20382 0.70687,-0.2768 0.31708,0.31708 -0.2768,0.70687 -0.20382,0.26493 -0.27281,0.21716 0.43587,0.65233 0.30504,-0.16894 0.32276,-0.08692 0.75899,0.01478 0.1716,0.41428 -0.52624,0.54714 -0.28968,0.16676 -0.33516,0.09624 z"
style="fill:none;stroke:#000000;stroke-width:0.26458332"
id="path1989"
inkscape:connector-curvature="0" />
</g>
<g
id="g2015"
inkscape:label="Gear16"
transform="rotate(-164.64789,3.0680186,-1.2216757)"
style="display:none">
<path
id="path2013"
style="fill:none;stroke:#000000;stroke-width:0.26458332"
d="m 4.4731195,-1.4948601 0.3307196,-0.1105155 0.3331888,-0.026656 0.7435981,0.1528474 0.093232,0.4386209 -0.6171421,0.44208162 -0.3152253,0.11116831 -0.347078,0.0335548 0.010267,0.7844782 L 5.0525243,0.3551725 5.3705454,0.45806054 5.9990426,0.88383277 5.9173262,1.3247374 5.1779949,1.4969973 4.8442163,1.4790823 4.5107175,1.3772554 4.2199993,2.1059529 4.5319979,2.2616471 4.786446,2.4784112 5.2041638,3.1122844 4.9599374,3.4883601 4.2109642,3.3645754 3.909447,3.2202914 3.6403121,2.998593 3.0928595,3.5605652 3.3215292,3.8238148 3.4736553,4.12145 3.6170012,4.8669272 3.2474519,5.120911 2.6028567,4.7199274 2.379513,4.4712489 2.2156924,4.1634224 1.4948601,4.4731195 1.6053756,4.8038391 1.632032,5.1370279 1.4791846,5.880626 1.0405637,5.9738578 0.59848208,5.3567157 0.48731377,5.0414904 0.45375894,4.6944124 -0.33071926,4.7046789 -0.3551725,5.0525243 -0.45806054,5.3705454 -0.88383277,5.9990426 -1.3247374,5.9173262 -1.4969973,5.1779949 -1.4790823,4.8442163 -1.3772554,4.5107175 -2.1059529,4.2199993 -2.2616471,4.5319979 -2.4784112,4.786446 -3.1122844,5.2041638 -3.4883601,4.9599374 -3.3645754,4.2109642 -3.2202914,3.909447 -2.998593,3.6403121 -3.5605652,3.0928595 -3.8238148,3.3215292 -4.12145,3.4736553 -4.8669272,3.6170012 -5.120911,3.2474519 -4.7199274,2.6028567 -4.4712489,2.379513 -4.1634224,2.2156924 -4.4731195,1.4948601 -4.8038391,1.6053756 -5.1370279,1.632032 -5.880626,1.4791846 -5.973858,1.0405637 l 0.6171421,-0.44208162 0.3152253,-0.11116831 0.347078,-0.0335548 -0.010267,-0.7844782 -0.3478454,-0.0244532 -0.3180211,-0.10288804 -0.6284972,-0.42577223 0.081716,-0.4409046 0.7393313,-0.1722599 0.3337786,0.017915 0.3334988,0.1018269 0.2907182,-0.7286975 -0.3119986,-0.1556942 -0.2544481,-0.2167641 -0.4177178,-0.6338732 0.2442264,-0.3760757 0.7489732,0.1237847 0.3015172,0.144284 0.2691349,0.2216984 0.5474526,-0.5619722 -0.2286697,-0.2632496 -0.1521261,-0.2976352 -0.1433459,-0.7454772 0.3695493,-0.2539838 0.6445952,0.4009836 0.2233437,0.2486785 0.1638206,0.3078265 0.7208323,-0.3096971 -0.1105155,-0.3307196 -0.026656,-0.3331888 0.1528474,-0.7435981 0.4386209,-0.093232 0.44208162,0.6171421 0.11116831,0.3152253 0.0335548,0.347078 0.7844782,-0.010267 0.0244532,-0.3478454 0.10288804,-0.3180211 0.42577223,-0.6284972 0.4409046,0.081716 0.1722599,0.7393313 -0.017915,0.3337786 -0.1018269,0.3334988 0.7286975,0.2907182 0.155695,-0.3119976 L 2.4784112,-4.786446 3.1122844,-5.2041638 3.4883601,-4.9599374 3.3645754,-4.2109642 3.2202914,-3.909447 2.998593,-3.6403121 3.5605652,-3.0928595 3.8238148,-3.3215292 4.12145,-3.4736553 4.8669272,-3.6170012 5.120911,-3.2474519 4.7199274,-2.6028567 4.4712489,-2.379513 4.1634224,-2.2156924 Z"
inkscape:connector-curvature="0" />
</g>
</svg>

+ 2458
- 0
plugins/community/repos/Alikins/res/SpecificValue.svg
File diff suppressed because it is too large
View File


BIN
plugins/community/repos/Alikins/screenshots/modules.png View File

Before After
Width: 1742  |  Height: 766  |  Size: 360KB

+ 167
- 0
plugins/community/repos/Alikins/src/BigMuteButton.cpp View File

@@ -0,0 +1,167 @@
#include "alikins.hpp"

#include "dsp/digital.hpp"

namespace rack_plugin_Alikins {

struct BigMuteButton : Module {
enum ParamIds {
BIG_MUTE_BUTTON_PARAM,
NUM_PARAMS
};
enum InputIds {
LEFT_INPUT,
RIGHT_INPUT,
NUM_INPUTS
};
enum OutputIds {
LEFT_OUTPUT,
RIGHT_OUTPUT,
NUM_OUTPUTS
};
enum LightIds {
NUM_LIGHTS
};

float gain_mult = 1.0f;

enum FadeState {
UNMUTED_STEADY,
MUTED_STEADY,
MUTED_FADE_DOWN,
UNMUTED_FADE_UP,
INITIAL
};

// FadeState state = UNMUTED_STEADY;
FadeState state = INITIAL;
SchmittTrigger muteOnTrigger;
SchmittTrigger muteOffTrigger;

float gmult2 = 1.0f;

float crossfade_mix = 0.005f;

BigMuteButton() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
void step() override;

void onReset() override {
state = UNMUTED_STEADY;
}

};

void BigMuteButton::step() {

// INITIAL state, choose next state based on current value of BIG_MUTE_BUTTON_PARAM
// since BIG_MUTE_BUTTON_PARAM should be based on either the default, or for a saved
// patch, the value saved to the params JSON.

if (muteOnTrigger.process(params[BIG_MUTE_BUTTON_PARAM].value)) {
// debug("MUTE ON");
state = MUTED_FADE_DOWN;
gmult2 = 1.0f;
}

if (muteOffTrigger.process(!params[BIG_MUTE_BUTTON_PARAM].value)) {
// debug("MUTE OFF");
state = UNMUTED_FADE_UP;
gmult2 = 0.0f;
}

switch(state) {
case INITIAL:
state = (params[BIG_MUTE_BUTTON_PARAM].value == 0.0f) ? UNMUTED_STEADY : MUTED_STEADY;
break;
case MUTED_STEADY:
gmult2 = 0.0f;
break;
case UNMUTED_STEADY:
gmult2 = 1.0f;
break;
case MUTED_FADE_DOWN:
if (isNear(gmult2, 0.0f)) {
state = MUTED_STEADY;
// debug("faded down crossfade to 0.0");
gmult2 = 0.0f;
break;
}
gmult2 = crossfade(gmult2, 0.0f, crossfade_mix);
break;
case UNMUTED_FADE_UP:
if (isNear(gmult2, 1.0f)) {
state = UNMUTED_STEADY;
// debug("faded up crossfade to 1.0");
gmult2 = 1.0f;
break;
}
gmult2 = crossfade(gmult2, 1.0f, crossfade_mix);
break;
}

gmult2 = clamp(gmult2, 0.0f, 1.0f);

outputs[LEFT_OUTPUT].value = inputs[LEFT_INPUT].value * gmult2;
outputs[RIGHT_OUTPUT].value = inputs[RIGHT_INPUT].value * gmult2;

// debug("state: %d, gmult2: %f", state, gmult2);

// TODO: to eliminate worse case DC thump, also apply a RC filter of some sort?
}

struct BigSwitch : SVGSwitch, ToggleSwitch {
BigSwitch() {
addFrame(SVG::load(assetPlugin(plugin, "res/BigMuteButtonMute.svg")));
addFrame(SVG::load(assetPlugin(plugin, "res/BigMuteButtonUnmute.svg")));
}
};


struct BigMuteButtonWidget : ModuleWidget {
BigMuteButtonWidget(BigMuteButton *module);
};


BigMuteButtonWidget::BigMuteButtonWidget(BigMuteButton *module) : ModuleWidget(module) {

box.size = Vec(6 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
setPanel(SVG::load(assetPlugin(plugin, "res/BigMuteButton.svg")));

addParam(ParamWidget::create<BigSwitch>(Vec(0.0f, 0.0f),
module,
BigMuteButton::BIG_MUTE_BUTTON_PARAM,
0.0f, 1.0f, 0.0f));

addInput(Port::create<PJ301MPort>(Vec(4.0f, 302.0f),
Port::INPUT,
module,
BigMuteButton::LEFT_INPUT));
addInput(Port::create<PJ301MPort>(Vec(4.0f, 330.0f),
Port::INPUT,
module,
BigMuteButton::RIGHT_INPUT));

addOutput(Port::create<PJ301MPort>(Vec(60.0f, 302.0f),
Port::OUTPUT,
module,
BigMuteButton::LEFT_OUTPUT));
addOutput(Port::create<PJ301MPort>(Vec(60.0f, 330.0f),
Port::OUTPUT,
module,
BigMuteButton::RIGHT_OUTPUT));

addChild(Widget::create<ScrewSilver>(Vec(0.0, 0)));
addChild(Widget::create<ScrewSilver>(Vec(box.size.x-15, 0)));
addChild(Widget::create<ScrewSilver>(Vec(30, 365)));

}

} // namespace rack_plugin_Alikins

using namespace rack_plugin_Alikins;

RACK_PLUGIN_MODEL_INIT(Alikins, BigMuteButton) {
Model *modelBigMuteButton = Model::create<BigMuteButton, BigMuteButtonWidget>(
"Alikins", "BigMuteButton", "Big Mute Button", UTILITY_TAG);
return modelBigMuteButton;
}

+ 359
- 0
plugins/community/repos/Alikins/src/ColorPanel.cpp View File

@@ -0,0 +1,359 @@
#include "global_pre.hpp"
#include "alikins.hpp"
#include "util/math.hpp"
#include "global_ui.hpp"

namespace rack_plugin_Alikins {

struct ColorPanel : Module {
enum ParamIds {
RED_PARAM,
GREEN_PARAM,
BLUE_PARAM,
NUM_PARAMS
};
enum InputIds {
RED_INPUT,
GREEN_INPUT,
BLUE_INPUT,
NUM_INPUTS
};
enum OutputIds {
NUM_OUTPUTS
};
enum LightIds {
NUM_LIGHTS
};

float red = 0.0f;
float green = 0.0f;
float blue = 0.0f;

enum InputRange {
ZERO_TEN,
MINUS_PLUS_FIVE
};

InputRange inputRange = MINUS_PLUS_FIVE;
const float in_min[2] = {0.0, -5.0};
const float in_max[2] = {10.0, 5.0};

enum ColorMode {
RGB_MODE,
HSL_MODE,
};

ColorMode colorMode = HSL_MODE;

ColorPanel() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
void step() override;

json_t *toJson() override;
void fromJson(json_t *rootJ) override;

};

json_t* ColorPanel::toJson() {
json_t *rootJ = json_object();

json_object_set_new(rootJ, "inputRange", json_integer(inputRange));
json_object_set_new(rootJ, "colorMode", json_integer(colorMode));

return rootJ;
}

void ColorPanel::fromJson(json_t *rootJ) {
json_t *inputRangeJ = json_object_get(rootJ, "inputRange");
if (inputRangeJ) {
inputRange = (InputRange) json_integer_value(inputRangeJ);
}

json_t *colorModeJ = json_object_get(rootJ, "colorMode");
if (colorModeJ) {
colorMode = (ColorMode) json_integer_value(colorModeJ);
}

}


void ColorPanel::step() {
if (inputs[RED_INPUT].active) {
float in_value = clamp(inputs[RED_INPUT].value, in_min[inputRange], in_max[inputRange]);
red = rescale(in_value, in_min[inputRange], in_max[inputRange], 0.0f, 1.0f);
}
if (inputs[GREEN_INPUT].active) {
float in_value = clamp(inputs[GREEN_INPUT].value, in_min[inputRange], in_max[inputRange]);
green = rescale(in_value, in_min[inputRange], in_max[inputRange], 0.0f, 1.0f);
}
if (inputs[BLUE_INPUT].active) {
float in_value = clamp(inputs[BLUE_INPUT].value, in_min[inputRange], in_max[inputRange]);
blue = rescale(in_value, in_min[inputRange], in_max[inputRange], 0.0f, 1.0f);
}
}

// From Rack/src/core/Blank.cpp
struct ColorPanelModuleResizeHandle : Widget {
bool right = false;
float dragX;
Rect originalBox;

ColorPanelModuleResizeHandle() {
box.size = Vec(RACK_GRID_WIDTH * 1, RACK_GRID_HEIGHT);
dragX = 0.0f;
}

void onMouseDown(EventMouseDown &e) override {
if (e.button == 0) {
e.consumed = true;
e.target = this;
}
}

void onDragStart(EventDragStart &e) override {
dragX = rack::global_ui->app.gRackWidget->lastMousePos.x;
ModuleWidget *m = getAncestorOfType<ModuleWidget>();
originalBox = m->box;
}

void onDragMove(EventDragMove &e) override {
ModuleWidget *m = getAncestorOfType<ModuleWidget>();

float newDragX = rack::global_ui->app.gRackWidget->lastMousePos.x;
float deltaX = newDragX - dragX;

Rect newBox = originalBox;

const float minWidth = 6 * RACK_GRID_WIDTH;

if (right) {
newBox.size.x += deltaX;
newBox.size.x = fmaxf(newBox.size.x, minWidth);
newBox.size.x = roundf(newBox.size.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
} else {
newBox.size.x -= deltaX;
newBox.size.x = fmaxf(newBox.size.x, minWidth);
newBox.size.x = roundf(newBox.size.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
newBox.pos.x = originalBox.pos.x + originalBox.size.x - newBox.size.x;
}
rack::global_ui->app.gRackWidget->requestModuleBox(m, newBox);
}
};



struct ColorFrame : TransparentWidget {

ColorPanel *module;
ColorPanel::ColorMode colorMode;

// std::vector<CreditData*> vcredits;
float red = 0.5f;
float green = 0.5f;
float blue = 0.5f;

ColorFrame() {
}

void step() override {
Widget::step();
red = module->red;
green = module->green;
blue = module->blue;
colorMode = module->colorMode;
}

void draw(NVGcontext *vg) override {
// FIXME: not really red, green, blue anymore
// could include alpha
// debug("RgbPanel.draw red=%f, green=%f, blue=%f", red, green, blue);
NVGcolor panelColor = nvgRGBf(red, green, blue);
if (module->colorMode == ColorPanel::HSL_MODE) {
panelColor = nvgHSL(red, green, blue);
}

nvgBeginPath(vg);

nvgRect(vg, 0.0, 0.0, box.size.x, box.size.y);
nvgFillColor(vg, panelColor);
nvgFill(vg);
}
};


struct ColorPanelWidget : ModuleWidget {
ColorPanelWidget(ColorPanel *module);
Widget *rightHandle;
ColorFrame *panel;

Menu *createContextMenu() override;

void step() override;

json_t *toJson() override;
void fromJson(json_t *rootJ) override;
};


ColorPanelWidget::ColorPanelWidget(ColorPanel *module) : ModuleWidget(module) {
box.size = Vec(6 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);

{
panel = new ColorFrame();
panel->box.size = box.size;
panel->module = module;
addChild(panel);
}

ColorPanelModuleResizeHandle *leftHandle = new ColorPanelModuleResizeHandle();
ColorPanelModuleResizeHandle *rightHandle = new ColorPanelModuleResizeHandle();
rightHandle->right = true;
this->rightHandle = rightHandle;
addChild(leftHandle);
addChild(rightHandle);

/*
addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
topRightScrew = Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0));
bottomRightScrew = Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365));
addChild(topRightScrew);
addChild(bottomRightScrew);
*/

debug("box.size (%f, %f)", box.size.x, box.size.y);

//debug("port box.size %f %f", Port::PJ301MPort.box.size.x, PJ301MPort.box.size.y);
// this type of port is 24.672108 x 24.672136 by default
// FIXME: how do I figure that out before creating the instance?i
float port_width = 24.672108f;
float empty_space = box.size.x - (3.0f * port_width);
float interstitial = empty_space / 5.0f;

float x_pos = interstitial;
addInput(Port::create<PJ301MPort>(Vec(x_pos, 340.0f),
Port::INPUT,
module,
ColorPanel::RED_INPUT));

x_pos = x_pos + interstitial + port_width;;
addInput(Port::create<PJ301MPort>(Vec(x_pos, 340.0f),
Port::INPUT,
module,
ColorPanel::GREEN_INPUT));

x_pos = x_pos + interstitial + port_width;;
addInput(Port::create<PJ301MPort>(Vec(x_pos, 340.0f),
Port::INPUT,
module,
ColorPanel::BLUE_INPUT));
}

void ColorPanelWidget::step() {
panel->box.size = box.size;
rightHandle->box.pos.x = box.size.x - rightHandle->box.size.x;

// debug("box.size (%f, %f)", box.size.x, box.size.y);
ModuleWidget::step();
}

json_t *ColorPanelWidget::toJson() {
json_t *rootJ = ModuleWidget::toJson();
json_object_set_new(rootJ, "width", json_real(box.size.x));
return rootJ;
}

void ColorPanelWidget::fromJson(json_t *rootJ) {
ModuleWidget::fromJson(rootJ);
json_t *widthJ = json_object_get(rootJ, "width");
if (widthJ)
box.size.x = json_number_value(widthJ);
}


struct ColorModeItem : MenuItem {

ColorPanel *colorPanel;
ColorPanel::ColorMode colorMode;

void onAction(EventAction &e) override {
colorPanel->colorMode = colorMode;
};

void step() override {
rightText = (colorPanel->colorMode == colorMode)? "âś”" : "";
};

};



struct InputRangeItem : MenuItem {
ColorPanel *colorPanel;
ColorPanel::InputRange inputRange;

void onAction(EventAction &e) override {
colorPanel->inputRange = inputRange;
};

void step() override {
rightText = (colorPanel->inputRange == inputRange)? "âś”" : "";
};

};

Menu *ColorPanelWidget::createContextMenu() {

Menu *menu = ModuleWidget::createContextMenu();

MenuLabel *spacerLabel = new MenuLabel();
menu->addChild(spacerLabel);

ColorPanel *colorPanel = dynamic_cast<ColorPanel*>(module);
assert(colorPanel);

MenuLabel *colorModeLabel = new MenuLabel();
colorModeLabel->text = "ColorMode";
menu->addChild(colorModeLabel);

// FIXME: colorModeItem looks too much like colorModelItem
ColorModeItem *colorModeItem = new ColorModeItem();
colorModeItem->text = "RGB";
colorModeItem->colorPanel = colorPanel;
colorModeItem->colorMode = ColorPanel::RGB_MODE;
menu->addChild(colorModeItem);

ColorModeItem *hslModeItem = new ColorModeItem();
hslModeItem->text = "HSL";
hslModeItem->colorPanel = colorPanel;
hslModeItem->colorMode = ColorPanel::HSL_MODE;
menu->addChild(hslModeItem);


MenuLabel *modeLabel2 = new MenuLabel();
modeLabel2->text = "Input Range";
menu->addChild(modeLabel2);

InputRangeItem *zeroTenItem = new InputRangeItem();
zeroTenItem->text = "0 - +10V (uni)";
zeroTenItem->colorPanel = colorPanel;
zeroTenItem->inputRange = ColorPanel::ZERO_TEN;
menu->addChild(zeroTenItem);

InputRangeItem *fiveFiveItem = new InputRangeItem();
fiveFiveItem->text = "-5 - +5V (bi)";
fiveFiveItem->colorPanel = colorPanel;
fiveFiveItem->inputRange = ColorPanel::MINUS_PLUS_FIVE;;
menu->addChild(fiveFiveItem);

return menu;
}

} // namespace rack_plugin_Alikins

using namespace rack_plugin_Alikins;

RACK_PLUGIN_MODEL_INIT(Alikins, ColorPanel) {
Model *modelColorPanel = Model::create<ColorPanel, ColorPanelWidget>(
"Alikins", "ColorPanel", "Color Panel", VISUAL_TAG);
return modelColorPanel;
}

+ 140
- 0
plugins/community/repos/Alikins/src/GateLength.cpp View File

@@ -0,0 +1,140 @@
#include "dsp/digital.hpp"

#include "alikins.hpp"
#include "MsDisplayWidget.hpp"

namespace rack_plugin_Alikins {

struct GateLength : Module {
enum ParamIds {
GATE_LENGTH_PARAM1,
GATE_LENGTH_PARAM2,
GATE_LENGTH_PARAM3,
GATE_LENGTH_PARAM4,
GATE_LENGTH_PARAM5,
NUM_PARAMS
};
enum InputIds {
TRIGGER_INPUT1,
TRIGGER_INPUT2,
TRIGGER_INPUT3,
TRIGGER_INPUT4,
TRIGGER_INPUT5,
GATE_LENGTH_INPUT1,
GATE_LENGTH_INPUT2,
GATE_LENGTH_INPUT3,
GATE_LENGTH_INPUT4,
GATE_LENGTH_INPUT5,
NUM_INPUTS
};
enum OutputIds {
GATE_OUTPUT1,
GATE_OUTPUT2,
GATE_OUTPUT3,
GATE_OUTPUT4,
GATE_OUTPUT5,
NUM_OUTPUTS
};
enum LightIds {
NUM_LIGHTS
};

float gate_length[GATE_LENGTH_INPUTS];

SchmittTrigger inputOnTrigger[GATE_LENGTH_INPUTS];

PulseGenerator gateGenerator[GATE_LENGTH_INPUTS];

GateLength() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
void step() override;

void onReset() override {
}

};

void GateLength::step() {
// FIXME: add way to support >10.0s gate length

float sample_time = engineGetSampleTime();
for (int i = 0; i < GATE_LENGTH_INPUTS; i++) {
gate_length[i] = clamp(params[GATE_LENGTH_PARAM1 + i].value + inputs[GATE_LENGTH_INPUT1 + i].value, 0.0f, 10.0f);
if (inputOnTrigger[i].process(inputs[TRIGGER_INPUT1 + i].value)) {
// debug("GL INPUT ON TRIGGER %d gate_length: %f", i, gate_length[i]);
gateGenerator[i].trigger(gate_length[i]);
}

outputs[GATE_OUTPUT1 + i].value = gateGenerator[i].process(sample_time) ? 10.0f : 0.0f;
}
}

struct GateLengthWidget : ModuleWidget {
GateLengthWidget(GateLength *module);
};

GateLengthWidget::GateLengthWidget(GateLength *module) : ModuleWidget(module) {

box.size = Vec(4 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
setPanel(SVG::load(assetPlugin(plugin, "res/GateLength.svg")));

float y_pos = 2.0f;
for (int i = 0; i < GATE_LENGTH_INPUTS; i++) {
float x_pos = 4.0f;
y_pos += 39.0f;

addInput(Port::create<PJ301MPort>(Vec(x_pos, y_pos),
Port::INPUT,
module,
GateLength::TRIGGER_INPUT1 + i));

x_pos += 30.0f;

MsDisplayWidget *gate_length_display = new MsDisplayWidget();
gate_length_display->box.pos = Vec(x_pos, y_pos + 1.0f);
gate_length_display->box.size = Vec(84, 24);
gate_length_display->value = &module->gate_length[i];
addChild(gate_length_display);

// FIXME: use new sequential box hbox/vbox thing
x_pos += 84.0f;
x_pos += 4.0f;
addOutput(Port::create<PJ301MPort>(Vec(x_pos, y_pos),
Port::OUTPUT,
module,
GateLength::GATE_OUTPUT1 + i));

x_pos = 4.0f;
y_pos += 26.0f;

addInput(Port::create<PJ301MPort>(Vec(x_pos, y_pos),
Port::INPUT,
module,
GateLength::GATE_LENGTH_INPUT1 + i));

x_pos += 30.0f;
addParam(ParamWidget::create<Trimpot>(Vec(x_pos, y_pos + 3.0f),
module,
GateLength::GATE_LENGTH_PARAM1 + i,
0.0f, 10.0f, 0.1f));
}

addChild(Widget::create<ScrewSilver>(Vec(0.0f, 0.0f)));
addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 15.0f, 0.0f)));
addChild(Widget::create<ScrewSilver>(Vec(0.0f, 365.0f)));
addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 15.0f, 365.0f)));

}

} // namespace rack_plugin_Alikins

using namespace rack_plugin_Alikins;

RACK_PLUGIN_MODEL_INIT(Alikins, GateLength) {
Model *modelGateLength = Model::create<GateLength, GateLengthWidget>(
"Alikins", "GateLength", "Gate Length", UTILITY_TAG);
return modelGateLength;
}

+ 328
- 0
plugins/community/repos/Alikins/src/IdleSwitch.cpp View File

@@ -0,0 +1,328 @@
#include <stdio.h>
#include <sstream>
#include <iomanip>

#include "alikins.hpp"
#include "dsp/digital.hpp"
// #include "util.hpp"

namespace rack_plugin_Alikins {

/* IdleSwitch
*
* What:
*
* If no input events are seen at Input Source within the timeout period
* emit a gate on Idle Gate Output that lasts until there are input events
* again. Then reset the timeout period.
*
* Sort of metaphoricaly like an idle handler or timeout in event based
* programming like GUI main loops.
*
* The timeout period is set by the value
* of the 'Time before idle' param.
*
* If there is a 'Reset idle' source, when it gets an event, the timeout period
* is reset. After a reset event, the Idle Gate Output will remain on until
* an input event is seen at Input Source. When there is an input event, the Idle
* Gate Output is turned off until the expiration of the 'Time before idle' or
* the next 'Reset idle'.
*
* To use the eventloop/gui main loop analogy, a 'Reset idle' event is equilivent to
* running an idle handler directly (or running a mainloop iteration with no non-idle
* events pending).
*
* Why:
*
* Original intentional was to use in combo with a human player and midi/cv keyboard.
* As long as the human is playing, the IdleSwitch output is 'off', but if they go
* idle for some time period the output is turned on. For example, a patch may plain
* loud drone when idle, but would turn the drone off or down when the human played
* and then turn it back on when it stopped. Or maybe it could be used to start an
* drum fill...
*
* The 'Reset idle' input allows this be kind of synced to a clock, beat, or sequence.
* In the dronevexample above, the drone would then only come back in on a beat.
*
* And perhaps most importantly, it can be used to do almost random output and
* make weird noises.
*/


/* TODO
* - is there a 'standard' for communicating lengths of time (like delay time)?
* - idle start trigger
* - idle end trigger
* - switch for output to be high for idle or low for idle
* - time display widget for timeout length
* - Fine/Course params fors for timeout
* - idle timeout countdown display for remaining time before timeout
* - gui 'progress' widget?
*/

struct IdleSwitch : Module {
enum ParamIds {
TIME_PARAM,
NUM_PARAMS
};
enum InputIds {
INPUT_SOURCE_INPUT,
HEARTBEAT_INPUT,
TIME_INPUT,
PULSE_INPUT,
SWITCHED_INPUT,
NUM_INPUTS
};
enum OutputIds {
IDLE_GATE_OUTPUT,
TIME_OUTPUT,
IDLE_START_OUTPUT,
IDLE_END_OUTPUT,
FRAME_COUNT_OUTPUT,
ON_WHEN_IDLE_OUTPUT,
OFF_WHEN_IDLE_OUTPUT,
NUM_OUTPUTS
};
enum LightIds {
NUM_LIGHTS
};

int idleTimeoutMS = 140;
int idleTimeLeftMS = 0;

SchmittTrigger inputTrigger;

// FIXME: these names are confusing
SchmittTrigger heartbeatTrigger;

// clock mode stuff
SchmittTrigger pulseTrigger;
int pulseFrame = 0;
bool waiting_for_pulse = false;
bool pulse_mode = false;

PulseGenerator idleStartPulse;
PulseGenerator idleEndPulse;

// FIXME: not really counts
int frameCount = 0;
int maxFrameCount = 0;

float idleGateOutput = 0.0;

float deltaTime = 0;

bool is_idle = false;

IdleSwitch() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
void step() override;
};


void IdleSwitch::step() {
bool pulse_seen = false;
bool time_exceeded = false;
pulse_mode = inputs[PULSE_INPUT].active;

float sampleRate = engineGetSampleRate();

// Compute the length of our idle time based on the knob + time cv
// -or-
// base it one the time since the last clock pulse
if (pulse_mode) {
if (inputTrigger.process(inputs[PULSE_INPUT].value)) {
// keep track of which frame we got a pulse
// FIXME: without a max time, frameCount can wrap?
// update pulseFrame to point to current frame count
pulseFrame = frameCount;

waiting_for_pulse = true;
pulse_seen = true;

}

deltaTime = fmax(frameCount - pulseFrame, 0) / sampleRate;
// if we are waiting, maxframeCount is the time since last pulse and increasing
maxFrameCount = frameCount;

} else {
deltaTime = params[TIME_PARAM].value;
if (inputs[TIME_INPUT].active) {
deltaTime += clamp(inputs[TIME_INPUT].value, 0.0f, 10.0f);
}

// TODO: refactor into submethods if not subclass
maxFrameCount = (int)ceilf(deltaTime * sampleRate);
}

idleTimeoutMS = std::round(deltaTime*1000);

// debug("is_idle: %d pulse_mode: %d pulse_frame: %d frameCount: %d maxFrameCount: %d ", is_idle, pulse_mode, pulseFrame, frameCount, maxFrameCount);
// debug("is_idle: %d pulse_mode: %d w_f_pulse: %d pulse_seen: %d pulseFrame: %d frameCount: %d deltaTime: %f",
// is_idle, pulse_mode, waiting_for_pulse, pulse_seen, pulseFrame, frameCount, deltaTime);

if (inputs[HEARTBEAT_INPUT].active &&
heartbeatTrigger.process(inputs[HEARTBEAT_INPUT].value)) {
frameCount = 0;
}

// time_left_s is always 0 for pulse mode until we predict the future
float frames_left = fmax(maxFrameCount - frameCount, 0);
float time_left_s = frames_left / sampleRate;

// TODO: simplify the start/end/gate on logic... really only a few states to check

// the start of idle (not idle -> idle trans)
if ((frameCount > maxFrameCount) || (waiting_for_pulse && pulse_seen)) {
time_exceeded = true;
if (!is_idle) {
idleStartPulse.trigger(0.01);
}

}

// stay idle once we start until there is an input event
is_idle = (is_idle || time_exceeded);

if (is_idle) {
idleGateOutput = 10.0;
outputs[ON_WHEN_IDLE_OUTPUT].value = inputs[SWITCHED_INPUT].value;
outputs[OFF_WHEN_IDLE_OUTPUT].value = 0.0f;

} else {
idleGateOutput = 0.0;
outputs[ON_WHEN_IDLE_OUTPUT].value = 0.0f;
outputs[OFF_WHEN_IDLE_OUTPUT].value = inputs[SWITCHED_INPUT].value;

is_idle = false;

// if we arent idle yet, the idleTimeLeft is changing and we need to update time remaining display
// update idletimeLeftMS which drives the digit display widget
idleTimeLeftMS = time_left_s*1000;
}

frameCount++;

if (inputs[INPUT_SOURCE_INPUT].active &&
inputTrigger.process(inputs[INPUT_SOURCE_INPUT].value)) {

// only end idle if we are already idle (idle->not idle transition)
if (is_idle) {
idleEndPulse.trigger(0.01);
}

is_idle = false;

waiting_for_pulse = false;
frameCount = 0;
pulseFrame = 0;
}

// once clock input works, could add an output to indicate how long between clock
// If in pulse mode, deltaTime can be larger than 10s internal, but the max output
// to "Time output" is 10V. ie, after 10s the "Time Output" stops increasing.
outputs[TIME_OUTPUT].value = clamp(deltaTime, 0.0f, 10.0f);
outputs[IDLE_GATE_OUTPUT].value = idleGateOutput;

outputs[IDLE_START_OUTPUT].value = idleStartPulse.process(1.0/engineGetSampleRate()) ? 10.0 : 0.0;
outputs[IDLE_END_OUTPUT].value = idleEndPulse.process(1.0/engineGetSampleRate()) ? 10.0 : 0.0;

}


// From AS DelayPlus.cpp https://github.com/AScustomWorks/AS
struct IdleSwitchMsDisplayWidget : TransparentWidget {

int *value;
std::shared_ptr<Font> font;

IdleSwitchMsDisplayWidget() {
font = Font::load(assetPlugin(plugin, "res/Segment7Standard.ttf"));
}

void draw(NVGcontext *vg) override {
// Background
// these go to...
NVGcolor backgroundColor = nvgRGB(0x11, 0x11, 0x11);

NVGcolor borderColor = nvgRGB(0xff, 0xff, 0xff);

nvgBeginPath(vg);

nvgRoundedRect(vg, 0.0, 0.0, box.size.x, box.size.y, 5.0);
nvgFillColor(vg, backgroundColor);
nvgFill(vg);

nvgStrokeWidth(vg, 3.0);
nvgStrokeColor(vg, borderColor);

nvgStroke(vg);

// text
nvgFontSize(vg, 18);
nvgFontFaceId(vg, font->handle);
nvgTextLetterSpacing(vg, 2.5);

std::stringstream to_display;
to_display << std::right << std::setw(5) << *value;

Vec textPos = Vec(0.5f, 19.0f);

NVGcolor textColor = nvgRGB(0x65, 0xf6, 0x78);
nvgFillColor(vg, textColor);
nvgText(vg, textPos.x, textPos.y, to_display.str().c_str(), NULL);
}
};


struct IdleSwitchWidget : ModuleWidget {
IdleSwitchWidget(IdleSwitch *module);
};


IdleSwitchWidget::IdleSwitchWidget(IdleSwitch *module) : ModuleWidget(module) {
setPanel(SVG::load(assetPlugin(plugin, "res/IdleSwitch.svg")));

addChild(Widget::create<ScrewSilver>(Vec(5, 0)));
addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 20, 365)));

addInput(Port::create<PJ301MPort>(Vec(37, 20.0), Port::INPUT, module, IdleSwitch::INPUT_SOURCE_INPUT));
addInput(Port::create<PJ301MPort>(Vec(37, 60.0), Port::INPUT, module, IdleSwitch::HEARTBEAT_INPUT));
addInput(Port::create<PJ301MPort>(Vec(70, 60.0), Port::INPUT, module, IdleSwitch::PULSE_INPUT));

// idle time display
// FIXME: handle large IdleTimeoutMs (> 99999ms) better
IdleSwitchMsDisplayWidget *idle_time_display = new IdleSwitchMsDisplayWidget();
idle_time_display->box.pos = Vec(20, 115);
idle_time_display->box.size = Vec(70, 24);
idle_time_display->value = &module->idleTimeoutMS;
addChild(idle_time_display);

addInput(Port::create<PJ301MPort>(Vec(10, 155.0), Port::INPUT, module, IdleSwitch::TIME_INPUT));
addParam(ParamWidget::create<Davies1900hBlackKnob>(Vec(38.86, 150.0), module, IdleSwitch::TIME_PARAM, 0.0, 10.0, 0.25));
addOutput(Port::create<PJ301MPort>(Vec(80, 155.0), Port::OUTPUT, module, IdleSwitch::TIME_OUTPUT));

IdleSwitchMsDisplayWidget *time_remaining_display = new IdleSwitchMsDisplayWidget();
time_remaining_display->box.pos = Vec(20, 225);
time_remaining_display->box.size = Vec(70, 24);
time_remaining_display->value = &module->idleTimeLeftMS;
addChild(time_remaining_display);

addOutput(Port::create<PJ301MPort>(Vec(10, 263.0), Port::OUTPUT, module, IdleSwitch::IDLE_START_OUTPUT));
addOutput(Port::create<PJ301MPort>(Vec(47.5, 263.0), Port::OUTPUT, module, IdleSwitch::IDLE_GATE_OUTPUT));
addOutput(Port::create<PJ301MPort>(Vec(85, 263.0), Port::OUTPUT, module, IdleSwitch::IDLE_END_OUTPUT));

addInput(Port::create<PJ301MPort>(Vec(10.0f, 315.0f), Port::INPUT, module, IdleSwitch::SWITCHED_INPUT));
addOutput(Port::create<PJ301MPort>(Vec(47.5f, 315.0f), Port::OUTPUT, module, IdleSwitch::ON_WHEN_IDLE_OUTPUT));
addOutput(Port::create<PJ301MPort>(Vec(85.0f, 315.0f), Port::OUTPUT, module, IdleSwitch::OFF_WHEN_IDLE_OUTPUT));
}

} // namespace rack_plugin_Alikins

using namespace rack_plugin_Alikins;

RACK_PLUGIN_MODEL_INIT(Alikins, IdleSwitch) {
Model *modelIdleSwitch = Model::create<IdleSwitch, IdleSwitchWidget>(
"Alikins", "IdleSwitch", "Idle Switch", SWITCH_TAG , UTILITY_TAG);
return modelIdleSwitch;
}

+ 152
- 0
plugins/community/repos/Alikins/src/MomentaryOnButtons.cpp View File

@@ -0,0 +1,152 @@
#include <stdio.h>
#include "alikins.hpp"

namespace rack_plugin_Alikins {

struct MomentaryOnButtons : Module {
enum ParamIds {
BUTTON1_PARAM,
BUTTON2_PARAM,
BUTTON3_PARAM,
BUTTON4_PARAM,
BUTTON5_PARAM,
BUTTON6_PARAM,
BUTTON7_PARAM,
BUTTON8_PARAM,
BUTTON9_PARAM,
BUTTON10_PARAM,
BUTTON11_PARAM,
BUTTON12_PARAM,
BUTTON13_PARAM,
NUM_PARAMS
};
enum InputIds {
BUTTON1_INPUT,
BUTTON2_INPUT,
BUTTON3_INPUT,
BUTTON4_INPUT,
BUTTON5_INPUT,
BUTTON6_INPUT,
BUTTON7_INPUT,
BUTTON8_INPUT,
BUTTON9_INPUT,
BUTTON10_INPUT,
BUTTON11_INPUT,
BUTTON12_INPUT,
BUTTON13_INPUT,
NUM_INPUTS
};
enum OutputIds {
BUTTON1_OUTPUT,
BUTTON2_OUTPUT,
BUTTON3_OUTPUT,
BUTTON4_OUTPUT,
BUTTON5_OUTPUT,
BUTTON6_OUTPUT,
BUTTON7_OUTPUT,
BUTTON8_OUTPUT,
BUTTON9_OUTPUT,
BUTTON10_OUTPUT,
BUTTON11_OUTPUT,
BUTTON12_OUTPUT,
BUTTON13_OUTPUT,
NUM_OUTPUTS
};
enum LightIds {
BLINK1_LIGHT,
BLINK2_LIGHT,
BLINK3_LIGHT,
BLINK4_LIGHT,
BLINK5_LIGHT,
BLINK6_LIGHT,
BLINK7_LIGHT,
BLINK8_LIGHT,
BLINK9_LIGHT,
BLINK10_LIGHT,
BLINK11_LIGHT,
BLINK12_LIGHT,
BLINK13_LIGHT,
NUM_LIGHTS
};


MomentaryOnButtons() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
void step() override;

// For more advanced Module features, read Rack's engine.hpp header file
// - toJson, fromJson: serialization of internal data
// - onSampleRateChange: event triggered by a change of sample rate
// - reset, randomize: implements special behavior when user clicks these from the context menu
};


void MomentaryOnButtons::step() {

for (int i = 0; i < MOMENTARY_BUTTONS; i++) {

lights[BLINK1_LIGHT + i].setBrightness(0.0);
outputs[BUTTON1_OUTPUT + i].value = 0.0;

if (params[BUTTON1_PARAM + i].value) {
outputs[BUTTON1_OUTPUT + i].value = 5.0;
lights[BLINK1_LIGHT + i].setBrightness(1.0);
}
}
}


struct MomentaryOnButtonsWidget : ModuleWidget {
MomentaryOnButtonsWidget(MomentaryOnButtons *module);
};


MomentaryOnButtonsWidget::MomentaryOnButtonsWidget(MomentaryOnButtons *module) : ModuleWidget(module) {
box.size = Vec(4 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);

int x_offset = 0;
int y_offset = 26;

int x_start = 0;
int y_start = 24;

int x_pos = 0;
int y_pos = 0;

int light_radius = 7;

{
SVGPanel *panel = new SVGPanel();
panel->box.size = box.size;
panel->setBackground(SVG::load(assetPlugin(plugin, "res/MomentaryOnButtons.svg")));
addChild(panel);
}

/*
addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
*/

for (int i = 0; i < MOMENTARY_BUTTONS; i++) {

x_pos = x_start + x_offset;
y_pos = y_start + (i * y_offset);

addParam(ParamWidget::create<LEDButton>(Vec(x_pos + light_radius, y_pos + 3), module, MomentaryOnButtons::BUTTON1_PARAM + i, 0.0, 1.0, 0.0));
addChild(ModuleLightWidget::create<MediumLight<RedLight>>(Vec(x_pos + 5 + light_radius, y_pos + light_radius), module, MomentaryOnButtons::BLINK1_LIGHT + i));

addOutput(Port::create<PJ301MPort>(Vec(x_pos + 20 + light_radius, y_pos), Port::OUTPUT, module, MomentaryOnButtons::BUTTON1_OUTPUT + i));
}
}

} // namespace rack_plugin_Alikins

using namespace rack_plugin_Alikins;

RACK_PLUGIN_MODEL_INIT(Alikins, MomentaryOnButtons) {
Model *modelMomentaryOnButtons = Model::create<MomentaryOnButtons, MomentaryOnButtonsWidget>(
"Alikins", "MomentaryOnButtons", "Momentary On Buttons", UTILITY_TAG);
return modelMomentaryOnButtons;
}


+ 49
- 0
plugins/community/repos/Alikins/src/MsDisplayWidget.hpp View File

@@ -0,0 +1,49 @@
#include <sstream>
#include <iomanip>


// From AS DelayPlus.cpp https://github.com/AScustomWorks/AS
struct MsDisplayWidget : TransparentWidget {

float *value;
std::shared_ptr<Font> font;

MsDisplayWidget() {
font = Font::load(assetPlugin(plugin, "res/Segment7Standard.ttf"));
}

void draw(NVGcontext *vg) override {
// Background
// these go to...
NVGcolor backgroundColor = nvgRGB(0x11, 0x11, 0x11);

NVGcolor borderColor = nvgRGB(0xff, 0xff, 0xff);

nvgBeginPath(vg);

nvgRoundedRect(vg, 0.0, 0.0, box.size.x, box.size.y, 3.0);
nvgFillColor(vg, backgroundColor);
nvgFill(vg);

nvgStrokeWidth(vg, 1.0f);
nvgStrokeColor(vg, borderColor);

nvgStroke(vg);

// text
nvgFontSize(vg, 14);
nvgFontFaceId(vg, font->handle);
nvgTextLetterSpacing(vg, 2.5);

std::stringstream to_display;
// to_display << std::setiosflags(std::ios::fixed) << std::right << std::setw(5) << std::setprecision(4) << *value;
to_display << std::setiosflags(std::ios::fixed) << std::left << std::setprecision(4) << *value;

Vec textPos = Vec(1.0f, 19.0f);

NVGcolor textColor = nvgRGB(0x65, 0xf6, 0x78);
nvgFillColor(vg, textColor);
nvgText(vg, textPos.x, textPos.y, to_display.str().c_str(), NULL);
}
};


+ 653
- 0
plugins/community/repos/Alikins/src/SpecificValue.cpp View File

@@ -0,0 +1,653 @@
#include "global_pre.hpp"
#include <stdio.h>
#include <string>
#include <vector>
#include <unordered_map>

#include "alikins.hpp"
#include "ui.hpp"
#include "global_ui.hpp"

namespace rack_plugin_Alikins {

struct SpecificValue : Module
{
enum ParamIds
{
VALUE1_PARAM,
OCTAVE_PARAM,
NUM_PARAMS
};
enum InputIds
{
VALUE1_INPUT,
NUM_INPUTS
};
enum OutputIds
{
VALUE1_OUTPUT,
NUM_OUTPUTS
};

enum LightIds
{
NUM_LIGHTS
};

SpecificValue() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}

float A440_octave = 4.0f;

void step() override;

// TODO: toJson/fromJson for saving values

float volt_value;
float hz_value;
float period_value;
float cents_value;

};

struct NoteInfo {
std::string name;
float offset_cents;
};

// TODO: mv to header
float A440_VOLTAGE = 4.75f;
int A440_MIDI_NUMBER = 69;

// TODO: support other enharmonic names Db G♭ A♯?
std::vector<std::string> note_name_vec = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};

std::unordered_map<std::string, float> gen_note_name_map() {
float volt = -10.0f;
std::string fs = note_name_vec[4];
std::unordered_map<std::string, float> note_name_map;

// FIXME: add a map of note name (including enharmonic) to voltage offset from C
// then just iterate over it for each octave
for (int i = -10; i <= 10; i++)
{
for (int j = 0; j < 12; j++)
{
// debug("oct=%d note=%s volt=%f ", i, note_name_vec[j].c_str(), volt);
note_name_map[stringf("%s%d", note_name_vec[j].c_str(), i)] = volt;
volt += (1.0f / 12.0f);
}
}
return note_name_map;
}

std::unordered_map<std::string, float> note_name_to_volts_map = gen_note_name_map();

// FIXME: can/should be inline
// FIXME: likely should be a NoteInfo type/struct/object
// These are assuming A440 == A4 == 4.75v
float freq_to_cv(float freq, float a440_octave) {
float volts = log2f(freq / 440.0f * powf(2.0f, A440_VOLTAGE)) - a440_octave;
// debug("freq_to_vc freq=%f a440_octave=%f volts=%f A440_voltage=%f", freq, a440_octave, volts, A440_VOLTAGE);
return volts;
}

float cv_to_freq(float volts, float a440_octave) {
float freq = 440.0f / powf(2.0f, A440_VOLTAGE) * powf(2.0f, volts + a440_octave);
// debug("cv_to_freq freq=%f a440_octave=%f volts=%f A440_voltage=%f", freq, a440_octave, volts, A440_VOLTAGE);
return freq;
}

// can return negative
float volts_of_nearest_note(float volts) {
float res = roundf( (volts * 12.0f) ) / 12.0f;
return res;
}

int volts_to_note(float volts) {
int res = abs(static_cast<int>( roundf( (volts * 12.0f) ) ) ) % 12;
// debug("volts_to_note volts=%f res=%d", volts, res);
return res;
}

int volts_to_octave(float volts, float a440_octave) {
// debug("a440_octave=%f", a440_octave);
int octave = floor(volts + a440_octave);
// debug("volts_to_octaves volts=%f, a440_octave=%f, octave=%d", volts, a440_octave, octave);
return octave;
}

float volts_to_note_cents(float volts, float a440_octave) {
float nearest_note = volts_of_nearest_note(volts);
float cent_volt = 1.0f / 12.0f / 100.0f;

float offset_cents = (volts-nearest_note)/cent_volt;
// debug("volts: %f volts_of_nearest: %f volts-volts_nearest: %f offset_cents %f",
// volts, nearest_note, volts-nearest_note, offset_cents);

return offset_cents;
}

int volts_to_midi(float volts, float a440_octave) {
int midi_note = floor(volts * 12.0f + a440_octave) + 21;
return midi_note;
}

void SpecificValue::step()
{
A440_octave = params[OCTAVE_PARAM].value;

if (inputs[VALUE1_INPUT].active) {
params[VALUE1_PARAM].value = inputs[VALUE1_INPUT].value;
}
volt_value = params[VALUE1_PARAM].value;
outputs[VALUE1_OUTPUT].value = volt_value;
}

struct FloatField : TextField
{
float value;
SpecificValue *module;

FloatField(SpecificValue *_module);

void onAction(EventAction &e) override;
void onChange(EventChange &e) override;

float textToVolts(std::string field_text);
std::string voltsToText(float param_volts);
};

FloatField::FloatField(SpecificValue *_module)
{
module = _module;
value = module->params[SpecificValue::VALUE1_PARAM].value;
text = voltsToText(value);
}

// TODO: this is really data stuff, so could be in type/struct/class for the data (volt, freq/hz, period/seconds, note_name)
// and instanced and provided to a generic ValueField widget that has-a data type converter thingy
float FloatField::textToVolts(std::string field_text) {
return atof(field_text.c_str());
}

std::string FloatField::voltsToText(float param_volts){
return stringf("%0.3f", param_volts);
}

void FloatField::onChange(EventChange &e) {
//debug("FloatField onChange text=%s param=%f", text.c_str(), module->params[SpecificValue::VALUE1_PARAM].value);

if (this != rack::global_ui->widgets.gFocusedWidget) {
std::string new_text = voltsToText(module->params[SpecificValue::VALUE1_PARAM].value);
setText(new_text);
}
}

void FloatField::onAction(EventAction &e)
{
//debug("FloatField onAction text=%s", text.c_str());

//update text first?
TextField::onAction(e);

float volts = textToVolts(text);

//debug("FloatField setting volts=%f text=%s", volts, text.c_str());
module->params[SpecificValue::VALUE1_PARAM].value = volts;

//debug("FloatField onAction2 text=%s volts=%f module->volt_values=%f",
// text.c_str(), volts, module->volt_value);

}


struct HZFloatField : TextField
{
float value;
SpecificValue *module;

HZFloatField(SpecificValue *_module);
void onChange(EventChange &e) override;
void onAction(EventAction &e) override;

float textToVolts(std::string field_text);
std::string voltsToText(float param_volts);
};

HZFloatField::HZFloatField(SpecificValue *_module)
{
module = _module;
}

float HZFloatField::textToVolts(std::string field_text) {
float freq = strtof(text.c_str(), NULL);
return freq_to_cv(freq, module->A440_octave);
}

std::string HZFloatField::voltsToText(float param_volts){
float freq = cv_to_freq(param_volts, module->A440_octave);
std::string new_text = stringf("%0.*f", freq < 100 ? 4 : 3, freq);
return new_text;
}


void HZFloatField::onChange(EventChange &e) {
//debug("HZFloatField onChange text=%s param=%f", text.c_str(), module->params[SpecificValue::VALUE1_PARAM].value);

//TextField::onChange(e);

if (this != rack::global_ui->widgets.gFocusedWidget)
{
std::string new_text = voltsToText(module->params[SpecificValue::VALUE1_PARAM].value);
setText(new_text);
}
}

void HZFloatField::onAction(EventAction &e)
{
//debug("HZFloatField onAction text=%s", text.c_str());

//update text first?
TextField::onAction(e);

float volts = textToVolts(text);

//debug("HZ FloatField onAction about to set VALUE*_PARAM to volts: %f", volts);
module->params[SpecificValue::VALUE1_PARAM].value = volts;
}


struct SecondsFloatField : TextField {
float value;
SpecificValue *module;

SecondsFloatField(SpecificValue *_module);
void onAction(EventAction &e) override;
void onChange(EventChange &e) override;

float textToVolts(std::string field_text);
std::string voltsToText(float param_volts);
};

SecondsFloatField::SecondsFloatField(SpecificValue *_module)
{
module = _module;
}


float SecondsFloatField::textToVolts(std::string field_text) {
float period = strtof(text.c_str(), NULL);
float freq = 1.0f / period;
return freq_to_cv(freq, module->A440_octave);
}

std::string SecondsFloatField::voltsToText(float param_volts){
float period = 1.0f / cv_to_freq(param_volts, module->A440_octave);
std::string new_text = stringf("%0.*f", period < 100 ? 4 : 3, period);
return new_text;
}

void SecondsFloatField::onChange(EventChange &e) {
//debug("SecondsFloatField onChange text=%s param=%f", text.c_str(), module->params[SpecificValue::VALUE1_PARAM].value);

//TextField::onChange(e);

if (this != rack::global_ui->widgets.gFocusedWidget)
{
std::string new_text = voltsToText(module->params[SpecificValue::VALUE1_PARAM].value);
setText(new_text);
}
}


void SecondsFloatField::onAction(EventAction &e) {
//debug("SecondsFloatField onAction text=%s", text.c_str());

//update text first?
TextField::onAction(e);

float volts = textToVolts(text);

//debug("SecondsFloatField onAction about to set VALUE*_PARAM to volts: %f", volts);
module->params[SpecificValue::VALUE1_PARAM].value = volts;
}

struct CentsField : TextField {
float value;
SpecificValue *module;

CentsField(SpecificValue *_module);
void onChange(EventChange &e) override;
void onAction(EventAction &e) override;

};

CentsField::CentsField(SpecificValue *_module) {
module = _module;
}

void CentsField::onChange(EventChange &e) {
// debug("CentsField onChange");
float cents = volts_to_note_cents(module->params[SpecificValue::VALUE1_PARAM].value,
module->params[SpecificValue::OCTAVE_PARAM].value);

// debug("CentsField onChange cents: %f", cents);
if (this != rack::global_ui->widgets.gFocusedWidget || fabs(cents) >= 0.50f)
{
float cents = volts_to_note_cents(module->params[SpecificValue::VALUE1_PARAM].value,
module->params[SpecificValue::OCTAVE_PARAM].value);
std::string new_text = stringf("% 0.2f", cents);
setText(new_text);
}
}


void CentsField::onAction(EventAction &e) {

TextField::onAction(e);
float cents = strtof(text.c_str(), NULL);

// figure what to tweak the current volts
float cent_volt = 1.0f / 12.0f / 100.0f;
float delta_volt = cents * cent_volt;
float nearest_note_voltage = volts_of_nearest_note(module->params[SpecificValue::VALUE1_PARAM].value);
//debug("volts: %f nearest_volts: %f", module->params[SpecificValue::VALUE1_PARAM].value, nearest_note_voltage);
//debug("delta_volt: %+f nearest_note_voltage+delta_volt: %f", delta_volt, nearest_note_voltage,
// nearest_note_voltage + delta_volt);
module->params[SpecificValue::VALUE1_PARAM].value = nearest_note_voltage + delta_volt;

}



struct NoteNameField : TextField {
float value;
SpecificValue *module;

NoteNameField(SpecificValue *_module);
void onChange(EventChange &e) override;
void onAction(EventAction &e) override;
};

NoteNameField::NoteNameField(SpecificValue *_module)
{
module = _module;
}

void NoteNameField::onChange(EventChange &e) {
//debug("NoteNameField onChange text=%s param=%f", text.c_str(), module->params[SpecificValue::VALUE1_PARAM].value);

//TextField::onChange(e);

if (this != rack::global_ui->widgets.gFocusedWidget)
{
float cv_volts = module->params[SpecificValue::VALUE1_PARAM].value;
int octave = volts_to_octave(cv_volts, module->params[SpecificValue::OCTAVE_PARAM].value);
int note_number = volts_to_note(cv_volts);
// float semi_cents = volts_to_note_and_cents(cv_volts, module->params[SpecificValue::OCTAVE_PARAM].value);
// note_info = volts_to_note_info(cv_volts, module->params[SpecificValue::OCTAVE_PARAM].value);
// TODO: modf for oct/fract part, need to get +/- cents from chromatic notes
std::string new_text = stringf("%s%d", note_name_vec[note_number].c_str(), octave);
// debug("foo %f bar %f", )
setText(new_text);
}

}


void NoteNameField::onAction(EventAction &e) {
//debug("NoteNameField onAction");
TextField::onAction(e);
// FIXME: Haven't tested but seems like this does a lot.
// FIXME: I suspect just a array of structs with name/freq in it and a linear search makes more sense
// but lets c++ stuff
auto search = note_name_to_volts_map.find(text);
if(search != note_name_to_volts_map.end()) {
/*
debug("note_name_to_volts_map[%s] = %f (%f) %f", text.c_str(),
note_name_to_volts_map[text],
(note_name_to_volts_map[text] - module->A440_octave),
module->A440_octave );
*/
module->params[SpecificValue::VALUE1_PARAM].value = note_name_to_volts_map[text] - module->A440_octave;
return;
}
else {
// TODO: change the text color to indicate bogus name?
debug("%s was NOT A VALID note name", text.c_str());
return;
}
}

struct SmallPurpleTrimpot : Trimpot {
SmallPurpleTrimpot();
};

SmallPurpleTrimpot::SmallPurpleTrimpot() : Trimpot() {
setSVG(SVG::load(assetPlugin(plugin, "res/SmallPurpleTrimpot.svg")));
shadow->blurRadius = 0.0;
shadow->opacity = 0.10;
shadow->box.pos = Vec(0.0, box.size.y * 0.1);
}

struct PurpleTrimpot : Trimpot {
Module *module;
bool initialized = false;
PurpleTrimpot();
void step() override;
void reset() override;
void randomize() override;
};

PurpleTrimpot::PurpleTrimpot() : Trimpot() {
setSVG(SVG::load(assetPlugin(plugin, "res/PurpleTrimpot.svg")));
shadow->blurRadius = 0.0;
shadow->opacity = 0.10;
shadow->box.pos = Vec(0.0, box.size.y * 0.05);
}

// FIXME: if we are getting moving inputs and we are hovering
// over the trimpot, we kind of jitter arround.
// maybe run this via an onChange()?
void PurpleTrimpot::step() {
//debug("paramId=%d this->initialized: %d initialized: %d this->value: %f value: %f param.value: %f",
// paramId, this->initialized, initialized, this->value, value, module->params[paramId].value);

if (this->value != module->params[paramId].value) {
if (this != rack::global_ui->widgets.gHoveredWidget && this->initialized) {
// this->value = module->params[paramId].value;
setValue(module->params[paramId].value);
} else {
module->params[paramId].value = this->value;
this->initialized |= true;
}
EventChange e;
onChange(e);
}

Trimpot::step();
}

void PurpleTrimpot::reset() {
this->initialized = false;
Trimpot::reset();
}

void PurpleTrimpot::randomize() {
reset();
setValue(rescale(randomUniform(), 0.0f, 1.0f, minValue, maxValue));
}

struct SpecificValueWidget : ModuleWidget
{
SpecificValueWidget(SpecificValue *module);

void step() override;
void onChange(EventChange &e) override;

float prev_volts = 0.0f;
float prev_octave = 4.0f;
float prev_input = 0.0f;

FloatField *volts_field;
HZFloatField *hz_field;
SecondsFloatField *period_field;
NoteNameField *note_name_field;
CentsField *cents_field;
};


SpecificValueWidget::SpecificValueWidget(SpecificValue *module) : ModuleWidget(module)
{
setPanel(SVG::load(assetPlugin(plugin, "res/SpecificValue.svg")));

// TODO: widget with these children?
float y_baseline = 45.0f;

Vec volt_field_size = Vec(70.0f, 22.0f);
Vec hz_field_size = Vec(70.0, 22.0f);
Vec seconds_field_size = Vec(70.0, 22.0f);

float x_pos = 10.0f;
// debug("adding field %d", i);

y_baseline = 45.0f;

volts_field = new FloatField(module);
volts_field->box.pos = Vec(x_pos, y_baseline);
volts_field->box.size = volt_field_size;
volts_field->value = module->params[SpecificValue::VALUE1_PARAM].value;
addChild(volts_field);

y_baseline = 90.0f;

float h_pos = x_pos;
hz_field = new HZFloatField(module);
hz_field->box.pos = Vec(x_pos, y_baseline);
hz_field->box.size = hz_field_size;
hz_field->value = module->hz_value;
addChild(hz_field);

y_baseline = 135.0f;

period_field = new SecondsFloatField(module);
period_field->box.pos = Vec(h_pos, y_baseline);
period_field->box.size = seconds_field_size;
period_field->value = module->period_value;

addChild(period_field);

y_baseline = 180.0f;

note_name_field = new NoteNameField(module);
note_name_field->box.pos = Vec(x_pos, y_baseline);
note_name_field->box.size = Vec(70.0f, 22.0f);
note_name_field->value = module->volt_value;
addChild(note_name_field);

y_baseline += note_name_field->box.size.y;
y_baseline += 5.0f;
// y_baseline += 20.0f;

cents_field = new CentsField(module);
cents_field->box.pos = Vec(x_pos, y_baseline);
cents_field->box.size = Vec(55.0f, 22.0f);
cents_field->value = module->cents_value;
addChild(cents_field);

// y_baseline += period_field->box.size.y;
y_baseline += 20.0f;

float middle = box.size.x / 2.0f;
float in_port_x = 15.0f;

y_baseline += 24.0f + 12.0f;

Port *value_in_port = Port::create<PJ301MPort>(
Vec(in_port_x, y_baseline),
Port::INPUT,
module,
SpecificValue::VALUE1_INPUT);
//value_in_port->box.pos = Vec(middle - value_in_port->box.size.x / 2, y_baseline);
value_in_port->box.pos = Vec(2.0f, y_baseline);

inputs.push_back(value_in_port);
addChild(value_in_port);

// octave trimpot
SmallPurpleTrimpot *octaveTrimpot = ParamWidget::create<SmallPurpleTrimpot>(
Vec(middle, y_baseline + 2.5f),
module,
SpecificValue::OCTAVE_PARAM,
0.0f, 8.0f, 4.0f);

params.push_back(octaveTrimpot);
octaveTrimpot->box.pos = Vec(middle - octaveTrimpot->box.size.x / 2, y_baseline + 2.5f);
octaveTrimpot->snap = true;
addChild(octaveTrimpot);

float out_port_x = middle + 24.0f;

Port *value_out_port = Port::create<PJ301MPort>(
Vec(out_port_x, y_baseline),
Port::OUTPUT,
module,
SpecificValue::VALUE1_OUTPUT);

outputs.push_back(value_out_port);
value_out_port->box.pos = Vec(box.size.x - value_out_port->box.size.x - 2.0f, y_baseline);

addChild(value_out_port);

y_baseline += value_out_port->box.size.y;
y_baseline += 16.0f;

PurpleTrimpot *trimpot = ParamWidget::create<PurpleTrimpot>(
Vec(middle - 24.0f, y_baseline + 2.5f),
module,
SpecificValue::VALUE1_PARAM,
-10.0f, 10.0f, 0.0f);

//debug(" trimpot: dv: %f v: %f p.value: %f", trimpot->defaultValue, trimpot->value,
// module->params[SpecificValue::VALUE1_PARAM].value);
params.push_back(trimpot);
addChild(trimpot);
}


void SpecificValueWidget::step() {
ModuleWidget::step();

if (prev_volts != module->params[SpecificValue::VALUE1_PARAM].value ||
prev_octave != module->params[SpecificValue::OCTAVE_PARAM].value ||
prev_input != module->params[SpecificValue::VALUE1_INPUT].value) {
// debug("SpVWidget step - emitting EventChange / onChange prev_volts=%f param=%f",
// prev_volts, module->params[SpecificValue::VALUE1_PARAM].value);
prev_volts = module->params[SpecificValue::VALUE1_PARAM].value;
prev_octave = module->params[SpecificValue::OCTAVE_PARAM].value;
prev_input = module->params[SpecificValue::VALUE1_INPUT].value;
EventChange e;
onChange(e);
}
}

void SpecificValueWidget::onChange(EventChange &e) {
// debug("SpvWidget onChange");
ModuleWidget::onChange(e);
volts_field->onChange(e);
hz_field->onChange(e);
period_field->onChange(e);
note_name_field->onChange(e);
cents_field->onChange(e);

}

} // namespace rack_plugin_Alikins

using namespace rack_plugin_Alikins;

RACK_PLUGIN_MODEL_INIT(Alikins, SpecificValue) {
Model *modelSpecificValue = Model::create<SpecificValue, SpecificValueWidget>(
"Alikins", "SpecificValue", "Specific Values", UTILITY_TAG);
return modelSpecificValue;
}

+ 22
- 0
plugins/community/repos/Alikins/src/alikins.cpp View File

@@ -0,0 +1,22 @@
#include "alikins.hpp"

RACK_PLUGIN_MODEL_DECLARE(Alikins, IdleSwitch);
RACK_PLUGIN_MODEL_DECLARE(Alikins, MomentaryOnButtons);
RACK_PLUGIN_MODEL_DECLARE(Alikins, BigMuteButton);
RACK_PLUGIN_MODEL_DECLARE(Alikins, ColorPanel);
RACK_PLUGIN_MODEL_DECLARE(Alikins, GateLength);
RACK_PLUGIN_MODEL_DECLARE(Alikins, SpecificValue);

RACK_PLUGIN_INIT(Alikins) {
RACK_PLUGIN_INIT_ID();

RACK_PLUGIN_INIT_WEBSITE("https://github.com/alikins/Alikins-rack-plugins");
RACK_PLUGIN_INIT_MANUAL("https://github.com/alikins/Alikins-rack-plugins/blob/master/README.md");

RACK_PLUGIN_MODEL_ADD(Alikins, IdleSwitch);
RACK_PLUGIN_MODEL_ADD(Alikins, MomentaryOnButtons);
RACK_PLUGIN_MODEL_ADD(Alikins, BigMuteButton);
RACK_PLUGIN_MODEL_ADD(Alikins, ColorPanel);
RACK_PLUGIN_MODEL_ADD(Alikins, GateLength);
RACK_PLUGIN_MODEL_ADD(Alikins, SpecificValue);
}

+ 12
- 0
plugins/community/repos/Alikins/src/alikins.hpp View File

@@ -0,0 +1,12 @@
#include "rack.hpp"

const int MOMENTARY_BUTTONS = 13;
const int INPUT_SOURCES = 1;
const int GATE_LENGTH_INPUTS = 5;
using namespace rack;

RACK_PLUGIN_DECLARE(Alikins);

#ifdef USE_VST2
#define plugin "Alikins"
#endif // USE_VST2

+ 20
- 0
plugins/community/repos/BaconMusic/BaconMusic.json View File

@@ -0,0 +1,20 @@
{
"slug": "BaconMusic",
"name": "Bacon Music",
"author": "@baconpaul",
"license": "Apache-2.0",
"version": "0.5.0",
"homepage": "https://github.com/baconpaul/BaconPlugs",
"manual": "https://github.com/baconpaul/BaconPlugs/blob/master/README.md",
"source": "https://github.com/baconpaul/BaconPlugs",
"downloads": {
"lin": {
"download": "https://github.com/baconpaul/BaconPlugs/files/1611795/BaconMusic-0.5.0-lin.zip",
"sha256": "89338dda1f75b3dfc0044df2177a93e397b35ac41e7dabd9d4c382502bcf8c78"
},
"mac": {
"download": "https://github.com/baconpaul/BaconPlugs/files/1611780/BaconMusic-0.5.0-mac.zip",
"sha256": "67a2b6c5f9f9a8974ffdfac359f8d2ceed639afb18373302e6e952379c18f171"
}
}
}

+ 26
- 0
plugins/community/repos/BaconMusic/LICENSE.txt View File

@@ -0,0 +1,26 @@
Copyright 2017-2018, Paul Walker

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


---------------------------------------------------------------------

The file "res/Keypunch029.json" which implements the KeyPunch029 font
used in the dot matrix widget is Copyright (c) 2017 Stewart C. Russell
and is released under the SIL Open Font License 1.1

http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL)

The original work can be found at the below location:

http://scruss.com/blog/2017/03/21/keypunch029-for-all-your-punched-card-font-needs/.

+ 45
- 0
plugins/community/repos/BaconMusic/Makefile View File

@@ -0,0 +1,45 @@

SLUG = BaconMusic

VERSION = 0.6.2
RELEASE_BRANCH = release_0.6.2

# FLAGS will be passed to both the C and C++ compiler
FLAGS +=
CFLAGS +=
CXXFLAGS += -Werror

# Careful about linking to shared libraries, since you can't assume much about the user's environment and library search path.
# Static libraries are fine.
LDFLAGS +=

# Add .cpp and .c files to the build
SOURCES += $(wildcard src/*.cpp)

# Add files to the ZIP package when running `make dist`
# The compiled plugin is automatically added.
DISTRIBUTABLES += $(wildcard LICENSE*) res docs patches README.md

# Include the VCV plugin Makefile framework
RACK_DIR ?= ../..
include $(RACK_DIR)/plugin.mk

shadist: dist
openssl sha256 dist/$(SLUG)-$(VERSION)-$(ARCH).zip > dist/$(SLUG)-$(VERSION)-$(ARCH).zip.sha256

COMMUNITY_ISSUE=https://github.com/VCVRack/community/issues/433

issue_blurb: dist
git diff --exit-code
git diff --cached --exit-code
@echo
@echo "Paste this into github issue " $(COMMUNITY_ISSUE)
@echo
@echo "* Version: v$(VERSION)"
@echo "* Transaction: " `git rev-parse HEAD`
@echo "* Branch: " `git rev-parse --abbrev-ref HEAD`

push_git:
@echo "Pushing current branch to git and dropbox"
git push dropbox `git rev-parse --abbrev-ref HEAD`
git push github `git rev-parse --abbrev-ref HEAD`

+ 286
- 0
plugins/community/repos/BaconMusic/README.md View File

@@ -0,0 +1,286 @@
# The Bacon Music VCVRack Modules

"Bacon Music" is my set of EuroRack style plugins for
[VCVRack](http://www.vcvrack.com). The modules are mostly inspired by me noodling around, and
they sort of fall into a few groups:

* Control voltage manipulation on 1v/oct signals to do things like glissando and musical quantization and a polyrhytmic clock;
* Classic synth algorithms, including an implementation of the NES oscillators and a Karplus Strong implementation.
* and finally, not very useful modulations and distortions and stuff.


All the source is here, released under an Apache 2.0 license. You are free to use
these modules as you see fit. If you happen to use them to make music you want to share, please
do let me know, either by raising an issue on this github or by tagging me on twitter (@baconpaul) or
soundcloud (@baconpaul).

As of the release of Rack 0.6, these plugins will be built as part of the
[v2 community distribution](https://github.com/VCVRack/community/tree/v2) so they should just be
available for you to try. A massive thanks to the [Rack community team](https://github.com/VCVRack/community/issues/248)
for maintaining these builds.

I'm happy to hear any feedback and bug reports. The best way
to reach me is to just open a github issue [right here on github](https://github.com/baconpaul/BaconPlugs/issues).

Finally, all the [sample patches I used to make the screen-shots](https://github.com/baconpaul/BaconPlugs/tree/master/patches) are
on the github here.

I hope you enjoy the plugins!

## Control Voltage Manipulation and Clocks

### HarMoNee

HarMoNee is a plugin which takes a 1v/oct CV signal and outputs two signals,
one which is the original, and the second which is modified by a musical amount,
like a minor 3rd. It spans plus or minus one octave, and is controlled by toggles.

The toggles are additive. So if you want a fourth, choose a major third and a half step
both. You get the idea.

<a href="https://baconpaul.github.io/audio/HarMoNee.mp3">
<img src="docs/HarMoNee.png" alt="ExampleQuanteyes Patch">
<br>
<img src="docs/SpeakerIconSmall.png" alt="Hear HarMoNee Sample">
</a>


### Glissinator

Glissinator takes a control voltage which is undergoing change and smooths out that
change with a linear glissando. It is not triggered by a gate, just by differences
in the input CV. It never jumps discontinuously, so if the CV changes "target" value
mid-gliss, the whole thing turns around. The slider will give you between 0 and 1 seconds
of gliss time. There is a gate output which is +10v when the module is glissing and
0 when it isn't. Note that the Glissinator is a constant time gliss, not a constant
slope gliss (which is what a slew limiter would do). A future version may have a switch
to pick between the modes.

Here's a sample patch.

<a href="https://baconpaul.github.io/audio/Glissinator.mp3">
<img src="docs/Glissinator.png" alt="ExampleQuanteyes Patch">
<br>
<img src="docs/SpeakerIconSmall.png" alt="Hear Glissinator Sample">
</a>


### QuantEyes

QuantEyes takes a CV signal and clamps it to certain values 1/12 of a volt apart.
Functionally this means that CV signals which are changing on input will be clamped to
a chromatic scale on output if all the notes are activated. But you can also deactivate
certain notes to allow you to pick scales to which you quantize.

Since quantizing to scales could be useful for multiple things driving oscillators,
you can apply this quantization to up to 3 inputs using the same scale.

Finally, you can choose where the "root" note is in CV space. The default is that
1 volt is the "R" note, but if you set root to 3, then 1 3/12 volts would be R. If you don't
understand this, send in a changing signal, select only the R note in the set of LED buttons,
and then twiddle the root note.

Here's a (pretty cool sounding, I think) patch which combines QuantEyes with the
Glissinator and HarMoNee modules.

<a href="https://baconpaul.github.io/audio/QuantEyes.mp3">
<img src="docs/QuantEyes.png" alt="ExampleQuanteyes Patch">
<br>
<img src="docs/SpeakerIconSmall.png" alt="Hear QuantEyes Sample">
</a>


### PolyGnome

PolyGnome is a polyrhytmic clock generator. It can output up to 5 clock signals with strict
fractional relationships between them. There is one clock which is the "1/1" clock controlled by
the speed settings implemented exactly like the clock rate controls in SEQ3. Then there are 4
other clocks which are fractionally adjusted clocks. This way you can do a 1/1 vs a 5/3 vs a 4/5
polyrhythm easily in your rack.

Here's an example which uses this to drive 3 independent oscillator / envelope sets all of which have
pitch set through the QuantEyes module.

<a href="https://baconpaul.github.io/audio/PolyGnome.mp3">
<img src="docs/PolyGnome.png" alt="Example PolyGnome Patch">
<br>
<img src="docs/SpeakerIconSmall.png" alt="Hear PolyGnome Sample">
</a>


## Classic and 8-bit algorithms

### ChipWaves

ChipWaves implements the NES triangle and pulse wave generator. It would have been
impossible to implement without the careful description of the algorithms at
[the NES Dev Wiki](http://wiki.nesdev.com/w/index.php/APU_Triangle).

The NES has two tonal oscillators, a triangle wave and a pulse. The pulse has 4
different duty cycles. The triangle is a fixed wave.

They are tuned by wavelength with values up to 2^11 clock cycles. Rather than
expose this very digital interface, though, I've set up the inputs to be tuned
to CV in exactly the same way as VCO-1. So the conversion from 1v/oct signal
to the 2^11 different wavelengths based on the simulated clock frequency (I chose NTSC)
is all done for you.

Basically, it just works like an oscillator. Drop it in and go chip crazy. The sample
patch runs it mixed along with a VCO-1 so I could check tuning. Here's how I did it.

<a href="https://baconpaul.github.io/audio/ChipWaves.mp3">
<img src="docs/ChipWaves.png" alt="Example ChipWaves Patch">
<br>
<img src="docs/SpeakerIconSmall.png" alt="Hear ChipWaves Sample">
</a>



### ChipNoise

ChipNoise implements the NES noise generator without the NES envelope. It would have been
impossible to implement without the careful description of the noise algorithm at
[the NES Dev WIKI](http://wiki.nesdev.com/w/index.php/APU_Noise). I also appreciate the
[lengthy conversation with @alto77](https://github.com/baconpaul/BaconPlugs/issues/6) which helped
identify a bug in the 0.6.1 release and add a new feature.

The NES noise system has 16 different frequencies; and two modes. The two modes generate either
a long pseudo-random pattern or a set of short pseudo-random patterns. That long pattern is just
long, but the short patterns are either 93 or 31 bits long. There are 351 distinct 93 bit patterns
and a single 31 bit pattern.

The sequence controls allow you to pick these patterns. If set at "long" then you choose the longest
pattern. If set at short, then either you have the 31 long pattern or one of the 93 patterns. Which of
the 93 patterns you pick is chosen by the "which 93 seq" knob.

This is a lot of information. If you just play with it you'll get the idea.

Here's a simple patch.

<a href="https://baconpaul.github.io/audio/ChipNoise.mp3">
<img src="docs/ChipNoise.png" alt="Example ChipNoise Patch">
<br>
<img src="docs/SpeakerIconSmall.png" alt="Hear ChipNoise Sample">
</a>

### ChipYourWaves

ChipYourWaves is a chip-like oscillator which doesn't actually exist in the old NES hardware.
The way the NES triangle wave generator works is it oscillates across a 32-sample-wide waveform of values
between 0 and 15, with 7/8 being the "zero point". This is set up as a ramp 0 1 2 ... 15 15 14 ... 0
and then tuned and oscillated. If you want this waveform, just use the ChipWaves module up above.

But I got to thinking. That waveform is something we could change and make even buzzier grunky chip-like
sounds. Perhaps. So I wrote a module which is the same internal implementation as the NES triangle wave
generator in ChipWaves but which has an editor which lets you pick each of the 32 values. Then you can
hear it. And see if you like it.

To set the values just click or drag on the LED vertical. It's pretty intuitive when you use it, I think. But
so you get an idea, here's the sample patch which sets a fixed frequency and hooks it up to the scope so you can
see the generated waveform is, indeed, the bits you draw in the LED-like controls.

![Example ChipYourWaves Patch](docs/ChipYourWaves.png)

Oh if you have any idea what to put in all that blank space at the top of the module, by the way, please do
just raise a github issue and let me know!

### KarplusStrongPoly

The [Karplus-Strong algorithm](https://en.m.wikipedia.org/wiki/Karplus–Strong_string_synthesis) is one of the
earlier methods to simulate plucked string instruments. The KarplusStrongPoly module implements a polyphonic
voides implementation of this. The module maps to the algorithm fairly cleanly. It's probably easier that you
just play with it, using the sample patch shown below.

<a href="https://baconpaul.github.io/audio/KarplusStrongPoly.mp3">
<img src="docs/KarplusStrongPoly.png" alt="Example ChipNoise Patch">
<br>
<img src="docs/SpeakerIconSmall.png" alt="Hear ChipNoise Sample">
</a>

There's one really important thing to know about this module. Unlike more traditional voltage controlled oscillators
which always produce output and are then fed into envelopes and stuff, the KarplusStrongPoly module needs to be
triggered with a gate signal to produce any sound. When it is triggered it will snap all the parameters set on
the front panel and play that voice until it fades. The system is configured to play upto 32 voices and will
voice steal beyond that. But since Rack adds a 1 sample delay to all its signals as they go through each module,
if you trigger from SEQ-3 and use a frequency you have modified, the trigger will "beat" the modified signal.
So adding a few sample delay to your trigger may be approrpriate. There's a really simple SampleDelay module
which ships with this plugin set if you want to do that.

I've only implemented one filter so far, so the only control which does anything in the filter space is the "A"
knob and CV input. If/as I add more that will get way more rich, kind of like initial packet is now.

Finally I think the algorithm is stable under all possible front panel configurations. There's certainly
regimes of parameters in the C++ which can break the synthesis, though. So if you get an
odd or growing sound, let me know the configuration which did it in a github issue and I'll put a check
in the widget to synth snap appropriately.

## Distortions and Modulations and so on
### ALingADing

ALingADing is a simulation of a Ring Modulator based on [this paper by Julian Parker](http://recherche.ircam.fr/pub/dafx11/Papers/66_e.pdf) and
then taking some shortcuts.
Rather than following Parker's use of a few polynomials to simulate his diode,
I basically use an implementation of a softmax, eye-balling the parameters to roughly meet the figure in his
paper. The only control is a wet/dry mix (where wet is the signal modulated by carrier
and dry is just the signal). Sloppy, sure, but it sounds kinda cool. Here's a sample patch.

<a href="https://baconpaul.github.io/audio/ALingADing.mp3">
<img src="docs/ALingADing.png" alt="ExampleQuanteyes Patch">
<br>
<img src="docs/SpeakerIconSmall.png" alt="Here QuantEyes">
</a>



### Bitulator

Bitulator is really just me screwing around with some math on the input. It has two
functions. Firstly, it "quantizes" to a smaller number of "bits", but does it in a
weird and sloppy way of basically making sure there are only N values possible in the
output. Apply this to a sine wave with a low value of N and you get sort of stacked squares.
Secondly it has a gross digital clipping amplifier. Basically signal is the clamp of input times
param. Apply this to a sine wave and turn it up and you get pretty much a perfect square.
Combine them for grunky grunk noise. Dumb, but fun. Here's a sample patch.

![Example Bitulator Patch](docs/Bitulator.png)

### SampleDelay

This is an incredibly simple module. All it does is add an n-sample digital delay at the
engine clock speed. Radically non-analog, I know. But it's useful since Rack adds a 1 sample
delay in each module hop to do things like triggering the Karplus Strong poly.

![Example SampleDelay](docs/SampleDelay.png)

## Credits and Comments

The Keypunch font used in the textual display LED widget comes from
[Stewart C. Russell's blog](http://scruss.com/blog/2017/03/21/keypunch029-for-all-your-punched-card-font-needs/).
The font is Copyright 2017 Stewart C. Russell and is released under
the [SIL Open Font License 1.1](http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL).

The slug name ('BaconMusic') is different than the repo name ('BaconPlugs'), somewhat confusingly.
When I made my git repo I had no idea really how anything worked or if I'd write anything.
I was thinking "Hey I'm writing a collection of plugins for this software right". When I went
with my first release, Andrew Rust pointed out that "BaconPlugs" wasn't a very good name for my
plugin and it's collected modules. He did it very politely, of course, and so I changed it to "Bacon Music"
for the slug name. The repo is still called BaconPlugs though, because that's more trouble to change than
I can handle.

## License

Copyright © 2017-2018 Paul Walker

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.



BIN
plugins/community/repos/BaconMusic/docs/ALingADing.png View File

Before After
Width: 3100  |  Height: 764  |  Size: 866KB

BIN
plugins/community/repos/BaconMusic/docs/Bitulator.png View File

Before After
Width: 2188  |  Height: 762  |  Size: 571KB

+ 18
- 0
plugins/community/repos/BaconMusic/docs/CODE_OF_CONDUCT.md View File

@@ -0,0 +1,18 @@
# Code of Conduct

The [Contrubitor Covenant](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html) is an excellent code of
conduct, and one by which I'd like to hope I carry myself. Please read it and follow its guidance when
working with this project.

BaconPlugs is mostly a one-person project, but I do welcome and appreciate all feedback.
Please use the
github issue mechanism to start discussions or leave comments. Your comments will be more gladly
recieved if they are constructive, polite,
and empathetic, and I will aspire to be constructive, polite, and empathetic in my responses.

I cannot, however, guarantee that my responses will always be very *timely*.
This is just a little side project for me!

I hope that you are also as excited to make music using open tools as I am, and hope that
you want to make that a positive, inclusive experience.


+ 19
- 0
plugins/community/repos/BaconMusic/docs/CONTRIBUTING.md View File

@@ -0,0 +1,19 @@
# Contribution guide

I welcome contributions to these plugins and am happy to review pull requests with changes.

I'm mostly writing this document so I can get a "checkmark" on the github opensource project
health checklist. I don't think any of you will do big development on this plug set, but I am
happy if you want to!

Here's some thoughts on how that would work, but the project is small enough that we can just sort of sort it
in an issue if you are interested in doing something big.

* Before you start developing, please open a github issue to chat with me about the change you
want to make. While you don't have to do this, it's probably best since then at least I'm not
surprised by your PR. *GitHub Issues are by far the best way to reach me about this project*.
* The plugin is licensed under Apache 2. If you aren't comfortable working under that license,
then we should chat. I'm happy for you to retain copyright for your changes if you want and
they are substantial (vs something tiny I could just fix myself if you mentioned it).
* Please see the [code of conduct](CODE_OF_CONDUCT.md) for community guidelines.


BIN
plugins/community/repos/BaconMusic/docs/ChipNoise.png View File

Before After
Width: 2170  |  Height: 912  |  Size: 674KB

BIN
plugins/community/repos/BaconMusic/docs/ChipWaves.png View File

Before After
Width: 3036  |  Height: 1128  |  Size: 1.0MB

BIN
plugins/community/repos/BaconMusic/docs/ChipYourWaves.png View File

Before After
Width: 2500  |  Height: 1120  |  Size: 583KB

BIN
plugins/community/repos/BaconMusic/docs/Glissinator.png View File

Before After
Width: 2488  |  Height: 902  |  Size: 718KB

BIN
plugins/community/repos/BaconMusic/docs/HarMoNee.png View File

Before After
Width: 2162  |  Height: 764  |  Size: 586KB

BIN
plugins/community/repos/BaconMusic/docs/KarplusStrongPoly.png View File

Before After
Width: 1928  |  Height: 1814  |  Size: 1.2MB

BIN
plugins/community/repos/BaconMusic/docs/PolyGnome.png View File

Before After
Width: 2816  |  Height: 1812  |  Size: 1.8MB

BIN
plugins/community/repos/BaconMusic/docs/QuantEyes.png View File

Before After
Width: 3414  |  Height: 902  |  Size: 1.1MB

BIN
plugins/community/repos/BaconMusic/docs/SampleDelay.png View File

Before After
Width: 1140  |  Height: 898  |  Size: 255KB

BIN
plugins/community/repos/BaconMusic/docs/SpeakerIcon.png View File

Before After
Width: 1600  |  Height: 1600  |  Size: 28KB

BIN
plugins/community/repos/BaconMusic/docs/SpeakerIconSmall.png View File

Before After
Width: 30  |  Height: 30  |  Size: 757B

+ 14
- 0
plugins/community/repos/BaconMusic/docs/release_notes/future_releases.md View File

@@ -0,0 +1,14 @@
Things for future releases perhaps?

Plugins:
* LSFR more general noise maker (sort of started in the ChipSym)
* CleverClipper (branch "CleverClipper" already exists on mac and in dbox)
* Lilypond or ABC-like music phrase generator
* This paper looks fun https://pdfs.semanticscholar.org/68fa/415703af07042d4301ac6cb3722c87f5bc43.pdf
* Karplus Strong Mono
* Gates in QuantEyes
* Add appropriate BaconHelpButtons to everything
* Keep or kill that sloppy chorus




+ 34
- 0
plugins/community/repos/BaconMusic/docs/release_notes/release_v0.6.2.md View File

@@ -0,0 +1,34 @@
# BaconMusic v0.6.2 Release Notes

* Added sound samples for most of the modules in the README.

* ChipNoise
* Fixed an important bit length bug that @alto777 found.
* Added control of short sequence selection; either the 31 long or which of the 93s.
* For more, see https://github.com/baconpaul/BaconPlugs/issues/6
* Update doc for ChipNoise

* KarplusStrongPoly
* A new module which implements KarplusStrong plucked instrument synthesis polyphonically.

* QuantEyes
* Don't trigger lights if there is no input

* PolyGnome
* Added this new widget which allows for exact fractional polyrhythms in clocks.

* Glissinator
* Fixed a bug found by @alto777 where a rapid decrease in the shift time would lock the module
* Added a gate output for when you are in the gliss
* Refactored to allow standalone tests of the stepper

* SampleDelay
* Just a teensy utility plugin to do sample accurate delays between 1 and 99 samples

* I added a DMP Text Widget using Stewart C. Russell's Keypunch029 font (see README.md for license and links).
* As well as a single digit, there's a multi digit sevent segment light. Take a look at ChipNoise for how to use it.
* Background got some new features, like colored labels and filled rounded rects in the API

(required)
* Code Review all diffs from master


+ 16
- 0
plugins/community/repos/BaconMusic/make.objects View File

@@ -0,0 +1,16 @@
ALL_OBJ= \
src/ALingADing.o \
src/BaconPlugs.o \
src/Bitulator.o \
src/BlankWidget.o \
src/ChipNoise.o \
src/ChipWaves.o \
src/ChipYourWave.o \
src/Components.o \
src/Glissinator.o \
src/HarMoNee.o \
src/KarplusStrongPoly.o \
src/PolyGnome.o \
src/QuantEyes.o \
src/SampleDelay.o \
src/SortaChorus.o

+ 9
- 0
plugins/community/repos/BaconMusic/makefile.msvc View File

@@ -0,0 +1,9 @@
SLUG=BaconMusic

include ../../../../dep/yac/install_msvc.mk

EXTRAFLAGS+= -DBUILD_SORTACHORUS

include make.objects

include ../../../build_plugin.mk

+ 422
- 0
plugins/community/repos/BaconMusic/pynb/KarplusStrong.ipynb
File diff suppressed because it is too large
View File


+ 505
- 0
plugins/community/repos/BaconMusic/res/BaconSliderHandle.svg View File

@@ -0,0 +1,505 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="41"
viewBox="0 0 20 41.000001"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="BaconSliderHandle.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.313708"
inkscape:cx="-2.4107142"
inkscape:cy="5"
inkscape:document-units="px"
inkscape:current-layer="layer4"
showgrid="false"
units="px"
inkscape:window-width="1813"
inkscape:window-height="1289"
inkscape:window-x="93"
inkscape:window-y="47"
inkscape:window-maximized="0" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Background"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1011.3621)"
style="display:none">
<image
y="1011.4246"
x="0.0625"
id="image4238"
xlink:href="data:image/png;base64,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
mzgjAL72T01NtkxNfa1Bin0IQPvE7Jw+bXJHAXA9x4i08r8Tnwj+1f4CYSsHOyGy924AAAAJcEhZ
cwAAFiUAABYlAUlSJPAAAAIEaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHht
bG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA1LjQuMCI+CiAgIDxyZGY6
UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5z
IyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5z
OmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczp0
aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDxleGlmOlBpeGVs
WURpbWVuc2lvbj4yNzg8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhl
bFhEaW1lbnNpb24+MTMwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPHRpZmY6T3Jp
ZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAg
IDwvcmRmOlJERj4KPC94OnhtcG1ldGE+ChDqyCAAADZqSURBVHgB7Z1Zl9w6sp2zqlLDGXq0ve6D
X+z//5fs5Sdfr9t9ZpVUo6q8v70jSGRKOspMSaW+3UAViSkQQO7NAEEQJM/u7+8fN3aPm8dHBSu2
OTvTP1vldroEduSSffReWlSX9xvVgtbN40PFqVcaiT08PGwe3r61/ouLi83Z+bnlUyFSZ5vzc/lL
GdTmd0QbEuSXn4Kbh8eHzduHt6rhbHNxsXXqw9t7xDbb7dZ139/fbR7fPmzOpZs6zs8vHG6QHixd
Cp/Yu7y83Pz9xx82//Hv/2/zt3//v5tnanN+BU2HLGNAQD88eDg87vblxryjwq2/6nwUuBBnyEXY
Pk7mR7K060zAmlSFcRx0iyvBJtTp/jGwWQVI9A8hiYPl3iRdcKCgW3KPtEUHF5pzUCskWYpRXXLk
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
UOJGK9U7AAAAAElFTkSuQmCC
"
preserveAspectRatio="none"
height="40.75"
width="19.875" />
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="RedFill">
<rect
style="fill:#888888;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4271"
width="20.240932"
height="41.365746"
x="0.088388346"
y="0.076194942" />
</g>
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="BlackBar">
<rect
style="fill:#222222;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4274"
width="20.152542"
height="5.833632"
x="0.088388398"
y="17.400312" />
<path
style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d="m 0.1767767,21.554563 19.8873783,0 0.08839,0"
id="path4276"
inkscape:connector-curvature="0" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Images"
style="display:inline">
<rect
style="fill:#a7a7a7;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4242"
width="20.166054"
height="5.3428516"
x="0.0625"
y="36" />
<rect
style="fill:#fcfbfc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4244"
width="20.125"
height="2.0946698"
x="0.125"
y="33.780331" />
<rect
style="fill:#f0f0f0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4246"
width="20.25"
height="3.4937184"
x="0.088388346"
y="29.484835" />
<rect
style="fill:#ececec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4248"
width="20.082108"
height="3.670495"
x="0.10983495"
y="24.969669" />
<rect
style="fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4250"
width="20.125"
height="2.625"
x="0.051776696"
y="21.625" />
<rect
style="fill:#d0d0d0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4252"
width="20.140165"
height="2.5"
x="0.073223308"
y="16.801777" />
<rect
style="fill:#b00000;fill-opacity:0;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4254"
width="19.75"
height="2.625"
x="0.5"
y="12.375" />
<rect
style="fill:#a6a6a6;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4256"
width="20.25"
height="3.125"
x="-0.051776696"
y="8" />
<rect
style="fill:#a0a0a0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4258"
width="20.301777"
height="1.25"
x="-0.125"
y="5.875" />
<rect
style="fill:#f0f0f0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4260"
width="20.1875"
height="5.5624785"
x="0.0625"
y="0.062521584" />
<rect
style="fill:#bcbcff;fill-opacity:0;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4262"
width="20.417707"
height="3.0935922"
x="0"
y="12.008622" />
<rect
style="fill:#bcbcff;fill-opacity:0;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4264"
width="6.5407376"
height="1.767767"
x="0.26516503"
y="13.864778" />
<rect
style="fill:#bcbcff;fill-opacity:0;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4266"
width="16.705399"
height="3.7123106"
x="0.35355338"
y="12.185399" />
<rect
style="fill:#bcbcbc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.84399998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4268"
width="20.240932"
height="4.154253"
x="0.088388346"
y="11.831845" />
</g>
</svg>

+ 360
- 0
plugins/community/repos/BaconMusic/res/HelpActive.svg View File

@@ -0,0 +1,360 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:ns1="http://sozi.baierouge.fr"
id="svg4888"
sodipodi:docname="error_button.svg"
viewBox="0 0 400 400"
version="1.1"
inkscape:version="0.48.0 r9654"
>
<defs
id="defs4890"
>
<linearGradient
id="linearGradient8435"
y2="367.88"
gradientUnits="userSpaceOnUse"
y1="287.49"
x2="315.47"
x1="241.41"
inkscape:collect="always"
>
<stop
id="stop4158-3"
style="stop-color:#ffffff"
offset="0"
/>
<stop
id="stop4160-1"
style="stop-color:#ffffff;stop-opacity:0"
offset="1"
/>
</linearGradient
>
<filter
id="filter6126-9"
color-interpolation-filters="sRGB"
inkscape:collect="always"
>
<feGaussianBlur
id="feGaussianBlur6128-8"
stdDeviation="0.53035713"
inkscape:collect="always"
/>
</filter
>
<linearGradient
id="linearGradient8437"
y2="391.45"
gradientUnits="userSpaceOnUse"
y1="300.86"
x2="342"
x1="275.61"
inkscape:collect="always"
>
<stop
id="stop7173"
style="stop-color:#00112b"
offset="0"
/>
<stop
id="stop7175"
style="stop-color:#0055d4"
offset="1"
/>
</linearGradient
>
<radialGradient
id="radialGradient8439"
gradientUnits="userSpaceOnUse"
cx="312.78"
cy="386.57"
r="53.036"
gradientTransform="matrix(-.59327 -.59327 .71505 -.71505 243.27 849.03)"
inkscape:collect="always"
>
<stop
id="stop7113-50"
style="stop-color:#ffffff;stop-opacity:.40816"
offset="0"
/>
<stop
id="stop7115-28"
style="stop-color:#ffffff;stop-opacity:0"
offset="1"
/>
</radialGradient
>
<filter
id="filter10443"
color-interpolation-filters="sRGB"
inkscape:collect="always"
>
<feGaussianBlur
id="feGaussianBlur10445"
stdDeviation="1.3973845"
inkscape:collect="always"
/>
</filter
>
<linearGradient
id="linearGradient6858"
y2="338.82"
gradientUnits="userSpaceOnUse"
x2="300.27"
gradientTransform="matrix(2.7754 0 0 2.7754 -606.45 -52.271)"
y1="286.67"
x1="255.32"
inkscape:collect="always"
>
<stop
id="stop4150-0"
style="stop-color:#ffffff"
offset="0"
/>
<stop
id="stop4152-2"
style="stop-color:#ffffff;stop-opacity:0"
offset="1"
/>
</linearGradient
>
</defs
>
<sodipodi:namedview
id="base"
bordercolor="#666666"
inkscape:pageshadow="2"
inkscape:window-y="-8"
pagecolor="#ffffff"
inkscape:window-height="988"
inkscape:window-maximized="1"
inkscape:zoom="0.70710678"
inkscape:window-x="-8"
showgrid="false"
borderopacity="1.0"
inkscape:current-layer="layer1"
inkscape:cx="304.89409"
inkscape:cy="341.52186"
inkscape:window-width="1680"
inkscape:pageopacity="0.0"
inkscape:document-units="px"
/>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0 -652.36)"
>
<g
id="g6872"
>
<path
id="path7262"
sodipodi:rx="53.035713"
sodipodi:ry="53.035713"
style="fill:#999999"
sodipodi:type="arc"
d="m356.79 346.11a53.036 53.036 0 1 1 -106.07 0 53.036 53.036 0 1 1 106.07 0z"
transform="matrix(2.8283 0 0 2.8283 -653.01 -129.79)"
sodipodi:cy="346.11218"
sodipodi:cx="303.75"
/>
<path
id="path7264"
sodipodi:rx="53.035713"
sodipodi:ry="53.035713"
style="fill:url(#linearGradient8435)"
sodipodi:type="arc"
d="m356.79 346.11a53.036 53.036 0 1 1 -106.07 0 53.036 53.036 0 1 1 106.07 0z"
transform="matrix(2.7878 0 0 2.7878 -640.71 -115.77)"
sodipodi:cy="346.11218"
sodipodi:cx="303.75"
/>
<path
id="path7266"
sodipodi:rx="53.035713"
sodipodi:ry="53.035713"
style="filter:url(#filter6126-9);fill:#ececec"
sodipodi:type="arc"
d="m356.79 346.11a53.036 53.036 0 1 1 -106.07 0 53.036 53.036 0 1 1 106.07 0z"
transform="matrix(2.5378 0 0 2.5378 -564.77 -29.245)"
sodipodi:cy="346.11218"
sodipodi:cx="303.75"
/>
<path
id="path7268"
sodipodi:rx="53.035713"
sodipodi:ry="53.035713"
style="filter:url(#filter6126-9);fill:#999999"
sodipodi:type="arc"
d="m356.79 346.11a53.036 53.036 0 1 1 -106.07 0 53.036 53.036 0 1 1 106.07 0z"
transform="matrix(2.4356 0 0 2.4356 -533.74 6.1126)"
sodipodi:cy="346.11218"
sodipodi:cx="303.75"
/>
<path
id="path7270"
sodipodi:rx="53.035713"
sodipodi:ry="53.035713"
style="fill:url(#linearGradient8437)"
sodipodi:type="arc"
d="m356.79 346.11a53.036 53.036 0 1 1 -106.07 0 53.036 53.036 0 1 1 106.07 0z"
transform="matrix(2.3412 0 0 2.3412 -505.05 38.806)"
sodipodi:cy="346.11218"
sodipodi:cx="303.75"
/>
<path
id="path7272"
sodipodi:rx="53.035713"
sodipodi:ry="53.035713"
style="fill:url(#radialGradient8439)"
sodipodi:type="arc"
d="m356.79 346.11a53.036 53.036 0 1 1 -106.07 0 53.036 53.036 0 1 1 106.07 0z"
transform="matrix(2.2028 0 0 2.2028 -459.36 92.554)"
sodipodi:cy="346.11218"
sodipodi:cx="303.75"
/>
<path
id="path7274"
d="m203.16 732.39c-38.727 0.87355-76.074 21.376-96.845 57.353-22.341 38.696-19.505 85.022 3.3539 120.07 2.4783-77.078 61.391-135.13 134.58-130.89 23.993 1.3918 46.64 9.2967 66.408 22.052-9.4642-21.643-25.615-40.536-47.626-53.244-18.845-10.88-39.582-15.802-59.868-15.344z"
style="opacity:.31771;fill:url(#linearGradient6858)"
inkscape:connector-curvature="0"
/>
<g
id="text7350"
style="filter:url(#filter10443);fill:#1a1a1a"
transform="matrix(2.9051 0 0 2.9051 -1408.6 -93.103)"
>
<path
id="path6867"
style=""
d="m546.92 335.78c0.12959-2.1773 0.24624-3.7326 0.34993-4.6657 0.10367-0.93312 0.24623-1.7431 0.42769-2.4301 0.18143-0.68688 0.40824-1.296 0.68042-1.8274 0.27215-0.53135 0.66096-1.1275 1.1664-1.7885 0.50544-0.66095 1.147-1.4062 1.9246-2.2357 0.77761-0.82943 1.8533-1.944 3.2271-3.3438l1.2831-1.322c0.44063-0.41469 0.83592-0.84238 1.1859-1.2831 0.34991-0.44062 0.6156-0.82294 0.79707-1.147 0.18142-0.32397 0.31102-0.62206 0.38881-0.89426 0.0777-0.27213 0.11662-0.55078 0.11664-0.83595-0.00002-1.3219-0.71284-2.3199-2.1385-2.9938-1.4257-0.67389-3.4475-1.0109-6.0654-1.0109-3.6548 0.00004-7.8799 0.77766-12.675 2.3329l1.2053-6.0654c0.1296-0.69981 0.28513-1.5617 0.46658-2.5856 0.18144-1.0238 0.3888-2.3522 0.62209-3.9853 5.7025-0.82941 10.926-1.2441 15.669-1.2442 3.1364 0.00005 5.9812 0.23982 8.5344 0.7193 2.5532 0.47958 4.7823 1.3026 6.6875 2.4689 1.9051 1.1665 3.3632 2.5532 4.3741 4.1603s1.5163 3.3309 1.5164 5.1712c-0.00004 0.77766-0.0778 1.5682-0.23328 2.3718-0.15557 0.80358-0.37589 1.5682-0.66098 2.294-0.28517 0.72581-0.70638 1.5358-1.2636 2.4301-0.55734 0.8943-1.2118 1.795-1.9635 2.7022-0.75173 0.90726-1.3674 1.6006-1.8468 2.0801-0.47957 0.47956-1.3868 1.3544-2.7217 2.6245s-2.3523 2.2681-3.0522 2.9938c-0.69989 0.7258-1.2701 1.4127-1.7108 2.0607-0.44068 0.64804-0.78413 1.3414-1.0304 2.0801-0.24628 0.73876-0.47308 1.808-0.68042 3.2077-2.618-0.0777-4.9768-0.11663-7.0764-0.11665-2.0478 0.00002-4.5491 0.0259-7.504 0.0778zm-1.7885 16.758 0.38881-4.6657 0.50546-6.2987c0.0259-0.28512 0.0648-0.98498 0.11664-2.0996 3.2919 0.0519 5.9877 0.0778 8.0873 0.0778 2.2551 0.00001 4.899-0.0259 7.9317-0.0778-0.25924 2.955-0.42772 5.4693-0.50546 7.5429-0.0778 2.0737-0.16851 3.914-0.27216 5.5211-3.4993-0.0518-6.1173-0.0778-7.854-0.0778-1.8404 0-4.6398 0.0259-8.3983 0.0778z"
/>
</g
>
<g
id="text8454"
style="fill:#ffffff"
transform="translate(-100)"
>
<path
id="path6870"
d="m281.32 881.31c0.36286-6.0965 0.68946-10.451 0.9798-13.064 0.29028-2.6128 0.68946-4.8808 1.1975-6.8042 0.50801-1.9232 1.1431-3.6288 1.9052-5.1168 0.76204-1.4878 1.8507-3.1571 3.266-5.0079 1.4152-1.8507 3.2115-3.9373 5.3889-6.2599 2.1773-2.3224 5.1893-5.4433 9.036-9.3626l3.5926-3.7015c1.2338-1.1612 2.3406-2.3587 3.3204-3.5926 0.97975-1.2337 1.7237-2.3042 2.2318-3.2116 0.50798-0.90713 0.87087-1.7418 1.0887-2.504 0.21767-0.76196 0.32654-1.5422 0.3266-2.3406-0.00006-3.7014-1.996-6.4956-5.9877-8.3828-3.9918-1.8869-9.6529-2.8304-16.983-2.8305-10.234 0.00012-22.064 2.1775-35.491 6.532l3.3749-16.983c0.36288-1.9595 0.79835-4.3727 1.3064-7.2397 0.50804-2.8667 1.0887-6.5863 1.7419-11.159 15.967-2.3224 30.592-3.4836 43.873-3.4837 8.7819 0.00015 16.747 0.67149 23.896 2.014 7.1488 1.3428 13.391 3.6472 18.725 6.913 5.3344 3.2662 9.4169 7.1491 12.248 11.649 2.8304 4.5 4.2457 9.3264 4.2458 14.479-0.00012 2.1775-0.21785 4.3911-0.65321 6.6409-0.43558 2.25-1.0525 4.3911-1.8507 6.4232-0.79847 2.0323-1.9779 4.3004-3.5382 6.8042-1.5605 2.504-3.3931 5.0261-5.4978 7.5663-2.1049 2.5403-3.8286 4.4818-5.1712 5.8244-1.3428 1.3428-3.883 3.7923-7.6207 7.3485-3.7378 3.5564-6.5865 6.3506-8.5461 8.3828-1.9597 2.0322-3.5564 3.9556-4.7902 5.77-1.2339 1.8145-2.1956 3.756-2.885 5.8244-0.68956 2.0685-1.3246 5.0624-1.9052 8.9815-7.3304-0.21768-13.935-0.32655-19.814-0.3266-5.7337 0.00005-12.737 0.0726-21.011 0.21774zm-5.0079 46.922 1.0887-13.064 1.4153-17.636c0.0726-0.79833 0.18141-2.7579 0.3266-5.8788 9.2174 0.14519 16.765 0.21777 22.644 0.21773 6.3142 0.00004 13.717-0.0725 22.209-0.21773-0.72585 8.2739-1.1976 15.314-1.4153 21.12-0.21781 5.8062-0.47183 10.959-0.76207 15.459-9.7981-0.14515-17.128-0.21773-21.991-0.21773-5.1531 0-12.992 0.0726-23.515 0.21773z"
inkscape:connector-curvature="0"
/>
</g
>
</g
>
</g
>
<metadata
>
<rdf:RDF
>
<cc:Work
>
<dc:format
>image/svg+xml</dc:format
>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage"
/>
<cc:license
rdf:resource="http://creativecommons.org/licenses/publicdomain/"
/>
<dc:publisher
>
<cc:Agent
rdf:about="http://openclipart.org/"
>
<dc:title
>Openclipart</dc:title
>
</cc:Agent
>
</dc:publisher
>
<dc:title
>Question Button</dc:title
>
<dc:date
>2011-02-24T17:49:39</dc:date
>
<dc:description
/>
<dc:source
>https://openclipart.org/detail/122449/question-button-by-ricardomaia</dc:source
>
<dc:creator
>
<cc:Agent
>
<dc:title
>ricardomaia</dc:title
>
</cc:Agent
>
</dc:creator
>
<dc:subject
>
<rdf:Bag
>
<rdf:li
>blue</rdf:li
>
<rdf:li
>button</rdf:li
>
<rdf:li
>circle</rdf:li
>
<rdf:li
>confirm</rdf:li
>
<rdf:li
>help</rdf:li
>
<rdf:li
>question</rdf:li
>
<rdf:li
>round</rdf:li
>
</rdf:Bag
>
</dc:subject
>
</cc:Work
>
<cc:License
rdf:about="http://creativecommons.org/licenses/publicdomain/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:License
>
</rdf:RDF
>
</metadata
>
</svg
>

+ 249
- 0
plugins/community/repos/BaconMusic/res/HelpActiveSmall.svg View File

@@ -0,0 +1,249 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg4888"
sodipodi:docname="HelpActiveSmall.svg"
viewBox="0 0 20 20"
version="1.1"
inkscape:version="0.91 r13725"
width="20"
height="20">
<defs
id="defs4890">
<linearGradient
id="linearGradient8435"
y2="367.88"
gradientUnits="userSpaceOnUse"
y1="287.48999"
x2="315.47"
x1="241.41"
inkscape:collect="always">
<stop
id="stop4158-3"
style="stop-color:#ffffff"
offset="0" />
<stop
id="stop4160-1"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<filter
id="filter6126-9"
inkscape:collect="always"
style="color-interpolation-filters:sRGB">
<feGaussianBlur
id="feGaussianBlur6128-8"
stdDeviation="0.53035713"
inkscape:collect="always" />
</filter>
<linearGradient
id="linearGradient8437"
y2="391.45001"
gradientUnits="userSpaceOnUse"
y1="300.85999"
x2="342"
x1="275.60999"
inkscape:collect="always">
<stop
id="stop7173"
style="stop-color:#00112b"
offset="0" />
<stop
id="stop7175"
style="stop-color:#0055d4"
offset="1" />
</linearGradient>
<radialGradient
id="radialGradient8439"
gradientUnits="userSpaceOnUse"
cx="312.78"
cy="386.57001"
r="53.035999"
gradientTransform="matrix(-0.59327,-0.59327,0.71505,-0.71505,243.27,849.03)"
inkscape:collect="always">
<stop
id="stop7113-50"
style="stop-color:#ffffff;stop-opacity:.40816"
offset="0" />
<stop
id="stop7115-28"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</radialGradient>
<filter
id="filter10443"
inkscape:collect="always"
style="color-interpolation-filters:sRGB">
<feGaussianBlur
id="feGaussianBlur10445"
stdDeviation="1.3973845"
inkscape:collect="always" />
</filter>
<linearGradient
id="linearGradient6858"
y2="338.82001"
gradientUnits="userSpaceOnUse"
x2="300.26999"
gradientTransform="matrix(2.7754,0,0,2.7754,-606.45,-52.271)"
y1="286.67001"
x1="255.32001"
inkscape:collect="always">
<stop
id="stop4150-0"
style="stop-color:#ffffff"
offset="0" />
<stop
id="stop4152-2"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
bordercolor="#666666"
inkscape:pageshadow="2"
inkscape:window-y="1"
pagecolor="#ffffff"
inkscape:window-height="1845"
inkscape:window-maximized="1"
inkscape:zoom="50.862829"
inkscape:window-x="0"
showgrid="false"
borderopacity="1.0"
inkscape:current-layer="layer1"
inkscape:cx="10.925276"
inkscape:cy="9.494275"
inkscape:window-width="3360"
inkscape:pageopacity="0.0"
inkscape:document-units="px" />
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-1032.36)">
<g
id="g6872"
transform="matrix(0.05,0,0,0.05,-0.42108026,999.761)">
<circle
id="path7262"
style="fill:#999999"
transform="matrix(2.8283,0,0,2.8283,-653.01,-129.79)"
cx="303.75"
cy="346.11218"
r="53.035713" />
<circle
id="path7264"
style="fill:url(#linearGradient8435)"
transform="matrix(2.7878,0,0,2.7878,-640.71,-115.77)"
cx="303.75"
cy="346.11218"
r="53.035713" />
<circle
id="path7266"
style="fill:#ececec;filter:url(#filter6126-9)"
transform="matrix(2.5378,0,0,2.5378,-564.77,-29.245)"
cx="303.75"
cy="346.11218"
r="53.035713" />
<circle
id="path7268"
style="fill:#999999;filter:url(#filter6126-9)"
transform="matrix(2.4356,0,0,2.4356,-533.74,6.1126)"
cx="303.75"
cy="346.11218"
r="53.035713" />
<circle
id="path7270"
style="fill:url(#linearGradient8437)"
transform="matrix(2.3412,0,0,2.3412,-505.05,38.806)"
cx="303.75"
cy="346.11218"
r="53.035713" />
<circle
id="path7272"
style="fill:url(#radialGradient8439)"
transform="matrix(2.2028,0,0,2.2028,-459.36,92.554)"
cx="303.75"
cy="346.11218"
r="53.035713" />
<path
id="path7274"
d="m 203.16,732.39 c -38.727,0.87355 -76.074,21.376 -96.845,57.353 -22.341,38.696 -19.505,85.022 3.3539,120.07 2.4783,-77.078 61.391,-135.13 134.58,-130.89 23.993,1.3918 46.64,9.2967 66.408,22.052 -9.4642,-21.643 -25.615,-40.536 -47.626,-53.244 -18.845,-10.88 -39.582,-15.802 -59.868,-15.344 z"
style="opacity:0.31771001;fill:url(#linearGradient6858)"
inkscape:connector-curvature="0" />
<g
id="text7350"
style="fill:#1a1a1a;filter:url(#filter10443)"
transform="matrix(2.9051,0,0,2.9051,-1408.6,-93.103)">
<path
id="path6867"
d="m 546.92,335.78 c 0.12959,-2.1773 0.24624,-3.7326 0.34993,-4.6657 0.10367,-0.93312 0.24623,-1.7431 0.42769,-2.4301 0.18143,-0.68688 0.40824,-1.296 0.68042,-1.8274 0.27215,-0.53135 0.66096,-1.1275 1.1664,-1.7885 0.50544,-0.66095 1.147,-1.4062 1.9246,-2.2357 0.77761,-0.82943 1.8533,-1.944 3.2271,-3.3438 l 1.2831,-1.322 c 0.44063,-0.41469 0.83592,-0.84238 1.1859,-1.2831 0.34991,-0.44062 0.6156,-0.82294 0.79707,-1.147 0.18142,-0.32397 0.31102,-0.62206 0.38881,-0.89426 0.0777,-0.27213 0.11662,-0.55078 0.11664,-0.83595 -2e-5,-1.3219 -0.71284,-2.3199 -2.1385,-2.9938 -1.4257,-0.67389 -3.4475,-1.0109 -6.0654,-1.0109 -3.6548,4e-5 -7.8799,0.77766 -12.675,2.3329 l 1.2053,-6.0654 c 0.1296,-0.69981 0.28513,-1.5617 0.46658,-2.5856 0.18144,-1.0238 0.3888,-2.3522 0.62209,-3.9853 5.7025,-0.82941 10.926,-1.2441 15.669,-1.2442 3.1364,5e-5 5.9812,0.23982 8.5344,0.7193 2.5532,0.47958 4.7823,1.3026 6.6875,2.4689 1.9051,1.1665 3.3632,2.5532 4.3741,4.1603 1.0109,1.6071 1.5163,3.3309 1.5164,5.1712 -4e-5,0.77766 -0.0778,1.5682 -0.23328,2.3718 -0.15557,0.80358 -0.37589,1.5682 -0.66098,2.294 -0.28517,0.72581 -0.70638,1.5358 -1.2636,2.4301 -0.55734,0.8943 -1.2118,1.795 -1.9635,2.7022 -0.75173,0.90726 -1.3674,1.6006 -1.8468,2.0801 -0.47957,0.47956 -1.3868,1.3544 -2.7217,2.6245 -1.3349,1.2701 -2.3523,2.2681 -3.0522,2.9938 -0.69989,0.7258 -1.2701,1.4127 -1.7108,2.0607 -0.44068,0.64804 -0.78413,1.3414 -1.0304,2.0801 -0.24628,0.73876 -0.47308,1.808 -0.68042,3.2077 -2.618,-0.0777 -4.9768,-0.11663 -7.0764,-0.11665 -2.0478,2e-5 -4.5491,0.0259 -7.504,0.0778 z m -1.7885,16.758 0.38881,-4.6657 0.50546,-6.2987 c 0.0259,-0.28512 0.0648,-0.98498 0.11664,-2.0996 3.2919,0.0519 5.9877,0.0778 8.0873,0.0778 2.2551,10e-6 4.899,-0.0259 7.9317,-0.0778 -0.25924,2.955 -0.42772,5.4693 -0.50546,7.5429 -0.0778,2.0737 -0.16851,3.914 -0.27216,5.5211 -3.4993,-0.0518 -6.1173,-0.0778 -7.854,-0.0778 -1.8404,0 -4.6398,0.0259 -8.3983,0.0778 z"
inkscape:connector-curvature="0" />
</g>
<g
id="text8454"
style="fill:#ffffff"
transform="translate(-100,0)">
<path
id="path6870"
d="m 281.32,881.31 c 0.36286,-6.0965 0.68946,-10.451 0.9798,-13.064 0.29028,-2.6128 0.68946,-4.8808 1.1975,-6.8042 0.50801,-1.9232 1.1431,-3.6288 1.9052,-5.1168 0.76204,-1.4878 1.8507,-3.1571 3.266,-5.0079 1.4152,-1.8507 3.2115,-3.9373 5.3889,-6.2599 2.1773,-2.3224 5.1893,-5.4433 9.036,-9.3626 l 3.5926,-3.7015 c 1.2338,-1.1612 2.3406,-2.3587 3.3204,-3.5926 0.97975,-1.2337 1.7237,-2.3042 2.2318,-3.2116 0.50798,-0.90713 0.87087,-1.7418 1.0887,-2.504 0.21767,-0.76196 0.32654,-1.5422 0.3266,-2.3406 -6e-5,-3.7014 -1.996,-6.4956 -5.9877,-8.3828 -3.9918,-1.8869 -9.6529,-2.8304 -16.983,-2.8305 -10.234,1.2e-4 -22.064,2.1775 -35.491,6.532 l 3.3749,-16.983 c 0.36288,-1.9595 0.79835,-4.3727 1.3064,-7.2397 0.50804,-2.8667 1.0887,-6.5863 1.7419,-11.159 15.967,-2.3224 30.592,-3.4836 43.873,-3.4837 8.7819,1.5e-4 16.747,0.67149 23.896,2.014 7.1488,1.3428 13.391,3.6472 18.725,6.913 5.3344,3.2662 9.4169,7.1491 12.248,11.649 2.8304,4.5 4.2457,9.3264 4.2458,14.479 -1.2e-4,2.1775 -0.21785,4.3911 -0.65321,6.6409 -0.43558,2.25 -1.0525,4.3911 -1.8507,6.4232 -0.79847,2.0323 -1.9779,4.3004 -3.5382,6.8042 -1.5605,2.504 -3.3931,5.0261 -5.4978,7.5663 -2.1049,2.5403 -3.8286,4.4818 -5.1712,5.8244 -1.3428,1.3428 -3.883,3.7923 -7.6207,7.3485 -3.7378,3.5564 -6.5865,6.3506 -8.5461,8.3828 -1.9597,2.0322 -3.5564,3.9556 -4.7902,5.77 -1.2339,1.8145 -2.1956,3.756 -2.885,5.8244 -0.68956,2.0685 -1.3246,5.0624 -1.9052,8.9815 -7.3304,-0.21768 -13.935,-0.32655 -19.814,-0.3266 -5.7337,5e-5 -12.737,0.0726 -21.011,0.21774 z m -5.0079,46.922 1.0887,-13.064 1.4153,-17.636 c 0.0726,-0.79833 0.18141,-2.7579 0.3266,-5.8788 9.2174,0.14519 16.765,0.21777 22.644,0.21773 6.3142,4e-5 13.717,-0.0725 22.209,-0.21773 -0.72585,8.2739 -1.1976,15.314 -1.4153,21.12 -0.21781,5.8062 -0.47183,10.959 -0.76207,15.459 -9.7981,-0.14515 -17.128,-0.21773 -21.991,-0.21773 -5.1531,0 -12.992,0.0726 -23.515,0.21773 z"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
<metadata
id="metadata34">
<rdf:RDF>
<cc:Work>
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<cc:license
rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
<dc:publisher>
<cc:Agent
rdf:about="http://openclipart.org/">
<dc:title>Openclipart</dc:title>
</cc:Agent>
</dc:publisher>
<dc:title></dc:title>
<dc:date>2011-02-24T17:49:39</dc:date>
<dc:description />
<dc:source>https://openclipart.org/detail/122449/question-button-by-ricardomaia</dc:source>
<dc:creator>
<cc:Agent>
<dc:title>ricardomaia</dc:title>
</cc:Agent>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>blue</rdf:li>
<rdf:li>button</rdf:li>
<rdf:li>circle</rdf:li>
<rdf:li>confirm</rdf:li>
<rdf:li>help</rdf:li>
<rdf:li>question</rdf:li>
<rdf:li>round</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
</cc:License>
</rdf:RDF>
</metadata>
</svg>

+ 249
- 0
plugins/community/repos/BaconMusic/res/HelpGraySmall.svg View File

@@ -0,0 +1,249 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg4888"
sodipodi:docname="HelpGraySmall.svg"
viewBox="0 0 20 20"
version="1.1"
inkscape:version="0.91 r13725"
width="20"
height="20">
<sodipodi:namedview
id="base"
bordercolor="#666666"
inkscape:pageshadow="2"
inkscape:window-y="1"
pagecolor="#ffffff"
inkscape:window-height="1845"
inkscape:window-maximized="1"
inkscape:zoom="50.862829"
inkscape:window-x="0"
showgrid="false"
borderopacity="1.0"
inkscape:current-layer="layer1"
inkscape:cx="10.925276"
inkscape:cy="9.494275"
inkscape:window-width="3360"
inkscape:pageopacity="0.0"
inkscape:document-units="px" />
<defs
id="defs4890">
<filter
style="color-interpolation-filters:sRGB"
inkscape:collect="always"
id="filter6126-9">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.53035713"
id="feGaussianBlur6128-8" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
inkscape:collect="always"
id="filter10443">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="1.3973845"
id="feGaussianBlur10445" />
</filter>
<linearGradient
inkscape:collect="always"
x1="241.41"
x2="315.47"
y1="287.48999"
gradientUnits="userSpaceOnUse"
y2="367.88"
id="linearGradient8435-662">
<stop
offset="0"
style="stop-color:#ffffff"
id="stop4200" />
<stop
offset="1"
style="stop-color:#ffffff;stop-opacity:0"
id="stop4202" />
</linearGradient>
<linearGradient
inkscape:collect="always"
x1="275.60999"
x2="342"
y1="300.85999"
gradientUnits="userSpaceOnUse"
y2="391.45001"
id="linearGradient8437-613">
<stop
offset="0"
style="stop-color:#0f0f0f"
id="stop4205" />
<stop
offset="1"
style="stop-color:#4a4a4a"
id="stop4207" />
</linearGradient>
<radialGradient
inkscape:collect="always"
gradientTransform="matrix(-0.59327,-0.59327,0.71505,-0.71505,243.27,849.03)"
r="53.035999"
cy="386.57001"
cx="312.78"
gradientUnits="userSpaceOnUse"
id="radialGradient8439-369">
<stop
offset="0"
style="stop-color:#ffffff;stop-opacity:.40816"
id="stop4210" />
<stop
offset="1"
style="stop-color:#ffffff;stop-opacity:0"
id="stop4212" />
</radialGradient>
<linearGradient
inkscape:collect="always"
x1="255.32001"
y1="286.67001"
gradientTransform="matrix(2.7754,0,0,2.7754,-606.45,-52.271)"
x2="300.26999"
gradientUnits="userSpaceOnUse"
y2="338.82001"
id="linearGradient6858-674">
<stop
offset="0"
style="stop-color:#ffffff"
id="stop4215" />
<stop
offset="1"
style="stop-color:#ffffff;stop-opacity:0"
id="stop4217" />
</linearGradient>
</defs>
<g
transform="translate(0,-1032.36)"
inkscape:groupmode="layer"
inkscape:label="Layer 1"
id="layer1">
<g
transform="matrix(0.05,0,0,0.05,-0.42108026,999.761)"
id="g6872">
<circle
r="53.035713"
cy="346.11218"
cx="303.75"
transform="matrix(2.8283,0,0,2.8283,-653.01,-129.79)"
style="fill:#999999"
id="path7262" />
<circle
r="53.035713"
cy="346.11218"
cx="303.75"
transform="matrix(2.7878,0,0,2.7878,-640.71,-115.77)"
style="fill:url(#linearGradient8435-662)"
id="path7264" />
<circle
r="53.035713"
cy="346.11218"
cx="303.75"
transform="matrix(2.5378,0,0,2.5378,-564.77,-29.245)"
style="fill:#ececec;filter:url(#filter6126-9)"
id="path7266" />
<circle
r="53.035713"
cy="346.11218"
cx="303.75"
transform="matrix(2.4356,0,0,2.4356,-533.74,6.1126)"
style="fill:#999999;filter:url(#filter6126-9)"
id="path7268" />
<circle
r="53.035713"
cy="346.11218"
cx="303.75"
transform="matrix(2.3412,0,0,2.3412,-505.05,38.806)"
style="fill:url(#linearGradient8437-613)"
id="path7270" />
<circle
r="53.035713"
cy="346.11218"
cx="303.75"
transform="matrix(2.2028,0,0,2.2028,-459.36,92.554)"
style="fill:url(#radialGradient8439-369)"
id="path7272" />
<path
inkscape:connector-curvature="0"
style="opacity:0.31771001;fill:url(#linearGradient6858-674)"
d="m 203.16,732.39 c -38.727,0.87355 -76.074,21.376 -96.845,57.353 -22.341,38.696 -19.505,85.022 3.3539,120.07 2.4783,-77.078 61.391,-135.13 134.58,-130.89 23.993,1.3918 46.64,9.2967 66.408,22.052 -9.4642,-21.643 -25.615,-40.536 -47.626,-53.244 -18.845,-10.88 -39.582,-15.802 -59.868,-15.344 z"
id="path7274" />
<g
transform="matrix(2.9051,0,0,2.9051,-1408.6,-93.103)"
style="fill:#1a1a1a;filter:url(#filter10443)"
id="text7350">
<path
inkscape:connector-curvature="0"
d="m 546.92,335.78 c 0.12959,-2.1773 0.24624,-3.7326 0.34993,-4.6657 0.10367,-0.93312 0.24623,-1.7431 0.42769,-2.4301 0.18143,-0.68688 0.40824,-1.296 0.68042,-1.8274 0.27215,-0.53135 0.66096,-1.1275 1.1664,-1.7885 0.50544,-0.66095 1.147,-1.4062 1.9246,-2.2357 0.77761,-0.82943 1.8533,-1.944 3.2271,-3.3438 l 1.2831,-1.322 c 0.44063,-0.41469 0.83592,-0.84238 1.1859,-1.2831 0.34991,-0.44062 0.6156,-0.82294 0.79707,-1.147 0.18142,-0.32397 0.31102,-0.62206 0.38881,-0.89426 0.0777,-0.27213 0.11662,-0.55078 0.11664,-0.83595 -2e-5,-1.3219 -0.71284,-2.3199 -2.1385,-2.9938 -1.4257,-0.67389 -3.4475,-1.0109 -6.0654,-1.0109 -3.6548,4e-5 -7.8799,0.77766 -12.675,2.3329 l 1.2053,-6.0654 c 0.1296,-0.69981 0.28513,-1.5617 0.46658,-2.5856 0.18144,-1.0238 0.3888,-2.3522 0.62209,-3.9853 5.7025,-0.82941 10.926,-1.2441 15.669,-1.2442 3.1364,5e-5 5.9812,0.23982 8.5344,0.7193 2.5532,0.47958 4.7823,1.3026 6.6875,2.4689 1.9051,1.1665 3.3632,2.5532 4.3741,4.1603 1.0109,1.6071 1.5163,3.3309 1.5164,5.1712 -4e-5,0.77766 -0.0778,1.5682 -0.23328,2.3718 -0.15557,0.80358 -0.37589,1.5682 -0.66098,2.294 -0.28517,0.72581 -0.70638,1.5358 -1.2636,2.4301 -0.55734,0.8943 -1.2118,1.795 -1.9635,2.7022 -0.75173,0.90726 -1.3674,1.6006 -1.8468,2.0801 -0.47957,0.47956 -1.3868,1.3544 -2.7217,2.6245 -1.3349,1.2701 -2.3523,2.2681 -3.0522,2.9938 -0.69989,0.7258 -1.2701,1.4127 -1.7108,2.0607 -0.44068,0.64804 -0.78413,1.3414 -1.0304,2.0801 -0.24628,0.73876 -0.47308,1.808 -0.68042,3.2077 -2.618,-0.0777 -4.9768,-0.11663 -7.0764,-0.11665 -2.0478,2e-5 -4.5491,0.0259 -7.504,0.0778 z m -1.7885,16.758 0.38881,-4.6657 0.50546,-6.2987 c 0.0259,-0.28512 0.0648,-0.98498 0.11664,-2.0996 3.2919,0.0519 5.9877,0.0778 8.0873,0.0778 2.2551,10e-6 4.899,-0.0259 7.9317,-0.0778 -0.25924,2.955 -0.42772,5.4693 -0.50546,7.5429 -0.0778,2.0737 -0.16851,3.914 -0.27216,5.5211 -3.4993,-0.0518 -6.1173,-0.0778 -7.854,-0.0778 -1.8404,0 -4.6398,0.0259 -8.3983,0.0778 z"
id="path6867" />
</g>
<g
transform="translate(-100,0)"
style="fill:#ffffff"
id="text8454">
<path
inkscape:connector-curvature="0"
d="m 281.32,881.31 c 0.36286,-6.0965 0.68946,-10.451 0.9798,-13.064 0.29028,-2.6128 0.68946,-4.8808 1.1975,-6.8042 0.50801,-1.9232 1.1431,-3.6288 1.9052,-5.1168 0.76204,-1.4878 1.8507,-3.1571 3.266,-5.0079 1.4152,-1.8507 3.2115,-3.9373 5.3889,-6.2599 2.1773,-2.3224 5.1893,-5.4433 9.036,-9.3626 l 3.5926,-3.7015 c 1.2338,-1.1612 2.3406,-2.3587 3.3204,-3.5926 0.97975,-1.2337 1.7237,-2.3042 2.2318,-3.2116 0.50798,-0.90713 0.87087,-1.7418 1.0887,-2.504 0.21767,-0.76196 0.32654,-1.5422 0.3266,-2.3406 -6e-5,-3.7014 -1.996,-6.4956 -5.9877,-8.3828 -3.9918,-1.8869 -9.6529,-2.8304 -16.983,-2.8305 -10.234,1.2e-4 -22.064,2.1775 -35.491,6.532 l 3.3749,-16.983 c 0.36288,-1.9595 0.79835,-4.3727 1.3064,-7.2397 0.50804,-2.8667 1.0887,-6.5863 1.7419,-11.159 15.967,-2.3224 30.592,-3.4836 43.873,-3.4837 8.7819,1.5e-4 16.747,0.67149 23.896,2.014 7.1488,1.3428 13.391,3.6472 18.725,6.913 5.3344,3.2662 9.4169,7.1491 12.248,11.649 2.8304,4.5 4.2457,9.3264 4.2458,14.479 -1.2e-4,2.1775 -0.21785,4.3911 -0.65321,6.6409 -0.43558,2.25 -1.0525,4.3911 -1.8507,6.4232 -0.79847,2.0323 -1.9779,4.3004 -3.5382,6.8042 -1.5605,2.504 -3.3931,5.0261 -5.4978,7.5663 -2.1049,2.5403 -3.8286,4.4818 -5.1712,5.8244 -1.3428,1.3428 -3.883,3.7923 -7.6207,7.3485 -3.7378,3.5564 -6.5865,6.3506 -8.5461,8.3828 -1.9597,2.0322 -3.5564,3.9556 -4.7902,5.77 -1.2339,1.8145 -2.1956,3.756 -2.885,5.8244 -0.68956,2.0685 -1.3246,5.0624 -1.9052,8.9815 -7.3304,-0.21768 -13.935,-0.32655 -19.814,-0.3266 -5.7337,5e-5 -12.737,0.0726 -21.011,0.21774 z m -5.0079,46.922 1.0887,-13.064 1.4153,-17.636 c 0.0726,-0.79833 0.18141,-2.7579 0.3266,-5.8788 9.2174,0.14519 16.765,0.21777 22.644,0.21773 6.3142,4e-5 13.717,-0.0725 22.209,-0.21773 -0.72585,8.2739 -1.1976,15.314 -1.4153,21.12 -0.21781,5.8062 -0.47183,10.959 -0.76207,15.459 -9.7981,-0.14515 -17.128,-0.21773 -21.991,-0.21773 -5.1531,0 -12.992,0.0726 -23.515,0.21773 z"
id="path6870" />
</g>
</g>
</g>
<metadata
id="metadata34">
<rdf:RDF>
<cc:Work>
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<cc:license
rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
<dc:publisher>
<cc:Agent
rdf:about="http://openclipart.org/">
<dc:title>Openclipart</dc:title>
</cc:Agent>
</dc:publisher>
<dc:title></dc:title>
<dc:date>2011-02-24T17:49:39</dc:date>
<dc:description />
<dc:source>https://openclipart.org/detail/122449/question-button-by-ricardomaia</dc:source>
<dc:creator>
<cc:Agent>
<dc:title>ricardomaia</dc:title>
</cc:Agent>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>blue</rdf:li>
<rdf:li>button</rdf:li>
<rdf:li>circle</rdf:li>
<rdf:li>confirm</rdf:li>
<rdf:li>help</rdf:li>
<rdf:li>question</rdf:li>
<rdf:li>round</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
</cc:License>
</rdf:RDF>
</metadata>
</svg>

+ 669
- 0
plugins/community/repos/BaconMusic/res/Keypunch029.json View File

@@ -0,0 +1,669 @@
{
"!" : [
"...#.",
"...#.",
"...#.",
"...#.",
"...#.",
".....",
"...#."
],
"\"" : [
".#.#.",
".#.#.",
".#.#.",
".....",
".....",
".....",
"....."
],
"#" : [
".#.#.",
".#.#.",
"##.##",
".....",
"##.##",
".#.#.",
".#.#."
],
"$" : [
"..#..",
".####",
"#....",
".###.",
"....#",
"####.",
"..#.."
],
"%" : [
"##..#",
"##..#",
"...#.",
"..#..",
".#...",
"#..##",
"#..##"
],
"&" : [
".#...",
"#.#..",
"#.#..",
".#...",
"#.#.#",
"#..#.",
".##.#"
],
"'" : [
".##..",
".##..",
".##..",
".....",
".....",
".....",
"....."
],
"(" : [
"...#.",
"..#..",
".#...",
".#...",
".#...",
"..#..",
"...#."
],
")" : [
".#...",
"..#..",
"...#.",
"...#.",
"...#.",
"..#..",
".#..."
],
"*" : [
"#.#.#",
".###.",
"#####",
".###.",
"#.#.#",
".....",
"....."
],
"+" : [
".....",
"..#..",
"..#..",
"#####",
"..#..",
"..#..",
"....."
],
"," : [
".....",
".....",
".....",
".##..",
".##..",
"..#..",
".#..."
],
"-" : [
".....",
".....",
".....",
".....",
"#####",
".....",
"....."
],
"." : [
".....",
".....",
".....",
".....",
".....",
".##..",
".##.."
],
"/" : [
".....",
"....#",
"...#.",
"..#..",
".#...",
"#....",
"....."
],
"0" : [
"..##.",
".#..#",
".#..#",
".#..#",
".#..#",
".#..#",
"..##."
],
"1" : [
"..#..",
".##..",
"..#..",
"..#..",
"..#..",
"..#..",
".###."
],
"2" : [
".###.",
"#...#",
"....#",
".###.",
"#....",
"#....",
"#####"
],
"3" : [
".###.",
"#...#",
"....#",
"..##.",
"....#",
"#...#",
".###."
],
"4" : [
"...#.",
"..##.",
".#.#.",
"#..#.",
"#####",
"...#.",
"...#."
],
"5" : [
"#####",
"#....",
"####.",
"....#",
"....#",
"#...#",
".###."
],
"6" : [
"..##.",
".#...",
"#....",
"####.",
"#...#",
"#...#",
".###."
],
"7" : [
"#####",
"....#",
"...#.",
"..#..",
".#...",
".#...",
".#..."
],
"8" : [
".###.",
"#...#",
"#...#",
".###.",
"#...#",
"#...#",
".###."
],
"9" : [
".###.",
"#...#",
"#...#",
".####",
"....#",
"...#.",
".##.."
],
":" : [
".....",
".##..",
".##..",
".....",
".##..",
".##..",
"....."
],
";" : [
".##..",
".##..",
".....",
".##..",
".##..",
"..#..",
".#..."
],
"<" : [
"....#",
"...#.",
"..#..",
".#...",
"..#..",
"...#.",
"....#"
],
"=" : [
".....",
".....",
"#####",
".....",
"#####",
".....",
"....."
],
">" : [
"#....",
".#...",
"..#..",
"...#.",
"..#..",
".#...",
"#...."
],
"?" : [
".##..",
"#..#.",
"...#.",
"..#..",
"..#..",
".....",
"..#.."
],
"@" : [
".###.",
"#...#",
"....#",
".##.#",
"#.#.#",
"#.#.#",
".###."
],
"A" : [
"..#..",
".#.#.",
"#...#",
"#...#",
"#####",
"#...#",
"#...#"
],
"B" : [
"####.",
".#..#",
".#..#",
".###.",
".#..#",
".#..#",
"####."
],
"C" : [
".###.",
"#...#",
"#....",
"#....",
"#....",
"#...#",
".###."
],
"D" : [
"####.",
".#..#",
".#..#",
".#..#",
".#..#",
".#..#",
"####."
],
"E" : [
"#####",
"#....",
"#....",
"###..",
"#....",
"#....",
"#####"
],
"F" : [
"#####",
"#....",
"#....",
"###..",
"#....",
"#....",
"#...."
],
"G" : [
".####",
"#....",
"#....",
"#..##",
"#...#",
"#...#",
".####"
],
"H" : [
"#...#",
"#...#",
"#...#",
"#####",
"#...#",
"#...#",
"#...#"
],
"I" : [
".###.",
"..#..",
"..#..",
"..#..",
"..#..",
"..#..",
".###."
],
"J" : [
"....#",
"....#",
"....#",
"....#",
"....#",
"#...#",
".###."
],
"K" : [
"#...#",
"#..#.",
"#.#..",
"##...",
"#.#..",
"#..#.",
"#...#"
],
"L" : [
"#....",
"#....",
"#....",
"#....",
"#....",
"#....",
"#####"
],
"M" : [
"#...#",
"##.##",
"#.#.#",
"#.#.#",
"#...#",
"#...#",
"#...#"
],
"N" : [
"#...#",
"##..#",
"#.#.#",
"#..##",
"#...#",
"#...#",
"#...#"
],
"O" : [
"#####",
"#...#",
"#...#",
"#...#",
"#...#",
"#...#",
"#####"
],
"P" : [
"####.",
"#...#",
"#...#",
"####.",
"#....",
"#....",
"#...."
],
"Q" : [
".###.",
"#...#",
"#...#",
"#...#",
"#.#.#",
"#..#.",
".##.#"
],
"R" : [
"####.",
"#...#",
"#...#",
"####.",
"#.#..",
"#..#.",
"#...#"
],
"S" : [
".###.",
"#...#",
".#...",
"..#..",
"...#.",
"#...#",
".###."
],
"T" : [
"#####",
"..#..",
"..#..",
"..#..",
"..#..",
"..#..",
"..#.."
],
"U" : [
"#...#",
"#...#",
"#...#",
"#...#",
"#...#",
"#...#",
".###."
],
"V" : [
"#...#",
"#...#",
"#...#",
".#.#.",
".#.#.",
"..#..",
"..#.."
],
"W" : [
"#...#",
"#...#",
"#...#",
"#...#",
"#.#.#",
"##.##",
"#...#"
],
"X" : [
"#...#",
"#...#",
".#.#.",
"..#..",
".#.#.",
"#...#",
"#...#"
],
"Y" : [
"#...#",
"#...#",
".#.#.",
"..#..",
"..#..",
"..#..",
"..#.."
],
"Z" : [
"#####",
"....#",
"...#.",
"..#..",
".#...",
"#....",
"#####"
],
"\\" : [
".....",
"#....",
".#...",
"..#..",
"...#.",
"....#",
"....."
],
"_" : [
".....",
".....",
".....",
".....",
".....",
".....",
"#####"
],
"|" : [
".....",
"..#..",
"..#..",
"..#..",
"..#..",
"..#..",
"....."
],
"¢" : [
"..#..",
".###.",
"#....",
"#....",
"#....",
".###.",
"..#.."
],
"¬" : [
".....",
".....",
".....",
".....",
"#####",
"....#",
"....#"
],
" " : [
".....",
".....",
".....",
".....",
".....",
".....",
"....."
],
"[" : [
"###..",
"#....",
"#....",
"#....",
"#....",
"#....",
"###.."
],
"]" : [
"..###",
"....#",
"....#",
"....#",
"....#",
"....#",
"..###"
],
"^" : [
"..#..",
".#.#.",
"#...#",
".....",
".....",
".....",
"....."
],
"`" : [
"#....",
".#...",
"..#..",
".....",
".....",
".....",
"....."
],
"{" : [
"..##.",
".#...",
".#...",
"#....",
".#...",
".#...",
"..##."
],
"}" : [
".##..",
"...#.",
"...#.",
"....#",
"...#.",
"...#.",
".##.."
],
"~" : [
".....",
".....",
".#...",
"#.#.#",
"...#.",
".....",
"....."
],
"€" : [
"..###",
".#...",
"###..",
".#...",
"###..",
".#...",
"..###"
],
"ÂŁ" : [
"..###",
".#...",
".#...",
"###..",
".#...",
".#...",
"#####"
],
"⌑" : [
"#...#",
".###.",
".#.#.",
".#.#.",
".#.#.",
".###.",
"#...#"
]
}


BIN
plugins/community/repos/BaconMusic/res/Monitorica-Bd.ttf View File


+ 3
- 0
plugins/community/repos/BaconMusic/res/README.md View File

@@ -0,0 +1,3 @@
Wood Grain from https://publicdomainvectors.org/en/free-clipart/Wood-grain/43630.html
KeyPunch from http://scruss.com/blog/tag/font/
Monitoria font: http://www.1001fonts.com/monitorica-font.html

+ 115
- 0
plugins/community/repos/BaconMusic/src/ALingADing.cpp View File

@@ -0,0 +1,115 @@
#include "BaconPlugs.hpp"

/*
** Based heavily on http://recherche.ircam.fr/pub/dafx11/Papers/66_e.pdf
*/

namespace rack_plugin_BaconMusic {

struct ALingADing : Module {
enum ParamIds {
WET_DRY_MIX, // TODO: Implement this
NUM_PARAMS
};

enum InputIds {
SIGNAL_INPUT,
CARRIER_INPUT,

NUM_INPUTS
};

enum OutputIds {
MODULATED_OUTPUT,
NUM_OUTPUTS
};

enum LightIds {
NUM_LIGHTS
};

ALingADing() : Module( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS ) {
params[ WET_DRY_MIX ].value = 1.0;
}


inline float diode_sim( float in )
{
if( in < 0 ) return 0;
else return 0.2 * log( 1.0 + exp( 10 * ( in - 1 ) ) );
}
void step() override
{
float vin = inputs[ SIGNAL_INPUT ].value;
float vc = inputs[ CARRIER_INPUT ].value;
float wd = params[ WET_DRY_MIX ].value;

float A = 0.5 * vin + vc;
float B = vc - 0.5 * vin;

float dPA = diode_sim( A );
float dMA = diode_sim( -A );
float dPB = diode_sim( B );
float dMB = diode_sim( -B );

float res = dPA + dMA - dPB - dMB;
outputs[ MODULATED_OUTPUT ].value = wd * res + ( 1.0 - wd ) * vin;
}
};

struct ALingADingWidget : ModuleWidget {
ALingADingWidget(ALingADing *module);
};


ALingADingWidget::ALingADingWidget(ALingADing *module) : ModuleWidget( module )
{
box.size = Vec( SCREW_WIDTH * 5, RACK_HEIGHT );

BaconBackground *bg = new BaconBackground( box.size, "ALingADing" );
addChild( bg->wrappedInFramebuffer() );
bg->addPlugLabel( Vec( 7, 70 ), BaconBackground::SIG_IN, "sig" );
addInput( Port::create< PJ301MPort >( Vec( 7, 70 ),
Port::INPUT,
module,
ALingADing::SIGNAL_INPUT ) );
bg->addPlugLabel( Vec( box.size.x-24-7, 70 ), BaconBackground::SIG_IN, "car" );
addInput( Port::create< PJ301MPort >( Vec( box.size.x-24 - 7, 70 ), // That 24 makes no sense but hey
Port::INPUT,
module,
ALingADing::CARRIER_INPUT ) );
bg->addLabel( Vec( bg->cx(), 140 ), "Mix", 14, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE );
bg->addLabel( Vec( bg->cx() + 10, 140 + 72 ),
"Wet", 13, NVG_ALIGN_LEFT | NVG_ALIGN_TOP );
bg->addLabel( Vec( bg->cx() - 10, 140 + 72 ),
"Dry", 13, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP );

addParam( ParamWidget::create< RoundHugeBlackKnob >( Vec( bg->cx( 56 ), 150 ),
module,
ALingADing::WET_DRY_MIX,
0, 1, 1 ));

Vec outP = Vec( bg->cx( 24 ), RACK_HEIGHT - 15 - 43 );
bg->addPlugLabel( outP, BaconBackground::SIG_OUT, "out" );
addOutput( Port::create< PJ301MPort >( outP,
Port::OUTPUT,
module,
ALingADing::MODULATED_OUTPUT ) );
}

} // namespace rack_plugin_BaconMusic

using namespace rack_plugin_BaconMusic;

RACK_PLUGIN_MODEL_INIT(BaconMusic, ALingADing) {
Model *modelALingADing = Model::create<ALingADing,ALingADingWidget>("Bacon Music", "ALingADing", "ALingADing", RING_MODULATOR_TAG);
return modelALingADing;
}

+ 45
- 0
plugins/community/repos/BaconMusic/src/BaconPlugs.cpp View File

@@ -0,0 +1,45 @@
#include "BaconPlugs.hpp"

// RACK_PLUGIN_MODEL_DECLARE(BaconMusic, HarMoNee); // crashes
RACK_PLUGIN_MODEL_DECLARE(BaconMusic, Glissinator);
RACK_PLUGIN_MODEL_DECLARE(BaconMusic, PolyGnome);
RACK_PLUGIN_MODEL_DECLARE(BaconMusic, QuantEyes);
RACK_PLUGIN_MODEL_DECLARE(BaconMusic, SampleDelay);
#ifdef BUILD_SORTACHORUS
RACK_PLUGIN_MODEL_DECLARE(BaconMusic, SortaChorus);
#endif
RACK_PLUGIN_MODEL_DECLARE(BaconMusic, ChipNoise);
RACK_PLUGIN_MODEL_DECLARE(BaconMusic, ChipWaves);
RACK_PLUGIN_MODEL_DECLARE(BaconMusic, ChipYourWave);

RACK_PLUGIN_MODEL_DECLARE(BaconMusic, KarplusStrongPoly);
RACK_PLUGIN_MODEL_DECLARE(BaconMusic, ALingADing);
RACK_PLUGIN_MODEL_DECLARE(BaconMusic, Bitulator);

RACK_PLUGIN_INIT(BaconMusic) {
RACK_PLUGIN_INIT_ID();

RACK_PLUGIN_INIT_WEBSITE("https://github.com/baconpaul/Bacon Music");
// RACK_PLUGIN_MODEL_ADD(BaconMusic, HarMoNee); // crashes
RACK_PLUGIN_MODEL_ADD(BaconMusic, Glissinator);
RACK_PLUGIN_MODEL_ADD(BaconMusic, PolyGnome);
RACK_PLUGIN_MODEL_ADD(BaconMusic, QuantEyes);
RACK_PLUGIN_MODEL_ADD(BaconMusic, SampleDelay);
#ifdef BUILD_SORTACHORUS
RACK_PLUGIN_MODEL_ADD(BaconMusic, SortaChorus);
#endif
RACK_PLUGIN_MODEL_ADD(BaconMusic, ChipNoise);
RACK_PLUGIN_MODEL_ADD(BaconMusic, ChipWaves);
RACK_PLUGIN_MODEL_ADD(BaconMusic, ChipYourWave);

RACK_PLUGIN_MODEL_ADD(BaconMusic, KarplusStrongPoly);
RACK_PLUGIN_MODEL_ADD(BaconMusic, ALingADing);
RACK_PLUGIN_MODEL_ADD(BaconMusic, Bitulator);
}

+ 23
- 0
plugins/community/repos/BaconMusic/src/BaconPlugs.hpp View File

@@ -0,0 +1,23 @@
#ifndef INCLUDE_BACONPLUGS_HPP
#define INCLUDE_BACONPLUGS_HPP

#include "rack.hpp"

#include <map>
#include <vector>
#include <string>

using namespace rack;

#define SCREW_WIDTH 15
#define RACK_HEIGHT 380

RACK_PLUGIN_DECLARE(BaconMusic);

#ifdef USE_VST2
#define plugin "BaconMusic"
#endif // USE_VST2

#include "Components.hpp"

#endif

+ 155
- 0
plugins/community/repos/BaconMusic/src/Bitulator.cpp View File

@@ -0,0 +1,155 @@
#include "BaconPlugs.hpp"

/*
** ToDo:
** Add lights for on/off
** Add a 7 segment display for step count
*/

namespace rack_plugin_BaconMusic {

struct Bitulator : Module {
enum ParamIds {
WET_DRY_MIX,
STEP_COUNT,
AMP_LEVEL,
BITULATE,
CLIPULATE,
NUM_PARAMS
};

enum InputIds {
SIGNAL_INPUT,
NUM_INPUTS
};

enum OutputIds {
CRUNCHED_OUTPUT,
NUM_OUTPUTS
};

enum LightIds {
BITULATING_LIGHT,
CRUNCHING_LIGHT,
NUM_LIGHTS
};

Bitulator() : Module( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS ) {
params[ WET_DRY_MIX ].value = 1.0;
params[ STEP_COUNT ].value = 6;
params[ AMP_LEVEL ].value = 1;
params[ BITULATE ].value = 1;
params[ CLIPULATE ].value = 1;

lights[ BITULATING_LIGHT ].value = 1;
lights[ CRUNCHING_LIGHT ].value = 1;
}


void step() override
{
float vin = inputs[ SIGNAL_INPUT ].value;
float wd = params[ WET_DRY_MIX ].value;

// Signals are +/-5V signals of course. So

float res = 0;
if( params[ BITULATE ].value > 0 ) {
float qi = params[ STEP_COUNT ].value / 2;
float crunch = (int)( (vin/5.0) * qi ) / qi * 5.0;

res = crunch;
lights[ BITULATING_LIGHT ].value = 1;
}
else
{
res = vin;
lights[ BITULATING_LIGHT ].value = 0;
}

if( params[ CLIPULATE ].value > 0 ) {
float al = params[ AMP_LEVEL ].value;
res = clamp( res * al, -5.0f, 5.0f );
lights[ CRUNCHING_LIGHT ].value = 1;
}
else {
lights[ CRUNCHING_LIGHT ].value = 0;
}

outputs[ CRUNCHED_OUTPUT ].value = wd * res + ( 1.0 - wd ) * vin;
}
};

struct BitulatorWidget : ModuleWidget {
BitulatorWidget( Bitulator *model );
};

BitulatorWidget::BitulatorWidget( Bitulator *model ) : ModuleWidget( model )
{
box.size = Vec( SCREW_WIDTH * 6, RACK_HEIGHT );

BaconBackground *bg = new BaconBackground( box.size, "Bitulator" );
addChild( bg->wrappedInFramebuffer() );
int wdpos = 40;
bg->addLabel( Vec( bg->cx(), wdpos ), "Mix", 14, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE );
bg->addLabel( Vec( bg->cx() + 10, wdpos + 72 ), "Wet", 13, NVG_ALIGN_LEFT | NVG_ALIGN_TOP );
bg->addLabel( Vec( bg->cx() - 10, wdpos + 72 ), "Dry", 13, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP );

addParam( ParamWidget::create< RoundHugeBlackKnob >( Vec( bg->cx( 56 ), wdpos + 10 ),
module,
Bitulator::WET_DRY_MIX,
0, 1, 1 ));

Vec cr( 5, 140 ), rs( box.size.x-10, 70 );
bg->addRoundedBorder( cr, rs );
bg->addLabel( Vec( bg->cx(), cr.y+3 ), "Quantize", 14, NVG_ALIGN_CENTER|NVG_ALIGN_TOP );
addChild( ModuleLightWidget::create< SmallLight< BlueLight > >( cr.plus( Vec( 5, 5 ) ), module, Bitulator::BITULATING_LIGHT ) );
addParam( ParamWidget::create< CKSS >( cr.plus( Vec( 5, 25 ) ), module, Bitulator::BITULATE, 0, 1, 1 ) );
Vec knobPos = Vec( cr.x + rs.x - 36 - 12, cr.y + 18 );
Vec knobCtr = knobPos.plus( Vec( 18, 18 ) );
addParam( ParamWidget::create< RoundLargeBlackKnob >( knobPos,
module,
Bitulator::STEP_COUNT,
2, 16, 6 ));
bg->addLabel( knobCtr.plus( Vec( 8, 21 ) ), "smth", 10, NVG_ALIGN_LEFT | NVG_ALIGN_TOP );
bg->addLabel( knobCtr.plus( Vec( -8, 21 ) ), "crnch", 10, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP );
cr = Vec( 5, 215 );
bg->addRoundedBorder( cr, rs );
bg->addLabel( Vec( bg->cx( 5 ), cr.y+3 ), "Amp'n'Clip", 14, NVG_ALIGN_CENTER|NVG_ALIGN_TOP );
addChild( ModuleLightWidget::create< SmallLight< BlueLight > >( cr.plus( Vec( 5, 5 ) ), module, Bitulator::CRUNCHING_LIGHT ) );
addParam( ParamWidget::create< CKSS >( cr.plus( Vec( 5, 25 ) ), module, Bitulator::CLIPULATE, 0, 1, 1 ) );
knobPos = Vec( cr.x + rs.x - 36 - 12, cr.y + 18 );
knobCtr = knobPos.plus( Vec( 18, 18 ) );
addParam( ParamWidget::create< RoundLargeBlackKnob >( knobPos,
module,
Bitulator::AMP_LEVEL,
1, 10, 1 ) );
bg->addLabel( knobCtr.plus( Vec( 12, 21 ) ), "11", 10, NVG_ALIGN_LEFT | NVG_ALIGN_TOP );
bg->addLabel( knobCtr.plus( Vec( -8, 21 ) ), "one", 10, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP );
Vec inP = Vec( 10, RACK_HEIGHT - 15 - 43 );
Vec outP = Vec( box.size.x - 24 - 10, RACK_HEIGHT - 15 - 43 );
bg->addPlugLabel( inP, BaconBackground::SIG_IN, "in" );
addInput( Port::create< PJ301MPort >( inP, Port::INPUT,
module,
Bitulator::SIGNAL_INPUT ) );

bg->addPlugLabel( outP, BaconBackground::SIG_OUT, "out" );
addOutput( Port::create< PJ301MPort >( outP, Port::OUTPUT,
module,
Bitulator::CRUNCHED_OUTPUT ) );
}

} // namespace rack_plugin_BaconMusic

using namespace rack_plugin_BaconMusic;

RACK_PLUGIN_MODEL_INIT(BaconMusic, Bitulator) {
Model *modelBitulator = Model::create< Bitulator, BitulatorWidget >("Bacon Music", "Bitulator", "Bitulator", DISTORTION_TAG);
return modelBitulator;
}

+ 45
- 0
plugins/community/repos/BaconMusic/src/BlankWidget.cpp View File

@@ -0,0 +1,45 @@
#if 0

#include "BaconPlugs.hpp"

struct MODULE_NAME : virtual Module {
enum ParamIds {
NUM_PARAMS
};

enum InputIds {
NUM_INPUTS
};

enum OutputIds {
NUM_OUTPUTS
};

enum LightIds {
NUM_LIGHTS
};

MODULE_NAME() : Module( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS )
{
}

void step() override
{
}
};

struct WIDGET_NAME : ModuleWidget {
WIDGET_NAME( MODULE_NAME *module);
};

WIDGET_NAME::WIDGET_NAME( MODULE_NAME *module ) : ModuleWidget( module )
{
box.size = Vec( SCREW_WIDTH * 8, RACK_HEIGHT );

BaconBackground *bg = new BaconBackground( box.size, "MODULE_NAME" );
addChild( bg->wrappedInFramebuffer());
}

Model *modelMODULE_NAME = Model::create<MODULE_NAME, WIDGET_NAME>("Bacon Music", "MODULE_NAME", "MODULE_NAME", RACK_REPLACE_WITH_TAG);

#endif

+ 70
- 0
plugins/community/repos/BaconMusic/src/BufferedDrawFunction.hpp View File

@@ -0,0 +1,70 @@
#ifndef BUFFERED_DRAW_FUNCTION_INCLUDE
#define BUFFERED_DRAW_FUNCTION_INCLUDE

#include "rack.hpp"

#include <functional>
#include <vector>

using namespace rack;

template < typename T >
struct BufferedDrawFunctionWidget : virtual FramebufferWidget
{
typedef std::function< void( T *, NVGcontext *) > drawfn_t;
T *that;
drawfn_t drawf;


struct InternalBDW : TransparentWidget
{
T* that;
drawfn_t drawf;
InternalBDW( Rect box_, T* that_, drawfn_t draw_ ) : that( that_ ), drawf( draw_ )
{
box = box_;
}
void draw( NVGcontext *vg ) override
{
drawf( that, vg );
}
};
BufferedDrawFunctionWidget( Vec pos, Vec sz, T* that_, drawfn_t draw_ ) : that( that_ ), drawf( draw_ )
{
box.pos = pos; box.size = sz;
auto kidBox = Rect( Vec( 0, 0 ), box.size );
InternalBDW *kid = new InternalBDW( kidBox, that, drawf );
addChild( kid );
}
};

struct BufferedDrawLambdaWidget : virtual FramebufferWidget
{
typedef std::function< void( NVGcontext *) > drawfn_t;
drawfn_t drawf;


struct InternalBDW : TransparentWidget
{
drawfn_t drawf;
InternalBDW( Rect box_, drawfn_t draw_ ) : drawf( draw_ )
{
box = box_;
}
void draw( NVGcontext *vg ) override
{
drawf( vg );
}
};
BufferedDrawLambdaWidget( Vec pos, Vec sz, drawfn_t draw_ ) : drawf( draw_ )
{
box.pos = pos; box.size = sz;
auto kidBox = Rect( Vec( 0, 0 ), box.size );
InternalBDW *kid = new InternalBDW( kidBox, drawf );
addChild( kid );
}
};

#endif

+ 177
- 0
plugins/community/repos/BaconMusic/src/ChipNoise.cpp View File

@@ -0,0 +1,177 @@
#include "BaconPlugs.hpp"
#include "ChipSym.hpp"

namespace rack_plugin_BaconMusic {

struct ChipNoise : virtual Module {
enum ParamIds {
NOISE_LENGTH,
LONG_MODE,
SHORT_LEN,
PERIOD_93,
NUM_PARAMS
};

enum InputIds {
NOISE_LENGTH_INPUT,
NUM_INPUTS
};

enum OutputIds {
NOISE_OUTPUT,
NUM_OUTPUTS
};

enum LightIds {
NOISE_FROM_INPUT,
NOISE_FROM_KNOB,

NOISE_LENGTH_LIGHT,

PERIOD_93_LIGHT,

USING_93,
NUM_LIGHTS
};

ChipSym::NESNoise noise;
int prior_shortlen;
bool prior_longmode;
ChipNoise() : Module( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS ),
noise( -5.0, 5.0, engineGetSampleRate() )
{
params[ LONG_MODE ].value = 1;
params[ NOISE_LENGTH ].value = 9;
params[ SHORT_LEN ].value = 1;
params[ PERIOD_93 ].value = 1;
prior_shortlen = 1;
prior_longmode = false;
}

void step() override
{
lights[ NOISE_FROM_KNOB ].value = !inputs[ NOISE_LENGTH_INPUT ].active;
lights[ NOISE_FROM_INPUT ].value = inputs[ NOISE_LENGTH_INPUT ].active;

unsigned int nl = (unsigned int)clamp( params[ NOISE_LENGTH ].value, 0.0f, 15.0f );
if( inputs[ NOISE_LENGTH_INPUT ].active )
nl = (unsigned int)clamp( inputs[ NOISE_LENGTH_INPUT ].value * 1.5, 0.0f, 15.0f );
lights[ NOISE_LENGTH_LIGHT ].value = nl;
noise.setPeriod(nl);

int p93 = (int)params[ PERIOD_93 ].value;
lights[ PERIOD_93_LIGHT ].value = p93;
if( params[ LONG_MODE ].value == 0 && params[ SHORT_LEN ].value == 1 )
{
noise.set93Key( p93 );
lights[ USING_93 ].value = 1;
}
else
{
lights[ USING_93 ].value = 0;
}

bool tmpNoiseFlag = ( params[ LONG_MODE ].value == 0 );
if ( tmpNoiseFlag != prior_longmode )
{
prior_longmode = tmpNoiseFlag;
noise.setModeFlag( prior_longmode );
}

if( params[ SHORT_LEN ].value != prior_shortlen )
{
prior_shortlen = params[SHORT_LEN].value;
if( prior_shortlen == 1 )
{
noise.setShortLength( ChipSym::NESNoise::SHORT_93 );
}
else
{
noise.setShortLength( ChipSym::NESNoise::SHORT_31 );
}
}
outputs[ NOISE_OUTPUT ].value = noise.step();
}
};

struct ChipNoiseWidget : ModuleWidget {
ChipNoiseWidget( ChipNoise *module);
};

ChipNoiseWidget::ChipNoiseWidget( ChipNoise *module ) : ModuleWidget( module )
{
box.size = Vec( SCREW_WIDTH * 6, RACK_HEIGHT );

BaconBackground *bg = new BaconBackground( box.size, "ChipNoise" );
addChild( bg->wrappedInFramebuffer());

// Control the noise length
bg->addRoundedBorder( Vec( 8, 45 ), Vec( SCREW_WIDTH * 6 - 16, 75 ) );
bg->addLabel( Vec( bg->cx() + 7, 55 ), "wave", 11, NVG_ALIGN_LEFT | NVG_ALIGN_TOP );
bg->addLabel( Vec( bg->cx() + 5, 66 ), "length", 11, NVG_ALIGN_LEFT | NVG_ALIGN_TOP );
Vec inP = Vec( 16, 53 );
addInput( Port::create< PJ301MPort >( inP,
Port::INPUT,
module,
ChipNoise::NOISE_LENGTH_INPUT ) );
addChild( ModuleLightWidget::create< SmallLight< BlueLight > >( inP.minus( Vec( 4, 4 ) ), module, ChipNoise::NOISE_FROM_INPUT ) );

int ybot = 120;
addParam( ParamWidget::create< RoundSmallBlackKnob >( Vec( 16, ybot - 3 - 28 ),
module,
ChipNoise::NOISE_LENGTH,
0, 15, 7 ) );
addChild( ModuleLightWidget::create< SmallLight< BlueLight > >( Vec( 16-4, ybot - 3 - 28 -4 ), module, ChipNoise::NOISE_FROM_KNOB ) );
addChild( MultiDigitSevenSegmentLight< BlueLight, 2, 2 >::create( Vec( 47, ybot - 5 - 24 ),
module,
ChipNoise::NOISE_LENGTH_LIGHT ) );


bg->addRoundedBorder( Vec( 8, 135 ), Vec( SCREW_WIDTH * 6 - 16, 160 ) );
bg->addLabel( Vec( bg->cx(), 155 ), "Sequence", 13, NVG_ALIGN_CENTER | NVG_ALIGN_BOTTOM );
addParam( ParamWidget::create< NKK >( Vec( bg->cx() - 32, 175 ), module, ChipNoise::LONG_MODE, 0, 1, 1 ) );
addParam( ParamWidget::create< NKK >( Vec( bg->cx() + 2, 175 ), module, ChipNoise::SHORT_LEN, 0, 1, 1 ) );
bg->addLabel( Vec( bg->cx() + 16 - 32, 160 ), "long", 11, NVG_ALIGN_CENTER | NVG_ALIGN_TOP );
bg->addLabel( Vec( bg->cx() + 16 - 32, 223 ), "short", 11, NVG_ALIGN_CENTER| NVG_ALIGN_TOP );

bg->addLabel( Vec( bg->cx() + 16 + 2, 160 ), "93", 11, NVG_ALIGN_CENTER | NVG_ALIGN_TOP );
bg->addLabel( Vec( bg->cx() + 16 + 2, 223 ), "31", 11, NVG_ALIGN_CENTER| NVG_ALIGN_TOP );


bg->addLabel( Vec( bg->cx(), 258 ), "Which 93 seq", 11, NVG_ALIGN_CENTER | NVG_ALIGN_BOTTOM );

addChild( MultiDigitSevenSegmentLight< BlueLight, 2, 3 >::create( Vec( 50 - 14, 262 ),
module,
ChipNoise::PERIOD_93_LIGHT ) );
addParam( ParamWidget::create< RoundSmallBlackKnob >( Vec( 11, 262 ),
module,
ChipNoise::PERIOD_93,
0, 351, 17 ) );
addChild( ModuleLightWidget::create< SmallLight< BlueLight > >( Vec( 12, 249 ), module, ChipNoise::USING_93 ) );

// Output port
Vec outP = Vec( bg->cx( 24 ), RACK_HEIGHT - 15 - 43 );
bg->addPlugLabel( outP, BaconBackground::SIG_OUT, "out" );
addOutput( Port::create< PJ301MPort >( outP,
Port::OUTPUT,
module,
ChipNoise::NOISE_OUTPUT ) );

}

} // namespace rack_plugin_BaconMusic

using namespace rack_plugin_BaconMusic;

RACK_PLUGIN_MODEL_INIT(BaconMusic, ChipNoise) {
Model *modelChipNoise = Model::create<ChipNoise, ChipNoiseWidget>("Bacon Music", "ChipNoise", "ChipNoise", NOISE_TAG );
return modelChipNoise;
}

+ 391
- 0
plugins/community/repos/BaconMusic/src/ChipSym.hpp View File

@@ -0,0 +1,391 @@
/*
** All my chip simulator noobits. But remember this is just me screwing around.
*/

#include <math.h>
#include <iostream>
#include <vector>

namespace ChipSym
{
class CPUStepper
{
private:
int sampleRateInHz;
double chipFrequencyInMHZ;

unsigned int ticksPerSample;
double tickFractionPerSample;
double accruedTickFraction;
public:
CPUStepper( unsigned int _sampleRateInHz, double _chipFrequencyInMHZ )
: sampleRateInHz( _sampleRateInHz ), chipFrequencyInMHZ( _chipFrequencyInMHZ ), accruedTickFraction( 0 )
{
double tpsD = chipFrequencyInMHZ * 1000000 / sampleRateInHz;
double tpsdi;
tickFractionPerSample = modf( tpsD, &tpsdi );
ticksPerSample = (unsigned int)tpsdi;
}

/*
** Take one step and tell me how many CPU ticks I would have seen if I am sampling at sampleRate.
** This won't be a constant of course since sometimes we get an extra to catch up
*/
unsigned int nextStepCPUTicks()
{
accruedTickFraction += tickFractionPerSample;
if( accruedTickFraction > 1 )
{
accruedTickFraction -= 1;
return ticksPerSample + 1;
}

return ticksPerSample;
}
};

static double NESNTSCCPURate = 1.789773;


class NESBase
{
protected:
int digWavelength; // this is the 2^11 which sets frequency time
int t, currPos;

float wfMin, wfMax, wfMinToMax;

public:
NESBase( float imin, float imax )
:
wfMin( imin ), wfMax( imax )
{
digWavelength = 1 << 7; // Callibrate this later
t = digWavelength;
currPos = 0;
wfMinToMax = wfMax - wfMin;
}

void setDigWavelength( int df ) // 0 -> 2^11
{
digWavelength = df;
}
};
class NESTriangle : public NESBase // http://wiki.nesdev.com/w/index.php/APU_Triangle
{
protected:
float waveForm[ 32 ];
CPUStepper cpu;


public:
NESTriangle( float imin, float imax, unsigned int sampleRate )
:
NESBase( imin, imax ), cpu( sampleRate, NESNTSCCPURate )
{
for( int i=0; i<16; ++i ) {
waveForm[ 15 - i ] = i / 15.0f;
waveForm[ 16 + i ] = i / 15.0f;
}
}

float step()
{
int ticks = cpu.nextStepCPUTicks();
t -= ticks;
if( t < 0 )
{
currPos ++;
t += digWavelength;
if( currPos >= 32 ) currPos = 0;
}
return waveForm[ currPos ] * wfMinToMax + wfMin;
}

void setWavelengthInSeconds( float seconds )
{
setDigWavelength( (unsigned int)( seconds * NESNTSCCPURate * 1000 * 1000 / 32 ) );
}
};

class NESArbitraryWaveform : public NESTriangle {
public:
NESArbitraryWaveform( float imin, float imax, unsigned int sampleRate ) : NESTriangle( imin, imax, sampleRate ) { }

void setWaveformPoint( unsigned int pos, // 0->31
unsigned int val ) // 0->15
{
waveForm[ pos ] = val / 15.0f;
}

unsigned int getWaveformPoint( unsigned int pos ) { return waveForm[ pos ] * 15.0f; }
};

class NESPulse : public NESBase // http://wiki.nesdev.com/w/index.php/APU_Pulse
{
private:
int dutyCycle;
float **waveForms;
int nDutyCycles;
int wfLength;
CPUStepper cpu;

public:
NESPulse( float imin, float imax, int sampleRate )
:
NESBase( imin, imax ), cpu( sampleRate, NESNTSCCPURate / 2 )
{
wfLength = 8;
nDutyCycles = 4;
dutyCycle = 1;
waveForms = new float*[ 4 ];
for( int i=0; i<nDutyCycles; ++i )
{
waveForms[ i ] = new float[ wfLength ];
for (int j=0; j<wfLength; ++j ) waveForms[ i ][ j ] = ( i == nDutyCycles - 1 ) ? 1 : 0;

// Really, read that website for this stuff.
switch( i )
{
case 0:
waveForms[ i ][ 1 ] = 1;
break;
case 1:
waveForms[ i ][ 1 ] = 1;
waveForms[ i ][ 2 ] = 1;
break;
case 2:
waveForms[ i ][ 1 ] = 1;
waveForms[ i ][ 2 ] = 1;
waveForms[ i ][ 3 ] = 1;
waveForms[ i ][ 4 ] = 1;
break;
case 3:
waveForms[ i ][ 1 ] = 0;
waveForms[ i ][ 2 ] = 0;
break;
}
}

}

void setWavelengthInSeconds( float seconds )
{
setDigWavelength( (unsigned int)( seconds * NESNTSCCPURate * 1000 * 1000 / 2.0 / 8.0) );
}

void setDutyCycle( int dc )
{
dutyCycle = dc;
}
float step()
{
int ticks = cpu.nextStepCPUTicks();
t -= ticks;
if( t < 0 )
{
currPos ++;
t += digWavelength;
if( currPos >= wfLength ) currPos = 0;
}
return waveForms[ dutyCycle ][ currPos ] * wfMinToMax + wfMin;
}
};

class NESNoise : public NESBase
{
public:
typedef enum ShortPeriods
{
SHORT_31,
SHORT_93
} ShortPeriods;

private:
CPUStepper cpu;
unsigned short shiftRegister;
unsigned short currentOutput;
unsigned short xorBit;

unsigned short curr93key;
std::vector< unsigned short > starts_for_93s;
ShortPeriods currShortPeriods;
public:

NESNoise( float imin, float imax, int sampleRate )
:
NESBase( imin, imax ), cpu( sampleRate, NESNTSCCPURate / 2 )
{
setPeriod( 8 );
shiftRegister = 0x07;
currentOutput = shiftRegister & 1;
xorBit = 1;
curr93key = 17;
init93();
currShortPeriods = SHORT_93;
}

void init93()
{
// To generate this, see ../standalone/chipNoisePeriod.cpp
unsigned short calc_start_for_93s[] = {
1, 3, 5, 7, 11, 13, 15, 17, 19, 21, 23, 25, 29, 31, 33,
35, 37, 39, 41, 43, 47, 49, 51, 53, 55, 57, 59, 61, 66, 68,
70, 74, 76, 78, 80, 84, 86, 88, 90, 92, 94, 96, 98, 102, 104,
106, 108, 110, 112, 114, 116, 120, 122, 124, 126, 129, 131, 133, 135, 139,
141, 143, 145, 147, 149, 151, 153, 157, 159, 161, 163, 165, 167, 169, 171,
175, 177, 179, 181, 183, 185, 187, 189, 194, 196, 198, 200, 202, 204, 206,
208, 212, 214, 218, 220, 222, 224, 226, 230, 232, 234, 236, 238, 240, 242,
244, 248, 250, 252, 254, 259, 263, 267, 271, 273, 275, 277, 279, 281, 285,
287, 291, 295, 299, 303, 305, 307, 309, 311, 313, 315, 317, 322, 326, 330,
334, 336, 340, 342, 344, 346, 348, 350, 354, 358, 362, 366, 368, 370, 372,
376, 378, 380, 382, 387, 389, 395, 397, 399, 401, 403, 405, 407, 409, 413,
415, 417, 419, 421, 423, 425, 427, 431, 435, 437, 443, 445, 450, 452, 454,
456, 458, 460, 464, 468, 470, 472, 474, 478, 482, 486, 488, 490, 492, 494,
498, 500, 506, 535, 543, 547, 551, 555, 559, 563, 565, 571, 573, 598, 606,
610, 614, 618, 622, 626, 628, 634, 636, 645, 647, 653, 655, 661, 663, 669,
671, 673, 677, 679, 681, 687, 689, 691, 693, 699, 701, 710, 716, 718, 724,
726, 732, 734, 742, 744, 750, 752, 756, 760, 762, 764, 775, 779, 785, 787,
789, 793, 797, 799, 803, 811, 815, 819, 821, 823, 827, 829, 834, 838, 842,
852, 858, 860, 862, 870, 874, 880, 882, 884, 888, 892, 894, 901, 907, 913,
915, 919, 927, 931, 933, 935, 947, 962, 970, 982, 988, 990, 994, 1000, 1004,
1012, 1018, 1057, 1059, 1061, 1063, 1065, 1067, 1075, 1077, 1079, 1081, 1083, 1100, 1110,
1116, 1130, 1132, 1134, 1138, 1144, 1185, 1187, 1189, 1191, 1195, 1201, 1209, 1211, 1228,
1238, 1244, 1264, 1274, 1293, 1311, 1313, 1335, 1354, 1392, 1415, 1419, 1425, 1455, 1467,
1510, 1524, 1569, 1620, 1638, 1671, 1868, 0 };
unsigned short* curr = calc_start_for_93s;
while( *curr != 0 )
{
starts_for_93s.push_back( *curr );
++curr;
}
}

void set93Key( int sp )
{
if( sp != curr93key )
{
setRegister( starts_for_93s[ sp ] );
}
curr93key = sp;
}
void setModeFlag( bool mf )
{
if( mf )
{
xorBit = 6;

// set register based on cached shortlen
setShortLength( currShortPeriods );
}
else xorBit = 1;
}

void setShortLength( ShortPeriods p )
{
currShortPeriods = p;
if( p == SHORT_31 )
{
setRegister( 0x0737 );
}
else
{
// A little state so we don't always land on the same one
setRegister( starts_for_93s[ curr93key ] );
}
}

void setPeriod( unsigned int c ) // 0 - 15
{
if( c > 15 ) c = 8;
switch( c ) {
case 0:
digWavelength = 4; break;
case 1:
digWavelength = 8; break;
case 2:
digWavelength = 16; break;
case 3:
digWavelength = 32; break;
case 4:
digWavelength = 64; break;
case 5:
digWavelength = 96; break;
case 6:
digWavelength = 128; break;
case 7:
digWavelength = 160; break;
case 8:
digWavelength = 202; break;
case 9:
digWavelength = 254; break;
case 10:
digWavelength = 380; break;
case 11:
digWavelength = 508; break;
case 12:
digWavelength = 762; break;
case 13:
digWavelength = 1016; break;
case 14:
digWavelength = 2034; break;
case 15:
digWavelength = 4068; break;
}
}

void advanceRegister()
{
// Do the LFSR Shift
unsigned short bit = ((shiftRegister >> 0) ^ (shiftRegister >> xorBit)) & 1;
shiftRegister = (shiftRegister >> 1) | (bit << 14); // thanks https://github.com/baconpaul/BaconPlugs/issues/6
}
float step()
{
int ticks = cpu.nextStepCPUTicks();
t -= ticks;
if( t < 0 )
{
t += digWavelength;
advanceRegister();
currentOutput = shiftRegister & 1;
}
return currentOutput * wfMinToMax + wfMin;

}

void setRegister( unsigned short r ) { shiftRegister = r; }
unsigned short getRegister() { return shiftRegister; }
};

#if 0
class LFSRGeneralImpl
{
public:
typedef std::bitset< 24 > bits;
private:
public:
void setActivetBits( size_t aBits ) // < 24 please
{
}
void setTapsAsInt( unsigned int taps ) // so 1 << 16 & 1 << 14 & 1 << 7 type thing
{
}
};
#endif
};

+ 128
- 0
plugins/community/repos/BaconMusic/src/ChipWaves.cpp View File

@@ -0,0 +1,128 @@

#include "BaconPlugs.hpp"
#include "ChipSym.hpp"

namespace rack_plugin_BaconMusic {

struct ChipWaves : virtual Module {
enum ParamIds {
FREQ_KNOB,
PULSE_CYCLE,
NUM_PARAMS
};

enum InputIds {
FREQ_CV,
NUM_INPUTS
};

enum OutputIds {
PULSE_OUTPUT,
TRI_OUTPUT,
NUM_OUTPUTS
};

enum LightIds {
PULSE_CYCLE_LIGHT,
NUM_LIGHTS
};

ChipSym::NESPulse npulse;
ChipSym::NESTriangle ntri;

ChipWaves() : Module( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS ),
npulse( -5.0, 5.0, engineGetSampleRate() ),
ntri( -5.0, 5.0, engineGetSampleRate() )
{
npulse.setDigWavelength( 2<<9 );
ntri.setDigWavelength( 2<<8 );
}

float digWFInSeconds( float pitchKnob, float pitchCV )
{
// This is the frequency tuning used in Fundamental/VCO so lets be consistent
float pitch = pitchKnob + pitchCV;
float freq = 261.626f * powf( 2.0f, pitch / 12.0f );
// OK so now we have the frequency. We need the wavelength though. Simple
float wl = 1.0f / freq;
return wl;
}
void step() override
{
float dwf = digWFInSeconds( params[ FREQ_KNOB ].value, 12.0f * inputs[ FREQ_CV ].value );

ntri.setWavelengthInSeconds( dwf );
npulse.setWavelengthInSeconds( dwf );

int dc = clamp( (int)(params[ PULSE_CYCLE ].value ), 0, 3 );
npulse.setDutyCycle( dc );
lights[ PULSE_CYCLE_LIGHT ].value = dc;
if( outputs[ TRI_OUTPUT ].active )
outputs[ TRI_OUTPUT ].value = ntri.step();
if( outputs[ PULSE_OUTPUT ].active )
outputs[ PULSE_OUTPUT ].value = npulse.step();
}
};

struct ChipWavesWidget : ModuleWidget {
ChipWavesWidget( ChipWaves *module);
};

ChipWavesWidget::ChipWavesWidget( ChipWaves *module ) : ModuleWidget( module )
{
box.size = Vec( SCREW_WIDTH * 8, RACK_HEIGHT );

BaconBackground *bg = new BaconBackground( box.size, "ChipWaves" );
addChild( bg->wrappedInFramebuffer());

Vec outP = Vec( bg->cx( 24 ) + 25, RACK_HEIGHT - 15 - 43 );
bg->addPlugLabel( outP, BaconBackground::SIG_OUT, "pulse" );
addOutput( Port::create< PJ301MPort >( outP,
Port::OUTPUT,
module,
ChipWaves::PULSE_OUTPUT ) );

Vec outT = Vec( bg->cx( 24 ) - 25, RACK_HEIGHT - 15 - 43 );
bg->addPlugLabel( outT, BaconBackground::SIG_OUT, "tri" );
addOutput( Port::create< PJ301MPort >( outT,
Port::OUTPUT,
module,
ChipWaves::TRI_OUTPUT ) );

Vec fcv = Vec( bg->cx( 24 ) + 35, 160 );
bg->addPlugLabel( fcv, BaconBackground::SIG_IN, "v/o" );
addInput( Port::create< PJ301MPort >( fcv,
Port::INPUT,
module,
ChipWaves::FREQ_CV ) );

bg->addRoundedBorder( Vec( 10, 140 ), Vec ( 63, 49 ) );
bg->addLabel( Vec( 40, 144 ), "Duty Cycle", 12, NVG_ALIGN_CENTER | NVG_ALIGN_TOP );
int ybot = 140 + 24 + 5 + 20;
addParam( ParamWidget::create< RoundSmallBlackKnob >( Vec( 16, ybot - 3 - 28 ),
module,
ChipWaves::PULSE_CYCLE,
0, 3, 0 ) );
addChild( ModuleLightWidget::create< SevenSegmentLight< BlueLight, 2 > >( Vec( 47, ybot - 5 - 24 ),
module,
ChipWaves::PULSE_CYCLE_LIGHT ) );

bg->addLabel( Vec( bg->cx(), 45 ), "Freq", 14, NVG_ALIGN_CENTER | NVG_ALIGN_BOTTOM );
addParam( ParamWidget::create< RoundHugeBlackKnob >( Vec( bg->cx( 56 ), 50 ), module,
ChipWaves::FREQ_KNOB, -54.0f, 54.0f, 0.0f ) );

}

} // namespace rack_plugin_BaconMusic

using namespace rack_plugin_BaconMusic;

RACK_PLUGIN_MODEL_INIT(BaconMusic, ChipWaves) {
Model *modelChipWaves = Model::create<ChipWaves, ChipWavesWidget>("Bacon Music", "ChipWaves", "ChipWaves", OSCILLATOR_TAG );
return modelChipWaves;
}

+ 108
- 0
plugins/community/repos/BaconMusic/src/ChipYourWave.cpp View File

@@ -0,0 +1,108 @@

#include "BaconPlugs.hpp"
#include "ChipSym.hpp"

namespace rack_plugin_BaconMusic {

struct ChipYourWave : virtual Module {
enum ParamIds {
FREQ_KNOB,

WAVEFORM_START,
NUM_PARAMS = WAVEFORM_START + 32
};

enum InputIds {
FREQ_CV,
NUM_INPUTS
};

enum OutputIds {
WAVE_OUTPUT,
NUM_OUTPUTS
};

enum LightIds {
NUM_LIGHTS
};

ChipSym::NESArbitraryWaveform narb;

ChipYourWave() : Module( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS ),
narb( -5.0, 5.0, engineGetSampleRate() )
{
narb.setDigWavelength( 2<<8 );
}

float digWFInSeconds( float pitchKnob, float pitchCV )
{
// This is the frequency tuning used in Fundamental/VCO so lets be consistent
float pitch = pitchKnob + pitchCV;
float freq = 261.626f * powf( 2.0f, pitch / 12.0f );
// OK so now we have the frequency. We need the wavelength though. Simple
float wl = 1.0f / freq;
return wl;
}
void step() override
{
float dwf = digWFInSeconds( params[ FREQ_KNOB ].value, 12.0f * inputs[ FREQ_CV ].value );

narb.setWavelengthInSeconds( dwf );

for( int i=0; i<32; ++i )
narb.setWaveformPoint( i, params[ WAVEFORM_START + i ].value );
if( outputs[ WAVE_OUTPUT ].active )
outputs[ WAVE_OUTPUT ].value = narb.step();
}
};

struct ChipYourWaveWidget : ModuleWidget {
ChipYourWaveWidget( ChipYourWave *module);
};

ChipYourWaveWidget::ChipYourWaveWidget( ChipYourWave *module ) : ModuleWidget( module )
{
box.size = Vec( SCREW_WIDTH * 23, RACK_HEIGHT );

BaconBackground *bg = new BaconBackground( box.size, "ChipYourWave" );
addChild( bg->wrappedInFramebuffer());

Vec outP = Vec( box.size.x - 40, 45 + 30 );
bg->addPlugLabel( outP, BaconBackground::SIG_OUT, "out" );
addOutput( Port::create< PJ301MPort >( outP,
Port::OUTPUT,
module,
ChipYourWave::WAVE_OUTPUT ) );

bg->addLabel( Vec( 50, 45 ), "Freq", 14, NVG_ALIGN_LEFT | NVG_ALIGN_BOTTOM );
addParam( ParamWidget::create< RoundHugeBlackKnob >( Vec( 10, 50 ), module,
ChipYourWave::FREQ_KNOB, -54.0f, 54.0f, 0.0f ) );
Vec fcv = Vec( 56 + 20, 45 + 30 );
bg->addPlugLabel( fcv, BaconBackground::SIG_IN, "v/o" );
addInput( Port::create< PJ301MPort >( fcv,
Port::INPUT,
module,
ChipYourWave::FREQ_CV ) );

bg->addLabel( Vec( bg->cx(), 135 ), "Draw your Digital Waveform Here", 14, NVG_ALIGN_CENTER | NVG_ALIGN_BOTTOM );
for( int i=0; i<32; ++i )
{
addParam( ParamWidget::create< NStepDraggableLEDWidget< 16, RedGreenFromMiddleColorModel >>( Vec( 10 + 10 * i, 140 ), module,
ChipYourWave::WAVEFORM_START + i,
0, 15,
module->narb.getWaveformPoint( i )) );
}

}

} // namespace rack_plugin_BaconMusic

using namespace rack_plugin_BaconMusic;

RACK_PLUGIN_MODEL_INIT(BaconMusic, ChipYourWave) {
Model *modelChipYourWave = Model::create<ChipYourWave, ChipYourWaveWidget>("Bacon Music", "ChipYourWave", "ChipYourWave", OSCILLATOR_TAG );
return modelChipYourWave;
}

+ 295
- 0
plugins/community/repos/BaconMusic/src/Components.cpp View File

@@ -0,0 +1,295 @@
#include "BaconPlugs.hpp"
#include <jansson.h>


struct InternalFontMgr
{
static std::map< std::string, int > fontMap;
static int get( NVGcontext *vg, std::string resName )
{
if( fontMap.find( resName ) == fontMap.end() )
{
fontMap[ resName ] = nvgCreateFont( vg, resName.c_str(), assetPlugin( plugin, resName.c_str() ).c_str() );
}
return fontMap[ resName ];
}
};

std::map< std::string, int > InternalFontMgr::fontMap;

struct InternalRoundedBorder : virtual TransparentWidget
{
bool doFill;
NVGcolor fillColor;

InternalRoundedBorder( Vec pos, Vec sz, NVGcolor fc )
{
box.pos = pos;
box.size = sz;
doFill = true;
fillColor = fc;
}

InternalRoundedBorder( Vec pos, Vec sz )
{
box.pos = pos;
box.size = sz;
doFill = false;
}

void draw( NVGcontext *vg ) override
{
nvgBeginPath( vg );
nvgRoundedRect( vg, 0, 0, box.size.x, box.size.y, 5 );
if( doFill )
{
nvgFillColor( vg, fillColor );
nvgFill( vg );
}
nvgStrokeColor( vg, COLOR_BLACK );
nvgStroke( vg );
}
};

struct InternalTextLabel : virtual TransparentWidget
{
int memFont = -1;
std::string label;
int pxSize;
int align;
NVGcolor color;

InternalTextLabel( Vec pos, const char* lab, int px, int al, NVGcolor col ) : label( lab ), pxSize( px ), align( al ), color( col )
{
box.pos = pos;
}

void draw( NVGcontext *vg ) override {
if( memFont < 0 )
memFont = InternalFontMgr::get( vg, "res/Monitorica-Bd.ttf" );

nvgBeginPath( vg );
nvgFontFaceId( vg, memFont );
nvgFontSize( vg, pxSize );
nvgFillColor( vg, color );
nvgTextAlign( vg, align );
nvgText( vg, 0, 0, label.c_str(), NULL );
}
};

struct InternalPlugLabel : virtual TransparentWidget
{
int memFont = -1;

BaconBackground::LabelStyle st;
BaconBackground::LabelAt at;
std::string label;

InternalPlugLabel( Vec portPos, BaconBackground::LabelAt l, BaconBackground::LabelStyle s, const char* ilabel );
void draw( NVGcontext *vg ) override;

};


void BaconBackground::draw( NVGcontext *vg )
{
if( memFont < 0 )
memFont = InternalFontMgr::get( vg, "res/Monitorica-Bd.ttf" );

nvgBeginPath( vg );
nvgRect( vg, 0, 0, box.size.x, box.size.y );
nvgFillColor( vg, BaconBackground::bg );
nvgFill( vg );

nvgBeginPath( vg );
nvgMoveTo( vg, 0, 0 );
nvgLineTo( vg, box.size.x, 0 );
nvgLineTo( vg, box.size.x, box.size.y );
nvgLineTo( vg, 0, box.size.y );
nvgLineTo( vg, 0, 0 );
nvgStrokeColor( vg, BaconBackground::bgOutline );
nvgStroke( vg );

nvgFontFaceId( vg, memFont );
nvgFontSize( vg, 14 );
nvgFillColor( vg, COLOR_BLACK );
nvgStrokeColor( vg, COLOR_BLACK );
nvgTextAlign( vg, NVG_ALIGN_CENTER|NVG_ALIGN_BOTTOM );
nvgText( vg, box.size.x / 2, box.size.y - 5, "Bacon Music", NULL );

nvgFontFaceId( vg, memFont );
nvgFontSize( vg, 16 );
nvgFillColor( vg, COLOR_BLACK );
nvgStrokeColor( vg, COLOR_BLACK );
nvgTextAlign( vg, NVG_ALIGN_CENTER|NVG_ALIGN_TOP );
nvgText( vg, box.size.x / 2, 5, title.c_str(), NULL );

for( auto w : children )
{
nvgTranslate( vg, w->box.pos.x, w->box.pos.y );
w->draw( vg );
nvgTranslate( vg, -w->box.pos.x, -w->box.pos.y );
}

for( auto it = rects.begin(); it != rects.end(); ++it )
{
col_rect_t tu = *it;
Rect r = std::get< 0 >(tu);
NVGcolor c = std::get< 1 >(tu);
bool f = std::get< 2 >(tu);
nvgBeginPath( vg );
nvgRect( vg, r.pos.x, r.pos.y, r.size.x, r.size.y );
if( f )
{
nvgFillColor( vg, c );
nvgFill( vg );
}
else
{
nvgStrokeColor( vg, c );
nvgStroke( vg );
}
}

}

InternalPlugLabel::InternalPlugLabel( Vec portPos, BaconBackground::LabelAt l, BaconBackground::LabelStyle s, const char* ilabel )
:
st( s ), at( l ), label( ilabel )
{
box.size.x = 24 + 5;
box.size.y = 24 + 5 + 20;
// switch on position but for now just do above
box.pos.x = portPos.x - 2.5;
box.pos.y = portPos.y - 2.5 - 17;
}


void InternalPlugLabel::draw( NVGcontext *vg )
{
if( memFont < 0 )
memFont = InternalFontMgr::get( vg, "res/Monitorica-Bd.ttf" );

NVGcolor txtCol = COLOR_BLACK;
switch( st ) {
case( BaconBackground::SIG_IN ) :
{
nvgBeginPath( vg );
nvgRoundedRect( vg, 0, 0, box.size.x, box.size.y, 5 );
nvgStrokeColor( vg, COLOR_BLACK );
nvgStroke( vg );
break;
}
case( BaconBackground::SIG_OUT ) :
{
nvgBeginPath( vg );
nvgRoundedRect( vg, 0, 0, box.size.x, box.size.y, 5 );
nvgFillColor( vg, BaconBackground::highlight );
nvgFill( vg );

nvgStrokeColor( vg, COLOR_BLACK );
nvgStroke( vg );

txtCol = COLOR_WHITE;
break;
}
case( BaconBackground::OTHER ) :
{
nvgBeginPath( vg );
nvgRoundedRect( vg, 0, 0, box.size.x, box.size.y, 5 );
nvgStrokeColor( vg, COLOR_RED );
nvgStroke( vg );
break;
}
}
nvgFontFaceId( vg, memFont );
nvgFontSize( vg, 13 );
nvgFillColor( vg, txtCol );
nvgTextAlign( vg, NVG_ALIGN_CENTER|NVG_ALIGN_TOP );
nvgText( vg, box.size.x / 2, 3, label.c_str(), NULL );

}



BaconBackground *BaconBackground::addLabel( Vec pos, const char* lab, int px, int align, NVGcolor col )
{
addChild( new InternalTextLabel( pos, lab, px, align, col ) );
return this;
}

BaconBackground *BaconBackground::addPlugLabel( Vec plugPos, LabelAt l, LabelStyle s, const char* ilabel )
{
addChild( new InternalPlugLabel( plugPos, l, s, ilabel ) );
return this;
}

BaconBackground *BaconBackground::addRoundedBorder( Vec pos, Vec sz )
{
addChild( new InternalRoundedBorder( pos, sz ) );
return this;
}

BaconBackground *BaconBackground::addRoundedBorder( Vec pos, Vec sz, NVGcolor fill )
{
addChild( new InternalRoundedBorder( pos, sz, fill ) );
return this;
}


NVGcolor BaconBackground::bg = nvgRGBA( 220, 220, 210, 255 );
NVGcolor BaconBackground::bgOutline = nvgRGBA( 180, 180, 170, 255 );
NVGcolor BaconBackground::highlight = nvgRGBA( 90, 90, 60, 255 );

BaconBackground::BaconBackground( Vec size, const char* lab ) : title( lab )
{
box.pos = Vec( 0, 0 );
box.size = size;
}

FramebufferWidget* BaconBackground::wrappedInFramebuffer()
{
FramebufferWidget *fb = new FramebufferWidget();
fb->box = box;
fb->addChild( this );
return fb;
}



BaconBackground *BaconBackground::addLabelsForHugeKnob( Vec topLabelPos,
const char* knobLabel,
const char* zeroLabel,
const char* oneLabel,
Vec &putKnobHere )
{
addLabel( topLabelPos, knobLabel, 14, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE );
addLabel( Vec( topLabelPos.x + 10, topLabelPos.y + 72 ),
oneLabel, 13, NVG_ALIGN_LEFT | NVG_ALIGN_TOP );
addLabel( Vec( topLabelPos.x - 10, topLabelPos.y + 72 ),
zeroLabel, 13, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP );
putKnobHere.y = topLabelPos.y + 10;
putKnobHere.x = topLabelPos.x - 28;
return this;
}

BaconBackground *BaconBackground::addLabelsForLargeKnob( Vec topLabelPos,
const char* knobLabel,
const char* zeroLabel,
const char* oneLabel,
Vec &putKnobHere )
{
addLabel( topLabelPos, knobLabel, 14, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE );
addLabel( Vec( topLabelPos.x + 10, topLabelPos.y + 48 ),
oneLabel, 13, NVG_ALIGN_LEFT | NVG_ALIGN_TOP );
addLabel( Vec( topLabelPos.x - 10, topLabelPos.y + 48 ),
zeroLabel, 13, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP );
putKnobHere.y = topLabelPos.y + 10;
putKnobHere.x = topLabelPos.x - 18;
return this;
}

+ 592
- 0
plugins/community/repos/BaconMusic/src/Components.hpp View File

@@ -0,0 +1,592 @@
#ifndef INCLUDE_COMPONENTS_HPP
#define INCLUDE_COMPONENTS_HPP

#include "rack.hpp"

#include <map>
#include <vector>
#include <string>
#include <tuple>
#include <functional>
#include <locale>
#include <thread>

#include "GraduatedFader.hpp"
#include "BufferedDrawFunction.hpp"

using namespace rack;


template <typename T, int px = 4>
struct SevenSegmentLight : T {
int lx, ly, ppl;
std::vector< Rect > unscaledLoc;
int elementsByNum[ 10 ][ 7 ] = {
{ 1, 1, 1, 1, 1, 1, 0 },
{ 0, 1, 1, 0, 0, 0, 0 },
{ 1, 1, 0, 1, 1, 0, 1 },
{ 1, 1, 1, 1, 0, 0, 1 },
{ 0, 1, 1, 0, 0, 1, 1 },
{ 1, 0, 1, 1, 0, 1, 1 },
{ 1, 0, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 0, 0, 0, 0 },
{ 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 0, 1, 1 }
};

const static int sx = px * 6 + 2;
const static int sy = px * 10 + 2; // match with lx-1 and ly-1 below
int pvalue;

int decimalPos;
BufferedDrawFunctionWidget<SevenSegmentLight<T, px>> *buffer;
SevenSegmentLight( )
{
lx = 7;
ly = 11;
ppl = px;
pvalue = 0;
this->box.size = Vec( sx, sy );
decimalPos = 1;

// https://en.wikipedia.org/wiki/Seven-segment_display#/media/File:7_segment_display_labeled.svg
unscaledLoc.push_back( Rect( Vec( 2, 1 ), Vec( 3, 1 ) ) );
unscaledLoc.push_back( Rect( Vec( 5, 2 ), Vec( 1, 3 ) ) );
unscaledLoc.push_back( Rect( Vec( 5, 6 ), Vec( 1, 3 ) ) );
unscaledLoc.push_back( Rect( Vec( 2, 9 ), Vec( 3, 1 ) ) );
unscaledLoc.push_back( Rect( Vec( 1, 6 ), Vec( 1, 3 ) ) );
unscaledLoc.push_back( Rect( Vec( 1, 2 ), Vec( 1, 3 ) ) );
unscaledLoc.push_back( Rect( Vec( 2, 5 ), Vec( 3, 1 ) ) );

buffer = new BufferedDrawFunctionWidget<SevenSegmentLight<T,px>>( Vec( 0, 0 ), this->box.size,
this,
&SevenSegmentLight<T,px>::drawSegments );
this->addChild( buffer );
}

void draw( NVGcontext *vg ) override
{
float fvalue = this->module->lights[ this->firstLightId ].value;
int value = int( fvalue / decimalPos ) % 10;

if( value != pvalue )
{
buffer->dirty = true;
}

pvalue = value;
buffer->draw( vg );
}

void drawSegments( NVGcontext *vg )
{
// This is now buffered to only be called when the value has changed
int w = this->box.size.x;
int h = this->box.size.y;
nvgBeginPath( vg );
nvgRect( vg, 0, 0, w, h );
nvgFillColor( vg, nvgRGBA( 25, 35, 25, 255 ) );
nvgFill( vg );
int i=0;
// float fvalue = this->module->lights[ this->firstLightId ].value;
// int value = clamp( fvalue, 0.0f, 9.0f );

int *ebn = elementsByNum[ pvalue ];

NVGcolor oncol = this->baseColors[ 0 ];
for( auto it = unscaledLoc.begin(); it < unscaledLoc.end(); ++it )
{
float y = it->pos.y - 0.5;
float x = it->pos.x - 0.5;
int ew = it->size.x;
int eh = it->size.y;
nvgBeginPath( vg );
// New version with corners
float x0 = x * ppl + 1;
float y0 = y * ppl + 1;
float w = ew * ppl;
float h = eh * ppl;
float tri = ppl / 2;
if( eh == 1 )
{
// This is a sideways element
nvgMoveTo( vg, x0, y0 );
nvgLineTo( vg, x0 + w, y0 );
nvgLineTo( vg, x0 + w + tri, y0 + tri );
nvgLineTo( vg, x0 + w, y0 + h);
nvgLineTo( vg, x0, y0 + h);
nvgLineTo( vg, x0 - tri, y0 + tri );
nvgClosePath( vg );
}
else
{
nvgMoveTo( vg, x0, y0 );
nvgLineTo( vg, x0, y0 + h );
nvgLineTo( vg, x0 + tri, y0 + h + tri );
nvgLineTo( vg, x0 + w, y0 + h);
nvgLineTo( vg, x0 + w, y0);
nvgLineTo( vg, x0 + tri, y0 - tri );
}


// Old version nvgRect( vg, x * ppl + 1, y * ppl + 1, ew * ppl, eh * ppl );
if( ebn[ i ] > 0 )
{
nvgFillColor( vg, oncol );
nvgFill( vg );
}
else
{
nvgFillColor( vg, nvgRGBA( 50, 70, 50, 255 ) );
nvgFill( vg );
}
++i;
}
}

static SevenSegmentLight< T, px > *create(Vec pos, Module *module, int firstLightId, int decimal) {
auto *o = ModuleLightWidget::create<SevenSegmentLight<T,px>>(pos, module, firstLightId);
o->decimalPos = decimal;
return o;
}

};

template <typename colorClass, int px, int digits>
struct MultiDigitSevenSegmentLight : ModuleLightWidget
{
typedef SevenSegmentLight< colorClass, px > LtClass;
MultiDigitSevenSegmentLight() : ModuleLightWidget()
{
this->box.size = Vec( digits * LtClass::sx, LtClass::sy );
}

static MultiDigitSevenSegmentLight< colorClass, px, digits > *create(Vec pos, Module *module, int firstLightId) {
auto *o = ModuleLightWidget::create<MultiDigitSevenSegmentLight<colorClass, px ,digits>>(pos, module, firstLightId);
o->layout();
return o;
}

void layout()
{
int dp = 1;
for( int i=0; i<digits-1; ++i ) dp *= 10;
for( int i=0; i<digits; ++i )
{
addChild( LtClass::create( Vec( i * LtClass::sx, 0 ), module, firstLightId, dp ) );
dp /= 10;
}
}

void draw( NVGcontext *vg ) override
{
for( auto it = children.begin(); it != children.end(); ++it )
{
nvgSave( vg );
nvgTranslate( vg, (*it)->box.pos.x, (*it)->box.pos.y );
(*it)->draw( vg );
nvgRestore( vg );
}
}

};

struct BaconBackground : virtual TransparentWidget
{
static NVGcolor bg;
static NVGcolor bgOutline;
static NVGcolor highlight;

typedef std::tuple< Rect, NVGcolor, bool > col_rect_t;
std::vector< col_rect_t > rects;

int memFont = -1;
std::string title;

enum LabelAt {
ABOVE,
BELOW,
LEFT,
RIGHT
};

enum LabelStyle {
SIG_IN,
SIG_OUT,
OTHER
};

int cx() { return box.size.x / 2; }
int cx( int w ) { return (box.size.x-w) / 2; }
BaconBackground( Vec size, const char* lab );
~BaconBackground() { }

BaconBackground *addLabel( Vec pos, const char* lab, int px )
{
return addLabel( pos, lab, px, NVG_ALIGN_CENTER | NVG_ALIGN_BOTTOM, COLOR_BLACK );
}
BaconBackground *addLabel( Vec pos, const char* lab, int px, int align )
{
return addLabel( pos, lab, px, align, COLOR_BLACK );
}
BaconBackground *addLabel( Vec pos, const char* lab, int px, int align, NVGcolor col );

BaconBackground *addPlugLabel( Vec plugPos, LabelStyle s, const char* ilabel ) {
return addPlugLabel( plugPos, LabelAt::ABOVE, s, ilabel );
}
BaconBackground *addPlugLabel( Vec plugPos, LabelAt l, LabelStyle s, const char* ilabel );
BaconBackground *addRoundedBorder( Vec pos, Vec sz );
BaconBackground *addRoundedBorder( Vec pos, Vec sz, NVGcolor fill );

BaconBackground *addLabelsForHugeKnob( Vec topLabelPos, const char* knobLabel, const char* zeroLabel, const char* oneLabel, Vec &putKnobHere );
BaconBackground *addLabelsForLargeKnob( Vec topLabelPos, const char* knobLabel, const char* zeroLabel, const char* oneLabel, Vec &putKnobHere );

BaconBackground *addFilledRect( Vec pos, Vec sz, NVGcolor fill )
{
Rect r;
r.pos = pos; r.size = sz;
rects.push_back( col_rect_t( r, fill, true ) );
return this;
}

BaconBackground *addRect( Vec pos, Vec sz, NVGcolor fill )
{
Rect r;
r.pos = pos; r.size = sz;
rects.push_back( col_rect_t( r, fill, false ) );
return this;
}

void draw( NVGcontext *vg ) override;

FramebufferWidget *wrappedInFramebuffer();
};

struct BaconHelpButton : public SVGButton
{
std::string url;
BaconHelpButton( std::string urli ) : url( urli )
{
box.pos = Vec( 0, 0 );
box.size = Vec( 20, 20 );
setSVGs( SVG::load( assetPlugin( plugin, "res/HelpActiveSmall.svg" ) ), NULL );
url = "https://github.com/baconpaul/BaconPlugs/blob/";
#ifdef RELEASE_BRANCH
url += TO_STRING( RELEASE_BRANCH );
#else
url += "master/";
#endif
url += urli;
info( "Help button configured to: %s", url.c_str() );
}

void onAction( EventAction &e ) override {
std::thread t( [this]() {
systemOpenBrowser(url.c_str() );
} );
t.detach();
}
};

template< int NSteps, typename ColorModel >
struct NStepDraggableLEDWidget : public ParamWidget
{
BufferedDrawFunctionWidget<NStepDraggableLEDWidget<NSteps, ColorModel>> *buffer;
bool dragging;
Vec lastDragPos;
ColorModel cm;
NStepDraggableLEDWidget()
{
box.size = Vec( 10, 200 );
dragging = false;
lastDragPos = Vec( -1, -1 );
buffer = new BufferedDrawFunctionWidget<NStepDraggableLEDWidget<NSteps, ColorModel>>( Vec( 0, 0 ), this->box.size,
this,
&NStepDraggableLEDWidget<NSteps, ColorModel>::drawSegments );

}

int getStep()
{
float pvalue = this->module->params[ this->paramId ].value;
int step = (int)pvalue;
return step;
}

int impStep( float yp )
{
float py = (box.size.y - yp)/box.size.y;
return (int)( py * NSteps );
}
void draw( NVGcontext *vg ) override
{
buffer->draw( vg );
}

void valueByMouse( float ey )
{
if( impStep( ey ) != getStep() )
{
buffer->dirty = true;
setValue( impStep( ey ) );
}
}
void onMouseDown( EventMouseDown &e ) override
{
ParamWidget::onMouseDown( e );
valueByMouse( e.pos.y );
dragging = true;
}

void onMouseUp( EventMouseUp &e ) override
{
ParamWidget::onMouseUp( e );
valueByMouse( e.pos.y );
dragging = false;
lastDragPos = Vec( -1, -1 );
}

void onMouseMove( EventMouseMove &e ) override
{
ParamWidget::onMouseMove( e );
if( dragging && ( e.pos.x != lastDragPos.x || e.pos.y != lastDragPos.y ))
{
valueByMouse( e.pos.y );
lastDragPos = e.pos;
}
}

void onMouseLeave( EventMouseLeave &e ) override
{
ParamWidget::onMouseLeave( e );
dragging = false;
lastDragPos = Vec( -1, -1 );
}

void drawSegments( NVGcontext *vg )
{
// This is now buffered to only be called when the value has changed
int w = this->box.size.x;
int h = this->box.size.y;
nvgBeginPath( vg );
nvgRect( vg, 0, 0, w, h );
nvgFillColor( vg, nvgRGB( 40, 40, 40 ) );
nvgFill( vg );

float dy = box.size.y / NSteps;
for( int i=0; i<NSteps; ++i )
{
nvgBeginPath( vg );
nvgRect( vg, 1, i * dy + 1, w - 2, dy - 2 );
nvgFillColor( vg, cm.elementColor( NSteps - 1 - i , NSteps, getStep() ) );
nvgFill( vg );
}
}

};

struct GreenFromZeroColorModel
{
NVGcolor GREEN, BLACK;
GreenFromZeroColorModel() : GREEN( nvgRGB( 10, 255, 10 ) ), BLACK( nvgRGB( 10, 10, 10 ) ) { }
NVGcolor elementColor( int stepNo, int NSteps, int value )
{
if( stepNo <= value )
return nvgRGB( 10, 155 + 1.0f * stepNo / NSteps * 100, 10 );
else
return BLACK;
}
};


struct RedGreenFromMiddleColorModel
{
NVGcolor GREEN, BLACK, RED;
RedGreenFromMiddleColorModel() : GREEN( nvgRGB( 10, 255, 10 ) ), BLACK( nvgRGB( 10, 10, 10 ) ), RED( nvgRGB( 255, 10, 10 ) ) { }
NVGcolor elementColor( int stepNo, int NSteps, int value )
{
// This has the 'midpoint' be 0 so we want to compare with NSteps/2
if( value < NSteps / 2 ) {
// We are in the bottom half.
if( stepNo < value || stepNo >= NSteps / 2) return BLACK;
else
{
int distance = NSteps / 2 - stepNo;
return nvgRGB( 155 + 1.0f * distance / ( NSteps / 2 ) * 100 , 10, 10 );
}
} else {
if( stepNo > value || stepNo < NSteps / 2) return BLACK;
else
{
int distance = stepNo - NSteps / 2;
return nvgRGB( 10, 155 + 1.0f * distance / ( NSteps / 2 ) * 100 , 10 );
}
}
}
};

#include <iostream>
// Think hard about dirty state management ... later
// Pixel Sizing
// Share fontdata
struct DotMatrixLightTextWidget : public Component // Thanks http://scruss.com/blog/tag/font/
{
typedef std::function< std::string( Module * )> stringGetter;
typedef std::function< bool( Module * )> stringDirtyGetter;

BufferedDrawFunctionWidget<DotMatrixLightTextWidget> *buffer;

int charCount;
std::string currentText;

typedef std::map< char, std::vector< bool > > fontData_t;
fontData_t fontData;

float ledSize, padSize;

DotMatrixLightTextWidget() : Component(), buffer( NULL ), currentText( "" )
{
}

void setup()
{
ledSize = 2;
padSize = 1;
box.size = Vec( charCount * ( 5 * ledSize + padSize ) + 2 * padSize, 7 * ledSize + 4.5 * padSize ); // 5 x 7 data structure
buffer = new BufferedDrawFunctionWidget< DotMatrixLightTextWidget >( Vec( 0, 0 ), this->box.size, this,
&DotMatrixLightTextWidget::drawText );

info( "BaconMusic loading DMP json: %s", assetPlugin( plugin, "res/Keypunch029.json" ).c_str() );
json_t *json;
json_error_t error;
json = json_load_file(assetPlugin( plugin, "res/Keypunch029.json" ).c_str(), 0, &error);
if(!json) {
info( "JSON FILE not loaded\n" );
}
const char* key;
json_t *value;
json_object_foreach( json, key, value ) {
fontData_t::mapped_type valmap;
size_t index;
json_t *aval;
json_array_foreach( value, index, aval ) {
std::string s( json_string_value( aval ) );
for( const char* c = s.c_str(); *c != 0; ++c ) {
valmap.push_back( *c == '#' );
}
}
fontData[ key[ 0 ] ] = valmap;
}
}
// create takes a function
static DotMatrixLightTextWidget *create( Vec pos, Module *module, int charCount, stringDirtyGetter dgf, stringGetter gf )
{
DotMatrixLightTextWidget *r = Component::create<DotMatrixLightTextWidget>( pos, module );
r->getfn = gf;
r->dirtyfn = dgf;
r->charCount = charCount;
r->setup();
return r;
}

stringDirtyGetter dirtyfn;
stringGetter getfn;
void draw( NVGcontext *vg ) override
{
if( dirtyfn( this->module ) )
{
currentText = getfn( this->module );
buffer->dirty = true;
}
if( buffer )
buffer->draw( vg );
}

void drawChar( NVGcontext *vg, Vec pos, char c )
{
#define UPPERCASE(a) ((char)( ((a)>='a'&&(a)<='z') ? ((a)&~32) : (a) ))
// fontData_t::iterator k = fontData.find( (cstd::toupper( c ) );
fontData_t::iterator k = fontData.find( UPPERCASE(c) );

if( k != fontData.end() ) {
fontData_t::mapped_type blist = k->second;
int row=0, col=0;
for( auto v = blist.begin(); v != blist.end(); ++v )
{
if( *v )
{
float xo = (col+0.5) * ledSize + pos.x;
float yo = (row+0.5) * ledSize + pos.y;
nvgBeginPath( vg );
// nvgRect( vg, xo, yo, ledSize, ledSize );
nvgCircle( vg, xo + ledSize/2.0f, yo + ledSize/2.0f, ledSize/2.0f * 1.1 );
nvgFillColor( vg, nvgRGBA( 25, 35, 25, 255 ) );
nvgFill( vg );
nvgBeginPath( vg );
// nvgRect( vg, xo, yo, ledSize, ledSize );
nvgCircle( vg, xo + ledSize/2.0f, yo + ledSize/2.0f, ledSize/2.0f );
nvgFillColor( vg, COLOR_BLUE ); // Thanks for having such a nice blue, Rack!!
nvgFill( vg );
}
col++;
if( col == 5 ) {
col = 0;
row ++;
}
}
}
else {
}
}
void drawText( NVGcontext *vg )
{
nvgBeginPath( vg );
nvgRect( vg, 0, 0, box.size.x, box.size.y );
nvgFillColor( vg, nvgRGBA( 15, 15, 55, 255 ) );
nvgFill( vg );

Vec cpos = Vec( padSize, padSize );
for( const char* c = currentText.c_str(); *c != 0; ++c ) {
drawChar( vg, cpos, *c );
cpos.x += ledSize * 5 + padSize;
}
}

void onZoom( EventZoom &e ) override
{
buffer->dirty = true;
}
};

#include "SizeTable.hpp"


#endif

+ 58
- 0
plugins/community/repos/BaconMusic/src/Glissinator.cpp View File

@@ -0,0 +1,58 @@
#include "BaconPlugs.hpp"
#include "Glissinator.hpp"

namespace rack_plugin_BaconMusic {

struct GlissinatorWidget : ModuleWidget {
typedef Glissinator< Module > G;
GlissinatorWidget( Glissinator<Module> *model );
};

GlissinatorWidget::GlissinatorWidget( Glissinator<Module> *model ) : ModuleWidget( model )
{
box.size = Vec( SCREW_WIDTH * 5, RACK_HEIGHT );
BaconBackground *bg = new BaconBackground( box.size, "Glissinator" );

addChild( bg->wrappedInFramebuffer() );
// FIXME - spacing
// addChild( new BaconHelpButton( "README.md#glissinator" ) );
ParamWidget *slider = ParamWidget::create< GraduatedFader< 230 > >( Vec( bg->cx( 29 ), 23 ),
module,
G::GLISS_TIME,
0,
1,
0.1 );
addParam( slider );

Vec inP = Vec( 7, RACK_HEIGHT - 15 - 43 );
Vec outP = Vec( box.size.x - 24 - 7, RACK_HEIGHT - 15 - 43 );
bg->addPlugLabel( inP, BaconBackground::SIG_IN, "in" );
addInput( Port::create< PJ301MPort >( inP, Port::INPUT,
module,
G::SOURCE_INPUT ) );

bg->addPlugLabel( outP, BaconBackground::SIG_OUT, "out" );
addOutput( Port::create< PJ301MPort >( outP, Port::OUTPUT,
module,
G::SLID_OUTPUT ) );

bg->addRoundedBorder( Vec( 5, RACK_HEIGHT - 120 ), Vec( box.size.x - 10, 38 ), BaconBackground::highlight );
bg->addLabel( Vec( 10, RACK_HEIGHT - 102 ), "gliss", 11, NVG_ALIGN_LEFT | NVG_ALIGN_BOTTOM, COLOR_WHITE );
bg->addLabel( Vec( 10, RACK_HEIGHT - 90 ), "gate", 11, NVG_ALIGN_LEFT | NVG_ALIGN_BOTTOM, COLOR_WHITE );
addChild( ModuleLightWidget::create< SmallLight< BlueLight > >( Vec( bg->cx() - 4 , RACK_HEIGHT - 120 + 38 / 2 - 3 ),
module, G::SLIDING_LIGHT ) );
addOutput( Port::create< PJ301MPort >( Vec( bg->cx() + 5, RACK_HEIGHT - 114 ), Port::OUTPUT, module, G::GLISSING_GATE ) );
}

} // namespace rack_plugin_BaconMusic

using namespace rack_plugin_BaconMusic;

RACK_PLUGIN_MODEL_INIT(BaconMusic, Glissinator) {
Model *modelGlissinator = Model::create<Glissinator<Module>,GlissinatorWidget>("Bacon Music", "Glissinator", "Glissinator", EFFECT_TAG);
return modelGlissinator;
}

+ 119
- 0
plugins/community/repos/BaconMusic/src/Glissinator.hpp View File

@@ -0,0 +1,119 @@

namespace rack_plugin_BaconMusic {

template <typename TBase>
struct Glissinator : public TBase {
enum ParamIds {
GLISS_TIME,

NUM_PARAMS
};

enum InputIds {
SOURCE_INPUT,
NUM_INPUTS
};

enum OutputIds {
SLID_OUTPUT,
GLISSING_GATE,
NUM_OUTPUTS
};

enum LightIds {
SLIDING_LIGHT,
NUM_LIGHTS
};

float priorIn;
float targetIn;
int offsetCount;

// Hey thanks https://stackoverflow.com/a/4643091
using TBase::params;
using TBase::inputs;
using TBase::outputs;
using TBase::lights;

Glissinator() : TBase( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS ) {
offsetCount = -1;
params[ GLISS_TIME ].value = 0.1;
}


void step() override
{
float glist_sec = params[ GLISS_TIME ].value;
int shift_time = engineGetSampleRate() * glist_sec;
if( shift_time < 10 ) shift_time = 10;
float thisIn = inputs[ SOURCE_INPUT ].value;

// This means I am being intialized
if( offsetCount < 0 )
{
priorIn = thisIn;
offsetCount = 0;
}

bool inGliss = offsetCount != 0;
float thisOut = thisIn;

// When I begin the cycle, the shift_time may be a different shift_time than the
// prior cycle. This is not a problem unless the shift time is now shorter than
// the offset_time. If that's the case we have basically finished the gliss.
// This check used to be at the end of the loop but that lead to one bad value
// even with the >=
if( offsetCount >= shift_time )
{
offsetCount = 0;
priorIn = thisIn;
targetIn = thisIn;
inGliss = false;
}

// I am not glissing
if( ! inGliss )
{
// But I have a new target, so start glissing by setting offset count to 1.
if( thisIn != priorIn )
{
targetIn = thisIn;
offsetCount = 1;
inGliss = true;
}
}

// I am glissing (note this is NOT in an else since inGliss can be reset above)
if( inGliss )
{
// OK this means my note has changed underneath me so I have to simulate my
// starting point.
if( thisIn != targetIn )
{
// This "-1" is here because we want to know the LAST known step - so at the prior
// offset count. Without this a turnaround will tick above the turnaround point for one
// sample.
float lastKnown = ( ( shift_time - (offsetCount-1) ) * priorIn +
(offsetCount-1) * targetIn) / shift_time;
targetIn = thisIn;
priorIn = lastKnown;
offsetCount = 0;
}

// Then the output is just the weighted sum of the prior input and this input.
thisOut = ( ( shift_time - offsetCount ) * priorIn +
offsetCount * thisIn ) / shift_time;

// and step along one.
offsetCount ++;
}

lights[ SLIDING_LIGHT ].value = inGliss ? 1 : 0;
outputs[ SLID_OUTPUT ].value = thisOut;
outputs[ GLISSING_GATE ].value = inGliss ? 10 : 0;
}
};

} // namespace rack_plugin_BaconMusic

+ 87
- 0
plugins/community/repos/BaconMusic/src/GraduatedFader.hpp View File

@@ -0,0 +1,87 @@
#include "rack.hpp"

#include "BufferedDrawFunction.hpp"

template <int H>
struct GraduatedFader : SVGFader
{
int slider_height = 41;
int slider_width = 20;
int widget_width = 28;
FramebufferWidget *notches;

GraduatedFader()
{
background->svg = NULL;
background->wrap();
background->box.pos = Vec( 0, 0 );
handle->svg = SVG::load( assetPlugin( plugin, "res/BaconSliderHandle.svg" ) );
handle->wrap();

maxHandlePos = Vec( (widget_width-slider_width)/2, 0 );
minHandlePos = Vec( (widget_width-slider_width)/2, (H-slider_height) );
box.size = Vec( widget_width, H );

notches = new BufferedDrawFunctionWidget<GraduatedFader<H>>( Vec( 0, 0 ), box.size, this,
&GraduatedFader<H>::drawBackground );
}
void draw( NVGcontext *vg ) override
{
notches->draw( vg );
SVGFader::draw( vg );
}

void drawBackground( NVGcontext *vg )
{
int nStrokes = 10;
int slideTop = slider_height / 2;
int slideHeight = H - slider_height;
int slideBump = 5;
int slotWidth = 1;
#ifdef DEBUG_NOTCHES
nvgBeginPath( vg );
nvgRect( vg, 0, 0, widget_width, H );
nvgFillColor( vg, COLOR_RED );
nvgFill( vg );
#endif
float dx = (1.0 * slideHeight) / nStrokes;
// Firest the gray highlights
for( int i=0; i<= nStrokes; ++i )
{
nvgBeginPath( vg );
nvgRect( vg, 1, slideTop + dx * i, widget_width-2, 1 );
nvgFillColor( vg, nvgRGBA( 200, 200, 200, 255 ) );
nvgFill( vg );
}
// and now the black notches
for( int i=0; i<= nStrokes; ++i )
{
nvgBeginPath( vg );
nvgRect( vg, 1, slideTop + dx * i-1, widget_width-2, 1.5 );
nvgFillColor( vg, nvgRGBA( 100, 100, 100, 255 ));
nvgFill( vg );
}
// OK so now we want to draw the vertical line
nvgBeginPath( vg );
nvgRect( vg, widget_width/2 - slotWidth, slideTop - slideBump, 2 * slotWidth + 1, slideHeight + 2 * slideBump );
nvgFillColor( vg, COLOR_BLACK );
nvgFill( vg );
}

void onZoom( EventZoom &e ) override
{
// Need this because I don't add it as a child, since the base class does something funky with that
notches->onZoom( e );
SVGFader::onZoom( e );
}

};


+ 217
- 0
plugins/community/repos/BaconMusic/src/HarMoNee.cpp View File

@@ -0,0 +1,217 @@
#include "BaconPlugs.hpp"

namespace rack_plugin_BaconMusic {

struct HarMoNee : Module {
enum ParamIds {
UP_OR_DOWN,
HALF_STEP,
WHOLE_STEP,
MINOR_THIRD,
MAJOR_THIRD,
FIFTH,
OCTAVE,
NUM_PARAMS
};
enum InputIds {
SOURCE_INPUT,
NUM_INPUTS
};
enum OutputIds {
ECHO_OUTPUT,
INCREASED_OUTPUT,
NUM_OUTPUTS
};
enum LightIds {
UP_LIGHT,
DOWN_LIGHT,
HALF_STEP_LIGHT,
WHOLE_STEP_LIGHT,
MINOR_THIRD_LIGHT,
MAJOR_THIRD_LIGHT,
FIFTH_LIGHT,
OCTAVE_LIGHT,

DIGIT_LIGHT,
NUM_LIGHTS
};
std::vector< float > offsets;
float priorOffset;
float targetOffset;
int offsetCount;
HarMoNee() : Module( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS ) {
for( int i=0; i<OCTAVE; ++i ) offsets.push_back( 0 );

offsets[ HALF_STEP ] = 1;
offsets[ WHOLE_STEP ] = 2;
offsets[ MINOR_THIRD ] = 3;
offsets[ MAJOR_THIRD ] = 4;
offsets[ FIFTH ] = 7;
offsets[ OCTAVE ] = 12;
priorOffset = 0;
targetOffset = 0;
offsetCount = 0;
}

void step() override;
};

void HarMoNee::step() {
/* TODO
Display the shift
Tests
*/

float in = inputs[ SOURCE_INPUT ].value;
float echo = in;

float offsetI = 0;
float uod = ( params[ UP_OR_DOWN ].value > 0 ) ? 1.0 : -1.0;
if( uod > 0 )
{
lights[ UP_LIGHT ].value = 1; lights[ DOWN_LIGHT ].value = 0;
}
else
{
lights[ DOWN_LIGHT ].value = 1; lights[ UP_LIGHT ].value = 0;
}

int ld = HALF_STEP_LIGHT - HALF_STEP;
for( int i=HALF_STEP; i <= OCTAVE; ++i )
{
if( params[ i ].value > 0 )
{
lights[ i + ld ].value = 1.0;
offsetI += offsets[ i ];
}
else
{
lights[ i + ld ].value = 0.0;
}
}
lights[ DIGIT_LIGHT ].value = offsetI;
offsetI = uod * offsetI / 12.0;

int shift_time = 44000 / 5;
/* Glissando state management
- priorOffset is the place we are starting the glide from
- targetOffset is where we are headed
- offsetI is where the switches are set
- offsetCount is how far we are in.

when we aren't in a glissando offsetCount will be 0 and
all three will be the same. offsetCount being
non-zero is the same as in-gliss.
*/
bool inGliss = offsetCount != 0;
if( ! inGliss )
{
// We are not sliding. Should we be?
if( offsetI != priorOffset )
{
targetOffset = offsetI;
offsetCount = 1;
inGliss = true;
}
}

if( inGliss )
{
// If the target == the offset we haven't changed anything so
// just march along linear time
if( offsetI != targetOffset )
{
float lastKnown = ( ( shift_time - offsetCount ) * priorOffset +
offsetCount * targetOffset ) / shift_time;
targetOffset = offsetI;
priorOffset = lastKnown;
offsetCount = 0;
}
offsetI = ( ( shift_time - offsetCount ) * priorOffset +
offsetCount * offsetI ) / shift_time;
offsetCount ++;
}

// Finally if we are done, reset it all to zero
if( offsetCount == shift_time )
{
offsetCount = 0;
priorOffset = offsetI;
targetOffset = offsetI;
}
float increased = in + offsetI;

outputs[ ECHO_OUTPUT ].value = echo;
outputs[ INCREASED_OUTPUT ].value = increased;
}

struct HarMoNeeWidget : ModuleWidget {
HarMoNeeWidget(HarMoNee *model);
};


HarMoNeeWidget::HarMoNeeWidget( HarMoNee *model ) : ModuleWidget( model )
{
box.size = Vec( SCREW_WIDTH*8 , RACK_HEIGHT );

BaconBackground *bg = new BaconBackground( box.size, "HarMoNee" );

addChild( bg->wrappedInFramebuffer() );
Vec iPos( 12, 100 );
bg->addPlugLabel( iPos, BaconBackground::SIG_IN, "in" );
addInput( Port::create< PJ301MPort >( iPos, Port::INPUT, module, HarMoNee::SOURCE_INPUT ) );

iPos.y += 60;
bg->addPlugLabel( iPos, BaconBackground::SIG_OUT, "root" );
addOutput( Port::create<PJ301MPort>(iPos, Port::OUTPUT, module, HarMoNee::ECHO_OUTPUT ) );

iPos.y += 60;
bg->addPlugLabel( iPos, BaconBackground::SIG_OUT, "harm" );
addOutput( Port::create<PJ301MPort>(iPos, Port::OUTPUT, module, HarMoNee::INCREASED_OUTPUT ) );

// NKK is 32 x 44
addParam( ParamWidget::create< NKK >( Vec( 80, 26 ), module, HarMoNee::UP_OR_DOWN, 0, 1, 1 ) );
bg->addLabel( Vec( 74, 26+22-4-5-5 ), "up", 12, NVG_ALIGN_CENTER | NVG_ALIGN_BOTTOM );
addChild( ModuleLightWidget::create< MediumLight< GreenLight >>( Vec( 70, 26 + 22 - 4 - 5 ), module, HarMoNee::UP_LIGHT ) );

bg->addLabel( Vec( 74, 26+22-4+5+8+7 ), "dn", 12, NVG_ALIGN_CENTER | NVG_ALIGN_TOP );
addChild( ModuleLightWidget::create< MediumLight< RedLight >>( Vec( 70, 26 + 22 - 4 + 5 ), module, HarMoNee::DOWN_LIGHT ) );


addChild( MultiDigitSevenSegmentLight< BlueLight, 4, 2 >::create( Vec( 10, 30 ),
module,
HarMoNee::DIGIT_LIGHT ) );


int x = 80; int y = 26 + 45; float v = -1;
int ld = HarMoNee::HALF_STEP_LIGHT - HarMoNee::HALF_STEP;

const char* labels[] = { "1/2", "W", "m3", "III", "V", "O" };
for( int i = HarMoNee::HALF_STEP; i <= HarMoNee::OCTAVE; ++i )
{
if( i == HarMoNee::OCTAVE ) { v = 1; } { v = -1; }
addParam( ParamWidget::create<NKK>( Vec( x, y ), module, i, 0, 1, v ) );
bg->addLabel( Vec( 66, y+22 ), labels[ i - HarMoNee::HALF_STEP ],
14, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE );
addChild( ModuleLightWidget::create< MediumLight< BlueLight > >( Vec( 70, y + 22 - 5 ), module, i + ld ) );
y += 45;
}
}

} // namespace rack_plugin_BaconMusic

using namespace rack_plugin_BaconMusic;

RACK_PLUGIN_MODEL_INIT(BaconMusic, HarMoNee) {
Model *modelHarMoNee = Model::create<HarMoNee,HarMoNeeWidget>("Bacon Music", "HarMoNee", "HarMoNee", TUNER_TAG);
return modelHarMoNee;
}

+ 217
- 0
plugins/community/repos/BaconMusic/src/KSSynth.hpp View File

@@ -0,0 +1,217 @@
// An implementation of the KSSYnth class in the ipython notebook in ../pynb/KarplusStrong.ipynb

#include <string>
#include <vector>
#include <math.h>
#include <cstdlib>

class KSSynth {
public:
typedef enum InitPacket {
RANDOM,
SQUARE,
SAW,
NOISYSAW,
SIN,
SINCHIRP // if you add remember to fix the count below...
} InitPacket;

std::string initPacketName( InitPacket p )
{
switch(p)
{
case RANDOM: return "random";
case SQUARE: return "square";
case SAW: return "saw";
case NOISYSAW: return "noisysaw";
case SIN: return "sin";
case SINCHIRP: return "sinchirp";
}
return "";
}

int numInitPackets()
{
return (int)SINCHIRP + 1;
}

typedef enum FilterType {
WEIGHTED_ONE_SAMPLE
} FilterType;

std::string filterTypeName( FilterType p )
{
switch(p)
{
case WEIGHTED_ONE_SAMPLE: return "wgt 1samp";
}
return "";
}

int numFilterTypes()
{
return WEIGHTED_ONE_SAMPLE + 1;
}

public:
// here's my interior state
InitPacket packet;
FilterType filter;

float filtParamA, filtParamB, filtParamC, filtAtten;

float sumDelaySquared; // This is updated about 100 times a second, not per sample

bool active;
//private:
float freq;
int burstLen;
float wfMin, wfMax;
int sampleRate, sampleRateBy100;
float filtAttenScaled;

long pos;
std::vector< float > delay;


public:

KSSynth( float minv, float maxv, int sampleRateIn )
:
packet( RANDOM ),
filter( WEIGHTED_ONE_SAMPLE ),

filtParamA( 0.5f ),
filtParamB( 0.0f ),
filtParamC( 0.0f ),
filtAtten( 3.0f ),

active( false ),

wfMin( minv ), wfMax( maxv ),
sampleRate( sampleRateIn ),
sampleRateBy100( (int)( sampleRate / 100 ) ),
pos( 0 )
{
setFreq( 220 );
}

void setFreq( float f )
{
freq = f;
burstLen = (int)( ( 1.0f * sampleRate / freq + 0.5 ) * 2 );
filtAttenScaled = filtAtten / 100 / ( freq / 440 );
delay.resize( burstLen );
}

void trigger( float f )
{
// remember: Interally we work on the range [-1.0f, 1.0f] to match the python (but different from
// the ChipSym which works on [ 0 1.0f ]
active = true;
setFreq( f );
pos = 1;
switch( packet )
{
case RANDOM:
{
for( int i=0; i<burstLen; ++i )
{
delay[ i ] = (float)rand() * 1.0 / RAND_MAX;
delay[ i ] = delay[ i ] * 2.0 - 1.0;
}
break;
}
case SQUARE:
{
int xo = (int)burstLen / 2.0;
for( int i=0; i<burstLen; ++i )
{
delay[ i ] = ( i <= xo ? 1.0 : -1.0 );
}
break;
}
case SAW:
{
for( int i=0; i<burstLen; ++i )
{
delay[ i ] = ( i * 2.0f / burstLen ) - 1.0;
}
break;
}

case NOISYSAW:
{
for( int i=0; i<burstLen; ++i )
{
delay[ i ] = ( i * 1.0f / burstLen ) - 0.5;
delay[ i ] += (float)rand() * 1.0f / RAND_MAX - 0.5;
}
break;
}

case SIN:
{
float scale = 2.0 * M_PI / burstLen;
for( int i=0; i<burstLen; ++i )
{
delay[ i ] = sin( i * scale );
}
break;
}
case SINCHIRP:
{
for( int i=0; i<burstLen; ++i )
{
float ls = 1.0f * i / burstLen;
float lse = exp( ls * 2 ) * 3;
delay[ i ] = sin( lse * 2 * M_PI );
}
break;
}
}
updateSumDelaySquared();
}

void updateSumDelaySquared()
{
sumDelaySquared = 0;
for( int i=0; i<burstLen; ++i )
{
sumDelaySquared += delay[ i ] * delay[ i ];
}
sumDelaySquared /= burstLen;

}
float step()
{
if( ! active ) return 0;
int dpos = pos % burstLen;
int dpnext = ( pos + 1 ) % burstLen;
int dpfill = ( pos - 1 ) % burstLen;
if( pos % sampleRateBy100 == 0 )
{
updateSumDelaySquared();
if( sumDelaySquared < 1e-7 ) // think about this threshold some
active = false;
}
pos++;


float filtval = 0.5;
switch( filter )
{
case WEIGHTED_ONE_SAMPLE:
float ftw = filtParamA;
float fta = filtAttenScaled;
filtval = ( ftw * delay[ dpos ] + ( 1.0 - ftw ) * delay[ dpnext ] ) * ( 1.0 - fta );
break;
}
delay[ dpfill ] = filtval;
return ( ( filtval + 1.0 ) * 0.5 ) * ( wfMax - wfMin ) + wfMin;
}
};

+ 411
- 0
plugins/community/repos/BaconMusic/src/KarplusStrongPoly.cpp View File

@@ -0,0 +1,411 @@

#include "BaconPlugs.hpp"
#include <sstream>
#include <vector>
#include <string>
#include "dsp/digital.hpp"

#include "KSSynth.hpp"

namespace rack_plugin_BaconMusic {

struct KarplusStrongPoly : virtual Module {
enum ParamIds {
INITIAL_PACKET,
FILTER_TYPE,
FREQ_KNOB,
ATTEN_KNOB,
FILTER_KNOB_A,
FILTER_KNOB_B,
FILTER_KNOB_C,
NUM_PARAMS
};

enum InputIds {
TRIGGER_GATE,
INITIAL_PACKET_INPUT,
FILTER_INPUT,
FREQ_CV,
ATTEN_CV,
FILTER_CV_A,
FILTER_CV_B,
FILTER_CV_C,
NUM_INPUTS
};

enum OutputIds {
SYNTH_OUTPUT,
NUM_OUTPUTS
};

enum LightIds {
LIGHT_PACKET_KNOB,
LIGHT_PACKET_CV,
LIGHT_FILTER_KNOB,
LIGHT_FILTER_CV,

LIGHT_FILTER_A,
LIGHT_FILTER_B,
LIGHT_FILTER_C,
NUM_LIGHTS
};


SchmittTrigger voiceTrigger;

std::vector< KSSynth *> voices;
const static int nVoices = 32;
KarplusStrongPoly() : Module( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS )
{
for( int i=0; i<nVoices; ++i ) voices.push_back( new KSSynth(-2.0f, 2.0f, engineGetSampleRate() ) );
initPacketStringDirty = true;
currentInitialPacket = KSSynth::RANDOM;
initPacketString = voices[ 0 ]->initPacketName( currentInitialPacket );

filterStringDirty = true;
currentFilter = KSSynth::WEIGHTED_ONE_SAMPLE;
filterString = voices[ 0 ]->filterTypeName( currentFilter );

}

virtual ~KarplusStrongPoly()
{
for( auto syn : voices )
delete syn;
}
int getNumPackets() { return voices[ 0 ]->numInitPackets(); }
KSSynth::InitPacket currentInitialPacket;

int getNumFilters() { return voices[ 0 ]->numFilterTypes(); }
KSSynth::FilterType currentFilter;
void step() override
{
int nextInitialPacket = currentInitialPacket;
float ipi, ipiS;
lights[ LIGHT_PACKET_CV ].value = inputs[INITIAL_PACKET_INPUT].active;
lights[ LIGHT_PACKET_KNOB ].value = !inputs[INITIAL_PACKET_INPUT].active;

lights[ LIGHT_FILTER_CV ].value = inputs[FILTER_INPUT].active;
lights[ LIGHT_FILTER_KNOB ].value = !inputs[FILTER_INPUT].active;

// For now, since we only have one filter, hardcode this
lights[ LIGHT_FILTER_A ].value = 1;
lights[ LIGHT_FILTER_B ].value = 0;
lights[ LIGHT_FILTER_C ].value = 0;
if( inputs[ INITIAL_PACKET_INPUT ].active )
{
ipi = inputs[ INITIAL_PACKET_INPUT ].value;
ipiS = ipi * getNumPackets() / 10.0;
nextInitialPacket = (int)(ipiS);
}
else
{
nextInitialPacket = (int)( params[ INITIAL_PACKET ].value );
}
if( nextInitialPacket != currentInitialPacket )
{
initPacketStringDirty = true;
currentInitialPacket = (KSSynth::InitPacket)( nextInitialPacket );
initPacketString = voices[ 0 ]->initPacketName( currentInitialPacket );
}

// Check a trigger here and find a voice
bool newVoice = false;
if( voiceTrigger.process( inputs[ TRIGGER_GATE ].value ) )
{
newVoice = true;
}

if( newVoice )
{
// find voice
KSSynth *voice = NULL;
for( auto syn: voices )
if( ! syn->active )
{
voice = syn;
break;
}

if( voice == NULL )
{
// info( "All voices are active: Running voice steal" );
voice = voices[ 0 ];
float ds = voice->sumDelaySquared;
for( auto syn: voices )
{
if( syn->sumDelaySquared < ds )
{
ds = syn->sumDelaySquared;
voice = syn;
}
}
}
// Capture parameters onto this voice and trigger it
float pitch = params[ FREQ_KNOB ].value + 12.0f * inputs[ FREQ_CV ].value;
float freq = 261.262f * powf( 2.0f, pitch / 12.0f );


// For now, since we only have one filter, hardcode this
voice->filtParamA = clamp( params[ FILTER_KNOB_A ].value + inputs[ FILTER_CV_A ].value * 0.1, 0.0f, 1.0f );
voice->filtParamB = 0;
voice->filtParamC = 0;
float atten = params[ ATTEN_KNOB ].value + inputs[ ATTEN_CV ].value;
voice->packet = currentInitialPacket;
voice->filtAtten = atten;
voice->trigger( freq );
}
float out = 0.0f;
for( auto syn : voices )
if( syn->active )
out += syn->step();

outputs[ SYNTH_OUTPUT ].value = out;
}

bool initPacketStringDirty;
std::string initPacketString;
static bool getInitialPacketStringDirty( Module *that )
{
return dynamic_cast<KarplusStrongPoly *>(that)->initPacketStringDirty;
}
static std::string getInitialPacketString( Module *that )
{
dynamic_cast<KarplusStrongPoly *>(that)->initPacketStringDirty = false;
return dynamic_cast<KarplusStrongPoly *>(that)->initPacketString;
}

bool filterStringDirty;
std::string filterString;
static bool getFilterStringDirty( Module *that )
{
return dynamic_cast<KarplusStrongPoly *>(that)->filterStringDirty;
}
static std::string getFilterString( Module *that )
{
dynamic_cast<KarplusStrongPoly *>(that)->filterStringDirty = false;
return dynamic_cast<KarplusStrongPoly *>(that)->filterString;
}
};

struct KarplusStrongPolyWidget : ModuleWidget {
KarplusStrongPolyWidget( KarplusStrongPoly *module);
};

KarplusStrongPolyWidget::KarplusStrongPolyWidget( KarplusStrongPoly *module ) : ModuleWidget( module )
{
box.size = Vec( SCREW_WIDTH * 15, RACK_HEIGHT );

BaconBackground *bg = new BaconBackground( box.size, "KarplusStrongPoly" );
addChild( bg->wrappedInFramebuffer());

float outy;
float yh;
int margin = 4;
float gap = 13;
int obuf = 10;
outy = 35;

float scale = 1.0;
bool last = false;

auto brd = [&](float ys)
{
// Add a downward pointing triangle here which means I need a draw glyph
if( ! last )
{
int w = 70;
addChild( new BufferedDrawLambdaWidget( Vec( bg->cx() - w/2, outy + ys + margin ),
Vec( w, gap ),
[=](NVGcontext *vg)
{
nvgBeginPath( vg );
nvgMoveTo( vg, 0, 0 );
nvgLineTo( vg, w/2, gap );
nvgLineTo( vg, w, 0 );
nvgClosePath( vg );
nvgStrokeColor( vg, COLOR_BLACK );
nvgStroke( vg );
nvgFillColor( vg, nvgRGB( 240 * scale, 240 * scale, 200 * scale ) );
nvgFill( vg );
}
)
);
}
bg->addRoundedBorder( Vec( obuf, outy - margin ),
Vec( box.size.x - 2 * obuf, ys + 2 * margin ),
nvgRGB( 240*scale, 240*scale, 200*scale ) );

scale *= 0.92;
};
auto cl = [&](std::string lab, float ys)
{
bg->addLabel( Vec( obuf + margin, outy + ys / 2 ), lab.c_str(), 13, NVG_ALIGN_MIDDLE | NVG_ALIGN_LEFT );
};

yh = SizeTable<PJ301MPort>::Y;
brd( yh );
cl( "Trigger", yh );
addInput( Port::create< PJ301MPort >( Vec( box.size.x - obuf - margin - SizeTable<PJ301MPort>::X, outy ),
Port::INPUT,
module,
KarplusStrongPoly::TRIGGER_GATE ) );

outy += yh + 2 * margin + gap;
yh = SizeTable<RoundBlackKnob >::Y;
brd( yh );
cl( "Freq", yh );
int xp = box.size.x - margin - obuf - SizeTable<PJ301MPort>::X;
addInput( Port::create< PJ301MPort >( Vec( xp, outy + diffY2c< RoundBlackKnob, PJ301MPort >() ),
Port::INPUT,
module,
KarplusStrongPoly::FREQ_CV ) );

xp -= SizeTable<RoundBlackKnob>::X + margin;
addParam( ParamWidget::create< RoundBlackKnob >( Vec( xp, outy ), module,
KarplusStrongPoly::FREQ_KNOB,
-54.0f, 54.0f, 0.0f ) );



outy += yh + 2 * margin + gap;


yh = SizeTable<RoundBlackSnapKnob>::Y;
brd( yh );
cl( "Packet", yh );

xp = 55;

addChild( ModuleLightWidget::create< SmallLight< BlueLight > >( Vec( xp - 2, outy - 2 ),
module,
KarplusStrongPoly::LIGHT_PACKET_KNOB ) );
addParam( ParamWidget::create< RoundBlackSnapKnob >( Vec( xp, outy ),
module,
KarplusStrongPoly::INITIAL_PACKET,
0,
module->getNumPackets()-1, 0 ) );


xp += SizeTable<RoundBlackSnapKnob>::X + margin;
addChild( ModuleLightWidget::create< SmallLight< BlueLight > >( Vec( xp - 2, outy - 2 + diffY2c<RoundBlackSnapKnob,PJ301MPort>()),
module,
KarplusStrongPoly::LIGHT_PACKET_CV ) );

addInput( Port::create<PJ301MPort>( Vec( xp, outy + diffY2c<RoundBlackSnapKnob,PJ301MPort>() ),
Port::INPUT, module, KarplusStrongPoly::INITIAL_PACKET_INPUT ) );
xp += SizeTable<PJ301MPort>::X + margin;
addChild( DotMatrixLightTextWidget::create( Vec( xp, outy + diffY2c<RoundBlackSnapKnob,DotMatrixLightTextWidget>() ),
module, 8,
KarplusStrongPoly::getInitialPacketStringDirty,
KarplusStrongPoly::getInitialPacketString ) );


outy += yh + 2 * margin + gap;

yh = SizeTable<RoundBlackSnapKnob>::Y + SizeTable<RoundBlackKnob>::Y + margin;
brd( yh );
cl( "Filter", SizeTable<RoundBlackKnob>::Y );
xp = 55;

addChild( ModuleLightWidget::create< SmallLight< BlueLight > >( Vec( xp - 2, outy - 2 ),
module,
KarplusStrongPoly::LIGHT_FILTER_KNOB ) );
addParam( ParamWidget::create< RoundBlackSnapKnob >( Vec( xp, outy ),
module,
KarplusStrongPoly::FILTER_TYPE,
0,
module->getNumFilters()-1, 0 ) );


xp += SizeTable<RoundBlackSnapKnob>::X + margin;
addChild( ModuleLightWidget::create< SmallLight< BlueLight > >( Vec( xp - 2, outy - 2 + diffY2c<RoundBlackSnapKnob,PJ301MPort>()),
module,
KarplusStrongPoly::LIGHT_FILTER_CV ) );

addInput( Port::create<PJ301MPort>( Vec( xp, outy + diffY2c<RoundBlackSnapKnob,PJ301MPort>() ),
Port::INPUT, module, KarplusStrongPoly::FILTER_INPUT ) );
xp += SizeTable<PJ301MPort>::X + margin;
addChild( DotMatrixLightTextWidget::create( Vec( xp, outy + diffY2c<RoundBlackSnapKnob,DotMatrixLightTextWidget>() ),
module, 8,
KarplusStrongPoly::getFilterStringDirty,
KarplusStrongPoly::getFilterString ) );

outy += SizeTable<RoundBlackKnob>::Y + 2 * margin;

xp = obuf + 2.5 * margin;
for( int i=0; i<3; ++i )
{
addChild( ModuleLightWidget::create< SmallLight< BlueLight> >( Vec( xp - 2, outy - 2 ),
module,
KarplusStrongPoly::LIGHT_FILTER_A + i ) );
bg->addLabel( Vec( xp, outy + SizeTable<RoundSmallBlackKnob>::Y ),
i == 0 ? "A" : i == 1 ? "B" : "C",
12,
NVG_ALIGN_BOTTOM | NVG_ALIGN_RIGHT );

xp += 3;

addParam( ParamWidget::create< RoundSmallBlackKnob >( Vec( xp, outy ),
module,
KarplusStrongPoly::FILTER_KNOB_A + i,
0, 1, 0.5 ) );
xp += SizeTable<RoundSmallBlackKnob>::X + margin;
addInput( Port::create<PJ301MPort>( Vec( xp, outy + diffY2c<RoundSmallBlackKnob,PJ301MPort>() ),
Port::INPUT, module, KarplusStrongPoly::FILTER_CV_A + i ) );
xp += SizeTable<PJ301MPort>::X + 3.5 * margin;
}

outy += yh - SizeTable<RoundBlackKnob>::Y + gap;
yh = SizeTable< RoundBlackKnob >::Y;
brd( yh );
cl( "Atten", yh );
xp = box.size.x - margin - obuf - SizeTable<PJ301MPort>::X;
addInput( Port::create< PJ301MPort >( Vec( xp, outy + diffY2c< RoundBlackKnob, PJ301MPort >() ),
Port::INPUT,
module,
KarplusStrongPoly::ATTEN_CV ) );

xp -= SizeTable<RoundBlackKnob>::X + margin;
addParam( ParamWidget::create< RoundBlackKnob >( Vec( xp, outy ), module,
KarplusStrongPoly::ATTEN_KNOB,
0.1, 4, 1.95 ) );


outy += yh + 2 * margin + gap;
last = true;
brd( SizeTable<PJ301MPort>::Y );
cl( "Output", SizeTable<PJ301MPort>::Y );
addOutput( Port::create< PJ301MPort >( Vec( box.size.x - obuf - margin - SizeTable<PJ301MPort>::X, outy ),
Port::OUTPUT,
module,
KarplusStrongPoly::SYNTH_OUTPUT ) );

}

} // namespace rack_plugin_BaconMusic

using namespace rack_plugin_BaconMusic;

RACK_PLUGIN_MODEL_INIT(BaconMusic, KarplusStrongPoly) {
Model *modelKarplusStrongPoly = Model::create<KarplusStrongPoly, KarplusStrongPolyWidget>("Bacon Music", "KarplusStrongPoly", "KarplusStrongPoly", OSCILLATOR_TAG );
return modelKarplusStrongPoly;
}

+ 179
- 0
plugins/community/repos/BaconMusic/src/PolyGnome.cpp View File

@@ -0,0 +1,179 @@

#include "BaconPlugs.hpp"

#include <vector>
#include <algorithm>

#define NUM_CLOCKS 4

namespace rack_plugin_BaconMusic {

struct PolyGnome : virtual Module {
enum ParamIds {
CLOCK_PARAM,
CLOCK_NUMERATOR_1,
CLOCK_DENOMINATOR_1 = CLOCK_NUMERATOR_1 + NUM_CLOCKS,
NUM_PARAMS = CLOCK_DENOMINATOR_1 + NUM_CLOCKS,
};

enum InputIds {
CLOCK_INPUT,
NUM_INPUTS,
};

enum OutputIds {
CLOCK_GATE_0,
NUM_OUTPUTS = CLOCK_GATE_0 + NUM_CLOCKS + 1 // the "1" is for the 1/4 note clock which isn't parameterized
};

enum LightIds {
LIGHT_NUMERATOR_1,
LIGHT_DENOMINATOR_1 = LIGHT_NUMERATOR_1 + NUM_CLOCKS,
NUM_LIGHTS = LIGHT_DENOMINATOR_1 + NUM_CLOCKS
};

float phase;
long phase_longpart;
PolyGnome() : Module( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS )
{
phase = 0.0f;
phase_longpart = 274;
}

inline int numi( int i ) { return (int)params[ CLOCK_NUMERATOR_1 + i ].value; }
inline int deni( int i ) { return (int)params[ CLOCK_DENOMINATOR_1 + i ].value; }
void step() override
{
float clockTime = powf(2.0f, params[CLOCK_PARAM].value + inputs[CLOCK_INPUT].value);
phase += clockTime * engineGetSampleTime();

while( phase > 1 )
{
phase = phase - 1;
phase_longpart ++;
}


/* Alright we have to stop that longpart from getting too big otherwise it will swamp
the fractional parts but we have to reset it when all the clocks are firing at once
otherwise one of the clocks will stutter. So figure out the product of my fractions.
Probably we should use the common prime factors so we can get an earlier step
but lets leave it for now.
*/
int sd = 1;
int sn = 1;
for( int i=0; i<NUM_CLOCKS; ++i )
{
if( outputs[ CLOCK_GATE_0 + i + 1 ].active )
{
sd *= deni( i );
sn *= numi( i );
}
}
int commonp = sd * sn; // so we know at least that the clocks will intersect at this tick.


while( phase_longpart > commonp )
{
phase_longpart -= commonp;
}
for( int i=0; i<NUM_CLOCKS+1 ; ++i )
{
bool gateIn = false;
float frac;
if( i == 0 )
frac = 1;
else
frac = deni( i - 1 ) / ( 1.0f * numi( i - 1 ) );

// Note that we have two parts which comprise the phase number now, the float and the long.
// The addition can overflow, though which is why I mod the phase_longpart with a larger number
float lphase = phase * frac;
double liphase = phase_longpart * frac;

double ipart;
// I still worry a bit this + may overflow if you let this run long enough and blow out the precision in the decimal
float fractPhase = modf( lphase + liphase, &ipart );
gateIn = (fractPhase < 0.5f);

outputs[ CLOCK_GATE_0 + i ].value = gateIn ? 10.0f : 0.0f;
}
for( int i=0; i<NUM_CLOCKS; ++i )
{
lights[ LIGHT_NUMERATOR_1 + i ].value = (int)params[ CLOCK_NUMERATOR_1 + i ].value;
lights[ LIGHT_DENOMINATOR_1 + i ].value = (int)params[ CLOCK_DENOMINATOR_1 + i ].value;
}
}
};

struct PolyGnomeWidget : ModuleWidget {
PolyGnomeWidget( PolyGnome *module);
};

PolyGnomeWidget::PolyGnomeWidget( PolyGnome *module ) : ModuleWidget( module )
{
box.size = Vec( SCREW_WIDTH * 14, RACK_HEIGHT );

BaconBackground *bg = new BaconBackground( box.size, "PolyGnome" );
addChild( bg->wrappedInFramebuffer());

bg->addLabel( Vec( 17, 45 ), "Clock", 13, NVG_ALIGN_LEFT | NVG_ALIGN_TOP );
addParam( ParamWidget::create< RoundSmallBlackKnob >( Vec( 55, 40 ),
module,
PolyGnome::CLOCK_PARAM,
-2.0f, 6.0f, 2.0f ) );
addInput( Port::create< PJ301MPort >( Vec( 85, 40 ),
Port::INPUT,
module,
PolyGnome::CLOCK_INPUT ) );
for( size_t i=0; i<= NUM_CLOCKS; ++i )
{
Vec outP = Vec( box.size.x - 45, 100 + 48 * i );
if( i == 0 )
{
bg->addLabel( Vec( 17, outP.y + 21 ), "Unit (1/1) clock", 13, NVG_ALIGN_LEFT | NVG_ALIGN_BOTTOM );
}
else
{
int yoff = 2;
// knob light knob light
addParam( ParamWidget::create< RoundSmallBlackKnob >( Vec( 17, outP.y + yoff ),
module,
PolyGnome::CLOCK_NUMERATOR_1 + (i-1),
1, 30, 1 ) );
addChild( MultiDigitSevenSegmentLight< BlueLight, 2, 2 >::create( Vec( 48, outP.y + yoff ),
module,
PolyGnome::LIGHT_NUMERATOR_1 + (i-1) ) );

int mv = 47 + 20 + 14 - 16;
addParam( ParamWidget::create< RoundSmallBlackKnob >( Vec( 16 + mv, outP.y + yoff ),
module,
PolyGnome::CLOCK_DENOMINATOR_1 + (i-1),
1, 16, 1 ) );
addChild( MultiDigitSevenSegmentLight< BlueLight, 2, 2 >::create( Vec( 47 + mv, outP.y + yoff ),
module,
PolyGnome::LIGHT_DENOMINATOR_1 + (i-1) ) );
}
addOutput( Port::create< PJ301MPort >( outP,
Port::OUTPUT,
module,
PolyGnome::CLOCK_GATE_0 + i ) );
bg->addRoundedBorder( Vec( 12, outP.y - 4 ), Vec( box.size.x - 24, 36 ) );
}

}

} // namespace rack_plugin_BaconMusic

using namespace rack_plugin_BaconMusic;

RACK_PLUGIN_MODEL_INIT(BaconMusic, PolyGnome) {
Model *modelPolyGnome = Model::create<PolyGnome, PolyGnomeWidget>("Bacon Music", "PolyGnome", "PolyGnome", CLOCK_TAG );
return modelPolyGnome;
}


+ 193
- 0
plugins/community/repos/BaconMusic/src/QuantEyes.cpp View File

@@ -0,0 +1,193 @@
#include "BaconPlugs.hpp"
#include "dsp/digital.hpp"

#define SCALE_LENGTH 12

namespace rack_plugin_BaconMusic {

struct QuantEyes : virtual Module {
enum ParamIds {
ROOT_STEP,
SCALE_PARAM,
NUM_PARAMS = SCALE_PARAM + SCALE_LENGTH
};

enum InputIds {
CV_INPUT,
CV_INPUT_2,
CV_INPUT_3,
NUM_INPUTS
};

enum OutputIds {
QUANTIZED_OUT,
QUANTIZED_OUT_2,
QUANTIZED_OUT_3,
NUM_OUTPUTS
};

enum LightIds {
ROOT_LIGHT,
ACTIVE_NOTE_LIGHTS,
SCALE_LIGHTS = ACTIVE_NOTE_LIGHTS + 3 * SCALE_LENGTH,
NUM_LIGHTS = SCALE_LIGHTS + SCALE_LENGTH
};


int scaleState[ SCALE_LENGTH ];
SchmittTrigger scaleTriggers[ SCALE_LENGTH ];

QuantEyes() : Module( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS )
{
for( int i=0; i<SCALE_LENGTH; ++i ) scaleState[ i ] = 1;
}

void step() override
{
int root = clamp( params[ ROOT_STEP ].value, 0.0f, 12.0f );
lights[ ROOT_LIGHT ].value = root;

for( int i=0; i<SCALE_LENGTH; ++i )
{
if( scaleTriggers[ i ].process( params[ SCALE_PARAM + i ].value ) )
{
scaleState[ i ] = ! scaleState[ i ];
}
lights[ SCALE_LIGHTS + i ].value = scaleState[ i ];
lights[ ACTIVE_NOTE_LIGHTS + i ].value = 0;
lights[ ACTIVE_NOTE_LIGHTS + i + SCALE_LENGTH ].value = 0;
lights[ ACTIVE_NOTE_LIGHTS + i + SCALE_LENGTH * 2 ].value = 0;
}

for( int i=0; i<3; ++i )
{
if( inputs[ CV_INPUT + i ].active )
{
float in = inputs[ CV_INPUT + i ].value;
double octave, note;
note = modf( in, &octave );
float noteF = ( floor( note * SCALE_LENGTH ) + root );
int noteI = (int)noteF % SCALE_LENGTH;
if( noteF > SCALE_LENGTH-1 ) octave += 1.0;
while( scaleState[ noteI ] == 0 && noteI > 0 ) noteI --;
lights[ ACTIVE_NOTE_LIGHTS + i * SCALE_LENGTH + noteI ].value = 1;
float out = 1.0 * noteI / SCALE_LENGTH + octave;
outputs[ QUANTIZED_OUT + i ].value = out;
}
}
}

json_t *toJson() override {
json_t *rootJ = json_object();
json_t *scaleJ = json_array();
for( int i=0; i<SCALE_LENGTH; ++i )
{
json_t *noteJ = json_integer( scaleState[ i ] );
json_array_append_new( scaleJ, noteJ );
}
json_object_set_new( rootJ, "scaleState", scaleJ );

return rootJ;
}

void fromJson( json_t *rootJ ) override {
json_t* scaleJ = json_object_get( rootJ, "scaleState" );
if( scaleJ )
for( int i=0; i<SCALE_LENGTH; ++i )
{
json_t *noteJ = json_array_get( scaleJ, i );
if( noteJ )
scaleState[ i ] = json_integer_value( noteJ );
}
}
};

struct QuantEyesWidget : ModuleWidget {
QuantEyesWidget( QuantEyes *model );
};

QuantEyesWidget::QuantEyesWidget( QuantEyes *model ) : ModuleWidget( model )
{
box.size = Vec( SCREW_WIDTH * 11, RACK_HEIGHT );

BaconBackground *bg = new BaconBackground( box.size, "QuantEyes" );
addChild( bg->wrappedInFramebuffer());

int rx = 15, ry = 30, sp = 22, slope = 8;
for( int i=0; i<SCALE_LENGTH; ++i )
{
char d[ 24 ];
sprintf( d, "%d", i+1 );
if( i==0 ) d[ 0 ] = 'R';
int x0 = rx + (i + 0.5) * slope;
int yp0 = (SCALE_LENGTH - i - 1) * sp;
bg->addLabel( Vec( rx - 3, yp0 + ry + sp / 2), d, 12, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE );
addParam( ParamWidget::create< LEDButton >( Vec( x0, yp0 + ry ), module, QuantEyes::SCALE_PARAM + i, 0, 1, 0 ) );
addChild( ModuleLightWidget::create< MediumLight< BlueLight > >( Vec( x0 + 4, yp0 + ry + 4 ), module, QuantEyes::SCALE_LIGHTS + i ) );
addChild( ModuleLightWidget::create< SmallLight< GreenLight > >( Vec( x0 + 20, yp0 + ry + 6 ), module, QuantEyes::ACTIVE_NOTE_LIGHTS + i ) );
addChild( ModuleLightWidget::create< SmallLight< GreenLight > >( Vec( x0 + 28, yp0 + ry + 6 ), module, QuantEyes::ACTIVE_NOTE_LIGHTS + i + 12 ) );
addChild( ModuleLightWidget::create< SmallLight< GreenLight > >( Vec( x0 + 36, yp0 + ry + 6 ), module, QuantEyes::ACTIVE_NOTE_LIGHTS + i + 24 ) );

auto c = nvgRGBA( 225, 225, 225, 255 );
if( i == 1 || i == 3 || i == 6 || i == 8 || i == 10 )
c = nvgRGBA( 110, 110, 110, 255 );
bg->addFilledRect( Vec( rx , yp0 + ry + 7), Vec( i * slope + 39 , 4.5 ), c );
bg->addRect( Vec( rx , yp0 + ry + 7), Vec( i * slope + 39 , 4.5 ), nvgRGBA( 70, 70, 70, 255 ) );
}

int xpospl = box.size.x - 24 - 9;
Vec inP = Vec( xpospl - 32, RACK_HEIGHT - 60 );
Vec outP = Vec( xpospl, RACK_HEIGHT - 60 );
for( int i=0; i<3; ++i )
{
Vec off( 0, -55 * (2-i) );
char buf[ 20 ];
sprintf( buf, "in %d", i+1 );
bg->addPlugLabel( inP.plus(off), BaconBackground::SIG_IN, buf );
addInput( Port::create< PJ301MPort >( inP.plus(off), Port::INPUT,
module,
QuantEyes::CV_INPUT + i ) );

sprintf( buf, "out %d", i+1 );
bg->addPlugLabel( outP.plus(off), BaconBackground::SIG_OUT, buf );

addOutput( Port::create< PJ301MPort >( outP.plus(off), Port::OUTPUT,
module,
QuantEyes::QUANTIZED_OUT + i) );

}

bg->addRoundedBorder( Vec( 10, box.size.y - 78 ), Vec ( 70, 49 ) );
bg->addLabel( Vec( 45, box.size.y - 74 ), "Root CV", 12, NVG_ALIGN_CENTER | NVG_ALIGN_TOP );
int ybot = box.size.y - 78 + 24 + 5 + 20;
addParam( ParamWidget::create< RoundSmallBlackKnob >( Vec( 16, ybot - 3 - 28 ),
module,
QuantEyes::ROOT_STEP,
0, 12, 0 ) );
addChild( MultiDigitSevenSegmentLight< BlueLight, 2, 2 >::create( Vec( 47, ybot - 5 - 24 ),
module,
QuantEyes::ROOT_LIGHT ) );

}

} // namespace rack_plugin_BaconMusic

using namespace rack_plugin_BaconMusic;

RACK_PLUGIN_MODEL_INIT(BaconMusic, QuantEyes) {
Model *modelQuantEyes = Model::create< QuantEyes, QuantEyesWidget > ("Bacon Music", "QuantEyes", "QuantEyes", QUANTIZER_TAG);
return modelQuantEyes;
}

+ 60
- 0
plugins/community/repos/BaconMusic/src/SampleDelay.cpp View File

@@ -0,0 +1,60 @@

#include "BaconPlugs.hpp"
#include "SampleDelay.hpp"

namespace rack_plugin_BaconMusic {

struct SampleDelayWidget : ModuleWidget {
typedef SampleDelay< Module > SD;
SampleDelayWidget( SD *module);
};

SampleDelayWidget::SampleDelayWidget( SD *module ) : ModuleWidget( module )
{
box.size = Vec( SCREW_WIDTH * 5, RACK_HEIGHT );

BaconBackground *bg = new BaconBackground( box.size, "SampDelay" );
addChild( bg->wrappedInFramebuffer());

int outy = 30;
int gap = 10;
int margin = 3;

// plug label is 29 x 49
Vec ppos = Vec( bg->cx( SizeTable<PJ301MPort>::X ), outy + 20 );
bg->addPlugLabel( ppos, BaconBackground::SIG_IN, "in" );
addInput( Port::create< PJ301MPort >( ppos, Port::INPUT,
module, SD::SIGNAL_IN ) );

outy += 49 + gap + margin;
bg->addRoundedBorder( Vec( bg->cx() - 14 * 1.5 - margin, outy - margin ),
Vec( 14 * 3 + 2 * margin , 14 + SizeTable<RoundBlackSnapKnob>::Y + 2 * margin + 22 + margin + 2 * margin) );
bg->addLabel( Vec( bg->cx(), outy ), "# samples", 11, NVG_ALIGN_CENTER | NVG_ALIGN_TOP );
outy += 14;
addParam( ParamWidget::create< RoundBlackSnapKnob >( Vec( bg->cx( SizeTable< RoundBlackSnapKnob >::X ), outy ),
module,
SD::DELAY_KNOB,
1, 99, 1 ) );

outy += SizeTable<RoundBlackSnapKnob>::Y + 2 * margin;
addChild( MultiDigitSevenSegmentLight<BlueLight, 2, 3>::create( Vec( bg->cx() - 14 * 1.5, outy ),
module,
SD::DELAY_VALUE_LIGHT ) );
outy += 22 + gap + margin;

ppos = Vec( bg->cx( SizeTable<PJ301MPort>::X ), outy + 20 );
bg->addPlugLabel( ppos, BaconBackground::SIG_OUT, "out" );
addOutput( Port::create< PJ301MPort >( ppos, Port::OUTPUT,
module, SD::SIGNAL_OUT ) );

}

} // namespace rack_plugin_BaconMusic

using namespace rack_plugin_BaconMusic;

RACK_PLUGIN_MODEL_INIT(BaconMusic, SampleDelay) {
Model *modelSampleDelay = Model::create<SampleDelayWidget::SD, SampleDelayWidget>("Bacon Music", "SampleDelay", "SampleDelay", DELAY_TAG );
return modelSampleDelay;
}

+ 62
- 0
plugins/community/repos/BaconMusic/src/SampleDelay.hpp View File

@@ -0,0 +1,62 @@

#include <vector>
#include <algorithm>

namespace rack_plugin_BaconMusic {

template< typename TBase >
struct SampleDelay : virtual TBase {
enum ParamIds {
DELAY_KNOB,
NUM_PARAMS
};

enum InputIds {
SIGNAL_IN,
NUM_INPUTS
};

enum OutputIds {
SIGNAL_OUT,
NUM_OUTPUTS
};

enum LightIds {
DELAY_VALUE_LIGHT,
NUM_LIGHTS
};

using TBase::params;
using TBase::inputs;
using TBase::outputs;
using TBase::lights;

std::vector< float > ring;
size_t ringSize;
size_t pos;
SampleDelay() : TBase( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS )
{
params[ DELAY_KNOB ].value = 1;
ringSize = 100;
ring.resize( ringSize );
std::fill( ring.begin(), ring.end(), 0 );
pos = 0;
}

void step() override
{
int del = params[ DELAY_KNOB ].value - 1;
int dpos = ( (int)pos - del );
if( dpos < 0 ) dpos += ringSize;

ring[ pos ] = inputs[ SIGNAL_IN ].value;
outputs[ SIGNAL_OUT ].value = ring[ dpos ];
lights[ DELAY_VALUE_LIGHT ].value = del + 1;

pos++;
if( pos >= ringSize ) pos = 0;
}
};

} // namespace rack_plugin_BaconMusic

+ 67
- 0
plugins/community/repos/BaconMusic/src/SizeTable.hpp View File

@@ -0,0 +1,67 @@
#ifndef INCLUDE_SIZE_TABLE
#define INCLUDE_SIZE_TABLE


// Wish there was a better way to do this
template< typename T >
struct SizeTable
{
};

template<>
struct SizeTable< PJ301MPort >
{
constexpr static const float X = 24.6721;
constexpr static const float Y = 24.6721;
};

template<>
struct SizeTable< RoundHugeBlackKnob >
{
constexpr static const float X = 56.1034;
constexpr static const float Y = 56.1034;
};

template<>
struct SizeTable< RoundLargeBlackKnob >
{
constexpr static const float X = 37.5;
constexpr static const float Y = 37.5;
};

template<>
struct SizeTable< RoundBlackSnapKnob >
{
constexpr static const float X = 29.5287;
constexpr static const float Y = 29.5287;
};

template<>
struct SizeTable< RoundBlackKnob >
{
constexpr static const float X = 29.5287;
constexpr static const float Y = 29.5287;
};

template<>
struct SizeTable< DotMatrixLightTextWidget >
{
constexpr static const float X = 11;
constexpr static const float Y = 18.5;
};

template<>
struct SizeTable< RoundSmallBlackKnob >
{
constexpr static const float X = 23.6206;
constexpr static const float Y = 23.6206;
};

// Diff Y to center
template< typename T1, typename T2 >
float diffY2c()
{
return ( SizeTable<T1>::Y - SizeTable<T2>::Y ) / 2;
}

#endif

+ 141
- 0
plugins/community/repos/BaconMusic/src/SortaChorus.cpp View File

@@ -0,0 +1,141 @@

#ifdef BUILD_SORTACHORUS

#include "BaconPlugs.hpp"
#include <algorithm>
#include <cmath>
#include <iostream>

namespace rack_plugin_BaconMusic {

struct SortaChorus : virtual Module {
private:
// Borrowing from RingBuffer which this sort of is, S must be a power of 2
template <typename T, size_t S>
struct ChorusBuffer
{
T data[ S ];
size_t SZ = S;
size_t currp = 0;
ChorusBuffer()
{
std::fill( data, data + S, 0 );
}

size_t mask(size_t i) const {
return i & (S - 1);
}
void push( T t )
{
size_t i = mask( currp++ );
data[ i ] = t;
}

// todo interpolate since this will sound like poop
T readBack( size_t off )
{
size_t pos = ( currp + ( S - 1 ) - off ) & ( S - 1 );
return data[ pos ];
}
};

ChorusBuffer< float, 16384 > buf;
float tNow;
public:
enum ParamIds {
DEPTH,
SPEED,
SHAPE,
NOISE,
NUM_PARAMS
};

enum InputIds {
SIGNAL_INPUT,
NUM_INPUTS
};

enum OutputIds {
CHORUSED_OUTPUT,
NUM_OUTPUTS
};

enum LightIds {
NUM_LIGHTS
};

SortaChorus() : Module( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS )
{
tNow = 0;
}

void step() override
{
buf.push( inputs[ SIGNAL_INPUT ].value );

// crude for now - basically a saw.
tNow += engineGetSampleTime();
float intpart;
float fractpart = modf( tNow, &intpart );
if( (int)intpart % 2 == 0 ) fractpart = 1.0 - fractpart;
float chSig = buf.readBack( (size_t)( fractpart * buf.SZ / 20 ) );

float depth = params[ DEPTH ].value;
outputs[ CHORUSED_OUTPUT ].value = ( inputs[ SIGNAL_INPUT ].value + depth * chSig ) / ( 1.0 + depth );
}
};

struct SortaChorusWidget : ModuleWidget {
SortaChorusWidget( SortaChorus *module);
};

SortaChorusWidget::SortaChorusWidget( SortaChorus *module ) : ModuleWidget( module )
{
box.size = Vec( SCREW_WIDTH * 10, RACK_HEIGHT );

BaconBackground *bg = new BaconBackground( box.size, "SortaChorus" );
addChild( bg->wrappedInFramebuffer());

Vec wdPos( 40, 40 ), knobPos;
bg->addLabelsForLargeKnob( wdPos, "Depth", "None", "Lots", knobPos );
addParam( ParamWidget::create< RoundLargeBlackKnob >( knobPos, module,
SortaChorus::DEPTH,
0, 2.0, 0.5 ) );

wdPos.x = box.size.x - 40;
bg->addLabelsForLargeKnob( wdPos, "Speed", "Slow", "Fast", knobPos );
addParam( ParamWidget::create< RoundLargeBlackKnob >( knobPos, module,
SortaChorus::SPEED,
0, 1.0, 0.5 ) );

Vec inP = Vec( bg->cx( 24 ) - 30, RACK_HEIGHT - 15 - 43 );
bg->addPlugLabel( inP, BaconBackground::SIG_IN, "in" );
addInput( Port::create< PJ301MPort >( inP,
Port::INPUT,
module,
SortaChorus::SIGNAL_INPUT ) );

Vec outP = Vec( bg->cx( 24 ) + 30, RACK_HEIGHT - 15 - 43 );
bg->addPlugLabel( outP, BaconBackground::SIG_OUT, "out" );
addOutput( Port::create< PJ301MPort >( outP,
Port::OUTPUT,
module,
SortaChorus::CHORUSED_OUTPUT ) );
}

} // namespace rack_plugin_BaconMusic

using namespace rack_plugin_BaconMusic;

RACK_PLUGIN_MODEL_INIT(BaconMusic, SortaChorus) {
Model *modelSortaChorus = Model::create<SortaChorus, SortaChorusWidget>("Bacon Music", "SortaChorus", "SortaChorus", CHORUS_TAG );
return modelSortaChorus;
}

#endif

+ 128
- 0
plugins/community/repos/BaconMusic/standalone/GlissinatorTest.cpp View File

@@ -0,0 +1,128 @@
#include "standalone_helpers.hpp"
#include "../src/Glissinator.hpp"
#include <iostream>

int main( int argch, char **argv )
{
std::cout << "Test Glissinator\n";
typedef Glissinator< StandaloneModule > G;

for( int io = 0; io <= 1; ++io )
{
G g;
g.params[ G::GLISS_TIME ].value = 0.1;
g.inputs[ G::SOURCE_INPUT ].value = 1.00 + io;
g.inputs[ G::SOURCE_INPUT ].active = true;
g.outputs[ G::SLID_OUTPUT ].active = true;
G::results_t ov;
g.multiStep( 100, ov );
g.inputs[ G::SOURCE_INPUT ].value = 2.00 - io;
g.multiStep( engineGetSampleRate() * 0.15, ov );

// So this should be monotonically increasing.
auto hd = ov.begin() + 1, pv = ov.begin();
while( hd != ov.end() )
{
if( io == 0 )
assert( (*hd)[ G::SLID_OUTPUT ].value >= (*pv)[ G::SLID_OUTPUT ].value );
else
assert( (*hd)[ G::SLID_OUTPUT ].value <= (*pv)[ G::SLID_OUTPUT ].value );
assert( (*hd)[ G::SLID_OUTPUT ].value >= 1 );
assert( (*hd)[ G::SLID_OUTPUT ].value <= 2 );
++hd;
++pv;
}
std::cout << "PASSED: Simple case is monotonic " << 1 + io << " -> " << 2 - io << "\n";
}

// The turnadound-half-way-through test
for( int io = 0; io <= 1; ++io )
{
G g;
g.params[ G::GLISS_TIME ].value = 0.1;
g.inputs[ G::SOURCE_INPUT ].value = 1.00 + io;
g.inputs[ G::SOURCE_INPUT ].active = true;
g.outputs[ G::SLID_OUTPUT ].active = true;
G::results_t ov;
g.multiStep( 100, ov );
g.inputs[ G::SOURCE_INPUT ].value = 2.00 - io;
g.multiStep( engineGetSampleRate() * 0.07, ov );

float maxO = g.outputs[ G::SLID_OUTPUT ].value;
g.inputs[ G::SOURCE_INPUT ].value = 1.00 + io;
g.multiStep( engineGetSampleRate() * 0.07, ov );
// So this should no longer be monotonic strictly but should monotone up to max
// and then down from
bool goingUp = (io == 0)?true:false;
bool hitMax = false;
auto hd = ov.begin() + 1, pv = ov.begin();
while( hd != ov.end() )
{
if( goingUp )
assert( (*hd)[ G::SLID_OUTPUT ].value >= (*pv)[ G::SLID_OUTPUT ].value );
else
assert( (*hd)[ G::SLID_OUTPUT ].value <= (*pv)[ G::SLID_OUTPUT ].value );

if( io == 0 )
{
assert( (*hd)[ G::SLID_OUTPUT ].value >= 1 );
assert( (*hd)[ G::SLID_OUTPUT ].value <= maxO );
}
else
{
assert( (*hd)[ G::SLID_OUTPUT ].value <= 2 );
assert( (*hd)[ G::SLID_OUTPUT ].value >= maxO );
}

if( (*hd)[G::SLID_OUTPUT].value == maxO && ! hitMax ) { goingUp = ! goingUp; hitMax = true; } // max can repeat
++hd;
++pv;
}
std::cout << "PASSED: Turnaround case is bi-monotonic " << 1 + io << " -> " << 2 - io << "\n";
}

{
G g;
// OK so now lets test that gliss time bug. If we reset the gliss time most of the way through
// a gliss, the 0.6.1 version runs away.
g.params[ G::GLISS_TIME ].value = 0.1;
g.inputs[ G::SOURCE_INPUT ].value = 1.00;
g.inputs[ G::SOURCE_INPUT ].active = true;
g.outputs[ G::SLID_OUTPUT ].active = true;

G::results_t ov;
g.multiStep( 100, ov );
g.inputs[ G::SOURCE_INPUT ].value = 2.00 ;
g.multiStep( engineGetSampleRate() * 0.07, ov );

g.params[ G::GLISS_TIME ].value = 0;

g.multiStep( 1, ov );
auto hd = ov.begin() + 1, pv = ov.begin();
while( hd != ov.end() )
{
assert( (*hd)[ G::SLID_OUTPUT ].value >= (*pv)[ G::SLID_OUTPUT ].value );
assert( (*hd)[ G::SLID_OUTPUT ].value >= 1 );
assert( (*hd)[ G::SLID_OUTPUT ].value <= 2 );
++hd;
++pv;
}
std::cout << "PASSED: Jump case is still monotonic and bounded\n";
}

}

+ 21
- 0
plugins/community/repos/BaconMusic/standalone/Makefile View File

@@ -0,0 +1,21 @@
# SUPER crude makefiles for my standalone tests.
# Basically use it as
# make run T=docsaw
# and that will build docsaw.cpp which depends on every header everywhere and voila.

HDRS = $(wildcard ../src/*.hpp) $(wildcard *.hpp)

CPPEXE = c++ -I../../../dep/include -L../../../dep/lib -lrtaudio -std=c++11 -stdlib=libc++ -Werror
RUN_PREFIX = DYLD_LIBRARY_PATH=../../../dep/lib

exe_%: %.cpp $(HDRS)
$(CPPEXE) -o $@ $<

run: exe_$(T)
$(RUN_PREFIX) ./$<

clean:
rm -f exe*




+ 27
- 0
plugins/community/repos/BaconMusic/standalone/SampleDelayTest.cpp View File

@@ -0,0 +1,27 @@
#include "standalone_helpers.hpp"
#include "../src/SampleDelay.hpp"
#include <iostream>

int main( int argc, char **argv )
{
typedef SampleDelay< StandaloneModule > SD;

{
SD sd;
int dk = 37;
sd.params[ SD::DELAY_KNOB ].value = dk;
sd.inputs[ SD::SIGNAL_IN ].active = 1;

SD::results_t ov;
int ns = 1000;
for( int i=0; i<ns; ++i )
{
sd.inputs[ SD::SIGNAL_IN ].value = i * 1.0f / ns;
sd.step();
ov.push_back( sd.outputs );
}
for( int i=dk; i<ns; ++i )
std::cout << i << " " << ov[ i-1 ][ SD::SIGNAL_OUT ].value << " " << 1.0f * (i-dk)/ ns << "\n";
}
}

+ 116
- 0
plugins/community/repos/BaconMusic/standalone/chipNoisePeriod.cpp View File

@@ -0,0 +1,116 @@
#include "../src/ChipSym.hpp"
#include <iostream>
#include <iomanip>
#include <map>
#include <set>
#include <cassert>

int main( int argc, char ** argv )
{
std::cout << "Testing chip periods" << std::endl;
ChipSym::NESNoise noise( 0.0f, 1.0f, 44100 );
noise.setPeriod( 2 );
noise.setModeFlag( true );

for( int i=0; i<5; ++i )
{
// So lets start by testing if 31 gives us 31 and 93 gives us 93
int ct = 0;
noise.setShortLength( ChipSym::NESNoise::SHORT_31 );
unsigned short target = noise.getRegister();
do { ct ++; noise.advanceRegister(); } while( noise.getRegister() != target );
assert( ct == 31 );

noise.setShortLength( ChipSym::NESNoise::SHORT_93 );
target = noise.getRegister();
ct = 0;
do { ct ++; noise.advanceRegister(); } while( noise.getRegister() != target && ct < 100 );
assert( ct == 93 );
}
std::map< int, std::pair< unsigned short, int > > resultMap;
std::map< unsigned short, int > sequenceMap;
int sequenceID = 0;

for( unsigned short iRegister=1; iRegister < 0x7FFF; iRegister ++ )
{
bool newSeq = false;
noise.setRegister( iRegister );
// step off my initial point into the sequence
while( noise.getRegister() == iRegister ) noise.advanceRegister();
unsigned short target = noise.getRegister();
bool gotR = false;
int stepC = 0;
if( sequenceMap.find( noise.getRegister() ) == sequenceMap.end() ) {
sequenceID ++;
newSeq = true;
}
while( ! gotR )
{
++stepC;
if( newSeq )
sequenceMap[ noise.getRegister() ] = sequenceID;
noise.advanceRegister();
if( noise.getRegister() == target )
{
if( resultMap.find( stepC ) == resultMap.end() )
{
resultMap[ stepC ] = std::pair< unsigned short, int >( target, 1 );
}
else
resultMap[ stepC ].second ++;
gotR = true;
}
}
}

std::cout << "Unique sequence count is " << sequenceID << " " << sequenceMap.size() << "\n";

// Invert sequenceMap
std::map< int, std::set< unsigned short > > inverseSequenceMap;
for( auto smapKey = sequenceMap.begin(); smapKey != sequenceMap.end(); ++smapKey )
{
inverseSequenceMap[ smapKey->second ].insert( smapKey->first );
}

std::map< int, int > lenMap;
lenMap[ 93 ] = 0;
lenMap[ 31 ] = 0;
for( auto imapKey = inverseSequenceMap.begin(); imapKey != inverseSequenceMap.end(); ++imapKey )
{
lenMap[ imapKey->second.size() ] ++;
}

std::cout << "Count[ 93 ] = " << lenMap[ 93 ] << "\nCount[ 31 ] = " << lenMap[ 31 ] << "\n";
for( auto imapKey = inverseSequenceMap.begin(); imapKey != inverseSequenceMap.end(); ++imapKey )
{
std::cout << "Seq: " << std::setw( 4 ) << std::setfill( ' ' ) << std::setbase( 10 ) << imapKey->first << " Len = " << imapKey->second.size() << " ";
int ct = 0;
for( auto secKey = imapKey->second.begin(); secKey != imapKey->second.end() && ct < 8; ++secKey, ++ct )
{
std::cout << " 0x" << std::setw( 4 ) << std::setbase( 16 ) << std::setfill( '0' ) << *secKey;
}
std::cout << "\n";
}

// Finally dump the c structure
std::cout << "unsigned short start_for_93s[] = {\n ";
int ct = 0;
for( auto imapKey = inverseSequenceMap.begin(); imapKey != inverseSequenceMap.end(); ++imapKey, ++ct )
{
if( imapKey->second.size() == 93 )
std::cout << std::setbase( 10 ) << *( imapKey->second.begin() ) << ", ";
if( (ct+1) % 15 == 0 )
std::cout << "\n ";
}
std::cout << " 0 };\n";
}

+ 87
- 0
plugins/community/repos/BaconMusic/standalone/chipTester.cpp View File

@@ -0,0 +1,87 @@
#include "../src/ChipSym.hpp"
#include "standalone_helpers.hpp"

template <typename T>
struct NESGen : StepHandler
{
T ngen;
NESGen() : ngen( -0.2, 0.2, 44100 ) {}

virtual int dostep( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status ) override
{
unsigned int i, j;
double *buffer = (double *) outputBuffer;

for ( i=0; i<nBufferFrames; i++ ) {
*buffer++ = ngen.step();
}
return 0;
}
};

int main( int argc, char** argv )
{
ChipSym::CPUStepper cp( 44100, 1.789773 );

std::cout << "Do some NES CPU Tick pulls at 44.1k\n";
for( uint i=0; i<5; ++i )
{
std::cout << i * 10 << "\t";
for( uint j=0; j<10; ++j )
{
std::cout << cp.nextStepCPUTicks() << " ";
}
std::cout << "\n";
}


#if 0
std::cout << "Running the NES tri gen\n";
NESGen< ChipSym::NESTriangle > triGen;
int df = 2<<8;
triGen.ngen.setDigWavelength( df );
triGen.playAudioUntilEnterPressed();

triGen.ngen.setDigWavelength( df / 2 );
triGen.playAudioUntilEnterPressed();

NESGen< ChipSym::NESPulse > pulsGen;
df = 2<<9;
pulsGen.ngen.setDigWavelength( df );
pulsGen.playAudioUntilEnterPressed();

pulsGen.ngen.setDigWavelength( df / 2 );
pulsGen.playAudioUntilEnterPressed();
NESGen< ChipSym::NESNoise > noiseGen;
noiseGen.playAudioUntilEnterPressed();

noiseGen.ngen.setModeFlag( true );
noiseGen.playAudioUntilEnterPressed();

noiseGen.ngen.setModeFlag( false );
noiseGen.ngen.setPeriod( 3 );
noiseGen.playAudioUntilEnterPressed();


noiseGen.ngen.setModeFlag( false );
noiseGen.ngen.setPeriod( 11 );
noiseGen.playAudioUntilEnterPressed();
#endif

NESGen< ChipSym::NESArbitraryWaveform > arbGen;
int df = 2<<7;
arbGen.ngen.setDigWavelength( df );
arbGen.playAudioUntilEnterPressed();

for( uint i=0; i<32; ++i )
{
arbGen.ngen.setWaveformPoint( i, 7 * ( sin ( 2 * 3.14159 * i / 32 ) + 1 ) );
}
arbGen.playAudioUntilEnterPressed();

return 0;
}

+ 34
- 0
plugins/community/repos/BaconMusic/standalone/docsaw.cpp View File

@@ -0,0 +1,34 @@
/*
** Just showing how to use the standalone helpers to make a mono generator which gets
** punped to default output quickly and easily
*/

#include "standalone_helpers.hpp"
#include <iostream>
#include <cstdlib>

struct SawGen : StepHandler
{
double lastValue;
SawGen() : lastValue( 0 ) {}

virtual int dostep( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status ) override
{
unsigned int i, j;
double *buffer = (double *) outputBuffer;

for ( i=0; i<nBufferFrames; i++ ) {
*buffer++ = lastValue;
lastValue += 0.015;
if ( lastValue >= 1.0 ) lastValue -= 2.0;
}
return 0;
}
};

int main()
{
SawGen sg;
sg.playAudioUntilEnterPressed();
}

+ 44
- 0
plugins/community/repos/BaconMusic/standalone/kssynthDemo.cpp View File

@@ -0,0 +1,44 @@
#include "../src/KSSynth.hpp"
#include "standalone_helpers.hpp"

#include <iostream>

struct KSGen : StepHandler
{
KSSynth s;
KSGen() : s( -0.9, 0.9, 44100 ) { }

virtual int dostep( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status ) override
{
unsigned int i, j;
double *buffer = (double *) outputBuffer;

for ( i=0; i<nBufferFrames; i++ ) {
*buffer++ = s.step();
}
if( ! s.active )
return 1;
return 0;
}
};

int main( int argc, char **argv )
{
KSGen gen;
std::cout << "packets " << gen.s.numInitPackets() << "\n";

gen.s.filtAtten = 3.0;
gen.s.filtParamA = 0.3;
gen.s.packet = KSSynth::RANDOM;
float freq = 440;
for( int i=0; i<=12; ++i )
{
float mul = pow( 2.0, i / 12.0f );
gen.s.trigger( freq * mul );
gen.playAudioUntilStepsDone();
}
}

+ 123
- 0
plugins/community/repos/BaconMusic/standalone/standalone_helpers.hpp View File

@@ -0,0 +1,123 @@

#include "RtAudio.h"
#include <unistd.h>

int engineGetSampleRate() { return 44100; }

struct StepHandler
{
virtual ~StepHandler() { };
virtual int dostep( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status ) = 0;

static int step( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status, void* userData )
{
StepHandler *sh = (StepHandler *)userData;
return sh->dostep( outputBuffer, inputBuffer, nBufferFrames, streamTime, status );
}

RtAudio startDac()
{
RtAudio dac;
if ( dac.getDeviceCount() < 1 ) {
std::cout << "\nNo audio devices found!\n";
exit( 0 );
}
RtAudio::StreamParameters parameters;
parameters.deviceId = dac.getDefaultOutputDevice();
parameters.nChannels = 1;
parameters.firstChannel = 0;
unsigned int sampleRate = 44100;
unsigned int bufferFrames = 256; // 256 sample frames

try {
dac.openStream( &parameters, NULL, RTAUDIO_FLOAT64,
sampleRate, &bufferFrames, &StepHandler::step, (void *)this );
dac.startStream();
}
catch ( RtAudioError& e ) {
e.printMessage();
exit( 0 );
}
return dac;
}

void stopDac( RtAudio dac )
{
try {
// Stop the stream
dac.stopStream();
}
catch (RtAudioError& e) {
e.printMessage();
}
if ( dac.isStreamOpen() ) dac.closeStream();
}

int playAudioUntilStepsDone()
{
RtAudio dac = startDac();
while( dac.isStreamRunning() )
{
usleep( 100 );
}

if ( dac.isStreamOpen() ) dac.closeStream();

return 0;
}
int playAudioUntilEnterPressed()
{
RtAudio dac = startDac();
char input;
std::cout << "\nPlaying ... press <enter> to quit.\n";
std::cin.get( input );

stopDac( dac );
return 0;
}
};

struct StandaloneModule
{
struct thing
{
float value;
bool active;
};

typedef std::vector< thing > values_t;
typedef std::vector< values_t > results_t;

void multiStep( size_t stepCount, results_t &into )
{
for( size_t i=0; i<stepCount; ++i )
{
step();
into.push_back( outputs );
}
}
values_t params;
values_t lights;
values_t inputs;
values_t outputs;

StandaloneModule( int nparam, int ninp, int nout, int nlight )
{
params.resize( nparam );
lights.resize( nlight );
inputs.resize( ninp );
outputs.resize( nout );
}

virtual void step() { };
};

+ 4
- 0
plugins/makefile.msvc View File

@@ -11,8 +11,10 @@ endef
.PHONY:
bin:
# $(foreach pname,$(PLUGINS),$(eval ($(call run_make,$(pname),bin))))
$(call run_make,Alikins,bin)
$(call run_make,AS,bin)
$(call run_make,AudibleInstruments,bin)
$(call run_make,BaconMusic,bin)
$(call run_make,Befaco,bin)
$(call run_make,Bidoo,bin)
$(call run_make,Bogaudio,bin)
@@ -47,8 +49,10 @@ bin:
clean:
# $(foreach pname,$(PLUGINS),$(eval $(call run_make,$(pname),clean)))
# $(foreach pname,$(PLUGINS),$(eval echo $(pname)))
$(call run_make,Alikins,clean)
$(call run_make,AS,clean)
$(call run_make,AudibleInstruments,clean)
$(call run_make,BaconMusic,clean)
$(call run_make,Befaco,clean)
$(call run_make,Bidoo,clean)
$(call run_make,Bogaudio,clean)


+ 4
- 0
src/plugin.cpp View File

@@ -568,8 +568,10 @@ Model *pluginGetModel(std::string pluginSlug, std::string modelSlug) {

#ifdef USE_VST2
extern "C" {
extern void init_plugin_Alikins (rack::Plugin *p);
extern void init_plugin_AS (rack::Plugin *p);
extern void init_plugin_AudibleInstruments (rack::Plugin *p);
extern void init_plugin_BaconMusic (rack::Plugin *p);
extern void init_plugin_Befaco (rack::Plugin *p);
extern void init_plugin_Bidoo (rack::Plugin *p);
extern void init_plugin_Bogaudio (rack::Plugin *p);
@@ -628,8 +630,10 @@ static void vst2_load_static_rack_plugin(const char *_name, InitCallback _initCa
}

void vst2_load_static_rack_plugins(void) {
vst2_load_static_rack_plugin("Alikins", &init_plugin_Alikins);
vst2_load_static_rack_plugin("AS", &init_plugin_AS);
vst2_load_static_rack_plugin("AudibleInstruments", &init_plugin_AudibleInstruments);
vst2_load_static_rack_plugin("BaconMusic", &init_plugin_BaconMusic);
vst2_load_static_rack_plugin("Befaco", &init_plugin_Befaco);
vst2_load_static_rack_plugin("Bidoo", &init_plugin_Bidoo);
vst2_load_static_rack_plugin("Bogaudio", &init_plugin_Bogaudio);


+ 20
- 0
vst2_bin/CHANGELOG_VST.txt View File

@@ -1,3 +1,23 @@
** July 9th, 2018
- add module Alikins.IdleSwitch
- add module Alikins.MomentaryOnButtons
- add module Alikins.BigMuteButton
- add module Alikins.ColorPanel
- add module Alikins.GateLength
- add module Alikins.SpecificValue
- add module BaconMusic.Glissinator
- add module BaconMusic.PolyGnome
- add module BaconMusic.QuantEyes
- add module BaconMusic.SampleDelay
- add module BaconMusic.SortaChorus
- add module BaconMusic.ChipNoise
- add module BaconMusic.ChipWaves
- add module BaconMusic.ChipYourWave
- add module BaconMusic.KarplusStrongPoly
- add module BaconMusic.ALingADing
- add module BaconMusic.Bitulator


** July 8th, 2018
- add module DHE-Modules.BoosterStage
- add module DHE-Modules.Cubic


+ 19
- 1
vst2_bin/README_vst2.txt View File

@@ -1,4 +1,4 @@
VeeSeeVST Rack VST 2.4 Plugin -- July 2nd, 2018
VeeSeeVST Rack VST 2.4 Plugin -- July 9th, 2018
===============================================

!!!------------------------------------------------------------------------------
@@ -15,6 +15,7 @@ This is a quick'n'dirty adaption of VCV Rack 0.6.1 for the VST2 format.
+ supports up to 8 audio inputs
+ supports VST program chunks (=> patches are saved with the DAW's project file or as .fxp files)
+ supports VST host timing (audioMasterGetTime / kVstTempoValid / kVstTransportPlaying, see Core.MIDI-1 module)
+ supports VST parameters (send / recv)
- does not support plugin DLLs due to VCV Rack's architecture which prevents this when it is run as a plugin itself
- future releases will contain additional (open source) add-ons modules

@@ -26,6 +27,12 @@ Tested in
- Propellerhead Reason 10

The VST2 plugin includes the following add-on modules:
- Alikins.IdleSwitch
- Alikins.MomentaryOnButtons
- Alikins.BigMuteButton
- Alikins.ColorPanel
- Alikins.GateLength
- Alikins.SpecificValue
- AS.ADSR
- AS.AtNuVrTr
- AS.BPMCalc
@@ -75,6 +82,17 @@ The VST2 plugin includes the following add-on modules:
- AudibleInstruments.Blinds
- AudibleInstruments.Veils
- AudibleInstruments.Frames
- BaconMusic.Glissinator
- BaconMusic.PolyGnome
- BaconMusic.QuantEyes
- BaconMusic.SampleDelay
- BaconMusic.SortaChorus
- BaconMusic.ChipNoise
- BaconMusic.ChipWaves
- BaconMusic.ChipYourWave
- BaconMusic.KarplusStrongPoly
- BaconMusic.ALingADing
- BaconMusic.Bitulator
- Befaco.ABC
- Befaco.DualAtenuverter
- Befaco.EvenVCO


+ 64
- 62
vst2_bin/log.txt View File

@@ -1,69 +1,71 @@
[0.000 info src/main.cpp:63] VeeSeeVST Rack 0.6.1
[0.000 info src/main.cpp:66] Global directory: f:\git\VeeSeeVSTRack\vst2_bin\/
[0.000 info src/main.cpp:67] Local directory: f:\git\VeeSeeVSTRack\vst2_bin\/
[0.000 info src/plugin.cpp:627] vcvrack: Loaded static plugin AS 0.6.1
[0.000 info src/plugin.cpp:627] vcvrack: Loaded static plugin AudibleInstruments 0.6.1
[0.001 info src/plugin.cpp:627] vcvrack: Loaded static plugin Befaco 0.6.1
[0.002 info src/plugin.cpp:627] vcvrack: Loaded static plugin Bidoo 0.6.1
[0.002 info src/plugin.cpp:627] vcvrack: Loaded static plugin Bogaudio 0.6.1
[0.002 info src/plugin.cpp:627] vcvrack: Loaded static plugin cf 0.6.1
[0.002 info src/plugin.cpp:627] vcvrack: Loaded static plugin DHE-Modules 0.6.1
[0.003 info src/plugin.cpp:627] vcvrack: Loaded static plugin ErraticInstruments 0.6.1
[0.003 info src/plugin.cpp:627] vcvrack: Loaded static plugin ESeries 0.6.1
[0.003 info src/plugin.cpp:627] vcvrack: Loaded static plugin FrozenWasteland 0.6.1
[0.003 info src/plugin.cpp:627] vcvrack: Loaded static plugin Fundamental 0.6.1
[0.003 info src/plugin.cpp:627] vcvrack: Loaded static plugin HetrickCV 0.6.1
[0.003 info src/plugin.cpp:627] vcvrack: Loaded static plugin huaba 0.6.1
[0.004 info src/plugin.cpp:627] vcvrack: Loaded static plugin Koralfx-Modules 0.6.1
[0.004 info src/plugin.cpp:627] vcvrack: Loaded static plugin LindenbergResearch 0.6.1
[0.005 info src/plugin.cpp:627] vcvrack: Loaded static plugin LOGinstruments 0.6.1
[0.005 info src/plugin.cpp:627] vcvrack: Loaded static plugin ML_modules 0.6.1
[0.005 info src/plugin.cpp:627] vcvrack: Loaded static plugin modular80 0.6.1
[0.005 info src/plugin.cpp:627] vcvrack: Loaded static plugin mscHack 0.6.1
[0.005 info src/plugin.cpp:627] vcvrack: Loaded static plugin mtsch-plugins 0.6.1
[0.005 info src/plugin.cpp:627] vcvrack: Loaded static plugin NauModular 0.6.1
[0.006 info src/plugin.cpp:627] vcvrack: Loaded static plugin Qwelk 0.6.1
[0.006 info src/plugin.cpp:627] vcvrack: Loaded static plugin SonusModular 0.6.1
[0.006 info src/plugin.cpp:627] vcvrack: Loaded static plugin Southpole-parasites 0.6.1
[0.006 info src/plugin.cpp:627] vcvrack: Loaded static plugin squinkylabs-plug1 0.6.1
[0.006 info src/plugin.cpp:627] vcvrack: Loaded static plugin SubmarineFree 0.6.1
[0.006 info src/plugin.cpp:627] vcvrack: Loaded static plugin Template 0.6.1
[0.007 info src/plugin.cpp:627] vcvrack: Loaded static plugin trowaSoft 0.6.1
[0.007 info src/plugin.cpp:627] vcvrack: Loaded static plugin Valley 0.6.1
[0.007 info src/plugin.cpp:627] vcvrack: Loaded static plugin VultModules 0.6.1
[0.000 info src/plugin.cpp:629] vcvrack: Loaded static plugin Alikins 0.6.1
[0.000 info src/plugin.cpp:629] vcvrack: Loaded static plugin AS 0.6.1
[0.001 info src/plugin.cpp:629] vcvrack: Loaded static plugin AudibleInstruments 0.6.1
[0.001 info src/plugin.cpp:629] vcvrack: Loaded static plugin BaconMusic 0.6.1
[0.002 info src/plugin.cpp:629] vcvrack: Loaded static plugin Befaco 0.6.1
[0.002 info src/plugin.cpp:629] vcvrack: Loaded static plugin Bidoo 0.6.1
[0.002 info src/plugin.cpp:629] vcvrack: Loaded static plugin Bogaudio 0.6.1
[0.003 info src/plugin.cpp:629] vcvrack: Loaded static plugin cf 0.6.1
[0.003 info src/plugin.cpp:629] vcvrack: Loaded static plugin DHE-Modules 0.6.1
[0.003 info src/plugin.cpp:629] vcvrack: Loaded static plugin ErraticInstruments 0.6.1
[0.003 info src/plugin.cpp:629] vcvrack: Loaded static plugin ESeries 0.6.1
[0.003 info src/plugin.cpp:629] vcvrack: Loaded static plugin FrozenWasteland 0.6.1
[0.003 info src/plugin.cpp:629] vcvrack: Loaded static plugin Fundamental 0.6.1
[0.004 info src/plugin.cpp:629] vcvrack: Loaded static plugin HetrickCV 0.6.1
[0.004 info src/plugin.cpp:629] vcvrack: Loaded static plugin huaba 0.6.1
[0.004 info src/plugin.cpp:629] vcvrack: Loaded static plugin Koralfx-Modules 0.6.1
[0.004 info src/plugin.cpp:629] vcvrack: Loaded static plugin LindenbergResearch 0.6.1
[0.004 info src/plugin.cpp:629] vcvrack: Loaded static plugin LOGinstruments 0.6.1
[0.004 info src/plugin.cpp:629] vcvrack: Loaded static plugin ML_modules 0.6.1
[0.004 info src/plugin.cpp:629] vcvrack: Loaded static plugin modular80 0.6.1
[0.005 info src/plugin.cpp:629] vcvrack: Loaded static plugin mscHack 0.6.1
[0.005 info src/plugin.cpp:629] vcvrack: Loaded static plugin mtsch-plugins 0.6.1
[0.005 info src/plugin.cpp:629] vcvrack: Loaded static plugin NauModular 0.6.1
[0.005 info src/plugin.cpp:629] vcvrack: Loaded static plugin Qwelk 0.6.1
[0.005 info src/plugin.cpp:629] vcvrack: Loaded static plugin SonusModular 0.6.1
[0.006 info src/plugin.cpp:629] vcvrack: Loaded static plugin Southpole-parasites 0.6.1
[0.006 info src/plugin.cpp:629] vcvrack: Loaded static plugin squinkylabs-plug1 0.6.1
[0.006 info src/plugin.cpp:629] vcvrack: Loaded static plugin SubmarineFree 0.6.1
[0.006 info src/plugin.cpp:629] vcvrack: Loaded static plugin Template 0.6.1
[0.006 info src/plugin.cpp:629] vcvrack: Loaded static plugin trowaSoft 0.6.1
[0.006 info src/plugin.cpp:629] vcvrack: Loaded static plugin Valley 0.6.1
[0.006 info src/plugin.cpp:629] vcvrack: Loaded static plugin VultModules 0.6.1
[0.007 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_146097_cc.svg
[0.008 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_31859_cc.svg
[0.008 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_1343816_cc.svg
[0.007 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_31859_cc.svg
[0.007 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_1343816_cc.svg
[0.008 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_1343811_cc.svg
[0.008 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_1084369_cc.svg
[0.008 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_1745061_cc.svg
[0.009 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_1240789_cc.svg
[0.009 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_305536_cc.svg
[0.010 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_468341_cc.svg
[0.200 info src/window.cpp:703] Loaded font f:\git\VeeSeeVSTRack\vst2_bin\/res/fonts/DejaVuSans.ttf
[0.202 info src/settings.cpp:185] Loading settings f:\git\VeeSeeVSTRack\vst2_bin\/settings.json
[0.303 info src/app/RackWidget.cpp:192] Loading patch from string
[0.304 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/Core/AudioInterface.svg
[0.305 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/ComponentLibrary/ScrewSilver.svg
[0.305 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/ComponentLibrary/PJ301M.svg
[0.305 info src/window.cpp:703] Loaded font f:\git\VeeSeeVSTRack\vst2_bin\/res/fonts/ShareTechMono-Regular.ttf
[0.306 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/Core/MIDIToCVInterface.svg
[0.309 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/XCO.svg
[0.309 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/knob_68px.svg
[0.309 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/knob_16px.svg
[0.309 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/button_9px_0.svg
[0.310 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/button_9px_1.svg
[0.310 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/knob_38px.svg
[0.310 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/slider_switch_2_14px_0.svg
[0.310 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/slider_switch_2_14px_1.svg
[0.310 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/port.svg
[0.311 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Fundamental/res/VCA.svg
[0.311 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/ComponentLibrary/RoundLargeBlackKnob.svg
[0.312 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Fundamental/res/VCF.svg
[0.312 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/ComponentLibrary/RoundHugeBlackKnob.svg
[0.313 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/AS/res/ADSR.svg
[0.314 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/AS/res/as-hexscrew.svg
[0.314 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/AS/res/as-SlidePot.svg
[0.314 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/AS/res/as-SlidePotHandle.svg
[0.315 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/AS/res/as-PJ301M.svg
[10.130 info src/app/RackWidget.cpp:154] Saving patch to string
[0.008 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_1240789_cc.svg
[0.008 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_305536_cc.svg
[0.008 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/icons/noun_468341_cc.svg
[0.179 info src/window.cpp:703] Loaded font f:\git\VeeSeeVSTRack\vst2_bin\/res/fonts/DejaVuSans.ttf
[0.181 info src/settings.cpp:185] Loading settings f:\git\VeeSeeVSTRack\vst2_bin\/settings.json
[0.281 info src/app/RackWidget.cpp:192] Loading patch from string
[0.283 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/Core/AudioInterface.svg
[0.283 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/ComponentLibrary/ScrewSilver.svg
[0.283 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/ComponentLibrary/PJ301M.svg
[0.283 info src/window.cpp:703] Loaded font f:\git\VeeSeeVSTRack\vst2_bin\/res/fonts/ShareTechMono-Regular.ttf
[0.285 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/Core/MIDIToCVInterface.svg
[0.287 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/XCO.svg
[0.287 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/knob_68px.svg
[0.288 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/knob_16px.svg
[0.288 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/button_9px_0.svg
[0.288 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/button_9px_1.svg
[0.288 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/knob_38px.svg
[0.289 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/slider_switch_2_14px_0.svg
[0.289 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/slider_switch_2_14px_1.svg
[0.289 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Bogaudio/res/port.svg
[0.290 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Fundamental/res/VCA.svg
[0.290 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/ComponentLibrary/RoundLargeBlackKnob.svg
[0.291 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/Fundamental/res/VCF.svg
[0.291 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\/res/ComponentLibrary/RoundHugeBlackKnob.svg
[0.292 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/AS/res/ADSR.svg
[0.292 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/AS/res/as-hexscrew.svg
[0.293 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/AS/res/as-SlidePot.svg
[0.293 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/AS/res/as-SlidePotHandle.svg
[0.293 info src/window.cpp:754] Loaded SVG f:\git\VeeSeeVSTRack\vst2_bin\plugins/AS/res/as-PJ301M.svg
[17.704 info src/app/RackWidget.cpp:154] Saving patch to string

+ 27
- 0
vst2_bin/plugins/Alikins/LICENSE.txt View File

@@ -0,0 +1,27 @@
BSD 3-Clause License

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


+ 153
- 0
vst2_bin/plugins/Alikins/README.md View File

@@ -0,0 +1,153 @@

# VCV Rack plugin

Plugins for use with VCV Rack virtual module synthesizer (https://github.com/VCVRack/Rack)

![screenshot](./screenshots/modules.png)

## Modules

### IdleSwitch

#### What

An 'idle loop' inspired module for detecting when an input
is idle and turns on a gate until it sees activity again.

If no input events are seen at "Input Source" within the timeout period
emit a gate on "Idle Gate Output" that lasts until there are input events
again. Then reset the timeout period.

Sort of metaphoricaly like an idle handler or timeout in event based
programming like GUI main loops.

The timeout period is set by the value
of the "Time before idle" param.

##### Input event

An "Input event" is a gate or trigger (or a CV or audio signal
that looks sufficently like a gate or trigger).

After a input event, the Idle Gate Output will remain on until
an input event is seen at Input Source. When there is an input event, the Idle
Gate Output is turned off until the expiration of the "Time before idle" or
the next "Reset idle".

##### Reset timer

If there is a "Reset timer" source, when it gets an event, the timeout period
is reset. But unlike an "Input event", a "Reset timer" event does does not
reset the idle status.

After "Reset time" event, the "Idle Gate Output" will remain on until
an input event is seen at Input Source. When there is an input event, the Idle
Gate Output is turned off until the expiration of the "Time before idle" or
the next "Reset idle".

To use the eventloop/gui main loop analogy, a "Reset idle" event is equilivent to
running an idle handler directly (or running a mainloop iteration with no non-idle
events pending).

##### Clock input

If a cable is hooked to the "Clock Input" then the pulse from the clock
will determine with the idle time expires. When there is a clock pulse,
if there were no input events since the previous clock pulse that is
considered idle.

The "Time before idle" display will reflect the time since the last
clock pulse. The "Time remaining" display will always show 0 for now,
at least until it can predict the future.

##### Time input and output

The "Time input" expects a CV output between 0 and 10V. The voltage
maps directly do the number of seconds for the idle timeout.
Eg. a 5.0V CV to "Time input" sets "Time before idle" to 5000ms (5.0 seconds)

The "Time output" sends a CV output between 0 and 10V indicating
the "Time before idle" value.

The "Time output" can be used to connect one or more IdleSwitch modules
together so they share the same "Time before idle".

In "Clock input" mode, the "Time Output" will correspond with the
"Time before idle" display until the time is over 10s, then the
"Time output" will max out at 10V.

##### Gate Output and idle start and end trigger outputs

Once the idle timeout has expired, the "gate output" output
will go high (+10V) and stay high until there are new input
source events. ie, it turns on when there is no actively for
the "Time before idle" length of time.

The "start out" output will send a +10V trigger at the start
of idle, at the start of the "gate out" gate.

The "end out" output will send a +10V trigger at the end of
idle, at the end of the "gate out" gate. This also corresponds
to the same time as when a new "Input source" event is detected.

"start of" trigger == "we have gone idle"
"end of" trigger == "we got input source events (activity) and am no
longer idle.

##### Switched input and output

The "Input" is switched between "When idle" and
"Off idle" outputs based on idle state.

The "Input" port on the bottom left can be any input.

The "Input" will be routed to the "When idle" output if idle.
Otherwise, the "Input" is routed to the "Off idle" output.

Note the "Input" does not have to be related to the input connected
to the "Input source". "Input source" typically needs to be triggers
or gates, but "Input" can be any signal.

#### Why

Original intentional was to use in combo with a human player and midi/cv keyboard.
As long as the human is playing, the IdleSwitch output is 'off', but if they go
idle for some time period the output is turned on. For example, a patch may plain
loud drone when idle, but would turn the drone off or down when the human played
and then turn it back on when it stopped. Or maybe it could be used to start an
drum fill...

The "Reset idle" input allows this be kind of synced to a clock, beat, or sequence.
In the dronevexample above, the drone would then only come back in on a beat.

And perhaps most importantly, it can be used to do almost random output and
make weird noises.

### ColorPanel

A CV controlled RGB/HSL color "blank" panel.

Supports selectable input ranges (0V to 10V or -5V to 5V) via right click context menu
The color input mode is also selectable via the context menu.

Module is resizable.

### BigMuteButton

A big mute button.

Use just before output to the audio interface module.

When clicked, will mute the output output. Will unmute on next
click.

Easier/quicker than adjusting mixer levels, or system volume, or finding
the tiny mute button on mixers.

### MomentaryOnButtons

A set of GUI buttons that send a +10V output while pressed.

## License

BSD 3-clause. See LICENSE.txt

+ 203
- 0
vst2_bin/plugins/Alikins/TODO.txt View File

@@ -0,0 +1,203 @@
plugin ideas:
- Mult with labels
- so I can route a distance output to mult and label
it as 'main seq gate output' to avoid tracing cables
- seq with start/stop/reset triggers (ie, one shot sequencer)
(or 'play', 'pause', 'go to begin')
- solve 'how do I run a sequence once?' FAQ
- event log
- visualization of past triggers/gates
- time series or sparkline-ish
- more or less a scope but without y values and
a very long time
- could do diff colors for gates/triggers
- or gates up and triggers down
- wide module
- multiple time view zooms
- 1x, 2x, 5x, 10, 20x, 50x, etc
- mostly for appearance or troubleshooting/debugging event stuff
- could evolve to supporting playing the the history back
- 1x speed or faster/slower
- scrubbing?
- multiple channels of events
- table module
- "an oscillator is a phasor and a table"
- phasor input (0.0 -> 1.0) or other scaled
- value output
- on step, read phasor value, look for a match
in the table, output the value
- ui
- just a scrollable list?
- columns
- phasor
- start range
- end range
- output value
- buttons to add delete entry
- load table from json in context menu
- uses:
- feed a sawtooth osc output into it to
create rudimentary wave table
- arbitrary quantizer
- building block
- fancy options
- entries that map a range of phasor input
values to a range of output values
- map ranges could be linear/log etc
- linear
- slope
- offset
- sub ranges could be cos/sine/exp/some distribution etc
- (similar to the old GIMP color gradient editor)
- likely could use gimp gradient (ggr) files as a type of table
- modulating the table offset or value amplitudes
- credits module
- widget that shows author, create/mod date, urls, license, other metainfo
- would save into vcv file as module json data
- use a rack_credits.json in ~/ or rack doc root to set the default
- list of author/credit metadata
- would get appended to if modified by new author
- how to only update on 'save' or 'save as' ?
- don't want to append on every autosave.vcv write
- track a single 'last_edit' to persist on every toJson
- then on load/fromJSON, add last_edit to author list
- if there is a way for plugin to distinquish a 'real save' vs
an 'autosave', then could use that.
- how to tell when a patch has been 'modified'?
- needed to avoid adding info on every save or autosave
- slightly klugey way:
- if plugin knows the patch it is in, could load patch .vcv/json
data and compare to 'previous'.
- chksum would be simplest
- but could do a smarter/deeper compare diving into the data
- uses:
- a patch with the module includes the author info
- if patch is shared (via patchstorage for ex), and modified
by a different author, the module json would include info
for the original author and modification author
- just as a display widget when sharing a screen capture
- concerns:
- could probably be better implemented as a feature of the core vcv serialization
- 'Equal and opposite'
- two eqs with 'opposite' settings and an effects loop in between
- before eq, after eq
- same bands and q's, but opposite gain
- ie, if 'before eq' boosts bass and treble by 10db and cuts mids by 12db
then the 'after eq' would cut bass and treble by 10db and boost mids by 12db
- an effects send and return in between
- munge audio signal, send it to effect (a distortion for ex) and unmunge on the way out
- the before/after transforms would automatically mirror each other
- otherwise pointless since it could be done with other modules
- other variations could exist for other reversible-ish transforms
- dont have to be perfect or lossless
- compress/expand
- bitcrush / 'bit extropalate' (is that a thing?)
- forward/reverse delay?
- pitch shift (probably most interesting, but
- transport gui module
- play/stop/pause/fast forward/reverse/record buttons
- gate and trig outputs for them
- just buttons, but with a explicit purpose
- uses
- generative patches that need a 'press play to start'
- specific values
- module with just text entrie fields for entering a float value
and an output for that value
- possibly with text widget in combo with a dial or inc/dec
buttons (spinbox widget)
- or 'click and drag to change value'
- up/down for small value
- left/right for multiplier (middle = 1x, left = 0..1.0x, right >1.0x multi)
- 'up and to the left' for fine grained adjustments
- fancy
- maybe automatically also show CV v/oct freq or note equiv
- maybe gate out and button to click to send value and gate output together
- Seq with per step gate length and rest length between steps
- 'rest' steps basically
- A cv 1v/oct display -> freq hz -> period secs -> bpm.
- ( could display v passed through and/or let you specify as text)
- CV out
- button to send gate
- basically a keyboard with text/entry widgets to let you specify
CV voltage/hz/period/note name
- other possible things to display/select
- midi note number
- # of steps from a root
- interval from a root ( third, flat fifth, etc)
- staff / note
- bpm (for a LFO or general nerdery)
- generic voltage quantizer
- based on 'table' module
- except input CV is 'rounded' to edge of maps
- see 'fancy options' for table module above
- 'Attached file' module.
- GUI file picker
- add base64 of file to data to store in plugin Json.
- Could be a list
- 'Maze Table'
- wave table, but with a maze
- instead of phasor indexing an array, would "index" into
a path along the maze graph
- could have breath first and depth first paths as options
- use DAG style mazes (one and only one path out, no loops or cycles)
- though cycles in maze could be analog for loops in waveform playback
- maybe something hilbert curve esque?
- scmhidtt trigger / pulse generator banks
- just ui to a set of SchmittTriggers
- each strip
- input
- attentuator for process()'ed value
- output trigger
- for generator strip
- trigger input
- knob/cv in/param for duration
- gate output
- Matrix clock
- N x N matrix
- each row defaults to a clock division
- each column defaults to clock multiply
- 0,0 defaults to 1x1 quarter note for tempo
- rows default to 1,2,3,4,6,8,12,16, division
- ditto for columns multi
- but row/columns mult/div could be changed to anything
- XY pad matrix mixer
- matrix mixer with a JL-Modules/kaosspad/reactor style XY pad
at each cross point
- 1,1 -> top output and right output
- 1,0 -> just top output
- -1,-1 -> inverted output to top and right output
- Matrix Mixer with multiple scenes that morph/interpolate
- more or less like Bidoo ACNE except values morph
between scenes insted of
- 2.5 dimension matrix / mixer
- 8x8 matrix but with an output at
each crossing point
- possibly with knob/param for output level
of each output
- maybe a per cross mute/solo
- Much like the movies, the first one was the best.
- Notes module with CV/trigger control and multiple messages
- like a plain notes module, but can react to input from
patch
- use case would be describing stages of a generative patch
- or for adding info to screencast videos
- Gate Divider
- like gate length, but instead of generating one gate, it
generates multiple gates that add up to gate length
- how to seperate?
- some fixed inbetween interval ("kerf")
- divide into on and off gates
- divide a 1s gate by 1 -> one .5s gate then a .5s 'rest'
(and vice versa / inverse 10 or 01)
- divide by 3 -> one .3333s gate, one .3333s rest, one .3333 gate
( ie, 101 or 010)
- divide by 4 -> .25 gate, .25 rest, .25 gate, .25rest
(1010, 0101)
- divide by 5 -> .20 on, .20 off, .20 on, .20 off, .20 on
(10101, 01010)
- kind of similar to Walsh codes
" Experimental Electronic Music Devices Employing Walsh Functions",
"BERNARD A. HUTCHINS, JR"
"JOURNAL OF THE AUDIO ENGINEERING SOCIETY, October 1973"
(https://pdfs.semanticscholar.org/6b9c/30f94551aaf05f077aa491f31b196898cd90.pdf)
- "Sequency" - theres a module name if I ever heard one.

+ 2006
- 0
vst2_bin/plugins/Alikins/res/BigMuteButton.svg
File diff suppressed because it is too large
View File


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

Loading…
Cancel
Save