首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用S16LE ( .NET /Mac/Linux)将PCM音频转换为Mac/8000

如何使用S16LE ( .NET /Mac/Linux)将PCM音频转换为Mac/8000
EN

Stack Overflow用户
提问于 2022-01-05 20:21:59
回答 1查看 271关注 0票数 3

我正在尝试接收和传输一个Twilio语音通话和一个不和谐的语音频道之间的音频。我很难找到如何将从DSharpPlus (.NET的不和谐库)接收到的音频数据转换成Twilio所要求的格式。

如果我正在阅读正确的DSharpPlus文档,来自DSharpPlus的PCM数据是以PCM S16LE格式表示的。Twilio预计数据将采用MU/8000格式(不包括标题,我相信)。

我正试图使用NAudio来转换数据,但我通过电话听到的只是尖锐的痛苦噪音。我不能使用完整的NAudio库,因为这个项目应该在上工作,而且一些NAudio API仅适用于NAudio。

下面是我目前拥有的相关代码:

代码语言:javascript
复制
private async Task VoiceReceiveHandler(VoiceNextConnection connection, VoiceReceiveEventArgs args)
{
    
    if (twilioSocketConnectionManager.TryGetSocketById(socketId, out var twilioSocket) && twilioSocket.Socket.State == WebSocketState.Open)
    {
        var media = ConvertPcmToMulawBase64Encoded(args.AudioFormat, args.PcmData.ToArray());
        var json = JsonSerializer.Serialize<MediaMessage>
        (
            new MediaMessage("media", twilioSocket.StreamSid, new MediaPayload(media)), 
            jsonSerializerOptions
        );
        logger.LogInformation(json);
        var bytes = Encoding.Default.GetBytes(json);
        var arraySegment = new ArraySegment<byte>(bytes, 0, bytes.Length);
        await twilioSocket.Socket.SendAsync(arraySegment, WebSocketMessageType.Text, WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
    }
}

private static string ConvertPcmToMulawBase64Encoded(AudioFormat audioFormat, byte[] pcmData)
{
        
    var sourceFormat = new WaveFormat(audioFormat.SampleRate, 16, audioFormat.ChannelCount);
    return Convert.ToBase64String(EncodeMuLaw(pcmData, 0, pcmData.Length));
}

public static byte[] EncodeMuLaw(byte[] data, int offset, int length)
{
    var encoded = new byte[length / 2];
    int outIndex = 0;
    for(int n = 0; n < length; n+=2)
    {
        encoded[outIndex++] = MuLawEncoder.LinearToMuLawSample(BitConverter.ToInt16(data, offset + n));
    }
    return encoded;
}

我还需要从MU-LAW转换到PCM S16LE,但首先要做的是.

当涉及到音频处理的时候,我完全被遗忘了,所以请对我轻松一点。

下面是源代码的其余部分:https://github.com/Swimburger/DiscordTwilioVoiceBot

本质上,我的问题是,如何使用.NET将PCM S16LE音频转换为MU-LAW/8000,同时支持.NET/Linux/Mac

更新1:

人们建议使用ffmpeg代替NAudio,我认为这是正确的,但我仍然听到尖锐的噪音,而不是实际的音频。

代码语言:javascript
复制
private async Task VoiceReceiveHandler(VoiceNextConnection connection, VoiceReceiveEventArgs args)
{
    var ffmpeg = Process.Start(new ProcessStartInfo
    {
        FileName = "ffmpeg",
        Arguments = $@"-hide_banner -ac 2 -f s16le -ar 48000 -i pipe:0 -c:a pcm_mulaw -f mulaw -ar 8000 -ac 1 pipe:1",
        RedirectStandardInput = true,
        RedirectStandardOutput = true
    });

    //byte[] trimmedData = new byte[args.PcmData.Length - 44];
    //Buffer.BlockCopy(args.PcmData.ToArray(), 44, trimmedData, 0, trimmedData.Length);

    await ffmpeg.StandardInput.BaseStream.WriteAsync(args.PcmData);
    ffmpeg.StandardInput.Close();
    byte[] data;
    using(var memoryStream = new MemoryStream())
    {
        ffmpeg.StandardOutput.BaseStream.CopyTo(memoryStream);
        data = memoryStream.ToArray();
    }
    ffmpeg.Dispose();

    //byte[] trimmedData = new byte[data.Length - 44];
    //Buffer.BlockCopy(data, 44, trimmedData, 0, trimmedData.Length);

    //return;

    if (twilioSocketConnectionManager.TryGetSocketById(socketId, out var twilioSocket) && twilioSocket.Socket.State == WebSocketState.Open)
    {
        var json = JsonSerializer.Serialize<MediaMessage>
        (
            new MediaMessage("media", twilioSocket.StreamSid, new MediaPayload(Convert.ToBase64String(data))), 
            jsonSerializerOptions
        );
        logger.LogInformation(json);
        var bytes = Encoding.Default.GetBytes(json);
        var arraySegment = new ArraySegment<byte>(bytes, 0, bytes.Length);
        await twilioSocket.Socket.SendAsync(arraySegment, WebSocketMessageType.Text, WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
    }
}

这是在一个分叉上。

EN

回答 1

Stack Overflow用户

发布于 2022-01-13 12:20:13

我有一个类似的问题,将Twilio的MU-LAW转换为PCM 16 to,然后流到Azure认知服务转录服务。我是用Java而不是dotnet编写的,我没有找到一个好的库解决方案。

然而,转换可以通过一个查找表(注意,一个字节的mulaw由2个字节的pcm表示)进行逐时字节转换。这里有一个维基百科对算法的抽象描述,我发现这个dotnet回购的代码很容易被翻译成Java,并且运行良好。对于您的情况,您需要查看MulawDecoder.cs。

我为mulaw->pcm生成的Java代码是这里

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70599169

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档