2025-03-19 11:40:50 +01:00

253 lines
7.2 KiB
C#

using UnityEngine;
using TMPro;
using System.IO.Ports;
public class ChordReader : MonoBehaviour
{
public int baudRate = 9600;
private SerialPort serialPort;
private bool serialConnected = false;
[Header("UI Elements")]
public TextMeshProUGUI chordText;
public TextMeshProUGUI sensorText;
[Header("Finger Dots")]
public Transform dot1, dot2, dot3;
public float xRange = 1.0f;
public float yRange = 1.0f;
public float yPos = 0.0f;
public float zOffsetDot1 = 0f;
public float zOffsetDot2 = 0.1f;
public float zOffsetDot3 = -0.1f;
[Header("Audio Clips")]
public AudioClip chordASound;
public AudioClip chordDSound;
public AudioClip chordESound;
private AudioSource audioSource;
public float yPosDot3 = 0.2f; // Top dot
public float yPosDot2 = 0.0f; // Middle dot
public float yPosDot1 = -0.2f; // Bottom dot
private float timer = 0f;
private int currentChord = 0;
private float mockInterval = 3f;
void Start()
{
audioSource = GetComponent<AudioSource>();
string[] ports = SerialPort.GetPortNames();
foreach (string port in ports)
{
try
{
serialPort = new SerialPort(port, baudRate);
serialPort.ReadTimeout = 50;
serialPort.Open();
serialConnected = true;
Debug.Log("Connected to: " + port);
return;
}
catch { Debug.LogWarning($"Failed to open port: {port}"); }
}
if (!serialConnected) Debug.LogWarning("No COM ports detected. Running MOCK mode.");
}
void Update()
{
if (serialConnected)
{
try
{
string line = serialPort.ReadLine().Trim();
ProcessRealData(line);
}
catch { }
}
// Keyboard input for playing chord sounds
if (Input.GetKeyDown(KeyCode.A)) // Press 'A' key for chord A
{
PlayChordSound("A");
MoveDotsForChord("A");
(string chord, string correctness) = DetectChord(850, 650, 350); // Mock values for A
Debug.Log($"Chord: {chord}, Correctness: {correctness}");
}
if (Input.GetKeyDown(KeyCode.D)) // Press 'D' key for chord D
{
PlayChordSound("D");
MoveDotsForChord("D");
(string chord, string correctness) = DetectChord(750, 150, 650); // Mock values for D
Debug.Log($"Chord: {chord}, Correctness: {correctness}");
}
if (Input.GetKeyDown(KeyCode.E)) // Press 'E' key for chord E
{
PlayChordSound("E");
MoveDotsForChord("E");
(string chord, string correctness) = DetectChord(150, 250, 850); // Mock values for E
Debug.Log($"Chord: {chord}, Correctness: {correctness}");
}
}
void ProcessData(string dataLine)
{
if (!dataLine.Contains("|")) return;
string[] parts = dataLine.Split('|');
if (parts.Length < 2) return;
string sensorPart = parts[0];
string chordName = parts[1];
if (chordText != null)
chordText.text = chordName;
PlayChordSound(chordName);
string[] tokens = sensorPart.Split(',');
if (tokens.Length == 3)
{
RunMockData();
}
}
void PlayChordSound(string chordName)
{
switch (chordName)
{
case "A":
audioSource.PlayOneShot(chordASound);
break;
case "D": // Add this case
audioSource.PlayOneShot(chordDSound);
break;
case "E": // Add this case
audioSource.PlayOneShot(chordESound);
break;
// Add more cases for other chords
default:
Debug.LogWarning("No sound assigned for chord: " + chordName);
break;
}
}
void ProcessRealData(string dataLine)
{
string[] tokens = dataLine.Split(',');
if (tokens.Length != 3) return;
int s1 = int.Parse(tokens[0]);
int s2 = int.Parse(tokens[1]);
int s3 = int.Parse(tokens[2]);
sensorText.text = $"S1={s1}, S2={s2}, S3={s3}";
(string chord, string correctness) = DetectChord(s1, s2, s3);
UpdateChordUI(chord);
Debug.Log(correctness);
PlayChordSound(chord);
UpdateDot(dot1, s1, yRange / 2f);
UpdateDot(dot2, s2, 0f);
UpdateDot(dot3, s3, -yRange / 2f);
}
void RunMockData()
{
timer += Time.deltaTime;
if (timer >= mockInterval)
{
timer = 0;
currentChord = (currentChord + 1) % 3;
}
int s1 = 0, s2 = 0, s3 = 0;
switch (currentChord)
{
case 0: s1 = 850; s2 = 650; s3 = 350; break; // A
case 1: s1 = 750; s2 = 150; s3 = 650; break; // D
case 2: s1 = 150; s2 = 250; s3 = 850; break; // E
}
sensorText.text = $"S1={s1}, S2={s2}, S3={s3}";
(string chord, string correctness) = DetectChord(s1, s2, s3);
UpdateChordUI(chord);
Debug.Log(correctness);
UpdateDot(dot1, s1, yRange / 2f);
UpdateDot(dot2, s2, 0f);
UpdateDot(dot3, s3, -yRange / 2f);
}
(string,string) DetectChord(int s1, int s2, int s3)
{
int MIN_DIFF = 100;
if (s1 > s2 && s2 > s3 && (s1 - s3 >= MIN_DIFF))
return ("A", "Correct!");
if (s1 > s3 && s3 > s2 && (s1 - s2 >= MIN_DIFF))
return ("D", "Correct!");
if (s3 > s2 && s2 > s1 && (s3 - s1 >= MIN_DIFF))
return ("E", "Correct!");
return ("None", "Wrong"); // If no chord matches
}
void UpdateChordUI(string chord)
{
chordText.text = chord;
switch (chord)
{
case "A": chordText.color = Color.green; break;
case "D": chordText.color = Color.cyan; break;
case "E": chordText.color = Color.yellow; break;
default: chordText.color = Color.white; break;
}
}
void UpdateDot(Transform dot, int sensorValue, float yPos)
{
float fraction = Mathf.Clamp01(sensorValue / 1023f);
float localX = Mathf.Lerp(-xRange / 2f, xRange / 2f, fraction);
dot.localPosition = new Vector3(localX, yPos, -0.1f);
dot.localEulerAngles = new Vector3(0f, 0f, 180f); // Flips the dot rotation
}
void OnApplicationQuit()
{
if (serialPort != null && serialPort.IsOpen)
serialPort.Close();
}
void MoveDotsForChord(string chordName)
{
int s1 = 0, s2 = 0, s3 = 0;
// Define mock sensor values for each chord
switch (chordName)
{
case "A":
s1 = 850; s2 = 650; s3 = 350; // Example values for chord A
break;
case "D":
s1 = 750; s2 = 150; s3 = 650; // Example values for chord D
break;
case "E":
s1 = 150; s2 = 250; s3 = 850; // Example values for chord E
break;
default:
return; // Do nothing for unrecognized chords
}
// Update the positions of the dots
UpdateDot(dot1, s1, yRange / 2f);
UpdateDot(dot2, s2, 0f);
UpdateDot(dot3, s3, -yRange / 2f);
}
}