В Unity, как сегментировать голос пользователя с микрофона на основе громкости? - PullRequest
0 голосов
/ 18 апреля 2019

Мне нужно собрать голосовые фрагменты из непрерывного аудиопотока.Мне нужно позже обработать голосовой фрагмент пользователя, который только что сказал (не для распознавания речи).Я сосредотачиваюсь только на сегментации голоса на основе его громкости.

Если после хотя бы 1 секунды молчания его голос на некоторое время становится достаточно громким, а затем снова молчит в течение как минимум 1 секунды, яскажем, это предложение, и голос должен быть сегментирован здесь.

Я просто знаю, что могу получить необработанные аудиоданные из AudioClip, созданного Microphone.Start().Я хочу написать некоторый код, подобный этому:

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), что яget - это последние 10 секунд звуковых данных, если fdata достаточно большой или короче, чем 10 секунд, если fdata не достаточно большой, верно?

  2. fdata - массив с плавающей запятой, и мне нужен 16-битный 16-битный PCM-буфер 16 кГц.Правильно ли конвертировать данные, например: u16data[i] = fdata[i] * 65535?

  3. Как правильно определять громкие и тихие моменты в fdata?

1 Ответ

1 голос
/ 18 апреля 2019
  1. Нет.Вы должны прочитать, начиная с текущей позиции в пределах AudioClip, используя Microphone.GetPosition

    Получить позицию в сэмплах записи.

    и передайте открытый индекс в AudioClip.GetData

    Используйте параметр offsetSamples, чтобы начать чтение с определенной позиции в клипе

    fdata = new float[clip.samples * clip.channels];
    
    var currentIndex = Microphone.GetPosition(null);
    audio.GetData(fdata, currentIndex);
    
  2. Я не понимаю, для чего именно вы конвертируете это.fdata будет содержать

    с плавающей запятой в диапазоне от -1.0f до 1.0f (AudioClip.GetData)

    , так что если по какой-то причине вынеобходимо получить значения между short.MinValue (= -32768) и short.MaxValue (= 32767) , чем да, вы можете сделать это, используя

    *Однако 1046 *

    обратите внимание, что значение 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.0f до 1.0f.

    так что "громкий" момент был бы там, где

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

    "молчаливый" момент был бы там, где

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

, где aCertainSiltenThreshold мог бынапример, быть 0.2f и aCertainLoudThreshold может быть, например, 0.8f.

...