ImageMagic can't catch exception - c#

I generating millions of bmp by Imagemagick in linux with multi-threaded code but for some reason I get one of these errors(without stack trace) which I can't handle:
dotnet: MagickCore/pixel.c:138: ClonePixelChannelMap: Assertion 'channel_map != (PixelChannelMap *) NULL' failed.
or
dotnet: MagickCore/semaphore.c:452: UnlockSemaphoreInfo: Assertion 'semaphore_info != (SemaphoreInfo *) NULL' failed.
or
dotnet: MagickCore/option.c:2137: CloneImageOptions: Assertion 'clone_info->signature == MagickCoreSignature' failed.
My try - catch block doesn't handle these errors so my program closes immediately.
The errors are very random because the same input for Imagemagick in another attempt passes without error.
I use Include="Magick.NET-Q16-x64" Version="7.11.0.0"
I also try "Magick.NET-Q8-x64" and previous versions of imagemagic with the same results.
Linux 4.18.0-3-amd64 #1 SMP Debian 4.18.20-2 (2018-11-23) x86_64 GNU/Linux
Here is code from thread(I run app with 9 threads)
public virtual void GeneratePictureForCurrSpin()
{
do
{
GenerateInternal();
} while (!isAllPicturesGenerated());
}
public override void GenerateInternal()
{
symbols = symbolParser.ParseSymbols(config, spins[currLocalSpin].symbols);
img = (MagickImage)SpinGenerator.rl.emptyImg.Clone();
bgImg = SpinGenerator.rl.bg;
img.Composite(bgImg, new PointD(config.BgX, config.BgY),ImageMagick.CompositeOperator.Over);
reelsBgImg = SpinGenerator.rl.reelsBg;
img.Composite(reelsBgImg, CompositeOperator.Over);
PointD startPoint = new PointD(config.StartOffsetX, config.StartOffsetY);
MagickImage sym;
for(int i = 0; i < symbols.Count; i++)
{
List<int> symbolsOnReel = symbols[i];
for(int j = 0; j < symbolsOnReel.Count; j++)
{
var newPoint = new PointD(startPoint.X + i * (config.SymbolWidth + config.OffsetX), startPoint.Y + j * (config.SymbolHeight + config.OffsetY));
sym = SpinGenerator.rl.symbols[symbolsOnReel[j]-1];
img.Composite(sym, newPoint, ImageMagick.CompositeOperator.Over);
}
}
bool isFreeSpin = (spins[currLocalSpin].betValue == 0)?true:false;
GenerateBottomBar(isFreeSpin);
ShowTokensValue(spins[currLocalSpin].coins);
ResizeImage();
int fileNr = spins[currLocalSpin].spinNr;
String dir = "Resources/Result/" + GAME_NAME + "/" + betValue;
SaveImg(dir , fileNr);
img.Dispose();
IncrementSpinValues();
}
public virtual void GenerateBottomBar(bool isFreeSpin)
{
var pos = (isFreeSpin)?1:0;
bottomBar = SpinGenerator.rl.bottomBars[pos];
PointD startPoint = new PointD(0,config.BgHeight);
img.Composite(bottomBar,startPoint);
}
private void ShowTokensValue(int tokens)
{
if(tokens < 10)
{
var tokenValueImg = SpinGenerator.rl.tokensValues[tokens];
tokenValueImg.Resize(90,60);
img.Composite(tokenValueImg, new PointD(tokenValueStartX + tokenValueImgWidth, tokenValueStartY),ImageMagick.CompositeOperator.Over);
}
else{
int a = tokens / 10;
int b = tokens % 10;
var tokenValueImgA = SpinGenerator.rl.tokensValues[a];
tokenValueImgA.Resize(90,55);
img.Composite(tokenValueImgA, new PointD(tokenValueStartX, tokenValueStartY),ImageMagick.CompositeOperator.Over);
var tokenValueImgB = SpinGenerator.rl.tokensValues[b];
tokenValueImgB.Resize(90,55);
img.Composite(tokenValueImgB, new PointD(tokenValueStartX+ tokenValueImgWidth, tokenValueStartY),ImageMagick.CompositeOperator.Over);
}
var tokensTxtImg = SpinGenerator.rl.tokensTxt;
img.Composite(tokensTxtImg, new PointD(tokenTxtStartX, tokenTxtStartY),ImageMagick.CompositeOperator.Over);
}
internal void ResizeImage()
{
img.Format = ImageMagick.MagickFormat.Bmp3;
img.Depth = 16;
img.Resize(new MagickGeometry("600, 450!"));
//img.Quality = 100;
}
internal void SaveImg(String dir , int fileNr)
{
System.IO.Directory.CreateDirectory(dir);
img.Write(dir + "/" +"s" + fileNr + ".bmp");
ClearImg();
}
internal virtual void IncrementSpinValues()
{
currLocalSpin++;
currSpin++;
}

