2015-03-11 13 views
5

Ich habe SuperPowered SDK CrossExample Projekt erfolgreich in Android Studio importiert und es auf Samsung Galaxy S3 und Emulator getestet. Jetzt implementiere ich eine Record-Option, um Audio aufzunehmen, das von der App mit SuperpoweredRecorder.h abgespielt wird. Ich benötige Hilfe, um die Variablen *tempPath und *destinationPath korrekt zu setzen, um die Aufzeichnung erfolgreich zu speichern. Das Projekt baut OK auf, aber wenn ich versuche, die App auf dem Galaxy S3 oder im Emulator auszuführen, erhalte ich folgende Fehlermeldung: 19565-19565/com.superpowered.crossexample A/libc﹕ Fatal signal 11 (SIGSEGV) at 0x006f0070 (code=1), thread 19565 (ed.crossexample) Dieser Fehler trat nach dem Hinzufügen von * tempPath und * destinationPath-Zeigern, so glaube ich Nach dem erfolgreichen Einrichten der Aufzeichnungspfade ist dieser Fehler verschwunden.Superpowered SDK: Implementieren von SuperpoweredRecorder.h und Einrichten von Aufnahmepfaden

Der Link zu SuperpoweredRecorder.h Dokumentation: http://superpowered.com/docs/class_superpowered_recorder.html Wenn in der Dokumentation suchen, was sonst muss ich den Code hinzufügen müssen tempPath und destinationPath Variablen zu benutzen?

Der Code selbst hinzugefügt ist zwischen zwei Schrägstriche vorwärts.

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

haben Sie das gelöst? –

+0

noch keine Auflösung –

+0

Ich bin mit dem gleichen Problem konfrontiert, haben Sie Hilfe gefunden oder es zu beheben ???? –

Antwort

2

Wenn Sie einen Segmentation Fault bekommen, ist es wahrscheinlich, dass Ihre Anwendung doesn‘ t deklarieren Sie die WRITE_EXTERNAL_STORAGE Erlaubnis (die CrossExample nicht, wie es schreibt nichts. Wenn es bestehen bleibt, kann das enthaltende Verzeichnis nicht existieren - z. "/ SD-Karte/nicht vorhanden/aus".

1

Ich weiß, das ist sehr spät, aber wenn es irgendeinen Nutzen hat, glaube ich, dass moe korrekt ist; Ab API 23 reicht es jedoch nicht aus, nur die Berechtigung WRITE_EXTERNAL_STORAGE in Ihrem Manifest zu haben. Aufgrund der neuen Berechtigungsmodelle müssen Sie auch explizit nach dieser Berechtigung suchen und danach fragen. Während der Entwicklung können Sie auch auf die App-Seite mit den Berechtigungen für Ihre App gehen und die Berechtigung dort manuell aktivieren (vorausgesetzt, sie befindet sich in Ihrem Manifest).

Ich hatte einen seg Fehler, bis ich diesen letzten Schritt gemacht habe und es jetzt nicht mehr passiert.

Ich hoffe, das hilft jemandem so verwirrt wie ich war.