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_channel
和reference_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
方法的返回值,确保重采样操作成功。 - 性能优化:可以考虑使用更高效的重采样算法或库,以提高重采样的性能。
- 代码复用:可以将双声道数据分离和合并的逻辑封装成独立的函数,提高代码的复用性。