SyncSoundMixer: improved and moved out of ZXSpectrum into Cores.Sound (as the CPC will use this and future cores may find it useful)
This commit is contained in:
parent
244b9d2231
commit
b2584145d7
|
@ -370,7 +370,6 @@
|
|||
<Compile Include="Computers\SinclairSpectrum\Media\Tape\WAV\WavConverter.cs" />
|
||||
<Compile Include="Computers\SinclairSpectrum\Media\Tape\WAV\WavHeader.cs" />
|
||||
<Compile Include="Computers\SinclairSpectrum\Media\Tape\WAV\WavStreamReader.cs" />
|
||||
<Compile Include="Computers\SinclairSpectrum\SoundProviderMixer.cs" />
|
||||
<Compile Include="Computers\SinclairSpectrum\Machine\MachineType.cs" />
|
||||
<Compile Include="Computers\SinclairSpectrum\Machine\SpectrumBase.cs" />
|
||||
<Compile Include="Computers\SinclairSpectrum\Machine\SpectrumBase.Input.cs">
|
||||
|
@ -1584,6 +1583,7 @@
|
|||
<Compile Include="Sound\DualSyncSound.cs" />
|
||||
<Compile Include="Sound\OneBitBeeper.cs" />
|
||||
<Compile Include="Sound\SN76489sms.cs" />
|
||||
<Compile Include="Sound\SyncSoundMixer.cs" />
|
||||
<Compile Include="Waterbox\CustomSaverammer.cs" />
|
||||
<Compile Include="Waterbox\ElfRunner.cs" />
|
||||
<Compile Include="FileID.cs" />
|
||||
|
|
|
@ -1,213 +0,0 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||
{
|
||||
/// <summary>
|
||||
/// My attempt at mixing multiple ISoundProvider sources together and outputting another ISoundProvider
|
||||
/// Currently only supports SyncSoundMode.Sync
|
||||
/// Attached ISoundProvider sources must already be stereo 44.1khz and ideally sound buffers should be the same length (882)
|
||||
/// (if not, only 882 samples of their buffer will be used)
|
||||
/// </summary>
|
||||
internal sealed class SoundProviderMixer : ISoundProvider
|
||||
{
|
||||
private class Provider
|
||||
{
|
||||
public ISoundProvider SoundProvider { get; set; }
|
||||
public string ProviderDescription { get; set; }
|
||||
public int MaxVolume { get; set; }
|
||||
public short[] Buffer { get; set; }
|
||||
public int NSamp { get; set; }
|
||||
}
|
||||
|
||||
private bool _stereo = true;
|
||||
public bool Stereo
|
||||
{
|
||||
get { return _stereo; }
|
||||
set { _stereo = value; }
|
||||
}
|
||||
|
||||
private readonly List<Provider> SoundProviders;
|
||||
|
||||
public SoundProviderMixer(params ISoundProvider[] soundProviders)
|
||||
{
|
||||
SoundProviders = new List<Provider>();
|
||||
|
||||
foreach (var s in soundProviders)
|
||||
{
|
||||
SoundProviders.Add(new Provider
|
||||
{
|
||||
SoundProvider = s,
|
||||
MaxVolume = short.MaxValue,
|
||||
});
|
||||
}
|
||||
|
||||
EqualizeVolumes();
|
||||
}
|
||||
|
||||
public SoundProviderMixer(short maxVolume, string description, params ISoundProvider[] soundProviders)
|
||||
{
|
||||
SoundProviders = new List<Provider>();
|
||||
|
||||
foreach (var s in soundProviders)
|
||||
{
|
||||
SoundProviders.Add(new Provider
|
||||
{
|
||||
SoundProvider = s,
|
||||
MaxVolume = maxVolume,
|
||||
ProviderDescription = description
|
||||
});
|
||||
}
|
||||
|
||||
EqualizeVolumes();
|
||||
}
|
||||
|
||||
public void AddSource(ISoundProvider source, string description)
|
||||
{
|
||||
SoundProviders.Add(new Provider
|
||||
{
|
||||
SoundProvider = source,
|
||||
MaxVolume = short.MaxValue,
|
||||
ProviderDescription = description
|
||||
});
|
||||
|
||||
EqualizeVolumes();
|
||||
}
|
||||
|
||||
public void AddSource(ISoundProvider source, short maxVolume, string description)
|
||||
{
|
||||
SoundProviders.Add(new Provider
|
||||
{
|
||||
SoundProvider = source,
|
||||
MaxVolume = maxVolume,
|
||||
ProviderDescription = description
|
||||
});
|
||||
|
||||
EqualizeVolumes();
|
||||
}
|
||||
|
||||
public void DisableSource(ISoundProvider source)
|
||||
{
|
||||
var sp = SoundProviders.Where(a => a.SoundProvider == source);
|
||||
if (sp.Count() == 1)
|
||||
SoundProviders.Remove(sp.First());
|
||||
else if (sp.Count() > 1)
|
||||
foreach (var s in sp)
|
||||
SoundProviders.Remove(s);
|
||||
|
||||
EqualizeVolumes();
|
||||
}
|
||||
|
||||
public void EqualizeVolumes()
|
||||
{
|
||||
if (SoundProviders.Count < 1)
|
||||
return;
|
||||
|
||||
int eachVolume = short.MaxValue / SoundProviders.Count;
|
||||
foreach (var source in SoundProviders)
|
||||
{
|
||||
source.MaxVolume = eachVolume;
|
||||
}
|
||||
}
|
||||
|
||||
#region ISoundProvider
|
||||
|
||||
public bool CanProvideAsync => false;
|
||||
public SyncSoundMode SyncMode => SyncSoundMode.Sync;
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode != SyncSoundMode.Sync)
|
||||
throw new InvalidOperationException("Only Sync mode is supported.");
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new NotSupportedException("Async is not available");
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
foreach (var soundSource in SoundProviders)
|
||||
{
|
||||
soundSource.SoundProvider.DiscardSamples();
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = null;
|
||||
nsamp = 0;
|
||||
|
||||
// get samples from all the providers
|
||||
foreach (var sp in SoundProviders)
|
||||
{
|
||||
int sampCount;
|
||||
short[] samp;
|
||||
sp.SoundProvider.GetSamplesSync(out samp, out sampCount);
|
||||
sp.NSamp = sampCount;
|
||||
sp.Buffer = samp;
|
||||
}
|
||||
|
||||
// are all the sample lengths the same?
|
||||
var firstEntry = SoundProviders.First();
|
||||
bool sameCount = SoundProviders.All(s => s.NSamp == firstEntry.NSamp);
|
||||
|
||||
if (!sameCount)
|
||||
{
|
||||
// this is a bit hacky, really all ISoundProviders should be supplying 44100 with 882 samples per frame.
|
||||
// we will make sure this happens (no matter how it sounds)
|
||||
if (SoundProviders.Count > 1)
|
||||
{
|
||||
for (int i = 0; i < SoundProviders.Count; i++)
|
||||
{
|
||||
int ns = SoundProviders[i].NSamp;
|
||||
short[] buff = new short[882 * 2];
|
||||
|
||||
for (int b = 0; b < 882 * 2; b++)
|
||||
{
|
||||
if (b == SoundProviders[i].Buffer.Length - 1)
|
||||
{
|
||||
// end of source buffer
|
||||
break;
|
||||
}
|
||||
|
||||
buff[b] = SoundProviders[i].Buffer[b];
|
||||
}
|
||||
|
||||
// save back to the soundprovider
|
||||
SoundProviders[i].NSamp = 882;
|
||||
SoundProviders[i].Buffer = buff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// just process what we have as-is
|
||||
}
|
||||
}
|
||||
|
||||
// mix the soundproviders together
|
||||
nsamp = 882;
|
||||
samples = new short[nsamp * 2];
|
||||
|
||||
for (int i = 0; i < samples.Length; i++)
|
||||
{
|
||||
short sectorVal = 0;
|
||||
foreach (var sp in SoundProviders)
|
||||
{
|
||||
if (sp.Buffer[i] > sp.MaxVolume)
|
||||
sectorVal += (short)sp.MaxVolume;
|
||||
else
|
||||
sectorVal += sp.Buffer[i];
|
||||
}
|
||||
|
||||
samples[i] = sectorVal;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BizHawk.Emulation.Cores.Components;
|
||||
using BizHawk.Emulation.Cores.Sound;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||
|
@ -47,11 +48,11 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
PutSettings((ZXSpectrumSettings)settings ?? new ZXSpectrumSettings());
|
||||
|
||||
List<JoystickType> joysticks = new List<JoystickType>();
|
||||
joysticks.Add(((ZXSpectrumSyncSettings)syncSettings as ZXSpectrumSyncSettings).JoystickType1);
|
||||
joysticks.Add(((ZXSpectrumSyncSettings)syncSettings as ZXSpectrumSyncSettings).JoystickType2);
|
||||
joysticks.Add(((ZXSpectrumSyncSettings)syncSettings as ZXSpectrumSyncSettings).JoystickType3);
|
||||
joysticks.Add(((ZXSpectrumSyncSettings)syncSettings).JoystickType1);
|
||||
joysticks.Add(((ZXSpectrumSyncSettings)syncSettings).JoystickType2);
|
||||
joysticks.Add(((ZXSpectrumSyncSettings)syncSettings).JoystickType3);
|
||||
|
||||
deterministicEmulation = ((ZXSpectrumSyncSettings)syncSettings as ZXSpectrumSyncSettings).DeterministicEmulation;
|
||||
deterministicEmulation = ((ZXSpectrumSyncSettings)syncSettings).DeterministicEmulation;
|
||||
|
||||
if (deterministic != null && deterministic == true)
|
||||
{
|
||||
|
@ -117,26 +118,29 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
ser.Register<IVideoProvider>(_machine.ULADevice);
|
||||
|
||||
// initialize sound mixer and attach the various ISoundProvider devices
|
||||
SoundMixer = new SoundProviderMixer((int)(32767 / 10), "System Beeper", (ISoundProvider)_machine.BuzzerDevice);
|
||||
SoundMixer.AddSource((ISoundProvider)_machine.TapeBuzzer, "Tape Audio");
|
||||
if (_machine.AYDevice != null)
|
||||
SoundMixer.AddSource(_machine.AYDevice, "AY-3-3912");
|
||||
SoundMixer = new SyncSoundMixer(targetSampleCount: 882);
|
||||
SoundMixer.PinSource(_machine.BuzzerDevice, "System Beeper", (int)(32767 / 10));
|
||||
SoundMixer.PinSource(_machine.TapeBuzzer, "Tape Audio", (int)(32767 / 10));
|
||||
if (_machine.AYDevice != null)
|
||||
{
|
||||
SoundMixer.PinSource(_machine.AYDevice, "AY-3-3912");
|
||||
}
|
||||
|
||||
// set audio device settings
|
||||
if (_machine.AYDevice != null && _machine.AYDevice.GetType() == typeof(AY38912))
|
||||
{
|
||||
((AY38912)_machine.AYDevice as AY38912).PanningConfiguration = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).AYPanConfig;
|
||||
_machine.AYDevice.Volume = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).AYVolume;
|
||||
((AY38912)_machine.AYDevice).PanningConfiguration = ((ZXSpectrumSettings)settings).AYPanConfig;
|
||||
_machine.AYDevice.Volume = ((ZXSpectrumSettings)settings).AYVolume;
|
||||
}
|
||||
|
||||
if (_machine.BuzzerDevice != null)
|
||||
{
|
||||
((OneBitBeeper)_machine.BuzzerDevice as OneBitBeeper).Volume = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).EarVolume;
|
||||
_machine.BuzzerDevice.Volume = ((ZXSpectrumSettings)settings).EarVolume;
|
||||
}
|
||||
|
||||
if (_machine.TapeBuzzer != null)
|
||||
{
|
||||
((OneBitBeeper)_machine.TapeBuzzer as OneBitBeeper).Volume = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).TapeVolume;
|
||||
_machine.TapeBuzzer.Volume = ((ZXSpectrumSettings)settings).TapeVolume;
|
||||
}
|
||||
|
||||
DCFilter dc = new DCFilter(SoundMixer, 512);
|
||||
|
@ -160,7 +164,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
public List<GameInfo> _tapeInfo = new List<GameInfo>();
|
||||
public List<GameInfo> _diskInfo = new List<GameInfo>();
|
||||
|
||||
private SoundProviderMixer SoundMixer;
|
||||
private SyncSoundMixer SoundMixer;
|
||||
|
||||
private readonly List<byte[]> _files;
|
||||
|
||||
|
|
|
@ -0,0 +1,340 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// ISoundProvider mixer that generates a single ISoundProvider output from multiple ISoundProvider sources
|
||||
/// Currently only supports sync (not async)
|
||||
///
|
||||
/// Bizhawk expects ISoundProviders to output at 44100KHz, so this is what SyncSoundMixer does. Therefore, try to make
|
||||
/// sure that your child ISoundProviders also do this I guess.
|
||||
///
|
||||
/// This is currently used in the ZX Spectrum and CPC cores but others may find it useful in future
|
||||
/// </summary>
|
||||
public sealed class SyncSoundMixer : ISoundProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Currently attached ChildProviders
|
||||
/// </summary>
|
||||
private readonly List<ChildProvider> _soundProviders = new List<ChildProvider>();
|
||||
|
||||
/// <summary>
|
||||
/// The final output max volume
|
||||
/// </summary>
|
||||
public short FinalMaxVolume
|
||||
{
|
||||
get { return _finalMaxVolume; }
|
||||
set
|
||||
{
|
||||
_finalMaxVolume = value;
|
||||
EqualizeVolumes();
|
||||
}
|
||||
}
|
||||
private short _finalMaxVolume;
|
||||
|
||||
/// <summary>
|
||||
/// How the sound sources are balanced against each other
|
||||
/// </summary>
|
||||
public SoundMixBalance MixBalanceMethod
|
||||
{
|
||||
get { return _mixBalanceMethod; }
|
||||
set
|
||||
{
|
||||
_mixBalanceMethod = value;
|
||||
EqualizeVolumes();
|
||||
}
|
||||
}
|
||||
private SoundMixBalance _mixBalanceMethod;
|
||||
|
||||
/// <summary>
|
||||
/// If specified the output buffer of the SyncSoundMixer will always contain this many samples
|
||||
/// You should probably nearly always specify a value for this and get your ISoundProvider sources
|
||||
/// to get as close to this nsamp value as possible. Otherwise the number of samples will
|
||||
/// be based on the highest nsamp out of all the child providers for that specific frame
|
||||
/// Useful examples:
|
||||
/// 882 - 44100KHz - 50Hz
|
||||
/// 735 - 44100Khz - 60Hz
|
||||
/// </summary>
|
||||
private int? _targetSampleCount;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="mixBalanceMethod">Whether each providers MaxVolume is reduced to an equal share of the final max volume value</param>
|
||||
/// <param name="maxVolume">The final 'master' max volume</param>
|
||||
/// <param name="targetSampleCount">
|
||||
/// If specified the output buffer of the SyncSoundMixer will always contain this many samples
|
||||
/// If left null the output buffer will contain the highest number of samples out of each of the providers every frame
|
||||
/// </param>
|
||||
public SyncSoundMixer(SoundMixBalance mixBalanceMethod = SoundMixBalance.Equalize, short maxVolume = short.MaxValue, int? targetSampleCount = null)
|
||||
{
|
||||
_mixBalanceMethod = mixBalanceMethod;
|
||||
_finalMaxVolume = maxVolume;
|
||||
_targetSampleCount = targetSampleCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an ISoundProvider to the SyncSoundMixer
|
||||
/// </summary>
|
||||
/// <param name="source">The source ISoundProvider</param>
|
||||
/// <param name="sourceDescription">An ident string for the ISoundProvider (useful when debugging)</param>
|
||||
/// <param name="isMono">If this is true then only half the samples should be present</param>
|
||||
public void PinSource(ISoundProvider source, string sourceDescription)
|
||||
{
|
||||
PinSource(source, sourceDescription, FinalMaxVolume);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an ISoundProvider to the SyncSoundMixer
|
||||
/// </summary>
|
||||
/// <param name="source">The source ISoundProvider</param>
|
||||
/// <param name="sourceDescription">An ident string for the ISoundProvider (useful when debugging)</param>
|
||||
/// <param name="sourceMaxVolume">The MaxVolume level for this particular ISoundProvider</param>
|
||||
/// <param name="isMono">If this is true then only half the samples should be present</param>
|
||||
public void PinSource(ISoundProvider source, string sourceDescription, short sourceMaxVolume)
|
||||
{
|
||||
_soundProviders.Add(new ChildProvider
|
||||
{
|
||||
SoundProvider = source,
|
||||
ProviderDescription = sourceDescription,
|
||||
MaxVolume = sourceMaxVolume
|
||||
});
|
||||
|
||||
EqualizeVolumes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an existing ISoundProvider from the SyncSoundMixer
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
public void UnPinSource(ISoundProvider source)
|
||||
{
|
||||
var sp = _soundProviders.Where(a => a.SoundProvider == source);
|
||||
|
||||
if (sp.Count() == 1)
|
||||
{
|
||||
_soundProviders.Remove(sp.First());
|
||||
}
|
||||
else if (sp.Count() > 1)
|
||||
{
|
||||
foreach (var s in sp)
|
||||
{
|
||||
_soundProviders.Remove(s);
|
||||
}
|
||||
}
|
||||
|
||||
EqualizeVolumes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets each pinned sound provider's MaxVolume based on the MixBalanceMethod
|
||||
/// </summary>
|
||||
public void EqualizeVolumes()
|
||||
{
|
||||
if (_soundProviders.Count < 1)
|
||||
return;
|
||||
|
||||
switch (MixBalanceMethod)
|
||||
{
|
||||
case SoundMixBalance.Equalize:
|
||||
var eachVolume = FinalMaxVolume / _soundProviders.Count;
|
||||
foreach (var source in _soundProviders)
|
||||
{
|
||||
source.MaxVolume = eachVolume;
|
||||
}
|
||||
break;
|
||||
case SoundMixBalance.MasterHardLimit:
|
||||
foreach (var source in _soundProviders)
|
||||
{
|
||||
if (source.MaxVolume > FinalMaxVolume)
|
||||
{
|
||||
source.MaxVolume = FinalMaxVolume;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the value of the highest nsamp in the SoundProviders collection
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private int GetHigestSampleCount()
|
||||
{
|
||||
var lookup = _soundProviders.OrderByDescending(x => x.InputNSamp)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (lookup == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return lookup.InputNSamp;
|
||||
}
|
||||
|
||||
#region ISoundProvider
|
||||
|
||||
public bool CanProvideAsync => false;
|
||||
public SyncSoundMode SyncMode => SyncSoundMode.Sync;
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode != SyncSoundMode.Sync)
|
||||
throw new InvalidOperationException("Only Sync mode is supported.");
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new NotSupportedException("Async is not available");
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
foreach (var soundSource in _soundProviders)
|
||||
{
|
||||
soundSource.SoundProvider.DiscardSamples();
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
// fetch samples from all the providers
|
||||
foreach (var sp in _soundProviders)
|
||||
{
|
||||
sp.GetSamples();
|
||||
}
|
||||
|
||||
nsamp = _targetSampleCount ?? GetHigestSampleCount();
|
||||
samples = new short[nsamp * 2];
|
||||
|
||||
// process the output buffers
|
||||
foreach (var sp in _soundProviders)
|
||||
{
|
||||
sp.PrepareOutput(nsamp);
|
||||
}
|
||||
|
||||
// mix the child providers together
|
||||
for (int i = 0; i < samples.Length; i++)
|
||||
{
|
||||
int sampleVal = 0;
|
||||
foreach (var sp in _soundProviders)
|
||||
{
|
||||
if (sp.OutputBuffer[i] > sp.MaxVolume)
|
||||
{
|
||||
sampleVal += (short)sp.MaxVolume;
|
||||
}
|
||||
else
|
||||
{
|
||||
sampleVal += sp.OutputBuffer[i];
|
||||
}
|
||||
}
|
||||
|
||||
// final hard limit
|
||||
if (sampleVal > (int)FinalMaxVolume)
|
||||
{
|
||||
sampleVal = (int)FinalMaxVolume;
|
||||
}
|
||||
|
||||
samples[i] = (short)sampleVal;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Instantiated for every ISoundProvider source that is added to the mixer
|
||||
/// </summary>
|
||||
private class ChildProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The Child ISoundProvider
|
||||
/// </summary>
|
||||
public ISoundProvider SoundProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Identification string
|
||||
/// </summary>
|
||||
public string ProviderDescription;
|
||||
|
||||
/// <summary>
|
||||
/// The max volume for this provider
|
||||
/// </summary>
|
||||
public int MaxVolume;
|
||||
|
||||
/// <summary>
|
||||
/// Stores the incoming samples
|
||||
/// </summary>
|
||||
public short[] InputBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// The incoming number of samples
|
||||
/// </summary>
|
||||
public int InputNSamp;
|
||||
|
||||
/// <summary>
|
||||
/// Stores the processed samples ready for mixing
|
||||
/// </summary>
|
||||
public short[] OutputBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// The output number of samples
|
||||
/// </summary>
|
||||
public int OutputNSamp;
|
||||
|
||||
/// <summary>
|
||||
/// Fetches sample data from the child ISoundProvider
|
||||
/// </summary>
|
||||
public void GetSamples()
|
||||
{
|
||||
SoundProvider.GetSamplesSync(out InputBuffer, out InputNSamp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures the output buffer is ready for mixing based on the supplied nsamp value
|
||||
/// Overflow samples will be omitted and underflow samples will be empty air
|
||||
/// </summary>
|
||||
/// <param name="nsamp"></param>
|
||||
public void PrepareOutput(int nsamp)
|
||||
{
|
||||
OutputNSamp = nsamp;
|
||||
var outputBuffSize = OutputNSamp * 2;
|
||||
|
||||
if (OutputNSamp != InputNSamp || InputBuffer.Length != outputBuffSize)
|
||||
{
|
||||
OutputBuffer = new short[outputBuffSize];
|
||||
|
||||
var i = 0;
|
||||
while (i < InputBuffer.Length && i < outputBuffSize)
|
||||
{
|
||||
OutputBuffer[i] = InputBuffer[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// buffer needs no modification
|
||||
OutputBuffer = InputBuffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines how mixed sound sources should be balanced
|
||||
/// </summary>
|
||||
public enum SoundMixBalance
|
||||
{
|
||||
/// <summary>
|
||||
/// Each sound source's max volume will be set to MaxVolume / nSources
|
||||
/// </summary>
|
||||
Equalize,
|
||||
/// <summary>
|
||||
/// Each sound source's individual max volume will be respected but the final MaxVolume will be limited to MaxVolume
|
||||
/// </summary>
|
||||
MasterHardLimit
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue