惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
有赞技术团队
有赞技术团队
IT之家
IT之家
博客园 - 聂微东
Jina AI
Jina AI
Hugging Face - Blog
Hugging Face - Blog
Last Week in AI
Last Week in AI
Apple Machine Learning Research
Apple Machine Learning Research
WordPress大学
WordPress大学
小众软件
小众软件
爱范儿
爱范儿
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
Visual Studio Blog
雷峰网
雷峰网
酷 壳 – CoolShell
酷 壳 – CoolShell
阮一峰的网络日志
阮一峰的网络日志
宝玉的分享
宝玉的分享
博客园 - 三生石上(FineUI控件)
大猫的无限游戏
大猫的无限游戏
博客园 - Franky
量子位
月光博客
月光博客
博客园 - 【当耐特】
博客园 - 叶小钗

博客园 - 风中灵药

如何在mvc中共用一个dbconext以节省资源提高性能? asp.net core api路由及多语言切换的实现 安装win7 64位和win10 64位双系统小结 macbook装双系统多分区其实很简单,你只要把macbook当作一台普通pc就可以了! 个人对AutoResetEvent和ManualResetEvent的理解 关于WPF下ComBox的SelectionChanged事件 一条语句实现查询各类别前10条记录 【原】Sql2005 实现递归 【转】javascript操作cookies 以及 正确使用cookies的属性 回归: css, bug bug, background-repeat and frames 如何用oledb读取dbf(FoxPro表)文件? SQL注入中利用XP_cmdshell提权的用法(转) Sql 2005自动备份并自动删除3天前的备份 ActiveX开发心得(原创) 常用正则表达式(包括中文匹配) 使用ASP.NET Global.asax 文件(转) 如何不打开文件 直接出现下载保存提示框 Replace ntext类型中的文字 关于IFRAME 自适应高度的研究[转]
mp3转speex的一些研究(貌似不能播放,暂存着)
风中灵药 · 2017-03-31 · via 博客园 - 风中灵药

思路是,先从mp3中提取pcm(raw原始数据),再将原始数据转成speex。

貌似不能播放,可能还存在其他问题,需要继续研究。

使用了两个类库NSpeex和NAudio

            using (var waveStream = new NAudio.Wave.Mp3FileReader(@"D:\我的项目源码\Record\Record\bin\Debug\2.mp3"))
            {
                using (var fileOutputStream = new FileStream(@"D:\我的项目源码\Record\Record\bin\Debug\xxx.spx", FileMode.Create, FileAccess.Write))
                {
                    byte[] buff = new byte[waveStream.Length];
                    var r = waveStream.Read(buff, 0, buff.Length);
                    var bytes = EncodeSpeech(buff, buff.Length);
                    fileOutputStream.Write(bytes, 0, bytes.Length);
                }
            }
private static byte[] EncodeSpeech(byte[] buf, int len)
        {
            SpeexEncoder encoder = new SpeexEncoder(BandMode.Narrow);

            // set encoding quality to lowest (which will generate the smallest size in the fastest time)
            encoder.Quality = 1;

            int inDataSize = len / 2;
            // convert to short array
            short[] data = new short[inDataSize];
            int sampleIndex = 0;
            for (int index = 0; index < len; index += 2, sampleIndex++)
            {
                data[sampleIndex] = BitConverter.ToInt16(buf, index);
            }

            // note: the number of samples per frame must be a multiple of encoder.FrameSize
            inDataSize = inDataSize - inDataSize % encoder.FrameSize;

            var encodedData = new byte[len];
            int encodedBytes = encoder.Encode(data, 0, inDataSize, encodedData, 0, len);
            if (encodedBytes != 0)
            {
                // each chunk is laid out as follows:
                // | 4-byte total chunk size | 4-byte encoded buffer size | <encoded-bytes> |
                byte[] inDataSizeBuf = BitConverter.GetBytes(inDataSize);
                byte[] sizeBuf = BitConverter.GetBytes(encodedBytes + inDataSizeBuf.Length);
                byte[] returnBuf = new byte[encodedBytes + sizeBuf.Length + inDataSizeBuf.Length];
                sizeBuf.CopyTo(returnBuf, 0);
                inDataSizeBuf.CopyTo(returnBuf, sizeBuf.Length);
                Array.Copy(encodedData, 0, returnBuf, sizeBuf.Length + inDataSizeBuf.Length, encodedBytes);
                return returnBuf;
            }
            else
                return buf;
        }
/// <summary>
        /// byte数组转short数组
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        private static short[] BytesToShorts(byte[] bytes)
        {
            //short[] data = new short[bytes.Length / 2];
            //Buffer.BlockCopy(bytes, 0, data, 0, bytes.Length);
            //return data;

            //convert to short
            short[] data = new short[bytes.Length / 2];
            int sampleIndex = 0;
            for (int index = 0; sampleIndex < data.Length; index += 2, sampleIndex++)
            {
                data[sampleIndex] = BitConverter.ToInt16(bytes, index);
            }
            return data;
        }

        /// <summary>
        /// 获取音频时长
        /// </summary>
        /// <param name="voiceFile"></param>
        /// <returns></returns>
        private static int GetVoiceTimeLength(string voiceFile)
        {
            ShellClass sh = new ShellClass();
            var dir = sh.NameSpace(Path.GetDirectoryName(voiceFile));
            var item = dir.ParseName(Path.GetFileName(voiceFile));
            string str = dir.GetDetailsOf(item, 27);// 获取歌曲时长。

            if (!String.IsNullOrEmpty(str))
            {
                var arr = str.Split(':');
                var i = int.Parse(arr[0]) * 3600 + int.Parse(arr[1]) * 60 + int.Parse(arr[2]);
                return i;
            }
            else
                return 0;
        }

第二种获取时长方法

        private static double GetVoiceTimeLength2(string voiceFile)
        {
            using (var waveStream = new NAudio.Wave.Mp3FileReader(voiceFile))
            {
                return Math.Floor(waveStream.TotalTime.TotalSeconds);
            }
        }