XAudio2 filter radian frequency - filter

In the documentation for the XAudio2 filter parameters it mentions
Filter radian frequency calculated as (2 * sin(pi * (desired filter cutoff frequency) / sampleRate))
Can someone explain to me where that formula comes from? Because the only source of frequency conversion that would make sense to me would come from sin(f * t) and cosine(f * t) vs sin(2*pi*f * t) and cosine(2*pi*f * t) where f is a "frequency" and t is time.

(2 * sin(pi * (desired filter cutoff frequency) / sampleRate))
This value will go monotonically from 0 to 2.0 as the filter cut-off frequency goes from DC to half the sample rate.
Digital filters scale relative to the sample rate, and your other offered options don't.

It's been a while since I've done filter math. It's kind of gnarly, but here's a basic interpretation:
The part that's a little confusing is the Sin no? I'm a little confused by it too, but I bet it's to keep the output of the conversion in the desired range. Looks like Microsoft's filter can only take up 8000hz. Forgive me if this way off base, I can't visualize what a sine function would do to the results at the moment.
2 * sin(pi * (desired filter cutoff frequency) / WHOLE THING
PARTS
2 * sin //// The 2*pi*f part you're used to.
(pi *
(
desired filter cutoff frequency) //// This in hertz will become radian freqs
/ sampleRate //// Sets up the whole equation for 1 sample

Related

Algorithm for automatic channel detection

I'm currently working on a spare-time project to perform automatic modulation classification (AMC) on radio signals (more precisely, I'm interested in L-band satellite channels), using SDR. I would like it to be able to discover channels in the power spectrum, along with their frequencies and bandwidths, so I can direct the application of AMC on the output of this step.
My first (naive) approach was rather simple: after every N samples (say 1024) apply a window function, perform the FFT on the last N, compute an estimation of the power spectrum and apply some exponential smoothing to reduce the noise. Then, in the smoothed power spectrum, find the maximum and minimum signal levels, calculate some threshold value based on a weighted mean of both levels and use this threshold to determine which frequency bins belong to a channel.
This works well in my unit tests (one QPSK channel + gaussian noise). However, in real-life scenarios I either get a few channels or a lot of false-positives. Of course I can fix this by fine-tuning the weights in the threshold calculation, but then it wouldn't be automatic anymore.
I've been doing some research on Google but maybe I'm not using the right search keywords, or there is no real interest on this subject (which would be strange, as frequency scanners must perform this task somehow).
How could I find the appropriate values for the mean weights? Maybe there is a better approach than calculating a threshold for the whole spectrum?
Your smoothing approach seems a bit counter-productive: Why would noise in a sufficiently long DFT form something like a "sharp" shape? You're most likely suppressing narrowband carriers that way.
Then: There's really a lot of signal detectors, many simply based on energy detection in spectrum (just like your approach).
However, the better an estimator has to be, the more info on the signal you're looking for you'll need to have. Are you looking for 20 kHz wide narrowband channels, or for dozens of Megahertzes of high-rate QPSK satellite downlink? Do you know anything about the channel/pulse shape? Autocorrelation?
This is a bit of a wide field, so I'd propose you look at something that already works:
gr-inspector of Sebastian Müller is a proven and pretty awesome automatic channel detector, and can, for some types of transmissions, also infer modulation parameters.
See a demo video (dubstep warning!); what you seem to be sketching looks something like this in that:
But: that's just one of the things it can do.
More importantly: Energy-band detection based on a DFT is really just one of many things you can do to detect signals. It wouldn't, for example, detect spread-spectrum transmissions, like GPS, for example. For that, you'd need knowledge of the spreading technique or at least a large autocorrelation-based detector.
After considering Marcus Müller's suggestion, I developed an algorithm that still relies on a global energy threshold but also on an estimation of the noise floor. It can be improved in many ways, but as its simplest realization already provides acceptable results with real-world captures (again, L-band captures at 250 ksps) I believe it could be a good ground for other people to start with.
The central idea of the algorithm is to calculate the energy threshold based on a continuous estimation of the noise power, updating it with every update of the spectrogram. This estimation keeps track of the maximum and minimum levels attained by each FFT bin after during all FFT runs, using them to estimate the PSD in that bin and discard outliers (i.e. channels, spurs...). The algorithm is to be executed every fixed number of samples. More formally:
Parameters of the algorithm:
int N /* spectrogram length (FFT bins) */
complex x[N] /* last N samples */
float alpha /* spectrogram smoothing factor between 0 (infinite smoothing,
spectrogram will never be updated) and 1 (no smoothing at all) */
float beta /* level decay factor between 0 (levels will never decay) and 1
(levels will be equal to the spectrogram). */
float gamma /* smooth factor applied to updates of the current noise estimation
between 0 (no updates allowed) and 1 /* no smoothing */
float SNR /* detection threshold above noise, in dB */
Recommended values for alpha, beta and gamma are 1e-2, 1e-3 and .5 respectively.
Variables:
complex dft[N] /* Fourier transform of the last N samples */
float spect[N] /* smoothed spectrogram */
float spmin[N] /* lower levels for spectrogram bins */
float spmax[N] /* upper levels for spectrogram bins */
int runs /* FFT run counter (initially zero) */
float N0 /* Current noise level estimation */
float new_N0 /* New noise level estimation */
float min_pwr /* Minimum power density found */
int min_pwr_bin /* FFT bin where min_pwr is */
int valid /* Number of valid bins for noise estimation */
int min_runs /* Minimum number of runs required to detect channels */
Algorithm:
min_runs = max(2. / alpha, 1. / beta)
dft = FFT(x);
++runs;
if (runs == 1) then /* First FFT run */
spect = dft * conj(dft) /* |FFT(x)|^2 */
spmin = spect /* Copy spect to spmin */
spmax = spect /* Copy spect to spmax */
N0 = min(spect); /* First noise estimation */
else
/* Smooth spectrogram w.r.t the previous run */
spect += alpha * (dft * conj(dft) - spect)
/* Update levels. This has to be performed element-wise */
new_N0 = 0
valid = 0
min_pwr = INFINITY
min_pwr_bin = -1
for (int i = 0; i < N; ++i)
/* Update current lower levels or raise them */
if (spect[i] < spmin[i]) then
spmin[i] = spect[i]
else
spmin[i] += beta * (spect[i] - spmin[i]);
end
/* Update current upper levels or decrease them */
if (spect[i] > spmax[i]) then
spmax[i] = spect[i]
else
spmax[i] += beta * (spect[i] - spmax[i]);
end
if (runs > min_runs) then
/* Use previous N0 estimation to detect outliers */
if (spmin[i] < N0 or N0 < spmax[i]) then
new_N0 += spect[i]
++valid
end
/* Update current minimum power */
if (spect[i] < min_pwr) then
min_pwr = spect[i]
min_pwr_bin = i
end
end
end
/*
* Check whether levels have stabilized and update noise
* estimation accordingly
*/
if (runs > min_runs) then
/*
* This is a key step: if the number of valid bins is
* 0 this means that our previous estimation was
* absolutely wrong. We reset it with a cruder estimation
* based on where the minimum value of the current
* spectrogram was found
*/
if (valid == 0) then
N0 = .5 * (spmin[min_pwr_bin] + spmax[min_pwr_bin])
else
N0 += gamma * (new_N0 / valid - N0)
end
/*
* Detect channels based on this threshold (trivial,
* not detailed)
*/
detect_channels(spect, 10^(SNR / 10) * N0)
end
end
Even though this algorithm makes the strong assumption that the noise floor is flat (which is false in most cases as in real-world radios, tuner output passes through a low-pass filter whose response is not flat), it works even if this condition doesn't hold. These are some of the algorithm results for different values of alpha, N = 4096 and SNR = 3 dB. Noise estimation is marked in yellow, channel threshold in green, upper levels in red, spectrogram in white and lower levels in cyan. I also provide an evolution of the N0 estimation after every FFT run:
Results for alpha = 1e-1:
Results for alpha = 1e-2. Note how the number of valid bins has been reduced as the spectrogram got clearer:
Results for alpha = 1e-3. In this case, the levels are so tight and the noise floor so obviously non-flat that there are novalid bins from one FFT run to another. In this case we fall back to the crude estimation of looking for the bin with the lowest power density:
The min_runs calculation is critical. To prevent the noise level to updrift (this is, to follow a channel and not the noise floor) we must wait at least 2. / alpha FFT runs before trusting the signal levels. This value was found experimentally: in my previous implementations, I was intuitively using 1. / alpha which failed miserably for alpha = 1e-3:
I haven't tested this yet on other scenarios (like burst transmissions) where this algorithm may not perform as well as with continuous channels because of the persistence of min/max levels, and it may fail to detect burst transmissions as outliers. However, given the kind of channels I'm working with, this is not a priority for now.

Bezier curve: I want to implement an algorithm to draw a continuous curve with bezier algorithm

Through the internet I found the quadratic beizer curve by given three control points. But what should I do if I have a set of points?
x = (1 - t) * (1 - t) * p[0].x + 2 * (1 - t) * t * p[1].x + t * t * p[2].x;
y = (1 - t) * (1 - t) * p[0].y + 2 * (1 - t) * t * p[1].y + t * t *
p[2].y;
In my program, I will have a touch event, when user touches it and move the finger around the screen, the program starts to draw curve.
If I am doing Android I can use quadTo but I can't do it that way coz I want to do it in many platform
For this you will need to use a curve fitting algorithm, this is typcally done iteratively using a least square solution.
A common reference for this is graphics-gems FitCurve.c, see:
https://github.com/erich666/GraphicsGems/blob/master/gems/FitCurves.c
While this is a good reference its not so usable as a library function since its using static vars everywhere.
I've extracted open-toonz curve fitting (also based on FitCurve.c) into a stand-alone, single file C library - which can calculate the curve.
https://developer.blender.org/diffusion/B/browse/master/extern/curve_fit_nd/intern/curve_fit_cubic.c (has various improvements, see header for details)

Curve Programmatically Calculated?

How can I calculate y in this curve ? t is the variable. Origin is (0|0) of course.
the tangents at t=0, t=0,5 and t=1 must be perfectly horizontal (incline = 0)
only basic mathematical operators are available (Java / Actionscript 3)
I have to calculate this a few hundred times each frame in Actionscript 3. So calculation needs good performance. Right now I'm actually failing at correctness of calculation (I'm not a mathematician).
Not sure about performance, but
-0.5 * cos(x * 2pi) + 0.5
AS3:
y = -0.5 * Math.cos(x * 2 * Math.PI) + 0.5;
seems to be the curve you are looking for.
You can view or edit the curve here:
wolfram alfa curve
The function suggested by bjornson (-0.5*cos(x) + 0.5) looks good.
One idea to improve performance is that you at the start of your application create a table of the values of that function at different times.
If you use fix timesteps, then the table is all you'll need. If you have variable time steps, then you can just do linear interpolation between the two closest times to the time you're calculating.
y(t) = 16 * t * t * (t - 1) * (t - 1)
I reckon that one satisfies your requirements
I tried my own way and I came up with a polynomial:
y = 16 * (t - 0.5)^4 - 8 * (t - 0.5)^2 + 1
y = 16 * Math.pow((t - 0.5), 4) - 8 * Math.pow((t - 0.5), 2) + 1;
// forgot to shift the curve 0.5 to the right, corrected

