Я пытаюсь использовать 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;
}
Некоторые замечания для рассмотрения:
- Это не дубликат этого вопроса , так какрешение в этой теме не работает для меня
- Я пытался играть с
decoder->samplesPerFrame
и numSamples
, но не могу получить приличный вывод. - Если я установлюTime Stretching до
1
и Pitch Shift до 0
, звук воспроизводится плавно.
UPDATE 1:
После еще нескольких манипуляций и воспроизведения с различными значениями для номерасэмплов, я решил, что проблема должна заключаться в разнице между количеством сэмплов, которое ожидает аудиовыход ( DAC MAN ), и количеством, которое фактически обеспечивает outputBuffers->nextSliceItem
.
Сказав, что я могуПодумайте, как можно решить эту проблему, добавив вывод outputBuffers->nextSliceItem
во временный буфер, а затем, когда он достигнет порогового значения, направьте его на аудиовыход.
Отсюда мой второй вопрос: Есть ли способ в C ++ добавить буфер в другой буфер?