COCKOS
CONFEDERATED FORUMS
Cockos : REAPER : NINJAM : Forums
Forum Home : Register : FAQ : Members List : Search :
Old 09-21-2014, 06:35 AM   #1
MezmerizeR
Human being with feelings
 
Join Date: Aug 2014
Posts: 12
Default SetBlockSize()

I have some kind of spectrum analyzer. When I plot the spectrum in Logic it is veeery slow. So now I have set the block size to something like 10 or so. It now gets updated fast, just like I wanted.

But then there seems to be the problem (I can only tell this case) that when I have two tracks routed to one bus and each has its own test oscillator and I have the spectrum plug on the bus, it crashes Logic.
I think it has to do with the block size. If I set it with GetBlockSize() it works fine I think.

Any ideas why this is? Or suggestions how I can update my GUI faster without changing the block size via IPlugBase::SetBlockSize() ?

Thanks,

MezmerizeR
MezmerizeR is offline   Reply With Quote
Old 09-21-2014, 11:22 PM   #2
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,057
Default

I don't think you should call SetBlockSize() yourself, it is called by the host to tell your plug-in about the maximum number of samples it will receive through ProcessDoubleReplacing().

Maybe you can change the GUI redraw speed via MakeGraphics() i.e.:

Code:
int fps = 24; // I think 24 is the default, so change this number.
IGraphics* pGraphics = MakeGraphics(this, 803, 447, fps);
Tale is offline   Reply With Quote
Old 09-22-2014, 04:25 AM   #3
MezmerizeR
Human being with feelings
 
Join Date: Aug 2014
Posts: 12
Default

Unfortunately this does not change the speed. At least not in my plug-in.

I found out that when I set the block size in the reset() function that the GUI redraws as fast as i want it to. But if I create a second track with the plug-in on it, then in crashes.

When I set the block size in the constructor and not in the reset() function it does no redrawing.

The whole thing is kind of strange.
MezmerizeR is offline   Reply With Quote
Old 09-22-2014, 06:07 AM   #4
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,057
Default

Quote:
Originally Posted by MezmerizeR View Post
Unfortunately this does not change the speed. At least not in my plug-in.
OK, my bad.

Quote:
Originally Posted by MezmerizeR View Post
I found out that when I set the block size in the reset() function that the GUI redraws as fast as i want it to. But if I create a second track with the plug-in on it, then in crashes.

When I set the block size in the constructor and not in the reset() function it does no redrawing.

The whole thing is kind of strange.
Again:

Quote:
Originally Posted by Tale View Post
I don't think you should call SetBlockSize() yourself, it is called by the host to tell your plug-in about the maximum number of samples it will receive through ProcessDoubleReplacing().
So I guess you will have to rethink your code, because the host determines the block size, not your plug-in. Note also that in some hosts the block size (nFrames) isn't constant.
Tale is offline   Reply With Quote
Old 09-22-2014, 06:46 AM   #5
MezmerizeR
Human being with feelings
 
Join Date: Aug 2014
Posts: 12
Default

Ok thank you for your help.

That's too bad because just setting the block size myself does exactly what I want, at least for one plugin on one track.

Maybe it's possible to call IsDirty more often? Or am I thinking in the wrong direction? Sorry, my prgramming knowledge is not that big. I do it in school for 2 years now. So audio programming is a complete new topic to me.
I'd be very grateful if you had more tips .
MezmerizeR is offline   Reply With Quote
Old 09-23-2014, 05:38 PM   #6
MezmerizeR
Human being with feelings
 
Join Date: Aug 2014
Posts: 12
Default

Has anybody an idea?

I really need your help. I still don't get it.
MezmerizeR is offline   Reply With Quote
Old 09-24-2014, 12:31 PM   #7
stw
Human being with feelings
 
stw's Avatar
 
Join Date: Apr 2012
Posts: 250
Default

I tried Tales suggestion and it behaves as expected. Did you implement the fps value in the plugs constructor?
Just for testing purpose set it down to 1 an watch if it works at all.
stw is offline   Reply With Quote
Old 09-24-2014, 04:15 PM   #8
MezmerizeR
Human being with feelings
 
Join Date: Aug 2014
Posts: 12
Default

No, it doesn't work. Here's the function that gets called in the constructor:

