add scripts for sample playback

This commit is contained in:
Chikashi Miyama 2019-10-01 15:08:35 +02:00
parent e8e4553b21
commit 0b0b9f0606
15 changed files with 160 additions and 123 deletions

View file

@ -6,15 +6,29 @@ namespace cylvester
[CustomEditor(typeof(PdBackend))]
public class PdBackendEditor : Editor
{
private IPdBackend pdBackend_;
private PdBackend pdBackend_;
private ILevelMeter[] levelMeters_;
private readonly string[] channels = {
private readonly string[] channels_ = {
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"
};
private readonly string[] samples_ =
{
"No Playback",
"Back_Back",
"Brutal_Synth",
"Dialog",
"Drums",
"Fox_Melo",
"Kick",
"Pads+Strings",
"Rose_Sax",
"Roses_Front"
};
private void Awake()
{
pdBackend_ = (IPdBackend) target;
pdBackend_ = (PdBackend) target;
levelMeters_ = new ILevelMeter[16];
for (var i = 0; i < 16; ++i)
levelMeters_[i] = new LevelMeter(i);
@ -22,27 +36,37 @@ namespace cylvester
public override void OnInspectorGUI ()
{
pdBackend_ = (IPdBackend) target;
pdBackend_ = (PdBackend) target;
GUILayout.Space(5);
GUILayout.BeginHorizontal();
GUILayout.Label("Main Patch");
pdBackend_.MainPatch = GUILayout.TextField(pdBackend_.MainPatch, 30);
pdBackend_.mainPatch = GUILayout.TextField(pdBackend_.mainPatch, 30);
GUILayout.EndHorizontal();
pdBackend_.NumInputChannels = EditorGUILayout.Popup("Number of input channels", pdBackend_.NumInputChannels, channels);
pdBackend_.inchannels = EditorGUILayout.Popup("Number of input channels", pdBackend_.inchannels, channels_);
if (Application.isPlaying)
{
GUILayout.Space(5);
GUILayout.BeginHorizontal();
foreach (var levelMeter in levelMeters_)
levelMeter.Render(pdBackend_.LevelMeterArray);
GUILayout.EndHorizontal();
RenderSamplePlayback();
RenderLevelMeters();
Repaint();
}
}
private void RenderSamplePlayback()
{
GUILayout.Space(5);
pdBackend_.samplePlayback = EditorGUILayout.Popup("Sample File to play", pdBackend_.samplePlayback, samples_);
}
private void RenderLevelMeters()
{
GUILayout.Space(5);
GUILayout.BeginHorizontal();
foreach (var levelMeter in levelMeters_)
levelMeter.Render(pdBackend_.levelMeterArray);
GUILayout.EndHorizontal();
}
}
}

View file

@ -0,0 +1,33 @@
using NUnit.Framework;
namespace cylvester
{
public class UnitTest_ChangeObserver
{
[Test]
public void Set_Get()
{
var called = false;
var observer = new ChangeObserver<float>(1.0f);
observer.ValueChanged += ()=> { called = true; };
observer.Value = 1.0001f;
Assert.IsTrue(called);
}
[Test]
public void ValueChanged()
{
var callCount = 0;
var observer = new ChangeObserver<float>(1.0f);
observer.ValueChanged += () => { callCount++; };
observer.Value = 1.0001f;
observer.Value = 1.0001f;
Assert.AreEqual(1, callCount);
}
}
}

View file

@ -1,35 +0,0 @@
using NUnit.Framework;
namespace cylvester
{
public class UnitTest_ParameterResponder
{
[Test]
public void Set_Get()
{
var responder = new Parameter<float>(1.0f);
responder.Value = 3.2f;
Assert.AreEqual(3.2f, responder.Value);
}
[Test]
public void ValueChanged()
{
var responder = new Parameter<float>(1.0f);
responder.Value = 0f;
void OnValueChanged()
{
Assert.AreEqual(3.2f, responder.Value);
}
responder.ValueChanged += OnValueChanged;
responder.Value = 3.2f;
responder.ValueChanged -= OnValueChanged;
}
}
}

View file

@ -3,52 +3,53 @@ using UnityEngine;
namespace cylvester
{
public interface IPdBackend
{
string MainPatch { get; set; }
int NumInputChannels { get; set;}
IPdArray LevelMeterArray { get; }
IFftArrayContainer FFTArrayContainer { get; }
}
public class PdBackend : MonoBehaviour, IPdBackend
public class PdBackend : MonoBehaviour
{
public string mainPatch = "analyzer.pd";
public int inchannels = 2;
private Action onToggled_;
private PdArray levelMeterArray_;
private FftArrayContainer fftArrayContainer_;
private const int NumMaxInputChannels = 16;
public IPdArray LevelMeterArray => levelMeterArray_;
public IFftArrayContainer FFTArrayContainer => fftArrayContainer_;
public string MainPatch { get => mainPatch; set => mainPatch = value; }
public int NumInputChannels { get => inchannels -1; set => inchannels = value + 1; }
public int samplePlayback = 0;
public PdArray levelMeterArray;
public FftArrayContainer fftArrayContainer;
private IChangeObserver<int> samplePlaybackObserver_;
private Action onSamplePlaybackChanged_;
private IPdSocket pdSocket_;
private void Start()
{
PdProcess.Instance.Start(mainPatch, inchannels);
levelMeterArray_ = new PdArray("levelmeters", NumMaxInputChannels);
fftArrayContainer_ = new FftArrayContainer();
levelMeterArray = new PdArray("levelmeters", PdConstant.NumMaxInputChannels);
fftArrayContainer = new FftArrayContainer();
pdSocket_ = new PdSocket(PdConstant.ip, PdConstant.port);
samplePlaybackObserver_ = new ChangeObserver<int>(samplePlayback);
onSamplePlaybackChanged_ = () =>
{
var bytes = new byte[]{(byte)PdMessage.SampleSound, (byte)samplePlayback};
pdSocket_.Send(bytes);
};
samplePlaybackObserver_.ValueChanged += onSamplePlaybackChanged_;
}
private void OnDestroy()
{
PdProcess.Instance.Stop();
levelMeterArray_?.Dispose();
levelMeterArray?.Dispose();
pdSocket_?.Dispose();
samplePlaybackObserver_.ValueChanged -= onSamplePlaybackChanged_;
}
public void Update()
{
if(PdProcess.Instance.Running)
levelMeterArray_.Update();
levelMeterArray.Update();
fftArrayContainer_.Update();
fftArrayContainer.Update();
samplePlaybackObserver_.Value = samplePlayback;
}
}
}

View file

@ -0,0 +1,17 @@
namespace cylvester
{
enum PdMessage
{
SampleSound = 0
}
public class PdConstant
{
public static readonly int NumMaxInputChannels = 16;
public static readonly string ip = "127.0.0.1";
public static readonly int port = 54345;
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 921619bf97b640dca91071f73784d3cb
timeCreated: 1569928306

View file

@ -0,0 +1,32 @@
using System;
using System.Net;
using System.Net.Sockets;
namespace cylvester
{
public interface IPdSocket : IDisposable
{
void Send(byte[] bytes);
}
public class PdSocket : IPdSocket
{
private Socket socket_;
public PdSocket(string ip, int port)
{
socket_ = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket_.Connect(IPAddress.Parse(ip), port);
}
public void Send(byte[] bytes)
{
socket_.Send(bytes);
}
public void Dispose()
{
socket_.Close();
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0b3bd2ba944d458c84bbeb5fa97b9382
timeCreated: 1569927529

View file

@ -17,7 +17,7 @@ namespace cylvester
public IPdArray GetPdArray(int index)
{
return pdBackend.FFTArrayContainer[index];
return pdBackend.fftArrayContainer[index];
}
public int Channel { get; set; }

View file

@ -1,34 +0,0 @@
using System;
namespace cylvester
{
interface IUdpSender : IDisposable
{
void SendBytes(byte[] data);
}
public class UdpSender : IDisposable
{
private readonly string remoteHost_;
private readonly int remotePort_;
private System.Net.Sockets.UdpClient udpClient_;
public UdpSender(string remoteHost, int remotePort)
{
remoteHost_ = remoteHost;
remotePort_ = remotePort;
udpClient_ = new System.Net.Sockets.UdpClient();
}
public void SendBytes(byte[] data)
{
udpClient_.Send(data, data.Length, remoteHost_, remotePort_);
}
public void Dispose()
{
udpClient_.Close();
udpClient_ = null;
}
}
}

View file

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 1f65f75415684cef9649e0eaa0fcbfc7
timeCreated: 1569772195

View file

@ -2,25 +2,22 @@ using System;
namespace cylvester
{
interface IParameter<T> where T : IComparable<T>
interface IChangeObserver<T> where T : IComparable<T>
{
T Value { set; get; }
T Value { set; }
event Action ValueChanged;
}
public class Parameter<T> : IParameter<T> where T : IComparable<T>
public class ChangeObserver<T> : IChangeObserver<T> where T : IComparable<T>
{
public Parameter(T initial)
private T value_;
public ChangeObserver(T initial)
{
Value = initial;
}
private T value_;
public T Value
{
get => value_;
set
{
if (value.CompareTo(value_) == 0)
@ -32,6 +29,5 @@ namespace cylvester
}
public event Action ValueChanged = () => { };
}
}