Related

SystemAccessViolationException in OpenTK.dll using Shaders

Using OpenTK to attempt to create shaders in C#, repeatedly getting memory access violation errors. Any help would be appreciated. Here is the class I am having errors with, full code will be able to be found at https://github.com/Autodesk/synthesis/engine-research/OpenTKBuild
Error at Line 53 :
An unhandled exception of type 'System.AccessViolationException'
occurred in OpenTK.dll
Additional information: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.
Source code:
using OpenTK.Graphics.OpenGL;
namespace OpenTKbuild
{
class Shader
{
public int Program;
public Shader(string vertexPath, string fragmentPath)
{
string vertexCode, fragmentCode;
int vertex, fragment;
try
{
System.IO.FileStream vShaderFile = new System.IO.FileStream(vertexPath, System.IO.FileMode.Open);
System.IO.FileStream fShaderFile = new System.IO.FileStream(fragmentPath, System.IO.FileMode.Open);
System.IO.StreamReader vShaderRead = new System.IO.StreamReader(vShaderFile);
System.IO.StreamReader fShaderRead = new System.IO.StreamReader(fShaderFile);
vShaderFile.Close();
fShaderFile.Close();
vertexCode = vShaderRead.ToString();
fragmentCode = fShaderRead.ToString();
char[] vShaderCodeChar = vertexCode.ToCharArray();
char[] fShaderCodeChar = fragmentCode.ToCharArray();
string[] vShaderCode = new string[vShaderCodeChar.Length];
string[] fShaderCode = new string[fShaderCodeChar.Length];
for (int i = 0; i < vShaderCodeChar.Length; i++)
{
vShaderCode[i] = vShaderCodeChar[i].ToString();
}
for (int i = 0; i < vShaderCodeChar.Length; i++)
{
vShaderCode[i] = vShaderCodeChar[i].ToString();
}
int vcount = vShaderCode.Length;
int fcount = fShaderCode.Length;
vertex = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertex, 1, vShaderCode, ref vcount);
GL.CompileShader(vertex);
fragment = GL.CreateShader(ShaderType.FragmentShader);
// --------> error occurs onthe next line. when commented out, error does not persist.
GL.ShaderSource(fragment, 1, fShaderCode, ref fcount);
GL.CompileShader(fragment);
Program = GL.CreateProgram();
GL.AttachShader(Program, vertex);
GL.AttachShader(Program, fragment);
GL.LinkProgram(Program);
GL.DeleteShader(vertex);
GL.DeleteShader(fragment);
}
catch
{
throw new System.Exception("wut");
}
}
public void Use()
{
GL.UseProgram(Program);
}
}
}
I'm not sure why you convert the shader source string into a character array and then into a string array with just one character per string. But even if you do so, the length and the count parameter of GL.ShaderSource have to fit your data. At the moment, you tell OpenGL that there is one element in the array and that this element has fcount characters, which is not the case. This is then the reason why OpenGL tries to read outside of your allocated memory.
To solve your problem, I would suggest the following code:
GL.ShaderSource(vertex, 1, new string[] { vertexCode }, vertexCode.Length);
solved using the following code:
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace MeshImport
{
class Shader
{
public int ShaderProgram = 0;
public static int vertex, fragment, geometry;
public Shader() : base()
{
}
public Shader(string vertexPath, string fragmentPath, string geometryPath)
{
#region OLD
//string vertexCode = null, fragmentCode = null;
//System.IO.FileStream vShaderFile = new System.IO.FileStream(vertexPath, System.IO.FileMode.Open);
//System.IO.FileStream fShaderFile = new System.IO.FileStream(fragmentPath, System.IO.FileMode.Open);
#endregion
string vCode = null, fCode = null, gCode = null;
try
{
#region OLD
//System.IO.StreamReader vShaderRead = new System.IO.StreamReader(vShaderFile);
//System.IO.StreamReader fShaderRead = new System.IO.StreamReader(fShaderFile);
//vShaderFile.Close();
//fShaderFile.Close();
//vertexCode = vShaderRead.ToString();
//fragmentCode = fShaderRead.ToString();
#endregion
vCode = System.IO.File.ReadAllText(vertexPath);
fCode = System.IO.File.ReadAllText(fragmentPath);
gCode = System.IO.File.ReadAllText(geometryPath);
}
catch
{
System.Console.WriteLine("FILE NOT READ SUCCESSFULLY\n");
}
#region OLD
//char[] vShaderCodeChar = vertexCode.ToCharArray();
//char[] fShaderCodeChar = fragmentCode.ToCharArray();
//string[] vShaderCode = new string[vShaderCodeChar.Length];
//string[] fShaderCode = new string[fShaderCodeChar.Length];
//for (int i = 0; i < vShaderCodeChar.Length; i++)
//{
// vShaderCode[i] = vShaderCodeChar[i].ToString();
//}
//for (int i = 0; i < vShaderCodeChar.Length; i++)
//{
// vShaderCode[i] = vShaderCodeChar[i].ToString();
//}
#endregion
vertex = GL.CreateShader(ShaderType.VertexShader);
GL.CompileShader(vertex);
fragment = GL.CreateShader(ShaderType.FragmentShader);
GL.CompileShader(fragment);
geometry = GL.CreateShader(ShaderType.GeometryShaderExt);
GL.CompileShader(geometry);
compileShader(vertex, vCode);
compileShader(fragment, fCode);
compileShader(geometry, gCode);
ShaderProgram = GL.CreateProgram();
GL.AttachShader(ShaderProgram, vertex);
GL.AttachShader(ShaderProgram, fragment);
GL.LinkProgram(ShaderProgram);
string info;
GL.GetProgramInfoLog(ShaderProgram, out info);
System.Console.WriteLine(info);
GL.ProgramParameter(ShaderProgram, Version32.GeometryInputType, (int)All.Lines);
GL.ProgramParameter(ShaderProgram, Version32.GeometryOutputType, (int)All.LineStrip);
int tmp;
GL.GetInteger((GetPName)ExtGeometryShader4.MaxGeometryOutputVerticesExt, out tmp);
#region OLD
//int success;
//char[] infolog = new char[512];
//int[] vcount = null;
//int[] fcount = null;
//int nullint = 0;
//System.Text.StringBuilder sb = new System.Text.StringBuilder();
//sb.Append(infolog);
//vertex = GL.CreateShader(ShaderType.VertexShader);
//GL.CompileShader(vertex);
//GL.GetShader(vertex, ShaderParameter.CompileStatus, out success);
//if (success == 0)
//{
// GL.GetShaderInfoLog(vertex, 512, out nullint, sb);
// System.Console.WriteLine("Error: Shader : Vertex : Compilation Failed\n" + infolog);
//}
//fragment = GL.CreateShader(ShaderType.FragmentShader);
//GL.CompileShader(fragment);
//GL.GetShader(fragment, ShaderParameter.CompileStatus, out success);
//if (success == 0)
//{
// GL.GetShaderInfoLog(fragment, 512, out nullint, sb);
// System.Console.WriteLine("Error: Shader : Fragment : Compilation Failed\n" + infolog);
//}
//Program = GL.CreateProgram();
//GL.AttachShader(Program, vertex);
//GL.AttachShader(Program, fragment);
//GL.LinkProgram(Program);
//GL.DeleteShader(vertex);
//GL.DeleteShader(fragment);
#endregion
}
public void Use()
{
GL.UseProgram(ShaderProgram);
}
private void compileShader(int shader, string source)
{
GL.ShaderSource(shader, source);
GL.CompileShader(shader);
string info;
GL.GetShaderInfoLog(shader, out info);
System.Console.WriteLine(info);
int compileResult;
GL.GetShader(shader, ShaderParameter.CompileStatus, out compileResult);
if (compileResult != 1)
{
System.Console.WriteLine("CompileError : " + source);
}
}
public void cleanUp()
{
if (fragment != 0)
GL.DeleteShader(fragment);
if (vertex != 0)
GL.DeleteShader(vertex);
if (geometry != 0)
GL.DeleteShader(geometry);
}
}
}

