在 Unity 中,如何根据响度将用户的声音从麦克风中分割出来?



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

如果沉默至少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)时,我得到的是最近 10 秒的声音数据(如果fdata足够大)或短于 10 秒(如果fdata不够大),对吗?

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

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

  1. 否,您必须使用Microphone.GetPositionAudioClip内的当前位置开始阅读

    获取录音样本中的位置。

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

    使用 offsetSamples 参数从剪辑中的特定位置开始读取

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

    浮子范围从-1.0f1.0f(AudioClip.GetData)

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

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

    但请注意,Convert.ToUInt16(float)

    值,舍入为最接近的 16 位无符号整数。如果值介于两个整数之间,则返回偶数;也就是说,4.5 转换为 4,5.5 转换为 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.2f,而aCertainLoudThreshold可能是例如0.8f

最新更新