Giter VIP home page Giter VIP logo

Comments (11)

modlfo avatar modlfo commented on August 25, 2024

The range is from -1.0 to 1.0. I created this code that you can paste into the web demo. You can use the CC30 to change the k.

fun shaper(x,k) {
    val pi = 3.1415;
    return (3.0 + k) * x * 20.0 * (pi/180.0)/(pi + k * abs(x));
}
fun process(input:real){
   mem k;
   return shaper(input,k);
}
and noteOn(note:int,velocity:int,channel:int){}
and noteOff(note:int,channel:int) {}
and controlChange(control:int,value:int,channel:int){
  if(control==30)
    k = real(value)/ 1.0;
}
and default(){}

As you increase the k is possible to hear the harmonics. If you have a fixed k it's possible to use the @[table()] attribute. I haven't tried to create very large tables, but the intention behind the implementation is to be able to use small tables that produce a nice sound. The interpolation used with @[table()] is second order. One would require large tables when using first order interpolation.

In this code I created the wave shaper with the @[table()] attribute, and if you move the CC30 if will change between the two implementations. I cannot hear any difference between them.

fun shaper_original(x,k) {
    val pi = 3.1415;
    return (3.0 + k) * x * 20.0 * (pi/180.0)/(pi + k * abs(x));
}
fun shaper_table(x) @[table(size=127, min=-2.0, max=2.0)] {
    val pi = 3.1415;
    val k = 10.0;
    return (3.0 + k) * x * 20.0 * (pi/180.0)/(pi + k * abs(x));
}
fun process(input:real){
   mem mix;
   val o = if mix > 0.5 then shaper_original(input,10.0) else shaper_table(input);
   return o;
}
and noteOn(note:int,velocity:int,channel:int){}
and noteOff(note:int,channel:int) {}
and controlChange(control:int,value:int,channel:int){
   if(control==30)
      mix = real(value)/127.0;
}
and default(){}

from vult.

cristiano-belloni avatar cristiano-belloni commented on August 25, 2024

Thanks.
Yes, I feel the harmonics if I turn the knob with my karplus-strong process function. Apart from being simplified and taking k as an input, your implementation is substantially equivalent to mine, but the output is still underwhelming and the effect very subtle, so I guess there's something else in play here. For comparison, pizzicatojs uses the same waveshaper with 0 < k < 100, but their "Distortion" demo sound much more "distorted" than my waveshaper. Maybe the Web Audio API is doing something else in the background? I'll investigate.

Thanks for the table example! That's really cool, and I still had a couple of doubts about tables that your example solved. I still don't understand why you generate the table in a -2.0, 2.0 range, since the input ranges from -1 to -1. Is it to prevent clipping input to return the wrong value? What would happen if I called it with 5, for example?

from vult.

modlfo avatar modlfo commented on August 25, 2024

When called outside the range, you get the extrapolated value of the limits. That's why I always leave a little bit of space in the range. If possible, I clip the input value to fit the range (check the implementation of saturate here https://github.com/modlfo/vult-examples/blob/master/src/util.vult

In your example, if you want more aggressive distortion, you can do what's done in the guitar pedals, multiply the input. For example:

fun shaper(x,k) {
    val pi = 3.1415;
    return (3.0 + k) * x * 20.0 * (pi/180.0)/(pi + k * abs(x));
}
fun process(input:real){
   mem gain;
   return shaper(gain*input,10.0);
}
and noteOn(note:int,velocity:int,channel:int){}
and noteOff(note:int,channel:int) {}
and controlChange(control:int,value:int,channel:int){
  if(control==30)
    gain = 1.0 + real(value);
}
and default(){
   gain = 1.0;
}

As the gain increases, the sine wave becomes a square signal.

from vult.

cristiano-belloni avatar cristiano-belloni commented on August 25, 2024

Yep, saturate was what triggered https://github.com/modlfo/vult/issues/18 :)
Clipping with gain helps a bit, but the sound is still different and underwhelming. I will investigate. Thanks!

