Elementary/Elementary/Audio/AudioMixer.cs
2023-07-25 01:16:16 +09:00

80 lines
2.2 KiB
C#

using ManagedBass;
using ManagedBass.Mix;
namespace Elementary.Audio;
public class AudioMixer
{
private readonly int _mixerStream;
private MemoryStream?[] _inputStreams;
private Stream _outStream;
private object _lock = new();
public AudioMixer(Stream outStream)
{
_outStream = outStream;
Bass.Init(-1, 44100, DeviceInitFlags.NoSpeakerAssignment, IntPtr.Zero);
_mixerStream = BassMix.CreateMixerStream(44100, 2, BassFlags.Float | BassFlags.MixerNonStop);
_inputStreams = new MemoryStream[10];
Bass.ChannelPlay(_mixerStream);
}
/// <summary>
/// Add a stream to the mixer.
/// wait for the stream to finish playing
/// </summary>
/// <param name="stream"></param>
/// <param name="volume"></param>
public void AddStream(Stream stream, float volume = 1.0f)
{
Console.WriteLine("Adding stream to mixer");
byte[] pcmBytes;
using (MemoryStream ms = new())
{
stream.CopyTo(ms);
pcmBytes = ms.ToArray();
}
lock (_lock)
{
for (var i = 0; i < _inputStreams.Length; i++)
{
if (_inputStreams[i] == null)
{
_inputStreams[i] = new MemoryStream(pcmBytes);
break;
}
}
}
var channel = Bass.CreateStream(pcmBytes, 0, pcmBytes.Length, BassFlags.Float);
Bass.ChannelSetAttribute(channel, ChannelAttribute.Volume, volume);
BassMix.MixerAddChannel(_mixerStream, channel, BassFlags.Default);
int length = Bass.ChannelGetData(_mixerStream, new byte[4096], 4096);
byte[] buffer = new byte[length];
length = Bass.ChannelGetData(_mixerStream, buffer, length);
_outStream.Write(buffer, 0, length);
}
public void Stop()
{
Bass.ChannelStop(_mixerStream);
}
public void Dispose()
{
lock (_lock)
{
foreach (var stream in _inputStreams)
{
stream?.Dispose();
}
}
_outStream.Flush();
Bass.StreamFree(_mixerStream);
Bass.Free();
}
}