Hi folks,
I’m trying to recreate the Sine Wave Synth tutorial found here:
https://docs.juce.com/master/tutorial_sine_synth.html
but as a plugin. I’m encountering two distinct issues:
1.) When I try to loop through the output channels using the processBlock template code provided by JUCE, I don’t hear a smooth sine-wave, but rather a distorted garble. I suspect that this is because I’m creating a waveform discontinuity between iterations of the outer, output-channel for-loop:
void updateAngleDelta()
{
auto cyclesPerSample = freq / currentSampleRate;
angleDelta = cyclesPerSample * 2.0 + MathConstants<double>::pi;
}
void prepareToPlay (double sampleRate, int samplesPerBlock) override
{
currentSampleRate = sampleRate;
updateAngleDelta();
}
void processBlock (AudioBuffer<float>& buffer, MidiBuffer&) override
{
// ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();
for(auto i = 0; i < totalNumOutputChannels; i++)
{
buffer.clear (i, 0, buffer.getNumSamples());
auto* channelData = buffer.getWritePointer (i);
for (auto sample = 0; sample < buffer.getNumSamples(); sample++)
{
channelData[sample] = (float) std::sin(currentAngle) * 0.5;
currentAngle += angleDelta;
}
//Added this line to correct for sequential incrementing in outer for-loop, but sound artifacts persist...
currentAngle -= angleDelta * buffer.getNumSamples();
}
}
2.) When I attempt to manually access each output channel with separate getWritePointer calls, I don’t hear anything. I am 99% sure that I have exactly 2 output channels (I tried using the above code and only writing to the left and right channels respectively, and I only hear output in my left/right speakers), but for some reason when I try to manually create WritePointers with params 0, 1, I can’t seem to get output:
void updateAngleDelta()
{
auto cyclesPerSample = freq / currentSampleRate;
angleDelta = cyclesPerSample * 2.0 + MathConstants<double>::pi;
}
void prepareToPlay (double sampleRate, int samplesPerBlock) override
{
currentSampleRate = sampleRate;
updateAngleDelta();
}
void processBlock (AudioBuffer<float>& buffer, MidiBuffer&) override
{
// ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();
// for(auto i = 0; i < totalNumOutputChannels; i++)
//{
buffer.clear (0, 0, buffer.getNumSamples());
buffer.clear (1, 0, buffer.getNumSamples());
auto* channelDataL = buffer.getWritePointer (0);
auto* channelDataR = buffer.getWritePointer(1);
for (auto sample = 0; sample < buffer.getNumSamples(); sample++)
{
channelDataL[sample] = (float) std::sin(currentAngle) * 0.5;
channelDataR[sample] = (float) std::sin(currentAngle) * 0.5;
currentAngle += angleDelta;
}
// }
}
So to summarize, two-part question:
1.) Is my logic wrong in example 1?
2.) In example 2, is there a reason that in a plugin context I can’t manually create writePointers for each output Buffer rather than using a for-loop?
Thanks very much!