Xamarin-Threading AudioTrack - c#

I am trying to generate white noise on a sinewave but there is a pause in my signal that should not be there.I am not sure why.
I have the write function on a different thread than generator.
here is my code:
public class whitenoise :AudioTrack
{
public whitenoise (int min1) : base(Stream.Music,44100, ChannelOut.Stereo, Encoding.Pcm16bit,793800,AudioTrackMode.Stream)
{
Frequency = 1000;
Amplitude = 1;
n2 = 0;
min = min1;
buffer = new short[793800];
}
public double Frequency { get; set; }
public double Amplitude { get; set; }
static int stopped;
static int n2;
int min;
short[] buffer;
Random rnd1;
void write1()
{
while(n2 < min )
{
Write (buffer, 0,793800);
}
}
public void play()
{
rnd1 = new System.Random();
stopped = 0;
gen(buffer);
ThreadPool.QueueUserWorkItem(o=>write1());
Play();
while (n2 < min)
{
gen (buffer);
//Write (buffer, 0, 793800);
}
stopped = 1;
}
public void gen(short[] buffer)
{
for (int n = 0; n <793800; n++) {
if (Frequency == 0) {
float temp1 = (float)(Amplitude * (2 * rnd1.NextDouble () - 1));
buffer [n] = (short)(temp1 * short.MaxValue);
} else {
float w = (float)( Math.Sin ( n2 * Math.PI * Frequency / 44100D));
float temp1 = (float)(w * Amplitude * (2 * rnd1.NextDouble () - 1));
buffer [n] = (short)(temp1 * short.MaxValue);
}
n2++;
}
}
public void stop ()
{
n2 = (min);
stopped = 1;
}
public int getstopped()
{
return stopped;
}
}
why is it not working?
why is there a pause ?
the gen is making the signal on a different thread
and both functions can use the buffer array
UPDate :
ok so while I was troubleshooting this problem, I learned that write() is called like 4 to 3 more times than gen(). SO, I need to make gen faster, I tried lowering the buffer size and I learned the loses I can go is without having problems in the sound is 44100, but gen is still too slow. so I tried this :
public void gen(short[] buffer)
{
for (int n = 0; n <44100; n++) {
if (Frequency == 0) {
float temp1 = (float)(Amplitude * (2 * rnd1.NextDouble () - 1));
buffer [n] = (short)(temp1 * short.MaxValue);
} else {
float temp1 = (float)( Math.Sin ( n2 * SinMath) * Amplitude * (2 * rnd1.NextDouble () - 1));
buffer [n] = (short)(temp1 * short.MaxValue);
}
n2++;
}
}
SinMath does this Math.PI * Frequency / 44100D somewhere else
but it is still not fast enough
any ideas ?

Related

Is there a way to increase the maximum number of stack frames in Visual Studio (or avoid exceeding it otherwise)?

