I'm trying to implement a Discrete Fourier Transformation algorithm for a project I'm doing in school. But creating a class is seeming to be difficult(which it shouldn't be).
I'm using Visual Studio 2012.
Basically I need a class called Complex to store the two values I get from a DFT; The real portion and the imaginary portion.
This is what I have so far for that:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SoundEditor_V3
{
public class Complex
{
public double real;
public double im;
public Complex()
{
real = 0;
im = 0;
}
}
}
The problem is that it doesn't recognize the constructor as a constructor, I'm just learning C#, but I looked it up online and this is how it's supposed to look.
But it recognizes my constructor as a method.
Why is that?
Am I creating the class wrong?
It's doing the same thing for my Fourier class as well. So each time I try to create a
Fourier object and then use it's method...there is no such thing.
example, I do this:
Fourier fou = new Fourier();
fou.DFT(s, N, amp, 0);
and it tells me fou is a 'field' but is used like a 'type'
why is it saying that?
Here is the code for my Fourier class as well:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SoundEditor_V3
{
public class Fourier
{
//FOURIER
//N = number of samples
//s is the array of samples(data)
//amp is the array where the complex result will be written to
//start is the where in the array to start
public void DFT(byte[] s, int N, ref Complex[] amp, int start)
{
Complex tem = new Complex();
int f;
int t;
for (f = 0; f < N; f++)
{
tem.real = 0;
tem.im = 0;
for (t = 0; t < N; t++)
{
tem.real += s[t + start] * Math.Cos(2 * Math.PI * t * f / N);
tem.im -= s[t + start] * Math.Sin(2 * Math.PI * t * f / N);
}
amp[f].real = tem.real;
amp[f].im = tem.im;
}
}
//INVERSE FOURIER
public void IDFT(Complex[] A, ref int[] s)
{
int N = A.Length;
int t, f;
double result;
for (t = 0; t < N; t++)
{
result = 0;
for (f = 0; f < N; f++)
{
result += A[f].real * Math.Cos(2 * Math.PI * t * f / N) - A[f].im * Math.Sin(2 * Math.PI * t * f / N);
}
s[t] = (int)Math.Round(result);
}
}
}
}
I'm very much stuck at the moment, any and all help would be appreciated. Thank you.
edit:
this is where I'm trying to access all my classes:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SoundEditor_V3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string filename;
NAudio.Wave.WaveStream waveStream;
private NAudio.Wave.DirectSoundOut sout = null;
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog open = new OpenFileDialog();
open.Filter = "Wave File (*.wav)|*.wav";
if (open.ShowDialog() != DialogResult.OK)
{
return;
}
waveStream = new NAudio.Wave.WaveFileReader(open.FileName);
filename = open.FileName;
sout = new NAudio.Wave.DirectSoundOut();
sout.Init(new NAudio.Wave.WaveChannel32(waveStream));
}
//Play
private void Play_btn_Click(object sender, EventArgs e)
{
sout.Play();
}
//Stop
private void Stop_btn_Click(object sender, EventArgs e)
{
sout.Stop();
waveStream.Position = 0;
}
//Pause
private void Pause_btn_Click(object sender, EventArgs e)
{
sout.Pause();
}
//display fourier
//N = number of samples(length of array)
//s is the array of samples(data)
//amp is the array where the complex result will be written to
//start is the where in the array to start
static int N = 8;
byte[] s = {1,2,3,4,5,6,7,8};
Complex[] amp = new Complex[N];
Fourier xfo = new Fourier();
//xfo.DFT(s, N, amp, 0);
}
}
This call should be inside a method. As of now, it looks its directly under a class.
//xfo.DFT(s, N, amp, 0);
Also add ref for amp. (As the void DFT(...., ref Complex[] amp,....) takes a ref amp parameter.
xfo.DFT(s, N, ref amp, 0);
Oh boy, so much room to improve.
First you are using the class Complex as a struct, in fact there is no need for it to be a class, so make it a struct:
public struct Complex
{
public double Imaginary;
public double Real;
}
No constructor needed, the default constructor (which the compilers add) will set the fields to their default value according to their type, and for double the default value is 0.0 (which is what you are assigning to them anyway*).
I have also renamed im to Imaginary, and don't tell me you have to type more because you got intellisense. If you didn't go download Mono Develop or Visual Studio Express. Oh, I can feel your thinking: we shouldn't relay on the tools. Well, that's right, and that is another reason to write code that is easy to read, even for those unfamiliar with the concepts (it also makes searching easier).
*: I want to note that 0 is a intenger literal and 0.0 is double, but the compiler reconizes this and optimizes the conversion away, so it is the same for practical purposes.
Let's move to your fourier class, first the method DFT, which I copy below (with the names of the fields of Complex renamed):
//FOURIER
//N = number of samples
//s is the array of samples(data)
//amp is the array where the complex result will be written to
//start is the where in the array to start
public void DFT(byte[] s, int N, ref Complex[] amp, int start)
{
Complex tem = new Complex();
int f;
int t;
for (f = 0; f < N; f++)
{
tem.real = 0;
tem.im = 0;
for (t = 0; t < N; t++)
{
tem.real += s[t + start] * Math.Cos(2 * Math.PI * t * f / N);
tem.im -= s[t + start] * Math.Sin(2 * Math.PI * t * f / N);
}
amp[f].real = tem.real;
amp[f].im = tem.im;
}
}
The first thing to notice is that you say that N is the number of samples and s is the samples array. Well, if you have an array you can query the size of the array, which is a good idea even if you want to allow to only process a portion of the array (I think you want that). But, really N and s?
Look, it's like magic:
//FOURIER
//amp is the array where the complex result will be written to
//start is the where in the array to start
public void DFT(byte[] samples, int samplesCount, ref Complex[] amp, int start)
{
Complex tem = new Complex();
int f;
int t;
for (f = 0; f < samplesCount; f++)
{
tem.Real = 0;
tem.Imaginary = 0;
for (t = 0; t < samplesCount; t++)
{
tem.Imaginary += samples[t + start] * Math.Cos(2 * Math.PI * t * f / samplesCount);
tem.Imaginary -= samples[t + start] * Math.Sin(2 * Math.PI * t * f / samplesCount);
}
amp[f].Real = tem.Real;
amp[f].Imaginary = tem.Imaginary;
}
}
Ok, next you say that amp is the output. Well if it is the output, why don't you make it te method return it?
Bam!
//FOURIER
//start is the where in the array to start
Complex[] DFT(byte[] samples, int samplesCount, int start)
{
var = new Complex[samplesCount];
Complex tem = new Complex();
int f;
int t;
for (f = 0; f < samplesCount; f++)
{
tem.Real = 0;
tem.Imaginary = 0;
for (t = 0; t < samplesCount; t++)
{
tem.Imaginary += samples[t + start] * Math.Cos(2 * Math.PI * t * f / samplesCount);
tem.Imaginary -= samples[t + start] * Math.Sin(2 * Math.PI * t * f / samplesCount);
}
result[f].Real = tem.Real;
result[f].Imaginary = tem.Imaginary;
}
return result;
}
Does it really need to be an array? I think this is a good oportunity to use the yield keyword and return IEnumerable<Complex>. But I'll take that you want, in deed, an array.
Now, may be you didn't want to return an array. May be you want to just modify portions of a preexisting array. In that case you should start checking your bounds. And even if that were true, you don't need ref at all! because the array is a reference type. It is a reference passed by value, if you cannot wrap your mind around that idea, just trust me, you can modify the contents of an array and see that reflected outside without ref... passing a reference by reference allows you to change the reference by another one, and you are not doing that.
To demostrate:
void Main()
{
var x = new int[1];
Do(x);
Console.WriteLine(x);
}
void Do (int[] array)
{
array[0] = 1;
}
The output of the previous program (compiled with LinqPad) is "1".
But let's get back to your code, shall we?
I don't know what are f and t. Thankfully I knew that im was imaginary (it was, right?). So I'll not rename them. But I'll move their definition to the loops:
Complex[] DFT(byte[] samples, int samplesCount, int start)
{
var result = new Complex[samplesCount];
Complex tem = new Complex();
for (int f = 0; f < samplesCount; f++)
{
tem.Real = 0;
tem.Imaginary = 0;
for (int t = 0; t < samplesCount; t++)
{
tem.Imaginary += samples[t + start] * Math.Cos(2 * Math.PI * t * f / samplesCount);
tem.Imaginary -= samples[t + start] * Math.Sin(2 * Math.PI * t * f / samplesCount);
}
result[f].Real = tem.Real;
result[f].Imaginary = tem.Imaginary;
}
return result;
}
Note my use of the var keyword. With it the compiler assigns the type of the variable to the type of what I'm using to initialize it. So in this case result is a Complex[] but I did not have to write that twice in the code.
And finally, that part where you copy the contents of the Complex object, well, I'll change that too. Why? Because Complex now is a struct, and structs are valuetypes. So it's content gets copied instead of a reference.
//FOURIER
//start is the where in the array to start
Complex[] DFT(byte[] samples, int samplesCount, int start)
{
var result = new Complex[samplesCount];
Complex tem = new Complex();
for (int f = 0; f < samplesCount; f++)
{
tem.Real = 0;
tem.Imaginary = 0;
for (int t = 0; t < samplesCount; t++)
{
tem.Imaginary += samples[t + start] * Math.Cos(2 * Math.PI * t * f / samplesCount);
tem.Imaginary -= samples[t + start] * Math.Sin(2 * Math.PI * t * f / samplesCount);
}
result[f] = tem;
}
return result;
}
I know you really want to proccess just a part of your array. But bear with me... you will learn a few things and that code will be useful anyway.
The next thing I want is to return an IEnumerable<Complex> which is an interface that represents anything that can be iterated to get objects of type Complex. I'll also use the yield keyword.
Additionally I've got rid of sampleCount and use samples.Length instead.
Just look how beautiful it gets:
//FOURIER
public IEnumerable<Complex> DFT(byte[] samples, int startIndex)
{
int samplesLength = samples.Length;
for (int f = 0; f < samplesLength; f++)
{
Complex resultItem = new Complex();
for (int t = 0; t < samplesLength; t++)
{
resultItem.Real += samples[t + startIndex] * Math.Cos(2 * Math.PI * t * f / samplesLength);
resultItem.Imaginary -= samples[t + startIndex] * Math.Sin(2 * Math.PI * t * f / samplesLength);
}
yield return resultItem;
}
}
In fact, I'll get rid of startIndex too (we are not checking bounds anyway*).
*: that is, we are not checking if the index are inside the array size. I know, I know, you was going to add them later... probably.
Anyway, you are learning some C# here.
//FOURIER
public IEnumerable<Complex> DFT(byte[] samples)
{
int samplesLength = samples.Length;
for (int f = 0; f < samplesLength; f++)
{
Complex resultItem = new Complex();
for (int t = 0; t < samplesLength; t++)
{
resultItem.Real += samples[t] * Math.Cos(2 * Math.PI * t * f / samplesLength);
resultItem.Imaginary -= samples[t] * Math.Sin(2 * Math.PI * t * f / samplesLength);
}
yield return resultItem;
}
}
Well, the next thing that bothers me is the fact that the class Fourier has no state (it has no fields, or any variable which value is persisted... somehow). So, make it a static class with a static method:
public static class Fourier
{
//FOURIER
public static IEnumerable<Complex> DFT(byte[] samples)
{
int samplesLength = samples.Length;
for (int f = 0; f < samplesLength; f++)
{
Complex resultItem = new Complex();
for (int t = 0; t < samplesLength; t++)
{
resultItem.Real += samples[t] * Math.Cos(2 * Math.PI * t * f / samplesLength);
resultItem.Imaginary -= samples[t] * Math.Sin(2 * Math.PI * t * f / samplesLength);
}
yield return resultItem;
}
}
}
Of course you notice I haven't added IDFT. That one is homework.
Now, let's see how you use it. In my case I created a ConsoleApplication, just to have it up and running fast (no time wasted designing a GUI).
What I want is to call Fourier.DFT which I can without an object of type Fourier because it is static (In fact I cannot create an object of type Fourier because it is static).
This method recieves an argument of type byte[]. That one will be new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }. And that method will return something I can use to iterate over to get objects of type Complex. So I want to put it a loop.
This is how my code looks like:
class Program
{
static void Main(string[] args)
{
//display fourier
foreach (var item in Fourier.DFT(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }))
{
Console.WriteLine(item);
}
}
}
Now... the output is... drum roll...
Well, I can't see it, I forgot Console.ReadLine(); but after adding that the output is...
Namespace.Complex
Namespace.Complex
Namespace.Complex
Namespace.Complex
Namespace.Complex
Namespace.Complex
Namespace.Complex
Namespace.Complex
Wait, what? It happens that I haven't told it how to convert an object of type Complex to string. So let's add that:
public struct Complex
{
public double Imaginary;
public double Real;
public override string ToString()
{
return string.Format("Complex [Real: {0}, Imaginary: {1}]", Real, Imaginary);
}
}
Now my output is:
Complex [Real: 36, Imaginary: 0]
Complex [Real: -4, Imaginary: 9,65685424949238]
Complex [Real: -4, Imaginary: 4]
Complex [Real: -4, Imaginary: 1,65685424949239]
Complex [Real: -4, Imaginary: -3,91874033223161E-15]
Complex [Real: -4,00000000000001, Imaginary: -1,65685424949239]
Complex [Real: -4,00000000000002, Imaginary: -4,00000000000001]
Complex [Real: -3,99999999999997, Imaginary: -9,65685424949237]
Is the output correct? I have no freaking idea! I have to learn more about Fourier (but it looks legit).
After verification, the output is correct.
One final note: Step trhoug the code with a debuger, you may find a surprise (hint: yield).
You need a method, try this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SoundEditor_V3
{
public class Complex
{
public double real;
public double im;
public Complex()
{
real = 0;
im = 0;
}
public Setval (double newReal, double newIm)
{
real = newReal;
im = newIm;
}
}
}
In regards to your other class, where is the constructor? ;)
Thank you for all your help; I actually ended up figuring everything out.
I couldn't access methods in the area I was trying to access them in. I had to put them inside a method block because this was all being coded inside a form.
That's my understanding anyway.
But again, thank you for all your suggestions, they were all helpful.
Related
I am using Hybridizer to total a FloatResidentArray and I am not able to return the calculated total to the device (or host) because of the need for a ref statement in the final AtomicExpr.apply statement.
Consider the following code which is based on the GenericReduce example provided by Altimesh.
The code takes a device resident array a, of float of length N and calculates the total – this value is placed in total[0].
[Kernel]
public static void Total(FloatResidentArray a, int N, float[] total)
{
var cache = new SharedMemoryAllocator<float>().allocate(blockDim.x);
int tid = threadIdx.x + blockDim.x * blockIdx.x;
int cacheIndex = threadIdx.x;
float sum = 0f;
while (tid < N)
{
sum = sum + a[tid];
tid += blockDim.x * gridDim.x;
}
cache[cacheIndex] = sum;
CUDAIntrinsics.__syncthreads();
int i = blockDim.x / 2;
while (i != 0)
{
if (cacheIndex < i)
{
cache[cacheIndex] = cache[cacheIndex] + cache[cacheIndex + i];
}
CUDAIntrinsics.__syncthreads();
i >>= 1;
}
if (cacheIndex == 0)
{
AtomicExpr.apply(ref total[0], cache[0], (x, y) => x + y);
}
}
The above code does not compile because you cannot pass a float[] and a FloatResidentArray in the same parameter list.
If total is defined as a FloatResidentArray itself, then the compiler will not allow the ref keyword to be used in the final line of code.
If I simply pass a float, then the returned variable is not updated with the total.
If I pass a ref float - then the program throws a runtime error at the point where the HybRunner wraps the above code to create the dynamic – the error message is
Value types by reference are not supported
How do I return the total? –either to Device or Host memory – both are acceptable.
Well, you need to understand how marshalling works
Object and arrays (even resident array) are all hosts when created in .Net.
Then we marshal them (pin host memory, allocate device memory and copy host to device) right before kernel execution.
For a float[], that will be done automatically
For an IntPtr, we do nothing and the user has to ensure the IntPtr is a valid device pointer containing the data
For a resident array, we do nothing and the user has to manually call RefreshDevice() and RefreshHost when she wants to get the data back and forth.
Mixing ResidentArray and float[] is supported, as show in this screenshot of the generated dll :
What is not supported is : mixing managed types and IntPtr.
Here is a complete version of your code working, and returning the correct result:
using Hybridizer.Runtime.CUDAImports;
using System;
using System.Runtime.InteropServices;
namespace SimpleMetadataDecorator
{
class Program
{
[EntryPoint]
public static void Total(FloatResidentArray a, int N, float[] total)
{
var cache = new SharedMemoryAllocator<float>().allocate(blockDim.x);
int tid = threadIdx.x + blockDim.x * blockIdx.x;
int cacheIndex = threadIdx.x;
float sum = 0f;
while (tid < N)
{
sum = sum + a[tid];
tid += blockDim.x * gridDim.x;
}
cache[cacheIndex] = sum;
CUDAIntrinsics.__syncthreads();
int i = blockDim.x / 2;
while (i != 0)
{
if (cacheIndex < i)
{
cache[cacheIndex] = cache[cacheIndex] + cache[cacheIndex + i];
}
CUDAIntrinsics.__syncthreads();
i >>= 1;
}
if (cacheIndex == 0)
{
AtomicExpr.apply(ref total[0], cache[0], (x, y) => x + y);
}
}
static void Main(string[] args)
{
const int N = 1024 * 1024 * 32;
FloatResidentArray arr = new FloatResidentArray(N);
float[] res = new float[1];
for (int i = 0; i < N; ++i)
{
arr[i] = 1.0F;
}
arr.RefreshDevice();
var runner = HybRunner.Cuda();
cudaDeviceProp prop;
cuda.GetDeviceProperties(out prop, 0);
runner.SetDistrib(16 * prop.multiProcessorCount, 1, 128, 1, 1, 128 * sizeof(float));
var wrapped = runner.Wrap(new Program());
runner.saveAssembly();
cuda.ERROR_CHECK((cudaError_t)(int)wrapped.Total(arr, N, res));
cuda.ERROR_CHECK(cuda.DeviceSynchronize());
Console.WriteLine(res[0]);
}
}
}
I'm working on a Midpoint Riemann Sum program, and it finds the integral of a randomly generated function called f.
Here's what wrote:
public static double FindIntegral (double start, double end, function f)
{
double sum = 0;
double stepsize = 1E-2;
int numSteps = (int)((end - start) / stepsize);
for (int i = 0; i < numSteps; i++)
{
sum += f(start + (stepsize * (i + 0.5)));
}
return sum * stepsize;
}
The function returns numbers that are too low (I have a reliable checking mechanism).
I put in x^3 for f, and I got the right answer. I tried a couple of more integrable functions and got a good answer. But somehow once I put in f it doesn't work.
I got the math formula for "Riemann Midpoint Sum" from here.
My implementation below seems to get the right answer (using the example function on the page). I used a class because 1) I could make the algorithm work specifying either the step size or the number of rectangles (I preferred the latter) and 2) I didn't see any reason to hard-code either into the algorithm.
As it turns out your code seemed to work just fine (see below); Make sure the code you have here in your question is what you're executing and make sure your expected result is accurate and that you're supplying good inputs (i.e. you don't have start and end backwards or the wrong function f or something). In other words what you provided in your question looks fine. Note double is approximate in C# (floating point arithmetic, in general) so to compare equality you can't use == unless you want exact if you're using unit tests or something.
public class Program
{
public static void Main()
{
function f = x => 50 / (10 + x * x);
// 9.41404285216233
Console.Out.WriteLine(new RiemannMidpointSum(6).FindIntegral(1, 4, f));
// 9.41654853716462
Console.Out.WriteLine(new RiemannMidpointSum(1E-2).FindIntegral(1, 4, f));
// 9.41654853716462
Console.Out.WriteLine(Program.FindIntegral(1, 4, f));
}
// This is your function.
public static double FindIntegral (double start, double end, function f)
{
double sum = 0;
double stepsize = 1E-2;
int numSteps = (int)((end - start) / stepsize);
for (int i = 0; i < numSteps; i++)
{
sum += f(start + (stepsize * (i + 0.5)));
}
return sum * stepsize;
}
}
public delegate double function(double d);
public class RiemannMidpointSum
{
private int? _numberOfRectangles;
private double? _widthPerRectangle;
public RiemannMidpointSum(int numberOfRectangles)
{
// TODO: Handle non-positive input.
this._numberOfRectangles = numberOfRectangles;
}
public RiemannMidpointSum(double widthPerRectangle)
{
// TODO: Handle non-positive input.
this._widthPerRectangle = widthPerRectangle;
}
public double FindIntegral(double a, double b, function f)
{
var totalWidth = b - a;
var widthPerRectangle = this._widthPerRectangle ?? (totalWidth / this._numberOfRectangles.Value);
var numberOfRectangles = this._numberOfRectangles ?? ((int)Math.Round(totalWidth / this._widthPerRectangle.Value, 0));
double sum = 0;
foreach (var i in Enumerable.Range(0, numberOfRectangles))
{
var rectangleMidpointX = a + widthPerRectangle * i + widthPerRectangle / 2;
var rectangleHeightY = f(rectangleMidpointX);
var rectangleArea = widthPerRectangle * rectangleHeightY;
sum += rectangleArea;
}
return sum;
}
}
I am trying to improve the speed of my program without changing the algorithm.
Currently I use this implementation of DFT:
public double[] dft(double[] data) {
int n = data.Length;
int m = n;// I use m = n / 2d;
float[] real = new float[n];
float[] imag = new float[n];
double[] result = new double[m];
float pi_div = (float)(2.0 * Math.PI / n);
for (int w = 0; w < m; w++) {
float a = w * pi_div;
for (int t = 0; t < n; t++) {
real[w] += (float)(data[t] * Math.Cos(a * t)); //thinking of threading this
imag[w] += (float)(data[t] * Math.Sin(a * t)); //and this
}
result[w] = (float)(Math.Sqrt(real[w] * real[w] + imag[w] * imag[w]) / n);
}
return result;
}
It is rather slow but it has one spot where I can see improvements can be made.
The internal parts of the functions are two separate tasks. The real and imaginary summations can be done separately but should always join to calculate the result.
Any ideas? I tried a few implementations I saw on the web but they all crashed and I have very little threading experience.
When you have a CPU bound algorithm that can be parallelized you can easily transform you single threaded implementation into a multi-threaded using the Parallel class.
In your case you have two nested loops but the number of iterations of the outer loop is much larger than the number of CPU cores you can execute on so it is only necessary to parallelize the outer loop to get all cores spinning:
public double[] ParallelDft(double[] data) {
int n = data.Length;
int m = n;// I use m = n / 2d;
float[] real = new float[n];
float[] imag = new float[n];
double[] result = new double[m];
float pi_div = (float)(2.0 * Math.PI / n);
Parallel.For(0, m,
w => {
float a = w * pi_div;
for (int t = 0; t < n; t++) {
real[w] += (float)(data[t] * Math.Cos(a * t)); //thinking of threading this
imag[w] += (float)(data[t] * Math.Sin(a * t)); //and this
}
result[w] = (float)(Math.Sqrt(real[w] * real[w] + imag[w] * imag[w]) / n);
}
);
return result;
}
I have taken your code and replaced the outer for loop with Parallel.For. On my computer with eight hyper-threaded cores I get a sevenfold increase in execution speed.
Another way to increase the execution speed is to employ the SIMD instruction set on the CPU. The System.Numerics.Vectors library and the Yeppp! library allows you to call SIMD instructions from managed code but it will require some work on your behalf to implement the algorithm using these instructions.
You should create a new Task for inner For, and each task will save result in a thread safe dictionary (ConcurrentDictionary).
I think following code be useful:
public ConcurrentDictionary<int, double> result = new ConcurrentDictionary<int, double>();
public void dft(double[] data)
{
int n = data.Length;
int m = n;// I use m = n / 2d;
float pi_div = (float)(2.0 * Math.PI / n);
for (int w = 0; w < m; w++)
{
var w1 = w;
Task.Factory.StartNew(() =>
{
float a = w1*pi_div;
float real = 0;
float imag=0;
for (int t = 0; t < n; t++)
{
real += (float)(data[t] * Math.Cos(a * t));
imag += (float)(data[t] * Math.Sin(a * t));
}
result.TryAdd(w1, (float) (Math.Sqrt(real*real + imag*imag)/n));
});
}
}
I am trying to learn C#, and as an exercise for myself, I have coded the Box-Muller method, and am now trying to plot a histogram of my simulated datapoints to check if the data looks fairly normal.
For creating the histogram, I am following this guide here: http://www.i-programmer.info/programming/uiux/2756-getting-started-with-net-charts.html
I have included my code so far below. My problem is that I get squiggly red lines under "chart1" in the main method, and I get the error "The name 'chart1' does not exist in the current context'. There seem to be nothing from the guide that I am missing. Can anyone clear up what I am missing?
Best regards.
using System;
using System.Windows.Forms.DataVisualization.Charting;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
double[] normalData = new double[200];
for (int i = 1; i <= 100; i++)
{
Tuple<double, double> Z = BoxMuller(i);
normalData[2 * i - 2] = Z.Item1;
normalData[2 * i - 1] = Z.Item2;
//Console.WriteLine("{0} {1}", normalData[2 * i - 2], normalData[2 * i - 1]);
}
//Trying to make a simple histogram (to begin with)
DataPoint Dp = new DataPoint();
Dp.SetValueY(3);
chart1.Series.Clear();
chart1.Series.Add("My Data");
}
static Tuple<double, double> BoxMuller(int i)
{
Random rand = new Random(i);
double U1 = rand.NextDouble();
double U2 = rand.NextDouble();
double R = -2 * Math.Log(U1);
double V = 2 * Math.PI * U2;
double Z1 = Math.Sqrt(R) * Math.Cos(V);
double Z2 = Math.Sqrt(R) * Math.Sin(V);
Tuple<double, double> tuple = new Tuple<double, double>(Z1, Z2);
return tuple;
}
}
}
I had a look at the wave format today and created a little wave generator. I create a sine sound like this:
public static Wave GetSine(double length, double hz)
{
int bitRate = 44100;
int l = (int)(bitRate * length);
double f = 1.0 / bitRate;
Int16[] data = new Int16[l];
for (int i = 0; i < l; i++)
{
data[i] = (Int16)(Math.Sin(hz * i * f * Math.PI * 2) * Int16.MaxValue);
}
return new Wave(false, Wave.MakeInt16WaveData(data));
}
MakeInt16WaveData looks like this:
public static byte[] MakeInt16WaveData(Int16[] ints)
{
int s = sizeof(Int16);
byte[] buf = new byte[s * ints.Length];
for(int i = 0; i < ints.Length; i++)
{
Buffer.BlockCopy(BitConverter.GetBytes(ints[i]), 0, buf, i * s, s);
}
return buf;
}
This works as expected! Now I wanted to swoop from one frequency to another like this:
public static Wave GetSineSwoop(double length, double hzStart, double hzEnd)
{
int bitRate = 44100;
int l = (int)(bitRate * length);
double f = 1.0 / bitRate;
Int16[] data = new Int16[l];
double hz;
double hzDelta = hzEnd - hzStart;
for (int i = 0; i < l; i++)
{
hz = hzStart + ((double)i / l) * hzDelta * 0.5; // why *0.5 ?
data[i] = (Int16)(Math.Sin(hz * i * f * Math.PI * 2) * Int16.MaxValue);
}
return new Wave(false, Wave.MakeInt16WaveData(data));
}
Now, when I swooped from 200 to 100 Hz, the sound played from 200 to 0 hertz. For some reason I had to multiply the delta by 0.5 to get the correct output. What might be the issue here ? Is this an audio thing or is there a bug in my code ?
Thanks
Edit by TaW: I take the liberty to add screenshots of the data in a chart which illustrate the problem, the first is with the 0.5 factor, the 2nd with 1.0 and the 3rd & 4th with 2.0 and 5.0:
Edit: here is an example, a swoop from 200 to 100 hz:
Debug values:
Wave clearly does not end at 100 hz
Digging out my rusty math I think it may be because:
Going in L steps from frequency F1 to F2 you have a frequency of
Fi = F1 + i * ( F2 - F1 ) / L
or with
( F2 - F1 ) / L = S
Fi = F1 + i * S
Now to find out how far we have progressed we need the integral over i, which would be
I(Fi) = i * F1 + 1/2 * i ^ 2 * S
Which give or take resembles the term inside your formula for the sine.
Note that you can gain efficiency by moving the constant part (S/2) out of the loop..