Superpowered: не удается заставить TimeStretching работать правильно, выходной звук искажен - PullRequest
0 голосов
/ 19 октября 2018

Я пытаюсь использовать Superpowered SDK , чтобы применить растягивание в реальном времени и изменение высоты тона к файлу mp3, который воспроизводится и одновременно записывается.Проблема в том, что независимо от того, что я делаю, качество звука на выходе ужасное (до такой степени, что оно искажается).
Я подозреваю, что это из-за конфликтующих выборок на номер кадра.Вот полный исходный код моего файла cpp:

static SuperpoweredAndroidAudioIO *audioIO;
static SuperpoweredTimeStretching *stretching;
static SuperpoweredAudiopointerList *outputBuffers;
static SuperpoweredDecoder *decoder;
static SuperpoweredRecorder *recorder;
const char *outFilePath;
const char *tempFilePath;

static short int *intBuffer;
static float *playerBuffer;

bool audioInitialized = false;
bool playing = false;

static bool audioProcessing(
        void *__unused clientData, // custom pointer
        short int *audio,           // buffer of interleaved samples
        int numberOfFrames,         // number of frames to process
        int __unused sampleRate     // sampling rate
) {

    if (playing) {
        unsigned int samplesDecoded = decoder->samplesPerFrame;
        if (decoder->decode(intBuffer, &samplesDecoded) == SUPERPOWEREDDECODER_ERROR) return false;
        if (samplesDecoded < 1) {
            playing = false;
            return false;
        }



        SuperpoweredAudiobufferlistElement inputBuffer;
        inputBuffer.samplePosition = decoder->samplePosition;
        inputBuffer.startSample = 0;
        inputBuffer.samplesUsed = 0;
        inputBuffer.endSample = samplesDecoded;
        inputBuffer.buffers[0] = SuperpoweredAudiobufferPool::getBuffer(samplesDecoded * 8 + 64);
        inputBuffer.buffers[1] = inputBuffer.buffers[2] = inputBuffer.buffers[3] = NULL;


        SuperpoweredShortIntToFloat(intBuffer, (float *) inputBuffer.buffers[0], samplesDecoded);

        stretching->process(&inputBuffer, outputBuffers);

        if (outputBuffers->makeSlice(0, outputBuffers->sampleLength)) {

            while (true) { 
                int numSamples = 0;
                float *timeStretchedAudio = (float *) outputBuffers->nextSliceItem(&numSamples);
                if (!timeStretchedAudio) break;

                SuperpoweredFloatToShortInt(timeStretchedAudio, intBuffer,
                                            (unsigned int) numSamples);
                SuperpoweredShortIntToFloat(intBuffer, playerBuffer, (unsigned int) numSamples);

                recorder->process(playerBuffer, (unsigned int) numSamples);
                SuperpoweredFloatToShortInt(playerBuffer, audio, (unsigned int) numSamples);

            };
            outputBuffers->clear();
            return true;
        };
    }
    return false;
}


extern "C" JNIEXPORT void
Java_com_example_activities_DubsmashActivity_InitAudio(
        JNIEnv  __unused *env,
        jobject  __unused obj,
        jint bufferSize,
        jint sampleRate,
        jstring outputPath,
        jstring tempPath
) {

    decoder = new SuperpoweredDecoder();

    outputBuffers = new SuperpoweredAudiopointerList(8, 16);

    outFilePath = env->GetStringUTFChars(outputPath, 0);
    tempFilePath = env->GetStringUTFChars(tempPath, 0);

}

extern "C" JNIEXPORT jdouble
Java_com_example_activities_DubsmashActivity_OpenFile(
        JNIEnv *env,
        jobject  __unused obj,
        jstring filePath) {
    const char *path = env->GetStringUTFChars(filePath, 0);
    decoder->open(path);
    intBuffer = (short int *) malloc(decoder->samplesPerFrame * 2 * sizeof(short int) + 32768);
    playerBuffer = (float *) malloc(decoder->samplesPerFrame * 2 * sizeof(short int) + 32768);
    audioIO = new SuperpoweredAndroidAudioIO(
            decoder->samplerate,
            decoder->samplesPerFrame,
            false,
            true,
            audioProcessing,
            NULL,
            -1, -1,
            decoder->samplesPerFrame * 2
    );

    stretching = new SuperpoweredTimeStretching(decoder->samplerate);

    stretching->setRateAndPitchShift(1, 0);

    recorder = new SuperpoweredRecorder(
            tempFilePath,              
            decoder->samplerate,  
            1,                  
            2,                  
            false,             
            recorderStopped,    
            NULL               
    );

    return 0;
}

Некоторые замечания для рассмотрения:

  1. Это не дубликат этого вопроса , так какрешение в этой теме не работает для меня
  2. Я пытался играть с decoder->samplesPerFrame и numSamples, но не могу получить приличный вывод.
  3. Если я установлюTime Stretching до 1 и Pitch Shift до 0, звук воспроизводится плавно.

UPDATE 1:
После еще нескольких манипуляций и воспроизведения с различными значениями для номерасэмплов, я решил, что проблема должна заключаться в разнице между количеством сэмплов, которое ожидает аудиовыход ( DAC MAN ), и количеством, которое фактически обеспечивает outputBuffers->nextSliceItem.
Сказав, что я могуПодумайте, как можно решить эту проблему, добавив вывод outputBuffers->nextSliceItem во временный буфер, а затем, когда он достигнет порогового значения, направьте его на аудиовыход.

Отсюда мой второй вопрос: Есть ли способ в C ++ добавить буфер в другой буфер?

1 Ответ

0 голосов
/ 26 октября 2018

Вам необходимо вывести audioProcessing (int numberOfFrames) количество кадров.Поэтому в outputBuffers-> makeSlice вам нужно задать число numberOfFrames, а не outputBuffers-> sampleLength (в основном вы запрашиваете «любое количество кадров в outputBuffers», а не «numberOfFrames»).

Затем вы конвертируете из float вint, затем обратно, чтобы плавать?Это не имеет смысла.Вы получили аудио с плавающей запятой в timeStretchedAudio, которое может быть немедленно обработано вашим рекордером.

После этого вы забыли переместить «аудио» вперед после преобразования в него сэмплов с плавающей запятой.

Инаконец, вы удаляете все аудио из outputBuffers, в то время как вам нужно удалить только количество кадров, которые вы выводите в «audio».

...