Code:
void SpectrumAnalyzer::CreateGraphics()
{
    int fps =1;
    IGraphics* pGraphics = MakeGraphics(this, kWidth, kHeight,fps);
    ...
   
    graph = new Graph(this, kGraph_X, kGraph_Y, kGraph_W, kGraph_H, kGraphDummy);
    graph->SetGraphVals(magFFT); 
    
    pGraphics->AttachControl(graph);
    ...

    AttachGraphics(pGraphics);
}
When I open the plug-in in Logic it draws a line and then it takes forever until something happens and then again forever.

So I now I shouldn't set the block size myself but what I also recognized if I do so, is that actually the spectrum isn't mirrored. But when I compile the plug as app then it does and I don't understand why. What is going wrong?

MezmerizeR
MezmerizeR is offline   Reply With Quote
Old 09-30-2014, 04:37 AM   #9
MezmerizeR
Human being with feelings
 
Join Date: Aug 2014
Posts: 12
Default

My header-file:

Code:
#ifndef __SPECTRUMANALYZER__
#define __SPECTRUMANALYZER__

#include "IPlug_include_in_plug_hdr.h"
#include "PeakEQ.h"
#include "fft.h"
#define WDL_FFT_REALSIZE 8
#define FFT_BUFFERSIZE 1024

class Graph : public IControl
{
public:
    Graph(IPlugBase* pPlug, int x, int y, int width, int height, int paramIdx);
    bool Draw(IGraphics* pGraphics);
    bool IsDirty(){return true;};
    void SetGraphVals(double* mag);
   
private:
    IPlugBase *m_pPlug;
    double * FFTmag;
};


class SpectrumAnalyzer : public IPlug
{
public:
    SpectrumAnalyzer(IPlugInstanceInfo instanceInfo);
    ~SpectrumAnalyzer();

    void Reset();
    void OnParamChange(int paramIdx);
    void ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames);
    double sinc(double x);
    bool IsDirty(){return true;};
    void FFT(double *in, int fftbuffersize);

private:
    void CreateParams();
    void CreateGraphics();
    void CreatePresets();
    double *mFreqVek;
    int mMaxIndex;
    Graph *graph;
    double *blackman;
    const double a0 = (1-0.16)/2;
    const double a1 = 1/2;
    const double a2 = 0.16/2;
    CPeakEQ	**peq;  
    int bins;
    WDL_FFT_COMPLEX *fftbuffer;
    WDL_FFT_COMPLEX *sortedbuffer;
    WDL_FFT_COMPLEX *unsortedbuffer;
    double magFFT[FFT_BUFFERSIZE];
    

};

#endif
My cpp-file:

Code:
#define MAXCHNS 8

const int kNumPrograms = 1;

enum EParams
{
    kGain = 0,
    kFreq,
    kQ,
    kGraphDummy,
    kNumParams
};

enum ELayout
{
    kWidth  = GUI_WIDTH,
    kHeight = GUI_HEIGHT,
    
    kGainX  = GUI_WIDTH/10,
    kGainY  = GUI_HEIGHT-GUI_HEIGHT/6,
    
    kFreqX  = 2*GUI_WIDTH/10,
    kFreqY  = GUI_HEIGHT-GUI_HEIGHT/6,
    
    kQX     = 3*GUI_WIDTH/10,
    kQY     = GUI_HEIGHT-GUI_HEIGHT/6,
    
    kKnobFrames = 60,
    
    kGraph_X = 50,
    kGraph_Y = 0,
    kGraph_W = GUI_WIDTH -2*kGraph_X,
    kGraph_H = GUI_HEIGHT/2,
};

typedef struct {
    const char* name;
    const int x;
    const int y;
    const double defaultVal;
    const double minVal;
    const double maxVal;
    const double stepSize;
} parameterProperties_struct;

const parameterProperties_struct parameterProperties[kNumParams] =
{
    {.name = "Gain",        .x = kGainX, .y = kGainY, .defaultVal = 0.0,    .minVal = -24.0,    .maxVal = 24.0,     .stepSize = 0.25},
    {.name = "Frequency",   .x = kFreqX, .y = kFreqY, .defaultVal = -57.0,  .minVal = 0.0,      .maxVal = 123.0                     },
    {.name = "Q-Factor",    .x = kQX,    .y = kQY,    .defaultVal = 1.0,    .minVal = 0.25,     .maxVal = 4.0,      .stepSize = 0.125}
};



