1

プロジェクトに OpenSL を使用する必要があります (Soundpool を試しましたが、まったくうまくいきません)。ただし、サウンドを複数回再生した後(連続35回程度)、アプリがシャットダウンします(おそらくオーバーフローのためだと思います)。

問題を解決するためにバッファ/メモリを解放しようとしました(そして、神のために、このOpenSLを使用して行う方法がわかりません)。そのため、ファイルの再生が終了したら解放することにしました。OpenSL ES は、RegisterCallback役立つ機能を提供してくれます。私の場合(URIファイルを使用)、新しい問題が発生し、RegisterCallbackアプリが再びクラッシュしました。行き詰まっています。

これが私のコードです。助けてください。の直後にクラッシュしました//register callback for uri

static short fdBuffer[SAWTOOTH_FRAMES];

// create URI audio player
    jboolean Java_jp_mobigame_ayakashi_CardGameActivity_createUriAudioPlayer(JNIEnv* env, jclass clazz,
            jstring uri)
    {
        __android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "\n createUri \n");
        SLresult result;

        // convert Java string to UTF-8
        const jbyte *utf8 = (*env)->GetStringUTFChars(env, uri, NULL);
        assert(NULL != utf8);

        // configure audio source
        // (requires the INTERNET permission depending on the uri parameter)
        SLDataLocator_URI loc_uri = {SL_DATALOCATOR_URI, (SLchar *) utf8};
        SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
        SLDataSource audioSrc = {&loc_uri, &format_mime};

        // configure audio sink
        SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
        SLDataSink audioSnk = {&loc_outmix, NULL};

        // create audio player
        const SLInterfaceID ids[3] = {SL_IID_SEEK, SL_IID_MUTESOLO /*SL_IID_BUFFERQUEUE*/, SL_IID_VOLUME};
        const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
        result = (*engineEngine)->CreateAudioPlayer(engineEngine, &uriPlayerObject, &audioSrc,
                &audioSnk, 3, ids, req);
        // note that an invalid URI is not detected here, but during prepare/prefetch on Android,
        // or possibly during Realize on other platforms
        assert(SL_RESULT_SUCCESS == result);

        // release the Java string and UTF-8
        (*env)->ReleaseStringUTFChars(env, uri, utf8);

        // realize the player
        result = (*uriPlayerObject)->Realize(uriPlayerObject, SL_BOOLEAN_FALSE);
        // this will always succeed on Android, but we check result for portability to other platforms
        if (SL_RESULT_SUCCESS != result) {
            (*uriPlayerObject)->Destroy(uriPlayerObject);
            uriPlayerObject = NULL;
            return JNI_FALSE;
        }

        // get the play interface
        result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PLAY, &uriPlayerPlay);
        assert(SL_RESULT_SUCCESS == result);

        // get the seek interface
        result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_SEEK, &uriPlayerSeek);
        assert(SL_RESULT_SUCCESS == result);


        __android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "\n createUri 1\n");
        //get the buffer queue interface
        result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &uriPlayerBufferQueue);
        assert(SL_RESULT_SUCCESS == result);
        __android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "\n createUri 2\n");


        //register callback for uri
        result = (*uriPlayerBufferQueue)->RegisterCallback(uriPlayerBufferQueue, bqUriPlayerCallback, NULL);
        assert(SL_RESULT_SUCCESS == result);
        __android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "\n createUri 4\n");

        //Enqueue
        __android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "\n createUri 3\n");
        result = (*uriPlayerBufferQueue)->Enqueue(uriPlayerBufferQueue, fdBuffer, sizeof(fdBuffer));


        // get the mute/solo interface
        result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_MUTESOLO, &uriPlayerMuteSolo);
        assert(SL_RESULT_SUCCESS == result);

        // get the volume interface
        result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_VOLUME, &uriPlayerVolume);
        assert(SL_RESULT_SUCCESS == result);

        return JNI_TRUE;

    }
4

1 に答える 1

1

URI ソースを指定しているにもかかわらず、バッファ キュー インターフェイスを取得しようとしているようです。また、データをエンキューしているようです。uri からオーディオを再生しようとしているだけの場合は、これを行う必要はありません。スピーカーの代わりにバッファに出力しようとしている場合は、これが有効な場合があります。私は決して OpenSL の専門家ではないので、これには理由があるかもしれません。ただし、その理由がない場合は、代わりにプレーヤー オブジェクトにコールバックを登録してみてください。

(*uriPlayerPlay)->RegisterCallback(uriPlayerPlay, bqUriPlayerCallback, NULL);

補足として、おそらくコールバック イベント マスクを設定することをお勧めします。いくつかのオプションがありますが、あなたが探しているものは次のとおりだと思います。

(*uriPlayerPlay)->SetCallbackEventsMask(uriPlayerPlay, SL_PLAYEVENT_HEADATEND)

これにより問題が発生する可能性があることに注意してください。https://groups.google.com/forum/?fromgroups=#!topic/android-ndk/7YaqlKlDMO4を参照してください。

これで解決しない場合は、コールバック関数の定義を確認すると役立つ場合があります。次のようになるはずです。

static void bqUriPlayerCallback (SLPlayItf caller, void *pContext, SLuint32 playevent)
于 2013-03-18T17:54:05.370 に答える