Initial sound impl

This commit is contained in:
2023-08-28 18:38:06 +02:00
parent 06c521a981
commit f4f88f711a
17 changed files with 372 additions and 10 deletions

View File

@@ -0,0 +1,7 @@
namespace Ryuclaw.Audio.Shared;
public class Class1
{
}

View File

@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,24 @@
using System;
namespace Ryuclaw.Audio.Shared
{
public class WaveHeader
{
public int SampleRate { get; private set; }
public int ChunkSize { get; private set; }
public int ByteRate { get; private set; }
public short BitsPerSample { get; private set; }
public short NumChannels { get; private set; }
public short BlockAlign { get; private set; }
public WaveHeader(int sampleRate = 48000, int chunkSize = 16, int byteRate = 16, short bitsPerSample = 16, short numChannels = 1, short blockAlign = 8)
{
SampleRate = sampleRate;
ChunkSize = chunkSize;
ByteRate = byteRate;
BitsPerSample = bitsPerSample;
NumChannels = numChannels;
BlockAlign = blockAlign;
}
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.IO;
namespace Ryuclaw.Audio.Shared
{
public class WaveReader
{
private WaveHeader _header;
public byte[] AudioData { get; private set; }
public WaveReader()
{
_header = new WaveHeader();
AudioData = new byte[0];
}
public void Load(string filePath)
{
using (var stream = new FileStream(filePath, FileMode.Open))
using (var reader = new BinaryReader(stream))
{
// RIFF header
string chunkID = new string(reader.ReadChars(4));
if (chunkID != "RIFF") throw new Exception("Not a valid WAV file.");
var ChunkSize = reader.ReadInt32(); // Chunk size
string format = new string(reader.ReadChars(4));
if (format != "WAVE") throw new Exception("Not a valid WAV file.");
// fmt sub-chunk
string subchunk1ID = new string(reader.ReadChars(4));
if (subchunk1ID != "fmt ") throw new Exception("Expected fmt chunk.");
int subChunk1Size = reader.ReadInt32();
short audioFormat = reader.ReadInt16();
var NumChannels = reader.ReadInt16();
var SampleRate = reader.ReadInt32();
var ByteRate = reader.ReadInt32(); // Byte rate
var BlockAlign = reader.ReadInt16(); // Block align
var BitsPerSample = reader.ReadInt16();
_header = new WaveHeader(SampleRate, ChunkSize, ByteRate, BitsPerSample, NumChannels, BlockAlign);
if (audioFormat != 1 || subChunk1Size != 16)
{
throw new Exception("Only PCM format WAV files are supported.");
}
// data sub-chunk
string subchunk2ID = new string(reader.ReadChars(4));
if (subchunk2ID != "data") throw new Exception("Expected data chunk.");
int subChunk2Size = reader.ReadInt32();
AudioData = reader.ReadBytes(subChunk2Size);
}
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.IO;
namespace Ryuclaw.Audio.Shared
{
public class WaveStreamer : IDisposable
{
private readonly FileStream _fileStream;
private readonly BinaryReader _reader;
private long _dataPosition; // This will store the position where audio data begins in the file.
private int _dataLength; // This will store the length of the audio data.
private WaveHeader _header;
public WaveStreamer(string filePath)
{
_header = new WaveHeader();
_fileStream = new FileStream(filePath, FileMode.Open);
_reader = new BinaryReader(_fileStream);
LoadHeader();
}
private void LoadHeader()
{
// RIFF header
string chunkID = new string(_reader.ReadChars(4));
if (chunkID != "RIFF") throw new Exception("Not a valid WAV file.");
var ChunkSize = _reader.ReadInt32(); // Chunk size
string format = new string(_reader.ReadChars(4));
if (format != "WAVE") throw new Exception("Not a valid WAV file.");
// fmt sub-chunk
string subchunk1ID = new string(_reader.ReadChars(4));
if (subchunk1ID != "fmt ") throw new Exception("Expected fmt chunk.");
int subChunk1Size = _reader.ReadInt32();
short audioFormat = _reader.ReadInt16();
var NumChannels = _reader.ReadInt16();
var SampleRate = _reader.ReadInt32();
var ByteRate = _reader.ReadInt32(); // Byte rate
var BlockAlign = _reader.ReadInt16(); // Block align
var BitsPerSample = _reader.ReadInt16();
_header = new WaveHeader(SampleRate, ChunkSize, ByteRate, BitsPerSample, NumChannels, BlockAlign);
if (audioFormat != 1 || subChunk1Size != 16)
{
throw new Exception("Only PCM format WAV files are supported.");
}
// data sub-chunk
string subchunk2ID = new string(_reader.ReadChars(4));
if (subchunk2ID != "data") throw new Exception("Expected data chunk.");
_dataLength = _reader.ReadInt32();
_dataPosition = _fileStream.Position; // Store the position where audio data begins.
}
public byte[] ReadData(int byteCount)
{
_fileStream.Seek(_dataPosition, SeekOrigin.Begin);
byte[] buffer = _reader.ReadBytes(byteCount); // Read a chunk of audio data.
_dataPosition = _fileStream.Position; // Update the position to start from next time.
return buffer;
}
public bool HasDataLeft()
{
return _fileStream.Position < _dataPosition + _dataLength;
}
public void Dispose()
{
_reader.Dispose();
_fileStream.Dispose();
}
}
}