SDRSharper/Plugins/SDRSharper.WaveRecorder/SDRSharp.WavRecorder/SimpleWavWriter.cs
SDRSharpR c07e6e6034 SDRSharper (SDRSharp Remake) Full Source (VS2017)
SDRSharper (SDRSharp Remake) Full Source (VS2017)
2018-03-26 14:02:05 -07:00

205 lines
5.4 KiB
C#

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace SDRSharp.WavRecorder
{
public class SimpleWavWriter
{
private const long MaxStreamLength = 2147483647L;
private readonly string _filename;
private readonly WavFormatHeader _format;
private readonly WavSampleFormat _wavSampleFormat;
private BinaryWriter _outputStream;
private long _fileSizeOffs;
private long _dataSizeOffs;
private long _length;
private byte[] _outputBuffer;
private bool _isStreamFull;
public WavSampleFormat SampleFormat => this._wavSampleFormat;
public WavFormatHeader WaveFormat => this._format;
public string FileName => this._filename;
public long Length => this._length;
public bool IsStreamFull => this._isStreamFull;
public SimpleWavWriter(string filename, WavSampleFormat recordingFormat, uint sampleRate)
{
this._filename = filename;
this._wavSampleFormat = recordingFormat;
this._format = new WavFormatHeader(recordingFormat, 2, sampleRate);
}
public void Open()
{
if (this._outputStream == null)
{
this._outputStream = new BinaryWriter(File.Create(this._filename));
this.WriteHeader();
return;
}
throw new InvalidOperationException("Stream already open");
}
public void Close()
{
if (this._outputStream != null)
{
this.UpdateLength();
this._outputStream.Flush();
this._outputStream.Close();
this._outputStream = null;
this._outputBuffer = null;
return;
}
throw new InvalidOperationException("Stream not open");
}
public unsafe void Write(float* data, int length)
{
if (this._outputStream != null)
{
switch (this._wavSampleFormat)
{
case WavSampleFormat.PCM8:
this.WritePCM8(data, length);
break;
case WavSampleFormat.PCM16:
this.WritePCM16(data, length);
break;
case WavSampleFormat.Float32:
this.WriteFloat(data, length);
break;
}
return;
}
throw new InvalidOperationException("Stream not open");
}
private unsafe void WritePCM8(float* data, int length)
{
if (this._outputBuffer == null || this._outputBuffer.Length != length * 2)
{
this._outputBuffer = null;
this._outputBuffer = new byte[length * 2];
}
float* ptr = data;
for (int i = 0; i < length; i++)
{
byte[] outputBuffer = this._outputBuffer;
int num = i * 2;
float* intPtr = ptr;
ptr = intPtr + 1;
outputBuffer[num] = (byte)(*intPtr * 128f + 128f);
byte[] outputBuffer2 = this._outputBuffer;
int num2 = i * 2 + 1;
float* intPtr2 = ptr;
ptr = intPtr2 + 1;
outputBuffer2[num2] = (byte)(*intPtr2 * 128f + 128f);
}
this.WriteStream(this._outputBuffer);
}
private unsafe void WritePCM16(float* data, int length)
{
if (this._outputBuffer == null || this._outputBuffer.Length != length * 2 * 2)
{
this._outputBuffer = null;
this._outputBuffer = new byte[length * 2 * 2];
}
float* ptr = data;
for (int i = 0; i < length; i++)
{
float* intPtr = ptr;
ptr = intPtr + 1;
short num = (short)(*intPtr * 32767f);
float* intPtr2 = ptr;
ptr = intPtr2 + 1;
short num2 = (short)(*intPtr2 * 32767f);
this._outputBuffer[i * 4] = (byte)(num & 0xFF);
this._outputBuffer[i * 4 + 1] = (byte)(num >> 8);
this._outputBuffer[i * 4 + 2] = (byte)(num2 & 0xFF);
this._outputBuffer[i * 4 + 3] = (byte)(num2 >> 8);
}
this.WriteStream(this._outputBuffer);
}
private unsafe void WriteFloat(float* data, int length)
{
if (this._outputBuffer == null || this._outputBuffer.Length != length * 4 * 2)
{
this._outputBuffer = null;
this._outputBuffer = new byte[length * 4 * 2];
}
Marshal.Copy((IntPtr)(void*)data, this._outputBuffer, 0, this._outputBuffer.Length);
this.WriteStream(this._outputBuffer);
}
private void WriteStream(byte[] data)
{
if (this._outputStream != null)
{
int num = (int)Math.Min(2147483647 - this._outputStream.BaseStream.Length, data.Length);
this._outputStream.Write(data, 0, num);
this._length += num;
this.UpdateLength();
this._isStreamFull = (this._outputStream.BaseStream.Length >= 2147483647);
}
}
private void WriteHeader()
{
if (this._outputStream != null)
{
this.WriteTag("RIFF");
this._fileSizeOffs = this._outputStream.BaseStream.Position;
this._outputStream.Write(0u);
this.WriteTag("WAVE");
this.WriteTag("fmt ");
this._outputStream.Write(16u);
this._outputStream.Write(this._format.FormatTag);
this._outputStream.Write(this._format.Channels);
this._outputStream.Write(this._format.SamplesPerSec);
this._outputStream.Write(this._format.AvgBytesPerSec);
this._outputStream.Write(this._format.BlockAlign);
this._outputStream.Write(this._format.BitsPerSample);
this.WriteTag("data");
this._dataSizeOffs = this._outputStream.BaseStream.Position;
this._outputStream.Write(0u);
}
}
private void UpdateLength()
{
if (this._outputStream != null)
{
this._outputStream.Seek((int)this._fileSizeOffs, SeekOrigin.Begin);
this._outputStream.Write((uint)(this._outputStream.BaseStream.Length - 8));
this._outputStream.Seek((int)this._dataSizeOffs, SeekOrigin.Begin);
this._outputStream.Write((uint)this._length);
this._outputStream.BaseStream.Seek(0L, SeekOrigin.End);
}
}
private void WriteTag(string tag)
{
byte[] bytes = Encoding.ASCII.GetBytes(tag);
this._outputStream.Write(bytes, 0, bytes.Length);
}
}
}