C#教程
主页 > 软件编程 > C#教程 >

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

2024-12-24 | 佚名 | 点击:

一、通过Nuget安装NAudio包

开发工具:vs2019

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

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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类型就不需要执行下边操作)

1

2

3

// 将short[]音频数据转换为byte[]数据

byte[] byteData = new byte[audioData.Length * 2]; // short类型占2个字节

Buffer.BlockCopy(audioData, 0, byteData, 0, byteData.Length);

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

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对象中,进行播放

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

// 创建内存流

           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();

           }

四、完整代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

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();

            }

  

  

        }

    }

}

原文链接:
相关文章
最新更新