SpectrumAnalyzer::SpectrumAnalyzer(IPlugInstanceInfo instanceInfo)
:	IPLUG_CTOR(kNumParams, kNumPrograms, instanceInfo)
{

    TRACE;

    CreateParams();
    CreateGraphics();
    CreatePresets();
    WDL_fft_init();

}

SpectrumAnalyzer::~SpectrumAnalyzer() 
{
    for (int kk = 0; kk < MAXCHNS; kk++)
    {
        delete peq[kk]; // destroy the EQs
        peq[kk] = 0;
    }
    delete[] peq; 
    peq = 0;
    delete[] mFreqVek;
    mFreqVek = 0;
    delete [] unsortedbuffer;
    delete [] sortedbuffer;
    delete [] fftbuffer;
    delete [] blackman;
}

void SpectrumAnalyzer::ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
    // Mutex is already locked for us.

    bool bInputConnected;

    for (int cc = 0; cc < MAXCHNS; cc++)
    {
        bInputConnected = IsInChannelConnected(cc);
        if (bInputConnected) 
        {
            double *in = inputs[cc];
            double *out = outputs[cc];

            peq[cc]->processSamples(in, out, nFrames);
            
            FFT(in, FFT_BUFFERSIZE);
            
        }
    }
}

void SpectrumAnalyzer::Reset()
{
    TRACE;
    IMutexLock lock(this);
    for (int cc = 0; cc < MAXCHNS;cc++)
    {
        peq[cc]->reset();
    }

}

void SpectrumAnalyzer::OnParamChange(int paramIdx)
{
    IMutexLock lock(this);
    //  double fs = GetSampleRate();

    double Gain, Freq, Q;
    int index;
    switch (paramIdx)
    {
        case kGain:
        Gain = GetParam(kGain)->Value();
        for (int cc = 0; cc < MAXCHNS;cc++)
        {
            peq[cc]->setGain(Gain);
        }
        break;
            
        case kFreq:
        index = GetParam(kFreq)->Value();
        Freq = mFreqVek[index];
        for (int cc = 0; cc < MAXCHNS;cc++)
        {
            peq[cc]->setFreq(Freq);
        }
        break;
            
        case kQ:
        Q = GetParam(kQ)->Value();
        for (int cc = 0; cc < MAXCHNS;cc++)
        {
            peq[cc]->setQFactor(Q);
        }
        break;

        default:
        break;
    }
}

double SpectrumAnalyzer::sinc(double x)
{
    if(x == 0)
    {
        return 1;
    }
    return sin(PI*x)/(PI*x);
}



void SpectrumAnalyzer::FFT(double *in, int fftbuffersize)
{
    static int qq = 0;



    if (qq==fftbuffersize)
    {
        WDL_fft(fftbuffer, fftbuffersize, false);

        for (int i = 0; i < fftbuffersize; i++)
        {
            int j = WDL_fft_permute(fftbuffersize, i);
            
            blackman[i] =  (a0 - a1*cos((2*M_PI*i)/(fftbuffersize-1)) + a2*cos((4*M_PI*i)/(fftbuffersize-1)));
            
            sortedbuffer[i].re = fftbuffer[j].re ;
            
            sortedbuffer[i].im = fftbuffer[j].im ;
            
            magFFT[i] = ((sqrt(sortedbuffer[i].re*sortedbuffer[i].re + sortedbuffer[i].im*sortedbuffer[i].im)));
            
        }
        
        qq=0;
        
    }
    
    fftbuffer[qq].re = *in ;
    
    fftbuffer[qq].im = 0 ;

    qq++;

}


Graph::Graph(IPlugBase *pPlug, int x, int y, int width, int height, int paramIdx)
: IControl(pPlug, IRECT(x,y,width,height))
{
    mPlug = pPlug;
}

bool Graph::Draw(IGraphics *pGraphics)
{
    double mag = 0 ,x = kGraph_X;
    int bins = FFT_BUFFERSIZE/2;

    for (int i=0; i<bins; i++)
    {
        if (FFTmag[i] > double(kGraph_H)/2.)
        {
            mag = double(kGraph_H)/2.;
        }
        else
        {
            mag = FFTmag[i];
        }

        pGraphics->DrawLine(    &COLOR_BLACK,
                                x,              //x1
                                kGraph_Y+kGraph_H-FFTmag[i],       //y1
                                x + double(kGraph_W)/double(bins) ,              //x2
                                kGraph_Y+kGraph_H-FFTmag[i+1]   // y2
                            );
        x= x + double(kGraph_W)/double(bins);
    }
    return true;
}

