. , . , , , , , , .
, , . , , .
( )
, . , , . , . .
( ) ( ). , .
, , . , , , , , .
:
1. , , .
2. . .
- , , , ,
, - , , , 16000 22000 . , , .
--, , , ( ) , , , ( ).
|
|
, , , . --. .
, , . .
3. .
() , , . , . ( )/( ). , . , , , , . , , , .
. , . , .
30 1 . , , , , , . .. , ,
,
, ,
, , . , , .
|
|
:
for (var i = 0; i < frameSize; i++)
{
frame[i] *= Window.Gausse(i, frameSize);
}
using System;
using System.Numerics;
namespace Rainbow
{
public class Window
{
private const double Q = 0.5;
public static double Rectangle(double n, double frameSize)
{
return 1;
}
public static double Gausse(double n, double frameSize)
{
var a = (frameSize - 1)/2;
var t = (n - a)/(Q*a);
t = t*t;
return Math.Exp(-t/2);
}
public static double Hamming(double n, double frameSize)
{
return 0.54 - 0.46*Math.Cos((2*Math.PI*n)/(frameSize - 1));
}
public static double Hann(double n, double frameSize)
{
return 0.5*(1 - Math.Cos((2*Math.PI*n)/(frameSize - 1)));
}
public static double BlackmannHarris(double n, double frameSize)
{
return 0.35875 - (0.48829*Math.Cos((2*Math.PI*n)/(frameSize - 1))) +
(0.14128*Math.Cos((4*Math.PI*n)/(frameSize - 1))) - (0.01168*Math.Cos((4*Math.PI*n)/(frameSize - 1)));
}
}
}
, , , . , (256, 512, 1024 ).
C#.
using System;
using System.Numerics;
namespace Rainbow
{
public static class Butterfly
{
public const double SinglePi = Math.PI;
public const double DoublePi = 2*Math.PI;
public static Complex[] DecimationInTime(Complex[] frame, bool direct)
{
if (frame.Length == 1) return frame;
var frameHalfSize = frame.Length >> 1; // frame.Length/2
var frameFullSize = frame.Length;
var frameOdd = new Complex[frameHalfSize];
var frameEven = new Complex[frameHalfSize];
for (var i = 0; i < frameHalfSize; i++)
{
var j = i << 1; // i = 2*j;
frameOdd[i] = frame[j + 1];
frameEven[i] = frame[j];
}
var spectrumOdd = DecimationInTime(frameOdd, direct);
var spectrumEven = DecimationInTime(frameEven, direct);
var arg = direct? -DoublePi/frameFullSize: DoublePi/frameFullSize;
var omegaPowBase = new Complex(Math.Cos(arg), Math.Sin(arg));
var omega = Complex.One;
var spectrum = new Complex[frameFullSize];
for (var j = 0; j < frameHalfSize; j++)
{
spectrum[j] = spectrumEven[j] + omega*spectrumOdd[j];
spectrum[j + frameHalfSize] = spectrumEven[j] - omega*spectrumOdd[j];
omega *= omegaPowBase;
}
return spectrum;
}
public static Complex[] DecimationInFrequency(Complex[] frame, bool direct)
{
if (frame.Length == 1) return frame;
var halfSampleSize = frame.Length >> 1; // frame.Length/2
var fullSampleSize = frame.Length;
var arg = direct? -DoublePi/fullSampleSize: DoublePi/fullSampleSize;
var omegaPowBase = new Complex(Math.Cos(arg), Math.Sin(arg));
var omega = Complex.One;
var spectrum = new Complex[fullSampleSize];
for (var j = 0; j < halfSampleSize; j++)
{
spectrum[j] = frame[j] + frame[j + halfSampleSize];
spectrum[j + halfSampleSize] = omega*(frame[j] - frame[j + halfSampleSize]);
omega *= omegaPowBase;
}
var yTop = new Complex[halfSampleSize];
var yBottom = new Complex[halfSampleSize];
for (var i = 0; i < halfSampleSize; i++)
{
yTop[i] = spectrum[i];
yBottom[i] = spectrum[i + halfSampleSize];
}
yTop = DecimationInFrequency(yTop, direct);
yBottom = DecimationInFrequency(yBottom, direct);
for (var i = 0; i < halfSampleSize; i++)
{
var j = i << 1; // i = 2*j;
spectrum[j] = yTop[i];
spectrum[j + 1] = yBottom[i];
}
return spectrum;
}
}
}
, . , , , . , , .
|
|
, . , --, ,
-, , .
:
var spectrum = Butterfly.DecimationInTime(frame, true);
for (var i = 0; i < frameSize; i++)
{
spectrum[i] /= frameSize;
}
, .
, , , . , : , , ( ). , , . , - . , , , . .
4.
, . ( )/( ), , - , . . . , .
, . , 1024 , .
C# :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
namespace Rainbow
{
// Δ∂ωπ
public static class Filters
|
|
{
public const double SinglePi = Math.PI;
public const double DoublePi = 2*Math.PI;
public static Dictionary<double, double> GetJoinedSpectrum(
IList<Complex> spectrum0, IList<Complex> spectrum1,
double shiftsPerFrame, double sampleRate)
{
var frameSize = spectrum0.Count;
var frameTime = frameSize/sampleRate;
var shiftTime = frameTime/shiftsPerFrame;
var binToFrequancy = sampleRate/frameSize;
var dictionary = new Dictionary<double, double>();
for (var bin = 0; bin < frameSize; bin++)
{
var omegaExpected = DoublePi*(bin*binToFrequancy); // ω=2πf
var omegaActual = (spectrum1[bin].Phase - spectrum0[bin].Phase)/shiftTime; // ω=∂φ/∂t
var omegaDelta = Align(omegaActual - omegaExpected, DoublePi); // Δω=(∂ω + π)%2π - π
var binDelta = omegaDelta/(DoublePi*binToFrequancy);
var frequancyActual = (bin + binDelta)*binToFrequancy;
var magnitude = spectrum1[bin].Magnitude + spectrum0[bin].Magnitude;
dictionary.Add(frequancyActual, magnitude*(0.5 + Math.Abs(binDelta)));
}
return dictionary;
}
public static double Align(double angle, double period)
{
var qpd = (int) (angle/period);
if (qpd >= 0) qpd += qpd & 1;
else qpd -= qpd & 1;
angle -= period*qpd;
return angle;
}
}
}
:
var spectrum0 = Butterfly.DecimationInTime(frame0, true);
var spectrum1 = Butterfly.DecimationInTime(frame1, true);
for (var i = 0; i < frameSize; i++)
{
spectrum0[i] /= frameSize;
spectrum1[i] /= frameSize;
}
var spectrum = Filters.GetJoinedSpectrum(spectrum0, spectrum1, ShiftsPerFrame, Device.SampleRate);
1/16 1/32 , ShiftsPerFrame 16 32.
-, . , . , .
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
namespace Rainbow
{
public static class Filters
{
public static Dictionary<double, double> Antialiasing(Dictionary<double, double> spectrum)
{
var result = new Dictionary<double, double>();
var data = spectrum.ToList();
for (var j = 0; j < spectrum.Count - 4; j++)
{
var i = j;
var x0 = data[i].Key;
var x1 = data[i + 1].Key;
var y0 = data[i].Value;
var y1 = data[i + 1].Value;
var a = (y1 - y0)/(x1 - x0);
var b = y0 - a*x0;
i += 2;
var u0 = data[i].Key;
var u1 = data[i + 1].Key;
var v0 = data[i].Value;
var v1 = data[i + 1].Value;
var c = (v1 - v0)/(u1 - u0);
var d = v0 - c*u0;
var x = (d - b)/(a - c);
var y = (a*d - b*c)/(a - c);
if (y > y0 && y > y1 && y > v0 && y > v1 &&
x > x0 && x > x1 && x < u0 && x < u1)
{
result.Add(x1, y1);
result.Add(x, y);
}
else
{
result.Add(x1, y1);
}
}
return result;
}
}
}
. , .
, , , , , , . .
. , , , .
. , .