Android: начальный вызов метода обработки звука занимает много времени

У меня возникает очень своеобразная проблема с обратными вызовами аудио в моем приложении для Android (использующем NDK/OpenSL ES). Я вывожу потоковое аудио с частотой 44,1 кГц и 512 кадрами (что дает мне время обратного вызова 11,6 мс). В обратном вызове я синтезирую пару сигналов, фильтров и т. д. (как синтезатор). Из-за оптимизации я никогда не превышаю 5 мс времени обратного вызова. Однако, когда я включаю определенный эффект (цифровую линию задержки), обратный вызов начинает занимать значительно больше времени. Цифровая линия задержки подскочит с 7,5 мс (после обработки всех голосов/фильтров) до 100–350 мс.

Это самая запутанная часть; примерно через 1 или 2 секунды время выполнения цифровой задержки подскочит с очень высокого значения до времени завершения 0,2 мс для каждого обратного вызова.

Почему Android-приложению потребовалось много времени, чтобы завершить мой код обработки цифровой задержки для первых нескольких обратных вызовов, а затем утихнуть до очень короткого и приятного для звука времени? Я сейчас немного в растерянности и не знаю, как это исправить. Чтобы подтвердить, это происходит только с методом обработки задержки. Это просто стандартная цифровая линия задержки (вы можете найти ее на github), и я чувствую, что алгоритм здесь не проблема...

Что-то вроде псевдокода/грубого наброска того, как выглядит мой аудио код обратного вызова:

static bool myAudioCallback(void *userData, short int *audIO, int numSamples, int srate) {
     AudioData *data = (AudioData *)userData;
     // Resets pointer array values to 0
     for (int i = 0; i < numSamples; i++) data->buffer[i] = 0;
     // Voice Generation Block
     for (int voice = 0; voice < data->numVoices; voice++) {
          // Reset voice buffers:
          for (int i = 0; i < numSamples; i++) data->voiceBuffer[i] = 0;
          // Generate Voice
          data->voiceManager[voice]->generateVoiceBlock(data->voiceBuffer, numSamples);
          // Sum voices
          for (int i = 0; i < numSamples; i++) data->buffer[i] += data->voiceBuffer[i]];
     }

     // When app first starts, delayEnabled = false so user must click on a  
     // button on the UI to enable it.
     // Trouble is that when we enable processDelay(double *buffer, in frames) the 
     // first time, we get a long execution time.
     if (data->delayEnabled) {
          data->delay->processDelay(data->buffer, numSamples);
     }

    // Conversion loop
    for (int i = 0; i < numSamples; i++) {
        double sample = clipOutput(data->buffer[i]);
        audIO[2*i] = audIO[(2*i)+1] = CONV_FLT_TO_16BIT(sample * data->volume);
    }
}

Спасибо!


person yun    schedule 07.11.2016    source источник


Ответы (1)


Не лучший ответ на решение, но вот что я сделал:

Прежде чем пользователь сможет что-либо сделать в приложении, я включил задержку и дал ей поработать примерно 2 секунды, прежде чем отключить ее. Это позволяет обратному вызову выполнять свое странное долгое время выполнения 300 мс, не разрушая при этом звук.

Очевидно, что это не очень хороший ответ, и если кто-нибудь сможет найти более логичное объяснение, я был бы более чем счастлив отметить это как ответ.

person yun    schedule 08.11.2016