final fixes for audio + installed parallelsync
This commit is contained in:
@ -9,6 +9,7 @@ using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
using System.IO;
|
||||
|
||||
namespace Convai.Scripts.Runtime.Multiplayer
|
||||
{
|
||||
@ -70,6 +71,16 @@ namespace Convai.Scripts.Runtime.Multiplayer
|
||||
|
||||
public event Action<bool> OnRecordingStateChanged;
|
||||
|
||||
[Header("Recording Storage")]
|
||||
[SerializeField] private bool saveLocalAudio = true;
|
||||
[SerializeField] private int localSampleRate = 16000;
|
||||
[SerializeField] private string localFilePrefix = "sender_audio";
|
||||
private readonly object _localAudioLock = new object();
|
||||
private readonly System.Collections.Generic.List<short> _localSamples = new System.Collections.Generic.List<short>(128 * 1024);
|
||||
private bool _localSaveInProgress = false;
|
||||
private DateTime _localSessionStart;
|
||||
private string _persistentDataPath;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Apply global config if enabled
|
||||
@ -84,6 +95,7 @@ namespace Convai.Scripts.Runtime.Multiplayer
|
||||
}
|
||||
InitializeNetwork();
|
||||
InitializeAudio();
|
||||
_persistentDataPath = Application.persistentDataPath;
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
_ackCancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
@ -423,6 +435,11 @@ namespace Convai.Scripts.Runtime.Multiplayer
|
||||
_lastMicrophonePosition = 0;
|
||||
_packetSequence = 0;
|
||||
_startAckReceived = false;
|
||||
_localSessionStart = DateTime.UtcNow;
|
||||
lock (_localAudioLock)
|
||||
{
|
||||
_localSamples.Clear();
|
||||
}
|
||||
|
||||
ConvaiLogger.Info("Started recording for UDP transmission (Simple)", ConvaiLogger.LogCategory.Character);
|
||||
OnRecordingStateChanged?.Invoke(true);
|
||||
@ -454,6 +471,11 @@ namespace Convai.Scripts.Runtime.Multiplayer
|
||||
|
||||
// Send end-of-recording signal
|
||||
SendEndOfRecordingSignal();
|
||||
|
||||
if (saveLocalAudio)
|
||||
{
|
||||
TrySaveLocalAudioAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -542,6 +564,12 @@ namespace Convai.Scripts.Runtime.Multiplayer
|
||||
// Create a simple packet structure
|
||||
byte[] packet = CreateSimpleAudioPacket(audioData, processedSamples, currentChunkSamples);
|
||||
|
||||
// Buffer locally for saving
|
||||
if (saveLocalAudio)
|
||||
{
|
||||
AppendLocalAudio(audioData, processedSamples, currentChunkSamples);
|
||||
}
|
||||
|
||||
// Send the packet
|
||||
await _udpClient.SendAsync(packet, packet.Length, _targetEndPoint);
|
||||
|
||||
@ -649,6 +677,100 @@ namespace Convai.Scripts.Runtime.Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendLocalAudio(float[] source, int startIndex, int count)
|
||||
{
|
||||
if (source == null || count <= 0)
|
||||
return;
|
||||
|
||||
lock (_localAudioLock)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
float sample = source[startIndex + i];
|
||||
short shortSample = (short)(Mathf.Clamp(sample, -1f, 1f) * short.MaxValue);
|
||||
_localSamples.Add(shortSample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TrySaveLocalAudioAsync()
|
||||
{
|
||||
if (_localSaveInProgress)
|
||||
return;
|
||||
|
||||
short[] dataToSave;
|
||||
DateTime sessionStart;
|
||||
lock (_localAudioLock)
|
||||
{
|
||||
if (_localSamples.Count == 0)
|
||||
{
|
||||
if (enableDebugLogging)
|
||||
ConvaiLogger.Info("No local audio to save.", ConvaiLogger.LogCategory.Character);
|
||||
return;
|
||||
}
|
||||
dataToSave = _localSamples.ToArray();
|
||||
_localSamples.Clear();
|
||||
sessionStart = _localSessionStart;
|
||||
}
|
||||
|
||||
_localSaveInProgress = true;
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// Small delay to allow any final chunks to enqueue
|
||||
await Task.Delay(100);
|
||||
string timestamp = sessionStart.ToLocalTime().ToString("yyyyMMdd_HHmmss");
|
||||
string fileName = $"{localFilePrefix}_{timestamp}.wav";
|
||||
string dir = _persistentDataPath;
|
||||
string path = Path.Combine(dir, fileName);
|
||||
WriteWav(path, dataToSave, localSampleRate, 1);
|
||||
ConvaiLogger.Info($"Saved local audio to: {path}", ConvaiLogger.LogCategory.Character);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ConvaiLogger.Error($"Failed to save local audio: {ex.Message}", ConvaiLogger.LogCategory.Character);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_localSaveInProgress = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void WriteWav(string path, short[] samples, int sampleRate, int channels)
|
||||
{
|
||||
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
using (var writer = new BinaryWriter(fs))
|
||||
{
|
||||
int bitsPerSample = 16;
|
||||
int byteRate = sampleRate * channels * (bitsPerSample / 8);
|
||||
int blockAlign = channels * (bitsPerSample / 8);
|
||||
int dataSize = samples.Length * (bitsPerSample / 8);
|
||||
int fileSize = 44 - 8 + dataSize;
|
||||
|
||||
writer.Write(System.Text.Encoding.ASCII.GetBytes("RIFF"));
|
||||
writer.Write(fileSize);
|
||||
writer.Write(System.Text.Encoding.ASCII.GetBytes("WAVE"));
|
||||
|
||||
writer.Write(System.Text.Encoding.ASCII.GetBytes("fmt "));
|
||||
writer.Write(16);
|
||||
writer.Write((short)1);
|
||||
writer.Write((short)channels);
|
||||
writer.Write(sampleRate);
|
||||
writer.Write(byteRate);
|
||||
writer.Write((short)blockAlign);
|
||||
writer.Write((short)bitsPerSample);
|
||||
|
||||
writer.Write(System.Text.Encoding.ASCII.GetBytes("data"));
|
||||
writer.Write(dataSize);
|
||||
for (int i = 0; i < samples.Length; i++)
|
||||
{
|
||||
writer.Write(samples[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SendStartOfRecordingSignalAndAwaitAck()
|
||||
{
|
||||
try
|
||||
|
||||
Reference in New Issue
Block a user