Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }