Skip to content

Instantly share code, notes, and snippets.

@clarvalon
Last active November 6, 2018 23:53
Show Gist options
  • Save clarvalon/6d36c2ed9af6d607a04b76a662571405 to your computer and use it in GitHub Desktop.
Save clarvalon/6d36c2ed9af6d607a04b76a662571405 to your computer and use it in GitHub Desktop.
Loading Ogg Vorbis via FAudio
// Not profiled and undoubtedly could be improved ...
public SoundEffect LoadOgg(Stream stream)
{
// Turn .ogg stream into byte buffer
byte[] rawData = new byte[stream.Length];
stream.Read(rawData, 0, (int)stream.Length);
// Access byte buffer as a pointer
GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
IntPtr address = rawDataHandle.AddrOfPinnedObject();
IntPtr output = IntPtr.Zero;
int error;
// Open .ogg natively via FAudio and get info
IntPtr decoder = FAudio.stb_vorbis_open_memory(address, (int)stream.Length, out error, output);
var info = FAudio.stb_vorbis_get_info(decoder);
uint numSamples = FAudio.stb_vorbis_stream_length_in_samples(decoder);
int channels = info.channels;
// Decode .ogg natively into float buffer
float[] floatBuffer = new float[numSamples * 2];
FAudio.stb_vorbis_get_samples_float_interleaved(decoder, channels, floatBuffer, floatBuffer.Length);
// Convert float buffer to byte buffer
byte[] byteBuffer = new byte[numSamples * 4];
for (int i = 0; i < floatBuffer.Length; i++)
{
short val = (short)Math.Max(Math.Min(short.MaxValue * floatBuffer[i], short.MaxValue), short.MinValue);
var decoded = BitConverter.GetBytes(val);
byteBuffer[i * 2] = decoded[0];
byteBuffer[i * 2 + 1] = decoded[1];
}
// Create SoundEffect using byte buffer
SoundEffect soundEffect = new SoundEffect(byteBuffer, (int)info.sample_rate, channels == 1 ? AudioChannels.Mono : AudioChannels.Stereo);
rawDataHandle.Free();
address = IntPtr.Zero;
output = IntPtr.Zero;
decoder = IntPtr.Zero;
return soundEffect;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment