Compare commits

..

2 Commits

Author SHA1 Message Date
Jonas Luz Jr. b6e5930ead Implements API touching and session initiation calls. 2025-11-22 11:19:11 -03:00
Jonas Luz Jr. ddb8e75ca7 Reorganizes and cleans up the project metadata files. 2025-11-22 11:18:02 -03:00
12 changed files with 338 additions and 37 deletions

View File

@ -150,6 +150,7 @@ MonoBehaviour:
m_Name: m_Name:
m_EditorClassIdentifier: Assembly-CSharp::PPGIA.X540.Project3.AudioCapture m_EditorClassIdentifier: Assembly-CSharp::PPGIA.X540.Project3.AudioCapture
_sampleRateInHz: 16000 _sampleRateInHz: 16000
_playingBack: 0
--- !u!4 &248765894 --- !u!4 &248765894
Transform: Transform:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -158,12 +159,12 @@ Transform:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 248765892} m_GameObject: {fileID: 248765892}
serializedVersion: 2 serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: [] m_Children: []
m_Father: {fileID: 0} m_Father: {fileID: 1044611067}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!82 &248765895 --- !u!82 &248765895
AudioSource: AudioSource:
@ -575,6 +576,95 @@ Transform:
m_Children: [] m_Children: []
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1044611066
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1044611067}
m_Layer: 0
m_Name: -- GAME MANAGER --
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1044611067
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1044611066}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1912693322}
- {fileID: 248765894}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1912693321
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1912693322}
- component: {fileID: 1912693323}
m_Layer: 0
m_Name: -- API Manager --
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1912693322
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1912693321}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1044611067}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1912693323
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1912693321}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 6df1f7169d6eca04abd7db0f712639ff, type: 3}
m_Name:
m_EditorClassIdentifier: PpgiaX540P3::PPGIA.X540.Project3.ApiClient
_apiBaseUrl: https://gyzypaneqa.execute-api.us-east-1.amazonaws.com/api/
_sessionInitEndpoint: /session/init
_sessionCloseEndpoint: /session/close
_llmAgentEndpoint: /agent/ask
_ttsEndpoint: /tts/synthesize
_sttEndpoint: /stt/upload
_clientId: unity-client
_timeoutInSeconds: 10
_query:
_session:
session_id: ddcc99fb-0474-4968-9b0c-ae13c56dfba6
created_at: 1763819290
--- !u!1660057539 &9223372036854775807 --- !u!1660057539 &9223372036854775807
SceneRoots: SceneRoots:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -582,4 +672,4 @@ SceneRoots:
- {fileID: 330585546} - {fileID: 330585546}
- {fileID: 410087041} - {fileID: 410087041}
- {fileID: 832575519} - {fileID: 832575519}
- {fileID: 248765894} - {fileID: 1044611067}

View File