I am applying the so-called Wolff algorithm to simulate a very large square lattice Ising model at critical temperature in Visual Studio C#. I start out with all lattice sites randomly filled with either -1 or +1, and then the Wolff algorithm is applied for a certain number of times. Basically, per application, it randomly activates one lattice site and it checks if neighbouring lattice sites are of the same spin (the same value as the initially selected site) and with a certain chance it gets activated as well. The process is repeated for every new activation, so the activated lattice sites form a connected subset of the full lattice. All activated spins flip (*= -1). This is done a large number of times.
This is the class I use:
class WolffAlgorithm
{
public sbyte[,] Data;
public int DimX;
public int DimY;
public double ExpMin2BetaJ;
private sbyte[,] transl = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
public WolffAlgorithm(sbyte[,] data, double beta, double j)
{
Data = data;
DimX = data.GetLength(0);
DimY = data.GetLength(1);
ExpMin2BetaJ = Math.Exp(- 2 * beta * j);
}
public void Run(int n, int print_n)
{
Random random = new Random();
DateTime t0 = DateTime.Now;
int act = 0;
for (int i = 0; i < n; i++)
{
int x = random.Next(0, DimX);
int y = random.Next(0, DimY);
int[] pos = { x, y };
List<int[]> activations = new List<int[]>();
activations.Add(pos);
sbyte up_down = Data[x, y];
Data[x, y] *= -1;
CheckActivation(random, up_down, activations, x, y);
act += activations.Count;
if ((i + 1) % print_n == 0)
{
DateTime t1 = DateTime.Now;
Console.WriteLine("n: " + i + ", act: " + act + ", time: " + (t1 - t0).TotalSeconds + " sec");
t0 = t1;
act = 0;
}
}
}
private void CheckActivation(Random random, sbyte up_down, List<int[]> activations, int x, int y)
{
for (int i = 0; i < transl.GetLength(0); i++)
{
int tr_x = (x + transl[i, 0]) % DimX;
if (tr_x < 0) tr_x += DimX;
int tr_y = (y + transl[i, 1]) % DimY;
if (tr_y < 0) tr_y += DimY;
if (Data[tr_x, tr_y] != up_down)
{
continue;
}
if (random.NextDouble() < 1 - ExpMin2BetaJ)
{
int[] new_activation = { tr_x, tr_y };
activations.Add(new_activation);
Data[tr_x, tr_y] *= -1;
CheckActivation(random, up_down, activations, tr_x, tr_y);
}
}
}
}
When I approach the equilibrium configuration, the activated groups become so large, that the recursive function exceeds the maximum number of stack frames (apparently 5000), triggering the StackOverflowException (fitting for my first post on StackOverflow.com, I guess haha).
What I've tried:
I have tried adjusting the maximum number of stack frames like what is proposed here: https://www.poppastring.com/blog/adjusting-stackframes-in-visual-studio
This did not work for me.
I have also tried to reduce the number of stack frames needed by just copying the same function in the function (however ugly this looks):
private void CheckActivation2(Random random, sbyte up_down, List<int[]> activations, int x, int y)
{
for (int i = 0; i < transl.GetLength(0); i++)
{
int tr_x = (x + transl[i, 0]) % DimX;
if (tr_x < 0) tr_x += DimX;
int tr_y = (y + transl[i, 1]) % DimY;
if (tr_y < 0) tr_y += DimY;
if (Data[tr_x, tr_y] != up_down)
{
continue;
}
if (random.NextDouble() < 1 - ExpMin2BetaJ)
{
int[] new_activation = { tr_x, tr_y };
activations.Add(new_activation);
Data[tr_x, tr_y] *= -1;
for (int i2 = 0; i2 < transl.GetLength(0); i2++)
{
int tr_x2 = (tr_x + transl[i2, 0]) % DimX;
if (tr_x2 < 0) tr_x2 += DimX;
int tr_y2 = (tr_y + transl[i2, 1]) % DimY;
if (tr_y2 < 0) tr_y2 += DimY;
if (Data[tr_x2, tr_y2] != up_down)
{
continue;
}
if (random.NextDouble() < 1 - ExpMin2BetaJ)
{
int[] new_activation2 = { tr_x2, tr_y2 };
activations.Add(new_activation2);
Data[tr_x2, tr_y2] *= -1;
CheckActivation2(random, up_down, activations, tr_x2, tr_y2);
}
}
}
}
}
This works, but it is not enough and I don't know how to scale this elegantly by an arbitrary number of times, without calling the function recursively.
I hope anyone can help me with this!

unity freezes when my loop activates, and displays no error message

