繁体   English   中英

是否可以使用NAudio从short []而不是byte []播放音频?

[英]Is it possible to play audio from a short[] instead of a byte[] with NAudio?

我正在尝试播放通过短裤组成的网络接收的音频。 我正在尝试使用NAudio的WaveOut对象使之工作,但是从我发现的情况来看,这仅适用于byte []。 所以到目前为止,我的问题是:

  • 是否可以从short []而不是byte []播放音频?
  • 如果是这样,将如何进行?

数量不多,但是我现在所拥有的(显然是从byte []播放音频):

protected override void Write(VoiceSource source, VoicePacket packet)
{
      if (connected)
      {
            try
            {
                dispatcher.Invoke((WriteCallback)provider.Write, packet.Data);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
      }
}

其中WriteCallback定义为:

private delegate void WriteCallback(byte[] data);

我正在写的提供程序是IWaveProvider接口的实现。


编辑

我尝试了Mark告诉我的“技巧”,我的界面看起来像这样:

interface ISampleBuffer {
    byte[] Bytes { get; set; }
    short[] Shorts { get; set; }
}

缓冲区结构如下所示:

[StructLayout(LayoutKind.Explicit, Pack = 2)]
public struct SampleBuffer : ISampleBuffer
{
    [FieldOffset(0)]
    private byte[] bytes;
    [FieldOffset(0)]
    private short[] shorts;
    public byte[] Bytes { get { return bytes; } set { bytes = value; } }
    public short[] Shorts { get { return shorts; } set { shorts = value; } }
}

我已经像这样实现了此缓冲区:

short[] audio = decoder.Decode(packet.Data);
buffer.Bytes = new byte[audio.Length * 2];
buffer.Shorts = audio;
dispatcher.Invoke((WriteCallback)provider.Write, buffer.Bytes);

但是,每当我运行此安装程序时,我的日志中都会出现一个带有以下异常的堆栈跟踪:

Object of type 'System.Int16[]' cannot be converted to type 'System.Byte[]'.

我如何执行此操作有问题吗?

NAudio包括一个巧妙的技巧(或肮脏的技巧,具体取决于您的观点),它使您可以将short[]byte[] 它称为WaveBuffer类,通过使用具有显式布局的结构来工作。 只需写入ShortBuffer属性并读出ByteBuffer属性即可。

我前一段时间写了一篇博客 它已经可靠地工作了几年,并节省了使用Buffer.BlockCopy的开销。

不确定NAudio位,但是我可以帮助您将short[]转换为byte[] Buffer.BlockCopy在这里可能有用,因为它可以在不同类型的数组之间复制字节:

 short[] shortArray = ...
 byte[] byteArray = new byte[shortArray.Length*2];
 Buffer.BlockCopy(shortArray, 0, byteArray, 0, byteArray.Length);

但是,您可能会遇到字节序问题。 您需要尝试一下,看看会发生什么。 如果您需要交换组成单个short的两个字节,则可以手动交换它:

 for (int i=0; i<byteArray.Length; i += 2) {
     byte b = byteArray[i];
     byteArray[i] = byteArray[i+1];
     byteArray[i] = b;
 }

另外,如果您想使事情更整洁,又不想担心字节序转换,则可以使用BinaryWriter为您完成转换:

BinaryWriter writer = new BinaryWriter(new MemoryStream(shortArray.Length*2));
foreach (short s in shortArray)
    writer.Write(s);

byte[] byteArray = ((MemoryStream)writer.BaseStream).ToArray();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM