C#播放short或者byte类型的音频

 更新时间:2024年12月23日 15:25:04   作者:rbigbearr  
这篇文章主要为大家详细介绍了如何使用C#实现播放short或者byte类型的音频,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

一、通过Nuget安装NAudio包

开发工具:vs2019

点击Visual Studio 2019的工具->NuGet包管理器-》管理解决方案的NuGet的程序包-》浏览-》在搜索框中输入NAudio-》点击安装

二、获取short类型或者byte类型的音频数据

我的数据是一组short类型的正弦波信号,存储在txt中,如下图所示:

通过C#读取文档并存储在short数组中

string filePath = "20500Left.txt"; // txt文件路径
short[] audioData = new short[48000 * 2]; //双声道数据 
int index = 0;
// 读取txt文档并按逗号分割文本
using (StreamReader reader = new StreamReader(filePath))
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        string[] parts = line.Split(',');
        foreach (string part in parts)
        {
            //Console.WriteLine(part);
            audioData[index] = Convert.ToInt16(part);
            index++;
        }
    }
              
}

将short变为byte类型的数据(如果本身你的音频数据就是byte类型就不需要执行下边操作)

// 将short[]音频数据转换为byte[]数据
byte[] byteData = new byte[audioData.Length * 2]; // short类型占2个字节
Buffer.BlockCopy(audioData, 0, byteData, 0, byteData.Length);

三、循环播放自己的音频数据,重写WaveStream类

主要是重写了Read这个函数,读到数据流末尾,就从开头读取。

 class LoopingWaveStream : WaveStream
    {
        private WaveStream sourceStream;
 
        public LoopingWaveStream(WaveStream sourceStream)
        {
            this.sourceStream = sourceStream;
        }
 
        public override WaveFormat WaveFormat => sourceStream.WaveFormat;
 
        public override long Length => sourceStream.Length;
 
        public override long Position
        {
            get => sourceStream.Position;
            set => sourceStream.Position = value;
        }
 
        public override int Read(byte[] buffer, int offset, int count)
        {
            int bytesRead = 0;
 
            while (bytesRead < count)
            {
                int read = sourceStream.Read(buffer, offset + bytesRead, count - bytesRead);
                if (read == 0)
                {
                    // 如果读取到末尾,重新从头开始读取
                    sourceStream.Position = 0;
                }
                bytesRead += read;
            }
 
            return bytesRead;
        }
    }

将上边的byte类型的数据转换为Stream类型,并填入WaveOut对象中,进行播放

 // 创建内存流
            using (MemoryStream stream = new MemoryStream(byteData))
            {
                // 从内存流中创建RawSourceWaveStream   //采样率设置为48000,位深设置位16位,通道为双声道
                RawSourceWaveStream rawStream = new RawSourceWaveStream(stream, new WaveFormat(48000, 16, 2));
                LoopingWaveStream loopingWaveStream=new LoopingWaveStream(rawStream); 
                // 使用WaveOutEvent播放音频数据
                WaveOut waveOut = new WaveOut();
                waveOut.Init(loopingWaveStream);//想要循环播放
                //waveOut.Init(rawStream);      //不想要循环播放
                waveOut.Play();
 
                //下边两种方式的循环播放会有爆音,不采用。
                //waveOut.PlaybackStopped += (sender, e) =>
                //   {
                //       if (waveOut.PlaybackState == PlaybackState.Stopped)
                //       {
                //           rawStream.Position = 0;
                //           waveOut.Play();
                //       }
                //   };
                //while (waveOut.PlaybackState == PlaybackState.Playing)
                //{
                //    if (rawStream.Position >= rawStream.Length)
                //    {
                //        rawStream.Position = 0;
                //        //Console.WriteLine("Audio stream reached the end.");
                //        //break;
                //    }                    
                //}
 
                Console.WriteLine("Press Enter to stop playback.");
                Console.ReadLine();   //阻塞线程
 
                waveOut.Stop();  //停止播放
                waveOut.Dispose();
            }

四、完整代码

using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Media;
using System.Text;
using System.Threading.Tasks;
 
namespace 播放short
{
    class LoopingWaveStream : WaveStream
    {
        private WaveStream sourceStream;
 
        public LoopingWaveStream(WaveStream sourceStream)
        {
            this.sourceStream = sourceStream;
        }
 
        public override WaveFormat WaveFormat => sourceStream.WaveFormat;
 
        public override long Length => sourceStream.Length;
 
        public override long Position
        {
            get => sourceStream.Position;
            set => sourceStream.Position = value;
        }
 
