Page 1 of 1

How to implement TubePreamp

Posted: Mon Jan 25, 2021 5:58 am
by Resomation
Hello! I'm new to both Java and Designer, and while I'm attempting to learn Java as I learn Designer, I'm having trouble with the TubePreamp class.

I have a module with an analog oscillator generating a sine wave and a noise generator producing white noise. There is a knob control that ring modulates the two signals together. I have successfully tested and built the module up to this point, and can confirm it works.

However, when I try to add a tube preamp before the output to add some warmth, I get tons of errors. For example, when I declared the oscillater under User Variables, I used the folliwing code:

Code: Select all

public AnalogOscillator the_essence = new AnalogOscillator();
When I declare a TubePreamp in the same way:

Code: Select all

public TubePreamp t00b = new TubePreamp();
I get an error saying I can't apply "new" to the class type.

If I try it this way:

Code: Select all

public TubePreamp t00b = TubePreamp();
I get an error saying there should be a semicolon after "t00b".

I'm stumped. How the heck do I construct a TubePreamp? Any help would be most appreciated, thanks.

Re: How to implement TubePreamp

Posted: Mon Jan 25, 2021 10:36 am
by honki-bobo
Hi Resomation,

one of your downloads should have been the Voltage Module Designer Developer Kit, which contains the JavaDoc documentation of the voltage package. According to this documentation the constructor of the TubePreamp class takes a double value as parameter, the drive amount, and it should be between 0 and 1.

Code: Select all

private TubePreamp t00b = new TubePreamp(0.0);
I highly recommend reading the JavaDoc of the classes you want to use, especially as a beginner. It will make your life a lot easier ;)

Re: How to implement TubePreamp

Posted: Mon Jan 25, 2021 3:41 pm
by Resomation
Thanks!

I did download the Dev Kit, and I've been trying to learn how to interpret code, but I'm still very green and stuff like this slips by me pretty easily. I also read the Java documentation, I think its more a lack of understanding on how to implement it when I'm writing code. I started learning Designer before I started learning Java, so there's a definite knowledge gap.

So once I declare it under user variables like you've shown above, theoretically I could use the following code in the process sample section, right?

Code: Select all

if outputJack1.IsConnected())
{
double input = inputJack1.GetValue();
t00b.SetDrive(0.5);
double output = t00b.Process(input);
outputJack1.SetValue(output);
}
Obviously there's more to implement, like a control for the drive and some pre/post filtering, but as a basic structure, would the code work or am I way off base?

EDIT: Eureka! I figured it out! The code I ended up with works and the module does exactly what I wanted. Thanks for the pointers, I feel like I have a better understanding of what I'm doing now.

Re: How to implement TubePreamp

Posted: Wed Jan 27, 2021 8:14 am
by honki-bobo
Great you made it work!

Just a tip: if you set a parameter only once and never change it (like you did with t00b.SetDrive(0.5)), do this in the Initialize() method and not in ProcessSample(). ProcessSample() should be kept as short and efficient as possible since it is called 48k times per second. If you were to change the drive amount with a knob, then change the parameter in the Notify() method in the Knob_Changed case

Code: Select all

case Knob_Changed:
{
    if (component == driveKnob) {
        t00b.SetDrive(doubleValue);
    }
}
break;
Best regards,
Martin

Re: How to implement TubePreamp

Posted: Wed Jan 27, 2021 6:03 pm
by Resomation
honki-bobo wrote: Wed Jan 27, 2021 8:14 am

Code: Select all

case Knob_Changed:
{
    if (component == driveKnob) {
        t00b.SetDrive(doubleValue);
    }
}
break;
I never thought of this! I was setting values individually, this makes much more sense.

If there's math involved, can that be included in the notify method, also? For example,

Code: Select all

case Knob_Changed:
{
    if (component == driveKnob) {
        driveValue.SetValue(doubleValue);
        hp1Value.SetValue(doubleValue*300)
        t00b1.SetDrive(driveValue.GetSmoothValue());
        hp1.SetCutoff(hp1Value.GetSmoothValue());
    }
}
break;
Also, I have a semi unrelated question. Do I have to declare a new variable every time I use a function under process sample? Here's what I've been doing vs what I'm asking:

