Я пытаюсь объединить отдельные волновые потоки для клиентов, подключенных к серверу голосового чата, в один волновой поток для передачи. голосовой канал.
Я пробовал так много вещей, но мне не удалось добиться правильного звука и отсутствия ошибок.
Я пытался создать собственную память потокового микшера и попробовал использовать NAudio, который, по моему мнению, был бы лучшим решением, но безуспешно.
Я видел в Интернете пару видеороликов о том, как это сделать, но я полностью слеп с рождения и реальных примеров кода с видео не было.
У меня есть код, который теоретически должен работать, но, похоже, этого не происходит.
Любая помощь с этим была бы очень полезна. очень признателен.
Вот мой код:
Код: Выделить всё
private async Task HandleClientAudioStreamAsync(TcpClient client, SslStream sslStream, string username)
{
var buffer = new byte[65536 * 2];
try
{
int clientChannelId;
int currentClientChannelId;
if (!ClientChannelMap.TryGetValue(client, out clientChannelId))
{
return; // Client not yet joined to channel
}
var channelMixer = GetOrCreateMixer(clientChannelId);
while (true)
{
ClientChannelMap.TryGetValue(client, out currentClientChannelId);
if (currentClientChannelId != clientChannelId)
{
clientChannelId = currentClientChannelId;
channelMixer = GetOrCreateMixer(clientChannelId);
}
int bytesRead = await sslStream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0)
{
// Client disconnected
break;
}
// Convert byte array to ISampleProvider
var sampleProvider = ByteArrayToSampleProvider(buffer, bytesRead);
await _semaphore.WaitAsync();
try
{
channelMixer.AddMixerInput(sampleProvider);
// Send mixed audio data to clients in the same channel
foreach (var (otherClient, otherSslStream, otherUsername) in ChannelConnectionLists[clientChannelId].ToArray())
{
if (_voiceFeedback == 0 && otherClient != client)
{
try
{
var mixedStream = new MemoryStream();
var waveFileWriter = new WaveFileWriter(mixedStream, WaveFormat.CreateIeeeFloatWaveFormat(32000, 2));
var bufferData = new float[buffer.Length];
var samples = channelMixer.Read(bufferData, 0, buffer.Length);
waveFileWriter.WriteSamples(bufferData, 0, samples);
var mixedBytes = mixedStream.ToArray();
await otherSslStream.WriteAsync(mixedBytes, 0, mixedBytes.Length);
await otherSslStream.FlushAsync();
}
catch (ObjectDisposedException)
{
_eventLog.WriteEntry("Attempted to write to a disposed SslStream.", EventLogEntryType.Warning);
}
catch (Exception ex)
{
_eventLog.WriteEntry($"Error sending audio data: {ex.Message}", EventLogEntryType.Error);
}
}
}
}
finally
{
_semaphore.Release();
}
}
}
catch (Exception ex)
{
_eventLog.WriteEntry($"Error handling client audio stream: {ex.Message}", EventLogEntryType.Error);
}
finally
{
// Remove the client from all channels and clean up
RemoveClientFromCurrentChannel(client, sslStream, username);
lock (Lock)
{
ConnectedClients.RemoveAll(x => x.client == client);
}
sslStream.Close();
sslStream.Dispose();
client.Close();
_eventLog.WriteEntry("Client disconnected.", EventLogEntryType.Information);
}
}
private MixingSampleProvider GetOrCreateMixer(int channelId)
{
if (!ChannelMixers.TryGetValue(channelId, out var mixer))
{
mixer = new MixingSampleProvider(WaveFormat.CreateIeeeFloatWaveFormat(32000, 2)); // Set appropriate format
ChannelMixers[channelId] = mixer;
}
return mixer;
}
private ISampleProvider ByteArrayToSampleProvider(byte[] buffer, int bytesRead)
{
var waveStream = new RawSourceWaveStream(new MemoryStream(buffer, 0, bytesRead), WaveFormat.CreateIeeeFloatWaveFormat(32000, 2));
return waveStream.ToSampleProvider();
}
Еще раз спасибо, что уделили время.
Подробнее здесь: https://stackoverflow.com/questions/790 ... in-c-sharp
Мобильная версия