from vult.

modlfo avatar modlfo commented on August 25, 2024

I updated the code. You should be able to use tanh in the web.

from vult.

modlfo avatar modlfo commented on August 25, 2024

By the way. I tested a tanh distortion with a sample of a real guitar and the distortion sounds really cool. While the same shaper with very ideal waveforms (like sine, or saw) sounds very week.

from vult.

cristiano-belloni avatar cristiano-belloni commented on August 25, 2024

Actually I'm generating the guitar string sounds from a simple Karplus-Strong model (one of the reasons I'm using Vult is to experiment with physical models and feedback). Turns out that the same model, written in javascript, sounds very weak even with the WAA wavershaper node.

Normally what people do is adding a bit of presence with a cabinet emulation based on an impulse response, which I guess is ok - I just need to write the convolution bit. The only hard thing is that I will have to manually load the IR somehow - any plans to add file i/o to Vult in the future, @modlfo? :D

from vult.

modlfo avatar modlfo commented on August 25, 2024

Yes. I have been experimenting with Wav file reading at compile time. I want to be able of embedding wav files as arrays. But I'm not sure how this can work on the web demo. It will require to generate the code from the terminal and somehow load it on the browser.

As a workaround you can declare an external function that takes an index and gives you back the sample of an IR and provide that function as external Js.

I'll let you know when I have this available.

from vult.

cristiano-belloni avatar cristiano-belloni commented on August 25, 2024

What comes to mind is just let the user specify a baseurl, then wrap the generated code in a fetch callback and put the retrieved file in a typed array. The user just has to host the files somewhere. But of course the CORS headers should be enabled on the hosting side and that would be complicated.

What would be really cool would be an online IDE that hosts the files (code and data) for the user. Then the user would prototype online and loading externals + loading data files would automagically work. Then the user could just export for a given target with a button and download the result. It could even be a service - write once, save as vst / code for dsp board / web audio component.

Is it easy to operate the compiler from javascript? I understand you generate a javascript lib with an utility that traslates ocaml to js. If all the APIs are there, I would like to try and do a PoC. Not being able to load externals in the web IDE is kind of frustrating, so the first target could be that :)

from vult.

modlfo avatar modlfo commented on August 25, 2024

The compiler API exposes the all the command line options, but the input files need to be passed as strings. This is the npm library https://www.npmjs.com/package/vultlib
In the web demo I add a few wrappers for that code.

Regarding the online IDE, I have one idea and I made some progress. Here's the basic idea https://github.com/modlfo/VultPlatform/wiki

I worked a bit in the (local) (AudioEngine)[https://github.com/modlfo/AudioEngine] but I have been slow with the development of the clients. I have been trying to write a simple client (in a private repo) in Elm.

Other idea that I have in mind is making a Visual Studio Code plugin that connects to the AudioEngine to run the code.

If you have a recommendation on how I should generate/export the Js code so is easy to use let me know.

from vult.

cristiano-belloni avatar cristiano-belloni commented on August 25, 2024

The Vult Platform idea is really cool. IMHO it should support multiple files. Also, if many people use it, a pseudo-registry (maybe a thin layer over GitHub) would be a quick win.

Exporting code to Javascript could be complex if loading files comes into play, depending on what is the target. You could probably solve it like this:

Previewing in demo:
Have the user upload its audio assets. Generate the javascript code like you do now, but wrap it in parallel fetch calls (maybe using async) to get the assets from whenever they're stored. Firebase Storage, for example, is dirty cheap and easy to use.

Exporting to a file:
The user can select whether to export as a ES6 module or an inline module. Generate the code like you do now, then:

  • ES6: prepend import assetName1 from './asset1.wav' statements. The user will need to use a webpack loader or some equivalent technique to load the file as a blob / typed array.
  • Inline: Just inline the audio assets as a blob / typed array.

from vult.

Related Issues (20)

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.