Question of the title.Recently using GDAL reading Terrasar—X data and dividing imaginary and real parts Like software NEST confuses me a lot.Any help and suggestion will be highly appreciated.Below is my implementation method:
string dataPath = #"E:\SARDATA\SampleData\TerraSar-X\SO_000009564_0002_1\SO_000009564_0002_1\TSX1_SAR__SSC______HS_S_SRA_20090223T204240_20090223T204241\TSX1_SAR__SSC______HS_S_SRA_20090223T204240_20090223T204241.xml";
Gdal.AllRegister();
Dataset dataset = Gdal.OpenShared(dataPath, Access.GA_ReadOnly);
Band band = dataset.GetRasterBand(1);
int xSize = band.XSize;
int ySize = band.YSize;
short[] realArray = new short[xSize * ySize];
short[] imgArray = new short[xSize * ySize];
if (band.DataType == DataType.GDT_CInt16)
{
short[] tmpArray = new short[2 * xSize * ySize];
band.ReadRaster(0, 0, xSize, ySize, tmpArray, xSize, ySize, 0, 0);
for (int i = 0; i < tmpArray.Length;i++ )
{
realArray[i] = tmpArray[i / 2];
imgArray[i] = tmpArray[i / 2 + 1];
}
tmpArray = null;
}
I think I have a solution to your problem. I also tried to read a complex TerraSAR-X and I encountered your answer.
The complex file format merges two Int16 for CInt16 and two Int32 for CInt32.
To read correctly the complex data you should split an Integer into two shorts. The correct reading should look like this:
string dataPath = #"E:\SARDATA\SampleData\TerraSar-X\SO_000009564_0002_1\SO_000009564_0002_1\TSX1_SAR__SSC______HS_S_SRA_20090223T204240_20090223T204241\TSX1_SAR__SSC______HS_S_SRA_20090223T204240_20090223T204241.xml";
Gdal.AllRegister();
Dataset dataset = Gdal.OpenShared(dataPath, Access.GA_ReadOnly);
Band band = dataset.GetRasterBand(1);
int xSize = band.XSize;
int ySize = band.YSize;
short[] realArray = new short[xSize * ySize];
short[] imgArray = new short[xSize * ySize];
if (band.DataType == DataType.GDT_CInt16)
{
short[] tmpArray = new short[xSize * ySize];
band.ReadRaster(0, 0, xSize, ySize, tmpArray, xSize, ySize, 0, 0);
for (int i = 0; i < tmpArray.Length;i++ )
{
int value = tmpArray[i];
realArray[i] = (short)(value>>16);
imgArray[i] = (short)(value & 0xffff);
}
tmpArray = null;
}
Related
I copied some code somewhere in this forum that represents a wav file and wrote it into a MemoryStream. I try to play it when clicking on a button with some variables passed in: PlayBeep(8000,500,16383);
But the emulator crashes and says:
An exception of type 'System.InvalidOperationException' occurred in
Microsoft.Xna.Framework.ni.dll but was not handled in user code
Additional information: FrameworkDispatcher.Update has not been called
Here is the code:
public static void PlayBeep(UInt16 frequency, int msDuration, UInt16 volume = 16383)
{
var mStrm = new MemoryStream();
BinaryWriter writer = new BinaryWriter(mStrm);
const double TAU = 2 * Math.PI;
int formatChunkSize = 16;
int headerSize = 8;
short formatType = 1;
short tracks = 1;
int samplesPerSecond = 44100;
short bitsPerSample = 16;
short frameSize = (short)(tracks * ((bitsPerSample + 7) / 8));
int bytesPerSecond = samplesPerSecond * frameSize;
int waveSize = 4;
int samples = (int)((decimal)samplesPerSecond * msDuration / 1000);
int dataChunkSize = samples * frameSize;
int fileSize = waveSize + headerSize + formatChunkSize + headerSize + dataChunkSize;
// var encoding = new System.Text.UTF8Encoding();
writer.Write(0x46464952); // = encoding.GetBytes("RIFF")
writer.Write(fileSize);
writer.Write(0x45564157); // = encoding.GetBytes("WAVE")
writer.Write(0x20746D66); // = encoding.GetBytes("fmt ")
writer.Write(formatChunkSize);
writer.Write(formatType);
writer.Write(tracks);
writer.Write(samplesPerSecond);
writer.Write(bytesPerSecond);
writer.Write(frameSize);
writer.Write(bitsPerSample);
writer.Write(0x61746164); // = encoding.GetBytes("data")
writer.Write(dataChunkSize);
{
double theta = frequency * TAU / (double)samplesPerSecond;
// 'volume' is UInt16 with range 0 thru Uint16.MaxValue ( = 65 535)
// we need 'amp' to have the range of 0 thru Int16.MaxValue ( = 32 767)
double amp = volume >> 2; // so we simply set amp = volume / 2
for (int step = 0; step < samples; step++)
{
short s = (short)(amp * Math.Sin(theta * (double)step));
writer.Write(s);
}
}
mStrm.Seek(0, SeekOrigin.Begin);
SoundEffect mySoundEffect = SoundEffect.FromStream(mStrm);
//mySoundEffect.Play(); //Crashing here
writer.Close();
mStrm.Close();
}
I wanna to calculate decibels of 1 second of any .wav file using naudio. This is my code:
WaveFileReader reader = new WaveFileReader(#"C:\Users\Admin\Desktop\result.wav");
int bytesPerMillisecond = reader.WaveFormat.AverageBytesPerSecond / 1000;
//byte[] buffer = new byte[reader.Length];
//int read = reader.Read(buffer, 0, (int)reader.Length);
TimeSpan time = new TimeSpan(0, 0, 1);
int bytesPerSecond = (int)time.TotalMilliseconds * bytesPerMillisecond;
byte[] oneSecondBuffer = new byte[bytesPerSecond];
int read = reader.Read(oneSecondBuffer, 0, bytesPerSecond);
short sample16Bit = BitConverter.ToInt16(oneSecondBuffer, 1);
double volume = Math.Abs(sample16Bit / 32768.0);
double decibels = 20 * Math.Log10(volume);
This line:
short sample16Bit = BitConverter.ToInt16(oneSecondBuffer, 1);
returns 0. What am I doing wrong?
I've resolved this task in another way. This is a piece of code, which may help other people:
var silenceDict = new Dictionary<int, bool>();
using (NAudio.Wave.AudioFileReader wave = new NAudio.Wave.AudioFileReader(filePath))
{
var samplesPerSecond = wave.WaveFormat.SampleRate * wave.WaveFormat.Channels;
var readBuffer = new float[samplesPerSecond];
int samplesRead;
int i = 1;
do
{
samplesRead = wave.Read(readBuffer, 0, samplesPerSecond);
if (samplesRead == 0) break;
var max = readBuffer.Take(samplesRead).Max();
if ((int)(max * 100) != 0)
silenceDict.Add(i, false);
else
silenceDict.Add(i, true);
i++;
} while (samplesRead > 0);
}
I am trying to implement a function which takes an wav file, runs a 100th of a second worth of audio through the FFT by AForge. When I change the offset to alter where in the audio I am computing through the FFT, sometimes I will get results in which I can show in my graph but most of the time I get a complex array of NaN's. Why could this be?
Here is my code.
public double[] test()
{
OpenFileDialog file = new OpenFileDialog();
file.ShowDialog();
WaveFileReader reader = new WaveFileReader(file.FileName);
byte[] data = new byte[reader.Length];
reader.Read(data, 0, data.Length);
samepleRate = reader.WaveFormat.SampleRate;
bitDepth = reader.WaveFormat.BitsPerSample;
channels = reader.WaveFormat.Channels;
Console.WriteLine("audio has " + channels + " channels, a sample rate of " + samepleRate + " and bitdepth of " + bitDepth + ".");
float[] floats = new float[data.Length / sizeof(float)];
Buffer.BlockCopy(data, 0, floats, 0, data.Length);
size = 2048;
int inputSamples = samepleRate / 100;
int offset = samepleRate * 15 * channels;
int y = 0;
Complex[] complexData = new Complex[size];
float[] window = CalcWindowFunction(inputSamples);
for (int i = 0; i < inputSamples; i++)
{
complexData[y] = new Complex(floats[i * channels + offset] * window[i], 0);
y++;
}
while (y < size)
{
complexData[y] = new Complex(0, 0);
y++;
}
FourierTransform.FFT(complexData, FourierTransform.Direction.Forward);
double[] arr = new double[complexData.Length];
for (int i = 0; i < complexData.Length; i++)
{
arr[i] = complexData[i].Magnitude;
}
Console.Write("complete, ");
return arr;
}
private float[] CalcWindowFunction(int inputSamples)
{
float[] arr = new float[size];
for(int i =0; i<size;i++){
arr[i] = 1;
}
return arr;
}
A complex array of NaNs is usually the result of one of the inputs to the FFT being a NaN. To debug, you might check all the values in the input array before the FFT to make sure they are within some valid range, given the audio input scaling.
Is it possible to read an array of structs from binary file in one call?
For example, I have a file containing thousands of vertices:
struct Vector3 { float x, y, z; }
I need C# port for the C++ code:
Vector3 *verts = new Vector3[num_verts];
fread ( verts, sizeof(Vector3), num_verts, f );
Here's one (of a few) ways:
void Main()
{
var pts =
(from x in Enumerable.Range(0, 10)
from y in Enumerable.Range(0, 10)
from z in Enumerable.Range(0, 10)
select new Vector3(){X = x, Y = y, Z = z}).ToArray();
// write it out...
var bigAssByteArray = new byte[Marshal.SizeOf(typeof(Vector3)) * pts.Length];
var pinnedHandle = GCHandle.Alloc(pts, GCHandleType.Pinned);
Marshal.Copy(pinnedHandle.AddrOfPinnedObject(), bigAssByteArray, 0, bigAssByteArray.Length);
pinnedHandle.Free();
File.WriteAllBytes(#"c:\temp\vectors.out", bigAssByteArray);
// ok, read it back...
var readBytes = File.ReadAllBytes(#"c:\temp\vectors.out");
var numVectors = readBytes.Length / Marshal.SizeOf(typeof(Vector3));
var readVectors = new Vector3[numVectors];
pinnedHandle = GCHandle.Alloc(readVectors, GCHandleType.Pinned);
Marshal.Copy(readBytes, 0, pinnedHandle.AddrOfPinnedObject(), readBytes.Length);
pinnedHandle.Free();
var allEqual =
pts.Zip(readVectors,
(v1,v2) => (v1.X == v2.X) && (v1.Y == v2.Y) && (v1.Z == v2.Z))
.All(p => p);
Console.WriteLine("pts == readVectors? {0}", allEqual);
}
struct Vector3
{
public float X;
public float Y;
public float Z;
}
Yes, it's possible, but you would have to add attributes to the structure so that you specify exactly how it's mapped in memory so that there is no padding in the struct.
Often it's easier to just convert the data yourself. The vast majority of the processing time will be reading the data from the file, so the overhead of converting the data is small. Example:
byte[] bytes = File.ReadAllBytes(fileName);
Vector3[] data = new Vector3[bytes.Length / 12];
for (var i = 0; i < data.Length; i++) {
Vector3 item;
item.x = BitConverter.ToSingle(bytes, i * 12);
item.y = BitConverter.ToSingle(bytes, i * 12 + 4);
item.z = BitConverter.ToSingle(bytes, i * 12 + 8);
data[i] = item;
}
I need fastest way to convert byte array to short array of audio data.
Audio data byte array contains data from two audio channels placed in such way:
C1C1C2C2 C1C1C2C2 C1C1C2C2 ...
where
C1C1 - two bytes of first channel
C2C2 - two bytes of second channel
Currently I use such algorithm, but I feel there is better way to perform this task.
byte[] rawData = //from audio device
short[] shorts = new short[rawData.Length / 2];
short[] channel1 = new short[rawData.Length / 4];
short[] channel2 = new short[rawData.Length / 4];
System.Buffer.BlockCopy(rawData, 0, shorts, 0, rawData.Length);
for (int i = 0, j = 0; i < shorts.Length; i+=2, ++j)
{
channel1[j] = shorts[i];
channel2[j] = shorts[i+1];
}
You can leave out copying the buffer:
byte[] rawData = //from audio device
short[] channel1 = new short[rawData.Length / 4];
short[] channel2 = new short[rawData.Length / 4];
for (int i = 0, j = 0; i < rawData.Length; i+=4, ++j)
{
channel1[j] = (short)(((ushort)rawData[i + 1]) << 8 | (ushort)rawData[i]);
channel2[j] = (short)(((ushort)rawData[i + 3]) << 8 | (ushort)rawData[i + 2]);
}
To get the loop faster, you can have a look at the Task Parralel Library, exspecially Parallel.For:
[EDIT]
System.Threading.Tasks.Parallel.For( 0, shorts.Length/2, ( i ) =>
{
channel1[i] = shorts[i*2];
channel2[i] = shorts[i*2+1];
} );
[/EDIT]
Another way is loop unrolling, but I think the TPL will boost this up as well.
You could use unsafe code to avoid array addressing or bit shifts. But as PVitt said on new PCs you are better using standard managed code and the TPL if your data size is important.
short[] channel1 = new short[rawData.Length / 4];
short[] channel2 = new short[rawData.Length / 4];
fixed(byte* pRawData = rawData)
fixed(short* pChannel1 = channel1)
fixed(short* pChannel2 = channel2)
{
byte* end = pRawData + rawData.Length;
while(pRawData < end)
{
(*(pChannel1++)) = *((short*)pRawData);
pRawData += sizeof(short);
(*(pChannel2++)) = *((short*)pRawData);
pRawData += sizeof(short);
}
}
As with all optimization problems you need to time carefully, pay special attention to your
buffer allocations, channel1 and channel2 could be static (big) buffers growing automatically
and you could use only the nth first bytes. You will be able to skip 2 big arrays allocations
for each executions of this function. and will make the GC work less
(always better when timing is important)
As noted by CodeInChaos the endianness could be important, if your data is not in the
correct endianness you will need to do the conversion, for example to convert between big
and little endian assuming 8bit atomic elements the code will look like :
short[] channel1 = new short[rawData.Length / 4];
short[] channel2 = new short[rawData.Length / 4];
fixed(byte* pRawData = rawData)
fixed(byte* pChannel1 = (byte*)channel1)
fixed(byte* pChannel2 = (byte*)channel2)
{
byte* end = pRawData + rawData.Length;
byte* pChannel1High = pChannel1 + 1;
byte* pChannel2High = pChannel2 + 1;
while(pRawData < end)
{
*pChannel1High = *pRawData;
pChannel1High += 2 * sizeof(short);
*pChannel1 = *pRawData;
pChannel1 += 2 * sizeof(short);
*pChannel2High = *pRawData;
pChannel2High += 2 * sizeof(short);
*pChannel2 = *pRawData;
pChannel2 += 2 * sizeof(short);
}
}
I didn't compile any code in this post with an actual compiler so if you find errors feel free to edit it.
You can benchmark it by yourself! remember to use Release Mode and run without Debug (Ctrl+F5)
class Program
{
[StructLayout(LayoutKind.Explicit)]
struct UnionArray
{
[FieldOffset(0)]
public byte[] Bytes;
[FieldOffset(0)]
public short[] Shorts;
}
unsafe static void Main(string[] args)
{
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
byte[] rawData = new byte[10000000];
new Random().NextBytes(rawData);
Stopwatch sw1 = Stopwatch.StartNew();
short[] shorts = new short[rawData.Length / 2];
short[] channel1 = new short[rawData.Length / 4];
short[] channel2 = new short[rawData.Length / 4];
System.Buffer.BlockCopy(rawData, 0, shorts, 0, rawData.Length);
for (int i = 0, j = 0; i < shorts.Length; i += 2, ++j)
{
channel1[j] = shorts[i];
channel2[j] = shorts[i + 1];
}
sw1.Stop();
Stopwatch sw2 = Stopwatch.StartNew();
short[] channel1b = new short[rawData.Length / 4];
short[] channel2b = new short[rawData.Length / 4];
for (int i = 0, j = 0; i < rawData.Length; i += 4, ++j)
{
channel1b[j] = BitConverter.ToInt16(rawData, i);
channel2b[j] = BitConverter.ToInt16(rawData, i + 2);
}
sw2.Stop();
Stopwatch sw3 = Stopwatch.StartNew();
short[] shortsc = new UnionArray { Bytes = rawData }.Shorts;
short[] channel1c = new short[rawData.Length / 4];
short[] channel2c = new short[rawData.Length / 4];
for (int i = 0, j = 0; i < shorts.Length; i += 2, ++j)
{
channel1c[j] = shortsc[i];
channel2c[j] = shortsc[i + 1];
}
sw3.Stop();
Stopwatch sw4 = Stopwatch.StartNew();
short[] channel1d = new short[rawData.Length / 4];
short[] channel2d = new short[rawData.Length / 4];
for (int i = 0, j = 0; i < rawData.Length; i += 4, ++j)
{
channel1d[j] = (short)((short)(rawData[i + 1]) << 8 | (short)rawData[i]);
channel2d[j] = (short)((short)(rawData[i + 3]) << 8 | (short)rawData[i + 2]);
//Equivalent warning-less version
//channel1d[j] = (short)(((ushort)rawData[i + 1]) << 8 | (ushort)rawData[i]);
//channel2d[j] = (short)(((ushort)rawData[i + 3]) << 8 | (ushort)rawData[i + 2]);
}
sw4.Stop();
Stopwatch sw5 = Stopwatch.StartNew();
short[] channel1e = new short[rawData.Length / 4];
short[] channel2e = new short[rawData.Length / 4];
fixed (byte* pRawData = rawData)
fixed (short* pChannel1 = channel1e)
fixed (short* pChannel2 = channel2e)
{
byte* pRawData2 = pRawData;
short* pChannel1e = pChannel1;
short* pChannel2e = pChannel2;
byte* end = pRawData2 + rawData.Length;
while (pRawData2 < end)
{
(*(pChannel1e++)) = *((short*)pRawData2);
pRawData2 += sizeof(short);
(*(pChannel2e++)) = *((short*)pRawData2);
pRawData2 += sizeof(short);
}
}
sw5.Stop();
Stopwatch sw6 = Stopwatch.StartNew();
short[] shortse = new short[rawData.Length / 2];
short[] channel1f = new short[rawData.Length / 4];
short[] channel2f = new short[rawData.Length / 4];
System.Buffer.BlockCopy(rawData, 0, shortse, 0, rawData.Length);
System.Threading.Tasks.Parallel.For(0, shortse.Length / 2, (i) =>
{
channel1f[i] = shortse[i * 2];
channel2f[i] = shortse[i * 2 + 1];
});
sw6.Stop();
if (!channel1.SequenceEqual(channel1b) || !channel1.SequenceEqual(channel1c) || !channel1.SequenceEqual(channel1d) || !channel1.SequenceEqual(channel1e) || !channel1.SequenceEqual(channel1f))
{
throw new Exception();
}
if (!channel2.SequenceEqual(channel2b) || !channel2.SequenceEqual(channel2c) || !channel2.SequenceEqual(channel2d) || !channel2.SequenceEqual(channel2e) || !channel2.SequenceEqual(channel2f))
{
throw new Exception();
}
Console.WriteLine("Original: {0}ms", sw1.ElapsedMilliseconds);
Console.WriteLine("BitConverter: {0}ms", sw2.ElapsedMilliseconds);
Console.WriteLine("Super-unsafe struct: {0}ms", sw3.ElapsedMilliseconds);
Console.WriteLine("PVitt shifts: {0}ms", sw4.ElapsedMilliseconds);
Console.WriteLine("unsafe VirtualBlackFox: {0}ms", sw5.ElapsedMilliseconds);
Console.WriteLine("TPL: {0}ms", sw6.ElapsedMilliseconds);
Console.ReadKey();
return;
}
}
On x86 fastest is the unsafe code of VirtualBlackFox, second the "super unsafe" struct "trick" of C# unsafe value type array to byte array conversions, third PVitt.
On x64 fastest is the unsafe code of VirtualBlackFox, second PVitt.