小智机器人关键函数解析,Application::InputAudio()处理麦克风音频数据输入的函数

发布于:2025-03-31 ⋅ 阅读:(20) ⋅ 点赞:(0)

Application::InputAudio(),这段代码定义了 Application 类中的 InputAudio 方法,其主要功能是从音频编解码器(AudioCodec)读取音频数据,根据采样率和声道数进行重采样处理,然后将处理后的数据分别传递给音频处理器(audio_processor_)和唤醒词检测器(wake_word_detect_)。
源码:

void Application::InputAudio() {
    auto codec = Board::GetInstance().GetAudioCodec();
    std::vector<int16_t> data;
    if (!codec->InputData(data)) { // 从I2S通道中读取数据,并返回数据长度
        return;
    }

    if (codec->input_sample_rate() != 16000) {
        if (codec->input_channels() == 2) {
            auto mic_channel = std::vector<int16_t>(data.size() / 2);
            auto reference_channel = std::vector<int16_t>(data.size() / 2);
            for (size_t i = 0, j = 0; i < mic_channel.size(); ++i, j += 2) {
                mic_channel[i] = data[j];
                reference_channel[i] = data[j + 1];
            }
            auto resampled_mic = std::vector<int16_t>(input_resampler_.GetOutputSamples(mic_channel.size()));
            auto resampled_reference = std::vector<int16_t>(reference_resampler_.GetOutputSamples(reference_channel.size()));
            input_resampler_.Process(mic_channel.data(), mic_channel.size(), resampled_mic.data());
            reference_resampler_.Process(reference_channel.data(), reference_channel.size(), resampled_reference.data());
            data.resize(resampled_mic.size() + resampled_reference.size());
            for (size_t i = 0, j = 0; i < resampled_mic.size(); ++i, j += 2) {
                data[j] = resampled_mic[i];
                data[j + 1] = resampled_reference[i];
            }
        } else {
            auto resampled = std::vector<int16_t>(input_resampler_.GetOutputSamples(data.size()));
            input_resampler_.Process(data.data(), data.size(), resampled.data());
            data = std::move(resampled); // 将从采样的数据移到data向量中
        }
    }
   
    if (audio_processor_.IsRunning()) {
        audio_processor_.Input(data); // 数据进行前端处理
    }
    if (wake_word_detect_.IsDetectionRunning()) {
        wake_word_detect_.Feed(data);
    }
}

以下是对代码的详细解析:

函数定义和整体功能

void Application::InputAudio() {
  • 定义了 Application 类的成员函数 InputAudio,该函数不接受参数,返回类型为 void,用于处理音频输入。

获取音频编解码器实例并读取数据

    auto codec = Board::GetInstance().GetAudioCodec();
    std::vector<int16_t> data;
    if (!codec->InputData(data)) { // 从I2S通道中读取数据,并返回数据长度
        return;
    }
  • Board::GetInstance().GetAudioCodec():通过单例模式获取 Board 类的实例,然后调用其 GetAudioCodec 方法获取音频编解码器的实例。
  • std::vector<int16_t> data;:创建一个 std::vector 用于存储从音频编解码器读取的音频数据。
  • codec->InputData(data):调用音频编解码器的 InputData 方法从I2S通道读取数据到 data 向量中。如果读取失败,函数直接返回。

重采样处理

    if (codec->input_sample_rate() != 16000) {
        if (codec->input_channels() == 2) {
            auto mic_channel = std::vector<int16_t>(data.size() / 2);
            auto reference_channel = std::vector<int16_t>(data.size() / 2);
            for (size_t i = 0, j = 0; i < mic_channel.size(); ++i, j += 2) {
                mic_channel[i] = data[j];
                reference_channel[i] = data[j + 1];
            }
            auto resampled_mic = std::vector<int16_t>(input_resampler_.GetOutputSamples(mic_channel.size()));
            auto resampled_reference = std::vector<int16_t>(reference_resampler_.GetOutputSamples(reference_channel.size()));
            input_resampler_.Process(mic_channel.data(), mic_channel.size(), resampled_mic.data());
            reference_resampler_.Process(reference_channel.data(), reference_channel.size(), resampled_reference.data());
            data.resize(resampled_mic.size() + resampled_reference.size());
            for (size_t i = 0, j = 0; i < resampled_mic.size(); ++i, j += 2) {
                data[j] = resampled_mic[i];
                data[j + 1] = resampled_reference[i];
            }
        } else {
            auto resampled = std::vector<int16_t>(input_resampler_.GetOutputSamples(data.size()));
            input_resampler_.Process(data.data(), data.size(), resampled.data());
            data = std::move(resampled); // 将从采样的数据移到data向量中
        }
    }
  • 检查采样率:如果音频编解码器的输入采样率不是16000Hz,则需要进行重采样处理。
  • 双声道处理:如果输入是双声道音频,将左右声道数据分离到 mic_channelreference_channel 向量中,分别对两个声道进行重采样处理,最后将重采样后的声道数据合并回 data 向量。
  • 单声道处理:如果输入是单声道音频,直接对 data 向量进行重采样处理,并将重采样后的数据移动到 data 向量中。

数据处理和唤醒词检测

    if (audio_processor_.IsRunning()) {
        audio_processor_.Input(data); // 数据进行前端处理
    }
    if (wake_word_detect_.IsDetectionRunning()) {
        wake_word_detect_.Feed(data);
    }
  • 音频处理:如果音频处理器正在运行,将处理后的数据传递给音频处理器进行前端处理。
  • 唤醒词检测:如果唤醒词检测器正在运行,将处理后的数据传递给唤醒词检测器进行检测。

代码优化建议

  • 错误处理:在重采样处理过程中,可以添加更多的错误处理逻辑,例如检查 input_resampler_reference_resampler_Process 方法的返回值,确保重采样操作成功。
  • 性能优化:可以考虑使用更高效的重采样算法或库,以提高重采样的性能。
  • 代码复用:可以将双声道数据分离和合并的逻辑封装成独立的函数,提高代码的复用性。