2015-03-11 5 views
5

Ho importato con successo il progetto Superpowered SDK CrossExample in Android Studio e l'ho testato su Samsung Galaxy S3 ed emulatore. Ora sto implementando un'opzione di registrazione per registrare l'audio riprodotto dall'app utilizzando SuperpoweredRecorder.h. Avrò bisogno di aiuto su come impostare correttamente le variabili *tempPath e *destinationPath per salvare correttamente la registrazione. Il progetto si basa su OK, ma quando cerco di eseguire l'app sul Galaxy S3 o sull'emulatore viene visualizzato il seguente messaggio di errore: 19565-19565/com.superpowered.crossexample A/libc﹕ Fatal signal 11 (SIGSEGV) at 0x006f0070 (code=1), thread 19565 (ed.crossexample) Questo errore si è verificato dopo l'aggiunta di * puntatori tempPath e * destinationPath quindi credo dopo aver impostato correttamente i percorsi di registrazione, questo errore non sarà più disponibile.SDK superpowered: implementazione di SuperpoweredRecorder.h e impostazione dei percorsi di registrazione

Il link alla documentazione SuperpoweredRecorder.h: http://superpowered.com/docs/class_superpowered_recorder.html Se si guarda alla documentazione che altro devo aggiungere al codice per utilizzare tempPath e destinationPath variabili?

Il codice aggiunto tra le doppie barre in avanti.

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"); 
} 
} 
+0

hai risolto? –

+0

senza risoluzione –

+0

Sto affrontando lo stesso problema, hai trovato aiuto o risolto ???? –

risposta

2

Se stai ricevendo un errore di segmentazione, è probabile che l'applicazione doesn' t dichiarare l'autorizzazione WRITE_EXTERNAL_STORAGE (che non corrisponde a CrossExample, poiché non sta scrivendo nulla). Se persiste, la directory contenente potrebbe non esistere, ad es. "/ Sdcard/inesistente/out".

1

Mi rendo conto che è molto tardi, ma se è inutile, credo che sia corretto; Tuttavia, a partire dall'API 23, non è sufficiente avere solo il permesso WRITE_EXTERNAL_STORAGE all'interno del tuo manifest. Sarà inoltre necessario verificare esplicitamente e chiedere questa autorizzazione a causa dei nuovi modelli di autorizzazioni. Durante lo sviluppo puoi anche accedere alla pagina delle informazioni app-> permessi per la tua app e abilitare manualmente l'autorizzazione lì (supponendo che si trovi nel tuo manifest).

Ho avuto un errore di sega fino a quando ho fatto l'ultimo passaggio e ora non succede più.

Spero che questo aiuti qualcuno confuso come lo ero io.

Problemi correlati