Skip to content

Commit

Permalink
Rename sstring parameter and change type to float array. Add paramete…
Browse files Browse the repository at this point in the history
…r ssystem
  • Loading branch information
HolyWu committed Aug 6, 2019
1 parent b815626 commit 8d85dd8
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 96 deletions.
109 changes: 50 additions & 59 deletions DFTTest/DFTTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,71 +147,60 @@ static void createWindow(float * VS_RESTRICT hw, const int tmode, const int smod
delete[] sw;
}

static float * parseString(const char * s, int & poscnt, const float sigma, const float pfact) {
static float * parseSigmaLocation(const double * s, const int num, int & poscnt, const float sigma, const float pfact) {
float * parray = nullptr;

if (s[0] == 0) {
if (!s) {
parray = new float[4];
parray[0] = 0.0f;
parray[2] = 1.0f;
parray[1] = parray[3] = std::pow(sigma, pfact);
poscnt = 2;
} else {
poscnt = 0;
const double * sT = s;
bool found[2] = { false, false };
const char * sT = s;

while (sT[0] != 0) {
float pos, sval;
poscnt = 0;

if (std::sscanf(sT, "%f:%f", &pos, &sval) != 2)
throw std::string{ "invalid entry in sigma string" };
for (int i = 0; i < num; i += 2) {
const float pos = static_cast<float>(sT[i]);

if (pos < 0.0f || pos > 1.0f)
throw std::string{ "sigma string - invalid pos (" } + std::to_string(pos) + ")";
throw std::string{ "sigma location - invalid pos (" } + std::to_string(pos) + ")";

if (pos == 0.0f)
found[0] = true;
else if (pos == 1.0f)
found[1] = true;

poscnt++;

while (sT[1] != 0 && sT[1] != ' ')
sT++;
sT++;
}

if (!found[0] || !found[1])
throw std::string{ "sigma string - one or more end points not provided" };
throw std::string{ "sigma location - one or more end points not provided" };

parray = new float[poscnt * 2];
sT = s;
poscnt = 0;

while (sT[0] != 0) {
std::sscanf(sT, "%f:%f", &parray[poscnt * 2], &parray[poscnt * 2 + 1]);
parray[poscnt * 2 + 1] = std::pow(parray[poscnt * 2 + 1], pfact);
for (int i = 0; i < num; i += 2) {
parray[poscnt * 2 + 0] = static_cast<float>(sT[i + 0]);
parray[poscnt * 2 + 1] = std::pow(static_cast<float>(sT[i + 1]), pfact);

poscnt++;

while (sT[1] != 0 && sT[1] != ' ')
sT++;
sT++;
}

for (int i = 1; i < poscnt; i++) {
int j = i;
const float t0 = parray[j * 2];
const float t0 = parray[j * 2 + 0];
const float t1 = parray[j * 2 + 1];

while (j > 0 && parray[(j - 1) * 2] > t0) {
parray[j * 2] = parray[(j - 1) * 2];
parray[j * 2 + 0] = parray[(j - 1) * 2 + 0];
parray[j * 2 + 1] = parray[(j - 1) * 2 + 1];
j--;
}

parray[j * 2] = t0;
parray[j * 2 + 0] = t0;
parray[j * 2 + 1] = t1;
}
}
Expand Down Expand Up @@ -904,21 +893,15 @@ static void VS_CC dfttestCreate(const VSMap * in, VSMap * out, void * userData,
if (err)
alpha = (ftype == 0) ? 5.0f : 7.0f;

const char * sstring = vsapi->propGetData(in, "sstring", 0, &err);
if (err)
sstring = "";
const double * slocation = vsapi->propGetFloatArray(in, "slocation", &err);

const char * ssx = vsapi->propGetData(in, "ssx", 0, &err);
if (err)
ssx = "";
const double * ssx = vsapi->propGetFloatArray(in, "ssx", &err);

const char * ssy = vsapi->propGetData(in, "ssy", 0, &err);
if (err)
ssy = "";
const double * ssy = vsapi->propGetFloatArray(in, "ssy", &err);

const char * sst = vsapi->propGetData(in, "sst", 0, &err);
if (err)
sst = "";
const double * sst = vsapi->propGetFloatArray(in, "sst", &err);

const int ssystem = int64ToIntS(vsapi->propGetInt(in, "ssystem", 0, &err));

const int m = vsapi->propNumElements(in, "planes");

Expand Down Expand Up @@ -993,8 +976,23 @@ static void VS_CC dfttestCreate(const VSMap * in, VSMap * out, void * userData,
if (alpha <= 0.0f)
throw std::string{ "alpha must be greater than 0.0" };

if (slocation && (vsapi->propNumElements(in, "slocation") & 1))
throw std::string{ "the number of elements in slocation must be a multiple of 2" };

if (ssx && (vsapi->propNumElements(in, "ssx") & 1))
throw std::string{ "the number of elements in ssx must be a multiple of 2" };

if (ssy && (vsapi->propNumElements(in, "ssy") & 1))
throw std::string{ "the number of elements in ssy must be a multiple of 2" };

if (sst && (vsapi->propNumElements(in, "sst") & 1))
throw std::string{ "the number of elements in sst must be a multiple of 2" };

if (ssystem < 0 || ssystem > 1)
throw std::string{ "ssystem must be 0 or 1" };

if (opt < 0 || opt > 3)
throw std::string{ "opt must be 0, 1, 2 or 3" };
throw std::string{ "opt must be 0, 1, 2, or 3" };

const unsigned numThreads = vsapi->getCoreInfo(core)->numThreads;
d->ebuff.reserve(numThreads);
Expand Down Expand Up @@ -1085,7 +1083,7 @@ static void VS_CC dfttestCreate(const VSMap * in, VSMap * out, void * userData,
if (!d->sigmas || !d->sigmas2 || !d->pmins || !d->pmaxs)
throw std::string{ "malloc failure (sigmas/sigmas2/pmins/pmaxs)" };

if (sstring[0] || ssx[0] || ssy[0] || sst[0]) {
if (slocation || ssx || ssy || sst) {
int ndim = 3;
if (d->tbsize == 1)
ndim -= 1;
Expand All @@ -1095,23 +1093,15 @@ static void VS_CC dfttestCreate(const VSMap * in, VSMap * out, void * userData,
const float ndiv = 1.0f / ndim;
int tcnt = 0, sycnt = 0, sxcnt = 0;
float * tdata, * sydata, * sxdata;
bool edis = false;

if (sstring[0]) {
const char * w = sstring;
if (sstring[0] == '$') { // FFT3DFilter method
edis = true;
while ((w[0] == '$' || w[0] == ' ') && w[0] != 0)
w++;
}

tdata = parseString(w, tcnt, sigma, edis ? 1.0f : ndiv);
sydata = parseString(w, sycnt, sigma, edis ? 1.0f : ndiv);
sxdata = parseString(w, sxcnt, sigma, edis ? 1.0f : ndiv);
if (slocation) {
tdata = parseSigmaLocation(slocation, vsapi->propNumElements(in, "slocation"), tcnt, sigma, ssystem ? 1.0f : ndiv);
sydata = parseSigmaLocation(slocation, vsapi->propNumElements(in, "slocation"), sycnt, sigma, ssystem ? 1.0f : ndiv);
sxdata = parseSigmaLocation(slocation, vsapi->propNumElements(in, "slocation"), sxcnt, sigma, ssystem ? 1.0f : ndiv);
} else {
tdata = parseString(sst, tcnt, sigma, ndiv);
sydata = parseString(ssy, sycnt, sigma, ndiv);
sxdata = parseString(ssx, sxcnt, sigma, ndiv);
tdata = parseSigmaLocation(sst, vsapi->propNumElements(in, "sst"), tcnt, sigma, ndiv);
sydata = parseSigmaLocation(ssy, vsapi->propNumElements(in, "ssy"), sycnt, sigma, ndiv);
sxdata = parseSigmaLocation(ssx, vsapi->propNumElements(in, "ssx"), sxcnt, sigma, ndiv);
}

const int cpx = d->sbsize / 2 + 1;
Expand All @@ -1127,7 +1117,7 @@ static void VS_CC dfttestCreate(const VSMap * in, VSMap * out, void * userData,
const float sxval = getSVal(x, d->sbsize, sxdata, sxcnt, pfx);
float val;

if (edis) {
if (ssystem) {
const float dw = std::sqrt((pft * pft + pfy * pfy + pfx * pfx) / ndim);
val = interp(dw, tdata, tcnt);
} else {
Expand Down Expand Up @@ -1296,10 +1286,11 @@ VS_EXTERNAL_API(void) VapourSynthPluginInit(VSConfigPlugin configFunc, VSRegiste
"f0beta:float:opt;"
"nlocation:int[]:opt;"
"alpha:float:opt;"
"sstring:data:opt;"
"ssx:data:opt;"
"ssy:data:opt;"
"sst:data:opt;"
"slocation:float[]:opt;"
"ssx:float[]:opt;"
"ssy:float[]:opt;"
"sst:float[]:opt;"
"ssystem:int:opt;"
"planes:int[]:opt;"
"opt:int:opt;",
dfttestCreate, nullptr, plugin);
Expand Down
72 changes: 35 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Ported from AviSynth plugin http://bengal.missouri.edu/~kes25c/
Usage
=====

dfttest.DFTTest(clip clip[, int ftype=0, float sigma=8.0, float sigma2=8.0, float pmin=0.0, float pmax=500.0, int sbsize=16, int smode=1, int sosize=12, int tbsize=3, int tmode=0, int tosize=0, int swin=0, int twin=7, float sbeta=2.5, float tbeta=2.5, bint zmean=True, float f0beta=1.0, int[] nlocation=None, float alpha, string sstring='', string ssx='', string ssy='', string sst='', int[] planes=[0, 1, 2], int opt=0])
dfttest.DFTTest(clip clip[, int ftype=0, float sigma=8.0, float sigma2=8.0, float pmin=0.0, float pmax=500.0, int sbsize=16, int smode=1, int sosize=12, int tbsize=3, int tmode=0, int tosize=0, int swin=0, int twin=7, float sbeta=2.5, float tbeta=2.5, bint zmean=True, float f0beta=1.0, int[] nlocation=None, float alpha, float[] slocation=None, float[] ssx=None, float[] ssy=None, float[] sst=None, int ssystem=0, int[] planes=[0, 1, 2], int opt=0])

```
clip -
Expand Down Expand Up @@ -52,7 +52,7 @@ ftype -
sigma,sigma2 -
Value of sigma and sigma2 (used as described in ftype parameter description).
If using the sstring parameter then the sigma parameter is ignored.
If using the slocation parameter then the sigma parameter is ignored.
pmin,pmax -
Expand Down Expand Up @@ -206,90 +206,88 @@ alpha -
Has no effect when nlocation is not used.
sstring/ssx/ssy/sst -
slocation/ssx/ssy/sst -
Used to specify functions of sigma based on frequency. If you want sigma to vary
based on frequency, then use 'sstring' instead of the 'sigma' parameter. sstring
based on frequency, then use 'slocation' instead of the 'sigma' parameter. slocation
allows you to enter values of sigma for different normalized [0.0,1.0] frequency
locations. Values for locations between the ones you explicitly specify are computed
via linear interpolation. The frequency range, which is dependent on sbsize/tbsize,
is normalized to [0.0,1.0] with 0.0 being the lowest frequency and 1.0 being the
highest frequency. You MUST specify sigma values for those end point locations
(0.0 and 1.0)! You can specify as many other locations as you wish, and they don't
have to be in any particular order. Each frequency/sigma pair is given as "f.f:s.s".
The list of frequency/sigma pairs is saved as a string, with each pair separated by
a space.
have to be in any particular order. Each frequency/sigma pair is given as "f.f,s.s".
For example, if you want a linear ramp of sigma from 1.0 for the lowest frequency
to 10.0 for the highest frequency use:
sstring = "0.0:1.0 1.0:10.0"
slocation = [0.0,1.0, 1.0,10.0]
"0.0:1.0" => this means sigma=1.0 at frequency 0.0
"0.0,1.0" => this means sigma=1.0 at frequency 0.0
"1.0:10.0" => this means sigma=10.0 at frequency 1.0
"1.0,10.0" => this means sigma=10.0 at frequency 1.0
Sigma values for frequencies between 0.0 and 1.0 will be computed via
linear interpolation.
Or if you want a band-stop filter that passes low and high frequencies (filters
middle frequencies) use something like:
sstring = "0.0:0.0 0.15:10.0 0.85:10.0 1.0:0.0"
There are two methods for computing sigma values for a given frequency bin based on
sstring. The first computes the normalized frequency location of each dimension
(horizontal,vertical,temporal), interpolates sigma for each of those dimensions,
and then multiples the individual sigmas to obtain the final sigma value. So that
everything scales correctly, all sigma values entered in sstring are first raised to
the 1/#_dimensions power before performing linear interpolation and multiplying.
The second method (based on fft3dfilter's system) works by computing a single location
from the seperate dimension locations (x,y,z) as:
new = sqrt((x*x+y*y+z*z)/3.0)
sigma is then interpolated to this location. By default the first system is used.
To use the second system simply put a '$' sign at the beginning of sstring as shown
below:
sstring = "$ 0.0:1.0 1.0:10.0"
slocation = [0.0,0.0, 0.15,10.0, 0.85,10.0, 1.0,0.0]
---------------- ssx/ssy/sst explanation -------------------------------
sstring breaks the 1D (sbsize=1), 2D (for tbsize=1), or 3D (for sbsize>1 and tbsize>1)
slocation breaks the 1D (sbsize=1), 2D (for tbsize=1), or 3D (for sbsize>1 and tbsize>1)
frequency spectrum into chunks by normalizing each dimension to [0.0,1.0]... i.e. the
frequency range [0.0,0.25] is a cube covering the first 1/4 of each dimension. This works
fine if you want to treat all dimensions the same in terms of how sigma should vary.
However, if you wanted to ramp sigma based only on temporal frequency or horizontal
frequency, this is too limited. This is where ssx/ssy/sst come in!
ssx/ssy/sst allow you to specify sigma as a function of horizontal (ssx), vertical (ssy),
and temporal (sst) frequency only. The syntax is exactly the same as that of sstring. To
and temporal (sst) frequency only. The syntax is exactly the same as that of slocation. To
get the final sigma value for a frequency location, the three separate values (one for
each dimension) are computed and then multiplied together. As with sstring the sigma values
each dimension) are computed and then multiplied together. As with slocation the sigma values
are first raised to the 1/#_dimensions power before performing linear interpolation and
multiplying. If you don't specify all three strings, then a flat function equal to the
multiplying. If you don't specify all three dimensions, then a flat function equal to the
'sigma' parameter is used for the missing dimensions. For dimensions of size one (the
spatial dimenions if sbsize=1 or the temporal dimension for tbsize=1) the corresponding
string is ignored.
value is ignored.
For example:
ssx="0.0:1.0 1.0:10.0",ssy="0.0:1.0 1.0:10.0",sst="0.0:1.0 1.0:10.0"
ssx=[0.0,1.0, 1.0,10.0],ssy=[0.0,1.0, 1.0,10.0],sst=[0.0,1.0, 1.0,10.0]
will give the same result as
sstring="0.0:1.0 1.0:10.0"
slocation=[0.0,1.0, 1.0,10.0]
Or if you want to ramp sigma based on temporal frequency:
sigma=10.0,sst="0.0:1.0 1.0:10.0"
sigma=10.0,sst=[0.0,1.0, 1.0,10.0]
This will use 10.0 for the horizontal/vertical dimensions, and ramp
sigma from 1.0 to 10.0 in the temporal dimension.
If 'sstring' is specified, it takes precedence over ssx/ssy/sst.
If 'slocation' is specified, it takes precedence over ssx/ssy/sst.
ssystem -
There are two methods for computing sigma values for a given frequency bin based on
slocation. ssystem=0 computes the normalized frequency location of each dimension
(horizontal,vertical,temporal), interpolates sigma for each of those dimensions,
and then multiples the individual sigmas to obtain the final sigma value. So that
everything scales correctly, all sigma values entered in slocation are first raised to
the 1/#_dimensions power before performing linear interpolation and multiplying.
ssystem=1 (based on fft3dfilter's system) works by computing a single location
from the seperate dimension locations (x,y,z) as:
new = sqrt((x*x+y*y+z*z)/3.0)
sigma is then interpolated to this location. By default the first system is used.
Has no effect when slocation is not used.
planes -
Expand Down

0 comments on commit 8d85dd8

Please sign in to comment.