diff --git a/README b/README index bf1b87b5..550acab7 100644 --- a/README +++ b/README @@ -1,231 +1,5 @@ - Super Destroy FX Plugin Sources + The Slow Fourier Transform + -------------------------- -These are some of the plugins that are part of the Destroy FX plugin -pack (DFX). All of them use the VST plugin standard, and should be -(nearly) source-portable to any platform which supports that. Some -advanced features may not work on all platforms or in all hosts. - -Unfortunately, C++ is currently the only appropriate language for -creating VST plugins. Thus, all of these are written in C++. You'll -need a C++ compiler for your platform in order to compile them. You'll -also need an appropriate version of the VST SDK. Right now, this means -that you'll be able to easily compile with Visual C++ for Windows, -and somewhat easily with CodeWarrior for the Macintosh, and that it -will be pretty difficult for any other platform. - -These plugins are Copyright (c) Tom Murphy 7 and Marc Poirier. You can -use them in your music however you like, without royalties. You can -also modify them to your liking. However, if you distribute them (or -derivative/modified versions of them) then you must also distribute -the source package in order to be in compliance with the license (see -the file COPYING). - -This software comes with no warranty (see the file COPYING). In fact, -it is likely that some of these crazy effects could crash hosts (by -sending out-of-range samples or taking too much time to process), so -you should be careful to save your work when using them in important -songs. Tom uses Wavelab on the PC, and Marc uses Logic on the Mac, so -the plugins are likely work properly in those programs, at least. - -Pre-packaged versions of (some of) these with fancy GUIs are available -at the Super Destroy FX web page: - -http://destroyfx.org/ - -If you are simply interested in making music, you should check there -first. If you want to get your feet wet making your own VST effects, -this might be a good place to start. (You can also see and play with -our effects before they're finished!) - -Here's a description of each of the plugins included. First, we have -our "premiere" plugins; these have been released, have fancy GUIs, -and are pretty thoroughly tested: - -transverb/ - - Fun simple plugin; sort of like a tape-loop with - independently-moving read/write heads. Lots of great effects - in this one. - -scrubby/ - - A nice plugin that zips around the audio buffer like a - DJ (or robot DJ) scratching a record. Has the ability - to control the scratch speeds using a MIDI keyboard, - among other advanced features. - -bufferoverride/ - - Reads data into a buffer that might be smaller or larger - than the host buffer size, and then keeps repeating that - buffer over and over. Gives a sort of robotic or - stuttering effect to your sound, though many twisted - uses are possible. - -skidder/ - - Turns your sound on and off at regular or random intervals. - Practically every facet is controllable by a parameter. - Skidder also features the possibility for extreme settings - and MIDI control. - -geometer/ - - A laboratory for waveform geometry. All sorts of crazy - effects are possible with this thing, and sports a neat - visual display of what's happening to your sound. - -monomaker/ - - Monomaker is just a simple stereo utility. It can do - panning and stereo merging (i.e. merging a stereo signal - to mono). The panning is equal-power / -6 dB law (sort of). - - -These plugins are somewhat mature, but are lacking GUIs and thorough -testing: - -brokenfft/ - - One of my favorite plugins; this converts to the frequency - domain using the FFT, and then does a number of crazy effects. - This one has an almost limitless variety of sounds that will - come out of it... - - -These plugins are in the beginning stages, may be buggy, but we plan -on finishing them eventually: - -vardelay/ - - Allows for short delays of each sample, but the amount of - delay is dependent on the amplitude of the sample. (Several - bands are individually adjustable). - -trans/ - - Converts to and from other domains (sin, tan, derivative, e^x, - fft); the idea is that you run this and its inverse with some - other plugins in-between. - - -These plugins are not in development, perhaps because their functionality -has been subsumed by another plugin: - -decimate/ - - Reduces bit depth and sample rate in order to produce - artifacting. Extreme settings. Also includes a bonus "DESTROY" - effect. Geometer is much more flexible and beautiful than - this oldie. - -intercom/ - - Adds noise to your sound based on its RMS volume; can also - swap samples around. Again, Geometer probably has more - flexible effects that are similar in sound. - - - -In the source package, each plugin has a corresponding directory, as -well as a corresponding plugin_win32 directory containing MS VC++ -project files. In these directories, a batch file called "make.bat" -can be used from the command line to build the plugin, provided that -the Visual Studio tools are in your path. Some directories have -Visual Studio project files, but these are no longer supported. - -Some of these plugins have plugin_mac directories with stuff for -building Audio Unit versions of our plugins. The plugin.pbproj -"files" (well, they are bundles, and might appear like directories, -which is what they really are) are Project Builder projects. The -plugin.r files are resource files for Rez (although most of our -plugins actually rely on prefix headers and dfxplugin.r for resource -building). The plugin.exp files are the entry point files. - -In order to build Audio Units, you need Mac OS X 10.2 or higher and -you need the Apple Developer Tools and CoreAudio SDK installed. The -Developer Tools CD comes with the OS X 10.2 CDs and the CoreAudio SDK -is available at http://connect.apple.com/ Currently, you need to be -an Apple Developer Connection member to download it (I don't know -why), but the minimum membership is free. Project Builder (if you -care to use that IDE) is included with the Developer Tools. Note -that the Project Builder projects files here assume use absolute -paths for the Apple-provided base API files; they assume that the -files are located in the places where the CoreAudio SDK installer -places them. If you've moved those files, you'll have to change the -paths in the project settings. Also note that Marc works with a -rather modified set of the CoreAudio SDK files. All of the changes -that Marc has made will make it into the next SDK revision, so -they're kind of legit, but just so that you know... All of the -modifications are things that have been discussed/proposed/etc. on -the CoreAudio API listserv. - -for building VST Mac versions: -Some plugins have plugin_mac directories with *def-vst.h "prefix" files. -You can use these to set various #defines in your CodeWarrior projects -to build the plugins in different ways. This is because CW does not -allow you to specify preprocessor #defines in the project target -settings (this is true as of v8.2, although Metroworks say they will -eventually implement this long-missing feature). In your CW project -target settings, you go to the C/C++ Language tab specify the -appropriate file in the "prefix file" field. This means that CW will -preprocess this file before everything else and use the preprocessor -stuff globally for the whole build process. Usually you would use -vstplugsmac.h (for classic Mac OS builds) or vstplugscarbon.h (for -carbon builds) as the prefix file. Those files come with Steinberg's -VST SDK distribution and include a few basic, necessary #defines. -Our prefix files #include those files so that you still get those -defines. With our prefix files, those that end in def.h are for -classic builds, defcarbon.h are for carbon builds, eatdef.h are -for Marc's fancy "food" workaround for some plugs for Logic 4 Mac, -and some also have the word "stereo" to mean that they define -stereo processing for plugins that have both mono and stereo version -builds. - - -Here is a description of each of the remaining directories in the -source distribution: - -windowingstub/ - - Sources for starting a new plugin with buffering and - windowing. This is important when discontinuities at the - beginning and end of processing buffers translate into audible - artifacts in the output. (For example, when doing FFT.) This - adds certain overhead and extra complexity, and requires - running twice as much effect processing. In addition, some - effects do not fit the model well (a memory-driven delay - plugin, for instance). If your plugin does not need this, use - stub-plugin below instead. - -fftw/ - - "Fastest Fourier Transform in the West", which actually comes - from the East at MIT. A very fast FFT routine (GPL). - -fft-lib/ - - FFT Library from Don Cross. Public Domain. - -vstsdk/ - - SDK from Steinberg for creating VST plugins. There is no code - in this directory; you should get the headers and class stubs - from Steinberg's site. - -vstsdk_win32/ - - Binary libraries for the VST GUI. There's nothing in here - except for directions on where to get the library from Steinberg's - site. - -stub-plugin/ - - Sources for starting a new plugin. Much nicer than the - Steinberg examples (in my opinion). - -docs/ - - The documentation for users. We include these in the - binary distributions of our plugins. +I haven't really started writing this. \ No newline at end of file diff --git a/brokenfft/brokenfft.cpp b/brokenfft/brokenfft.cpp index 919839a2..bd7dce0c 100644 --- a/brokenfft/brokenfft.cpp +++ b/brokenfft/brokenfft.cpp @@ -21,6 +21,7 @@ PLUGIN::PLUGIN(audioMasterCallback audioMaster) FPARAM(bufsizep, P_BUFSIZE, "wsize", 0.5f, "samples"); FPARAM(shape, P_SHAPE, "shape", 0.0f, ""); + FPARAM(method, P_METHOD, "how", 0.0f, "which"); FPARAM(destruct, P_DESTRUCT, "very special", 1.0f, "?"); FPARAM(perturb, P_PERTURB, "perturb", 0.0f, "?"); @@ -33,7 +34,7 @@ PLUGIN::PLUGIN(audioMasterCallback audioMaster) FPARAM(spikehold, P_SPIKEHOLD, "spikehold", 0.0f, "?"); FPARAM(echomix, P_ECHOMIX, "eo mix", 0.0f, "?"); FPARAM(echotime, P_ECHOTIME, "eo time", 0.5f, "?"); - FPARAM(echomodf, P_ECHOMODF, "eo mod f", 2.0f * pi, "?"); + FPARAM(echomodf, P_ECHOMODF, "eo mod f", float(2.0 * pi), "?"); FPARAM(echomodw, P_ECHOMODW, "eo mod w", 0.0f, "?"); FPARAM(echofb, P_ECHOFB, "eo fbx", 0.50f, "?"); FPARAM(echolow, P_ECHOLOW, "eo >", 0.0f, "?"); @@ -65,13 +66,15 @@ PLUGIN::PLUGIN(audioMasterCallback audioMaster) echoc = (float*)malloc(MAXECHO * sizeof(float)); ampl = (amplentry*)malloc(sizeof (amplentry) * maxframe); - amplsamples = maxframe; fftr = (float*)malloc(maxframe * sizeof(float)); ffti = (float*)malloc(maxframe * sizeof(float)); tmp = (float*)malloc(maxframe * sizeof(float)); oot = (float*)malloc(maxframe * sizeof(float)); - buffersamples = maxframe; + + framesize = MKBUFSIZE(bufsizep); + plan = rfftw_create_plan(framesize, FFTW_FORWARD, FFTW_ESTIMATE); + rplan = rfftw_create_plan(framesize, FFTW_BACKWARD, FFTW_ESTIMATE); changed = 0; } @@ -104,6 +107,9 @@ void PLUGIN::resume() { third = framesize / 2; bufsize = third * 3; + plan = rfftw_create_plan(framesize, FFTW_FORWARD, FFTW_ESTIMATE); + rplan = rfftw_create_plan(framesize, FFTW_BACKWARD, FFTW_ESTIMATE); + /* set up buffers. Prevmix and first frame of output are always filled with zeros. */ @@ -200,6 +206,12 @@ void PLUGIN::getParameterDisplay(long index, char *text) { strcpy(text, "cos^2"); } break; + + case P_METHOD: + if (method < 0.25) strcpy(text, "dc"); + else if (method < 0.50) strcpy(text, "west"); + else strcpy(text, "west-bug"); + break; /* special cases here */ case P_POSTROT: if (postrot > 0.5f) { @@ -292,17 +304,19 @@ void PLUGIN::fftops(long samples) { samplesleft = 1 + (int)(binquant * binquant * binquant) * (samples >> 3); } - /* very special */ - if ((rand ()/(float)RAND_MAX) > destruct) { - /* swap with random sample */ - int j = (int)((rand()/(float)RAND_MAX) * (samples - 1)); - float u = fftr[i]; - fftr[i] = fftr[j]; - fftr[j] = u; - - u = ffti[i]; - ffti[i] = ffti[j]; - ffti[j] = u; + if (destruct < 1.0) { + /* very special */ + if ((rand ()/(float)RAND_MAX) > destruct) { + /* swap with random sample */ + int j = (int)((rand()/(float)RAND_MAX) * (samples - 1)); + float u = fftr[i]; + fftr[i] = fftr[j]; + fftr[j] = u; + + u = ffti[i]; + ffti[i] = ffti[j]; + ffti[j] = u; + } } /* operation Q */ @@ -312,15 +326,18 @@ void PLUGIN::fftops(long samples) { } /* perturb */ - fftr[i] = (double)((rand()/(float)RAND_MAX) * perturb + - fftr[i]*(1.0f-perturb)); - ffti[i] = (double)((rand()/(float)RAND_MAX) * perturb + - ffti[i]*(1.0f-perturb)); + if (perturb > 0.000001) { + fftr[i] = (double)((rand()/(float)RAND_MAX) * perturb + + fftr[i]*(1.0f-perturb)); + ffti[i] = (double)((rand()/(float)RAND_MAX) * perturb + + ffti[i]*(1.0f-perturb)); + } /* rotate */ int j = (i + (int)(rotate * samples)) % samples; fftr[i] = fftr[j]; + /* XXX and ffti? */ /* compress */ @@ -338,7 +355,7 @@ void PLUGIN::fftops(long samples) { } /* pretty expensive spike operation */ - if (spike < 0.999999 ) { + if (spike < 0.999999) { double loudness = 0.0; @@ -416,7 +433,7 @@ void PLUGIN::fftops(long samples) { } /* bufferride */ - if (bride < 1.0f) { + if (bride < 0.999999f) { int smd = 0; int md = bride * samples; for(int ss = 0; ss < samples; ss ++) { @@ -429,7 +446,7 @@ void PLUGIN::fftops(long samples) { /* first moment */ /* XXX support later moments (and do what with them??) */ - if (moments > 0.0f) { + if (moments > 0.00001f) { float mtr = 0.0f; float mti = 0.0f; @@ -465,7 +482,7 @@ void PLUGIN::fftops(long samples) { /* XXX sounds crappy */ /* freq(i) = 44100.0 * i / samples */ - if (harm > 0.0001f) { + if (harm > 0.000001f) { for(int i = 0; i < samples; i ++) { /* j = bin(freq(i)/2) */ int fi = 44100.0 * i /(float) samples; @@ -483,22 +500,24 @@ void PLUGIN::fftops(long samples) { /* post-processing rotate-up */ if (postrot > 0.5f) { int rotn = (postrot - 0.5f) * 1.0f * samples; - for(int v = samples - 1; v >= 0; v --) { - if (v < rotn) fftr[v] = ffti[v] = 0.0f; - else { - fftr[v] = fftr[v - rotn]; - ffti[v] = ffti[v - rotn]; + if (rotn != 0) + for(int v = samples - 1; v >= 0; v --) { + if (v < rotn) fftr[v] = ffti[v] = 0.0f; + else { + fftr[v] = fftr[v - rotn]; + ffti[v] = ffti[v - rotn]; + } } - } } else if (postrot < 0.5f) { int rotn = (int)((0.5f - postrot) * 1.0f * MKBUFSIZE(bufsizep)); - for(int v = 0; v < samples; v++) { - if (v > (samples - rotn)) fftr[v] = ffti[v] = 0.0f; - else { - fftr[v] = fftr[(samples - rotn) - v]; - ffti[v] = ffti[(samples - rotn) - v]; + if (rotn != 0) + for(int v = 0; v < samples; v++) { + if (v > (samples - rotn)) fftr[v] = ffti[v] = 0.0f; + else { + fftr[v] = fftr[(samples - rotn) - v]; + ffti[v] = ffti[(samples - rotn) - v]; + } } - } } @@ -528,7 +547,9 @@ void PLUGIN::fftops(long samples) { /* XXX I'm probably copying more times than I need to! PS, use memmove! */ -void PLUGIN::processw(float * in, float * out, long samples) { +void PLUGIN::processw(float * in, float * out) { + + int samples = framesize; static int ss; ss = !ss; @@ -537,12 +558,33 @@ void PLUGIN::processw(float * in, float * out, long samples) { for (int c = 0; c < samples; c++) tmp[c] = in[c]; - fft_float(samples, 0, tmp, 0, fftr, ffti); + /* do the processing */ + if (method < 0.25) { + /* Don Cross style */ + fft_float(samples, 0, tmp, 0, fftr, ffti); + fftops(samples); + fft_float(samples, 1, fftr, ffti, oot, tmp); + } else if (method < 0.50) { + /* FFTW .. this still doesn't work. How come? */ + rfftw_one(plan, tmp, fftr); + memcpy(ffti, fftr, samples * sizeof(float)); /* dup? */ - /* do actual processing */ - fftops(samples); + fftops(samples); - fft_float(samples, 1, fftr, ffti, oot, tmp); + rfftw_one(rplan, fftr, oot); + + float div = 1.0 / samples; + for(int xa = 0; xa < samples; xa++) { + oot[xa] = oot[xa] * div; + } + + } else { + /* bug -- using forward plan both ways, not normalizing */ + rfftw_one(plan, tmp, fftr); + memcpy(ffti, fftr, samples * sizeof(float)); /* dup? */ + fftops(samples); + rfftw_one(plan, fftr, oot); + } for (int cc = 0; cc < samples; cc++) out[cc] = oot[cc]; @@ -670,7 +712,7 @@ void PLUGIN::processX(float **trueinputs, float **trueoutputs, long samples, /* frame is full! */ /* in0 -> process -> out0(first free space) */ - processw(in0, out0+outstart+outsize, framesize); + processw(in0, out0+outstart+outsize); float oneDivThird = 1.0f / (float)third; /* apply envelope */ diff --git a/brokenfft/brokenfft.h b/brokenfft/brokenfft.h index 1a356446..a93ba26c 100644 --- a/brokenfft/brokenfft.h +++ b/brokenfft/brokenfft.h @@ -5,6 +5,7 @@ #define __DFX_BROKENFFT_H #include +#include "rfftw.h" #ifdef WIN32 /* turn off warnings about default but no cases in switch, etc. */ @@ -26,7 +27,7 @@ #define NUM_PROGRAMS 16 /* the names of the parameters */ -enum { P_BUFSIZE, P_SHAPE, +enum { P_BUFSIZE, P_SHAPE, P_METHOD, P_DESTRUCT, P_PERTURB, P_QUANT, @@ -109,7 +110,7 @@ class PLUGIN : public AudioEffectX { virtual void resume(); virtual long fxIdle(); - virtual void processw(float * in, float * out, long samples); + virtual void processw(float * in, float * out); void normalize(long, float); @@ -210,7 +211,7 @@ class PLUGIN : public AudioEffectX { float echomix, echotime; - int amplhold, amplsamples, stopat; + int amplhold, stopat; amplentry * ampl; float * echor; float * echoc; @@ -219,8 +220,6 @@ class PLUGIN : public AudioEffectX { /* fft work area */ float * tmp, * oot, * fftr, * ffti; - int buffersamples; /* size of work area */ - float echomodw, echomodf; float echolow, echohi; @@ -241,6 +240,11 @@ class PLUGIN : public AudioEffectX { float harm; + float method; + + rfftw_plan plan; + rfftw_plan rplan; + }; diff --git a/brokenfft/win32/make.bat b/brokenfft/win32/make.bat index 7c6e9339..ee9ac728 100755 --- a/brokenfft/win32/make.bat +++ b/brokenfft/win32/make.bat @@ -1,2 +1,4 @@ -cl /nologo /O2 /Ot /Og /Oi /Oy /Gs /I..\vstsdk\ /LD ..\brokenfft\brokenfft.cpp ..\vstsdk\AudioEffect.cpp ..\vstsdk\audioeffectx.cpp ..\fft-lib\fftdom.cpp ..\fft-lib\fftmisc.c ..\fft-lib\fourierf.c -I..\fft-lib\ brokenfft.def /Fec:\progra~1\steinberg\vstplugins\dfx-brokenfft.dll +cl /nologo /O2 /Ot /Og /Oi /Oy /Gs /I..\vstsdk\ /LD ..\brokenfft\brokenfft.cpp ..\vstsdk\AudioEffect.cpp ..\vstsdk\audioeffectx.cpp ..\fft-lib\fftdom.cpp ..\fft-lib\fftmisc.c ..\fft-lib\fourierf.c ..\fftw\rfftw\fcr_1.c ..\fftw\rfftw\fcr_10.c ..\fftw\rfftw\fcr_11.c ..\fftw\rfftw\fcr_12.c ..\fftw\rfftw\fcr_128.c ..\fftw\rfftw\fcr_13.c ..\fftw\rfftw\fcr_14.c ..\fftw\rfftw\fcr_15.c ..\fftw\rfftw\fcr_16.c ..\fftw\rfftw\fcr_2.c ..\fftw\rfftw\fcr_3.c ..\fftw\rfftw\fcr_32.c ..\fftw\rfftw\fcr_4.c ..\fftw\rfftw\fcr_5.c ..\fftw\rfftw\fcr_6.c ..\fftw\rfftw\fcr_64.c ..\fftw\rfftw\fcr_7.c ..\fftw\rfftw\fcr_8.c ..\fftw\rfftw\fcr_9.c ..\fftw\rfftw\fhb_10.c ..\fftw\rfftw\fhb_16.c ..\fftw\rfftw\fhb_2.c ..\fftw\rfftw\fhb_3.c ..\fftw\rfftw\fhb_32.c ..\fftw\rfftw\fhb_4.c ..\fftw\rfftw\fhb_5.c ..\fftw\rfftw\fhb_6.c ..\fftw\rfftw\fhb_7.c ..\fftw\rfftw\fhb_8.c ..\fftw\rfftw\fhb_9.c ..\fftw\rfftw\fhf_10.c ..\fftw\rfftw\fhf_16.c ..\fftw\rfftw\fhf_2.c ..\fftw\rfftw\fhf_3.c ..\fftw\rfftw\fhf_32.c ..\fftw\rfftw\fhf_4.c ..\fftw\rfftw\fhf_5.c ..\fftw\rfftw\fhf_6.c ..\fftw\rfftw\fhf_7.c ..\fftw\rfftw\fhf_8.c ..\fftw\rfftw\fhf_9.c ..\fftw\rfftw\frc_1.c ..\fftw\rfftw\frc_10.c ..\fftw\rfftw\frc_11.c ..\fftw\rfftw\frc_12.c ..\fftw\rfftw\frc_128.c ..\fftw\rfftw\frc_13.c ..\fftw\rfftw\frc_14.c ..\fftw\rfftw\frc_15.c ..\fftw\rfftw\frc_16.c ..\fftw\rfftw\frc_2.c ..\fftw\rfftw\frc_3.c ..\fftw\rfftw\frc_32.c ..\fftw\rfftw\frc_4.c ..\fftw\rfftw\frc_5.c ..\fftw\rfftw\frc_6.c ..\fftw\rfftw\frc_64.c ..\fftw\rfftw\frc_7.c ..\fftw\rfftw\frc_8.c ..\fftw\rfftw\frc_9.c ..\fftw\rfftw\rconfig.c ..\fftw\rfftw\rexec.c ..\fftw\rfftw\rexec2.c ..\fftw\rfftw\rfftwf77.c ..\fftw\rfftw\rfftwnd.c ..\fftw\rfftw\rgeneric.c ..\fftw\rfftw\rplanner.c ..\fftw\fftw\config.c ..\fftw\fftw\executor.c ..\fftw\fftw\fftwf77.c ..\fftw\fftw\fftwnd.c ..\fftw\fftw\fn_1.c ..\fftw\fftw\fn_10.c ..\fftw\fftw\fn_11.c ..\fftw\fftw\fn_12.c ..\fftw\fftw\fn_13.c ..\fftw\fftw\fn_14.c ..\fftw\fftw\fn_15.c ..\fftw\fftw\fn_16.c ..\fftw\fftw\fn_2.c ..\fftw\fftw\fn_3.c ..\fftw\fftw\fn_32.c ..\fftw\fftw\fn_4.c ..\fftw\fftw\fn_5.c ..\fftw\fftw\fn_6.c ..\fftw\fftw\fn_64.c ..\fftw\fftw\fn_7.c ..\fftw\fftw\fn_8.c ..\fftw\fftw\fn_9.c ..\fftw\fftw\fni_1.c ..\fftw\fftw\fni_10.c ..\fftw\fftw\fni_11.c ..\fftw\fftw\fni_12.c ..\fftw\fftw\fni_13.c ..\fftw\fftw\fni_14.c ..\fftw\fftw\fni_15.c ..\fftw\fftw\fni_16.c ..\fftw\fftw\fni_2.c ..\fftw\fftw\fni_3.c ..\fftw\fftw\fni_32.c ..\fftw\fftw\fni_4.c ..\fftw\fftw\fni_5.c ..\fftw\fftw\fni_6.c ..\fftw\fftw\fni_64.c ..\fftw\fftw\fni_7.c ..\fftw\fftw\fni_8.c ..\fftw\fftw\fni_9.c ..\fftw\fftw\ftw_10.c ..\fftw\fftw\ftw_16.c ..\fftw\fftw\ftw_2.c ..\fftw\fftw\ftw_3.c ..\fftw\fftw\ftw_32.c ..\fftw\fftw\ftw_4.c ..\fftw\fftw\ftw_5.c ..\fftw\fftw\ftw_6.c ..\fftw\fftw\ftw_64.c ..\fftw\fftw\ftw_7.c ..\fftw\fftw\ftw_8.c ..\fftw\fftw\ftw_9.c ..\fftw\fftw\ftwi_10.c ..\fftw\fftw\ftwi_16.c ..\fftw\fftw\ftwi_2.c ..\fftw\fftw\ftwi_3.c ..\fftw\fftw\ftwi_32.c ..\fftw\fftw\ftwi_4.c ..\fftw\fftw\ftwi_5.c ..\fftw\fftw\ftwi_6.c ..\fftw\fftw\ftwi_64.c ..\fftw\fftw\ftwi_7.c ..\fftw\fftw\ftwi_8.c ..\fftw\fftw\ftwi_9.c ..\fftw\fftw\generic.c ..\fftw\fftw\malloc.c ..\fftw\fftw\planner.c ..\fftw\fftw\putils.c ..\fftw\fftw\rader.c ..\fftw\fftw\timer.c ..\fftw\fftw\twiddle.c ..\fftw\fftw\wisdom.c ..\fftw\fftw\wisdomio.c -I..\fftw\rfftw\ -I..\fftw\fftw\ -I..\fft-lib\ brokenfft.def /Fec:\progra~1\steinberg\vstplugins\dfx-brokenfft.dll + + diff --git a/config_win32/config.c b/config_win32/config.c new file mode 100644 index 00000000..84521ac3 --- /dev/null +++ b/config_win32/config.c @@ -0,0 +1,17 @@ +#include + +#include "resource.h" + +#include + + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpCmdLine, int nCmdShow) { + + InitCommonControls (); + + MessageBox(NULL, "THIS IS DFX CONFIG APP !!!!", "Warning", MB_OK); + + return 0; + +} diff --git a/config_win32/config.rc b/config_win32/config.rc new file mode 100644 index 00000000..dd8691eb --- /dev/null +++ b/config_win32/config.rc @@ -0,0 +1,28 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" +#include "winres.h" + +#if 0 +IDD_MAIN DIALOG DISCARDABLE 0, 0, 207, 156 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Destroy FX Config (Windows)" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Add",IDC_STATIC,7,10,14,8 + + + EDITTEXT IDC_TEXT,25,7,120,14,ES_AUTOHSCROLL + EDITTEXT IDC_NUMBER,150,7,21,14,ES_NUMBER + LTEXT "times.",IDC_STATIC,177,10,23,8 + LISTBOX IDC_LIST,7,25,138,106,LBS_NOINTEGRALHEIGHT | + LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "&Add",IDC_ADD,150,30,50,14 + PUSHBUTTON "&Remove",IDC_REMOVE,150,47,50,14 + PUSHBUTTON "&Clear",IDC_CLEAR,150,63,50,14 + LTEXT "This item was added",IDC_STATIC,7,141,66,8 + CTEXT "-",IDC_SHOWCOUNT,77,141,32,8 + LTEXT "times",IDC_STATIC,114,141,17,8 +END + +#endif diff --git a/config_win32/eep.c b/config_win32/eep.c new file mode 100644 index 00000000..f829b2e0 --- /dev/null +++ b/config_win32/eep.c @@ -0,0 +1,47 @@ +#define AUTH_REGISTRY_KEY_NAME "Software\\Destroy FX\\Super Destroy FX transgendered bi-splendored XTREME plugin pack\\1.0" +#define AUTH_REGISTRY_VALUE_NAME "da data" + +//----------------------------------------------------------------------------- +// given a file system domain ref num, try to open the stored authorization data +int shakeleg(bool writing, HKEY baseKey, HKEY *valueKey) +{ + LONG error; + + if (writing) + { + DWORD moreInfo; + error = RegCreateKeyEx(baseKey, AUTH_REGISTRY_KEY_NAME, 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, NULL, valueKey, &moreInfo); + if (error != ERROR_SUCCESS) + return AUTH_OPENDATA_CREATE_FILE_ERR; + //if (moreInfo == REG_CREATED_NEW_KEY) printf("The key did not exist and was created.\n"); + //if (moreInfo == REG_OPENED_EXISTING_KEY) printf("The key existed and was simply opened without being changed.\n"); + } + else + { + error = RegOpenKeyEx(baseKey, AUTH_REGISTRY_KEY_NAME, 0, KEY_READ, valueKey); + if (error != ERROR_SUCCESS) + return AUTH_OPENDATA_OPEN_FILE_ERR; + } + + return DFX_AUTH_NOERR; // success +} + +//----------------------------------------------------------------------------- +// open the authorization file for reading or writing +int shakejeans(bool writing, HKEY *valueKey) +{ + HKEY searchKey1 = writing ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; + HKEY searchKey2 = writing ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; + + // attempt the first (prefered) domain (the local machine) + int goodleg = shakeleg(writing, searchKey1, valueKey); + // failing that, attempt the backup domain (the user domain) + if (goodleg != DFX_AUTH_NOERR) + goodleg = shakeleg(writing, searchKey2, valueKey); + // failing that, exit with the error + if (goodleg != DFX_AUTH_NOERR) + return goodleg; + + return DFX_AUTH_NOERR; // success +} diff --git a/config_win32/eep2.c b/config_win32/eep2.c new file mode 100644 index 00000000..2fe208c0 --- /dev/null +++ b/config_win32/eep2.c @@ -0,0 +1,49 @@ +// read data from registry + + // check the size of the stored data + LONG error; + DWORD dataSize; + error = RegQueryValueEx(dataRef, AUTH_REGISTRY_VALUE_NAME, NULL, NULL, NULL, &dataSize); + if (error != ERROR_SUCCESS) + { + RegCloseKey(dataRef); + return AUTH_CHECK_SIZE_CALC_ERR; + } + if (dataSize != AUTH_DATA_SIZE) + { + RegCloseKey(dataRef); + return AUTH_CHECK_DATA_SIZE_ERR; + } + + // copy the data out of the file into a buffer in memory + error = RegQueryValueEx(dataRef, AUTH_REGISTRY_VALUE_NAME, NULL, NULL, buf, &dataSize); + // file read error + if ( (error != ERROR_SUCCESS) || (dataSize != CORRECT_DATA_SIZE) ) + { + RegCloseKey(dataRef); + return AUTH_CHECK_DATA_GET_ERR; + } + + // all done reading, close the auth file + error = RegCloseKey(dataRef); + + + +// write the the data to registry + + // now flush the authorization data out to disk to save it + LONG error; + DWORD numBytes = AUTH_DATA_SIZE; + error = RegSetValueEx(dataRef, AUTH_REGISTRY_VALUE_NAME, 0, REG_BINARY, buf, numBytes); + // if there was an error or the number of bytes written was not what we tried to write, exit with an error + if (error != ERROR_SUCCESS) + { + RegCloseKey(dataRef); + return AUTH_WRITEDATA_WRITE_FILE_ERR; + } + + // close the file + error = RegCloseKey(dataRef); + // the file must close without error, otherwise our data probably was not saved + if (error != ERROR_SUCCESS) + return AUTH_WRITEDATA_CLOSE_FILE_ERR; diff --git a/config_win32/make.bat b/config_win32/make.bat new file mode 100755 index 00000000..79988a35 --- /dev/null +++ b/config_win32/make.bat @@ -0,0 +1,12 @@ + +echo ----- resource + +rc /l 0x409 /d "NDEBUG" config.rc + +echo ----- compile + +cl /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c config.c + +echo ----- link + +link /nologo config.obj /out:config.exe config.res kernel32.lib user32.lib gdi32.lib comdlg32.lib comctl32.lib shell32.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 \ No newline at end of file diff --git a/config_win32/resource.h b/config_win32/resource.h new file mode 100644 index 00000000..e66ad9a0 --- /dev/null +++ b/config_win32/resource.h @@ -0,0 +1,12 @@ + +#if 0 +#define IDD_MAIN 101 +#define IDC_TEXT 1000 +#define IDC_NUMBER 1001 +#define IDC_LIST 1002 +#define IDC_ADD 1003 +#define IDC_CLEAR 1004 +#define IDC_REMOVE 1005 +#define IDC_SHOWCOUNT 1006 + +#endif diff --git a/dfx-library/dfxdefines.h b/dfx-library/dfxdefines.h index c7fc2baa..363bb43c 100644 --- a/dfx-library/dfxdefines.h +++ b/dfx-library/dfxdefines.h @@ -49,11 +49,12 @@ class DfxPluginCore; #ifdef WIN32 #if WIN32 /* turn off warnings about default but no cases in switch, unknown pragma, etc. */ - #pragma warning( disable : 4065 57 4200 4244 4068 ) + #pragma warning( disable : 4065 57 4200 4244 4068 4326 ) #include #endif #endif #endif -/* __DFXDEFINES_H */ \ No newline at end of file + +/* __DFXDEFINES_H */ diff --git a/dfx-library/dfxmidi.cpp b/dfx-library/dfxmidi.cpp index 35bf750d..a4d3c683 100644 --- a/dfx-library/dfxmidi.cpp +++ b/dfx-library/dfxmidi.cpp @@ -199,8 +199,8 @@ void DfxMidi::insertNote(int currentNote) } // shift every note up a position (normal scenario) - for (int notecount = NUM_NOTES-1; notecount > 0; notecount--) - noteQueue[notecount] = noteQueue[notecount-1]; + for (int notecount_ = NUM_NOTES-1; notecount_ > 0; notecount_--) + noteQueue[notecount_] = noteQueue[notecount_ - 1]; // then place the new note into the first position noteQueue[0] = currentNote; } @@ -614,4 +614,4 @@ MIDI events over & over & over for every processing block until a new MIDI event is received. This fact about processEvents() is not explained in the SDK & I spent FOREVER with a malfunctioning plugin until I figured this out. -*/ \ No newline at end of file +*/ diff --git a/dfx-library/dfxparameter.h b/dfx-library/dfxparameter.h index a72cf565..4fb99c6b 100644 --- a/dfx-library/dfxparameter.h +++ b/dfx-library/dfxparameter.h @@ -159,6 +159,9 @@ property. When setusevaluestrings(true) is called, memory is allocated for the value strings. ------------------------------------------------------------------------*/ +#ifdef WIN32 + typedef __int64 int64_t; +#endif #ifndef __DFXPARAMETER_H #define __DFXPARAMETER_H diff --git a/guitest/graphic.h b/guitest/graphic.h index 085222cf..c3fa7565 100644 --- a/guitest/graphic.h +++ b/guitest/graphic.h @@ -20,6 +20,8 @@ struct PANELVERTEX #define DXTEST(c) do { int err; if ((err=(c)) != D3D_OK) \ MessageBox(0, #c, "ERROR", MB_OK); } while(0) +extern HINSTANCE instance; + struct Graphic { public: @@ -52,13 +54,21 @@ LPDIRECT3DVERTEXBUFFER8 verts; // A quick hack to get the size of the image into srcInfo. DXTEST(device->CreateImageSurface(1, 1, SURFACE_FORMAT, &pSurface)); +#if 0 DXTEST(D3DXLoadSurfaceFromFile(pSurface, NULL, NULL, filename, NULL, FILTER_HOW, 0, &srcInfo)); +#endif + DXTEST(D3DXLoadSurfaceFromResource(pSurface, + NULL, NULL, + instance, + filename, + NULL, FILTER_HOW, 0, &srcInfo)); + pSurface->Release(); - + height = srcInfo.Height; width = srcInfo.Width; - + // Create a surface to hold the entire file DXTEST(device->CreateImageSurface(width, height, SURFACE_FORMAT, ppSurface)); @@ -66,11 +76,18 @@ LPDIRECT3DVERTEXBUFFER8 verts; // The default colour key is 0xFF000000 (opaque black). Magenta // (0xFFFF00FF) is another common colour used for transparency. - DXTEST(D3DXLoadSurfaceFromFile(pSurface, palette, NULL, filename, - NULL, FILTER_HOW, - colourKey, &srcInfo)); +#if 1 + DXTEST(D3DXLoadSurfaceFromResource(pSurface, + palette, + NULL, + instance, + filename, + NULL, FILTER_HOW, + colourKey, &srcInfo)); +#endif } + /* height and width have to be set */ void CreateTextureFromSurface(LPDIRECT3DSURFACE8 surf, LPDIRECT3DTEXTURE8* ppTexture) { diff --git a/guitest/guitesteditor.cpp b/guitest/guitesteditor.cpp index 6055357a..f0b9edda 100644 --- a/guitest/guitesteditor.cpp +++ b/guitest/guitesteditor.cpp @@ -17,16 +17,16 @@ int useCount = 0; GuitestEditor::GuitestEditor (AudioEffect *effect) : AEffEditor (effect) { effect->setEditor (this); - g_pD3D = 0; - g_pd3dDevice = 0; + pD3D = 0; + pd3dDevice = 0; } GuitestEditor::~GuitestEditor () { - if( g_pd3dDevice != NULL) - g_pd3dDevice->Release(); + if( pd3dDevice != NULL) + pd3dDevice->Release(); - if( g_pD3D != NULL) - g_pD3D->Release(); + if( pD3D != NULL) + pD3D->Release(); } @@ -94,23 +94,23 @@ long GuitestEditor::open (void *ptr) { D3DXMatrixOrthoLH(&Ortho2D, EDIT_WIDTH, EDIT_HEIGHT, 0.0f, 1.0f); D3DXMatrixIdentity(&Identity); - g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &Ortho2D); - g_pd3dDevice->SetTransform(D3DTS_WORLD, &Identity); - g_pd3dDevice->SetTransform(D3DTS_VIEW, &Identity); + pd3dDevice->SetTransform(D3DTS_PROJECTION, &Ortho2D); + pd3dDevice->SetTransform(D3DTS_WORLD, &Identity); + pd3dDevice->SetTransform(D3DTS_VIEW, &Identity); - g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); + pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); - ggg = new Graphic(g_pd3dDevice, "c:\\temp\\dfx.png"); + ggg = new Graphic(pd3dDevice, "dfximage"); /* turn on alpha blending */ // Turn off culling, so we see the front and back of primitives - // DXTEST( g_lpD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE) ); + // DXTEST( lpD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE) ); - g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); return true; } @@ -154,25 +154,25 @@ void GuitestEditor::postUpdate() { void GuitestEditor::redraw() { - if( NULL == g_pd3dDevice ) + if( NULL == pd3dDevice ) return; // Clear the backbuffer to a green color - g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, + pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,50,0), 1.0f, 0 ); // Begin the scene - g_pd3dDevice->BeginScene(); + pd3dDevice->BeginScene(); // Rendering of scene objects can happen here Render2D(); // End the scene - g_pd3dDevice->EndScene(); + pd3dDevice->EndScene(); // Present the backbuffer contents to the display - g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); + pd3dDevice->Present( NULL, NULL, NULL, NULL ); } void GuitestEditor::Render2D () { @@ -220,13 +220,12 @@ LONG WINAPI GuitestEditor::WindowProc (HWND hwnd, UINT message, WPARAM wParam, HRESULT GuitestEditor:: InitD3D( HWND hWnd ) { // Create the D3D object, which is needed to create the D3DDevice. - if( NULL == ( g_pD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) ) + if( NULL == ( pD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) ) return E_FAIL; // Get the current desktop display mode D3DDISPLAYMODE d3ddm; - if( FAILED( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) ) - return E_FAIL; + DXTEST( pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ); // Set up the structure used to create the D3DDevice. Most parameters are // zeroed out. We set Windowed to TRUE, since we want to do D3D in a @@ -250,10 +249,9 @@ HRESULT GuitestEditor:: InitD3D( HWND hWnd ) // specified since we know it will work on all cards. On cards that support // hardware vertex processing, though, we would see a big performance gain // by specifying hardware vertex processing. - if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, + if( FAILED( pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, - &d3dpp, &g_pd3dDevice ) ) ) - { + &d3dpp, &pd3dDevice ) ) ) { return E_FAIL; } diff --git a/guitest/guitesteditor.h b/guitest/guitesteditor.h index c3d09400..0adfa205 100644 --- a/guitest/guitesteditor.h +++ b/guitest/guitesteditor.h @@ -51,8 +51,8 @@ struct GuitestEditor : public AEffEditor { public: void setValue(void* fader, int value); - LPDIRECT3D8 g_pD3D; // = NULL; // Used to create the D3DDevice - LPDIRECT3DDEVICE8 g_pd3dDevice;// = NULL; // Our rendering device + LPDIRECT3D8 pD3D; // = NULL; // Used to create the D3DDevice + LPDIRECT3DDEVICE8 pd3dDevice;// = NULL; // Our rendering device /* XXX */ diff --git a/guitest/win32/make.bat b/guitest/win32/make.bat index d6c5c7fb..8b558179 100755 --- a/guitest/win32/make.bat +++ b/guitest/win32/make.bat @@ -7,12 +7,14 @@ echo -------------- resources. rem You might want to compile some resources, if your plugin has a GUI. -rem rc something.rc +rc guitest.rc echo -------------- compile. -cl /FD /MD /nologo /O2 /Ot /Og /Oi /Oy /Gs /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /I..\guitest\ /I..\vstsdk\ /I..\dfx-library\ /LD /D "TARGET_API_VST" /FI "..\guitest\guitestdefs.h" /D "VST_NUM_CHANNELS=2" ..\guitest\guitest.cpp ..\guitest\guitesteditor.cpp ..\vstsdk\audioeffect.cpp ..\vstsdk\audioeffectx.cpp ..\dfx-library\dfxplugin.cpp ..\dfx-library\dfxparameter.cpp ..\dfx-library\dfxsettings.cpp ..\dfx-library\dfxmidi.cpp ..\dfx-library\dfxplugin-vst.cpp ..\guitest\alpha.cpp /c +cl /FD /MD /nologo /O2 /Ot /Og /Oi /Oy /Gs /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /I..\guitest\ /I..\vstsdk\ /I..\dfx-library\ /LD /D "TARGET_API_VST" /II:\dxsdk\include /FI "..\guitest\guitestdefs.h" /D "VST_NUM_CHANNELS=2" ..\guitest\guitest.cpp ..\guitest\guitesteditor.cpp ..\vstsdk\audioeffect.cpp ..\vstsdk\audioeffectx.cpp ..\dfx-library\dfxplugin.cpp ..\dfx-library\dfxparameter.cpp ..\dfx-library\dfxsettings.cpp ..\dfx-library\dfxmidi.cpp ..\dfx-library\dfxplugin-vst.cpp /c echo -------------- link. -link /IGNORE:4089 dxguid.lib kernel32.lib ddraw.lib user32.lib gdi32.lib shell32.lib winspool.lib comdlg32.lib advapi32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"guitest.pdb" /machine:I386 /def:".\guitest.def" /out:"C:\Progra~1\Steinberg\VstPlugIns\dfx Guitest.dll" /implib:"guitest.lib" audioeffect.obj guitesteditor.obj audioeffectx.obj guitest.obj dfxplugin.obj dfxplugin-vst.obj dfxparameter.obj dfxsettings.obj dfxmidi.obj alpha.obj +rem /NODEFAULTLIB:msvcrt.lib /IMPLIB:"C:\progra~1\Microsoft Visual Studio\VC98\Lib\MSVCRT.LIB" + +link /LIBPATH:"I:\dxsdk\lib" /IGNORE:4089 dxguid.lib d3d8.lib d3dx8.lib kernel32.lib ddraw.lib user32.lib gdi32.lib shell32.lib winspool.lib comdlg32.lib advapi32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"guitest.pdb" /machine:I386 /def:".\guitest.def" /out:"C:\Progra~1\Steinberg\VstPlugIns\dfx Guitest.dll" /implib:"guitest.lib" audioeffect.obj guitesteditor.obj audioeffectx.obj guitest.obj dfxplugin.obj dfxplugin-vst.obj dfxparameter.obj dfxsettings.obj dfxmidi.obj guitest.res diff --git a/slowft/README b/slowft/README new file mode 100644 index 00000000..eb06d2ab --- /dev/null +++ b/slowft/README @@ -0,0 +1,3 @@ + +This is the Slow Fourier Transform. But because it's not implemented, +I can't really tell you what it does!! diff --git a/slowft/slowft.cpp b/slowft/slowft.cpp new file mode 100644 index 00000000..6f32312f --- /dev/null +++ b/slowft/slowft.cpp @@ -0,0 +1,342 @@ + +/* Slowft, + Featuring the Super Destroy FX Windowing System! */ + +#include "slowft.h" + +#include + +#if defined(TARGET_API_VST) && TARGET_PLUGIN_HAS_GUI + #ifndef __DFX_SLOWFTEDITOR_H + #include "slowfteditor.hpp" + #endif +#endif + +/* this macro does boring entry point stuff for us */ +DFX_ENTRY(Slowft); +DFX_CORE_ENTRY(SlowftDSP); + + +PLUGIN::PLUGIN(TARGET_API_BASE_INSTANCE_TYPE inInstance) + : DfxPlugin(inInstance, NUM_PARAMS, NUM_PRESETS) { + + 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++) { + if (buffersizes[i] > 1000) + sprintf(bufstr, "%ld,%03ld", buffersizes[i]/1000, buffersizes[i]%1000); + else + sprintf(bufstr, "%ld", buffersizes[i]); + setparametervaluestring(P_BUFSIZE, i, bufstr); + } + + 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++) + setparametervaluestring(P_SHAPE, i, "???"); + + long delay_samples = buffersizes[getparameter_i(P_BUFSIZE)]; + setlatency_samples(delay_samples); + settailsize_samples(delay_samples); + + setpresetname(0, "Slowft Default"); /* default preset name */ + makepresets(); + + /* allow MIDI keys to be used to control parameters */ + dfxsettings->setAllowPitchbendEvents(true); + dfxsettings->setAllowNoteEvents(true); + +#if !TARGET_PLUGIN_USES_DSPCORE + addchannelconfig(1, 1); /* mono */ +#endif + + #ifdef TARGET_API_VST + #if TARGET_PLUGIN_USES_DSPCORE + DFX_INIT_CORE(SlowftDSP); /* we need to manage DSP cores manually in VST */ + #endif + /* if you have a GUI, need an Editor class... */ + #if TARGET_PLUGIN_HAS_GUI + editor = new SlowftEditor(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; + + /* add some leeway? */ + in0 = (float*)malloc(maxframe * sizeof (float)); + out0 = (float*)malloc(maxframe * 2 * sizeof (float)); + + /* prevmix is only a single third long */ + prevmix = (float*)malloc((maxframe / 2) * sizeof (float)); +} + + +PLUGINCORE::~PLUGINCORE() { + /* windowing buffers */ + free (in0); + free (out0); + + free (prevmix); +} + +void PLUGINCORE::reset() { + + framesize = buffersizes[getparameter_i(P_BUFSIZE)]; + third = framesize / 2; + bufsize = third * 3; + + /* set up buffers. Prevmix and first frame of output are always + filled with zeros. XXX memset */ + + for (int i = 0; i < third; i ++) { + prevmix[i] = 0.0f; + } + + for (int j = 0; j < framesize; j ++) { + out0[j] = 0.0f; + } + + /* start input at beginning. Output has a frame of silence. */ + insize = 0; + outstart = 0; + outsize = framesize; + + dfxplugin->setlatency_samples(framesize); + /* tail is the same as delay, of course */ + dfxplugin->settailsize_samples(framesize); +} + +void PLUGINCORE::processparameters() { + + shape = getparameter_i(P_SHAPE); + + #ifdef TARGET_API_VST + /* this tells the host to call a suspend()-resume() pair, + which updates initialDelay value */ + if (getparameterchanged(P_BUFSIZE)) + dfxplugin->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) { + + /* compute the 'slow fourier transform' */ + + + /* XXX get sample rate from parameter somewhere. */ + float rate = 44100.0f; + + /* freq given in hz */ + { + float freq = BASE_FREQ; + for(int key = 0; key < NUM_KEYS; key ++) { + + /* compute dot product */ + sines[key] = 0.0f; + cosines[key] = 0.0f; + + /* PERF this is probably really inefficient. pre-computing + tables of sines first, at least, would probably help. */ + for(int s = 0; s < samples; s ++) { + + // float frac = ((float)s / (float)samples); + + /* PERF This could be strength-reduced */ + float seconds = ((float)s / (float)rate); + + /* argument to sin, cosine. */ + float arg = freq * seconds * SLOWFT_2PI; + + sines[key] += sin(arg) * in[s]; + cosines[key] += cos(arg) * in[s]; + } + + /* go to next key */ + freq *= HALFSTEP_RATIO; + } + } + + /* XXX do ops... */ + + + /* now generate output! */ + + /* Start silent */ + { + for(int s = 0; s < samples; s++) { + out[s] = 0.0f; + } + } + + { + float freq = BASE_FREQ; + + /* now add back in sines and cosines */ + for(int key = 0; key < NUM_KEYS; key ++) { + + for(int s = 0; s < samples; s ++) { + + float seconds = ((float)s / (float)rate); + + /* argument to sin, cosine. */ + float arg = freq * seconds * SLOWFT_2PI; + + out[s] += sin(arg) + cos(arg); + + } + + freq *= HALFSTEP_RATIO; + } + } + +} + + +/* this fake process function reads samples one at a time + from the true input. It simultaneously copies samples from + the beginning of the output buffer to the true output. + We maintain that out0 always has at least 'third' samples + in it; this is enough to pick up for the delay of input + processing and to make sure we always have enough samples + to fill the true output buffer. + + If the input frame is full: + - calls wprocess on this full input frame + - applies the windowing envelope to the tail of out0 (output frame) + - mixes in prevmix with the first half of the output frame + - increases outsize so that the first half of the output frame is + now available output + - copies the second half of the output to be prevmix for next frame. + - copies the second half of the input buffer to the first, + resets the size (thus we process each third-size chunk twice) + + If we have read more than 'third' samples out of the out0 buffer: + - Slide contents to beginning of buffer + - Reset outstart + +*/ + +/* 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; + + for (unsigned long ii = 0; ii < samples; ii++) { + + /* copy sample in */ + in0[insize] = tin[ii]; + insize ++; + + if (insize == framesize) { + /* frame is full! */ + + /* in0 -> process -> out0(first free space) */ + processw(in0, out0+outstart+outsize, framesize); + + float oneDivThird = 1.0f / (float)third; + /* apply envelope */ + + switch(shape) { + + case WINDOW_TRIANGLE: + for(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++) { + 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); + 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); + out0[z+outstart+outsize] *= p; + out0[z+outstart+outsize+third] *= (1.0f - p); + } + break; + } + + /* mix in prevmix */ + for(int u = 0; u < third; u ++) + out0[u+outstart+outsize] += prevmix[u]; + + /* prevmix becomes out1 */ + memcpy(prevmix, out0 + outstart + outsize + third, third * sizeof (float)); + + /* 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)); + + 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 + + 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)); + outstart = 0; + } + } +} + + +void PLUGIN::makepresets() { + /* initialize presets here, see geometer for an example. */ +} diff --git a/slowft/slowft.h b/slowft/slowft.h new file mode 100644 index 00000000..44b06ad7 --- /dev/null +++ b/slowft/slowft.h @@ -0,0 +1,101 @@ + +/* Slowft, starring the Super Destroy FX Windowing System! */ + +#ifndef __DFX_SLOWFT_H +#define __DFX_SLOWFT_H + +#include "dfxplugin.h" + +/* change these for your plugins */ +#define PLUGIN Slowft +#define NUM_PRESETS 16 + +#define BUFFERSIZESSIZE 14 +const long buffersizes[BUFFERSIZESSIZE] = { + 4, 8, 16, 32, 64, 128, 256, 512, + 1024, 2048, 4096, 8192, 16384, 32768, +}; + + +#define PLUGINCORE SlowftDSP + +#define BASE_FREQ 27.5 +#define NUM_KEYS 88 +#define HALFSTEP_RATIO 1.05946309436 + +#define SLOWFT_PI 3.1415926535897932384626433832795f +#define SLOWFT_2PI 6.28318530718f + + +/* the types of window shapes available for smoothity */ +enum { WINDOW_TRIANGLE, + WINDOW_ARROW, + WINDOW_WEDGE, + WINDOW_COS, + NUM_WINDOWSHAPES, + MAX_WINDOWSHAPES=16 +}; + +/* the names of the parameters */ +enum { P_BUFSIZE, P_SHAPE, + NUM_PARAMS, +}; + + +class PLUGIN : public DfxPlugin { +public: + PLUGIN(TARGET_API_BASE_INSTANCE_TYPE inInstance); + virtual ~PLUGIN(); + +private: + /* set up the built-in presets */ + void makepresets(); +}; + +class PLUGINCORE : public DfxPluginCore { +public: + PLUGINCORE(DfxPlugin * inInstance); + virtual ~PLUGINCORE(); + + virtual void reset(); + virtual void processparameters(); + virtual void process(const float *in, float *out, unsigned long inNumFrames, bool replacing=true); + + long getwindowsize() { return third; } + + private: + + /* input and output buffers. out is framesize*2 samples long, in is framesize + samples long. (for maximum framesize) + */ + float * in0, * out0; + + /* bufsize is 3 * third, framesize is 2 * third + bufsize is used for outbuf. + */ + long bufsize, framesize, third; + + void processw(float * in, float * out, long samples); + + int shape; + + /* third-sized tail of previous processed frame. already has mixing envelope + applied. + */ + float * prevmix; + + /* number of samples in in0 */ + int insize; + + /* number of samples and starting position of valid samples in out0 */ + int outsize; + int outstart; + + + /* the transformed data */ + float sines[NUM_KEYS]; + float cosines[NUM_KEYS]; + +}; + +#endif diff --git a/slowft/slowftdefs.h b/slowft/slowftdefs.h new file mode 100644 index 00000000..7d24bdb6 --- /dev/null +++ b/slowft/slowftdefs.h @@ -0,0 +1,23 @@ + +/* You need to redefine this stuff in order to make your plugin. + see dfxplugin.h for details. */ + +#define PLUGIN_NAME_STRING "WINDOWINGSTUB" +#define PLUGIN_ID 'DFws' +#define PLUGIN_VERSION 0x00010100 +#define PLUGIN_ENTRY_POINT "WindowingstubEntry" + +#define TARGET_PLUGIN_USES_MIDI 1 +#define TARGET_PLUGIN_IS_INSTRUMENT 0 +#define TARGET_PLUGIN_USES_DSPCORE 1 + +#ifndef TARGET_PLUGIN_HAS_GUI +#define TARGET_PLUGIN_HAS_GUI 0 +#endif + +/* only necessary if using a custom GUI */ +#define PLUGIN_EDITOR_ENTRY_POINT "WindowingstubEditorEntry" + +// optional +#define PLUGIN_DESCRIPTION_STRING "i forgot to change the description" +#define PLUGIN_EDITOR_DESCRIPTION_STRING "i forgot to change the gui description too" diff --git a/slowft/win32/make.bat b/slowft/win32/make.bat new file mode 100755 index 00000000..03d1b28a --- /dev/null +++ b/slowft/win32/make.bat @@ -0,0 +1,19 @@ +@echo off + +rem To use this, run c:\progra~1\micros~2\vc98\bin\vcvars32.bat +rem (or wherever that file is located). + +echo -------------- resources. + +rem You might want to compile some resources, if your plugin has a GUI. + +rem rc something.rc + +echo -------------- compile. + +cl /FD /MD /nologo /O2 /Ot /Og /Oi /Oy /Gs /GD /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /I..\slowft\ /I..\vstsdk\ /I..\dfx-library\ /LD /D "TARGET_API_VST" /FI "..\slowft\slowftdefs.h" /D "VST_NUM_CHANNELS=2" ..\slowft\slowft.cpp ..\vstsdk\audioeffect.cpp ..\vstsdk\audioeffectx.cpp ..\dfx-library\dfxplugin.cpp ..\dfx-library\dfxparameter.cpp ..\dfx-library\dfxsettings.cpp ..\dfx-library\dfxmidi.cpp ..\dfx-library\dfxplugin-vst.cpp /c + +echo -------------- link. + +link kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"slowft.pdb" /machine:I386 /def:".\slowft.def" /out:"C:\Progra~1\Steinberg\VstPlugIns\dfx Slowft.dll" /implib:"slowft.lib" audioeffect.obj audioeffectx.obj slowft.obj dfxplugin.obj dfxplugin-vst.obj dfxparameter.obj dfxsettings.obj dfxmidi.obj ..\vstsdk_win32\vstgui.lib +