Code: Select all

//What I'm doing
if (outputJack.IsConnected())
     {
     double inputValue = inputJack.GetValue();
     double t00bValue = t00b.Process(inputValue);
     double filtValue = hp1.ProcessSample(t00bValue);
     outputJack.SetValue(filtValue);
     }
     
 //Would this work?
 if (outputJack.IsConnected())
     {
     inputJack.GetValue();
     t00b.Process();
     hp1.ProcessSample();
     outputJack.SetValue();
     }

Re: How to implement TubePreamp

Posted: Wed Jan 27, 2021 6:58 pm
by honki-bobo
Resomation wrote: Wed Jan 27, 2021 6:03 pm If there's math involved, can that be included in the notify method, also? For example,

Code: Select all

case Knob_Changed:
{
    if (component == driveKnob) {
        driveValue.SetValue(doubleValue);
        hp1Value.SetValue(doubleValue*300)
        t00b1.SetDrive(driveValue.GetSmoothValue());
        hp1.SetCutoff(hp1Value.GetSmoothValue());
    }
}
break;
Of course you can. But remember, Notify() is only called in case of an event. The SmoothValue works with timers, so it makes much more sense to call t00b.SetDrive(driveValue.GetSmoothValue()) and hp1.SetCutoff(hp1Value.GetSmoothValue()) inside the ProcessSample() method to update the drive and filter parameters, like so:

Code: Select all

case Knob_Changed:
{
    if (component == driveKnob) {
        driveValue.SetValue(doubleValue);
        hp1Value.SetValue(doubleValue*300);
    }
}
break;

...

public void ProcessSample() {
    ...
    t00b.SetDrive(driveValue.GetSmoothValue());
    hp1.SetCutoff(hp1Value.GetSmoothValue());
    ...
}
Resomation wrote: Wed Jan 27, 2021 6:03 pm Also, I have a semi unrelated question. Do I have to declare a new variable every time I use a function under process sample? Here's what I've been doing vs what I'm asking:

Code: Select all

//What I'm doing
if (outputJack.IsConnected())
     {
     double inputValue = inputJack.GetValue();
     double t00bValue = t00b.Process(inputValue);
     double filtValue = hp1.ProcessSample(t00bValue);
     outputJack.SetValue(filtValue);
     }
     
 //Would this work?
 if (outputJack.IsConnected())
     {
     inputJack.GetValue();
     t00b.Process();
     hp1.ProcessSample();
     outputJack.SetValue();
     }
It would not work like this. You need to declare some class variables first and then use them inside methods. In Voltage Module Designer you declare class variables at the bottom of the Java file

Code: Select all

private double inputValue;
private double t00bValue;
private double filterValue;

private TubePreamp t00b;
private AnalogFilter hp1;

private SmoothValue driveValue;
private SmoothValue hp1Value;
and initialize them all in the Initialize() method accordingly.

Your ProcessSample() method would then look like this:

Code: Select all

public void ProcessSample() {
    if (outputJack.IsConnected()) {
        inputValue = inputJack.GetValue();
        
        t00b.SetDrive(driveValue.GetSmoothValue());
        t00bValue = t00b.Process(inputValue);
        
        hp1.SetCutoff(hp1Value.GetSmoothValue());
        hp1.ProcessSample(t00bValue);
        
        filterValue = hp1.GetHighpassValue();
        
        outputJack.SetValue(filterValue);
    }
}

Re: How to implement TubePreamp

Posted: Wed Jan 27, 2021 11:14 pm
by Resomation
This is all excellent information. Thank you for all your help, there is a ton of stuff I've been doing that works, but is really badly optimized. Time to go clean up some code and see if I can improve the designs.

Do you have a patreon? I feel like I owe you a beer.

Re: How to implement TubePreamp

Posted: Wed Jan 27, 2021 11:23 pm
by honki-bobo
Glad I could help. I don't have a patreon, but you can always buy some of my modules or bundles if you like :)

https://store.cherryaudio.com/manufactu ... ness-audio

Cheers,
Martin