Skip to content

Commit

Permalink
Fix memory leak. Store voices in std::list.
Browse files Browse the repository at this point in the history
  • Loading branch information
chirs241097 committed Mar 27, 2017
1 parent 70a157a commit 9ee0865
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 57 deletions.
12 changes: 9 additions & 3 deletions Synthesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ enum ELayout
Synthesis::Synthesis(IPlugInstanceInfo instanceInfo)
: IPLUG_CTOR(kNumParams, kNumPrograms, instanceInfo),
lastVirtualKeyboardNoteNumber(virtualKeyboardMinimumNoteNumber - 1) {

_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
TRACE;

IGraphics* pGraphics = MakeGraphics(this, kWidth, kHeight);
Expand Down Expand Up @@ -267,8 +267,14 @@ void Synthesis::ProcessDoubleReplacing(double** inputs, double** outputs, int nF
*/

// don't alloc new mem space every time we call ProcessDoubleReplacing. Will faster?
if (ori_l == nullptr || sizeof(*ori_l) != nFrames * sizeof(double)) ori_l = (double*)malloc(nFrames * sizeof(double));
if (ori_r == nullptr || sizeof(*ori_r) != nFrames * sizeof(double)) ori_r = (double*)malloc(nFrames * sizeof(double));
if (ori_l == nullptr || sizeof(*ori_l) < nFrames * sizeof(double)) {
if (ori_l) {free(ori_l); ori_l = nullptr;}
ori_l = (double*)malloc(nFrames * sizeof(double));
}
if (ori_r == nullptr || sizeof(*ori_r) < nFrames * sizeof(double)) {
if(ori_r) { free(ori_r); ori_r = nullptr; }
ori_r = (double*)malloc(nFrames * sizeof(double));
}

double *leftOutput = outputs[0];
double *rightOutput = outputs[1];
Expand Down
6 changes: 5 additions & 1 deletion Synthesis.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#ifndef __SYNTHESIS__
#define __SYNTHESIS__

//Memory leakage debugging
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
//end of memory leakage debugging
#include "IPlug_include_in_plug_hdr.h"
#include "MIDIReceiver.h"
#include "ADSRVisualizationControl.h"
Expand Down
132 changes: 84 additions & 48 deletions VoiceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@

Voice* VoiceManager::findFreeVoice() {
Voice* freeVoice = NULL;
for (int i = 0; i < NumberOfVoices; i++) {
if (!voices[i].isActive) {
freeVoice = &(voices[i]);
break;
}
if (voices.size()<NumberOfVoices)
{
freeVoice=new Voice();
voices.push_back(freeVoice);
}
return freeVoice;
}
Expand All @@ -18,6 +17,26 @@ void VoiceManager::onNoteOn(int channel, int noteNumber, int velocity) {
return;
}
voice->reset();
voice->mOscillatorMix=oscmix;
voice->mFilter.setCutoff(fltcutoff);
voice->mFilter.setResonance(fltreso);
voice->mFilterEnvelopeAmount=fltamt;
voice->mAmpEnvelopeAmount=ampamt;
voice->mOscillator1.setMode(oscmod[0]);
voice->mOscillator2.setMode(oscmod[1]);
voice->mFilter.setFilterMode(fltmod);
for(int i=0;i<EnvelopeGenerator::EnvelopeStage::kNumEnvelopeStages;++i)
{
voice->mAmpEnvelope.setStageValue((EnvelopeGenerator::EnvelopeStage)i,ampenv[i]);
voice->mFilterEnvelope.setStageValue((EnvelopeGenerator::EnvelopeStage)i,fltenv[i]);
}
voice->mCentOffset1=oscfine[0];
voice->mCentOffset2=oscfine[1];
voice->mSemiOffset1=osccoarse[0];
voice->mSemiOffset2=osccoarse[1];
voice->mOscillator1.setBitCrusher(bcrush);
voice->mOscillator2.setBitCrusher(bcrush);
voice->setPhaseStart(bpstart);
voice->setChannel(channel);
voice->setPBAmount(pbendRange * MIDIReceiver::getReference()->getPitchBendAmount(channel));
voice->setNoteNumber(noteNumber);
Expand All @@ -29,126 +48,143 @@ void VoiceManager::onNoteOn(int channel, int noteNumber, int velocity) {

void VoiceManager::onNoteOff(int channel, int noteNumber, int velocity) {
// Find the voice(s) with the given noteNumber:
for (int i = 0; i < NumberOfVoices; i++) {
Voice& voice = voices[i];
if (voice.isActive && voice.mNoteNumber == noteNumber) {
voice.mAmpEnvelope.enterStage(EnvelopeGenerator::ENVELOPE_STAGE_RELEASE);
voice.mFilterEnvelope.enterStage(EnvelopeGenerator::ENVELOPE_STAGE_RELEASE);
for (auto i = voices.begin(); i != voices.end(); i++) {
Voice* voice = *i;
if (voice->isActive && voice->mNoteNumber == noteNumber) {
voice->mAmpEnvelope.enterStage(EnvelopeGenerator::ENVELOPE_STAGE_RELEASE);
voice->mFilterEnvelope.enterStage(EnvelopeGenerator::ENVELOPE_STAGE_RELEASE);
}
}
}

void VoiceManager::onPbChanged()
{
for(int i = 0; i < NumberOfVoices; i++) {
if(voices[i].isActive)
voices[i].setPBAmount(pbendRange * MIDIReceiver::getReference()->getPitchBendAmount(voices[i].channel()));
for(auto i = voices.begin(); i != voices.end(); i++) {
if((*i)->isActive)
(*i)->setPBAmount(pbendRange * MIDIReceiver::getReference()->getPitchBendAmount((*i)->channel()));
}
}

double VoiceManager::nextSample() {
double output = 0.0;
for (int i = 0; i < NumberOfVoices; i++) {
Voice& voice = voices[i];
output += voice.nextSample();
for(auto i = voices.begin(); i != voices.end(); ) {
Voice* voice = *i;
output += voice->nextSample();
if(!voice->isActive) {
delete *i;auto t=i;++t;
voices.erase(i);i=t;
} else ++i;
}
return output;
}

// Setting attributes
void VoiceManager::setFilterCutoffForEachVoice(double newCutoff) {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].mFilter.setCutoff(newCutoff);
fltcutoff=newCutoff;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->mFilter.setCutoff(newCutoff);
}
}

void VoiceManager::setFilterResonanceForEachVoice(double newResonance) {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].mFilter.setResonance(newResonance);
fltreso=newResonance;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->mFilter.setResonance(newResonance);
}
}

void VoiceManager::setOscillatorModeForEachVoice(int oscID, Oscillator::OscillatorMode mode) {
oscmod[oscID-1]=mode;
if (oscID == 1) {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].mOscillator1.setMode(mode);
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->mOscillator1.setMode(mode);
}
} else { // osc2
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].mOscillator2.setMode(mode);
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->mOscillator2.setMode(mode);
}
}

}

