New to DSP, need some help!


#1

I'm new to DPS (and c++ too really), I'm almost clueless as to how I should proceed.

I have my plugin building now using the provided Makefile, but I'm not sure how I would, for example, generate a sine wave of a given frequency, say 440hz?

 

After some hours of googling I came up with something like this:

 


void HelloJuceAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
    // In case we have more outputs than inputs, this code clears any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    // I've added this to avoid people getting screaming feedback
    // when they first compile the plugin, but obviously you don't need to
    // this code if your algorithm already fills all the output channels.
    for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
        buffer.clear (i, 0, buffer.getNumSamples());
    this->sine += 1 * buffer.getNumSamples();

    // This is the place where you'd normally do the guts of your plugin's
    // audio processing...
    for (int channel = 0; channel < getNumInputChannels(); ++channel)
    {
        float *channelData = buffer.getWritePointer (channel);
        //*channelData *= rand() % 1;
        //*channelData = 0.5f;
        *channelData = std::sin(440 * (2 * 3.141592653589793) * this->sine / 44100);

        //1000 * (2 * pi) * i / 44100
        //frequency * (2 * pi) * i / 44100
        //frequency * (2 * pi) * (this.sine * samplesPerBlock) / 44100
    }
}

 

I tried to run the plugin, but the sound output isn't exactly what I thought it would be... of course, I'm just guessing my way around this.

 

The main issue for me is I don't know what the channelData contains. Are the supposed to contain floats between 0 and 1 ? or -1 and 1?

Or something else?


#2

Check out how the JUCE demo plugin does it. You should probably make your oscillator in a SynthesizerVoice class like the demo plugin does. That way you can play it from the keyboard and play more than one voice. As for how to make oscillators, you'll need to do some studying on that.

I'd recommend not starting to your DSP journey in C++ (especially if you're new to it). Something like Reaktor or Max/MSP will help you learn the basics much faster. I started in Reaktor (not too long ago) and I wouldn't know half of what I do if I didn't use it first. Even if you do plan on making plugins with C++, it might still be a good idea to prototype in something like Reaktor. That way you could focus on the algorithms and sound instead of all the setting up required. But hey, do what works for you. 

As for the buffer, it uses a -1 to 1 range. 

From what I can tell from looking from my phone, you're not storing the osc in the buffer per sample. It seems like you're doing it per block. I would just do it the way the JUCE demo does it. It basically gets called every block and loops through the block depending on its size and stores the output into each sample on each iteration. Sorry, I'm not good at explaining it.

I'll try to post an example of a simple synth with a sine osc and saw osc that can be easily modified into different oscillators soon. I'm pretty new to JUCE and C++ too, but maybe I can help you.


#3

Check out Digital Sound Generation - Part 1 & 2.  Part 1 has a very simple phase accumulator (saw/ramp osc) algorithm at the beginning, as well as some awesome more advanced oscillator algorithms for down the road. 

Try out that accumulatot in chapter 1.1 in part 1. Try implementing it in a SynthesizerVoice, following the guidelines of the SineWave in the JUCE demo plugin. 

You can actually use the phase accumulator from that algorithm for a lot of other oscillators. If you just make N = 0.5, you have a saw or a ramp oscillator. A phase accumulator is basically just a ramp oscillator by the way. You'll be using that for a lot of oscillators down the road, so it'll be nice to have it as a "template" of some sort.

After you have that made, you can just set    N = pi and run that phase accumulator's (or ramp/sawtooth oscillator's) output through a sin() function to get a sine oscillator.

Here's the links to both papers. I'll try to make a good example of this for you soon and post it.

https://www.zhdk.ch/fileadmin/data_subsites/data_icst/Downloads/Digital_Sound/Digital_Sound_Generation_1.pdf

http://courses.cs.washington.edu/courses/cse490s/11au/Readings/Digital_Sound_Generation_2.pdf


#4

Well, I'm on Linux. And As I understand, neither reaktor nor max/dsp are available natively for linux. It would be a lot easier with some sort of prototyping system indeed.

 

Anyway, I'll have a look at the SynthesizerVoice. Thanks.


#5

Pd and/or SuperCollider might be a free alternative to Max/MSP for prototyping on GNU/Linux.

https://puredata.info/
https://supercollider.github.io/