85 lines
2.5 KiB
C#
85 lines
2.5 KiB
C#
using NAudio.Wave;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Projector
|
|
{
|
|
// Custom ISampleProvider to mix 4 channels to stereo
|
|
public class FourChannelToStereoSampleProvider : ISampleProvider
|
|
{
|
|
private readonly ISampleProvider _source;
|
|
private float offTransition = 1f;
|
|
private float _voiceVolume = 0f;
|
|
private bool goingOff = false;
|
|
|
|
public WaveFormat WaveFormat { get; }
|
|
|
|
public void SetOff()
|
|
{
|
|
goingOff = true;
|
|
}
|
|
|
|
public bool IsOff => goingOff && offTransition == 0f;
|
|
|
|
public float VoiceVolume
|
|
{
|
|
get
|
|
{
|
|
return _voiceVolume;
|
|
}
|
|
set
|
|
{
|
|
_voiceVolume = Math.Clamp(value, 0f, 1f);
|
|
}
|
|
}
|
|
|
|
public FourChannelToStereoSampleProvider(ISampleProvider source)
|
|
{
|
|
if (source.WaveFormat.Channels != 4)
|
|
throw new ArgumentException("Source must have 4 channels");
|
|
if (source.WaveFormat.Encoding != WaveFormatEncoding.IeeeFloat)
|
|
throw new ArgumentException("Source must be IEEE float format");
|
|
|
|
_source = source;
|
|
WaveFormat = WaveFormat.CreateIeeeFloatWaveFormat(source.WaveFormat.SampleRate, 2);
|
|
}
|
|
|
|
public int Read(float[] buffer, int offset, int count)
|
|
{
|
|
int samplesNeeded = (count / 2) * 4;
|
|
float[] sourceBuffer = new float[samplesNeeded];
|
|
int samplesRead = _source.Read(sourceBuffer, 0, samplesNeeded);
|
|
|
|
int stereoSamples = samplesRead / 4 * 2;
|
|
int outIndex = offset;
|
|
|
|
if (goingOff && offTransition > 0f)
|
|
{
|
|
offTransition -= 0.2f;
|
|
if (offTransition <= 0f)
|
|
{
|
|
offTransition = 0f;
|
|
}
|
|
}
|
|
|
|
float musicVolume = 1f - VoiceVolume;
|
|
float voiceVolume = VoiceVolume;
|
|
|
|
for (int i = 0; i < samplesRead; i += 4)
|
|
{
|
|
// Mix channel 0 and 2 to left, 1 and 3 to right
|
|
float left = (sourceBuffer[i] * musicVolume) + (sourceBuffer[i + 2] * voiceVolume);
|
|
float right = (sourceBuffer[i + 1] * musicVolume) + (sourceBuffer[i + 3] * voiceVolume);
|
|
buffer[outIndex++] = left * offTransition;
|
|
buffer[outIndex++] = right * offTransition;
|
|
}
|
|
|
|
return stereoSamples;
|
|
}
|
|
}
|
|
|
|
}
|