void VoiceManager::setOscillatorMixForEachVoice(double mix) {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].setOscillatorMix(mix);
oscmix=mix;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->setOscillatorMix(mix);
}
}

void VoiceManager::setFilterModeForEachVoice(Filter::FilterMode mode) {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].mFilter.setFilterMode(mode);
fltmod=mode;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->mFilter.setFilterMode(mode);
}
}

void VoiceManager::setAmpEnvStageValueForEachVoice(EnvelopeGenerator::EnvelopeStage stage, double value) {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].mAmpEnvelope.setStageValue(stage, value);
ampenv[stage]=value;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->mAmpEnvelope.setStageValue(stage, value);
}
}

void VoiceManager::setFilterEnvStageValueForEachVoice(EnvelopeGenerator::EnvelopeStage stage, double value) {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].mFilterEnvelope.setStageValue(stage, value);
fltenv[stage]=value;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->mFilterEnvelope.setStageValue(stage, value);
}
}

void VoiceManager::setFilterAmountForEachVoice(double amount) {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].mFilterEnvelopeAmount = amount;
fltamt=amount;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->mFilterEnvelopeAmount = amount;
}
}

void VoiceManager::setAmpAmountForEachVoice(double amount) {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].mAmpEnvelopeAmount = amount;
ampamt=amount;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->mAmpEnvelopeAmount = amount;
}
}

void VoiceManager::setSemiOffsetForEachVoice(int oscID, int semi) {
osccoarse[oscID-1]=semi;
if (oscID == 1) {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].mSemiOffset1 = semi;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->mSemiOffset1 = semi;
}
} else {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].mSemiOffset2 = semi;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->mSemiOffset2 = semi;
}
}
}

void VoiceManager::setCentOffsetForEachVoice(int oscID, int cent) {
oscfine[oscID-1]=cent;
if (oscID == 1) {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].mCentOffset1 = cent;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->mCentOffset1 = cent;
}
} else {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].mCentOffset2 = cent;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->mCentOffset2 = cent;
}
}
}

void VoiceManager::setBitCrusherEnabledForEachVoice(bool enabled) {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].setOscillatorBitCrusher(enabled);
bcrush=enabled;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->setOscillatorBitCrusher(enabled);
}
}

void VoiceManager::setPhaseStartForEachVoice(bool enabled) {
for (int i = 0; i < NumberOfVoices; i++) {
voices[i].setPhaseStart(enabled);
bpstart=enabled;
for(auto i = voices.begin(); i != voices.end(); i++) {
(*i)->setPhaseStart(enabled);
}
}
38 changes: 33 additions & 5 deletions VoiceManager.h
Original file line number Diff line number Diff line change
@@ -1,24 +1,52 @@
#pragma once

#include <list>
#include "Voice.h"

class VoiceManager {
private:
int NumberOfVoices = 64; // need a static const?
Voice voices[64]; // Max voice count: 64
std::list<Voice*> voices; // Max voice count: 64
Voice* findFreeVoice();
int pbendRange = 2;
double
oscmix=.0,
fltcutoff=0.99,
fltreso=0.01,
fltamt=.0,
ampamt=50.;
Oscillator::OscillatorMode oscmod[2]={
Oscillator::OscillatorMode::OSCILLATOR_MODE_SINE,
Oscillator::OscillatorMode::OSCILLATOR_MODE_SINE
};
Filter::FilterMode fltmod=Filter::FilterMode::FILTER_MODE_LOWPASS;
double ampenv[EnvelopeGenerator::EnvelopeStage::kNumEnvelopeStages]={
.0,
.01,
.5,
.1,
1.
},
fltenv[EnvelopeGenerator::EnvelopeStage::kNumEnvelopeStages]={
.0,
.01,
.5,
.1,
1.
};
int oscfine[2]={0,0},osccoarse[2]={0,0};
bool bcrush=false,bpstart=false;
public:
void onNoteOn(int channel, int noteNumber, int velocity);
void onNoteOff(int channel, int noteNumber, int velocity);
void onPbChanged();
double nextSample();
void setSampleRate(double sampleRate) {
EnvelopeGenerator::setSampleRate(sampleRate);
for (int i = 0; i < NumberOfVoices; i++) {
Voice& voice = voices[i];
voice.mOscillator1.setSampleRate(sampleRate);
voice.mOscillator2.setSampleRate(sampleRate);
for (auto i = voices.begin(); i != voices.end(); i++) {
Voice* voice = *i;
voice->mOscillator1.setSampleRate(sampleRate);
voice->mOscillator2.setSampleRate(sampleRate);
}
}
void setPBRange(int pbr) { pbendRange=pbr; }
Expand Down

0 comments on commit 9ee0865

Please sign in to comment.