@ -0,0 +1,158 @@
using System;
using System.Collections;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
namespace PPGIA.X540.Project3.API
{
public class ApiClient : MonoBehaviour
{
#region -- Inspector Fields -------------------------------------------
[Header("API URL Settings")]
[SerializeField]
private string _apiBaseUrl = "https://api.example.com";
[SerializeField]
private string _sessionInitEndpoint = "/session/init";
[SerializeField]
private string _sessionCloseEndpoint = "/session/close";
[SerializeField]
private string _llmAgentEndpoint = "/agent/ask";
[SerializeField]
private string _ttsEndpoint = "/tts/synthesize";
[SerializeField]
private string _sttEndpoint = "/stt/upload";
[Header("API Settings & Workload")]
[SerializeField]
private string _clientId = "unity-client";
[SerializeField]
private float _timeoutInSeconds = 10f;
[SerializeField, Multiline, TextArea(3, 10)]
private string _query;
[Header("API State Information")]
[SerializeField]
private Session _session;
#endregion ------------------------------------------------------------
#region -- Helper Methods ---------------------------------------------
// Helper Method to build endpoint URLs
string EndpointUrl(params string[] parts) =>
_apiBaseUrl.TrimEnd('/') + '/' +
string.Join("/", parts.Select(p => p.Trim('/')));
// Helper Method to encode payloads as JSON byte arrays
byte[] EncodePayload(object payload) =>
Encoding.UTF8.GetBytes(JsonUtility.ToJson(payload));
IEnumerator WaitForTimeout(
UnityWebRequestAsyncOperation operation,
Action callbackIfTimeout = null)
{
float startTime = Time.realtimeSinceStartup;
while (!operation.isDone)
{
if (Time.realtimeSinceStartup - startTime > _timeoutInSeconds)
{
callbackIfTimeout?.Invoke();
yield break;
}
yield return null;
}
}
IEnumerator CallEndpointWithGetCoroutine(
string url, Action<UnityWebRequest> callback)
{
using (var request = UnityWebRequest.Get(url))
{
var op = request.SendWebRequest();
yield return WaitForTimeout(op, () =>
{
Debug.LogError("Request timed out.");
});
callback?.Invoke(request);
}
}
IEnumerator CallEndpointWithPostCoroutine(
string url, object payload, Action<UnityWebRequest> callback)
{
using (var request = new UnityWebRequest(url, "POST"))
{
byte[] bodyRaw = EncodePayload(payload);
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
var op = request.SendWebRequest();
yield return WaitForTimeout(op, () =>
{
Debug.LogError("Request timed out.");
});
callback?.Invoke(request);
}
}
#endregion -- Helper Methods ------------------------------------------
#region -- API Calls --------------------------------------------------
[ContextMenu("Test API Availability")]
public void TestApiAvailability()
{
var url = EndpointUrl("");
Debug.Log($"Testing API availability at: {url}");
StartCoroutine(CallEndpointWithGetCoroutine(url, (request) =>
{
if (request.result == UnityWebRequest.Result.Success)
{
var body = request.downloadHandler?.text ?? string.Empty;
Debug.Log($"API call returned: {body}");
}
else
{
Debug.LogError(
$"API availability check failed: {request.error} (HTTP {request.responseCode})");
}
}));
}
[ContextMenu("Initiate Session")]
public string InitiateSession()
{
var url = EndpointUrl(_sessionInitEndpoint, _clientId);
Debug.Log($"Initiating session at: {url}");
StartCoroutine(CallEndpointWithPostCoroutine(url, null, (request) =>
{
if (request.result == UnityWebRequest.Result.Success)
{
var body = request.downloadHandler?.text ?? string.Empty;
var session = JsonUtility.FromJson<Session>(body);
_session = session;
}
else
{
Debug.LogError(
$"Session init failed: {request.error} (HTTP {request.responseCode})");
}
}));
return _session.SessionId;
}
#endregion -- API Calls ------------------------------------------------
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 6df1f7169d6eca04abd7db0f712639ff

View File

@ -6,51 +6,54 @@ namespace PPGIA.X540.Project3
[RequireComponent(typeof(AudioSource))] [RequireComponent(typeof(AudioSource))]
public class AudioCapture : MonoBehaviour public class AudioCapture : MonoBehaviour
{ {
public enum SampleRate { public enum SampleRate
{
Hz16000 = 16000, Hz16000 = 16000,
Hz44100 = 44100, Hz44100 = 44100,
Hz48000 = 48000, Hz48000 = 48000,
Hz96000 = 96000 Hz96000 = 96000
} }
[Header("Audio Capture Settings")] [Header("Audio Capture Settings")]
[SerializeField] [SerializeField]
private SampleRate _sampleRateInHz = SampleRate.Hz44100; private SampleRate _sampleRateInHz = SampleRate.Hz44100;
[SerializeField]
private bool _playingBack = false;
private AudioSource _audioSource; private AudioSource _audioSource;
private AudioClip _audioClip; private AudioClip _audioClip;
void Start() void Awake()
{ {
_audioSource = GetComponent<AudioSource>(); _audioSource = GetComponent<AudioSource>();
}
void OnDestroy()
{
Stop();
}
[ContextMenu("Record Audio")]
public void Record()
{
_audioClip = Microphone.Start(null, true, 1, (int)_sampleRateInHz); _audioClip = Microphone.Start(null, true, 1, (int)_sampleRateInHz);
_audioSource.clip = _audioClip; _audioSource.clip = _audioClip;
_audioSource.loop = true; _audioSource.loop = true;
// Wait until the microphone starts recording // Wait until the microphone starts recording
while (!(Microphone.GetPosition(null) > 0)) { } while (!(Microphone.GetPosition(null) > 0)) { }
_audioSource.Play(); if (_playingBack)
{
_audioSource.Play();
}
} }
// void Update() [ContextMenu("Stop Audio")]
// { public void Stop()
// var samples = new float[SAMPLE_RATE]; {
// _audioClip.GetData(samples, 0); Microphone.End(null);
}
// for (int i = 0; i < samples.Length; i++)
// {
// samples[i] *= _gain;
// samples[i] = Mathf.Clamp(samples[i], -1.0f, 1.0f);
// }
// var processedClip = AudioClip.Create(
// "ProcessedClip", samples.Length, _audioClip.channels,
// SAMPLE_RATE, false);
// processedClip.SetData(samples, 0);
// _audioSource.clip = processedClip;
// if (!_audioSource.isPlaying) _audioSource.Play();
// }
} }
} }

View File

@ -0,0 +1,14 @@
{
"name": "PpgiaX540P3",
"rootNamespace": "PPGIA.X540.Project3",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a6a47ac00b0ae694d9c530983e8e8c22
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a9e9a88d8a4978c4ba0e6bf106276b7a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
using System;
using UnityEngine;
namespace PPGIA.X540.Project3.API
{
[Serializable]
public class Session
{
public string session_id;
public string created_at;
// Optional convenience properties with C#-style names:
public string SessionId => session_id;
public DateTime CreatedAt => DateTime.Parse(created_at);
public static Session FromJson(string json) =>
JsonUtility.FromJson<Session>(json);
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 905309ff23223794faea2150bde7a080

View File

@ -1,4 +0,0 @@
<Solution>
<Project Path="Assembly-CSharp-Editor.csproj" />
<Project Path="Assembly-CSharp.csproj" />
</Solution>

View File

@ -144,8 +144,7 @@ PlayerSettings:
visionOSBundleVersion: 1.0 visionOSBundleVersion: 1.0
tvOSBundleVersion: 1.0 tvOSBundleVersion: 1.0
bundleVersion: 0.1.0 bundleVersion: 0.1.0
preloadedAssets: preloadedAssets: []
- {fileID: -944628639613478452, guid: 052faaac586de48259a63d0c4782560b, type: 3}
metroInputSource: 0 metroInputSource: 0
wsaTransparentSwapchain: 0 wsaTransparentSwapchain: 0
m_HolographicPauseOnTrackingLoss: 1 m_HolographicPauseOnTrackingLoss: 1

View File

@ -1,4 +1,5 @@
<Solution> <Solution>
<Project Path="Assembly-CSharp.csproj" /> <Project Path="PpgiaX540P3.csproj" />
<Project Path="Assembly-CSharp-Editor.csproj" /> <Project Path="Assembly-CSharp-Editor.csproj" />
<Project Path="Assembly-CSharp.csproj" />
</Solution> </Solution>