从 PCM 样本创建 WaveStream

发布于 2024-10-04 10:30:22 字数 2357 浏览 0 评论 0原文

我检查了 NAudio 及其 WaveStream 相关类,但我找不到基于我提供的 PCM 示例创建 WaveStream 的内置方法。

理想情况下,我想做这样的事情:

byte[] samples = ...
WaveFormat waveFormat = new WaveFormat(audioSampleRate, 
                                       audioBitsPerSample,
                                       audioChannels);
WaveStream waveStream = CreateWaveStreamfromSamples(waveFormat,
                                                    samples);

有办法使用 NAudio 做到这一点吗?

编辑汉斯、马克澄清后(感谢反馈):

我需要我可以传递给 SoundPlayer.Play 的流,这与 WaveStream 不太适合。在我的项目中,我最终实现了以下类,该类采用样本和 WaveFormat 并且可以由 SoundPlayer 播放。

public class MemoryWaveStream : Stream
{
    public override bool CanSeek { get { return false; } }
    public override bool CanWrite { get { return false; } }
    public override bool CanRead { get { return true; } }
    public override long Length { get { return _waveStream.Length; } }
    public override long Position { get { return _waveStream.Position; } set { _waveStream.Position = value; } }

    private MemoryStream _waveStream;

    public MemoryWaveStream(byte[] sampleData, WaveFormat waveFormat)
    {
        _waveStream = new MemoryStream();
        BinaryWriter bw = new BinaryWriter(_waveStream);
        bw.Write(new char[4] { 'R', 'I', 'F', 'F' });

        int length = 36 + sampleData.Length;
        bw.Write(length);

        bw.Write(new char[8] { 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ' });

        waveFormat.Serialize(bw);
        bw.Write(new char[4] { 'd', 'a', 't', 'a' });
        bw.Write(sampleData.Length);
        bw.Write(sampleData, 0, sampleData.Length);
        _waveStream.Position = 0;
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        return _waveStream.Read(buffer, offset, count);
    }

    public override void Flush()
    {
        _waveStream.Flush();
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        return _waveStream.Seek(offset, origin);
    }

    public override void SetLength(long value)
    {
        throw new NotImplementedException();
    }
    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotImplementedException();
    }
}

I checked NAudio and its WaveStream related classes, but I couldn't find a built in way to create a WaveStream based on PCM samples that I provide.

Ideally I would like to do something like this:

byte[] samples = ...
WaveFormat waveFormat = new WaveFormat(audioSampleRate, 
                                       audioBitsPerSample,
                                       audioChannels);
WaveStream waveStream = CreateWaveStreamfromSamples(waveFormat,
                                                    samples);

Is there a way to do this using NAudio?

Edit after clarification from Hans, Mark (thanks for the feedback):

I needed a stream that I could pass to SoundPlayer.Play, this doesn't fit well with WaveStream. In my project I ended up implementing the following class which takes samples and a WaveFormat and can be played back by SoundPlayer.

public class MemoryWaveStream : Stream
{
    public override bool CanSeek { get { return false; } }
    public override bool CanWrite { get { return false; } }
    public override bool CanRead { get { return true; } }
    public override long Length { get { return _waveStream.Length; } }
    public override long Position { get { return _waveStream.Position; } set { _waveStream.Position = value; } }

    private MemoryStream _waveStream;

    public MemoryWaveStream(byte[] sampleData, WaveFormat waveFormat)
    {
        _waveStream = new MemoryStream();
        BinaryWriter bw = new BinaryWriter(_waveStream);
        bw.Write(new char[4] { 'R', 'I', 'F', 'F' });

        int length = 36 + sampleData.Length;
        bw.Write(length);

        bw.Write(new char[8] { 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ' });

        waveFormat.Serialize(bw);
        bw.Write(new char[4] { 'd', 'a', 't', 'a' });
        bw.Write(sampleData.Length);
        bw.Write(sampleData, 0, sampleData.Length);
        _waveStream.Position = 0;
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        return _waveStream.Read(buffer, offset, count);
    }

    public override void Flush()
    {
        _waveStream.Flush();
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        return _waveStream.Seek(offset, origin);
    }

    public override void SetLength(long value)
    {
        throw new NotImplementedException();
    }
    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotImplementedException();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

桃扇骨 2024-10-11 10:30:22

如果需要,您可以将基于字节数组的 MemoryStream 传递到以下类。我可能会在 NAudio 1.4 中包含类似的内容,因为我收到了很多关于如何执行此操作的支持请求。

public class RawSourceWaveStream : WaveStream
{
    private Stream sourceStream;
    private WaveFormat waveFormat;

    public RawSourceWaveStream(Stream sourceStream, WaveFormat waveFormat)
    {
        this.sourceStream = sourceStream;
        this.waveFormat = waveFormat;
    }

    public override WaveFormat WaveFormat
    {
        get { return this.waveFormat; }
    }

    public override long Length
    {
        get { return this.sourceStream.Length; }
    }

    public override long Position
    {
        get
        {
            return this.sourceStream.Position;
        }
        set
        {
            this.sourceStream.Position = value;
        }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        return sourceStream.Read(buffer, offset, count);
    }
}

Here's a class that you can pass a MemoryStream based on your byte array into if you want. I'll probably include something like this in NAudio 1.4 as I get a lot of support requests about how to do this.

public class RawSourceWaveStream : WaveStream
{
    private Stream sourceStream;
    private WaveFormat waveFormat;

    public RawSourceWaveStream(Stream sourceStream, WaveFormat waveFormat)
    {
        this.sourceStream = sourceStream;
        this.waveFormat = waveFormat;
    }

    public override WaveFormat WaveFormat
    {
        get { return this.waveFormat; }
    }

    public override long Length
    {
        get { return this.sourceStream.Length; }
    }

    public override long Position
    {
        get
        {
            return this.sourceStream.Position;
        }
        set
        {
            this.sourceStream.Position = value;
        }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        return sourceStream.Read(buffer, offset, count);
    }
}
浅忆流年 2024-10-11 10:30:22

不,没有什么比这更好的了。不过,您可以创建自己的。 wave\wavestream\wavefilereader.cs 源代码文件可能是最好的入门工具。您可以从中剥离一些东西,用正确初始化的 MemoryStream 替换 waveStream。

No, nothing like it. You can however create your own. The wave\wavestream\wavefilereader.cs source code file is probably best to get started with. Bunch of stuff you can strip from it, replace the waveStream by a properly initialized MemoryStream.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文