Compiler is refusing to compile correct code in Unity3d C#

I just added an integer argument to a function definition and added an integer to the only instance where the function is called. an error is generated:
CustomShaderEditor.cs(44,46): error CS1501: No overload for method UpdateTexture' takes0' arguments
I don't know how to cope with an error of this kind, I would love some advice.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;
public class CustomShader : MonoBehaviour
{
public int numTiles = 10;
public GameObject RenderGameObject;
public GameObject[] gamObjectClones;
public Texture2D ComputeTexture;
public ComputeShader ComputeShader;
ComputeBuffer wavBuffer ;
ComputeBuffer computeBuffer ;
void Start ()
{
ResetTexture();
gamObjectClones = new GameObject[numTiles];
for (int i=0; i<numTiles; i++)
{
gamObjectClones[i] = (GameObject)Instantiate(RenderGameObject, new Vector3(i * 10.0f, 0, 0), Quaternion.identity);
}
}
void Update ()
{
RefreshComputeShaderMaterial();
}
public void RefreshComputeShaderMaterial()
{
for (int i=0; i<numTiles; i++)
{
UpdateTexture( 10 );
Material m = gamObjectClones[i].GetComponent<Renderer>().sharedMaterial;
if (m.HasProperty("_DataTexture"))
{
m.SetTexture("_DataTexture", ComputeTexture);
}
}
}
public void ResetTexture()
{
int BufferSize = ComputeTexture.width * ComputeTexture.height;
Color[] ColorBuffer = new Color[BufferSize];
ComputeTexture.SetPixels(ColorBuffer);
ComputeTexture.Apply();
}
public void SetupTexture()
{
int BufferSize = ComputeTexture.width * ComputeTexture.height;
Color[] ColorBuffer = ComputeTexture.GetPixels();
for (int i=0; i<BufferSize; i++)
{
if ((i&31)==31)
{
ColorBuffer[i] = Color.white;
}
}
ComputeTexture.SetPixels(ColorBuffer);
ComputeTexture.Apply();
}
public void UpdateTexture( int tile )
{
int csi;
csi = ComputeShader.FindKernel("computeGameOfLife");
if (csi>-1)
{
var ran = UnityEngine.Random.Range(1f,100f);
int BufferSize = ComputeTexture.width * ComputeTexture.height;
Vector4[] TextureBuffer = new Vector4[BufferSize];
Color [] ColorBuffer = ComputeTexture.GetPixels();
for (int i=0; i<BufferSize; i++)
{
TextureBuffer[i].x = 0;//Mathf.Sin(i/10f);
TextureBuffer[i].y = 0;
TextureBuffer[i].z = 0;
TextureBuffer[i].w = 0;
}
computeBuffer = new ComputeBuffer(BufferSize, sizeof(float) * 4);
computeBuffer.SetData(TextureBuffer);
ComputeShader.SetBuffer(csi, "DataTexture", computeBuffer);
//////////////////// patch
int sBufferSize = 88000 ;
float[] sTextureBuffer = new float[sBufferSize] ;
for (int i = 0 ; i < sBufferSize ; i++)
{
sTextureBuffer[ i ] = Mathf.Sin( i / ran + 20*Mathf.Sin(i/1000) ) ;
}
ReleaseBuffers();
print( " sin " + sTextureBuffer[23]);
wavBuffer = new ComputeBuffer(sBufferSize, sizeof(float) ) ;
wavBuffer.SetData(sTextureBuffer);
ComputeShader.SetBuffer(csi, "re", wavBuffer) ;
//wavBuffer.Release() ;
/////////////////////
ComputeShader.Dispatch(csi, 1, 1, 1);
computeBuffer.GetData (TextureBuffer);
computeBuffer.Release();
for (int i=0; i<BufferSize; i++)
{
ColorBuffer[i].r = TextureBuffer[i].x;
ColorBuffer[i].g = TextureBuffer[i].y;
ColorBuffer[i].b = TextureBuffer[i].z;
ColorBuffer[i].a = TextureBuffer[i].w;
}
ComputeTexture.SetPixels(ColorBuffer);
ComputeTexture.Apply();
}
}
public void ReleaseBuffers() {
if (wavBuffer != null) wavBuffer.Release();
wavBuffer = null;
}
}
UpdateTexture( i ); //'=-='error is for this line
This is not the problem with your code. There is a problem somewhere else. Make sure to save the new code and see whether your old code is still the one being used instead of the new code. Also re-start Unity. If these fails, dump your whole code here for further help because what you have now is NOT the problem.

Command line arguments in c#

I am pretty new to c# . Got a problem with command line arguments. what i want to do is make use of the third cmd line argument and write to it. I have specified the path of the file I want to write into and other stuffs. But the question here is can i access the command line arguments(for eg; args[3]) from user defined functions? How do we do tat? below is my code.
public class Nodes
{
public bool isVisited;
public string parent;
public string[] neighbour;
public int nodeValue;
public Nodes(string[] arr, int nodeValue)
{
this.neighbour = new string[arr.Length];
for (int x = 0; x < arr.Length; x++)
this.neighbour[x] = arr[x];//hi...works??
this.isVisited = false;
this.nodeValue = nodeValue;
}
}
public class DFS
{
static List<string> traversedList = new List<string>();
static List<string> parentList = new List<string>();
static BufferBlock<Object> buffer = new BufferBlock<object>();
static BufferBlock<Object> buffer1 = new BufferBlock<object>();
static BufferBlock<Object> buffer3 = new BufferBlock<object>();
static BufferBlock<Object> buffer2 = new BufferBlock<object>();
public static void Main(string[] args)
{
int N = 100;
int M = N * 4;
int P = N * 16;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
List<string> global_list = new List<string>();
StreamReader file = new StreamReader(args[2]);
string text = file.ReadToEnd();
string[] lines = text.Split('\n');
string[][] array1 = new string[lines.Length][];
Nodes[] dfsNodes = new Nodes[lines.Length];
for (int i = 0; i < lines.Length; i++)
{
lines[i] = lines[i].Trim();
string[] words = lines[i].Split(' ');
array1[i] = new string[words.Length];
dfsNodes[i] = new Nodes(words, i);
for (int j = 0; j < words.Length; j++)
{
array1[i][j] = words[j];
}
}
StreamWriter sr = new StreamWriter(args[4]);
int startNode = int.Parse(args[3]);
if (args[1].Equals("a1"))
{
Console.WriteLine("algo 0");
buffer.Post(1);
dfs(dfsNodes, startNode, "root");
}
else if (args[1].Equals("a2"))
{
Console.WriteLine("algo 1");
buffer1.Post(1);
dfs1(dfsNodes, startNode, "root",sr);
}
else if (args[1].Equals("a3"))
{
buffer3.Post(1);
List<string> visitedtList = new List<string>();
Console.WriteLine("algo 2");
dfs2(dfsNodes, startNode, "root", visitedtList,sr);
}
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed);
Console.ReadLine();
}
public static void dfs(Nodes[] node, int value, string parent,StreamWriter sr1)
{
int id = (int)buffer.Receive();
sr1=new StreamWriter(arg
Console.WriteLine("Node:" + value + " Parent:" + parent + " Id:" + id);
sr1.Write("Node:" + value + " Parent:" + parent + " Id:" + id);
id++;
traversedList.Add(value.ToString());
buffer.Post(id);
for (int z = 1; z < node[value].neighbour.Length; z++)
{
if (!traversedList.Contains(node[value].neighbour[z]))
{
dfs(node, int.Parse(node[value].neighbour[z]), value.ToString(),sr1);
}
}
return;
}
public static void dfs1(Nodes[] node, int value, string parent, StreamWriter sr)
{
int id = (int)buffer1.Receive();
sr.Write("Node:" + value + " Parent:" + parent + " Id:" + id);
node[value].isVisited = true;
node[value].parent = parent;
id++;
buffer1.Post(id);
for (int z = 1; z < node[value].neighbour.Length; z++)
{
buffer2.Post(node[int.Parse(node[value].neighbour[z])]);
if (!isVisited())
{
dfs1(node, int.Parse(node[value].neighbour[z]), value.ToString(),sr);
}
}
return;
}
public static void dfs2(Nodes[] node, int value, string parent, List<string> visitedtList, StreamWriter sr)
{
int id = (int)buffer3.Receive();
sr.Write("Node:" + value + " Parent:" + parent + " Id:" + id);
id++;
visitedtList.Add(value.ToString());
buffer3.Post(id);
for (int z = 1; z < node[value].neighbour.Length; z++)
{
buffer2.Post(node[int.Parse(node[value].neighbour[z])]);
if (!visitedtList.Contains(node[value].neighbour[z]))
dfs2(node, int.Parse(node[value].neighbour[z]), value.ToString(), visitedtList,sr);
}
return;
}
public static bool isVisited()
{
Nodes node = (Nodes)buffer2.Receive();
return node.isVisited;
}
}
So the thing is I want to write the output of each dfs to the file specified as the command line argument. So can I have access to the args in the dfs, dfs1 methods??? Thank you.
You could either keep a static field to hold it, or just use Environment.GetCommandLineArgs().
Well, in its simplest form, just save it to use later
class Program
{
static string _fpath;
static void Main(string[] args)
{
// ...stuff
_fpath = args[3];
}
static void WriteFile()
{
using(var stream = File.Open(_fpath, ...))
{
// write to file
}
}
}
Not necessarily exactly how I would do it, but you get the idea.
Also, regarding this bit of code...
this.neighbour = new string[arr.Length];
for (int x = 0; x < arr.Length; x++)
this.neighbour[x] = arr[x];//hi...works??
You can simply write
this.neighbour = arr;
Ahh, the wonders of managed code :D. No need to copy elements across to the second array. Of course, you need to consider the fact that changes to elements in the argument array (arr) will be reflected in your internal array now.
It would be better to pass arguments into functions instead of relying on some "hidden" way to pass them.
Both static variable and GetCommandLineArgs are useful to pass them in hidden way (as pointed out in other answers). Drawbacks are harder to test (since need to set static shared dependency) and less clear for future readers that there is this hidden dependency.

