I'm trying to write a Winforms application that calculates the beats per minute of click, similar to this website: https://www.all8.com/tools/bpm.htm but nothing works for me.
I've tried to create a System.Diagnostics.Stopwatch object to count the number of milliseconds, and divide that by 60,000 to get the number of minutes that pass, but that doesn't count what the future
public Stopwatch stopwatch = new Stopwatch();
public Form1()
{
InitializeComponent();
}
float i = 0f;
private void Button1_Click(object sender, EventArgs e)
{
if (!stopwatch.IsRunning) { stopwatch.Start(); }
i++;
speed.Text = String.Format("Speed: {0} bpm\nClicks: {1} Clicks", i / Millis(), i);
}
private float Millis()
{
var returntype = stopwatch.ElapsedMilliseconds / 60000;
return returntype + 1;
}
This just counts the number of times you've clicked the button and divides it by the number of minutes that have passed, and doesn't predict at the rate of clicking.
This is very similar to some code I wrote to calculate FPS of an encoding process that I wrote some time ago.
Start with this code and then adapt it to your needs. The Calculate method will take a bool indicating whether it's a click or not. You'll call it with True on every click, and have a timer call it with False every second. Then you simply bind the BMP to the property of this class for display.
This should be enough to get you started. I recommend keeping the logic of that calculation in a specialized class to not clutter the main class.
/// <summary>
/// Allows calculating the time left during an encoding process.
/// </summary>
public class TimeLeftCalculator {
private KeyValuePair<DateTime, long>[] progressHistory;
private int iterator;
private bool fullCycle;
private long lastPos;
private long frameCount;
private int historyLength;
/// <summary>
/// After calling Calculate, returns the estimated processing time left.
/// </summary>
public TimeSpan ResultTimeLeft { get; private set; }
/// <summary>
/// After calling Calculate, returns the estimated processing rate per second.
/// </summary>
public double ResultFps { get; private set; }
protected readonly IEnvironmentService environment;
/// <summary>
/// Initializes a new instance of the TimeLeftCalculator class.
/// </summary>
/// <param name="frameCount">The total number of frames to encode.</param>
/// <param name="historyLength">The number of status entries to store. The larger the number, the slower the time left will change. Default is 20.</param>
public TimeLeftCalculator(long frameCount, int historyLength = 20) : this(new EnvironmentService(), frameCount, 20) { }
/// <summary>
/// Initializes a new instance of the TimeLeftCalculator class.
/// </summary>
/// <param name="environmentService">A reference to an IEnvironmentService.</param>
/// <param name="frameCount">The total number of frames to encode.</param>
/// <param name="historyLength">The number of status entries to store. The larger the number, the slower the time left will change. Default is 20.</param>
public TimeLeftCalculator(IEnvironmentService environmentService, long frameCount, int historyLength = 20) {
this.environment = environmentService ?? throw new ArgumentNullException(nameof(environmentService));
this.FrameCount = frameCount;
this.HistoryLength = historyLength;
progressHistory = new KeyValuePair<DateTime, long>[historyLength];
}
/// <summary>
/// Gets or sets the total number of frames to encode.
/// </summary>
public long FrameCount {
get => frameCount;
set => frameCount = value >= 0 ? value : throw new ArgumentOutOfRangeException(nameof(FrameCount));
}
/// <summary>
/// Gets or sets the number of status entries to store. The larger the number, the slower the time left will change.
/// </summary>
public int HistoryLength {
get => historyLength;
set => historyLength = value >= 1 ? value : throw new ArgumentOutOfRangeException(nameof(HistoryLength));
}
/// <summary>
/// Calculates the time left and fps. Result will be in ResultTimeLeft and ResultFps.
/// </summary>
/// <param name="pos">The current frame position.</param>
public void Calculate(long pos) {
if (pos < 0)
return;
TimeSpan Result = TimeSpan.Zero;
progressHistory[iterator] = new KeyValuePair<DateTime, long>(environment.Now, pos);
lastPos = pos;
// Calculate SampleWorkTime and SampleWorkFrame for each host
TimeSpan SampleWorkTime = TimeSpan.Zero;
long SampleWorkFrame = 0;
int PosFirst = -1;
if (fullCycle) {
PosFirst = (iterator + 1) % HistoryLength;
} else if (iterator > 0)
PosFirst = 0;
if (PosFirst > -1) {
SampleWorkTime += progressHistory[iterator].Key - progressHistory[PosFirst].Key;
SampleWorkFrame += progressHistory[iterator].Value - progressHistory[PosFirst].Value;
}
if (SampleWorkTime.TotalSeconds > 0 && SampleWorkFrame >= 0) {
ResultFps = SampleWorkFrame / SampleWorkTime.TotalSeconds;
long WorkLeft = FrameCount - pos;
if (WorkLeft <= 0)
ResultTimeLeft = TimeSpan.Zero;
else if (ResultFps > 0)
ResultTimeLeft = TimeSpan.FromSeconds(WorkLeft / ResultFps);
}
iterator = (iterator + 1) % HistoryLength;
if (iterator == 0)
fullCycle = true;
}
}
Here's a couple of utility ex. methods that convert between BPM and TimeSpan:
public static class BpmExtensions
{
const long SecondsPerMinute = TimeSpan.TicksPerMinute / TimeSpan.TicksPerSecond;
public static int ToBpm(this TimeSpan timeSpan)
{
var seconds = 1 / timeSpan.TotalSeconds;
return (int)Math.Round(seconds * SecondsPerMinute);
}
public static TimeSpan ToInterval(this int bpm)
{
var bps = (double)bpm / SecondsPerMinute;
var interval = 1 / bps;
return TimeSpan.FromSeconds(interval);
}
}
Related
I'm just lost and can't seem to know what to do to calculate the simple moving average?
This is one of the method in the file which is used to calculate the simple moving average.
public async Task<decimal?> UpdateAsync(decimal? value, CancellationToken cancelToken)
{
await Task.Run(() =>
{
var av = default(decimal?);
if (_av.Count - 1 >= _p)
{
}
else
{
av = value;
}
_av.Add(av);
return av;
}, cancelToken).ConfigureAwait(false);
throw new Exception("major issue");
}
}
Let's start with the question:
I'm just lost and can't seem to know what to do to calculate the
simple moving average?
Given
public static class Extensions
{
public static IEnumerable<decimal> MovingAvg(this IEnumerable<decimal> source, int period)
{
var buffer = new Queue<decimal>();
foreach (var value in source)
{
buffer.Enqueue(value);
// sume the buffer for the average at any given time
yield return buffer.Sum() / buffer.Count;
// Dequeue when needed
if (buffer.Count == period)
buffer.Dequeue();
}
}
}
Usage
static void Main(string[] args)
{
var input = new decimal[] { 1, 2, 2, 4, 5, 6, 6, 6, 9, 10, 11, 12, 13, 14, 15 };
var result = input.MovingAvg(2);
Console.WriteLine(string.Join(", ",result));
}
Output
1, 1.5, 2, 3, 4.5, 5.5, 6, 6, 7.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5
So first of all what is moving average
A simple moving average is a method for computing an average of a stream of numbers by only averaging the last P numbers from the stream, where P is known as the period.
Next is the code as how I imagined my moving average to be implemented. It is possible to use LINQ but at each and every step after we add a number I want my Average to be updated.
My code is heavily commented so please read the comments.
public class MovingAverageCalculator {
/// <summary>
/// Maximum number of numbers this moving average calculator can hold.
/// </summary>
private readonly int maxElementCount;
/// <summary>
/// Numbers which will be used for calculating moving average.
/// </summary>
private readonly int[] currentElements;
/// <summary>
/// At which index the next number will be added.
/// </summary>
private int currentIndex;
/// <summary>
/// How many elements are there currently in this moving average calculator.
/// </summary>
private int currentElementCount;
/// <summary>
/// Current total of all the numbers that are being managed by this moving average calculator
/// </summary>
private double currentTotal;
/// <summary>
/// Current Average of all the numbers.
/// </summary>
private double currentAvg;
/// <summary>
/// An object which can calcauclate moving average of given numbers.
/// </summary>
/// <param name="period">Maximum number elements</param>
public MovingAverageCalculator(int period) {
maxElementCount = period;
currentElements = new int[maxElementCount];
currentIndex = 0;
currentTotal = 0;
currentAvg = 0;
}
/// <summary>
/// Adds an item to the moving average series then updates the average.
/// </summary>
/// <param name="number">Number to add.</param>
public void AddElement(int number){
// You can only have at most maximum elements in your moving average series.
currentElementCount = Math.Min(++currentElementCount, maxElementCount);
// IF your current index reached the maximum allowable number then you must reset
if (currentIndex == maxElementCount){
currentIndex = 0;
}
// Copy the current index number to the local variable
var temp = currentElements[currentIndex];
// Substract the value from the current total because it will be replaced by the added number.
currentTotal -= temp;
// Add the number to the current index
currentElements[currentIndex] = number;
// Increase the total by the added number.
currentTotal += number;
// Increase index
currentIndex++;
// Calculate average
currentAvg = (double)currentTotal / currentElementCount;
}
/// <summary>
/// Gets the current average
/// </summary>
/// <returns>Average</returns>
public double GetAverage() => currentAvg;
}
And lastly, I checked your code but It does not make sense to me
Given this problem:
Consider two of the planets in the orbital system: Earth and Mars.
Assume the Earth orbits the Sun in exactly 365 Earth days, and Mars
orbits the Sun in exactly 687 Earth days. Thus the Earth’s orbit
starts at day 0 and continues to day 364, and then starts over at day
0. Mars orbits similarly, but on a 687-day time scale.
We would like to find out how long it will take until both planets are
on day. 0 of their orbits simultaneously. Write a program that can
determine this.
Input Format:
The first line of input contains an integer N indicating the number of
test cases. N lines follow. Each test case contains two integers E and
M. These indicate which days Earth and Mars are at their respective
orbits.
Output Format:
For each case, display the case number followed by the smallest number
of days until the two planets will both be on day 0 of their orbits.
Follow the format of the sample output.
Sample Input 1
0 0
364 686
360 682
0 1
1 0
Sample Output 1
Case 1: 0
Case 2: 1
Case 3: 5
Case 4: 239075
Case 5: 11679
I tried solving the problem using modules but it doesn't seem correct
static string readInput;
static string firstStr = "";
static string secondStr = "";
static int firstInput;
static int secondInput;
static int testCases = 10;
static int caseNumber = 1;
static int outPut;
caseNumber <= testCases
static void Main(string[] args) {
//recall runProcess as long caseNumber is less or equal testCases
while (caseNumber <= testCases) {
runProcess();
Console.WriteLine("Case " + caseNumber + ": " + outPut);
caseNumber++;
}
}
Read input from console:
/// <summary>
/// This is the main process, is extracted to void so we can recall it.
/// </summary>
public static void runProcess() {
readInput = Console.ReadLine();
if (readInput != null) {
for (int i = 0; i < readInput.Length; i++) {
secondStr = secondStr + readInput[i];
if (readInput[i] == ' ') {
firstStr = secondStr;
secondStr = "";
continue;
}
}
}
firstInput = Convert.ToInt32(firstStr);
secondInput = Convert.ToInt32(secondStr);
outPut = atZero(firstInput, secondInput);
}
/// <summary>
/// This method takes the input data from the console to later determine the zero point
/// </summary>
/// <param name="earthDays"></param>
/// <param name="marsDays"></param>
/// <returns></returns>
public static int atZero(int earthDays, int marsDays) {
int earthOrbit = 365;
int marsOrbit = 687;
int modEarth = earthOrbit;
int modMars = marsOrbit;
int earthDistinction = earthOrbit - earthDays;
int marsDistinction = marsOrbit - marsDays;
if ((modInverse(earthDistinction, marsDistinction, modMars)) == 0) {
return (modInverse(marsDistinction, earthDistinction, modEarth)) * marsDistinction;
} else {
return (modInverse(earthDistinction, marsDistinction, modMars)) * earthDistinction;
}
}
mod invert
/// <summary>
/// The method below takes a denominator, numerator and a mod to later invert the mod.
/// </summary>
/// <param name="denominator"></param>
/// <param name="numerator"></param>
/// <param name="mod"></param>
/// <returns>modInverse</returns>
static int modInverse(int denominator, int numerator, int mod) {
int i = mod, outputAll = 0, d = numerator;
while (denominator > 0) {
int divided = i / denominator, x = denominator;
denominator = i % x;
i = x;
x = d;
d = outputAll - divided * x;
outputAll = x;
}
outputAll %= mod;
if (outputAll < 0) outputAll = (outputAll + mod) % mod;
return outputAll;
}
Is there any way to solve the problem without modules?
Thanks.
A straight forward way to calculate a solution could be this method:
private static int DaysTillBothAt0(int currentEarthDay, int currentMarsDay)
{
int result = 0, earth = currentEarthDay, mars = currentMarsDay;
while (earth != 0 || mars != 0)
{
result += 1;
earth = (earth + 1) % 365;
mars = (mars + 1) % 687;
}
return result;
}
This is of course not the fastest alogrithm or mathematically extraordinary elegant, but for the required data range performance doesn't matter here at all. (I don't know what your teacher expects, though).
It simply counts the orbits forward until they meet at 0.
You can use this for your test cases like this:
result = DaysTillBothAt0(0, 0); // 0
result = DaysTillBothAt0(364, 686); // 1
result = DaysTillBothAt0(360, 682); // 5
result = DaysTillBothAt0(0, 1); // 239075
result = DaysTillBothAt0(1, 0); // 11679
One more solution for this problem
private static int DaysTillBothAt0(int currentEarthday, int currentMarsday) {
int count = 365 - currentEarthday;
currentMarsday = (currentMarsday + count) % 687;
while (currentMarsday != 0) {
currentMarsday = (currentMarsday + 365) % 687;
count += 365;
}
return currentMarsday;
}
I'm developing a project using DirectShow .NET.
I'm trying to integrate a library called "WPF Sound Visualization Library" which creates a spectrum analyzer visual.
In order for the visual to work I need to implement these 2 methods in my player:
GetFFTData(float[] fftDataBuffer) - Assigns current FFT data to a buffer.
Remarks: The FFT data in the buffer should consist only of the real number intensity values. This means that if your FFT algorithm returns complex numbers (as many do), you'd run an algorithm similar to: for(int i = 0; i < complexNumbers.Length / 2; i++) fftResult[i] = Math.Sqrt(complexNumbers[i].Real * complexNumbers[i].Real + complexNumbers[i].Imaginary * complexNumbers[i].Imaginary);
GetFFTFrequencyIndex(int frequency) - Gets the index in the FFT data buffer for a given frequency.
Edit:
I already added the SampleGrabber and integrated it's callback with the GetFFTData (which is still not tested). But how do integrate the GetFFTFrequencyIndex method?
protected int SampleCB(double SampleTime, IMediaSample pSample)
{
IntPtr pointer = IntPtr.Zero;
pSample.GetPointer(out pointer);
sampleDataBytes = new byte[pSample.GetSize()];
Marshal.Copy(pointer, sampleDataBytes, 0, sampleDataBytes.Length);
var sampleTime = SampleTime;
var actualDataLength = pSample.GetActualDataLength();
/* Release unmanaged resources */
Marshal.ReleaseComObject(pSample);
pSample = null;
return (int)HResults.S_OK;
}
#region ISpectrumPlayer
byte[] sampleDataBytes = null;
public bool GetFFTData(float[] fftDataBuffer)
{
if (sampleDataBytes != null)
{
var sampleData = Utils.GetInt16Array(sampleDataBytes);
double[] pRealIn = new double[sampleData.Length];
for (var i = 0; i <= sampleData.Length - 1; i++)
pRealIn[i] = sampleData[i];
var pImagIn = new double[sampleDataBytes.Length];
var pRealOut = new double[sampleDataBytes.Length];
var pImagOut = new double[sampleDataBytes.Length];
FFTUtils.Compute((uint) pRealIn.Length, pRealIn, pImagIn, pRealOut, pImagOut, false);
fftDataBuffer = new float[sampleDataBytes.Length];
for (int i = 0; i < pRealOut.Length; i++)
fftDataBuffer[i] = (float) Math.Sqrt(pRealOut[i] * pRealOut[i] + pImagOut[i] * pImagOut[i]);
}
return true;
}
public int GetFFTFrequencyIndex(int frequency)
{
throw new NotImplementedException();
}
#endregion
I ודקג this class with methods that can help:
public class FFTUtils
{
public const Double DDC_PI = 3.14159265358979323846;
/// <summary>
/// Verifies a number is a power of two
/// </summary>
/// <param name="x">Number to check</param>
/// <returns>true if number is a power two (i.e.:1,2,4,8,16,...)</returns>
public static Boolean IsPowerOfTwo(UInt32 x)
{
return ((x != 0) && (x & (x - 1)) == 0);
}
/// <summary>
/// Get Next power of number.
/// </summary>
/// <param name="x">Number to check</param>
/// <returns>A power of two number</returns>
public static UInt32 NextPowerOfTwo(UInt32 x)
{
x = x - 1;
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >> 16);
return x + 1;
}
/// <summary>
/// Get Number of bits needed for a power of two
/// </summary>
/// <param name="PowerOfTwo">Power of two number</param>
/// <returns>Number of bits</returns>
public static UInt32 NumberOfBitsNeeded(UInt32 PowerOfTwo)
{
if (PowerOfTwo > 0)
{
for (UInt32 i = 0, mask = 1; ; i++, mask <<= 1)
{
if ((PowerOfTwo & mask) != 0)
return i;
}
}
return 0; // error
}
/// <summary>
/// Reverse bits
/// </summary>
/// <param name="index">Bits</param>
/// <param name="NumBits">Number of bits to reverse</param>
/// <returns>Reverse Bits</returns>
public static UInt32 ReverseBits(UInt32 index, UInt32 NumBits)
{
UInt32 i, rev;
for (i = rev = 0; i < NumBits; i++)
{
rev = (rev << 1) | (index & 1);
index >>= 1;
}
return rev;
}
/// <summary>
/// Return index to frequency based on number of samples
/// </summary>
/// <param name="Index">sample index</param>
/// <param name="NumSamples">number of samples</param>
/// <returns>Frequency index range</returns>
public static Double IndexToFrequency(UInt32 Index, UInt32 NumSamples)
{
if (Index >= NumSamples)
return 0.0;
else if (Index <= NumSamples / 2)
return (double)Index / (double)NumSamples;
return -(double)(NumSamples - Index) / (double)NumSamples;
}
/// <summary>
/// Compute FFT
/// </summary>
/// <param name="NumSamples">NumSamples Number of samples (must be power two)</param>
/// <param name="pRealIn">Real samples</param>
/// <param name="pImagIn">Imaginary (optional, may be null)</param>
/// <param name="pRealOut">Real coefficient output</param>
/// <param name="pImagOut">Imaginary coefficient output</param>
/// <param name="bInverseTransform">bInverseTransform when true, compute Inverse FFT</param>
public static void Compute(UInt32 NumSamples, Double[] pRealIn, Double[] pImagIn,
Double[] pRealOut, Double[] pImagOut, Boolean bInverseTransform)
{
UInt32 NumBits; /* Number of bits needed to store indices */
UInt32 i, j, k, n;
UInt32 BlockSize, BlockEnd;
double angle_numerator = 2.0 * DDC_PI;
double tr, ti; /* temp real, temp imaginary */
if (pRealIn == null || pRealOut == null || pImagOut == null)
{
// error
throw new ArgumentNullException("Null argument");
}
if (!IsPowerOfTwo(NumSamples))
{
// error
throw new ArgumentException("Number of samples must be power of 2");
}
if (pRealIn.Length < NumSamples || (pImagIn != null && pImagIn.Length < NumSamples) ||
pRealOut.Length < NumSamples || pImagOut.Length < NumSamples)
{
// error
throw new ArgumentException("Invalid Array argument detected");
}
if (bInverseTransform)
angle_numerator = -angle_numerator;
NumBits = NumberOfBitsNeeded(NumSamples);
/*
** Do simultaneous data copy and bit-reversal ordering into outputs...
*/
for (i = 0; i < NumSamples; i++)
{
j = ReverseBits(i, NumBits);
pRealOut[j] = pRealIn[i];
pImagOut[j] = (double)((pImagIn == null) ? 0.0 : pImagIn[i]);
}
/*
** Do the FFT itself...
*/
BlockEnd = 1;
for (BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1)
{
double delta_angle = angle_numerator / (double)BlockSize;
double sm2 = Math.Sin(-2 * delta_angle);
double sm1 = Math.Sin(-delta_angle);
double cm2 = Math.Cos(-2 * delta_angle);
double cm1 = Math.Cos(-delta_angle);
double w = 2 * cm1;
double ar0, ar1, ar2;
double ai0, ai1, ai2;
for (i = 0; i < NumSamples; i += BlockSize)
{
ar2 = cm2;
ar1 = cm1;
ai2 = sm2;
ai1 = sm1;
for (j = i, n = 0; n < BlockEnd; j++, n++)
{
ar0 = w * ar1 - ar2;
ar2 = ar1;
ar1 = ar0;
ai0 = w * ai1 - ai2;
ai2 = ai1;
ai1 = ai0;
k = j + BlockEnd;
tr = ar0 * pRealOut[k] - ai0 * pImagOut[k];
ti = ar0 * pImagOut[k] + ai0 * pRealOut[k];
pRealOut[k] = (pRealOut[j] - tr);
pImagOut[k] = (pImagOut[j] - ti);
pRealOut[j] += (tr);
pImagOut[j] += (ti);
}
}
BlockEnd = BlockSize;
}
/*
** Need to normalize if inverse transform...
*/
if (bInverseTransform)
{
double denom = (double)(NumSamples);
for (i = 0; i < NumSamples; i++)
{
pRealOut[i] /= denom;
pImagOut[i] /= denom;
}
}
}
/// <summary>
/// Calculate normal (power spectrum)
/// </summary>
/// <param name="NumSamples">Number of sample</param>
/// <param name="pReal">Real coefficient buffer</param>
/// <param name="pImag">Imaginary coefficient buffer</param>
/// <param name="pAmpl">Working buffer to hold amplitude Xps(m) = | X(m)^2 | = Xreal(m)^2 + Ximag(m)^2</param>
public static void Norm(UInt32 NumSamples, Double[] pReal, Double[] pImag, Double[] pAmpl)
{
if (pReal == null || pImag == null || pAmpl == null)
{
// error
throw new ArgumentNullException("pReal,pImag,pAmpl");
}
if (pReal.Length < NumSamples || pImag.Length < NumSamples || pAmpl.Length < NumSamples)
{
// error
throw new ArgumentException("Invalid Array argument detected");
}
// Calculate amplitude values in the buffer provided
for (UInt32 i = 0; i < NumSamples; i++)
{
pAmpl[i] = pReal[i] * pReal[i] + pImag[i] * pImag[i];
}
}
/// <summary>
/// Find Peak frequency in Hz
/// </summary>
/// <param name="NumSamples">Number of samples</param>
/// <param name="pAmpl">Current amplitude</param>
/// <param name="samplingRate">Sampling rate in samples/second (Hz)</param>
/// <param name="index">Frequency index</param>
/// <returns>Peak frequency in Hz</returns>
public static Double PeakFrequency(UInt32 NumSamples, Double[] pAmpl, Double samplingRate, ref UInt32 index)
{
UInt32 N = NumSamples >> 1; // number of positive frequencies. (numSamples/2)
if (pAmpl == null)
{
// error
throw new ArgumentNullException("pAmpl");
}
if (pAmpl.Length < NumSamples)
{
// error
throw new ArgumentException("Invalid Array argument detected");
}
double maxAmpl = -1.0;
double peakFreq = -1.0;
index = 0;
for (UInt32 i = 0; i < N; i++)
{
if (pAmpl[i] > maxAmpl)
{
maxAmpl = (double)pAmpl[i];
index = i;
peakFreq = (double)(i);
}
}
return samplingRate * peakFreq / (double)(NumSamples);
}
}
Thank you so much!
If I remember well, the algorithm takes a real (e.g. int[n]) signal or a complex one (e.g. int[n][2]) and returns a complex FFT result.
So, it seems quite easy:
You take your input values (that you can plot as value-to-time in a chart, e.g. the left speaker audio values) and you feed them in the pRealIn parameter. In pImagIn you put zeros (as many as in pRealIn). In bInverseTransform you put false (of course).
Then you will take the result back in pRealOut & pImagOut. The result buffers should logically be of the same size as the input buffers.
You must take those two output buffers and combine them in pair like so (for each element of the OUT arrays):
fftDataBuffer[k] = Math.Sqrt(pRealOut[k] * pRealOut[k] + pImagOut[k] * pImagOut[k]); // Do this from 1 to n
FFT result is an array of complex values (x = real part and y = imaginary part - you can depict it on a Cartesian system as a vector). You want the vector's size/amplitude that why you do the above.
That is for GetFFTData.
I see that you have a function called IndexToFrequency. So that may work.
All you have to do is call this method for every index of your buffers. That is:
for(int i=0; i<n; i++) freq[i] = IndexToFrequency(i, n);
Keep those values stored and then in your GetFFTFrequencyIndex(int frequency) you find the closest match of the input parameter (frequency) to the elements in freq[n] and return its index.
I think that will be enough.
Important: Make sure that your buffers have a power-of-two size (NextPowerOfTwo seems to be designed to help you do just that).
If your data happens to be smaller some times, you can pad the values with zeros at the end (a.k.a. append zeros to your input buffers).
Also: To get a better resolution you can again pad with zeros your data. This will increase the 'smoothness' of your result which may be desirable.
Where did you find this code, if I may ask (just curious :) )?
So, that's all it! :)
I don't know it my nomenclature is correct! Anyway, these are the integer I have, for example :
76
121
9660
And I'd like to round them to the close hundred, such as they must become :
100
100
9700
How can I do it faster in C#? I think about an algorithm, but maybe there are some utilities on C#?
Try the Math.Round method. Here's how:
Math.Round(76d / 100d, 0) * 100;
Math.Round(121d / 100d, 0) * 100;
Math.Round(9660d / 100d, 0) * 100;
I wrote a simple extension method to generalize this kind of rounding a while ago:
public static class MathExtensions
{
public static int Round(this int i, int nearest)
{
if (nearest <= 0 || nearest % 10 != 0)
throw new ArgumentOutOfRangeException("nearest", "Must round to a positive multiple of 10");
return (i + 5 * nearest / 10) / nearest * nearest;
}
}
It leverages integer division to find the closest rounding.
Example use:
int example = 152;
Console.WriteLine(example.Round(100)); // round to the nearest 100
Console.WriteLine(example.Round(10)); // round to the nearest 10
And in your example:
Console.WriteLine(76.Round(100)); // 100
Console.WriteLine(121.Round(100)); // 100
Console.WriteLine(9660.Round(100)); // 9700
Try this expression:
(n + 50) / 100 * 100
Caveat: only works for non-negative n.
Just some addition to #krizzzn's accepted answer...
Do note that the following will return 0:
Math.Round(50d / 100d, 0) * 100;
Consider using the following and make it return 100 instead:
Math.Round(50d / 100d, 0, MidpointRounding.AwayFromZero) * 100;
Depending on what you're doing, using decimals might be a better choice (note the m):
Math.Round(50m / 100m, 0, MidpointRounding.AwayFromZero) * 100m;
I know this is an old thread. I wrote a new method. Hope this will be useful for some one.
public static double Round(this float value, int precision)
{
if (precision < -4 && precision > 15)
throw new ArgumentOutOfRangeException("precision", "Must be and integer between -4 and 15");
if (precision >= 0) return Math.Round(value, precision);
else
{
precision = (int)Math.Pow(10, Math.Abs(precision));
value = value + (5 * precision / 10);
return Math.Round(value - (value % precision), 0);
}
}
Example:
float value = 6666.677777F;
Console.Write(value.Round(2)); //6666.68
Console.Write(value.Round(0)); //6667
Console.Write(value.Round(-2)); //6700
Hi i write this extension this gets the next hundred for each number you pass
/// <summary>
/// this extension gets the next hunfìdred for any number you whant
/// </summary>
/// <param name="i">numeber to rounded</param>
/// <returns>the next hundred number</returns>
/// <remarks>
/// eg.:
/// i = 21 gets 100
/// i = 121 gets 200
/// i = 200 gets 300
/// i = 1211 gets 1300
/// i = -108 gets -200
/// </remarks>
public static int RoundToNextHundred(this int i)
{
return i += (100 * Math.Sign(i) - i % 100);
//use this line below if you want RoundHundred not NEXT
//return i % 100 == byte.MinValue? i : i += (100 * Math.Sign(i) - i % 100);
}
//and for answer at title point use this algoritm
var closeHundred = Math.Round(number / 100D)*100;
//and here the extension method if you prefer
/// <summary>
/// this extension gets the close hundred for any number you whant
/// </summary>
/// <param name="number">number to be rounded</param>
/// <returns>the close hundred number</returns>
/// <remarks>
/// eg.:
/// number = 21 gets 0
/// number = 149 gets 100
/// number = 151 gets 200
/// number = -149 gets -100
/// number = -151 gets -200
/// </remarks>
public static int RoundCloseHundred(this int number)
{
return (int)Math.Round(number / 100D) * 100;
}
If you only want to round integer numbers up (as the OP actually did), then you can resort to this solution:
public static class MathExtensions
{
public static int RoundUpTo(this int number, int nearest)
{
if (nearest < 10 || nearest % 10 != 0)
throw new ArgumentOutOfRangeException(nameof(nearest), $"{nameof(nearest)} must be a positive multiple of 10, but you specified {nearest}.");
int modulo = number % nearest;
return modulo == 0 ? number : modulo > 0 ? number + (nearest - modulo) : number - modulo;
}
}
If you want to perform floating-point (or decimal) rounding, then resort to the answers of #krizzzn and #Jim Aho.
int num = 9660;
int remainder = num % 100;
Console.WriteLine(remainder < 50 ? num - remainder : num + (100 -remainder));
Note: I haven't tested this thoroughly.
I had a similar project internally where the business requirements were to search within the 100's range of a given number and find duplicate DB records. So if the user was using line 856 I would search 800 - 899. If the user was using 8567 I would search 8500 - 8599. Not an exact rounding by 100's, but thought I would include my unique approach as some of these basic coding questions are embedded within a larger business project. To test this I seeded a decimal list from 1 - 99999 and spit the results out into a file.
/// <summary>
/// This method accepts an inbound Line Number and returns the line range
/// in the form of lowest to highest based on 100's
/// Example would be 9122 returns 9100 - 9199
/// It's used for generating some additional BOM Temp functionality.
/// </summary>
/// <param name="inboundNumber"></param>
/// <returns></returns>
public static ProjectLineRange CalculateLineRange(decimal inboundNumber)
{
var lineRange = new ProjectLineRange();
var numberLength = inboundNumber.ToString(CultureInfo.InvariantCulture).Length;
switch (numberLength)
{
case 0: //NULL?
break;
case 1: //Represents 1 - 9
lineRange.LineBottom = 1;
lineRange.LineTop = 99;
break;
case 2: //Represents 10 - 99
lineRange.LineBottom = 1;
lineRange.LineTop = 99;
break;
case 3: //Represents 100 - 999
lineRange = CalculateHundredsRange((int)(inboundNumber / 100));
break;
case 4: //Represents 1000 - 9999
lineRange = CalculateThousandsRange(
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(1, 1)),
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(0, 1)));
break;
case 5: //Represents 10000 - 99999
lineRange = CalculateTenThousandsRange(
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(2, 1)),
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(1, 1)),
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(0, 1)));
break;
}
return lineRange;
}
public class ProjectLineRange
{
public decimal LineBottom { get; set; }
public decimal LineTop { get; set; }
}
/// <summary>
/// Helper method to return the range for the 100's place
/// </summary>
/// <param name="hundredsPlaceValue"></param>
/// <returns></returns>
public static ProjectLineRange CalculateHundredsRange(int hundredsPlaceValue)
{
var tempLineRange = new ProjectLineRange();
tempLineRange.LineBottom = hundredsPlaceValue * 100;
tempLineRange.LineTop = tempLineRange.LineBottom + 99;
return tempLineRange;
}
/// <summary>
/// Helper method to return the range for the 100's place when factoring a 1000's number
/// </summary>
/// <param name="hundredsPlaceValue"></param>
/// <param name="thousandsPlaceValue"></param>
/// <returns></returns>
public static ProjectLineRange CalculateThousandsRange(int hundredsPlaceValue, int thousandsPlaceValue)
{
var tempLineRange = new ProjectLineRange();
var tempThousands = thousandsPlaceValue * 1000;
var hundredsRange = CalculateHundredsRange(hundredsPlaceValue);
tempLineRange.LineBottom = tempThousands + hundredsRange.LineBottom;
tempLineRange.LineTop = tempThousands + hundredsRange.LineTop;
return tempLineRange;
}
/// <summary>
/// Helper method to return the range for the 100's place when factoring a 10000's number
/// </summary>
/// <param name="hundredsPlaceValue"></param>
/// <param name="thousandsPlaceValue"></param>
/// <param name="tenThousandsPlaceValue"></param>
/// <returns></returns>
public static ProjectLineRange CalculateTenThousandsRange(int hundredsPlaceValue, int thousandsPlaceValue, int tenThousandsPlaceValue)
{
var tempLineRange = new ProjectLineRange();
var tempThousands = thousandsPlaceValue * 1000;
var tempTenThousands = tenThousandsPlaceValue * 10000;
var hundredsRange = CalculateHundredsRange(hundredsPlaceValue);
tempLineRange.LineBottom = tempTenThousands + tempThousands + hundredsRange.LineBottom;
tempLineRange.LineTop = tempTenThousands + tempThousands + hundredsRange.LineTop;
return tempLineRange;
}
public static class Maths
{
public static int Round(this int value, int precision)
{
var coef = Math.Pow(10, Math.Abs(precision));
var x = (int)Math.Round(value / coef, 0);
return x * (int)coef;
}
}
var number = 34569;
Debug.WriteLine(number.Round(0));//34569
Debug.WriteLine(number.Round(1));//34570
Debug.WriteLine(number.Round(2));//34600
Debug.WriteLine(number.Round(3));//35000
Debug.WriteLine(number.Round(4));//30000
Debug.WriteLine(number.Round(5));// 0
Debug.WriteLine(number.Round(6));// 0
Here is a problem. I have seen many solutions, but no one seems to be fulfilling the criteria I want...
I want to display the age in this format
20 y(s) 2 m(s) 20 d(s)
20 y(s) 2 m(s)
2 m(s) 20 d(s)
20 d(s)
etc...
I have tried several solutions, but the leap year is causing the problem with me. My unit tests are always being failed because of leap years and no matter how many days come in between, the leap yeas count for extra number of days.
Here is my code....
public static string AgeDiscription(DateTime dateOfBirth)
{
var today = DateTime.Now;
var days = GetNumberofDaysUptoNow(dateOfBirth);
var months = 0;
var years = 0;
if (days > 365)
{
years = today.Year - dateOfBirth.Year;
days = days % 365;
}
if (days > DateTime.DaysInMonth(today.Year, today.Month))
{
months = Math.Abs(today.Month - dateOfBirth.Month);
for (int i = 0; i < months; i++)
{
days -= DateTime.DaysInMonth(today.Year, today.AddMonths(0 - i).Month);
}
}
var ageDescription = new StringBuilder("");
if (years != 0)
ageDescription = ageDescription.Append(years + " y(s) ");
if (months != 0)
ageDescription = ageDescription.Append(months + " m(s) ");
if (days != 0)
ageDescription = ageDescription.Append(days + " d(s) ");
return ageDescription.ToString();
}
public static int GetNumberofDaysUptoNow(DateTime dateOfBirth)
{
var today = DateTime.Now;
var timeSpan = today - dateOfBirth;
var nDays = timeSpan.Days;
return nDays;
}
Any ideas???
UPDATE:
I want the difference between the two dates as:
var dateOfBirth = DateTime.Now.AddYears(-20);
string expected = "20 y(s) ";
string actual; // returns 20 y(s) 5 d(s)
actual = Globals.AgeDiscription(dateOfBirth);
Assert.AreEqual(expected, actual);
Age is pretty tricky. Here's the relevant excerpts from a struct I use.
public struct Age
{
private readonly Int32 _years;
private readonly Int32 _months;
private readonly Int32 _days;
private readonly Int32 _totalDays;
/// <summary>
/// Initializes a new instance of <see cref="Age"/>.
/// </summary>
/// <param name="start">The date and time when the age started.</param>
/// <param name="end">The date and time when the age ended.</param>
/// <remarks>This </remarks>
public Age(DateTime start, DateTime end)
: this(start, end, CultureInfo.CurrentCulture.Calendar)
{
}
/// <summary>
/// Initializes a new instance of <see cref="Age"/>.
/// </summary>
/// <param name="start">The date and time when the age started.</param>
/// <param name="end">The date and time when the age ended.</param>
/// <param name="calendar">Calendar used to calculate age.</param>
public Age(DateTime start, DateTime end, Calendar calendar)
{
if (start > end) throw new ArgumentException("The starting date cannot be later than the end date.");
var startDate = start.Date;
var endDate = end.Date;
_years = _months = _days = 0;
_days += calendar.GetDayOfMonth(endDate) - calendar.GetDayOfMonth(startDate);
if (_days < 0)
{
_days += calendar.GetDaysInMonth(calendar.GetYear(startDate), calendar.GetMonth(startDate));
_months--;
}
_months += calendar.GetMonth(endDate) - calendar.GetMonth(startDate);
if (_months < 0)
{
_months += calendar.GetMonthsInYear(calendar.GetYear(startDate));
_years--;
}
_years += calendar.GetYear(endDate) - calendar.GetYear(startDate);
var ts = endDate.Subtract(startDate);
_totalDays = (Int32)ts.TotalDays;
}
/// <summary>
/// Gets the number of whole years something has aged.
/// </summary>
public Int32 Years
{
get { return _years; }
}
/// <summary>
/// Gets the number of whole months something has aged past the value of <see cref="Years"/>.
/// </summary>
public Int32 Months
{
get { return _months; }
}
/// <summary>
/// Gets the age as an expression of whole months.
/// </summary>
public Int32 TotalMonths
{
get { return _years * 12 + _months; }
}
/// <summary>
/// Gets the number of whole weeks something has aged past the value of <see cref="Years"/> and <see cref="Months"/>.
/// </summary>
public Int32 Days
{
get { return _days; }
}
/// <summary>
/// Gets the total number of days that have elapsed since the start and end dates.
/// </summary>
public Int32 TotalDays
{
get { return _totalDays; }
}
/// <summary>
/// Gets the number of whole weeks something has aged past the value of <see cref="Years"/> and <see cref="Months"/>.
/// </summary>
public Int32 Weeks
{
get { return (Int32) Math.Floor((Decimal) _days/7); }
}
/// <summary>
/// Gets the age as an expression of whole weeks.
/// </summary>
public Int32 TotalWeeks
{
get { return (Int32) Math.Floor((Decimal) _totalDays/7); }
}
}
Here's an example unit test that passes:
[Test]
public void Should_be_exactly_20_years_old()
{
var now = DateTime.Now;
var age = new Age(now.AddYears(-20), now);
Assert.That(age, Has.Property("Years").EqualTo(20)
.And.Property("Months").EqualTo(0)
.And.Property("Days").EqualTo(0));
}
Use
Timespan interval = DateTime.Now - DateOfBirth;
Then use
interval.Days
interval.TotalDays;
interval.Hours;
interval.TotalHours;
interval.Minutes;
interval.TotalMinutes;
interval.Seconds;
interval.TotalSeconds;
interval.Milliseconds;
interval.TotalMilliseconds;
interval.Ticks;
to get desired result.
static int AgeInYears(DateTime birthday, DateTime today)
{
return ((today.Year - birthday.Year) * 372 + (today.Month - birthday.Month) * 31 + (today.Day - birthday.Day)) / 372;
}
write this small function to have the number of leap year days between the current year and the date of birth year and add the returned days to the days part of your age:
private static int NumberOfLeapYears(int startYear, int endYear)
{
int counter = 0;
for (int year = startYear; year <= endYear; year++)
counter += DateTime.IsLeapYear(year) ? 1 : 0;
return counter;
}
Check this code:
{
dif = int(datediff("D", Convert.ToDateTime("01/" + Q101m.text + "/" + Q101y.Text), (Convert.ToDateTime(Vdate.text)))/365.25)
//If dif < 15 Or dif > 49
{
MessageBox.Show("xxxxxxx");
Q101m.Focus();
}
}
I created a solution as extension method in DateTime class which is 'derived' from #HackedByChinese:
/// <summary>
/// Calculate age in years relative to months and days, for example Peters age is 25 years 2 months and 10 days
/// </summary>
/// <param name="startDate">The date when the age started</param>
/// <param name="endDate">The date when the age ended</param>
/// <param name="calendar">Calendar used to calculate age</param>
/// <param name="years">Return number of years, with considering months and days</param>
/// <param name="months">Return calculated months</param>
/// <param name="days">Return calculated days</param>
public static bool GetAge(this DateTime startDate, DateTime endDate, Calendar calendar, out int years, out int months, out int days)
{
if (startDate > endDate)
{
years = months = days = -1;
return false;
}
years = months = days = 0;
days += calendar.GetDayOfMonth(endDate) - calendar.GetDayOfMonth(startDate);
// When negative select days of last month
if (days < 0)
{
days += calendar.GetDaysInMonth(calendar.GetYear(startDate), calendar.GetMonth(startDate));
months--;
}
months += calendar.GetMonth(endDate) - calendar.GetMonth(startDate);
// when negative select month of last year
if (months < 0)
{
months += calendar.GetMonthsInYear(calendar.GetYear(startDate));
years--;
}
years += calendar.GetYear(endDate) - calendar.GetYear(startDate);
return true;
}
But I recognized that the results days can differ a little bit from other calculators.