首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【愚公系列】2023年08月 .NET/C#知识点-即时语音的通信解析

【愚公系列】2023年08月 .NET/C#知识点-即时语音的通信解析

作者头像
愚公搬代码
发布2025-05-28 17:21:29
发布2025-05-28 17:21:29
3330
举报
文章被收录于专栏:历史专栏历史专栏

前言

即时语音是指通过网络或互联网实时通信的语音通话服务。通常使用VoIP(Voice over Internet Protocol)技术,即通过将语音转换为数字信号,通过互联网传输,接收方再将数字信号转换回语音。这种通信形式可以在任何具有互联网连接的设备上进行,如计算机、智能手机、平板电脑等。即时语音通常是一种免费或低成本的通信方式,已经成为人们经常使用的通信方式之一。

即时语音通话广泛应用于各种场合和领域,包括但不限于:

  1. 社交网络:如Facebook、微信、WhatsApp等;
  2. 网络游戏:玩家之间通过语音实时进行游戏配合和沟通;
  3. 远程办公:公司员工通过即时语音进行远程协作和会议;
  4. 在线教育:学生和老师通过语音实现在线教学和互动;
  5. 客服服务:企业通过即时语音与客户实行快速的在线服务;
  6. 医疗卫生:医生和患者进行远程医疗咨询和诊断。

即时语音的优势包括:

  1. 实时性强:即时语音通话可以在几乎瞬间完成,比发送信息更加方便快捷。
  2. 更好的沟通效果:语音通话能够传递更多的信息,包括语调、情感等,让交流更加自然流畅,减少了信息传递误解的可能性。
  3. 更高的人际交往效果:语音通话比文字交流更能够提升人际交往效果,增强了人际关系的亲密度和信任。
  4. 可以节省成本:即时语音通话可以在任何地方通过网络实现,节省了电话费和长途费用。
  5. 便携性:即时语音通话可以在各种设备上进行,如智能手机、平板电脑、电脑等,非常灵活方便。

一、即时语音的通信解析

实现语音聊天的步骤可以分为以下几个部分:

  1. 音频采集:使用C#中提供的音频采集库或API,通过麦克风采集用户的音频输入。可以使用Windows自带的WASAPI (Windows Audio Session API)或第三方库如NAudio来实现。
  2. 音频编码:将采集到的音频数据进行编码,以便传输或存储。常用的音频编码算法包括PCM、AAC、MP3等。你可以使用C#中的音频编码库或者调用第三方库来实现。
  3. 音频传输:将编码后的音频数据传输给对方进行实时的语音聊天。可以通过网络传输,使用TCP或UDP协议进行传输。你可以使用C#中的网络编程库来实现。
  4. 音频解码:对方接收到音频数据后,需要进行解码还原成原始的音频数据。同样可以使用C#中的音频解码库或第三方库来实现。
  5. 音频播放:将解码后的音频数据进行播放,让用户听到对方的声音。可以使用C#中的音频播放库或第三方库进行播放。

请注意,语音聊天涉及到音频数据的处理和网络传输,实现起来可能需要涉及到多个方面的知识和技术。这只是一个一般性的步骤指导,具体的实现细节可能因具体的需求和使用的库而有所不同。希望对你有帮助!如果你还有其他问题,可以继续问我。

1.音频采集

1.1 NAudio介绍

NAudio是一个用于处理音频的开源.NET库,常用的类型如下:

  1. WaveFormat:用于描述音频采样率、位深、编码格式和通道数等信息,是NAudio中最基础的类型。
  2. WaveInEvent:代表音频输入设备,可以从麦克风、线路输入等设备中捕获音频数据。
  3. WaveOutEvent:代表音频输出设备,可以将音频数据播放到扬声器、耳机等输出设备中。
  4. WaveFileReaderWaveFileWriter:用于读取和写入音频文件。
  5. WaveChannel32:实现音频数据的混音、音量调节、平衡等操作。
  6. SampleProvider:提供音频数据的数据流,可用于实现音频数据的处理和转换。
  7. Mp3FileReader:用于读取MP3格式的音频文件。
  8. MediaFoundationReader:用于读取Windows Media Audio (WMA)、Advanced Audio Coding (AAC)、Audio Interchange File Format (AIFF)、MPEG-4 Part 14 (MP4)等常见音频格式的文件。

以上仅列举了常用的NAudio类型,实际上NAudio还提供了许多其他类型和功能,比如音频特效处理、音频录制和播放的API等。若想深入了解NAudio的使用方法,建议参考官方文档和示例代码。