Parsing Through Wave File with BinaryReader

In .NET Assembly mscorlib System.IO namespace, I am using ReadInt16() method to loop through audio data bytes and dumping signed integer values into a text file. How does one interpret the two values associated with one sample rate? That is if I have one second of mono data there will be 88200 bytes, hence using ReadInt16() returns 88200 discrete integers. This is too much information, I should only have 44100 integers. So do I need to use a different method or perhaps advance the loop by 1 per each iteration.
Many thanks..........Mickey
using System;
using System.IO;
public struct WaveFormat
{
private short m_FormatTag; // most often PCM = 1
private short m_nChannels; // number of channels
private int m_SamplesPerSecond; // samples per second eg 44100
private int m_AvgBytesPerSecond; // bytes per second eg 176000
private short m_BlockAlign; // blockalign (byte per sample) eg 4 bytes
private short m_BitsPerSample; // bits per sample, 8, 16, 24
public WaveFormat(byte BPS, int SPS, byte nChn)
{
m_FormatTag = 1; //PCM
m_nChannels = nChn;
m_SamplesPerSecond = SPS;
m_BitsPerSample = BPS;
m_BlockAlign = (short)(m_nChannels * m_BitsPerSample / 8);
m_AvgBytesPerSecond = (int)(m_BlockAlign * m_SamplesPerSecond);
}
public short FormatTag
{
get { return m_FormatTag; }
set { m_FormatTag = value; }
}
public short Channels
{
get { return m_nChannels; }
}
public int SamplesPerSecond
{
get { return m_SamplesPerSecond; }
}
public int AvgBytesPerSecond
{
get { return m_AvgBytesPerSecond; }
}
public short BlockAlign
{
get { return m_BlockAlign; }
}
public short BitsPerSample
{
get { return m_BitsPerSample; }
}
public void Read(BinaryReader br)
{
m_FormatTag = br.ReadInt16();
m_nChannels = br.ReadInt16();
m_SamplesPerSecond = br.ReadInt32();
m_AvgBytesPerSecond = br.ReadInt32();
m_BlockAlign = br.ReadInt16();
m_BitsPerSample = br.ReadInt16();
}
public void Write(BinaryWriter bw)
{
bw.Write(m_FormatTag);
bw.Write(m_nChannels);
bw.Write(m_SamplesPerSecond);
bw.Write(m_AvgBytesPerSecond);
bw.Write(m_BlockAlign);
bw.Write(m_BitsPerSample);
}
public override string ToString()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.AppendLine("FormatTag: " + m_FormatTag.ToString());
sb.AppendLine("nChannels: " + m_nChannels.ToString());
sb.AppendLine("SamplesPerSecond: " + m_SamplesPerSecond.ToString());
sb.AppendLine("AvgBytesPerSecond: " + m_AvgBytesPerSecond.ToString());
sb.AppendLine("BlockAlign: " + m_BlockAlign.ToString());
sb.AppendLine("BitsPerSample: " + m_BitsPerSample.ToString());
return sb.ToString();
}
}
Generally when you read arrays of data your code should look like:
for(int i = 0; i < totalNumberOfEntries; i++)
{
// read all data for this entry
var component1 = reader.ReadXXX();
var component2 = reader.ReadXXX();
// deal with data for this entry
someEntryStroage.Add(new Entry(component1, component2);
}
Most likely (I don't know Wave file format) in your case you either need to read pairs of Int16 values (if samples are together) or read channels separately if data for one channel is after another.
you must read the chunkinfos. The data-chunk tells you how much bytes you have to read. the WaveFormat tells you ho much Averagebytespersecond you have, and much more. I have some VB-code...
have converted the VB-code with sharpdevelop to C# maybe it helps a little bit...
using System;
using System.IO;
public class ChunkInfo
{
private byte[] m_Header;
private long m_Length;
private long m_OffSet;
public ChunkInfo(string Header)
{
m_Header = new byte[Header.Length];
for (int i = 0; i <= m_Header.GetUpperBound(0); i++)
{
m_Header[i] = (byte)Header[i];
}
}
public ChunkInfo(byte[] Header)
{
m_Header = Header;
}
public void Read(BinaryReader br)
{
m_OffSet = SearchOffset(br);
if (m_OffSet >= 0)
{
br.BaseStream.Position = m_OffSet + m_Header.Length;
m_Length = br.ReadInt32();
}
}
public void Write(BinaryWriter bw)
{
bw.Write(m_Header);
bw.Write(m_Length);
}
public long Length
{
get { return m_Length; }
}
public long OffSet
{
get { return m_OffSet; }
}
private long SearchOffset(BinaryReader br)
{
byte[] haystack = null;
bool found = false;
long offset = 0;
long basepos = 0;
int hlength = 260;
long basepos_grow = hlength - m_Header.Length;
while (!(found || (basepos >= br.BaseStream.Length)))
{
br.BaseStream.Position = basepos;
haystack = br.ReadBytes(hlength);
offset = BoyerMooreHorspool.find(haystack, m_Header);
found = offset >= 0;
if (found)
{
offset += basepos;
break;
}
else
{
basepos += basepos_grow;
}
}
return offset;
}
}
public static class BoyerMooreHorspool
{
//detects a needle in the haystack
const int UBYTE_MAX = 255;
static int[] bad_char_skip4 = new int[UBYTE_MAX + 3];
static int[] bad_char_skip8 = new int[UBYTE_MAX + 3];
static bool IsInitialized = false;
public static void init()
{
//little optimization for needles with length 4 or 8
for (int i = 0; i <= UBYTE_MAX + 2; i++)
{
bad_char_skip4[i] = 4;
bad_char_skip8[i] = 8;
}
IsInitialized = true;
}
public static int find(byte[] haystack, byte[] needle, int start = 0)
{
if (!IsInitialized) init();
int i_n = 0;
//needle index
int n_n = needle.Length;
int[] bad_char_skip = null;
switch (n_n)
{
case 4:
bad_char_skip = bad_char_skip4;
break;
case 8:
bad_char_skip = bad_char_skip8;
break;
default:
bad_char_skip = new int[UBYTE_MAX + 3];
for (i_n = 0; i_n <= UBYTE_MAX + 2; i_n++)
{
bad_char_skip[i_n] = n_n;
}
break;
}
int ifind = -1;
//if not found then return - 1
int i_h = start;
//haystack index
int n_h = haystack.Length;
if (n_n > n_h)
throw new ArgumentOutOfRangeException("needle", "needle is to long");
int last = n_n - 1;
for (i_n = 0; i_n <= last - 1; i_n++)
{
bad_char_skip[needle[i_n]] = last - i_n;
}
byte bcs = 0;
int bhs = 0;
while ((n_h - start) >= n_n)
{
i_n = last;
while (haystack[i_h + i_n] == needle[i_n])
{
i_n -= 1;
if (i_n == 0)
{
ifind = i_h;
break;
}
}
bhs = haystack[i_h + last];
bcs = (byte)(bad_char_skip[bhs]);
n_h -= bcs;
i_h += bcs;
}
return ifind;
}
}

Help with capture sound from microphone and play it back in C#?

Hi i got this code and i got 2 errors which i can't get rid of.
Any help pls?
namespace pleasework
{
public partial class Form1 : Form
{
private Thread _echoThread;
private Capture _captureDevice;
private CaptureBuffer _captureBuffer;
private Device _playbackDevice;
private SecondaryBuffer _playbackBuffer;
private int _bufferSize;
private const int _bufferPositions = 4;
private AutoResetEvent _notificationEvent = null;
private BufferPositionNotify[] _positionNotify = new BufferPositionNotify[_bufferPositions + 1];
private Notify _echoNotify = null;
private void EchoThread()
{
int offset = 0;
_captureBuffer.Start(true);
_playbackBuffer.Play(0, BufferPlayFlags.Looping);
//byte[] buffer = (byte[])_captureBuffer.Read(offset, typeof(byte), LockFlag.FromWriteCursor, _bufferSize);
for (; ; )
{
_notificationEvent.WaitOne(Timeout.Infinite, true);
byte[] buffer = (byte[])_captureBuffer.Read(offset, typeof(byte), LockFlag.None, _bufferSize);
_playbackBuffer.Write(offset, buffer, LockFlag.None);
offset = (offset + _bufferSize) % (_bufferPositions * _bufferSize);
}
}
public Form1()
{
CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
_captureDevice = new Capture();
short channels = 2;
short bitsPerSample = 16;
int samplesPerSecond = 22050;
//Set up the wave format to be captured
WaveFormat waveFormat = new WaveFormat();
waveFormat.Channels = channels;
waveFormat.FormatTag = WaveFormatTag.Pcm;
waveFormat.SamplesPerSecond = samplesPerSecond;
waveFormat.BitsPerSample = bitsPerSample;
waveFormat.BlockAlign = (short)(channels * (bitsPerSample / 8));
waveFormat.AverageBytesPerSecond = waveFormat.BlockAlign * samplesPerSecond;
_bufferSize = waveFormat.AverageBytesPerSecond / 20;
CaptureBufferDescription captureBufferDescription = new CaptureBufferDescription();
captureBufferDescription.BufferBytes = _bufferPositions * _bufferSize;
captureBufferDescription.Format = waveFormat;
_captureBuffer = new CaptureBuffer(captureBufferDescription, _captureDevice);
_playbackDevice = new Device();
_playbackDevice.SetCooperativeLevel(this, CooperativeLevel.Normal);
BufferDescription playbackBufferDescription = new BufferDescription();
playbackBufferDescription.BufferBytes = _bufferPositions * _bufferSize;
playbackBufferDescription.Format = waveFormat;
_playbackBuffer = new SecondaryBuffer(playbackBufferDescription, _playbackDevice);
_echoThread = new Thread(new ThreadStart(EchoThread));
_echoThread.Start();
_notificationEvent = new AutoResetEvent(false);
for (int i = 0; i < _bufferPositions; i++)
{
_positionNotify.Offset = (_bufferSize * i) + _bufferSize - 1; // got error here
_positionNotify.EventNotifyHandle = _notificationEvent.SafeWaitHandle.DangerousGetHandle();// got error here
}
_echoNotify = new Notify(_captureBuffer);
_echoNotify.SetNotificationPositions(_positionNotify, _bufferPositions);
}
private void EchoClose(object sender, FormClosingEventArgs e)
{
_echoThread.Abort();
}
}
}
Thanks!
You are setting _positionNotify to an array with _bufferPosition + 1 elements. Yet, when you are in your for loop you never specify which of the elements you are setting the Offset and EventNotifyHandle for. Also I think you need to add one additional line so actually create a new instance of the BufferPositionNotify structure. Try changing those lines to something like this:
for (int i = 0; i < _bufferPositions; i++)
{
_positionNotify[i] = new BufferPositionNotify();
_positionNotify[i].Offset = (_bufferSize * i) + _bufferSize - 1;
_positionNotify[i].EventNotifyHandle =
_notificationEvent.SafeWaitHandle.DangerousGetHandle();
}
I tried the code. First it didn't work.
Instead of: private BufferPositionNotify[] _positionNotify = new BufferPositionNotify[_bufferPositions + 1]; it should be private BufferPositionNotify[] _positionNotify = new BufferPositionNotify[_bufferPositions];. Otherwhise you have an element to much in your array.

Categories

Resources