开发完成语音播报产品,由于客户所使用的播放产品种类繁多,在使用HDMI接口播放音频时,由于采用的声卡不同,个别机器会出现播报声音过小,或者不播报的情况。所以采用将语音文件合并播放的方式,来解决此问题。

   /// <summary>
        /// 合并语音流
        /// </summary>
        /// <param name="pPlayStreamsList">语音流集合</param>
        public void MergeAndPlayWavFile(ObservableCollection<Stream> pPlayStreamsList)
        {
            try
            {
                if (pPlayStreamsList.Count > 0)
                {
                    int dataFileBeginIndex = 0;
                    int formatSize;
                    List<byte[]> bInfoList = new List<byte[]>();
                    List<int> fileSizeList = new List<int>();
                    List<int> dataSizeList = new List<int>();
                    foreach (Stream fs in pPlayStreamsList)
                    {
                        fs.Position = 0;
                        byte[] bInfo = new byte[46];
                        fs.Read(bInfo, 0, 46);
                        formatSize = BitConverter.ToInt32(bInfo, 16);
                        //Wave = RIFF_WAVE_Chunk + Format_Chunk + Data_Chunk(RIFF)/Fact_Chunk(FACT)
                        //RIFF_WAVE_Chunk(文件头,12个字节)+
                        //Format_Chunk(声音内容定义,根据第16到20个字节得到剩下区块大小,16或者18个字节)+
                        //Data_Chunk(数据区)
                        dataFileBeginIndex = formatSize + 20 + 4;
                        bInfoList.Add(bInfo);
                        fileSizeList.Add(System.BitConverter.ToInt32(bInfo, 4));
                        dataSizeList.Add(System.BitConverter.ToInt32(bInfo, dataFileBeginIndex));
                    }

                    //计算所有WAV文件大小
                    int fileSize = 0;
                    foreach (int fSize in fileSizeList)
                    {
                        fileSize += fSize;
                    }
                    byte[] totalFileSize = System.BitConverter.GetBytes(fileSize);

                    //计算所有WAV数据大小
                    int dataSize = 0;
                    foreach (int dSize in dataSizeList)
                    {
                        dataSize += dSize;
                    }
                    byte[] totalDataSize = System.BitConverter.GetBytes(dataSize);
                    using (Stream toFile = new MemoryStream())
                    {
                        //Stream toFile = new MemoryStream();
                        BinaryWriter bWriter = new BinaryWriter(toFile);

                        //获取最后一个wav文件的详细内容
                        int lastWaveFile = pPlayStreamsList.Count - 1;

                        for (int i = 4, j = 0; i < 8; i++, j++)
                        {
                            bInfoList[lastWaveFile][i] = totalFileSize[j];
                        }

                        for (int i = dataFileBeginIndex, j = 0; i < dataFileBeginIndex + 4; i++, j++)
                        {
                            bInfoList[lastWaveFile][i] = totalDataSize[j];
                        }
                        bWriter.Write(bInfoList[lastWaveFile]);
                        int k = 0;
                        foreach (Stream fs in pPlayStreamsList)
                        {
                            int readLength;
                            fs.Position = dataFileBeginIndex + 4;
                            if (k < dataSizeList.Count)
                            {
                                readLength = dataSizeList[k] - 40;
                                byte[] dushu = new byte[readLength];
                                fs.Read(dushu, 0, readLength);
                                bWriter.Write(dushu, 0, readLength);
                                k++;
                            }
                        }
                        SoundPlayer player = new SoundPlayer();
                        if (toFile != null)
                        {
                            player.Stream = null;
                            player.Stream = toFile;
                            toFile.Position = 0;
                            player.LoadAsync();
                            for (int i = 0; i < playTimes; i++)
                            { player.PlaySync(); }

                        }

                        bWriter.Flush();
                        bWriter.Close();

                        toFile.Flush();
                        toFile.Close();
                        player.Dispose();
                        bWriter.Dispose();
                        toFile.Dispose();
                    }
                }
            }
            catch (Exception e)
            {
                LogInfo.saveLog("合并语音流报错,方法MergeAndPlayWavFile():" + e.Message);
            }

   }

