Superpowered SDK CrossExample projesini android stüdyosuna başarıyla aktardım ve Samsung galaxy S3 ve emülatörde test ettim. Artık SuperpoweredRecorder.h kullanarak uygulamanın oynadığı sesi kaydetmek için bir kayıt seçeneği uyguluyorum. Kaydı başarıyla kaydetmek için *tempPath
ve *destinationPath
değişkenlerini doğru şekilde nasıl ayarlayacağınız konusunda yardıma ihtiyacım olacak. Proje tamam, ancak ben Galaxy S3 veya emülatörde uygulamayı çalıştırmaya çalıştığımda aşağıdaki hata iletisini alıyorum: 19565-19565/com.superpowered.crossexample A/libc﹕ Fatal signal 11 (SIGSEGV) at 0x006f0070 (code=1), thread 19565 (ed.crossexample)
Bu hatayı * tempPath ve * destinationPath işaretçileri ekledikten sonra oluştu, bu yüzden inanıyorum Kayıt yollarını başarıyla ayarladıktan sonra bu hata gider.Superpowered SDK: SuperpoweredRecorder.h'nin uygulanması ve kayıt yollarının ayarlanması
SuperpoweredRecorder.h belgelerine linki: http://superpowered.com/docs/class_superpowered_recorder.html başka ben tempPath
ve destinationPath
değişkenleri kullanmak koduna eklemek zorunda ne belgelerine bakarak?
Kendim eklenmiş kod ileri çift eğik çizgi arasındadır.
SuperpoweredExample.h
#ifndef Header_SuperpoweredExample
#define Header_SuperpoweredExample
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <math.h>
#include <pthread.h>
#include "SuperpoweredExample.h"
#include "SuperpoweredAdvancedAudioPlayer.h"
#include "SuperpoweredFilter.h"
#include "SuperpoweredRoll.h"
#include "SuperpoweredFlanger.h"
#include "SuperpoweredMixer.h"
#include "SuperpoweredRecorder.h"
#define NUM_BUFFERS 2
#define HEADROOM_DECIBEL 3.0f
static const float headroom = powf(10.0f, -HEADROOM_DECIBEL * 0.025);
class SuperpoweredExample {
public:
SuperpoweredExample(const char *path, int *params);
~SuperpoweredExample();
void process(SLAndroidSimpleBufferQueueItf caller);
void onPlayPause(bool play);
void onCrossfader(int value);
void onFxSelect(int value);
void onFxOff();
void onFxValue(int value);
//Added function declaration
void onRecord(bool record);
//
private:
SLObjectItf openSLEngine, outputMix, bufferPlayer;
SLAndroidSimpleBufferQueueItf bufferQueue;
SuperpoweredAdvancedAudioPlayer *playerA, *playerB;
SuperpoweredRoll *roll;
SuperpoweredFilter *filter;
SuperpoweredFlanger *flanger;
SuperpoweredStereoMixer *mixer;
SuperpoweredRecorder *recorder;
//added object variables
const char *tempPath;
const char *destinationPath;
//
unsigned char activeFx;
float crossValue, volA, volB;
pthread_mutex_t mutex;
float *outputBuffer[NUM_BUFFERS];
int currentBuffer, buffersize;
};
#endif
SuperpoweredExample.cpp
#include "SuperpoweredExample.h"
#include <jni.h>
#include <stdlib.h>
#include <stdio.h>
#include <android/log.h>
static void playerEventCallbackA(void *clientData, SuperpoweredAdvancedAudioPlayerEvent event, void *value) {
if (event == SuperpoweredAdvancedAudioPlayerEvent_LoadSuccess) {
SuperpoweredAdvancedAudioPlayer *playerA = * ((SuperpoweredAdvancedAudioPlayer **)clientData);
playerA->setBpm(126.0f);
playerA->setFirstBeatMs(353);
playerA->setPosition(playerA->firstBeatMs, false, false);
};
}
static void playerEventCallbackB(void *clientData, SuperpoweredAdvancedAudioPlayerEvent event, void *value) {
if (event == SuperpoweredAdvancedAudioPlayerEvent_LoadSuccess) {
SuperpoweredAdvancedAudioPlayer *playerB = *((SuperpoweredAdvancedAudioPlayer **)clientData);
playerB->setBpm(123.0f);
playerB->setFirstBeatMs(40);
playerB->setPosition(playerB->firstBeatMs, false, false);
};
}
static void openSLESCallback(SLAndroidSimpleBufferQueueItf caller, void *pContext) {
((SuperpoweredExample *)pContext)->process(caller);}
static const SLboolean requireds[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
SuperpoweredExample::SuperpoweredExample(const char *path, int *params) : currentBuffer(0), buffersize(params[5]), activeFx(0), crossValue(0.0f), volB(0.0f), volA(1.0f * headroom) {
pthread_mutex_init(&mutex, NULL); // This will keep our player volumes and playback states in sync.
for (int n = 0; n < NUM_BUFFERS; n++) outputBuffer[n] = (float *)memalign(16, (buffersize + 16) * sizeof(float) * 2);
unsigned int samplerate = params[4];
playerA = new SuperpoweredAdvancedAudioPlayer(&playerA , playerEventCallbackA, samplerate, 0);
playerA->open(path, params[0], params[1]);
playerB = new SuperpoweredAdvancedAudioPlayer(&playerB, playerEventCallbackB, samplerate, 0);
playerB->open(path, params[2], params[3]);
playerA->syncMode = playerB->syncMode = SuperpoweredAdvancedAudioPlayerSyncMode_TempoAndBeat;
roll = new SuperpoweredRoll(samplerate);
filter = new SuperpoweredFilter(SuperpoweredFilter_Resonant_Lowpass, samplerate);
flanger = new SuperpoweredFlanger(samplerate);
mixer = new SuperpoweredStereoMixer();
//Create SuperpoweredRecorder and allocate memory for it
recorder = new SuperpoweredRecorder(tempPath, samplerate);
//
// Create the OpenSL ES engine.
slCreateEngine(&openSLEngine, 0, NULL, 0, NULL, NULL);
(*openSLEngine)->Realize(openSLEngine, SL_BOOLEAN_FALSE);
SLEngineItf openSLEngineInterface = NULL;
(*openSLEngine)->GetInterface(openSLEngine, SL_IID_ENGINE, &openSLEngineInterface);
// Create the output mix.
(*openSLEngineInterface)->CreateOutputMix(openSLEngineInterface, &outputMix, 0, NULL, NULL);
(*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE);
SLDataLocator_OutputMix outputMixLocator = { SL_DATALOCATOR_OUTPUTMIX, outputMix };
// Create the buffer queue player.
SLDataLocator_AndroidSimpleBufferQueue bufferPlayerLocator = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS };
SLDataFormat_PCM bufferPlayerFormat = { SL_DATAFORMAT_PCM, 2, samplerate * 1000, SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, SL_BYTEORDER_LITTLEENDIAN };
SLDataSource bufferPlayerSource = { &bufferPlayerLocator, &bufferPlayerFormat };
const SLInterfaceID bufferPlayerInterfaces[1] = { SL_IID_BUFFERQUEUE };
SLDataSink bufferPlayerOutput = { &outputMixLocator, NULL };
(*openSLEngineInterface)->CreateAudioPlayer(openSLEngineInterface, &bufferPlayer, &bufferPlayerSource, &bufferPlayerOutput, 1, bufferPlayerInterfaces, requireds);
(*bufferPlayer)->Realize(bufferPlayer, SL_BOOLEAN_FALSE);
// Initialize and start the buffer queue.
(*bufferPlayer)->GetInterface(bufferPlayer, SL_IID_BUFFERQUEUE, &bufferQueue);
(*bufferQueue)->RegisterCallback(bufferQueue, openSLESCallback, this);
memset(outputBuffer[0], 0, buffersize * 4);
memset(outputBuffer[1], 0, buffersize * 4);
(*bufferQueue)->Enqueue(bufferQueue, outputBuffer[0], buffersize * 4);
(*bufferQueue)->Enqueue(bufferQueue, outputBuffer[1], buffersize * 4);
SLPlayItf bufferPlayerPlayInterface;
(*bufferPlayer)->GetInterface(bufferPlayer, SL_IID_PLAY, &bufferPlayerPlayInterface);
(*bufferPlayerPlayInterface)->SetPlayState(bufferPlayerPlayInterface, SL_PLAYSTATE_PLAYING);
}
SuperpoweredExample::~SuperpoweredExample() {
for (int n = 0; n < NUM_BUFFERS; n++) free(outputBuffer[n]);
delete playerA;
delete playerB;
delete mixer;
pthread_mutex_destroy(&mutex);
}
void SuperpoweredExample::onPlayPause(bool play) {
pthread_mutex_lock(&mutex);
if (!play) {
playerA->pause();
playerB->pause();
} else {
bool masterIsA = (crossValue <= 0.5f);
playerA->play(!masterIsA);
playerB->play(masterIsA);
};
pthread_mutex_unlock(&mutex);
}
//onRecord function
void SuperpoweredExample::onRecord(bool record) {
pthread_mutex_lock(&mutex);
if (!record) {
recorder->stop();
} else {
recorder->start(destinationPath);
};
pthread_mutex_unlock(&mutex);
}
//
void SuperpoweredExample::onCrossfader(int value) {
pthread_mutex_lock(&mutex);
crossValue = float(value) * 0.01f;
if (crossValue < 0.01f) {
volA = 1.0f * headroom;
volB = 0.0f;
} else if (crossValue > 0.99f) {
volA = 0.0f;
volB = 1.0f * headroom;
} else { // constant power curve
volA = cosf(M_PI_2 * crossValue) * headroom;
volB = cosf(M_PI_2 * (1.0f - crossValue)) * headroom;
};
pthread_mutex_unlock(&mutex);
}
void SuperpoweredExample::onFxSelect(int value) {
__android_log_print(ANDROID_LOG_VERBOSE, "SuperpoweredExample", "FXSEL %i", value);
activeFx = value;
}
void SuperpoweredExample::onFxOff() {
filter->enable(false);
roll->enable(false);
flanger->enable(false);
}
#define MINFREQ 60.0f
#define MAXFREQ 20000.0f
static inline float floatToFrequency(float value) {
if (value > 0.97f) return MAXFREQ;
if (value < 0.03f) return MINFREQ;
value = powf(10.0f, (value + ((0.4f - fabsf(value - 0.4f)) * 0.3f)) * log10f(MAXFREQ - MINFREQ)) + MINFREQ;
return value < MAXFREQ ? value : MAXFREQ;
}
void SuperpoweredExample::onFxValue(int ivalue) {
float value = float(ivalue) * 0.01f;
switch (activeFx) {
case 1:
filter->setResonantParameters(floatToFrequency(1.0f - value), 0.2f);
filter->enable(true);
flanger->enable(false);
roll->enable(false);
break;
case 2:
if (value > 0.8f) roll->beats = 0.0625f;
else if (value > 0.6f) roll->beats = 0.125f;
else if (value > 0.4f) roll->beats = 0.25f;
else if (value > 0.2f) roll->beats = 0.5f;
else roll->beats = 1.0f;
roll->enable(true);
filter->enable(false);
flanger->enable(false);
break;
default:
flanger->setWet(value);
flanger->enable(true);
filter->enable(false);
roll->enable(false);
};
}
void SuperpoweredExample::process(SLAndroidSimpleBufferQueueItf caller) {
pthread_mutex_lock(&mutex);
float *stereoBuffer = outputBuffer[currentBuffer];
bool masterIsA = (crossValue <= 0.5f);
float masterBpm = masterIsA ? playerA->currentBpm : playerB->currentBpm;
double msElapsedSinceLastBeatA = playerA->msElapsedSinceLastBeat; // When playerB needs it, playerA has already stepped this value, so save it now.
bool silence = !playerA->process(stereoBuffer, false, buffersize, volA, masterBpm, playerB->msElapsedSinceLastBeat);
if (playerB->process(stereoBuffer, !silence, buffersize, volB, masterBpm, msElapsedSinceLastBeatA)) silence = false;
roll->bpm = flanger->bpm = masterBpm; // Syncing fx is one line.
if (roll->process(silence ? NULL : stereoBuffer, stereoBuffer, buffersize) && silence) silence = false;
if (!silence) {
filter->process(stereoBuffer, stereoBuffer, buffersize);
flanger->process(stereoBuffer, stereoBuffer, buffersize);
//adding buffer to process function
recorder->process(stereoBuffer, 0, buffersize);
//
};
pthread_mutex_unlock(&mutex);
// The stereoBuffer is ready now, let's put the finished audio into the requested buffers.
if (silence) memset(stereoBuffer, 0, buffersize * 4); else SuperpoweredStereoMixer::floatToShortInt(stereoBuffer, (short int *)stereoBuffer, buffersize);
(*caller)->Enqueue(caller, stereoBuffer, buffersize * 4);
if (currentBuffer < NUM_BUFFERS - 1) currentBuffer++; else currentBuffer = 0;
}
extern "C" {
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_SuperpoweredExample(JNIEnv *javaEnvironment, jobject self, jstring apkPath, jlongArray offsetAndLength);
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_onPlayPause(JNIEnv *javaEnvironment, jobject self, jboolean play);
//connect onRecord with java
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_onRecord(JNIEnv *javaEnvironment, jobject self, jboolean record);
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_onCrossfader(JNIEnv *javaEnvironment, jobject self, jint value);
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_onFxSelect(JNIEnv *javaEnvironment, jobject self, jint value);
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_onFxOff(JNIEnv *javaEnvironment, jobject self);
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_onFxValue(JNIEnv *javaEnvironment, jobject self, jint value);
}
static SuperpoweredExample *example = NULL;
// Android is not passing more than 2 custom parameters, so we had to pack file offsets and lengths into an array.
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_SuperpoweredExample(JNIEnv *javaEnvironment, jobject self, jstring apkPath, jlongArray params) {
// Convert the input jlong array to a regular int array.
jlong *longParams = javaEnvironment->GetLongArrayElements(params, JNI_FALSE);
int arr[6];
for (int n = 0; n < 6; n++) arr[n] = longParams[n];
javaEnvironment->ReleaseLongArrayElements(params, longParams, JNI_ABORT);
const char *path = javaEnvironment->GetStringUTFChars(apkPath, JNI_FALSE);
example = new SuperpoweredExample(path, arr);
javaEnvironment->ReleaseStringUTFChars(apkPath, path);
}
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_onPlayPause(JNIEnv *javaEnvironment, jobject self, jboolean play) {
example->onPlayPause(play);
}
//connect onRecord with java code
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_onRecord(JNIEnv *javaEnvironment, jobject self, jboolean record) {
example->onRecord(record);
}
//
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_onCrossfader(JNIEnv *javaEnvironment, jobject self, jint value) {
example->onCrossfader(value);
}
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_onFxSelect(JNIEnv *javaEnvironment, jobject self, jint value) {
example->onFxSelect(value);
}
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_onFxOff(JNIEnv *javaEnvironment, jobject self) {
example->onFxOff();
}
JNIEXPORT void Java_com_superpowered_crossexample_MainActivity_onFxValue(JNIEnv *javaEnvironment, jobject self, jint value) {
example->onFxValue(value);
}
MainActivity.java
package com.superpowered.crossexample;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import java.io.IOException;
public class MainActivity extends ActionBarActivity {
boolean playing = false;
//Added variable
boolean recording = false;
//
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get the device's sample rate and buffer size to enable low-latency Android audio output, if available.
String samplerateString = null, buffersizeString = null;
if (Build.VERSION.SDK_INT >= 17) {
AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
samplerateString = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
buffersizeString = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
}
if (samplerateString == null) samplerateString = "44100";
if (buffersizeString == null) buffersizeString = "512";
// Files under res/raw are not compressed, just copied into the APK. Get the offset and length to know where our files are located.
AssetFileDescriptor fd0 = getResources().openRawResourceFd(R.raw.lycka), fd1 = getResources().openRawResourceFd(R.raw.nuyorica);
long[] params = {
fd0.getStartOffset(),
fd0.getLength(),
fd1.getStartOffset(),
fd1.getLength(),
Integer.parseInt(samplerateString),
Integer.parseInt(buffersizeString)
};
try {
fd0.getParcelFileDescriptor().close();
fd1.getParcelFileDescriptor().close();
} catch (IOException e) {}
// Arguments: path to the APK file, offset and length of the two resource files, sample rate, audio buffer size.
SuperpoweredExample(getPackageResourcePath(), params);
// crossfader events
final SeekBar crossfader = (SeekBar)findViewById(R.id.crossFader);
crossfader.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
onCrossfader(progress);
}
public void onStartTrackingTouch(SeekBar seekBar) {}
public void onStopTrackingTouch(SeekBar seekBar) {}
});
// fx fader events
final SeekBar fxfader = (SeekBar)findViewById(R.id.fxFader);
fxfader.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
onFxValue(progress);
}
public void onStartTrackingTouch(SeekBar seekBar) {
onFxValue(seekBar.getProgress());
}
public void onStopTrackingTouch(SeekBar seekBar) {
onFxOff();
}
});
// fx select event
final RadioGroup group = (RadioGroup)findViewById(R.id.radioGroup1);
group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
RadioButton checkedRadioButton = (RadioButton)radioGroup.findViewById(checkedId);
onFxSelect(radioGroup.indexOfChild(checkedRadioButton));
}
});
}
public void SuperpoweredExample_PlayPause(View button) { // Play/pause.
playing = !playing;
onPlayPause(playing);
Button b = (Button) findViewById(R.id.playPause);
b.setText(playing ? "Pause" : "Play");
}
//Added the following Record method
public void SuperpoweredExample_Record(View button) { // Record/Stop Recording.
recording = !recording;
onRecord(recording);
Button r = (Button) findViewById(R.id.rec);
r.setText(recording ? "Start Recording" : "Stop Recording");
}
//
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private native void SuperpoweredExample(String apkPath, long[] offsetAndLength);
private native void onPlayPause(boolean play);
private native void onCrossfader(int value);
private native void onFxSelect(int value);
private native void onFxOff();
private native void onFxValue(int value);
//Added the following line
private native void onRecord(boolean record);
//
static {
System.loadLibrary("SuperpoweredExample");
}
}
bunu çözdünüz mü? –
Çözünürlük yok –
Aynı konuyla karşı karşıyayım, herhangi bir yardım buldunuz mu ya da tamir ettiniz ???? –