equal power crossfade in Audio Unit?

This is actually more of a theoretical question, but here it goes:
I'm developing an effect audio unit and it needs an equal power crossfade between dry and wet signals.
But I'm confused about the right way to do the mapping function from the linear fader to the scaling factor (gain) for the signal amplitudes of dry and wet streams.
Basically, I'ev seen it done with cos / sin functions or square roots... essentially approximating logarithmic curves. But if our perception of amplitude is logarithmic to start with, shouldn't these curves mapping the fader position to an amplitude actually be exponential?
This is what I mean:
Assumptions:
signal[i] means the ith sample in a signal.
each sample is a float ranging [-1, 1] for amplitudes between [0,1].
our GUI control is an NSSlider ranging from [0,1], so it is in
principle linear.
fader is a variable with the value of the NSSlider.
First Observation:
We perceive amplitude in a logarithmic way. So if we have a linear fader and merely adjust a signal's amplitude by doing: signal[i] * fader what we are perceiving (hearing, regardless of the math) is something along the lines of:
This is the so-called crappy fader-effect: we go from silence to a drastic volume increase across the leftmost segment in the slider and past the middle the volume doesn't seem to get that louder.
So to do the fader "right", we instead either express it in a dB scale and then, as far as the signal is concerned, do: signal[i] * 10^(fader/20) or, if we were to keep or fader units in [0,1], we can do :signal[i] * (.001*10^(3*fader))
Either way, our new mapping from the NSSlider to the fader variable which we'll use for multiplying in our code, looks like this now:
Which is what we actually want, because since we perceive amplitude logarithmically, we are essentially mapping from linear (NSSLider range 0-1) to exponential and feeding this exponential output to our logarithmic perception. And it turns out that : log(10^x)=x so we end up perceiving the amplitude change in a linear (aka correct) way.
Great.
Now, my thought is that an equal-power crossfade between two signals (in this case a dry / wet horizontal NSSlider to mix together the input to the AU and the processed output from it) is essentially the same only that with one slider acting on both hypothetical signals dry[i] and wet[i].
So If my slider ranges from 0 to 100 and dry is full-left and wet is full-right), I'd end up with code along the lines of:
Float32 outputSample, wetSample, drySample = <assume proper initialization>
Float32 mixLevel = .01 * GetParameter(kParameterTypeMixLevel);
Float32 wetPowerLevel = .001 * pow(10, (mixLevel*3));
Float32 dryPowerLevel = .001 * pow(10, ((-3*mixLevel)+1));
outputSample = (wetSample * wetPowerLevel) + (drySample * dryPowerLevel);
The graph of which would be:
And same as before, because we perceive amplitude logarithmically, this exponential mapping should actually make it where we hear the crossfade as linear.
However, I've seen implementations of the crossfade using approximations to log curves. Meaning, instead:
But wouldn't these curves actually emphasize our logarithmic perception of amplitude?
The "equal power" crossfade you're thinking of has to do with keeping the total output power of your mix constant as you fade from wet to dry. Keeping total power constant serves as a reasonable approximation to keeping total perceived loudness constant (which in reality can be fairly complicated).
If you are crossfading between two uncorrelated signals of equal power, you can maintain a constant output power during the crossfade by using any two functions whose squared values sum to 1. A common example of this is the set of functions
g1(k) = ( 0.5 + 0.5*cos(pi*k) )^.5
g2(k) = ( 0.5 - 0.5*cos(pi*k) )^.5,
where 0 <= k <= 1 (note that g1(k)^2 + g2(k)^2 = 1 is satisfied, as mentioned). Here's a proof that this results in a constant power crossfade for uncorrelated signals:
Say we have two signals x1(t) and x2(t) with equal powers E[ x1(t)^2 ] = E[ x2(t)^2 ] = Px, which are also uncorrelated ( E[ x1(t)*x2(t) ] = 0 ). Note that any set of gain functions satisfying the previous condition will have that g2(k) = (1 - g1(k)^2)^.5. Now, forming the sum y(t) = g1(k)*x1(t) + g2(k)*x2(t), we have that:
E[ y(t)^2 ] = E[ (g1(k) * x1(t))^2 + 2*g1(k)*(1 - g1(k)^2)^.5 * x1(t) * x2(t) + (1 - g1(k)^2) * x2(t)^2 ]
= g1(k)^2 * E[ x1(t)^2 ] + 2*g1(k)*(1 - g1(k)^2)^.5 * E[ x1(t)*x2(t) ] + (1 - g1(k)^2) * E[ x2(t)^2 ]
= g1(k)^2 * Px + 0 + (1 - g1(k)^2) * Px = Px,
where we have used that g1(k) and g2(k) are deterministic and can thus be pulled outside the expectation operator E[ ], and that E[ x1(t)*x2(t) ] = 0 by definition because x1(t) and x2(t) are assumed to be uncorrelated. This means that no matter where we are in the crossfade (whatever k we choose) our output will still have the same power, Px, and thus hopefully equal perceived loudness.
Note that for completely correlated signals, you can achieve constant output power by doing a "linear" fade - using and two functions that sum to one ( g1(k) + g2(k) = 1 ). When mixing signals that are somewhat correlated, gain functions between those two would theoretically be appropriate.
What you're thinking of when you say
And same as before, because we perceive amplitude logarithmically,
this exponential mapping should actually make it where we hear the
crossfade as linear.
is that one signal should perceptually decrease in loudness as a linear function of slider position (k), while the other signal should perceptually increase in loudness as a linear function of slider position, when applying your derived crossfade. While your derivation of that seems pretty spot on, unfortunately that may not the best way to blend your dry and wet signals in terms of consistency - often, maintaining equal output loudness, regardless of slider position, is the better thing to shoot for. In any case, it might be worth trying a couple different functions to see what is most usable and consistent.

