void JuceDemoPluginAudioProcessor::applyDelay (AudioBuffer<FloatType>& buffer, AudioBuffer<FloatType>& delayBuffer) { const int numSamples = buffer.getNumSamples(); const float delayLevel = *delayParam; int delayPos = 0; for (int channel = 0; channel < getNumInputChannels(); ++channel) { FloatType* const channelData = buffer.getWritePointer (channel); FloatType* const delayData = delayBuffer.getWritePointer (jmin (channel, delayBuffer.getNumChannels() - 1)); delayPos = delayPosition; for (int i = 0; i < numSamples; ++i) { const FloatType in = channelData[i]; channelData[i] += delayData[delayPos]; delayData[delayPos] = (delayData[delayPos] + in) * delayLevel; if (++delayPos >= delayBuffer.getNumSamples()) delayPos = 0; } } delayPosition = delayPos; }
void DaalDelAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages) { ScopedNoDenormals noDenormals; auto totalNumInputChannels = getTotalNumInputChannels(); auto totalNumOutputChannels = getTotalNumOutputChannels(); // 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). // This is here to avoid people getting screaming feedback // when they first compile a plugin, but obviously you don't need to keep // this code if your algorithm always overwrites all the output channels. for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i) buffer.clear (i, 0, buffer.getNumSamples()); // ==== // Lengths for circular buffer const int bufferLength = buffer.getNumSamples(); const int delayBufferLength = _delayBuffer.getNumSamples(); // This is the place where you'd normally do the guts of your plugin's // audio processing... // Make sure to reset the state if your inner loop is processing // the samples and the outer loop is handling the channels. // Alternatively, you can process the samples with the channels // interleaved by keeping the same state. for (int channel = 0; channel < totalNumInputChannels; ++channel) { //auto* channelData = buffer.getWritePointer (channel); // ..do something to the data... // Set up circular buffer const float* bufferData = buffer.getReadPointer(channel); const float* delayBufferData = _delayBuffer.getReadPointer(channel); float* dryBuffer = buffer.getWritePointer(channel); // Apply gains (now do this before getting from delay) applyDryWetToBuffer(buffer, channel, bufferLength, dryBuffer); // Copy data from main to delay buffer fillDelayBuffer(channel, bufferLength, delayBufferLength, bufferData, delayBufferData); // Copy data from delay buffer to output buffer getFromDelayBuffer(buffer, channel, bufferLength, delayBufferLength, bufferData, delayBufferData); // Feedback feedbackDelay(channel, bufferLength, delayBufferLength, dryBuffer); } _writePosition += bufferLength; // Increment _writePosition %= delayBufferLength; // Wrap around position index // Update values from tree updateTreeParams(); }
//============================================================================== void copyBufferToTemporaryLocation (const AudioBuffer<float>& buffer) { const SpinLock::ScopedLockType sl (processLock); auto numChannels = buffer.getNumChannels() > 1 ? 2 : 1; temporaryBuffer.setSize (numChannels, buffer.getNumSamples(), false, false, true); for (auto channel = 0; channel < numChannels; ++channel) temporaryBuffer.copyFrom (channel, 0, buffer, channel, 0, buffer.getNumSamples()); }
void processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages) override { Reverb::Parameters reverbParameters; reverbParameters.roomSize = roomSizeParam->get(); reverb.setParameters (reverbParameters); synth.renderNextBlock (buffer, midiMessages, 0, buffer.getNumSamples()); if (getMainBusNumOutputChannels() == 1) reverb.processMono (buffer.getWritePointer (0), buffer.getNumSamples()); else if (getMainBusNumOutputChannels() == 2) reverb.processStereo (buffer.getWritePointer (0), buffer.getWritePointer (1), buffer.getNumSamples()); }
void JuceDemoPluginAudioProcessor::process (AudioBuffer<FloatType>& buffer, MidiBuffer& midiMessages, AudioBuffer<FloatType>& delayBuffer) { const int numSamples = buffer.getNumSamples(); // apply our gain-change to the incoming data.. applyGain (buffer, delayBuffer); // Now pass any incoming midi messages to our keyboard state object, and let it // add messages to the buffer if the user is clicking on the on-screen keys keyboardState.processNextMidiBuffer (midiMessages, 0, numSamples, true); // and now get our synth to process these midi events and generate its output. synth.renderNextBlock (buffer, midiMessages, 0, numSamples); // Apply our delay effect to the new output.. applyDelay (buffer, delayBuffer); // In case we have more outputs than inputs, we'll clear any output // channels that didn't contain input data, (because these aren't // guaranteed to be empty - they may contain garbage). for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i) buffer.clear (i, 0, numSamples); // Now ask the host for the current time so we can store it to be displayed later... updateCurrentTimeInfoFromHost(); }
void JuceDemoPluginAudioProcessor::applyGain (AudioBuffer<FloatType>& buffer, AudioBuffer<FloatType>& delayBuffer) { ignoreUnused (delayBuffer); const float gainLevel = *gainParam; for (int channel = 0; channel < getNumInputChannels(); ++channel) buffer.applyGain (channel, 0, buffer.getNumSamples(), gainLevel); }
void VAOscillator::fillBufferSquarePulse(AudioBuffer<float>& buffer, AudioBuffer<float>& phaseModBuffer, AudioBuffer<float>& volumeModBuffer, AudioBuffer<float>& pitchModBuffer) { if(isActive) { float* const data = buffer.getWritePointer(0); float const *phaseMod = phaseModBuffer.getReadPointer(0); float const *volMod = volumeModBuffer.getReadPointer(0); float const *pitchMod = pitchModBuffer.getReadPointer(0); //write momentary phase values into the buffer for(int sampleIndex = 0; sampleIndex < buffer.getNumSamples(); sampleIndex++) { double phase = currentPhase + phaseModAmp * phaseMod[sampleIndex]; while (phase < 0) { phase += 2 * double_Pi; } while (phase > 2 * double_Pi) { phase -= 2 * double_Pi; } currentPhase += 2 * double_Pi * ((currentFrequency * (pitchMod[sampleIndex] + 2.0))/currentSampleRate); if(currentPhase > 2 * double_Pi) { currentPhase -= 2 * double_Pi; } if(phase < double_Pi) { data[sampleIndex] = -1; } else { data[sampleIndex] = 1; } data[sampleIndex] += getBlep(phase, currentFrequency); if(phase < double_Pi) { data[sampleIndex] -= getBlep(phase + double_Pi, currentFrequency); } if(phase > double_Pi) { data[sampleIndex] -= getBlep(phase - double_Pi, currentFrequency); } data[sampleIndex] *= (float)std::abs(0.5 * (volMod[sampleIndex] + 1)); } } else { buffer.clear(); } }// end square pulse
void VAOscillator::postFilter(AudioBuffer<float> buffer) { float* const data = buffer.getWritePointer(0); for(int sampleIndex = 0; sampleIndex < buffer.getNumSamples(); sampleIndex++) { postFilterState = (1/0.65) * data[sampleIndex]; data[sampleIndex] -= (float)((0.35/0.65) * postFilterState); } }
void VAOscillator::fillBufferTriangle(AudioBuffer<float>& buffer, AudioBuffer<float>& phaseModBuffer, AudioBuffer<float>& volumeModBuffer, AudioBuffer<float>& pitchModBuffer) { if(isActive) { float* const data = buffer.getWritePointer(0); float const *phaseMod = phaseModBuffer.getReadPointer(0); float const *volMod = volumeModBuffer.getReadPointer(0); float const *pitchMod = pitchModBuffer.getReadPointer(0); for(int sampleIndex = 0; sampleIndex < buffer.getNumSamples(); sampleIndex++) { double phase = currentPhase + phaseModAmp * phaseMod[sampleIndex]; while (phase < 0) { phase += 2 * double_Pi; } while (phase > 2 * double_Pi) { phase -= 2 * double_Pi; } currentPhase += 2 * double_Pi * ((currentFrequency * (pitchMod[sampleIndex] + 2.0))/currentSampleRate); if(currentPhase > 2 * double_Pi) { currentPhase -= 2 * double_Pi; } if(phase < double_Pi) { data[sampleIndex] = (float)((2 * phase)/double_Pi - 1); } else { data[sampleIndex] = (float)((3 - 2 * phase/double_Pi)); } //the 0.000026 is kind of a magic number i didnt calculate it just found it by trying out data[sampleIndex] += (float)(0.000026 * currentFrequency * getTriRes(phase, currentFrequency)); if(phase < double_Pi) { data[sampleIndex] -= (float)(0.000026 * currentFrequency * getTriRes(phase + double_Pi, currentFrequency)); } else if(phase >= double_Pi) { data[sampleIndex] -= (float)(0.000026 * currentFrequency * getTriRes(phase - double_Pi, currentFrequency)); } data[sampleIndex] *= (float)std::abs(0.5 * (volMod[sampleIndex] + 1)); } } else { buffer.clear(); } }// end triangle
MemoryAudioSource::MemoryAudioSource (AudioBuffer<float>& bufferToUse, bool copyMemory, bool shouldLoop) : isLooping (shouldLoop) { if (copyMemory) buffer.makeCopyOf (bufferToUse); else buffer.setDataToReferTo (bufferToUse.getArrayOfWritePointers(), bufferToUse.getNumChannels(), bufferToUse.getNumSamples()); }
void NoiseOscillator::fillBufferNoise(AudioBuffer<float> &buffer) { float* const data = buffer.getWritePointer(0); for(int sampleIndex = 0; sampleIndex < buffer.getNumSamples(); sampleIndex++) { data[sampleIndex] = (2 * rand.nextFloat()) - 1; } }
void perform (AudioBuffer<FloatType>& buffer, MidiBuffer& midiMessages, AudioPlayHead* audioPlayHead) { auto numSamples = buffer.getNumSamples(); auto maxSamples = renderingBuffer.getNumSamples(); if (numSamples > maxSamples) { // being asked to render more samples than our buffers have, so slice things up... tempMIDI.clear(); tempMIDI.addEvents (midiMessages, maxSamples, numSamples, -maxSamples); { AudioBuffer<FloatType> startAudio (buffer.getArrayOfWritePointers(), buffer.getNumChannels(), maxSamples); midiMessages.clear (maxSamples, numSamples); perform (startAudio, midiMessages, audioPlayHead); } AudioBuffer<FloatType> endAudio (buffer.getArrayOfWritePointers(), buffer.getNumChannels(), maxSamples, numSamples - maxSamples); perform (endAudio, tempMIDI, audioPlayHead); return; } currentAudioInputBuffer = &buffer; currentAudioOutputBuffer.setSize (jmax (1, buffer.getNumChannels()), numSamples); currentAudioOutputBuffer.clear(); currentMidiInputBuffer = &midiMessages; currentMidiOutputBuffer.clear(); { const Context context { renderingBuffer.getArrayOfWritePointers(), midiBuffers.begin(), audioPlayHead, numSamples }; for (auto* op : renderOps) op->perform (context); } for (int i = 0; i < buffer.getNumChannels(); ++i) buffer.copyFrom (i, 0, currentAudioOutputBuffer, i, 0, numSamples); midiMessages.clear(); midiMessages.addEvents (currentMidiOutputBuffer, 0, buffer.getNumSamples(), 0); currentAudioInputBuffer = nullptr; }
void VAOscillator::fillBufferSine(AudioBuffer<float>& buffer, AudioBuffer<float>& phaseModBuffer, AudioBuffer<float>& volumeModBuffer, AudioBuffer<float>& pitchModBuffer, Array<int>& midiOns)// add midi buffer and know channel with control Voltage { if(isActive) { float* const data = buffer.getWritePointer(0); float const *phaseMod = phaseModBuffer.getReadPointer(0); float const *volMod = volumeModBuffer.getReadPointer(0); float const *pitchMod = pitchModBuffer.getReadPointer(0); for(int sampleIndex = 0; sampleIndex < buffer.getNumSamples(); sampleIndex++) { //check if this is the best i can do if(midiOns.size() != 0) { if(sampleIndex == midiOns[0]) { resetPhase(); midiOns.remove(0); } } double phase = currentPhase + phaseModAmp * phaseMod[sampleIndex] + currentPhaseOffset; while (phase < 0) { phase += 2 * double_Pi; } while (phase > 2 * double_Pi) { phase -= 2 * double_Pi; } data[sampleIndex] = static_cast<float>(sin(phase) * std::abs(0.5 * (volMod[sampleIndex] + 1))); currentPhase += 2 * double_Pi * ((currentFrequency * (pitchMod[sampleIndex] + 2.0))/currentSampleRate); if(currentPhase > 2 * double_Pi) { currentPhase -= 2 * double_Pi; } } } else { buffer.clear(); } }// end sine
void VAOscillator::fillBufferFallingSaw(AudioBuffer<float>& buffer, AudioBuffer<float>& phaseModBuffer, AudioBuffer<float>& volumeModBuffer, AudioBuffer<float>& pitchModBuffer) { if(isActive) { fillBufferRisingSaw(buffer, phaseModBuffer, volumeModBuffer, pitchModBuffer); float* const data = buffer.getWritePointer(0); for(int sampleIndex = 0; sampleIndex < buffer.getNumSamples(); sampleIndex++) { data[sampleIndex] *= -1; } } else { buffer.clear(); } }// end falling Saw
bool AudioFormatWriter::writeFromAudioSampleBuffer (const AudioBuffer<float>& source, int startSample, int numSamples) { auto numSourceChannels = source.getNumChannels(); jassert (startSample >= 0 && startSample + numSamples <= source.getNumSamples() && numSourceChannels > 0); if (startSample == 0) return writeFromFloatArrays (source.getArrayOfReadPointers(), numSourceChannels, numSamples); const float* chans[256]; jassert ((int) numChannels < numElementsInArray (chans)); for (int i = 0; i < numSourceChannels; ++i) chans[i] = source.getReadPointer (i, startSample); chans[numSourceChannels] = nullptr; return writeFromFloatArrays (chans, numSourceChannels, numSamples); }
void VAOscillator::fillBufferRisingSaw(AudioBuffer<float>& buffer, AudioBuffer<float>& phaseModBuffer, AudioBuffer<float>& volumeModBuffer, AudioBuffer<float>& pitchModBuffer) { if(isActive) { float* const data = buffer.getWritePointer(0); float const *phaseMod = phaseModBuffer.getReadPointer(0); float const *volMod = volumeModBuffer.getReadPointer(0); float const *pitchMod = pitchModBuffer.getReadPointer(0); //write momentary phase values into the buffer for(int sampleIndex = 0; sampleIndex < buffer.getNumSamples(); sampleIndex++) { double phase = currentPhase + phaseModAmp * phaseMod[sampleIndex]; while (phase < 0) { phase += 2 * double_Pi; } while (phase > 2 * double_Pi) { phase -= 2 * double_Pi; } currentPhase += 2 * double_Pi * ((currentFrequency * (pitchMod[sampleIndex] + 2.0))/currentSampleRate); if(currentPhase > 2 * double_Pi) { currentPhase -= 2 * double_Pi; } data[sampleIndex] = (float)((2 * phase)/(2 * double_Pi) - 1); data[sampleIndex] += getBlep(phase , currentFrequency);// i have to watch out here because actually currentFrequency is not valid for this calculation data[sampleIndex] *= std::abs(0.5f * (volMod[sampleIndex] + 1)); } } else { buffer.clear(); } }// end rising Saw
// copy data from internal audio buffer to external audio buffer void AverageLevelFiltered::copyTo( AudioBuffer<float> &destination, const int numberOfSamples) { jassert(fftSampleBuffer_.getNumChannels() == destination.getNumChannels()); jassert(fftSampleBuffer_.getNumSamples() >= numberOfSamples); jassert(destination.getNumSamples() >= numberOfSamples); int numberOfChannels = fftSampleBuffer_.getNumChannels(); // copy data to external buffer for (int channel = 0; channel < numberOfChannels; ++channel) { destination.copyFrom(channel, 0, fftSampleBuffer_, channel, 0, numberOfSamples); } }
void PolyWavegeneratorProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& midiBuffer) { // clear all the midibuffers of the voices because they still contain the events from the last process Block for(int index = 0; index < voices.size(); index++) { voices[index]->clearMidiBuffer(); } // Midi and Voice Handler this is not correct yet i need to watch out for different note ons of the same note in one buffer and other stuff if(takesMidi && !midiBuffer.isEmpty()) { MidiMessage& message1 = *new MidiMessage(); ScopedPointer<MidiBuffer::Iterator> iterator = new MidiBuffer::Iterator(midiBuffer); int sampleInBuffer = 0; while(iterator->getNextEvent(message1, sampleInBuffer)) { if(message1.isNoteOn()) { // always take the first one and move it to the back => the oldest voice will be "overwritten" voices[0]->setIsOn(true); voices[0]->setMidiNote(message1.getNoteNumber()); voices[0]->addMidiEvent(message1, sampleInBuffer); voices.move(0, voices.size()-1); } else if(message1.isNoteOff()) { for(int index = 0; index < voices.size(); index++) { if(voices[index]->getMidiNote() == message1.getNoteNumber()) { ScopedPointer<Voice> tempVoice = voices[index]; tempVoice->setIsOn(false); tempVoice->addMidiEvent(message1, sampleInBuffer); tempVoice->setMidiNote(-1); // this should be removed but just in case for now break; } } } } } // Audio Handling of the voices AudioBuffer<float> outBuffer = getBusBuffer(buffer, false, 0); int numActive = 0; // eventually this could be a member variable for(int index = 0; index < voices.size(); index++) { if(voices[index]->getIsOn()) { numActive++; voices[index]->clearAudioBuffer(); voices[index]->fillBufferEnvelope(); voices[index]->fillBufferAudio(); outBuffer.addFrom(0, 0, voices[index]->getOutBuffer(), 0, 0, outBuffer.getNumSamples()); } } outBuffer.applyGain(1.0f/numActive); }
Result Upsampler::upsample(AudioBuffer<float> const &inputBuffer, int const inputChannel, AudioBuffer<float> &outputBuffer_, int const outputChannel, int &outputSampleCount_) { int outputSamplesNeeded = roundDoubleToInt( (outputSampleRate * inputBuffer.getNumSamples())/ inputSampleRate); if (outputBuffer_.getNumSamples() < outputSamplesNeeded) return Result::fail("Output buffer too small"); //DBG("upsample inputSampleCount:" << inputSampleCount); if (nullptr == resampler) return Result::fail("No resampler object"); // // Clear the resample and pump some initial zeros into it // resampler->clear(); #if 0 int preloadSamples = resampler->getInLenBeforeOutStart(MAX_RESAMPLER_INPUT_SAMPLES); inputBlockBuffer.clear(MAX_RESAMPLER_INPUT_SAMPLES); while (preloadSamples > 0) { int count = jmin((int)MAX_RESAMPLER_INPUT_SAMPLES, preloadSamples); double* outputBlock = nullptr; resampler->process(inputBlockBuffer, count, outputBlock); preloadSamples -= count; } #endif // // Flush the output buffer // outputBuffer_.clear(); // // Do the actual upsample // outputSampleCount_ = 0; int inputSampleCount = inputBuffer.getNumSamples(); const float * source = inputBuffer.getReadPointer(inputChannel); while (inputSampleCount > 0) { // // Convert float to double // int inputConvertCount = jmin(inputSampleCount, (int)MAX_RESAMPLER_INPUT_SAMPLES); for (int i = 0; i < inputConvertCount; ++i) { inputBlockBuffer[i] = *source; source++; } inputSampleCount -= inputConvertCount; // // Run the SRC // double* outputBlock = nullptr; int outputBlockSampleCount = resampler->process(inputBlockBuffer, inputConvertCount, outputBlock); int outputSpaceRemaining = outputBuffer_.getNumSamples() - outputSampleCount_; int outputCopyCount = jmin( outputSpaceRemaining, outputBlockSampleCount); float *destination = outputBuffer_.getWritePointer(outputChannel, outputSampleCount_); for (int i = 0; i < outputCopyCount; ++i) { *destination = (float)outputBlock[i]; destination++; } outputSampleCount_ += outputCopyCount; } // // Keep filling the output buffer // inputBlockBuffer.clear(MAX_RESAMPLER_INPUT_SAMPLES); while (outputSampleCount_ < outputBuffer_.getNumSamples()) { // // Run the SRC // double* outputBlock = nullptr; int outputBlockSampleCount = resampler->process(inputBlockBuffer, MAX_RESAMPLER_INPUT_SAMPLES, outputBlock); int outputSpaceRemaining = outputBuffer_.getNumSamples() - outputSampleCount_; int outputCopyCount = jmin( outputSpaceRemaining, outputBlockSampleCount); float *destination = outputBuffer_.getWritePointer(outputChannel, outputSampleCount_); for (int i = 0; i < outputCopyCount; ++i) { *destination = (float)outputBlock[i]; destination++; } outputSampleCount_ += outputCopyCount; } //DBG(" outputSampleCount:" << outputSampleCount); return Result::ok(); }
void AudioProcessor::processBypassed (AudioBuffer<floatType>& buffer, MidiBuffer&) { for (int ch = getMainBusNumInputChannels(); ch < getTotalNumOutputChannels(); ++ch) buffer.clear (ch, 0, buffer.getNumSamples()); }