ok, so i am making a script for my game that generates the composition of a silicate planet. it is not great code, as i am pretty new to coding, but here it is:
using UnityEngine;
public class silicateComposition : MonoBehaviour
{
public GameObject noise;
public int silicone;
public int ironOxide;
public int iron;
public int oxygen;
public int aluminium;
public int calcium;
public int sodium;
public int potassium;
public int magnesium;
// Start is called before the first frame update
void Start()
{
Debug.Log("was run");
int seed = noise.GetComponent<mapGenerator>().seed;
Debug.Log("go2");
ironOxide = seed / 15;
iron = seed / 100;
oxygen = seed / 13;
aluminium = seed / 132;
calcium = seed / 104;
sodium = seed / 115;
potassium = seed / 193;
magnesium = seed / 294;
int total = iron + ironOxide + oxygen + aluminium + calcium + sodium + potassium + magnesium;
Debug.Log(ironOxide);
Debug.Log(iron);
Debug.Log(oxygen);
Debug.Log(aluminium);
Debug.Log(calcium);
Debug.Log(sodium);
Debug.Log(potassium);
Debug.Log(magnesium);
Debug.Log(total);
if (total > 85)
{
int t = total - 85;
total = total - t;
int iod = ironOxide.ToString().Length;
int id = iron.ToString().Length;
int od = oxygen.ToString().Length;
int ad = aluminium.ToString().Length;
int sd = sodium.ToString().Length;
int pd = potassium.ToString().Length;
int md = magnesium.ToString().Length;
int cd = calcium.ToString().Length;
Debug.Log(iod);
if (iod >= 2)
{
int iod2 = iod;
int temp = 0;
while (iod > 2)
{
iod = iod - 1;
temp = temp + 1;
}
iod = temp;
int tens = 1000000;
temp = 0;
while (tens.ToString().Length > iod)
{
tens = tens / 10;
}
if (tens = 1)
{
tens = 10;
}
ironOxide = ironOxide / tens;
}
silicone = 100 - total;
if (silicone < 0)
{
silicone = 0;
}
}
}
}
so basically it generates a random percentage based on real life proportions and a seed. Also i have only coded the iron Oxide loop, so I can figure out how to do it before i do it with every element.
It does work, until it hits the if total is above 85 if statement. then unity just freezes. I do not understand why, as I have poured over the code for 2 days now and I'm losing my sanity. thank you for any help.
while (tens.ToString().Length > iod)
If iod is 0 or less, the loop will never terminate.
Also, if (tens = 1) should be if (tens == 1).

How to return a value from Cudafy c# GPU calculation?

My Issue
Hey, so I'm making this simple calculation to find the sum of sins between 0 and 100 degrees(as I use it as a benchmark for my systems), the calculation isn't the problem my issue is that I am new to Cudafy and I am unsure on how to properly pass in and return values so that it can be printed off here is my code:
Code
public const int N = 33 * 1024;
public const int threadsPerBlock = 256;
public const int blocksPerGrid = 32;
public static void Main()
{
Stopwatch watch = new Stopwatch();
watch.Start();
string Text = "";
int iterations = 1000000;
CudafyModule km = CudafyTranslator.Cudafy();
GPGPU gpu = CudafyHost.GetDevice(CudafyModes.Target, CudafyModes.DeviceId);
gpu.LoadModule(km);
double[] dev_Value = gpu.Allocate<double>();
gpu.Launch(blocksPerGrid, threadsPerBlock).SumOfSines(iterations,dev_Value);
double Value;
gpu.CopyFromDevice(dev_Value, out Value);
watch.Stop();
Text = watch.Elapsed.TotalSeconds.ToString();
Console.WriteLine("The process took a total of: " + Text + " Seconds");
Console.WriteLine(Value);
Console.Read();
gpu.FreeAll();
}
[Cudafy]
public static void SumOfSines(GThread thread,int iterations,double [] Value)
{
double total = new double();
double degAsRad = Math.PI / 180.0;
for (int i = 0; i < iterations; i++)
{
total = 0.0;
for (int z = 1; z < 101; z++)
{
double angle = (double)z * degAsRad;
total += Math.Sin(angle);
}
}
Value[0] = total;
}
The value that I am trying to extract from the CUDAfy part is the total and then print it off aswell as printing the time for the benchmarking. If anyone could post advice it would be very much appreciated (also any suggestions for making rid of any useless lines or unefficient pieces would also be good).
Doesn't matter I found the answer but I'll post it here:
public const int N = 33 * 1024;
public const int threadsPerBlock = 256;
public const int blocksPerGrid = 32;
public static void Main()
{
Stopwatch watch = new Stopwatch();
watch.Start();
CudafyModule km = CudafyTranslator.Cudafy();
GPGPU gpu = CudafyHost.GetDevice(CudafyModes.Target, CudafyModes.DeviceId);
gpu.LoadModule(km);
string Text = "";
int iterations = 1000000;
double Value;
double[] dev_Value = gpu.Allocate<double>(iterations * sizeof(double));
gpu.Launch(blocksPerGrid, threadsPerBlock).SumOfSines(iterations, dev_Value);
gpu.CopyFromDevice(dev_Value, out Value);
watch.Stop();
Text = watch.Elapsed.TotalSeconds.ToString();
Console.WriteLine("The process took a total of: " + Text + " Seconds");
Console.WriteLine(Value);
Console.Read();
gpu.FreeAll();
}
[Cudafy]
public static void SumOfSines(GThread thread, int _iterations, double[] Value)
{
int threadID = thread.threadIdx.x + thread.blockIdx.x * thread.blockDim.x;
int numThreads = thread.blockDim.x * thread.gridDim.x;
if (threadID < _iterations){
for (int i = threadID; i < _iterations; i += numThreads)
{
double _degAsRad = Math.PI / 180;
Value[i] = 0.0;
for (int a = 0; a < 100; a++)
{
double angle = (double)a * _degAsRad;
Value[i] += Math.Sin(angle);
}
}
}
}
-Jack