C# wav语音文件合并的更多相关文章

  1. [Audio processing] wav音频文件合并

    合并多个文件,需要包含1.文件读取和写入功能,2.数组合并 package com.audioprocessingbox.myfunc; import java.io.File; import jav ...

  2. 多个wav音频文件合并(连接)成一个文件

    场景:一段声音从浏览器麦克风缓冲上一段一段发给服务器,按照时间戳生成很多文件. 目的:把他们按时间顺序连到一个时间轴上. 命令如下: ffmpeg -f concat -i list.txt out. ...

  3. Python网页正文转换语音文件的操作方法

    天气真的是越来越冷啦,有时候我们想翻看网页新闻,但是又冷的不想把手拿出来,移动鼠标翻看.这时候,是不是特别想电脑像讲故事一样,给我们念出来呢?人生苦短,我有python啊,试试用 Python 来朗读 ...

  4. WAV格式文件无损合并&帧头数据体解析(python)(原创)

    一,百度百科 WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频 ...

  5. C# 使用NAudio合并mp3、wav音频文件

    1.什么是wav格式    WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windo ...

  6. asp.net使用SpeechSynthesizer类生成语音文件部署到iis遇到的几个坑

    首先需要引入命名空间System.Speech.Synthesis,代码如下: using (var speechSyn = new SpeechSynthesizer()) { speechSyn. ...

  7. 解析WAV音频文件----》生成WAV音频文件头

    前言:请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i WAV音频文件介绍: WAV文件是在PC机平台上很常见的.最经典的多媒体音频文件,最早于1991年8月出现在Windows3.1操作系统 ...

  8. CDN的combo技术能把多个资源文件合并引用,减少请求次数

    CDN的combo技术能把多个资源文件合并引用,减少请求次数.比如淘宝的写法: <link rel="stylesheet" href="//g.alicdn.co ...

  9. linux 两个文件合并

    可以使用cat命令,有两种实现的方式,一种将两个文件合并的到一个新的文件,另一种将一个文件追加到另一个文件的末尾. 方法一:使用cat命令从文件中读入两个文件,然后将重定向到一个新的文件.这种方法可以 ...

随机推荐

  1. [dsu on tree]【学习笔记】

    十几天前看到zyf2000发过关于这个的题目的Blog, 今天终于去学习了一下 Codeforces原文链接 dsu on tree 简介 我也不清楚dsu是什么的英文缩写... 就像是树上的启发式合 ...

  2. 在ASP.NET MVC中使用Web API和EntityFramework构建应用程序

    最近做了一个项目技术预研:在ASP.NET MVC框架中使用Web API和EntityFramework,构建一个基础的架构,并在此基础上实现基本的CRUD应用. 以下是详细的步骤. 第一步 在数据 ...

  3. Java并发(一)——线程安全的容器(上)

    Java中线程安全的容器主要包括两类: Vector.Hashtable,以及封装器类Collections.synchronizedList和Collections.synchronizedMap: ...

  4. Java集合中的Map接口

    jdk1.8.0_144 Map是Java三种集合中的一种位于java.util包中,Map作为一个接口存在定义了这种数据结构的一些基础操作,它的最终实现类有很多:HashMap.TreeMap.So ...

  5. [翻译] 编写高性能 .NET 代码--第二章 GC -- 减少大对象堆的碎片,在某些情况下强制执行完整GC,按需压缩大对象堆,在GC前收到消息通知,使用弱引用缓存对象

    减少大对象堆的碎片 如果不能完全避免大对象堆的分配,则要尽量避免碎片化. 对于LOH不小心就会有无限增长,但LOH使用的空闲列表机制可以减轻增长的影响.利用这个空闲列表,我们可以在两块分配区域中间找到 ...

  6. Maven项目热部署,修改代码后不用重启tomcat服务器

    只需要在pom.xml文件中添加 <build> <finalName>MySSM</finalName> <!-- 指定部署的服务器类型 --> &l ...

  7. 前端时间戳timestamp相关总结:

    一.JavaScript获取当前时间戳的方法 第一种方法:var timestamp = Date.parse(new Date());结果:1280977330000 第二种方法:var times ...

  8. requests+多进程poll+pymongo实现抓取小说

    今天看着有个很吸引人的小说作品信息:一家只在深夜开门营业的书屋,欢迎您的光临.作为东野奎吾<深夜食堂>漫画的fans,看到这个标题按捺不住我的好奇心........ 所以我又抓下来了,总共 ...

  9. 【java学习笔记】文件操作

    文件操作 java.io.File ①创建删除文件及目录 ②查看文件及目录属性 ③文件过滤器 (PS:不包括文件读写数据) 1.单个文件 创建单个文件,查看属性,删除单个文件. package tmp ...

  10. js数据类型的判断方法

    判断js中的数据类型有一下几种方法:typeof.instanceof. constructor. prototype. $.type()/jquery.type(),接下来主要比较一下这几种方法的异 ...