虚幻引擎实时音频采集

Part1前言

虚幻引擎其实对实时音频的采集支持得非常好。不过由于对音频概念的学习,还是花了一些时间进行研究。本文主要介绍如何基于虚幻引擎采集实时麦克风的音频数据。

Part2音频采样率

在虚幻引擎中,我没有找到动态修改音频采样率的方法。下面的方法设置是不行的,不知道有没有哪位高手可以指点一下。虚幻引擎实时音频采集_第1张图片单双通道可以自己进行处理。针对双通道转单通道,可以尝试如下思路。单通道:在单通道PCM数据中,音频样本按时间顺序连续排列。数据流看起来像这样:S1, S2, S3, S4, ...,其中每个S代表一个样本。
双通道:在双通道PCM数据中,通常使用交错排列方式。这意味着左右声道的样本交替出现。数据流看起来像这样:L1, R1, L2, R2, L3, R3, ...,其中L和R分别代表左声道和右声道的样本。
将双通道转成单通道可以尝试如下方案:
单声道样本 = (左声道样本 + 右声道样本) / 2

Part3音频编码字节序

PCM数据可以以大端字节序(Big Endian)或小端字节序(Little Endian)存储
WAV文件通常使用小端字节序
另外 Windows系统使用的是小端字节序(Little Endian)。在小端字节序中,多字节值的低位字节存储在内存中的低地址处,而高位字节则存储在高地址处。
例如,在小端系统中,一个16位整数0x1234将以34 12的形式存储在内存中(假设内存地址从左到右增加):0x34是低位字节,存储在较低的地址,而0x12是高位字节,存储在较高的地址。
所以在虚幻音频当中我就默认小端字节序了。

Part4音频数据保存

在虚幻引擎中使用FFileHelper类写文件时,如果目标文件已经存在,那么默认行为是覆盖该文件。这意味着原始文件的内容将被新内容完全替换。如果你需要根据文件是否存在来采取不同的行动,可以在写文件之前先检查文件是否存在。

#include "HAL/PlatformFilemanager.h"

void AppendOrCreateFile(const FString& FilePath, const TArray& Data)
{
    // 获取平台文件管理器的引用
    IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();

    // 检查文件是否存在
    if (PlatformFile.FileExists(*FilePath))
    {
        // 文件已存在,追加内容
        IFileHandle* FileHandle = PlatformFile.OpenWrite(*FilePath, true);
        if (FileHandle)
        {
            FileHandle->Write(Data.GetData(), Data.Num());
            delete FileHandle; // 关闭文件
        }
    }
    else
    {
        // 文件不存在,创建新文件并写入内容
        FFileHelper::SaveArrayToFile(Data, *FilePath);
    }
}

Part5音频数据采集

主要通过 UAudioCapture 对象进行采集,代码调用也非常简洁。创建一个UAudioCapture对象

m_AudioCapture = UAudioCaptureFunctionLibrary::CreateAudioCapture();

注册音频回调函数

m_AudioGeneratorHandle = m_AudioCapture->AddGeneratorDelegate(MyFunction);

启动音频采集

m_AudioCapture->StartCapturingAudio();

启动成功之后就可以获取到相关音频参数如采样率和通道

auto samplerate =  m_AudioCapture->GetSampleRate();
 auto channelnum = m_AudioCapture->GetNumChannels();

音频处理方面,在回调函数中,音频被设置在0-1之间,如果我们想保存为32bit的音频,可以自己等比例变换。

void ATestVoiceChatAudioCapture::OnAudioGenerate(const float* InAudio, int32 NumSamples)

这里我转成了32bit的pcm编码,转换如下

outAudio[i] = InAudio[i] * MAX_int32;

之后在保存为文件即可。有了实时音频采集的加持,我们可以做很多工作,比如语音识别,语音聊天等等。

Part6关于源码

请关注公众号g0415shenw 加入知识星球。
星球地址 https://t.zsxq.com/15EvfoA7n

你可能感兴趣的:(虚幻,音视频,游戏引擎)