yunxizfj

等待...

导航

简单实用的PCM音频播放器--沉寂几年之后回归的第一份笔记

---恢复内容开始---

PCM音频网络流播放,至于用处,就不多解释了。

一个简单的类,基于NAudio,一个简单的拼装类,实例化时三个参数,依次是采样率,系统播放设备Index,播放声道,调用PlayData方法传入PCM的音频流即可,有流就传进去,数据断了,播放自动停。

接下来把代码贴出来:

 1 public class PCMPlayer
 2     {
 3         private MonoToStereoProvider16 monoToStereoProvider16;
 4         private BufferedWaveProvider bufferedWaveProvider;
 5         private WaveOut waveOut;
 6         private bool isRunning = false;
 7         private PCMPlayerChannel currentChannel;
 8 
 9         /// <summary>
10         /// 
11         /// </summary>
12         /// <param name="sampleRate">采样率8K至64K</param>
13         /// <param name="deviceNumber">通过GetPlayDevices来获取字典的KEY值</param>
14         /// <param name="playerChannel">初始化时播放的声道</param>
15         public PCMPlayer(int sampleRate, int deviceNumber = 0, PCMPlayerChannel playerChannel = PCMPlayerChannel.Both)
16         {
17             currentChannel = playerChannel;
18             WaveFormat = new WaveFormat(sampleRate, 16, 1);
19             bufferedWaveProvider = new BufferedWaveProvider(WaveFormat);
20             monoToStereoProvider16 = new MonoToStereoProvider16(bufferedWaveProvider);
21             waveOut = new WaveOut();
22             waveOut.DeviceNumber = deviceNumber;
23             waveOut.Init(monoToStereoProvider16);
24             waveOut.Play();
25             isRunning = true;
26         }
27 
28         public void PlayData(byte[] data)
29         {
30             if (!isRunning) return;
31             bufferedWaveProvider.AddSamples(data, 0, data.Length);
32         }
33 
34         public void ClosePlay()
35         {
36             isRunning = false;
37             waveOut.Stop();
38             waveOut.Dispose();
39         }
40 
41         public bool SetPlayChannel(PCMPlayerChannel playerChannel)
42         {
43             if (!isRunning || waveOut == null || monoToStereoProvider16 == null) return false;
44             switch (playerChannel)
45             {
46                 case PCMPlayerChannel.Left:
47                     {
48                         monoToStereoProvider16.LeftVolume = 1.0f;
49                         monoToStereoProvider16.RightVolume = 0.0f;
50                     }
51                     break;
52                 case PCMPlayerChannel.Right:
53                     {
54                         monoToStereoProvider16.LeftVolume = 0.0f;
55                         monoToStereoProvider16.RightVolume = 1.0f;
56                     }
57                     break;
58                 case PCMPlayerChannel.Both:
59                     {
60                         monoToStereoProvider16.LeftVolume = 1.0f;
61                         monoToStereoProvider16.RightVolume = 1.0f;
62                     }
63                     break;
64                 default: return false;
65             }
66             return true;
67         }
68 
69         public WaveFormat WaveFormat { get; private set; }
70 
71         public static Dictionary<int, WaveOutCapabilities> GetPlayDevices
72         {
73             get
74             {
75                 Dictionary<int, WaveOutCapabilities> result = new Dictionary<int, WaveOutCapabilities>();
76                 try
77                 {
78                     int count = WaveOut.DeviceCount;
79                     for (int i = 0; i < count; i++)
80                     {
81                         var item = WaveOut.GetCapabilities(i);
82                         result.Add(i, item);
83                     }
84                 }
85                 catch { }
86                 return result;
87             }
88         }
89     }
90 
91     public enum PCMPlayerChannel
92     {
93         Left,
94         Right,
95         Both
96     }
View Code

 

预告:下一篇简单讲一下音频流网络传输时压缩与解压(基于NSpeex的音频10倍压缩,肉耳听不出损耗)

posted on 2019-08-23 20:48  yunxizfj  阅读(2590)  评论(1编辑  收藏  举报