Skip to content

Commit

Permalink
Windowingstub: I'm not sure why I fixed this up (current DfxPlugin in…
Browse files Browse the repository at this point in the history
…terfaces + basic modernization), but I did
  • Loading branch information
sophiapoirier committed Feb 26, 2022
1 parent 49b122f commit 8ad6778
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 108 deletions.
115 changes: 37 additions & 78 deletions windowingstub/windowingstub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@

#include "windowingstub.h"

#include <stdio.h>
#include <algorithm>
#include <array>
#include <cmath>
#include <cstdio>

#if defined(TARGET_API_VST) && TARGET_PLUGIN_HAS_GUI
#ifndef _DFX_WINDOWINGSTUBEDITOR_H
#include "windowingstubeditor.hpp"
#endif
#endif

/* this macro does boring entry point stuff for us */
Expand All @@ -23,22 +24,21 @@ PLUGIN::PLUGIN(TARGET_API_BASE_INSTANCE_TYPE inInstance)
initparameter_indexed(P_BUFSIZE, {"wsize"}, 9, 9, BUFFERSIZESSIZE, kDfxParamUnit_samples);
initparameter_indexed(P_SHAPE, {"wshape"}, WINDOW_TRIANGLE, WINDOW_TRIANGLE, MAX_WINDOWSHAPES);

long i;
/* set up values for windowing */
char bufstr[64];
for (i=0; i < BUFFERSIZESSIZE; i++) {
for (long i = 0; i < BUFFERSIZESSIZE; i++) {
std::array<char, 64> bufstr {};
if (buffersizes[i] > 1000)
sprintf(bufstr, "%ld,%03ld", buffersizes[i]/1000, buffersizes[i]%1000);
snprintf(bufstr.data(), bufstr.size(), "%ld,%03ld", buffersizes[i] / 1000, buffersizes[i] % 1000);
else
sprintf(bufstr, "%ld", buffersizes[i]);
setparametervaluestring(P_BUFSIZE, i, bufstr);
snprintf(bufstr.data(), bufstr.size(), "%ld", buffersizes[i]);
setparametervaluestring(P_BUFSIZE, i, bufstr.data());
}

setparametervaluestring(P_SHAPE, WINDOW_TRIANGLE, "linear");
setparametervaluestring(P_SHAPE, WINDOW_ARROW, "arrow");
setparametervaluestring(P_SHAPE, WINDOW_WEDGE, "wedge");
setparametervaluestring(P_SHAPE, WINDOW_COS, "best");
for (i=NUM_WINDOWSHAPES; i < MAX_WINDOWSHAPES; i++)
for (long i = NUM_WINDOWSHAPES; i < MAX_WINDOWSHAPES; i++)
setparametervaluestring(P_SHAPE, i, "???");

long delay_samples = buffersizes[getparameter_i(P_BUFSIZE)];
Expand All @@ -49,52 +49,25 @@ PLUGIN::PLUGIN(TARGET_API_BASE_INSTANCE_TYPE inInstance)
makepresets();

/* allow MIDI keys to be used to control parameters */
dfxsettings->setAllowPitchbendEvents(true);
dfxsettings->setAllowNoteEvents(true);
getsettings()->setAllowPitchbendEvents(true);
getsettings()->setAllowNoteEvents(true);

#if !TARGET_PLUGIN_USES_DSPCORE
addchannelconfig(1, 1); /* mono */
#endif

#ifdef TARGET_API_VST
/* if you have a GUI, need an Editor class... */
#if TARGET_PLUGIN_HAS_GUI
editor = new WindowingstubEditor(this);
#endif
#endif
}

PLUGIN::~PLUGIN() {

#ifdef TARGET_API_VST
/* VST doesn't have initialize and cleanup methods like Audio Unit does,
so we need to call this manually here */
do_cleanup();
#endif
}

PLUGINCORE::PLUGINCORE(DfxPlugin * inInstance)
: DfxPluginCore(inInstance) {
/* determine the size of the largest window size */
long maxframe = 0;
for (int i = 0; i < BUFFERSIZESSIZE; i++)
maxframe = (buffersizes[i] > maxframe) ? buffersizes[i] : maxframe;
auto const maxframe = *std::max_element(std::cbegin(buffersizes), std::cend(buffersizes));

/* add some leeway? */
in0 = (float*)malloc(maxframe * sizeof (float));
out0 = (float*)malloc(maxframe * 2 * sizeof (float));
in0.assign(maxframe, 0.f);
out0.assign(maxframe * 2, 0.f);

/* prevmix is only a single third long */
prevmix = (float*)malloc((maxframe / 2) * sizeof (float));
}


PLUGINCORE::~PLUGINCORE() {
/* windowing buffers */
free (in0);
free (out0);

free (prevmix);
prevmix.assign(maxframe / 2, 0.f);
}

