Я пишу аудиоприложение в реальном времени на C++, которое выполняет огромную обработку фрагментов звука длительностью 10 мс. Я использую miniaudio для обработки аудио ввода-вывода. При измерении времени, которое занимает обработка, т. е. записи чисел из следующих значений внутри функции обратного вызова:
std::chrono::high_resolution_clock::time_point begin = std::chrono::high_resolution_clock::now();
process_audio(input, output);
std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
float elapsed_microseconds = (float)std::chrono::duration_cast(end - begin).count();
Один процесс обычно занимает около 2,5 мс, но иногда время сокращается до 1,7 мс и до 4 мс.
Однако, если я сделаю то же самое в сценарии, не работающем в реальном времени (т. е. при загрузке аудиофайла и его обработке в цикле for без функции прерывания/обратного вызова), я получаю числа стабильно около 1,8 мс с очень небольшим отклонением.
Сначала я думал, что это может быть связано с операционной системой, но я наблюдаю то же самое в Windows, Mac и Linux. Я также думал, что это может быть как-то связано с miniaudio, но то же самое происходит и с RtAudio.
Что приводит к тому, что это происходит медленнее и более непредсказуемо внутри функции обратного вызова, и могу ли я что-нибудь сделать, чтобы улучшить его?
РЕДАКТИРОВАТЬ: Вот минимальный пример:
// https://github.com/mackron/miniaudio
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
#include
#include
ma_device_config m_mic_path_config;
ma_device m_mic_device;
int discardCount;
float average_execution_time_usec;
float max_execution_time_usec;
float min_execution_time_usec;
int samples_collected;
float temp = 0;
void zero_vars() {
discardCount = 0;
average_execution_time_usec = 0.0f;
max_execution_time_usec = 0;
min_execution_time_usec = 1000000;
samples_collected = 0;
}
void log_measurement(float elapsed_microseconds) {
// Discard measurements during the first second
if (discardCount < 10){
discardCount++;
}
else {
average_execution_time_usec += elapsed_microseconds;
if (elapsed_microseconds > max_execution_time_usec){
max_execution_time_usec = elapsed_microseconds;
}
if (elapsed_microseconds < min_execution_time_usec){
min_execution_time_usec = elapsed_microseconds;
}
samples_collected++;
}
}
void print_stats() {
printf("Min execution time: %0.2f\n", min_execution_time_usec);
printf("Average execution time: %0.2f\n", average_execution_time_usec / (float) samples_collected);
printf("Max execution time: %0.2f\n", max_execution_time_usec);
printf("Samples collected: %d\n", samples_collected);
}
float beefy_process(float num) {
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
for(int i = 0; i < 200000; i++){
num = num * 1.55;
num = num + 5;
num = num / 2.3;
}
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
float elapsed_microseconds = (float)std::chrono::duration_cast(end - begin).count();
log_measurement(elapsed_microseconds);
return num;
}
void microphone_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) {
temp += beefy_process(5);
}
int start_microphone() {
ma_result result;
m_mic_path_config = ma_device_config_init(ma_device_type_capture);
m_mic_path_config.sampleRate = 48000;
m_mic_path_config.pUserData = nullptr;
m_mic_path_config.capture.pDeviceID = NULL; /* system default microphone */
m_mic_path_config.capture.format = ma_format_s16;
m_mic_path_config.capture.channels = 1;
m_mic_path_config.capture.shareMode = ma_share_mode_shared;
m_mic_path_config.dataCallback = microphone_callback;
result = ma_device_init(NULL, &m_mic_path_config, &m_mic_device);
if (result != MA_SUCCESS)
{
printf("Failed to set up microphone path. Error: %d", result);
assert(0);
return result;
}
result = ma_device_start(&m_mic_device);
if (result != MA_SUCCESS)
{
printf("Failed to start microphone path. Error: %d", result);
assert(0);
return result;
}
return 0;
}
int stop_microphone() {
ma_result result = ma_device_stop(&m_mic_device);
if (result != MA_SUCCESS)
{
printf("Failed to stop microphone path. Error: %d", result);
assert(0);
return result;
}
ma_device_uninit(&m_mic_device);
return 0;
}
int main(int argc, char** argv) {
printf("NON-REALTIME:\n");
zero_vars();
for (int i = 0; i < 300; i++){
temp += beefy_process(5);
}
print_stats();
printf("%f\n", temp); //prevents compiler from optimizing away beefy_process
printf("\nREALTIME:\n");
zero_vars();
start_microphone();
std::this_thread::sleep_for(std::chrono::milliseconds(3 * 1000));
stop_microphone();
print_stats();
printf("%f\n", temp);
return 0;
}
В результате я получаю следующий результат:
NON-REALTIME:
Min execution time: 2004.00
Average execution time: 2494.63
Max execution time: 2987.00
Samples collected: 290
1999.995239
REALTIME:
Min execution time: 2551.00
Average execution time: 3893.67
Max execution time: 4362.00
Samples collected: 291
4006.685547
Подробнее здесь: https://stackoverflow.com/questions/786 ... -to-a-loop
Почему процесс внутри аудиопрерывания/обратного вызова медленнее, чем в цикле? ⇐ C++
Программы на C++. Форум разработчиков
1720472651
Anonymous
Я пишу аудиоприложение в реальном времени на C++, которое выполняет огромную обработку фрагментов звука длительностью 10 мс. Я использую miniaudio для обработки аудио ввода-вывода. При измерении времени, которое занимает обработка, т. е. записи чисел из следующих значений внутри функции обратного вызова:
std::chrono::high_resolution_clock::time_point begin = std::chrono::high_resolution_clock::now();
process_audio(input, output);
std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
float elapsed_microseconds = (float)std::chrono::duration_cast(end - begin).count();
Один процесс обычно занимает около 2,5 мс, но иногда время сокращается до 1,7 мс и до 4 мс.
Однако, если я сделаю то же самое в сценарии, не работающем в реальном времени (т. е. при загрузке аудиофайла и его обработке в цикле for без функции прерывания/обратного вызова), я получаю числа стабильно около 1,8 мс с очень небольшим отклонением.
Сначала я думал, что это может быть связано с операционной системой, но я наблюдаю то же самое в Windows, Mac и Linux. Я также думал, что это может быть как-то связано с miniaudio, но то же самое происходит и с RtAudio.
Что приводит к тому, что это происходит медленнее и более непредсказуемо внутри функции обратного вызова, и могу ли я что-нибудь сделать, чтобы улучшить его?
[b]РЕДАКТИРОВАТЬ:[/b] Вот минимальный пример:
// https://github.com/mackron/miniaudio
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
#include
#include
ma_device_config m_mic_path_config;
ma_device m_mic_device;
int discardCount;
float average_execution_time_usec;
float max_execution_time_usec;
float min_execution_time_usec;
int samples_collected;
float temp = 0;
void zero_vars() {
discardCount = 0;
average_execution_time_usec = 0.0f;
max_execution_time_usec = 0;
min_execution_time_usec = 1000000;
samples_collected = 0;
}
void log_measurement(float elapsed_microseconds) {
// Discard measurements during the first second
if (discardCount < 10){
discardCount++;
}
else {
average_execution_time_usec += elapsed_microseconds;
if (elapsed_microseconds > max_execution_time_usec){
max_execution_time_usec = elapsed_microseconds;
}
if (elapsed_microseconds < min_execution_time_usec){
min_execution_time_usec = elapsed_microseconds;
}
samples_collected++;
}
}
void print_stats() {
printf("Min execution time: %0.2f\n", min_execution_time_usec);
printf("Average execution time: %0.2f\n", average_execution_time_usec / (float) samples_collected);
printf("Max execution time: %0.2f\n", max_execution_time_usec);
printf("Samples collected: %d\n", samples_collected);
}
float beefy_process(float num) {
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
for(int i = 0; i < 200000; i++){
num = num * 1.55;
num = num + 5;
num = num / 2.3;
}
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
float elapsed_microseconds = (float)std::chrono::duration_cast(end - begin).count();
log_measurement(elapsed_microseconds);
return num;
}
void microphone_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) {
temp += beefy_process(5);
}
int start_microphone() {
ma_result result;
m_mic_path_config = ma_device_config_init(ma_device_type_capture);
m_mic_path_config.sampleRate = 48000;
m_mic_path_config.pUserData = nullptr;
m_mic_path_config.capture.pDeviceID = NULL; /* system default microphone */
m_mic_path_config.capture.format = ma_format_s16;
m_mic_path_config.capture.channels = 1;
m_mic_path_config.capture.shareMode = ma_share_mode_shared;
m_mic_path_config.dataCallback = microphone_callback;
result = ma_device_init(NULL, &m_mic_path_config, &m_mic_device);
if (result != MA_SUCCESS)
{
printf("Failed to set up microphone path. Error: %d", result);
assert(0);
return result;
}
result = ma_device_start(&m_mic_device);
if (result != MA_SUCCESS)
{
printf("Failed to start microphone path. Error: %d", result);
assert(0);
return result;
}
return 0;
}
int stop_microphone() {
ma_result result = ma_device_stop(&m_mic_device);
if (result != MA_SUCCESS)
{
printf("Failed to stop microphone path. Error: %d", result);
assert(0);
return result;
}
ma_device_uninit(&m_mic_device);
return 0;
}
int main(int argc, char** argv) {
printf("NON-REALTIME:\n");
zero_vars();
for (int i = 0; i < 300; i++){
temp += beefy_process(5);
}
print_stats();
printf("%f\n", temp); //prevents compiler from optimizing away beefy_process
printf("\nREALTIME:\n");
zero_vars();
start_microphone();
std::this_thread::sleep_for(std::chrono::milliseconds(3 * 1000));
stop_microphone();
print_stats();
printf("%f\n", temp);
return 0;
}
В результате я получаю следующий результат:
NON-REALTIME:
Min execution time: 2004.00
Average execution time: 2494.63
Max execution time: 2987.00
Samples collected: 290
1999.995239
REALTIME:
Min execution time: 2551.00
Average execution time: 3893.67
Max execution time: 4362.00
Samples collected: 291
4006.685547
Подробнее здесь: [url]https://stackoverflow.com/questions/78673096/why-is-a-process-slower-inside-an-audio-interrupt-callback-compared-to-a-loop[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия