jameshball / osci-render-juce Goto Github PK
View Code? Open in Web Editor NEWγ°πΊπ Synthesizer for making music by drawing objects on an oscilloscope using audio. Now as an audio plugin!
License: GNU General Public License v3.0
γ°πΊπ Synthesizer for making music by drawing objects on an oscilloscope using audio. Now as an audio plugin!
License: GNU General Public License v3.0
CONTEXT AS TO WHAT THIS IS: https://www.youtube.com/watch?v=pCn297Ejvlw
Should be relatively straightforward to implement by copying the implementation from legacy osci-render https://github.com/jameshball/osci-render/blob/master/src/main/java/sh/ball/engine/ObjectServer.java
JUCE has a StreamingSocket class that should make setting up the TCP server easy, and a JSON class that will let you parse the message.
For completeness, this is the client-side code for connecting to the server in Blender https://github.com/jameshball/osci-render/blob/master/blender/osci_render/__init__.py . This will let you see the JSON format that is sent to osci-render.
The only complex part of this will be routing up the lines that are drawn to the PluginProcessor, either via the frameFifo directly
osci-render-juce/Source/PluginProcessor.cpp
Line 404 in 9293214
Project files should be compatible with Java osci-render and be in the exact same format.
We might run into issues with effect precedence being changeable in osci-render 2.0, unlike in Java osci-render. We should hard-code the precedence to be the same as the Java osci-render one in the case it isn't given in the project file.
Lua live-coding is unstable for certain scripts. Some examples I've noticed are:
But there are probably several others.
The code that handles parsing Lua scripts is in LuaParser.cpp, specifically in the parse() function
osci-render-juce/Source/lua/LuaParser.cpp
Line 18 in 9293214
I've noticed that there are a lot of abort() called in the lua library, which we NEVER want to happen as this crashes the entire program. We want to just fail parsing and return silence from the function. This is already done in parse() but clearly is doesn't catch every case. Just need to have a look at the stack trace to see where it's crashing and either change what functions we call to parse the code, or in the worst case change the lua library code.
The Lua C API is fairly complicated, but there is a good reference here https://www.lua.org/manual/5.3/manual.html
Similar to the prev. issue, if parsing ever fails, we should save the script/function of whatever was previously successfully parsed and either save it or reparse it. That way, the audio keeps playing and doesn't constantly cut out whenever you make an edit to it.
This should be fairly straightforward and can be done in the LuaParser.cpp/.h files.
This is elaborated more in this JUCE tutorial: https://docs.juce.com/master/tutorial_sine_synth.html under "Smoothing frequency changes" which also explains how this can be implemented.
Doing this vastly improves the usability of osci-render in live performances and when being controlled with MIDI controllers that jump in large steps.
CONTEXT FOR THIS: https://www.youtube.com/watch?v=PKVCx7rs_r8&t=269s
This gives good context as to what MIDI CC channels are (ignore anything specific to Ableton) https://help.ableton.com/hc/en-us/articles/360010389480-Using-MIDI-CC-in-Live but basically, they are used to control effects/parameters such as adding reverb, or a low/high-pass filter etc. In osci-render, it can control any effect/slider seen.
This involves the following:
osci-render-juce/Source/PluginProcessor.cpp
Line 453 in 9293214
Try and use legacy osci-render as a reference, but this might be a bit hard if you don't have a MIDI controller!
The bulk of legacy osci-render's code for this is here: https://github.com/jameshball/osci-render/blob/0330152b4e951ccf15d6fee9736ea27576805155/src/main/java/sh/ball/audio/ShapeAudioPlayer.java#L687
BUT I am generally unhappy with how it works here. This might need to be reworked from scratch.
MIDI in legacy osci-render works as follows:
keyTargetVolumes
)
baseNote
in notesChanged() https://github.com/jameshball/osci-render/blob/0330152b4e951ccf15d6fee9736ea27576805155/src/main/java/sh/ball/audio/ShapeAudioPlayer.java#L667
The major problems with this are:
I think the best solution could be to convert https://github.com/jameshball/osci-render-juce/blob/master/Source/PluginProcessor.cpp into a Synthesiser which would require a lot of refactoring, BUT means that handling MIDI should be super simple because the Synthesiser class handles most of it for you.
This would also allow the user to easily choose between monophonic and polyphonic audio and the SynthesiserVoice interface is a very easy way to add a lot of customizability in the additional sounds that are played, rather than them all being sine waves.
We could also try and support full polyphonic oscilloscope graphics, however this would likely be extremely expensive to run in real-time. This COULD work by having a separate FrameProducer for every SynthesiserVoice so that it is fully multi-threaded...
In the simplest case:
In the complex case:
I would advocate for the complex case as it would make it very powerful :)
Currently this looks laggy on lower sample rates. It shouldn't be laggy, it should just be more jagged. The buffer size should be a fixed period of time, changing depending on sample rate, rather than constant.
maybe add a 'compile' or 'run' button or something?
Chinese postman is extremely expensive to run. We can use Fleury's algorithm and pair odd degree nodes suboptimally as a heuristic for Chinese postman.
Fleury's algorithm: https://slaystudy.com/fleurys-algorithm/
Working implementation of this: https://github.com/Eric-Lennartson/pd-osci/blob/dev/Classes/Source/tsp.c
To implement this, we should replace the code in
osci-render-juce/Source/obj/WorldObject.cpp
Line 132 in 9293214
As an aside, we should look to improve the performance of the graphs used to perform this algorithm as they can probably be improved a decent amount.
Currently, they are hideous and light-theme-oriented! Just change it to use similar colours to the darcula theme https://github.com/dracula/dracula-theme by creating a ColourScheme and setting it on each CodeEditorComponent here https://docs.juce.com/master/classCodeEditorComponent.html#a4faca1aad5f908a0e35a71ca25e784b1
All the CodeEditorComponents are initialised here:
osci-render-juce/Source/PluginEditor.cpp
Line 146 in 069633a
Legacy osci-render lets you open the software oscilloscope ( https://james.ball.sh/oscilloscope ) from within osci-render by clicking on Window and then Open Software Oscilloscope.
We should mimic this in osci-render 2.0, but possibly with better UX! It's a bit weird atm that it's part of the title bar under Window when we don't use Window for anything else. So, either think of a better way of doing it with a button or something or just replicate it.
This should be trivial to do in JUCE: https://docs.juce.com/master/classURL.html#a2e0faa22cab2447d64c8ac0d01bdccda
We obviously depend on #8 before we can implement this.
Something like this would be amazing:
Can download here to reverse-engineer / for a case study https://vital.audio/ and it's also open source: https://github.com/mtytel/vital
This explains what an envelope is and what all the parameters do: https://en.wikipedia.org/wiki/Envelope_(music)#ADSR
To see roughly how you'd implement a basic version of this, take a look at the volume visualiser component: https://github.com/jameshball/osci-render-juce/blob/9293214943af555d2aaa15eb4f71dc3771a66a9d/Source/components/VolumeComponent.cpp
This has a paint() function that you draw the component for. We could quite easily draw a JUCE Path that goes between the attack/decay/release/sustain etc. points. The harder part would be supporting dragging the points around which I don't immediately know how to do, but the JUCE Slider class will give some ideas. The DragAndDropContainer also looks very promising - we could have the knobs as separate components that are DragAndDropContainers and have the parent ADSR component be the DragAndDropTarget that has callbacks for when the knob is being dragged and can update values accordingly.
Legacy osci-render supports changing the font and style (i.e. bold/italic etc.) globally for all text files, but this is pretty limiting.
A better solution would be to add these settings as a separate TextComponent, in exactly the same way LuaComponent and ObjComponent have been added. i.e. the settings should control just the current txt file open, and should appear when a txt file is opened.
When this has been created, it just needs to be added to the PluginEditor and then a few bits need to be changed to toggle whether it is visible or not:
osci-render-juce/Source/PluginEditor.cpp
Line 114 in 9293214
osci-render-juce/Source/PluginEditor.cpp
Line 186 in 9293214
Changing the font should trigger the font file to be re-parsed, as it takes in the Font
The style of the font is part of JUCE Font itself, so it should be fairly trivial to set using https://docs.juce.com/master/classFont.html#a52a35b5dc1e6f782e25283c9283bae4f
JUCE has a very easy way of getting all the installed fonts on the machine: https://docs.juce.com/master/classFont.html#a95f7587d2f1bb76329f4f09444b09cdb so having a ComboBox that contains all the fonts that a user can choose from makes sense here.
The font and font style should be stored with the project file and used in both getStateInformation() and setStateInformation()
Legacy osci-render also supports custom fonts/styles so https://github.com/jameshball/osci-render-juce/blob/9293214943af555d2aaa15eb4f71dc3771a66a9d/Source/LegacyProject.cpp should be updated to recognise custom fonts from the legacy project file. To get an example legacy project file have a look here https://james.ball.sh/docs/spiral_dots.osci and it's under fontFamily
and fontStyle
XML tags.
IMPORTANT: The fonts that are installed are not the same on every computer, so it's important that there is always a fallback font if the font saved to a project file is not available on the machine.
Hello! On my osci-viewport project, which is based on osci-render, I have improved the software oscilloscope drastically and I want to do the same for osci-render. I'll create a fork and make a pull request once osci-viewport has been detached.
I'm generally very happy with the project select screen in legacy osci-render, the only thing that would need changing is thinking about WHEN the project select screen is opened by default.
Currently, legacy osci-render opens this screen whenever osci-render is opened. But, now we are dealing with audio plugins, I think it only makes sense to open the project select screen when the DAW doesn't try loading the previous state of the program using setStateInformation() first.
For clarity, project select screen should NOT open when osci-render opens if:
The UX for an example first-time-user of osci-render within a DAW could be:
If the project select screen is visited again, and the user closes osci-render, then they should be greeted with the project select screen upon reopening.
To achieve this, we could do something like save the page that the user is currently on (i.e. project select or main page) with the project state and look at this to determine what page to show them.
SIDE NOTE: We should probably be storing currentProjectFile with the project file so that we can restore this when saving.
Port the web-based software oscilloscope to C++ and and have it work either within osci-render or as a separate VST.
Should be trivial to create the logger itself using FileLogger which should be a member of the PluginProcessor class so that it persists.
The hard part is finding all aspects of osci-render where errors could possibly occur and logging them rather than silently ignoring them or hard crashing like we are at the moment!
Things that immediately come to mind are:
Goes without saying that over-logging is much more important than under-logging as this is the number 1 most useful tool for debugging when you don't have access to a user's machine.
ASIDE: There should be a max log file size to prevent somehow using up all space on user's machine! (this mistake was made with legacy osci-render, oops)
There should be one global frequency analyser that other classes can listen to, the same as in Java osci-render. We need this for the wobble effect
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.