        public override int Read(byte[] buffer, int offset, int count)
        {
            int bytesRead = 0;
 
            while (bytesRead < count)
            {
                int read = sourceStream.Read(buffer, offset + bytesRead, count - bytesRead);
                if (read == 0)
                {
                    // 如果读取到末尾,重新从头开始读取
                    sourceStream.Position = 0;
                }
                bytesRead += read;
            }
 
            return bytesRead;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始");
 
            string filePath = "20500Left.txt"; // txt文件路径
            short[] audioData = new short[48000 * 2]; //双声道数据 
            int index = 0;
            // 读取txt文档并按逗号分割文本
            using (StreamReader reader = new StreamReader(filePath))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    string[] parts = line.Split(',');
                    foreach (string part in parts)
                    {
                        //Console.WriteLine(part);
                        audioData[index] = Convert.ToInt16(part);
                        index++;
                    }
                }
              
            }
            // 将short[]音频数据转换为byte[]数据
            byte[] byteData = new byte[audioData.Length * 2]; // short类型占2个字节
            Buffer.BlockCopy(audioData, 0, byteData, 0, byteData.Length);
            //方式1///
            
            // 创建内存流
            using (MemoryStream stream = new MemoryStream(byteData))
            {
                // 从内存流中创建RawSourceWaveStream   //采样率设置为48000,位深设置位16位,通道为双声道
                RawSourceWaveStream rawStream = new RawSourceWaveStream(stream, new WaveFormat(48000, 16, 2));
                LoopingWaveStream loopingWaveStream=new LoopingWaveStream(rawStream); 
                // 使用WaveOutEvent播放音频数据
                WaveOut waveOut = new WaveOut();
                waveOut.Init(loopingWaveStream);//想要循环播放
                //waveOut.Init(rawStream);      //不想要循环播放
                waveOut.Play();
 
                //下边两种方式的循环播放会有爆音,不采用。
                //waveOut.PlaybackStopped += (sender, e) =>
                //   {
                //       if (waveOut.PlaybackState == PlaybackState.Stopped)
                //       {
                //           rawStream.Position = 0;
                //           waveOut.Play();
                //       }
                //   };
                //while (waveOut.PlaybackState == PlaybackState.Playing)
                //{
                //    if (rawStream.Position >= rawStream.Length)
                //    {
                //        rawStream.Position = 0;
                //        //Console.WriteLine("Audio stream reached the end.");
                //        //break;
                //    }                    
                //}
 
                Console.WriteLine("Press Enter to stop playback.");
                Console.ReadLine();   //阻塞线程
 
                waveOut.Stop();  //停止播放
                waveOut.Dispose();
            }
 
 
        }
    }
}

以上就是C#播放short或者byte类型的音频的详细内容,更多关于C#播放音频的资料请关注脚本之家其它相关文章!

相关文章

  • WPF利用TextBlock实现查找结果高亮显示效果

    WPF利用TextBlock实现查找结果高亮显示效果

    在应用开发过程中,经常遇到这样的需求:通过关键字查找数据,把带有关键字的数据显示出来,同时在结果中高亮显示关键字,所以本文就来和大家介绍一下如何利用TextBlock实现查找结果高亮显示效果吧
    2023-08-08
  • Unity中EventTrigger的几种使用操作

    Unity中EventTrigger的几种使用操作

    这篇文章主要介绍了Unity中EventTrigger的几种使用操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • C#对象与XMl文件之间的相互转换

    C#对象与XMl文件之间的相互转换

    本文是对C#中对象与XMl文件之间的相互转换进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-10-10
  • C#中SQL Command的基本用法

    C#中SQL Command的基本用法

    今天小编就为大家分享一篇关于C#中SQL Command的基本用法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • C# Winform实现表格复制粘贴效果

    C# Winform实现表格复制粘贴效果

    这篇文章主要为大家学习介绍了如何通过C# Winform实现表格复制粘贴效果,文中的示例代码讲解详细,具有一定的参考价值,需要的可以了解一下
    2023-07-07
  • C# 进行图片压缩的示例代码(对jpg压缩效果最好)

    C# 进行图片压缩的示例代码(对jpg压缩效果最好)

    这篇文章主要介绍了C# 进行图片压缩的示例代码,帮助大家更好的利用c# 处理图片,提高办公效率,感兴趣的朋友可以了解下
    2020-11-11
  • TortoiseSVN使用教程

    TortoiseSVN使用教程

    TortoiseSVN 是 Subversion 版本控制系统的一个免费开源客户端,可以超越时间的管理文件和目录。本文给大家介绍TortoiseSVN使用教程,对tortoisesvn使用相关知识感兴趣的朋友一起学习吧
    2015-12-12
  • Unity3D游戏-鼠标点击使角色移动避开障碍物

    Unity3D游戏-鼠标点击使角色移动避开障碍物

    在Unity的世界里,当你轻点鼠标,角色仿佛被赋予了新的使命,沿着一条无形的轨迹,向着地图上的目标点进发,每一次移动,不仅是简单的位移,更是对未知的探索,这种交互,让玩家与游戏世界紧密相连,仿佛自己就是那个掌控命运的魔法师,用指尖绘制出角色的冒险之路......
    2025-08-08
  • unity 鼠标悬停事件操作

    unity 鼠标悬停事件操作

    这篇文章主要介绍了unity 鼠标悬停事件操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • c#完美截断字符串代码(中文+非中文)

    c#完美截断字符串代码(中文+非中文)

    c#完美截断字符串代码(中文+非中文),需要的朋友可以参考下
    2012-08-08

最新评论