Giter VIP home page Giter VIP logo

osci-render-juce's People

Contributors

djlevel3 avatar jameshball avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

osci-render-juce's Issues

Blender integration

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

void OscirenderAudioProcessor::addFrame(std::vector<std::unique_ptr<Shape>> frame, int fileIndex) {
or somehow integrating it with FileParser but I think the first option is probably best. This would mean you'd need to disable the current frame source / file parser whilst connected to blender and then have the blender server thread add frames directly.

Add support for .osci project files

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.

Increase Lua live-coding stability and save last successfully-compiled script

Increase stability

Lua live-coding is unstable for certain scripts. Some examples I've noticed are:

  • Empty scripts completely crash osci-render (anything with only blank space or only comments)
  • Scripts that are just a return with no expression crash osci-render

But there are probably several others.

The code that handles parsing Lua scripts is in LuaParser.cpp, specifically in the parse() function

void LuaParser::parse() {

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

Save last successful script

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.

Add MIDI CC support for controlling sliders

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:

  • Add MIDI SvgButton to EffectComponent so that every single effect has a button they can click to arm a MIDI channel.
    • Linking a parameter to a MIDI CC channel has three states: unlinked (white icon), listening/armed (red icon), linked (green icon)
    • SvgButton colour must be changed accordingly. Currently it only has support for changing colour when toggled on/off, so maybe add a function to it that lets you change the colour arbitrarily.
  • Only one parameter can be armed at once, so store a reference to the armed effect that is overwritten whenever the MIDI button on an unlinked effect is clicked
  • Then, look for any MIDI CC channel messages in PluginProcessor processBlock
    void OscirenderAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
    and if there are any, link the CC channel to that effect, and update the value of the parameter to the value in the CC message
  • Set the effect's MIDI button to green to indicate it's linked to a CC channel
  • Now, any time that MIDI CC channel is seen in the future, it is assumed to be linked to that effect and the value should be updated
  • You should be able to unlink the effect and CC channel by clicking on the button again

Try and use legacy osci-render as a reference, but this might be a bit hard if you don't have a MIDI controller!

Add MIDI support for playing notes

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:

The major problems with this are:

  • It sounds terrible for anything other than monophonic MIDI because you have one main note that has a usually very harsh oscilloscope-music-sounding timbre, mixed with several very smooth sine waves
  • The simple algorithm for choosing the base note leads to some jarring switches in what melody sounds like the main melody due to the oscilloscope graphics image being the prominent sound you hear

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:

  • Convert PluginProcessor to a Synthesiser
  • Have SynthesiserVoices for the main oscilloscope graphics as well as any additional sounds, e.g. the sine wave sound we had in legacy osci-render
  • Let the user choose what SynthesiserVoices they use and whether it's mono/polyphonic

In the complex case:

  • Completely refactor PluginProcessor to allow many instances of it as a SynthesiserVoice so that you can have many oscilloscope graphics voices at the same time
  • Each SynthesiserVoice has its own FrameProducer, meaning samples are produced in multiple threads

I would advocate for the complex case as it would make it very powerful :)

Use Fleury’s algorithm as a chinese postman heuristic

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

// perform chinese postman on all connected sub-components of graph
with this alternative algorithm.

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.

Update syntax highlighting colours for code editor

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:

void OscirenderAudioProcessorEditor::addCodeEditor(int index) {
This is where you should set the colour scheme.

Add .lua file support

  • .lua file parsing working
  • SampleSource needs to be introduced, like in Java osci-render

Add button to open software oscilloscope in the browser

Image

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

Add intuitive way of controlling MIDI settings like attack/decay/etc.

We obviously depend on #8 before we can implement this.

Something like this would be amazing:

Image

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.

Add .txt specific file settings (or allow font+style to be controlled globally)

Image

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:

if (lua.isVisible() || obj.isVisible()) {

void OscirenderAudioProcessorEditor::fileUpdated(juce::String fileName) {

Changing the font should trigger the font file to be re-parsed, as it takes in the Font

TextParser::TextParser(juce::String text, juce::Font 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.

Improve Software Oscilloscope

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.

Add project select screen

Image

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:

  • setStateInformation() is called
  • The project passed to setStateInformation() is actually a valid project
  • The project is non-default (this is fairly hard to identify so maybe ignore this)

The UX for an example first-time-user of osci-render within a DAW could be:

  • Greeted with the project select screen
  • Closes osci-render on the project select screen
  • Opens again, and greeted with project select screen
  • Starts a new project
  • Closes osci-render (DAW saves the state when closing)
  • Opens again, now the DAW has saved the state, so they bypass the project select screen and go straight to their previously started project

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.

Add software oscilloscope

Port the web-based software oscilloscope to C++ and and have it work either within osci-render or as a separate VST.

Log any runtime errors to a file

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:

  • Server that sends data to software oscilloscope can fail to start
  • Server that receives Blender line data can fail to start ( #36 needs to be implemented first obv )
  • Critical errors with Lua
    • Could involve adding extra safety checks like making sure the lua script doesn't take too long to run and cancelling if it does and logging this
  • IF POSSIBLE: checks in any threads that use locking to wait on the audio thread to log to a file if they have waited for too long for audio (i.e. suspicion of deadlocks)
    • Examples of components that wait for the audio thread are anything that has a BufferConsumer, so AudioWebSocketServer, PitchDetector, VisualiserComponent, VolumeComponent.

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.