我正在尝试使用 Superpowered SDK 创建 android 应用程序,这将允许我将麦克风输入重定向到耳机,并为麦克风添加混响效果,以模拟巨大的房间效果。我找到了这个带有代码片段的存储库:https ://bitbucket.org/snippets/kasurd/Mynnp/nativesuperpoweredrecorder-with ,但我无法让它工作。这是我当前的代码:
#include <jni.h>
#include <stdio.h>
#include "SuperpoweredExample.h"
#include <SuperpoweredSimple.h>
#include <SuperpoweredCPU.h>
#include <pthread.h>
#include <malloc.h>
static void playerEventCallback(void *clientData, SuperpoweredAdvancedAudioPlayerEvent event, void * __unused value) {
if (event == SuperpoweredAdvancedAudioPlayerEvent_LoadSuccess) {
SuperpoweredAdvancedAudioPlayer *player = *((SuperpoweredAdvancedAudioPlayer **)clientData);
//player->setBpm(126.0f);
//player->setFirstBeatMs(353);
player->setPosition(player->firstBeatMs, false, false);
}else if (event == SuperpoweredAdvancedAudioPlayerEvent_LoadError) {
} else if (event == SuperpoweredAdvancedAudioPlayerEvent_EOF) {
};
}
static bool audioProcessingPlayback(void *clientdata, short int *audioIO, int numberOfSamples, int samplerate) {
return ((SuperpoweredPlayer *)clientdata)->processPlayback(0, audioIO, numberOfSamples);
}
static bool audioProcessingRecording(void *clientdata, short int *audioIO, int numberOfSamples, int samplerate) {
return ((SuperpoweredPlayer *)clientdata)->processRecording(audioIO, numberOfSamples);
}
bool SuperpoweredPlayer::process(short int *output, unsigned int numberOfSamples) {
bool processResult = player->process(stereoBuffer, false, numberOfSamples);
SuperpoweredFloatToShortInt(stereoBuffer, output, numberOfSamples);
return processResult;
}
static bool audioProcessing(void *clientdata, short int *audioIO, int numberOfSamples, int __unused samplerate) {
return ((SuperpoweredPlayer *)clientdata)->process(audioIO, (unsigned int)numberOfSamples);
}
SuperpoweredPlayer::SuperpoweredPlayer(unsigned int sampleRate, unsigned int bufferSize, const char *path, int fileOffset, int fileLength) {
stereoBuffer = (float *)memalign(16, (bufferSize + 16) * sizeof(float) * 2);
stereoBufferRecording = (float *)memalign(16, (bufferSize + 16) * sizeof(float) * 2);
this->sampleRate = sampleRate;
this->bufferSize = bufferSize;
playerA = NULL;
recorder = NULL;
audioSystemRecording = new SuperpoweredAndroidAudioIO(sampleRate, bufferSize, true, false, audioProcessingRecording, this, bufferSize * 2);
initPlayerA(path, fileOffset, fileLength, 0);
}
void SuperpoweredPlayer::initPlayerA(const char *path, int fileOffset, int fileSize, double startOffsetMs) {
audioSystemA = new SuperpoweredAndroidAudioIO(sampleRate, bufferSize, false, true, audioProcessingPlayback, this, bufferSize * 2);
playerA = new SuperpoweredAdvancedAudioPlayer(&playerA , playerEventCallback, sampleRate, 0);
playerA->open(path, fileOffset, fileSize);
playerA->syncMode = SuperpoweredAdvancedAudioPlayerSyncMode_TempoAndBeat;
}
void SuperpoweredPlayer::playPause(bool play) {
if (!play) {
askPlaying = false;
if (playerA != NULL) {
playerA->pause();
}
} else {
if (playerA != NULL) {
playerA->play(false);
}
askPlaying = true;
};
SuperpoweredCPU::setSustainedPerformanceMode(play);
}
void SuperpoweredPlayer::startRecording(const char *tempPath, const char *destinationPath) {
recorder = new SuperpoweredRecorder(tempPath, sampleRate);
askRecording = true;
recorder->start(destinationPath);
playPause(true);
}
void SuperpoweredPlayer::stopRecording() {
if (!askRecording) {
return;
}
askPlaying = false;
askRecording = false;
recorder->stop();
playPause(false);
}
// method to receive playback parts
bool SuperpoweredPlayer::processPlayback(int playerId, short int *output, unsigned int numberOfSamples) {
pthread_mutex_lock(&mutex);
if (!askPlaying) {
pthread_mutex_unlock(&mutex);
return false;
}
playerA->process(stereoBuffer, false, numberOfSamples, 1.0f, 0.0f, -1.0f);
SuperpoweredFloatToShortInt(stereoBuffer, output, numberOfSamples);
pthread_mutex_unlock(&mutex);
return true;
}
// method to receive recording parts
bool SuperpoweredPlayer::processRecording(short int *input, unsigned int numberOfSamples) {
pthread_mutex_lock(&mutex);
if (askRecording) {
unsigned int data = 0;
SuperpoweredShortIntToFloat(input, stereoBufferRecording, numberOfSamples);
data = recorder->process(stereoBufferRecording, NULL, numberOfSamples);
pthread_mutex_unlock(&mutex);
return true;
}
pthread_mutex_unlock(&mutex);
return false;
}
//void SuperpoweredPlayer::setTempo(double value) {
// player->setTempo(value, true);
//}
SuperpoweredPlayer::~SuperpoweredPlayer() {
delete playerA;
free(stereoBuffer);
pthread_mutex_destroy(&mutex);
}
static SuperpoweredPlayer *player = NULL;
static const char *path;
extern "C" JNIEXPORT void Java_com_example_pc_superpoweredsdk_SuperPoweredPlayerWrapper_SuperpoweredPlayer(JNIEnv *javaEnvironment, jobject __unused obj, jint sampleRate, jint bufferSize, jstring apkPath, jint fileOffset, jint fileLength) {
path = javaEnvironment->GetStringUTFChars(apkPath, JNI_FALSE);
player = new SuperpoweredPlayer((unsigned int)sampleRate, ((unsigned int)bufferSize), path + 'temp.wav', fileOffset, fileLength);
javaEnvironment->ReleaseStringUTFChars(apkPath, path);
}
extern "C" JNIEXPORT void Java_com_example_pc_superpoweredsdk_SuperPoweredPlayerWrapper_playPause(JNIEnv * __unused javaEnvironment, jobject __unused obj, jboolean play) {
player->startRecording(path + 'temp.wav', path + 'dest.wav');
}
sampleRate 是 44100,bufferSize 是 512,路径是 context.getFilesDir().getAbsolutePath()
我现在被困住了,试图弄清楚,我应该如何播放带有混响滤波器的麦克风输入,并以尽可能少的延迟实时播放耳机。