Skip to content

Commit

Permalink
Proper handling of multiple points for same attribute/command
Browse files Browse the repository at this point in the history
  • Loading branch information
eetteri committed Oct 28, 2020
1 parent 9e46d0f commit 792ee24
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 73 deletions.
3 changes: 2 additions & 1 deletion Runtime/AudioControlPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class AudioControlPoint
public HumanBodyBones m_bonePointFrom = HumanBodyBones.LeftHand;
public HumanBodyBones m_bonePointTo = HumanBodyBones.RightHand;
public GameObject m_distanceToGameObject;
public ControlDataManager cds; //reference to the object holding the control point
//public ControlDataManager cds; //reference to the object holding the control point
public Color m_drawColor = Color.red;
public Vector3 previousPosition = Vector3.zero;
public Vector3 frameVelocity = Vector3.zero;
Expand Down Expand Up @@ -50,6 +50,7 @@ public virtual bool valuesShouldBeVisible()
if (m_active && m_showValue) return true;
return false;
}


public bool m_active = true;

Expand Down
161 changes: 91 additions & 70 deletions Runtime/ControlDataManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public class ControlDataManager : MonoBehaviour
[HideInInspector]
public int oscPort;
[HideInInspector]
public OutputChoice m_outputChoice;
[HideInInspector]
public bool m_connectionFoldout = true;
[HideInInspector]
public bool m_controlPointsFoldout = true;
Expand All @@ -32,6 +34,9 @@ public class ControlDataManager : MonoBehaviour
private float _timeThreshold = 0.02f; //50fps
private float _fmodExectime;
private OscClient _client;

private Dictionary<string, List<AudioControlPoint>> _fmodPointsByAttribute = new Dictionary<string, List<AudioControlPoint>>();
private Dictionary<string, List<AudioControlPoint>> _oscPointsByCommand = new Dictionary<string, List<AudioControlPoint>>();


private void Awake()
Expand All @@ -53,10 +58,9 @@ private void Start()
}
}


void SendOSC(AudioControlPoint acp) //NEED TO REFACTOR THE PART BELOW TOGETHER WITH FMOD
void UpdateValue(AudioControlPoint acp)
{
Vector3 currentPos = animator.GetBoneTransform(acp.m_bonePoint).position;
Vector3 currentPos = animator.GetBoneTransform(acp.m_bonePoint).position;
float value = 0;
if (acp.m_argumentType == ArgumentType.Position)
{
Expand Down Expand Up @@ -106,70 +110,103 @@ void SendOSC(AudioControlPoint acp) //NEED TO REFACTOR THE PART BELOW TOGETHER
//acp.fmodParameterValue = Mathf.Abs(value);
acp.fmodParameterValue = value;
}

}
}

_client.Send(acp.m_oscCommand, acp.fmodParameterValue);


public void AddNewControlPoint()
{
AudioControlPoint acp = new AudioControlPoint();
controlPoints.Add(acp);
}

void UpdateFMOD(AudioControlPoint acp)
private void Update()
{
Vector3 currentPos = animator.GetBoneTransform(acp.m_bonePoint).position;
float value = 0;
if (acp.m_argumentType == ArgumentType.Position)
if (Time.time - _lastExecTime > _timeThreshold) //throttle the data output
{
switch (acp.m_axis)
{
case Axis.x:
value = animator.GetBoneTransform(acp.m_bonePoint).position.x;
acp.positionOnSelectedAxis = value; //store the result into instance for reuse in other parts of GUI drawing
//acp.fmodParameterValue = Mathf.Abs(value);
acp.fmodParameterValue = value;
break;
case Axis.y:
value = animator.GetBoneTransform(acp.m_bonePoint).position.y;
acp.positionOnSelectedAxis = value;
//acp.fmodParameterValue = Mathf.Abs(value);
acp.fmodParameterValue = value;
break;
case Axis.z:
value = animator.GetBoneTransform(acp.m_bonePoint).position.z;
acp.positionOnSelectedAxis = value;
//acp.fmodParameterValue = Mathf.Abs(value);
acp.fmodParameterValue = value;
break;
default:
break;
}
} else if (acp.m_argumentType == ArgumentType.Velocity)
{
Vector3 currFrameVelocity = (currentPos - acp.previousPosition) / Time.deltaTime;
acp.frameVelocity = Vector3.Lerp(acp.frameVelocity, currFrameVelocity, 0.1f);
acp.previousPosition = currentPos;
value = acp.velocityMagnitude();
//acp.fmodParameterValue = Mathf.Abs(value);
acp.fmodParameterValue = value;
} else if (acp.m_argumentType == ArgumentType.Distance)
IterateControlPoints();
SendData(_fmodPointsByAttribute);
SendData(_oscPointsByCommand);
_lastExecTime = Time.time;
}
}

