Я слышу потрескивание в моем бесконтактном чатеC#

Место общения программистов C#
Ответить
Anonymous
 Я слышу потрескивание в моем бесконтактном чате

Сообщение Anonymous »

Я пытаюсь реализовать голосовой чат в Godot с помощью Steamworks.NET. Я последовал официальному руководству Steam по Godot и адаптировал его к своей собственной многопользовательской настройке. Передача голоса работает, но во время воспроизведения слышится потрескивание. Я пробовал изменять различные случайные значения, чтобы увидеть, изменилось ли что-нибудь, а также добавил множество средств обработки ошибок и проверок, но мне не удалось найти источник потрескивающих звуков.
Чтобы записать голос игрока, я использую голосовую систему Steamworks. А затем, чтобы воспроизвести его, я использую Godot AudioStreamGeneratorPlayback, связанный с AudioStreamPlayer3D. Длина буфера генератора аудиопотока установлена ​​на 0,5f, а скорость микширования установлена ​​на возвращаемое значение SteamUser.GetVoiceOptimalSampleRate().
Вот мой код, который я максимально упростил, но при этом сохранил управление ошибками для устранения возможных ошибок:
public partial class ProximityChat : Node3D
{
uint voiceSampleRate = 0;

private const int MaxCompressedBufferSize = 1024;
private const int MaxUncompressedBufferSize = 88200;

private byte[] reusableCompressedBuffer = new byte[MaxCompressedBufferSize];
private byte[] reusableUncompressedBuffer = new byte[MaxUncompressedBufferSize];

private double voiceProcessTimer = 0.0;
private const double VoiceProcessInterval = 1.0 / 20.0; // 20fps

public override void _Ready()
{
SteamUser.StartVoiceRecording();
ServerAbstract.Instance.OnVoiceDataReceived += HandleVoiceDataReceived;
voiceSampleRate = SteamUser.GetVoiceOptimalSampleRate();
}

public override void _Process(double delta)
{
voiceProcessTimer += delta;

if (voiceProcessTimer >= VoiceProcessInterval)
{
voiceProcessTimer = 0.0;
ProcessVoiceData();
}
}

private void ProcessVoiceData()
{
uint countCompressedData = 0;
EVoiceResult result = SteamUser.GetAvailableVoice(out countCompressedData);

if (countCompressedData >= MaxCompressedBufferSize)
{
GD.PrintErr("Voice data size exceeds buffer size.");
return;
}

if (result == EVoiceResult.k_EVoiceResultOK && countCompressedData > 0)
{
uint nBytesWritten = 0;
SteamUser.GetVoice(true, reusableCompressedBuffer, (uint)MaxCompressedBufferSize, out nBytesWritten);
MemoryStream memoryStream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(memoryStream);
writer.Write((byte)ServerAbstract.Instance.UserIndex);
writer.Write(nBytesWritten);
writer.Write(reusableCompressedBuffer, 0, (int)nBytesWritten);
ServerAbstract.Instance.SendToAll(memoryStream.ToArray(), (int)memoryStream.Length, ServerAbstractClass.DeliveryMethod.Unreliable);
}
}

private void HandleVoiceDataReceived(BinaryReader reader, byte[] dataBuffer)
{
byte userIndex = reader.ReadByte();
uint dataSize = reader.ReadUInt32();
byte[] compressedData = reader.ReadBytes((int)dataSize);

uint nBytesWritten = 0;

EVoiceResult result = SteamUser.DecompressVoice(compressedData, dataSize, reusableUncompressedBuffer, (uint)MaxUncompressedBufferSize, out nBytesWritten, voiceSampleRate);

if (result == EVoiceResult.k_EVoiceResultOK)
{
Character character = (Character)ReplicationServer.Instance.GetReplicatedObject(userIndex);

if (character?.voiceStreamPlayback == null)
{
GD.PrintErr("Character or voice stream playback is null.");
return;
}

int requiredFrames = (int)(nBytesWritten / 2);

if (!character.voiceStreamPlayback.CanPushBuffer(requiredFrames))
{
GD.PrintErr("Voice stream buffer full, dropping old data.");
return;
}

Vector2[] stereoData = new Vector2[requiredFrames];

for (int i = 0; i < requiredFrames; i++)
{
short sample = (short)(
reusableUncompressedBuffer[i * 2] |
(reusableUncompressedBuffer[i * 2 + 1]

Подробнее здесь: https://stackoverflow.com/questions/798 ... imity-chat
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»