Emux/Emux.NAudio/GameBoyNAudioMixer.cs

133 lines
3.7 KiB
C#
Raw Normal View History

2017-08-20 19:47:05 +00:00
using System;
using System.Collections;
2017-08-03 14:34:40 +00:00
using System.Collections.Generic;
2017-08-20 19:47:05 +00:00
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
2017-08-03 14:34:40 +00:00
using Emux.GameBoy.Audio;
using NAudio.Wave;
namespace Emux.NAudio
2017-08-03 14:34:40 +00:00
{
public class GameBoyNAudioMixer : IWaveProvider, INotifyPropertyChanged
2017-08-03 14:34:40 +00:00
{
2017-08-20 19:47:05 +00:00
public event PropertyChangedEventHandler PropertyChanged;
2017-08-03 14:34:40 +00:00
private readonly MixingWaveProvider32 _mixer = new MixingWaveProvider32();
2017-08-20 19:47:05 +00:00
private bool _enabled = true;
private WaveFileWriter _writer;
private bool _isRecording;
2017-08-03 14:34:40 +00:00
public GameBoyNAudioMixer()
2017-08-03 14:34:40 +00:00
{
Channels = new List<NAudioChannelOutput>
{
2017-08-20 19:47:05 +00:00
new NAudioChannelOutput(this, "Square + Sweep"),
new NAudioChannelOutput(this, "Square"),
new NAudioChannelOutput(this, "Wave"),
new NAudioChannelOutput(this, "Noise"),
2017-08-03 14:34:40 +00:00
}.AsReadOnly();
foreach (var channel in Channels)
_mixer.AddInputStream(channel);
}
public WaveFormat WaveFormat
{
get { return _mixer.WaveFormat; }
}
public IList<NAudioChannelOutput> Channels
{
get;
}
2017-08-20 19:47:05 +00:00
public bool IsRecording
{
get { return _isRecording; }
private set
{
if (_isRecording != value)
{
_isRecording = value;
OnPropertyChanged(nameof(IsRecording));
}
}
}
public bool Enabled
{
get { return _enabled; }
set
{
if (_enabled != value)
{
_enabled = value;
OnPropertyChanged(nameof(Enabled));
}
}
}
2017-08-03 14:34:40 +00:00
public int Read(byte[] buffer, int offset, int count)
{
_mixer.Read(buffer, offset, count);
2017-08-20 19:47:05 +00:00
if (!Enabled)
Array.Clear(buffer, offset, count);
lock (this)
{
_writer?.Write(buffer, offset, count);
}
2017-08-03 14:34:40 +00:00
return count;
}
public void Connect(GameBoySpu spu)
{
for (var i = 0; i < spu.Channels.Count; i++)
2017-09-18 21:57:09 +00:00
{
var channel = spu.Channels[i];
channel.ChannelOutput = Channels[i];
channel.ChannelVolume = 0.05f;
}
2017-08-20 19:47:05 +00:00
}
public void StartRecording(Stream outputStream)
{
if (outputStream == null)
throw new ArgumentNullException(nameof(outputStream));
lock (this)
2017-08-03 14:34:40 +00:00
{
2017-08-20 19:47:05 +00:00
if (IsRecording)
throw new InvalidOperationException("Cannot start a recording when a recording is already happening.");
_writer = new WaveFileWriter(outputStream, WaveFormat);
IsRecording = true;
2017-08-03 14:34:40 +00:00
}
}
2017-08-20 19:47:05 +00:00
public void StopRecording()
{
lock (this)
{
2017-09-16 15:26:09 +00:00
if (!IsRecording)
2017-08-20 19:47:05 +00:00
throw new InvalidOperationException("Cannot stop a recording when a recording is not happening.");
try
{
_writer.Flush();
}
finally
{
_writer.Dispose();
_writer = null;
IsRecording = false;
}
}
}
protected virtual void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
2017-08-03 14:34:40 +00:00
}
}