public RiffCodec Read(string filePath) { using var file = File.OpenRead(filePath); var buffer = new byte[1024]; int read = file.Read(buffer, 0, 1024); var readOnlySpan = new ReadOnlySpan <byte>(buffer); var riff = new RiffCodec(); riff.Signature = Encoding.ASCII.GetString(readOnlySpan.Slice(0, 4)); EnforceCorrectMarker(riff.Signature, RIFF_SIGNATURE, nameof(riff.Signature)); riff.Filesize = BinaryPrimitives.ReadUInt32LittleEndian(readOnlySpan.Slice(4, 4)); riff.FormatHeaderType = Encoding.ASCII.GetString(readOnlySpan.Slice(8, 4)); riff.FormatChunkMarker = Encoding.ASCII.GetString(readOnlySpan.Slice(12, 4)); EnforceCorrectMarker(riff.FormatChunkMarker, MARKER_FMT, nameof(riff.FormatChunkMarker)); riff.FormatHeaderSize = BinaryPrimitives.ReadUInt32LittleEndian(readOnlySpan.Slice(16, 4)); riff.FormatHeader = ReadFormatHeader(readOnlySpan, riff.FormatHeaderType, riff.FormatHeaderSize); riff.DataChunkMarker = Encoding.ASCII.GetString(readOnlySpan.Slice(20 + (int)riff.FormatHeaderSize, 4)); EnforceCorrectMarker(riff.DataChunkMarker, MARKER_DATA, nameof(riff.DataChunkMarker)); riff.DataSize = BinaryPrimitives.ReadUInt32LittleEndian(readOnlySpan.Slice(24 + (int)riff.FormatHeaderSize, 4)); riff.Data = new byte[riff.DataSize]; int currentPos = 28 + (int)riff.FormatHeaderSize; Array.Copy(buffer, currentPos, riff.Data, 0, 1024 - currentPos); bool finished = false; currentPos = 1024 - currentPos; do { read = file.Read(buffer, 0, 1024); if (read > 0) { if ((currentPos + read) > riff.DataSize) { int amountToCopy = (int)riff.DataSize - currentPos; Array.Copy(buffer, 0, riff.Data, currentPos, amountToCopy); currentPos += amountToCopy; //var ros = new ReadOnlySpan<byte>(buffer); //Console.WriteLine($"Weird: {Encoding.ASCII.GetString(ros.Slice(amountToCopy, read - amountToCopy))}"); } else { Array.Copy(buffer, 0, riff.Data, currentPos, read); currentPos += read; } } else { finished = true; } } while (!finished); return(riff); }
public async Task PlayWave(RiffCodec riff) { uint WAVE_MAPPER = uint.MaxValue; int CALLBACK_NULL = 0; IntPtr handle = IntPtr.Zero; var header = riff.FormatHeader as WaveFormatHeader; int duration = Convert.ToInt32(header.AvgBytesPerSec / header.SampleRate); var waveFormat = new WAVEFORMAT { wFormatTag = header.FormatTag, nChannels = header.ChannelsCount, nSamplesPerSec = header.SampleRate, nAvgBytesPerSec = header.AvgBytesPerSec, nBlockAlign = header.BlockAlign, wBitsPerSample = header.BitsPerSample, cbSize = header.ExtraInfoSize }; var waveHdr = new WAVEHDR { dwBufferLength = riff.DataSize, dwBytesRecorded = riff.DataSize, dwUser = 0, dwFlags = 0, dwLoops = 0 }; using var buffer = new UnamanagedMemory((int)riff.DataSize); Marshal.Copy(riff.Data, 0, buffer.Pointer, riff.Data.Length); waveHdr.lpData = buffer.Pointer; uint res = uint.MaxValue; res = WindowsMultimedia.waveOutOpen(ref handle, WAVE_MAPPER, ref waveFormat, 0, 0, CALLBACK_NULL); CheckMethodResult(nameof(WindowsMultimedia.waveOutOpen), res); res = WindowsMultimedia.waveOutPrepareHeader(handle, ref waveHdr, Marshal.SizeOf(waveHdr)); CheckMethodResult(nameof(WindowsMultimedia.waveOutPrepareHeader), res); res = WindowsMultimedia.waveOutWrite(handle, ref waveHdr, Marshal.SizeOf(waveHdr)); CheckMethodResult(nameof(WindowsMultimedia.waveOutWrite), res); await Task.Delay(duration * 1000); res = WindowsMultimedia.waveOutClose(handle); CheckMethodResult(nameof(WindowsMultimedia.waveOutClose), res); }