1.1 NAudio实现音频采集

C#可以通过使用NAudio库来实现音频采集。

以下是一个基本的示例,实现了从麦克风捕获音频并在控制台输出:

代码语言:javascript
复制
private readonly WaveIn _waveIn;
_waveIn = new WaveIn();
_waveIn.BufferMilliseconds = 50;
_waveIn.DeviceNumber = 0;
_waveIn.DataAvailable += OnAudioCaptured;
_waveIn.StartRecording();

该示例中使用的WaveIn 类代表音频输入设备,并且可以设置音频捕获的相关参数。DataAvailable事件将在每次捕获到音频数据时触发,可以将数据通过事件参数e.Buffer获取。

你可以在DataAvailable事件处理程序中编写自己的逻辑,对音频数据进行处理或者保存。

2.音频编码

在C#中实现音频编码需要使用特定的编码库或API。以下是一些常用的编码方法:

  1. 使用NAudio库:NAudio是一个强大的音频库,可以用于播放、录制、编码和解码音频文件。它支持多种常用的音频格式,包括MP3、WAV、AAC等。你可以在你的C#项目中使用NAudio,以实现音频编码。
  2. 使用FFmpeg:FFmpeg是一个跨平台的音视频处理库。它可以用来进行编码、解码、转码等操作,支持多种音频格式,包括MP3、WAV、AAC等。你可以在你的C#项目中使用FFmpeg的API来进行音频编码。
  3. 使用Windows Media Encoder:Windows Media Encoder是微软提供的一个免费的编码工具,可以将音频文件编码为Windows Media格式。它提供了一个基于图形用户界面的应用程序和一个API,可以用来进行音频编码。

本文主要介绍NAudio实现音频编码

代码语言:javascript
复制
private readonly WideBandSpeexCodec _speexCodec;
_speexCodec = new WideBandSpeexCodec();
_waveIn.WaveFormat = _speexCodec.RecordFormat;
void OnAudioCaptured(object sender, WaveInEventArgs e)
{
     byte[] encoded = _speexCodec.Encode(e.Buffer, 0, e.BytesRecorded);
     _audioClient.Send(encoded);
}

3.音频传输

在C#中,常用的音频传输协议包括:

  1. RTP (Real-time Transport Protocol): 实时传输协议,是一种用于实时传输音频和视频的协议。C#中可以使用第三方库,比如FreeRTP和RtpNet等进行实现。
  2. RTSP (Real-time Streaming Protocol):实时流媒体传输协议,是一种用于流媒体的控制协议。C#中可以使用第三方库,如SharpRTSP和FFmpeg等。
  3. SIP (Session Initiation Protocol):会话发起协议,是一种用于建立、修改和终止会话的协议。C#中可以使用第三方库,如Ozeki VoIP SIP SDK和VaxVoIP等。
  4. WebSocket:WebSocket是一种在单个TCP连接上进行全双工通信的协议。C#中可以使用WebSocketSharp等第三方库进行实现。
  5. Icecast:是一个流媒体服务器,可以用于音频和视频的传输。C#中可以使用第三方库,如Icecast.NET等进行实现。

除此之外,还有一些其他协议和技术可以用于音频传输,比如HTTP、WebRTC、MQTT-SN、XMPP等,不过它们的实现复杂度较高,需要较多的代码和开发经验。

为了保证即时传输WebSocket的udp协议有着天然的优点

代码语言:javascript
复制
using SAEA.Sockets;
using SAEA.Sockets.Base;
using SAEA.Sockets.Model;
using System;
using System.Net;
namespace GFF.Component.GAudio.Net
{
    public class AudioClient
    {
        IClientSocket _udpClient;
        BaseUnpacker _baseUnpacker;
        public event Action<Byte[]> OnReceive;
        public AudioClient(IPEndPoint endPoint)
        {
            var bContext = new BaseContext();
            _udpClient = SocketFactory.CreateClientSocket(SocketOptionBuilder.Instance.SetSocket(SAEASocketType.Udp)
                .SetIPEndPoint(endPoint)
                .UseIocp(bContext)
                .SetReadBufferSize(SocketOption.UDPMaxLength)
                .SetWriteBufferSize(SocketOption.UDPMaxLength)
                .Build());
            _baseUnpacker = (BaseUnpacker)bContext.Unpacker;
            _udpClient.OnReceive += _udpClient_OnReceive;
        }
        private void _udpClient_OnReceive(byte[] data)
        {
            OnReceive?.Invoke(data);
        }
        public void Connect()
        {
            _udpClient.Connect();
        }
        public void Send(byte[] data)
        {
            _udpClient.SendAsync(data);
        }
        public void Disconnect()
        {
            _udpClient.Disconnect();
        }
    }
}