private void SendData(Dictionary<string,List<AudioControlPoint>> pointDict)
{
foreach (KeyValuePair<string,List<AudioControlPoint>> entry in pointDict)
{
if (acp.m_distanceTo == DistanceTo.JointToJoint)
{
value = Vector3.Distance(animator.GetBoneTransform(acp.m_bonePointFrom).position, animator.GetBoneTransform(acp.m_bonePointTo).position);
acp.distanceBetweenPoints = value; //store the result into instance for reuse in other parts of GUI drawing
//acp.fmodParameterValue = Mathf.Abs(value);
acp.fmodParameterValue = value;
} else if (acp.m_distanceToGameObject != null && acp.m_distanceTo == DistanceTo.JointToObject)
var attributeOrCommand = entry.Key;
var size = entry.Value.Count;
float cumulativeValue = 0f;
float maxValue = 0f;
foreach (var point in entry.Value)
{
value = Vector3.Distance(animator.GetBoneTransform(acp.m_bonePointFrom).position, acp.m_distanceToGameObject.transform.position);
acp.distanceBetweenPoints = value; //store the result into instance for reuse in other parts of GUI drawing
//acp.fmodParameterValue = Mathf.Abs(value);
acp.fmodParameterValue = value;
UpdateValue(point);
cumulativeValue += point.fmodParameterValue;
maxValue = point.fmodParameterValue > maxValue ? point.fmodParameterValue : maxValue;
}

//determine the final value for output
float outValue = m_outputChoice == OutputChoice.MaxValue ? maxValue : cumulativeValue / size;

//FMOD or OSC
if (Application.isPlaying)
{
if (entry.Value[0].m_controlType == ControlDataType.FMODEvent)
{
FMOD.RESULT _result = _instance.setParameterByName(attributeOrCommand, outValue);
} else if (entry.Value[0].m_controlType == ControlDataType.OSC)
{
_client.Send(attributeOrCommand, outValue);
}
}
}
//set the data on fmod
FMOD.RESULT _result = _instance.setParameterByName(acp.m_fmodParameter, acp.fmodParameterValue );
//Debug.Assert(_result == RESULT.OK, "Couldn't set the volume");
pointDict.Clear();
}

private void IterateControlPoints()
{
foreach (AudioControlPoint acp in controlPoints)
{
//this is bit inefficient but doesn't matter now in this context
//create audio control point groupings based on point's current fmod attribute or OSC command
//use own list for each type, fmod or osc
if (acp.m_controlType == ControlDataType.FMODEvent)
{
//is this first occurrance of this fmod attribute as a key in dict
if (!_fmodPointsByAttribute.ContainsKey(acp.m_fmodParameter))
{
var list = new List<AudioControlPoint>();
list.Add(acp);
_fmodPointsByAttribute[acp.m_fmodParameter] = list;
}
else
{
var list = _fmodPointsByAttribute[acp.m_fmodParameter];
list.Add(acp);
_fmodPointsByAttribute[acp.m_fmodParameter] = list;
}
} else if (acp.m_controlType == ControlDataType.OSC)
{
//is this first occurrance of this OSC command as a key in dict
if (!_oscPointsByCommand.ContainsKey(acp.m_oscCommand))
{
var list = new List<AudioControlPoint>();
list.Add(acp);
_oscPointsByCommand[acp.m_oscCommand] = list;
}
else
{
var list = _oscPointsByCommand[acp.m_oscCommand];
list.Add(acp);
_oscPointsByCommand[acp.m_oscCommand] = list;
}
}
}
}

private Texture2D MakeTex(int width, int height, Color col)
{
Color[] pix = new Color[width * height];
Expand Down Expand Up @@ -219,23 +256,7 @@ private void OnDrawGizmos()
Handles.DrawBezier(p1, p2, p1, p2, acp.m_drawColor, null, 8f);
}
}

}
}

private void Update()
{
if (Time.time - _lastExecTime > _timeThreshold)
{
foreach (AudioControlPoint acp in controlPoints)
{
// let's throttle a bit the not so optimized loops
if (acp.m_controlType == ControlDataType.OSC && acp.m_active) SendOSC(acp);
if (acp.m_controlType == ControlDataType.FMODEvent && acp.m_active) UpdateFMOD(acp);
}
_lastExecTime = Time.time;
}
}

}
}
6 changes: 6 additions & 0 deletions Runtime/ControlDataUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ public enum ControlDataType
OSC
}

public enum OutputChoice
{
MaxValue,
Avaraged
}

public enum ArgumentType
{
Position,
Expand Down
7 changes: 5 additions & 2 deletions Runtime/Editor/ControlDataManagerEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,15 @@ private void DrawControlPointHeader()

void DrawConnectionSetups()
{
m_target.m_connectionFoldout = EditorGUILayout.Foldout(m_target.m_connectionFoldout, "Connection settings");
m_target.m_connectionFoldout = EditorGUILayout.Foldout(m_target.m_connectionFoldout, "Connection and output settings");
using (new EditorGUI.IndentLevelScope())
if (m_target.m_connectionFoldout)
{
EditorGUILayout.BeginVertical();
m_target.fmodEvent = (string)EditorGUILayout.TextField("FMOD event path:", m_target.fmodEvent);
m_target.oscAddress =(string)EditorGUILayout.TextField("OSC ip address:", m_target.oscAddress);
m_target.oscPort = (int)EditorGUILayout.IntField("OSC port:", m_target.oscPort);
m_target.m_outputChoice = (OutputChoice)EditorGUILayout.EnumPopup("Value if same targets: ", m_target.m_outputChoice);
EditorGUILayout.EndVertical();
}
}
Expand All @@ -62,7 +63,9 @@ void DrawAddControlPointButton()
//Create an Undo/Redo step for this modification
Undo.RecordObject(m_target, "Add new State");

m_target.controlPoints.Add(new AudioControlPoint());
//move this into main class?
//m_target.controlPoints.Add(new AudioControlPoint());
m_target.AddNewControlPoint();

//Whenever you modify a component variable directly without using serializedObject you need to tell
//Unity that this component has changed so the values are saved next time the user saves the project.
Expand Down

0 comments on commit 792ee24

Please sign in to comment.