How to apply weights in neural network?

I am attempting to learn how to implement neural networks. The one main thing I can't seem to find anywhere is how to apply and store the weights. I got this to work in a simple [2 Input, 4 Output] Network by manually doing all of the multiplication for each output. But now I have 4 Input, 4 Hidden in 2 Layers, and 4 Outputs and am storing them in a 4x4x2 Array. I can't seem to grasp how to apply this using for loops. The current code below shows what I currently have and the parts commented as neural network are what I am currently trying to figure out.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Import SFML
using SFML.Graphics;
using SFML.System;
using SFML.Window;
namespace GeneticAlgorithims
{
class Program
{
//Neural Network Variables
public static int Inputs = 4;
public static int Outputs = 4;
public static int Hiddens = 2;
//End Variables
public static Random rand = new Random();
public static List<Organism> organisms = new List<Organism>();
public static RenderWindow window = new RenderWindow(new VideoMode(800,600), "Neural Networks", Styles.Default, new ContextSettings(512, 512, 16));
static void Main(string[] args)
{
Generate();
while(window.IsOpen)
{
window.DispatchEvents();
Update();
window.Clear(Color.Cyan);
Draw();
window.Display();
}
}
static void Generate()
{
for (int x = 0; x < 2; x++)
{
organisms.Add(new Organism(new Vector2f(rand.Next(0, (int)window.Size.X), rand.Next(0, (int)window.Size.Y)), new Matrix(new double[Inputs, Inputs, Hiddens])));
}
foreach (Organism organism in organisms)
{
organism.color = new Color((byte)rand.Next(0, 255),(byte)rand.Next(0, 255),(byte)rand.Next(0, 255));
organism.rotation = rand.Next(1, 360);
}
}
static void Update()
{
//Image map = window.Capture();
foreach(Organism organism in organisms)
{
//Get Near Organism
Organism near = new Organism();
foreach (Organism check in organisms)
{
if (check != organism)
{
if (Math.Abs(check.position.X - organism.position.X) < 128)
{
if (Math.Abs(check.position.Y - organism.position.Y) < 128)
{
near = check;
}
}
}
}
//Begin Neural Network
int CurrentColor = near.color.R;
float DistanceX = (near.position != null) ? Math.Abs(near.position.X - organism.position.X) : 0;
float DistanceY = (near.position != null) ? Math.Abs(near.position.Y - organism.position.Y) : 0;
float Health = organism.Health;
Console.WriteLine(CurrentColor);
for (int A = 0; A < Inputs; A++)
{
for (int B = 0; B < Outputs; B += 4)
{
for (int C = 0; C < Hiddens; C++)
{
organism.rotation +=
}
}
}
//End Neural Network
organism.Age++;
organism.position.X += organism.Speed * (float)Math.Cos(organism.rotation * 0.0174f);
organism.position.Y += organism.Speed * (float)Math.Sin(organism.rotation * 0.0174f);
float X = organism.position.X;
float Y = organism.position.Y;
if (organism.position.X > window.Size.X) organism.position.X = 0;
if (organism.position.X < 0) organism.position.X = window.Size.X;
if (organism.position.Y > window.Size.Y) organism.position.Y = 0;
if (organism.position.Y < 0) organism.position.Y = window.Size.Y;
if(organism.Age % 2500 == 0)
{
Organism newOrganism = new Organism(organism.position, organism.brain);
newOrganism.rotation = rand.Next(0, 360);
newOrganism.color = organism.color;
//organisms.Add(newOrganism);
//return;
}
if (organism.Age > 3000)
{
//organisms.Remove(organism);
//return;
}
}
}
static void Draw()
{
Sprite bufferSprite = new Sprite(new Texture("img.png"));
foreach (Organism organism in organisms)
{
Vertex[] line = new Vertex[2];
line[0] = new Vertex(organism.position, Color.Red);
line[1] = new Vertex(new Vector2f(organism.position.X + (float)(120 * Math.Cos((organism.rotation - 30) * 0.0174)), organism.position.Y + (float)(120 * Math.Sin((organism.rotation - 30) * 0.0174))), Color.Red);
window.Draw(line, PrimitiveType.Lines);
line[0] = new Vertex(organism.position, Color.Red);
line[1] = new Vertex(new Vector2f(organism.position.X + (float)(120 * Math.Cos((organism.rotation + 30) * 0.0174)), organism.position.Y + (float)(120 * Math.Sin((organism.rotation + 30) * 0.0174))), Color.Red);
window.Draw(line, PrimitiveType.Lines);
bufferSprite.Origin = new Vector2f(8, 8);
bufferSprite.Color = organism.color;
bufferSprite.Rotation = organism.rotation;
bufferSprite.Position = organism.position;
window.Draw(bufferSprite);
}
}
}
}
So as I said in the comments you'd have a layer class with weights and a network class. There's no need to break things up smaller than that in most cases.
So for the layer class, we have N weights plus a bias:
class Layer
{
double[] weights;
int nOut, nIn;
Layer(int inputs, int outputs)
{
nIn=inputs; nOut=outputs;
weights=new double[(inputs+1)*outputs]; //Assume random weights chosen
}
double[] processInput(double[] in)
{
double[] out=new double[nOut]; //initialise all to zero
for(int i=0; i<nOut; i++)
{
out[i] = weights[(i+1)*nIn] //bias always present
for(int j=0; j<nIn; j++)
{
out[i] +=in[j]*weights[(i+1)*nIn+j +1] //skips bias
}
out[i]=activationFunction(out[i])
}
return out
}
}
Then for the network class
class Network
{
List<Layer>
//skipping adding and setting up layers
double[] processInput(double[] in)
{
double[] temp=in;
for(Layer l:layers)
{
temp=layer.processInput(temp);
//input for next layer is output from previous
}
return temp;
}
}
Hopefully that's clear

