unity-game-engine - 在Unity中,如何根据响度分割来自麦克风的用户声音?

标签 unity-game-engine audio-recording

我需要从连续的音频流中收集语音片段。我需要稍后处理用户刚才所说的语音片段(不是用于语音识别)。我关注的只是基于声音响度的语音分割。

如果在至少1秒的沉默之后,他的声音变得足够大一段时间,然后又沉默了至少1秒,我说这是一个句子,声音应该在这里分段。

我只知道我可以从 Microphone.Start() 创建的 AudioClip 获取原始音频数据。我想写一些这样的代码:

void Start()
{
    audio = Microphone.Start(deviceName, true, 10, 16000);
}

void Update()
{
    audio.GetData(fdata, 0);
    for(int i = 0; i < fdata.Length; i++) {
        u16data[i] = Convert.ToUInt16(fdata[i] * 65535);
    }
    // ... Process u16data
}

但我不确定的是:

  1. 每一帧,当我调用audio.GetData(fdata, 0)时,如果fdata足够大,我得到的是最新10秒的声音数据或者如果fdata不够大,则少于10秒,对吗?

  2. fdata 是一个 float 组,我需要的是一个 16 kHz、16 位 PCM 缓冲区。像这样转换数据是否正确:u16data[i] = fdata[i] * 65535

  3. 检测 fdata 中大声时刻和沉默时刻的正确方法是什么?

最佳答案

  1. 没有。您必须使用 Microphone.GetPositionAudioClip 中的当前位置开始阅读

    Get the position in samples of the recording.

    并将获得的索引传递给 AudioClip.GetData

    Use the offsetSamples parameter to start the read from a specific position in the clip

    fdata = new float[clip.samples * clip.channels];
    
    var currentIndex = Microphone.GetPosition(null);
    audio.GetData(fdata, currentIndex);
    
  2. 我不明白你到底将其转换为什么。 fdata 将包含

    floats ranging from -1.0f to 1.0f (AudioClip.GetData)

    因此,如果由于某种原因您需要获取 short.MinValue (= -32768) 之间的值和 short.MaxValue(= 32767)是的,您可以使用

    来做到这一点
    u16data[i] = Convert.ToUInt16(fdata[i] * short.MaxValue);
    

    但请注意 Convert.ToUInt16(float) :

    value, rounded to the nearest 16-bit unsigned integer. If value is halfway between two whole numbers, the even number is returned; that is, 4.5 is converted to 4, and 5.5 is converted to 6.

    您可能更想使用Mathf.RoundToInt如果某个值是例如,则首先进行四舍五入4.5

    u16data[i] = Convert.ToUInt16(Mathf.RoundToInt(fdata[i] * short.MaxValue));
    

    但是,您的命名表明您实际上正在尝试获取无符号值ushort(或UInt16)。为此,您不能值!因此,您必须向上移动浮点值才能将范围 (-1.0f | 1.0f ) 映射到范围 (0.0f | 1.0f) 在通过 ushort.MaxValue(= 65535) 多重播放之前

    u16data[i] = Convert.ToUInt16(Mathf.RoundToInt(fdata[i] + 1) / 2 * ushort.MaxValue);
    
  3. 您从 AudioClip.GetData 收到的内容是 -1.0f1.0f 之间音轨的增益值。

    所以“大声”的时刻就是这样的

    Mathf.Abs(fdata[i]) >= aCertainLoudThreshold;
    

    “沉默”的时刻就是这样

    Mathf.Abs(fdata[i]) <= aCertainSiltenThreshold;
    

其中aCertainSiltenThreshold可能例如例如,为 0.2faCertainLoudThreshold0.8f

关于unity-game-engine - 在Unity中,如何根据响度分割来自麦克风的用户声音?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55746995/

相关文章:

c# - Unity/C# 中的三角形

c# - Admob 横幅广告在 Unity3D 中无法正常工作

objective-c - 如何保存音调和速度变化的iOS音频?

android - Unity 使用什么默认 keystore 进行 apk 签名?

ios - 在后处理中启用 Unity3D xCode 项目的功能

c# - 使用 Unity 5.3.5 从 Rails 4.2.5.1 应用程序检索数据

delphi - 如何在 Delphi 中使用 TMediaPlayer 从麦克风输入录制音频?

python - 使用 Python 使用音频传输数据

ios - 同时录制和播放音频

android - 如何自动限制Android录音长度?