void PLUGINCORE::reset() {
Expand All @@ -104,24 +77,20 @@ void PLUGINCORE::reset() {
bufsize = third * 3;

/* set up buffers. Prevmix and first frame of output are always
filled with zeros. XXX memset */
filled with zeros. */

for (int i = 0; i < third; i ++) {
prevmix[i] = 0.0f;
}

for (int j = 0; j < framesize; j ++) {
out0[j] = 0.0f;
}
std::fill_n(prevmix.begin(), third, 0.f);
std::fill_n(out0.begin(), framesize, 0.f);

/* start input at beginning. Output has a frame of silence. */
insize = 0;
outstart = 0;
outsize = framesize;

dfxplugin->setlatency_samples(framesize);
getplugin()->setlatency_samples(framesize);
/* tail is the same as delay, of course */
dfxplugin->settailsize_samples(framesize);
getplugin()->settailsize_samples(framesize);
}

void PLUGINCORE::processparameters() {
Expand All @@ -132,18 +101,17 @@ void PLUGINCORE::processparameters() {
/* this tells the host to call a suspend()-resume() pair,
which updates initialDelay value */
if (getparameterchanged(P_BUFSIZE))
dfxplugin->setlatencychanged(true);
getplugin()->setlatencychanged(true);
#endif
}

/* this processes an individual window. Basically, this is where you
write your DSP, and it will be always called with the same sample
size (as long as the block size parameter stays the same) and
automatically overlapped. */
void PLUGINCORE::processw(float * in, float * out, long samples) {
void PLUGINCORE::processw(float const * in, float * out, long samples) {

memmove(out, in, samples * sizeof (float));

}


Expand Down Expand Up @@ -172,58 +140,55 @@ void PLUGINCORE::processw(float * in, float * out, long samples) {
*/

/* to improve:
- use memcpy and arithmetic instead of
sample-by-sample copy
- can we use tail of out0 as prevmix, instead of copying?
- can we use circular buffers instead of memmoving a lot?
(probably not)
*/


void PLUGINCORE::process(const float *tin, float *tout, unsigned long samples, bool replacing) {
int z = 0;
void PLUGINCORE::process(float const *tin, float *tout, unsigned long samples) {

for (unsigned long ii = 0; ii < samples; ii++) {
for (unsigned long i = 0; i < samples; i++) {

/* copy sample in */
in0[insize] = tin[ii];
in0[insize] = tin[i];
insize ++;

if (insize == framesize) {
/* frame is full! */

/* in0 -> process -> out0(first free space) */
processw(in0, out0+outstart+outsize, framesize);
processw(in0.data(), out0.data()+outstart+outsize, framesize);

float oneDivThird = 1.0f / (float)third;
/* apply envelope */

switch(shape) {

case WINDOW_TRIANGLE:
for(z = 0; z < third; z++) {
for(int z = 0; z < third; z++) {
out0[z+outstart+outsize] *= ((float)z * oneDivThird);
out0[z+outstart+outsize+third] *= (1.0f - ((float)z * oneDivThird));
}
break;
case WINDOW_ARROW:
for(z = 0; z < third; z++) {
for(int z = 0; z < third; z++) {
float p = (float)z * oneDivThird;
p *= p;
out0[z+outstart+outsize] *= p;
out0[z+outstart+outsize+third] *= (1.0f - p);
}
break;
case WINDOW_WEDGE:
for(z = 0; z < third; z++) {
float p = sqrtf((float)z * oneDivThird);
for(int z = 0; z < third; z++) {
float p = std::sqrt((float)z * oneDivThird);
out0[z+outstart+outsize] *= p;
out0[z+outstart+outsize+third] *= (1.0f - p);
}
break;
case WINDOW_COS:
for(z = 0; z < third; z ++) {
float p = 0.5f * (-cosf(PI * ((float)z * oneDivThird)) + 1.0f);
for(int z = 0; z < third; z ++) {
float p = 0.5f * (-std::cos(PI * ((float)z * oneDivThird)) + 1.0f);
out0[z+outstart+outsize] *= p;
out0[z+outstart+outsize+third] *= (1.0f - p);
}
Expand All @@ -235,32 +200,26 @@ void PLUGINCORE::process(const float *tin, float *tout, unsigned long samples, b
out0[u+outstart+outsize] += prevmix[u];

/* prevmix becomes out1 */
memcpy(prevmix, out0 + outstart + outsize + third, third * sizeof (float));
std::copy_n(std::next(out0.cbegin(), outstart + outsize + third), third, prevmix.begin());

/* copy 2nd third of input over in0 (need to re-use it for next frame),
now insize = third */
memcpy(in0, in0 + third, third * sizeof (float));
std::copy_n(std::next(in0.cbegin(), third), third, in0.begin());

insize = third;

outsize += third;
}

/* send sample out */
#ifdef TARGET_API_VST
if (replacing)
#endif
tout[ii] = out0[outstart];
#ifdef TARGET_API_VST
else tout[ii] += out0[outstart];
#endif
tout[i] = out0[outstart];

outstart ++;
outsize --;

/* make sure there is always enough room for a frame in out buffer */
if (outstart == third) {
memmove(out0, out0 + outstart, outsize * sizeof (float));
memmove(out0.data(), out0.data() + outstart, outsize * sizeof (float));
outstart = 0;
}
}
Expand Down
53 changes: 25 additions & 28 deletions windowingstub/windowingstub.h
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@

/* Windowingstub, starring the Super Destroy FX Windowing System! */

#ifndef _DFX_WINDOWINGSTUB_H
#define _DFX_WINDOWINGSTUB_H
#pragma once

#include "dfxplugin.h"

#include <vector>

/* change these for your plugins */
#define PLUGIN Windowingstub
#define NUM_PRESETS 16
#define PLUGINCORE WindowingstubDSP

#define BUFFERSIZESSIZE 14
const long buffersizes[BUFFERSIZESSIZE] = {

static constexpr long buffersizes[] = {
4, 8, 16, 32, 64, 128, 256, 512,
1024, 2048, 4096, 8192, 16384, 32768,
};


#define PLUGINCORE WindowingstubDSP
static constexpr long BUFFERSIZESSIZE = std::size(buffersizes);

/* the types of window shapes available for smoothity */
enum { WINDOW_TRIANGLE,
Expand All @@ -34,55 +33,53 @@ enum { P_BUFSIZE, P_SHAPE,
};


class PLUGIN : public DfxPlugin {
class PLUGIN final : public DfxPlugin {
public:
PLUGIN(TARGET_API_BASE_INSTANCE_TYPE inInstance);
virtual ~PLUGIN();
explicit PLUGIN(TARGET_API_BASE_INSTANCE_TYPE inInstance);

private:
static constexpr long NUM_PRESETS = 16;

/* set up the built-in presets */
void makepresets();
};

class PLUGINCORE : public DfxPluginCore {
class PLUGINCORE final : public DfxPluginCore {
public:
PLUGINCORE(DfxPlugin * inInstance);
virtual ~PLUGINCORE();
explicit PLUGINCORE(DfxPlugin * inInstance);

virtual void reset();
virtual void processparameters();
virtual void process(const float *in, float *out, unsigned long inNumFrames, bool replacing=true);
void reset() override;
void processparameters() override;
void process(float const * in, float * out, unsigned long inNumFrames) override;

long getwindowsize() { return third; }
long getwindowsize() const noexcept { return third; }

private:

/* input and output buffers. out is framesize*2 samples long, in is framesize
samples long. (for maximum framesize)
*/
float * in0, * out0;
std::vector<float> in0, out0;

/* bufsize is 3 * third, framesize is 2 * third
bufsize is used for outbuf.
*/
long bufsize, framesize, third;
long bufsize = 0, framesize = 0, third = 0;

void processw(float * in, float * out, long samples);
void processw(float const * in, float * out, long samples);

int shape;
int shape = 0;

/* third-sized tail of previous processed frame. already has mixing envelope
applied.
*/
float * prevmix;
std::vector<float> prevmix;

/* number of samples in in0 */
int insize;
int insize = 0;

/* number of samples and starting position of valid samples in out0 */
int outsize;
int outstart;
int outsize = 0;
int outstart = 0;

};

#endif
18 changes: 16 additions & 2 deletions windowingstub/windowingstubdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,29 @@
see dfxplugin.h for details. */

#ifndef DFX_WINDOWING_STUB_DEF_H
#define DFX_WINDOWING_STUB_DEF_H


#include "dfxplugin-prefix.h"

#define PLUGIN_NAME_STRING "WINDOWINGSTUB"
#define PLUGIN_ID FOURCC('D', 'F', 'w', 's')
#define PLUGIN_VERSION 0x00010100
#define PLUGIN_ENTRY_POINT "WindowingstubEntry"
#define PLUGIN_VERSION_MAJOR 1
#define PLUGIN_VERSION_MINOR 1
#define PLUGIN_VERSION_BUGFIX 0

#define TARGET_PLUGIN_USES_MIDI 1
#define TARGET_PLUGIN_IS_INSTRUMENT 0
#define TARGET_PLUGIN_USES_DSPCORE 1

#define PLUGIN_COPYRIGHT_YEAR_STRING "2002-2022"

#define VST_NUM_CHANNELS 2

#ifndef TARGET_PLUGIN_HAS_GUI
#define TARGET_PLUGIN_HAS_GUI 0
#endif


#endif

0 comments on commit 8ad6778

Please sign in to comment.