To split for-cycle using TPL

In order to parallelize and accelerate calculations I"ve splitted one long for-cycle by two short for-cycles using TPL, these parts are called PointGenerator and PointGenerator2 in my class bellow:
class CalcPiTPL
{
int n;
int totalCounter;
int counter1;
int counter2;
double aPi;
public StringBuilder Msg; // diagonstic message
Stopwatch stopWatch = new Stopwatch();
public void Init(int aN)
{
stopWatch.Start();
n = aN; // save total calculate-iterations amount
aPi = -1; // flag, if no any calculate-iteration has been completed
Msg = new StringBuilder("No any calculate-iteration has been completed");
}
public void Run()
{
if (n < 1)
{
Msg = new StringBuilder("Invalid N-value");
return;
}
Task[] tasks = new Task[2];
tasks[0] = Task.Factory.StartNew((obj) => { PointGenerator((int)obj); }, n);
tasks[1] = Task.Factory.StartNew((obj) => { PointGenerator2((int)obj); }, n);
Task.WaitAll(tasks[0], tasks[1]);
totalCounter = counter1 + counter2;
aPi = 4.0 * ((double)totalCounter / (double)n); // to calculate approximate Pi - value
Console.WriteLine(aPi);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine("RunTime " + elapsedTime);
}
public double Done()
{
if (aPi > 0)
{
Msg = new StringBuilder("Calculates has been completed successful");
return aPi; // return gotten value
}
else
{
return 0; // no result
}
}
public void PointGenerator(int n)//FIRST PART OF ONE BIG FOR-CYCLE
{
double s = 0.125;
double sP = s / (n / 2);
double x = Math.Sqrt(sP);
for (double cX = 0; cX <= 0.25; cX += x)
{
for (double cY = 0; cY <= 0.5; cY += x)
{
if (((cX - 0.5) * (cX - 0.5) + (cY - 0.5) * (cY - 0.5)) < 0.25)
{
counter1++; // coordinate in a circle! mark it by incrementing N_0
}
}
}
}
public void PointGenerator2(int n)//SECOND PART OF ONE BIG FOR-CYCLE
{
double s = 0.125;
double sP = s / (n / 2);
double x = Math.Sqrt(sP);
for (double cX = 0.25; cX <= 0.5; cX += x)
{
for (double cY = 0; cY <= 0.5; cY += x)
{
if (((cX - 0.5) * (cX - 0.5) + (cY - 0.5) * (cY - 0.5)) < 0.25)
{
counter2++; // coordinate in a circle! mark it by incrementing N_0
}
}
}
}
}
And this is the same class without Tasks using(TPL), it has one long for-cycle:
class TCalcPi//unparallel calculating method
{
int N;
int n_0;
double aPi;
public StringBuilder Msg; // diagnostic message
Stopwatch stopWatch = new Stopwatch();
public void Init(int aN)
{
stopWatch.Start();
N = aN; // save total calculate-iterations amount
aPi = -1; // flag, if no any calculate-iteration has been completed
Msg = new StringBuilder("No any calculate-iteration has been completed");
}
public void Run()
{
if (N < 1)
{
Msg = new StringBuilder("Invalid N - value");
return;
}
double s = 0.25;
double sP = s / N;
double x = Math.Sqrt(sP);
for (double cX = 0; cX <= 0.5; cX += x)//ONE LONG FOR-CYCLE
{
for(double cY = 0; cY <= 0.5; cY += x)
{
if (((cX - 0.5) * (cX - 0.5) + (cY - 0.5) * (cY - 0.5)) < 0.25)
{
n_0++; // coordinate in a circle! mark it by incrementing N_0
}
}
}
aPi = 4.0 * ((double)n_0 / (double)N); // to calculate approximate Pi - value
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine("RunTime " + elapsedTime);
}
public double Done()
{
if (aPi > 0)
{
Msg = new StringBuilder("Calculates has been completed successful");
return aPi; // return gotten value
}
else
{
return 0; // no result
}
}
}
But unparallelized-class works faster, than parallelized(using TPL)class. How to fix it?
counter1 and counter2 most likely sit on the same cache line because they are adjacent in memory. This causes False Sharing. Probably, you are incrementing those counters very often. This pings the cacheline between the L1's of two cores for every alternation in time between the counters.
Separate them. As a proof of concept, like this:
int counter1;
long padding0, p1, p2, p3, p4, p5, p6, p7; //64 bytes padding
int counter2;
Let's hope the JIT does not reorder the fields. Maybe you need to use StructLayout.
Alternatively, make the counters local variables. Stack variables only have false sharing by extreme coincidence.

Categories