探索生活本源
传递多元价值

Linux开发板实时语音聊天功能:音频处理的技术探索与突破 Linux开发板实时语音聊天功能实现:音频处理难题全攻克

本文围绕在Linux开发板上接入实时语音聊天功能展开,介绍了相关的前置技术基础,以Luckfox开发板为例,着重探讨了音频处理过程中遇到的直流偏移、回声抑制、启动噪声等问题,并给出了相应的解决办法,最后对项目进行了总结和展望。

此前,我们已经探讨了如何运用纯前端技术接入OpenAI的实时语音聊天接口,也掌握了怎样利用.NET在Linux系统上实现基础的语音录制与播放功能,同时还能驱动LCD屏幕进行显示。如今,各项前期准备工作均已就绪,只差关键的一步,那就是将这些技术结合起来,实现在Linux开发板上的实时语音聊天功能。

为了能更好地理解本文的内容,建议大家先回顾一下之前的相关文章。

在这里,我们依旧选用Luckfox开发板作为示例。这款开发板价格实惠,仅需一百多元,而且直接板载了麦克风和扬声器,非常契合实时语音聊天的应用场景。

波形对比

在音频处理过程中,我们遇到了直流偏移的问题。不过,解决这个问题并不困难。当我们使用 alsamixer 进行音频配置时,发现其中有相关的HPF(High Pass Filter)选项,这个选项可以用于去除音频信号中的直流偏移。

alsamixer 的UI界面里,我们可以通过 HPF 选项来开启高通滤波器,以此去除音频信号中的低频成分,进而消除直流偏移。当然,我们也可以直接借助 amixer 命令来设置HPF选项。

需要注意的是,不同的设备可能会存在一些差异,具体的设置大家可以自行尝试。经过这样的处理之后,再次录制音频并发送到服务端,服务端就能够正确解析音频数据了。

4.3 回声抑制

在实时语音聊天中,回声抑制是一项至关重要的技术。它的主要作用是消除扬声器输出的音频信号在麦克风中产生的回声,从而提高语音通话的质量,减少回声和杂音,让通话更加清晰、稳定。当然,回声抑制也是一项较为复杂的技术,如果大家想要了解更多相关内容,可以参考《一文读懂回声消除(AEC)》。

在本项目中,回声问题主要是由于扬声器输出的音频信号在麦克风中产生的回声所导致的。这会出现一种情况,当我们询问一个问题后,服务端会不断地自问自答,不断地打断自己的推理返回结果,这显然不是我们所期望的。所以,我们需要在录制音频时,对音频数据进行回声抑制处理。

不过,在这个项目中,我并没有采用常规的回声抑制处理方法,而是调整了逻辑。在播放音频时,将麦克风静音,这样就有效地避免了回声问题的出现。此外,我们也可以通过调整麦克风和扬声器的位置,来减少回声的产生。后续有时间的话,我会尝试进行回声抑制处理。

4.4 启动噪声

由于 Alsa.Net 库已经很久没有更新了,在使用过程中也频繁出现问题,特别是声道方面的问题。录制和播放单声道音频都会报错,这就需要我们额外占用更多的资源来对音频数据进行加工处理。而且,流式录制和流式播放音频都需要我们自行实现,这无疑是一个比较复杂的问题。

在音频播放的初始版本中,我们实现了流式播放,代码如下:

publicasyncTask PlayAudioAsync(byte[] pcmData){varmonoData = ConvertMonoToStereo(pcmData); _playbackQueue.Enqueue(monoData);

if(!_isPlaying) {_isPlaying = true; awaitTask.Run( => ProcessPlaybackQueue); }}

privatevoidProcessPlaybackQueue{while(_playbackQueue.TryDequeue( outvarpcmData)) {Play(pcmData);}_isPlaying = false; OnPlaybackStopped?.Invoke;}

privatevoidPlay(byte[] pcmData){varwavData = CreateWavHeader( 24000, 16, 2).Concat(pcmData).ToArray; //using var alsaDevice = AlsaDeviceBuilder.Create(_settings);_alsaDevice.Play( newMemoryStream(wavData), _cancellationTokenSourcePlayback.Token); }

privatevoidStopPlayback{_cancellationTokenSourcePlayback?.Cancel;_cancellationTokenSourcePlayback = newCancellationTokenSource; _isPlaying = false; _playbackQueue.Clear;}

然而,在播放音频时,刚开始会出现刺耳的高音异响。这种噪音是由扬声器在刚开始播放音频时产生的杂音所导致的,通常被称为“启动噪声”或“开机噪声”(Power-on Noise)。它一般是由于电路在启动时电压不稳定、瞬态电流变化或扬声器驱动电路的初始化过程引起的。而且,由于服务器的音频是流式传输的,流式播放会导致这种启动噪音一直出现。

为了解决这个问题,我将音频数据保存到文件,然后再进行播放,代码如下:

publicasyncTask PlayAudio(stringaudioId){stringfilePath = $”audio/{audioId}.wav”; if(!File.Exists(filePath)) {return; }awaitTask.Run( =>{ //using var alsaDevice = AlsaDeviceBuilder.Create(_settings);_alsaDevice.Play(filePath, _cancellationTokenSourcePlayback.Token);OnPlaybackStopped?.Invoke;}, _cancellationTokenSourcePlayback.Token); }

采用这种方法后,启动噪声的问题就得到了解决。当然,这样做会增加一些延迟,但对于这个项目来说,这种延迟是可以接受的,也算是一种折中的解决方案。

5. 总结

在这个项目中,主要的难点集中在音频处理方面。再加上硬件设备的限制,使得整个项目变得更加复杂。目前,我们还没有找到合适的、在Linux系统上可靠的音频库,这也引发了很多问题。不过,这也正是技术的魅力所在,我们需要不断地解决问题,不断地学习,才能取得进步。后续有时间的话,我们可以尝试使用其他的音频库,如 PortAudioSharp2,或者对现有的音频库进行优化,解决流式播放等问题。

回首这段项目经历,那些曾经看似棘手的难题,不过是我们在技术探索道路上必须经历的磨炼。通过这个项目,我们学到了很多关于音频处理的知识,也深刻体会到了技术的无穷魅力。虽然一路走来道路曲折,但每一步都弥足珍贵,那些困难也不过是成长路上的些许风霜罢了。

本文围绕在Linux开发板上实现实时语音聊天功能展开,详细阐述了音频处理过程中遇到的直流偏移、回声抑制、启动噪声等问题,并给出了相应的解决办法。项目虽面临诸多困难,但也让我们收获了音频处理的相关知识,后续可尝试其他音频库或优化现有库来解决更多问题。

赞(0)
未经允许不得转载:果源资讯 » Linux开发板实时语音聊天功能:音频处理的技术探索与突破 Linux开发板实时语音聊天功能实现:音频处理难题全攻克

评论 抢沙发