【C#通过共享内存MemoryMappedFile解码和播放WavPack等PCM音频】

在这里插入图片描述

这里只介绍思路,具体代码可以指路
如果有更好的方法,欢迎指出,这里仅当抛砖引玉

原理很简单,找到一个可以同时可读可写的流对象而且不必担心写入时流的位置对播放的影响就完事大吉,因为两个解码的位置和读取流的位置必定不一样(也许可以通过锁来解决),一开始博主想到的是TCP UDP这些的,的确是可以的,服务端发送数据,客户端读取数据;其实还有一个更好的,就是MemoryMappedFile,它是读写毫不相干,那么我发送端只需要发送就可以了,另外一端直接读取,非常方便

        //全局
        static MemoryMappedFile mmf;
        static Imouto.Audio.WaveFormat waveFormat;
//解码WavPack格式无损音频
//WavPackCodec:https://www.wavpack.com/downloads.html  -->C# Wrapper
 static void tesk_server(object o)
        {
            using (WavPack wavPack = new WavPack(@"E:\Audio\LosslessAudio\[EAC] [MGRT][WavPack][ANZX-6718]「白金ディスコ」&「偽物語」劇伴音楽集 其ノ參(WavPack+CUE)\ANZX-6718.wv"))
            {
                waveFormat = wavPack.WaveFormat;
                using (MemoryMappedViewStream stream = mmf.CreateViewStream())
                {
                    BinaryWriter writer = new BinaryWriter(stream);
                    Byte[] buffer = new Byte[1024 * 16];
                    for (Int32 bytesRead; (0 != (bytesRead = wavPack.Read(buffer)));)
                    {
                        writer.Write(buffer, 0, bytesRead);
                    }
                }
            }
        }
//用NAudio的BufferedWaveProvider播放PCM数据
//https://github.com/hha1501/NanoBot/tree/8d7051ccc184718ce2960f30cfb0e45e4d172dc7
        static void  tesk_client(object o)
        {
            using (MemoryMappedViewStream stream = mmf.CreateViewStream())
            {
                BufferedWavePlayer dd = new BufferedWavePlayer(stream, waveFormat.SamplesPerSecond, waveFormat.BitsPerSample, waveFormat.Channels);

                System.Threading.Tasks.Task task = dd.PlayAsync();
                task.GetAwaiter().GetResult();
            }
        }


主函数:
PS:这里只要关心产生的数据大小会不会爆内存,这里博主设置了1G大小
一般音频也没有那么大。
创建一个解码线程,一个播放线程,思路其实和SDL音频播放接口异曲同工

      static void Main(string[] args)
        {
            mmf = MemoryMappedFile.CreateNew("test", 1024*1024*1024, MemoryMappedFileAccess.ReadWrite);
            ThreadPool.QueueUserWorkItem(tesk_server, null);
            System.Threading.Thread.Sleep(1000);
            ThreadPool.QueueUserWorkItem(tesk_client, null);
            Console.ReadKey();

        }

PS:以上函数仅供参考,在内存效率使用上还是有一点点缺陷,一般有可能出现内存溢出等问题,可以参考“https://www.codenong.com/15662455/” 去解决和优化
在这里插入图片描述

知道了这个的话,其实播放Wav格式的音频也一样,只要读取Wav的头,大小44个字节,里面包括了sampleRate(一般为44100),channels(一般为2),和bitperSample(一般为16)这三个关键数据,就可以直接截取44字节后面的PCM数据了,一模一样,可以Git找一下Wav的解析类

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值