Lucas Teske revidoval tento gist 9 years ago. Přejít na revizi
2 files changed, 178 insertions
WaveReader.cs(vytvořil soubor)
| @@ -0,0 +1,95 @@ | |||
| 1 | + | using System; | |
| 2 | + | using System.IO; | |
| 3 | + | using System.Text; | |
| 4 | + | using RTLSharp.Audio.Structs; | |
| 5 | + | using System.Text.RegularExpressions; | |
| 6 | + | using System.Globalization; | |
| 7 | + | ||
| 8 | + | namespace RTLSharp.Audio { | |
| 9 | + | public class WaveReader { | |
| 10 | + | //private readonly static Regex SDRSharpRegex = new Regex(@"SDRSharp_([0-9]+)_([0-9]+).__([0-9]+)Hz_(.+)\.wav", RegexOptions.IgnoreCase); | |
| 11 | + | // SDRSharp_20160922_003831Z_137900000Hz_IQ | |
| 12 | + | private readonly static Regex SDRSharpRegex = new Regex(@"SDRSharp_([0-9]+)_([0-9]+)._([0-9]+)Hz_(.+)\.wav", RegexOptions.IgnoreCase); | |
| 13 | + | private readonly static Regex MetDemodIFRecorderRegex = new Regex(@"([0-9]+)-([0-9]+)-([0-9]+)_([0-9]+)kHz\.wav", RegexOptions.IgnoreCase); | |
| 14 | + | ||
| 15 | + | private static bool isSDRSharpFile(string fileName) { | |
| 16 | + | return SDRSharpRegex.IsMatch(fileName); | |
| 17 | + | } | |
| 18 | + | ||
| 19 | + | private static bool isMetDemodIFFile(string fileName) { | |
| 20 | + | return MetDemodIFRecorderRegex.IsMatch(fileName); | |
| 21 | + | } | |
| 22 | + | public static Wave readFromFile(string fileName) { | |
| 23 | + | if (File.Exists(fileName)) { | |
| 24 | + | ChunkHeader header = new ChunkHeader(); | |
| 25 | + | FormatChunkHeader subHeader = new FormatChunkHeader(); | |
| 26 | + | DataChunkHeader dataHeader = new DataChunkHeader(); | |
| 27 | + | Wave wave = new Wave(); | |
| 28 | + | string basename = Path.GetFileName(fileName); | |
| 29 | + | if (isSDRSharpFile(basename)) { | |
| 30 | + | MatchCollection matches = SDRSharpRegex.Matches(basename); | |
| 31 | + | GroupCollection groups = matches[0].Groups; | |
| 32 | + | uint.TryParse(groups[3].Value, out wave.Frequency); | |
| 33 | + | wave.DateTime = DateTime.ParseExact(groups[1].Value + groups[2].Value, "yyyyMMddHHmmss", CultureInfo.InvariantCulture); | |
| 34 | + | } else if (isMetDemodIFFile(basename)) { | |
| 35 | + | MatchCollection matches = MetDemodIFRecorderRegex.Matches(basename); | |
| 36 | + | GroupCollection groups = matches[0].Groups; | |
| 37 | + | uint.TryParse(groups[4].Value, out wave.Frequency); | |
| 38 | + | wave.Frequency *= 1000; | |
| 39 | + | wave.DateTime = DateTime.ParseExact(groups[1].Value + groups[2].Value + groups[3].Value, "HHmmss", CultureInfo.InvariantCulture); | |
| 40 | + | } | |
| 41 | + | ||
| 42 | + | using (BinaryReader reader = new BinaryReader(File.Open(fileName, FileMode.Open))) { | |
| 43 | + | subHeader.Format = WavType.UNKNOWN; | |
| 44 | + | ||
| 45 | + | header.Id = Encoding.UTF8.GetString(reader.ReadBytes(4)); | |
| 46 | + | header.Size = reader.ReadUInt32(); | |
| 47 | + | header.Format = Encoding.UTF8.GetString(reader.ReadBytes(4)); | |
| 48 | + | ||
| 49 | + | if (!header.Id.Equals("RIFF")) { | |
| 50 | + | Console.WriteLine("Non Wave file!"); | |
| 51 | + | } | |
| 52 | + | ||
| 53 | + | Console.WriteLine("ID: {0}\nSize: {1}\nFormat: {2}", header.Id, header.Size, header.Format); | |
| 54 | + | ||
| 55 | + | bool cont = true; | |
| 56 | + | while (reader.BaseStream.Position != reader.BaseStream.Length && cont) { | |
| 57 | + | string chunkId = Encoding.UTF8.GetString(reader.ReadBytes(4)).Trim(); | |
| 58 | + | switch (chunkId) { | |
| 59 | + | case "fmt": | |
| 60 | + | subHeader.Id = chunkId; | |
| 61 | + | subHeader.Size = reader.ReadUInt32(); | |
| 62 | + | subHeader.Format = (WavType)reader.ReadUInt16(); | |
| 63 | + | subHeader.Channels = reader.ReadUInt16(); | |
| 64 | + | subHeader.SampleRate = reader.ReadUInt32(); | |
| 65 | + | subHeader.ByteRate = reader.ReadUInt32(); | |
| 66 | + | subHeader.BlockAlign = reader.ReadUInt16(); | |
| 67 | + | subHeader.BitsPerSample = reader.ReadUInt16(); | |
| 68 | + | ||
| 69 | + | wave.SampleRate = subHeader.SampleRate; | |
| 70 | + | ||
| 71 | + | Console.WriteLine("Format Chunk 0:\n\tId: {0}\n\tSize: {1}\n\tFormat: {2}\n\tChannels: {3}\n\tSample Rate: {4}\n\tByte Rate: {5}\n\tBlock Align: {6}\n\tBitsPerSample: {7}", subHeader.Id, subHeader.Size, subHeader.Format, subHeader.Channels, subHeader.SampleRate, subHeader.ByteRate, subHeader.BlockAlign, subHeader.BitsPerSample); | |
| 72 | + | break; | |
| 73 | + | case "data": | |
| 74 | + | dataHeader.Id = chunkId; | |
| 75 | + | dataHeader.Size = reader.ReadUInt32(); | |
| 76 | + | wave.Data = new WaveStream(fileName, reader.BaseStream.Position, dataHeader.Size, subHeader); | |
| 77 | + | ||
| 78 | + | Console.WriteLine("Data Chunk 0:\n\tId: {0}\n\tSize: {1}", dataHeader.Id, dataHeader.Size); | |
| 79 | + | cont = false; | |
| 80 | + | break; | |
| 81 | + | default: | |
| 82 | + | Console.WriteLine("Not recognized: {0}", chunkId); | |
| 83 | + | cont = false; | |
| 84 | + | break; | |
| 85 | + | } | |
| 86 | + | } | |
| 87 | + | } | |
| 88 | + | return wave; | |
| 89 | + | } else { | |
| 90 | + | Console.WriteLine("File does not exists!"); | |
| 91 | + | return null; | |
| 92 | + | } | |
| 93 | + | } | |
| 94 | + | } | |
| 95 | + | } | |
WaveStream.cs(vytvořil soubor)
| @@ -0,0 +1,83 @@ | |||
| 1 | + | using RTLSharp.Audio.Structs; | |
| 2 | + | using RTLSharp.Types; | |
| 3 | + | using System; | |
| 4 | + | using System.IO; | |
| 5 | + | ||
| 6 | + | namespace RTLSharp.Audio { | |
| 7 | + | public class WaveStream { | |
| 8 | + | private BinaryReader _reader; | |
| 9 | + | private string _fileName; | |
| 10 | + | private long _readPosition; | |
| 11 | + | private long _readSize; | |
| 12 | + | private FormatChunkHeader _format; | |
| 13 | + | ||
| 14 | + | internal WaveStream(string fileName, long readPosition, long readSize, FormatChunkHeader format) { | |
| 15 | + | _readPosition = readPosition; | |
| 16 | + | _readSize = readSize; | |
| 17 | + | _fileName = fileName; | |
| 18 | + | _format = format; | |
| 19 | + | } | |
| 20 | + | ||
| 21 | + | public void Open() { | |
| 22 | + | if (File.Exists(FileName)) { | |
| 23 | + | _reader = new BinaryReader(File.Open(FileName, FileMode.Open)); | |
| 24 | + | _reader.BaseStream.Position = _readPosition; | |
| 25 | + | } | |
| 26 | + | } | |
| 27 | + | ||
| 28 | + | public void Close() { | |
| 29 | + | if (_reader != null) { | |
| 30 | + | _reader.Close(); | |
| 31 | + | } | |
| 32 | + | } | |
| 33 | + | public float readFloat() { | |
| 34 | + | return (_reader.BaseStream.Position < _readPosition + _readSize) ? _reader.ReadSingle() : 0.0f; | |
| 35 | + | } | |
| 36 | + | ||
| 37 | + | public Int16 readInt16() { | |
| 38 | + | return (_reader.BaseStream.Position < _readPosition + _readSize) ? _reader.ReadInt16() : (Int16) 0; | |
| 39 | + | } | |
| 40 | + | ||
| 41 | + | public byte readByte() { | |
| 42 | + | return (_reader.BaseStream.Position < _readPosition + _readSize) ? _reader.ReadByte() : (byte)0; | |
| 43 | + | } | |
| 44 | + | ||
| 45 | + | public Complex readComplex() { | |
| 46 | + | float real = 0.0f, imag = 0.0f; | |
| 47 | + | ||
| 48 | + | switch (_format.Format) { | |
| 49 | + | case WavType.FLOAT: | |
| 50 | + | real = readFloat(); | |
| 51 | + | imag = (_format.Channels == 2) ? readFloat() : 0.0f; | |
| 52 | + | break; | |
| 53 | + | case WavType.PCM: | |
| 54 | + | if (_format.Size == 8) { | |
| 55 | + | real = (readByte() - 128) / 127.0f; | |
| 56 | + | imag = (_format.Channels == 2) ? (readByte() - 128) / 127.0f : 0.0f; | |
| 57 | + | } else if (_format.Size == 16) { | |
| 58 | + | real = readInt16() / 16384.0f; | |
| 59 | + | imag = (_format.Channels == 2) ? readInt16() / 16384.0f : 0.0f; | |
| 60 | + | } | |
| 61 | + | break; | |
| 62 | + | } | |
| 63 | + | ||
| 64 | + | return new Complex(real, imag); | |
| 65 | + | } | |
| 66 | + | ||
| 67 | + | public void readComplexes(ref Complex[] cs, uint size) { | |
| 68 | + | for (int i=0; i<size; i++) { | |
| 69 | + | cs[i] = readComplex(); | |
| 70 | + | } | |
| 71 | + | } | |
| 72 | + | ||
| 73 | + | public unsafe void readComplexes(Complex *cs, uint size) { | |
| 74 | + | for (int i = 0; i < size; i++) { | |
| 75 | + | cs[i] = readComplex(); | |
| 76 | + | } | |
| 77 | + | } | |
| 78 | + | ||
| 79 | + | public string FileName { | |
| 80 | + | get { return _fileName; } | |
| 81 | + | } | |
| 82 | + | } | |
| 83 | + | } | |
Novější
Starší