void Graph::SetGraphVals(double* mag)
{
    FFTmag = mag;
}


void SpectrumAnalyzer::CreateParams()
{
    bins = FFT_BUFFERSIZE/2;
    fftbuffer = new WDL_FFT_COMPLEX[FFT_BUFFERSIZE];
    sortedbuffer = new WDL_FFT_COMPLEX[FFT_BUFFERSIZE];
    unsortedbuffer = new WDL_FFT_COMPLEX[FFT_BUFFERSIZE];
    blackman = new double[FFT_BUFFERSIZE];
    
    mMaxIndex = 124;
    mFreqVek = new double[mMaxIndex];
    int LowestSemitone = -57;
    int HighestSemitone = 66;
    double StandardPitchFreq = 440.;
    
    for (int kk = LowestSemitone; kk <= HighestSemitone ;kk++)
    {
        mFreqVek[kk-LowestSemitone] = StandardPitchFreq*pow(2,double(kk)/12.);
    }
    
    for (int i=0;i<FFT_BUFFERSIZE;i++)  //initialize buffer
    {
        magFFT[i]=0;
    }
    
    for (int i = 0; i<kNumParams; i++)
    {
        IParam *param = GetParam(i);
        const parameterProperties_struct& properties = parameterProperties[i];
        switch (i) {
           
            case kGain:
                param->InitDouble(properties.name, properties.defaultVal, properties.minVal, properties.maxVal, properties.stepSize);
                param->SetShape(1.);
                break;
           
            case kFreq:
                param->InitInt(properties.name, properties.defaultVal, properties.minVal, properties.maxVal);
                break;
            
            case kQ:
                param->InitDouble(properties.name, properties.defaultVal, properties.minVal, properties.maxVal, properties.stepSize);
                param->SetShape(2.);
                break;
           
            default:
                break;
        }
        
    }
    for (int i; i<kNumParams; i++) {
        OnParamChange(i);
    }
        
    double Gain = 00;
    double Freq = 1000;
    double Q = 1;
    double fs = GetSampleRate();
    
    // Multi-Channel EQ
    peq = new CPeakEQ*[MAXCHNS];
    
    for (int kk = 0; kk < MAXCHNS; kk++)
    {
        peq[kk] = new CPeakEQ(Gain,Freq,fs,Q);
    }
    
}

void SpectrumAnalyzer::CreateGraphics()
{
    int fps =25;
    IGraphics* pGraphics = MakeGraphics(this, kWidth, kHeight,fps);
    
    pGraphics->AttachPanelBackground(&COLOR_WHITE);

    IBitmap knob = pGraphics->LoadIBitmap(KNOB_ID, KNOB_FN, kKnobFrames);
    
    graph = new Graph(this, kGraph_X, kGraph_Y, kGraph_W, kGraph_H, kGraphDummy);
    
    graph->SetGraphVals(magFFT);
    
    pGraphics->AttachControl(graph);
    
    pGraphics->AttachControl(new IKnobMultiControl(this, kGainX, kGainY, kGain, &knob));
    
    pGraphics->AttachControl(new IKnobMultiControl(this, kFreqX, kFreqY, kFreq, &knob));
    
    pGraphics->AttachControl(new IKnobMultiControl(this, kQX, kQY, kQ, &knob));

    AttachGraphics(pGraphics);
}

void SpectrumAnalyzer::CreatePresets()
{
    //MakePreset("preset 1", ... );
    MakeDefaultPreset((char *) "-", kNumPrograms);
}
MezmerizeR is offline   Reply With Quote
Old 04-11-2017, 12:12 AM   #10
Lex248
Human being with feelings
 
Join Date: Apr 2017
Location: Russia
Posts: 18
Default

Wrong:

: IControl(pPlug, IRECT(x,y,width,height))


Has to be so:

: IControl(pPlug, IRECT(x, y , x + width, y + height))
Lex248 is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 05:57 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2020, vBulletin Solutions Inc.