4.服务器转发

代码语言:javascript
复制
using SAEA.Sockets;
using SAEA.Sockets.Base;
using SAEA.Sockets.Interface;
using SAEA.Sockets.Model;
using System;
using System.Collections.Concurrent;
using System.Net;
using System.Threading.Tasks;
namespace GFF.Component.GAudio.Net
{
    public class AudioServer
    {
        IServerSocket _udpServer;
        ConcurrentDictionary<string, IUserToken> _cache;
        public AudioServer(IPEndPoint endPoint)
        {
            _cache = new ConcurrentDictionary<string, IUserToken>();
            _udpServer = SocketFactory.CreateServerSocket(SocketOptionBuilder.Instance.SetSocket(SAEASocketType.Udp)
                .SetIPEndPoint(endPoint)
                .UseIocp<BaseContext>()
                .SetReadBufferSize(SocketOption.UDPMaxLength)
                .SetWriteBufferSize(SocketOption.UDPMaxLength)
                .SetTimeOut(5000)
                .Build());
            _udpServer.OnAccepted += _udpServer_OnAccepted;
            _udpServer.OnDisconnected += _udpServer_OnDisconnected;
            _udpServer.OnReceive += _udpServer_OnReceive;
        }
        public void Start()
        {
            _udpServer.Start();
        }
        public void Stop()
        {
            _udpServer.Stop();
        }
        private void _udpServer_OnReceive(ISession currentSession, byte[] data)
        {
            Parallel.ForEach(_cache.Keys, (id) =>
            {
                try
                {
                    _udpServer.SendAsync(id, data);
                }
                catch { }                
            });
        }
        private void _udpServer_OnAccepted(object obj)
        {
            var ut = (IUserToken)obj;
            if (ut != null)
            {
                _cache.TryAdd(ut.ID, ut);
            }
        }
        private void _udpServer_OnDisconnected(string ID, Exception ex)
        {
            _cache.TryRemove(ID, out IUserToken _);
        }
    }
}

5.解码还原

代码语言:javascript
复制
private readonly BufferedWaveProvider _waveProvider;
_waveProvider = new BufferedWaveProvider(_speexCodec.RecordFormat);
private void _audioClient_OnReceive(byte[] data)
{
     byte[] decoded = _speexCodec.Decode(data, 0, data.Length);
     _waveProvider.AddSamples(decoded, 0, decoded.Length);
}

6.播放音频

代码语言:javascript
复制
private readonly BufferedWaveProvider _waveProvider;
_waveProvider = new BufferedWaveProvider(_speexCodec.RecordFormat);
private void _audioClient_OnReceive(byte[] data)
{
     byte[] decoded = _speexCodec.Decode(data, 0, data.Length);
     _waveProvider.AddSamples(decoded, 0, decoded.Length);
}

二、通信测试

1.客户端封装

代码语言:javascript
复制
GAudioClient _gAudioClient = null;
private void toolStripDropDownButton2_ButtonClick(object sender, EventArgs e)
{
    if (_gAudioClient == null)
    {
        ClientConfig clientConfig = ClientConfig.Instance();
        _gAudioClient = new GAudioClient(clientConfig.IP, clientConfig.Port + 2);
        _gAudioClient.Start();
    }
    else
    {
        _gAudioClient.Dispose();
        _gAudioClient = null;
    }
}

2.服务端封装

代码语言:javascript
复制
ConsoleHelper.WriteLine("正在初始化语音服务器...", ConsoleColor.DarkBlue);
_gAudioServer = new GAudioServer(filePort + 1);
ConsoleHelper.WriteLine("语音服务器初始化完毕...", ConsoleColor.DarkBlue);
ConsoleHelper.WriteLine("正在启动语音服务器...", ConsoleColor.DarkBlue);
_gAudioServer.Start();
ConsoleHelper.WriteLine("语音服务器初始化完毕", ConsoleColor.DarkBlue);
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-08-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、即时语音的通信解析
    • 1.音频采集
      • 1.1 NAudio介绍
      • 1.1 NAudio实现音频采集
    • 2.音频编码
    • 3.音频传输
    • 4.服务器转发
    • 5.解码还原
    • 6.播放音频
  • 二、通信测试
    • 1.客户端封装
    • 2.服务端封装
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档