Distances between houses, Google Directions API query limit is too low, need better algorithm

I need to rent two houses. I want them to be as close as possible. There are about 300 houses available for rent. I wish to use the Google Maps Directions API to calculate the walking distance between any two available houses so then I can sort the list and choose two that are close.
Everything works great, except that Google sets a theoretical limit of 2,500 queries per day (and in practice the limit is much lower, at only 250 per day). I have 3002/2 - 300 = 44,700 queries to make so obviously this limit is not enough for me.
This would be a one time thing, any hints on how can I accomplish what I need with the Google Maps API? Can I somehow run the program distributed so the limit will affect only one instance? Would Google App Engine help?
I also welcome advice for improving the algorithm. If two houses are far apart, and another house is close to one of them it means it would not have to check the third house with the remaining house as they are probably far away. I also care more about the qualitative nature of the algorithm, not the exact distances, so maybe there is a simple approximation I can make that will result in fewer queries.
Thanks,
The geographic distance between any two houses, as the crow flies, will be a strict lower bound on the walking distance. So I'd start with 300 queries, to get the long/lat for each house, plug them into the Haversine formula (for example) to get the distances between the 45,000 unordered pairs, and sort them to get the closest pairs by geographic distance. Then with
some likely candidates in hand, you can start checking the walking distances with another set of calls to the Google API.
Consider, that you are pizza deliverer and you want to calculate your effective range (where you can go within 30 minutes). And you want to make a colored bar 3d graph of N to E section of that time data, something like (with bogus data):
And you want to include like 100k of houses ... Well at least I heard, that program like this, was made before limits where introduced in Google map. Limits just bite hard in this case.
If you have geo location from all the houses, then you can find a prediction from how far are the points on earth, when you fly like a bird. Sort them based on that, and find results for best predictions.
Edit: Added Java code example, that could be useful when creating predictions:
/**
* Thaddeus Vincenty's inverse method formulae implementation for
* geographical distance between two given points on earth.
* #param L1
* geographical latitude of standpoint in decimal degrees
* #param G1
* geographical longitude of standpoint in decimal degrees
* #param L2
* geographical latitude of destination in decimal degrees
* #param G2
* geographical longitude of destination in decimal degrees
* #return Geographical distance in kilometeres
*/
public static double getDistance(final double L1, final double G1,
final double L2, final double G2) {
double delta, p0, p1, p2, p3;
// The average radius for a spherical approximation of Earth
double rEarth = 6371.01d;
delta = G1 - G2;
p0 = Math.cos(L2) * Math.cos(delta);
p1 = Math.cos(L2) * Math.sin(delta);
p2 = Math.cos(L1) * Math.sin(L2) - Math.sin(L1) * p0;
p3 = Math.sin(L1) * Math.sin(L2) + Math.cos(L1) * p0;
return rEarth * Math.atan2(Math.sqrt(p1 * p1 + p2 * p2), p3);
}
/**
* Rounds double to nr number of decimal places
* #param d
* floating-point number
* #param nr
* decimal places to keep
* #return rounded number with nr decimal places
*/
public static double round(double d, int nr) {
return new java.math.BigDecimal(Double.toString(d)).setScale(nr,
java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
}
public static void main(String[] args) {
double L1 = Math.toRadians(Double.parseDouble(args[0]));
double G1 = Math.toRadians(Double.parseDouble(args[1]));
double L2 = Math.toRadians(Double.parseDouble(args[2]));
double G2 = Math.toRadians(Double.parseDouble(args[3]));
System.out.println(round(getDistance(L1, G1, L2, G2), 2));
}
i would use this formula :
distance = Math.acos(Math.sin(lat1)*Math.sin(lat2) +
Math.cos(lat1)*Math.cos(lat2) *
Math.cos(lon2-lon1)) * 6371;
to rank all 45,000 houses by distance as the crow flies.
I would then take the top 250 results ranked by shortest distance and run them through google to get the accurate walking distance and re-rank.
I don't know if this is working with the directions method but you want to interleave (nesting) the directions query into a single query. A google chunk can hold up to 24 directions per chunk. Thus you can increase your query to a maximum of 250 * 24 (6000 directions) per day. Maybe you want to change your IP adress after 6000 queries? Maybe Google let you then query more then 6000 directions per day? I got the interleaving idea from geweb tsp solver where he interleaves 24 cities from a query matrix into 1 chunk saving up to 22 single queries and thus reducing bandwidth and Google's API limitation.

Resources