1

NDK と 100% ネイティブ コードを使用して構築しているオーディオ サンプラー アプリ用に、SD カードから wav ファイルを読み込もうとしています。サンプルパスを含む事前定義された配列を反復処理し、後で OpenSL によって再生されるように、それぞれ個別にデータバッファーにストリームするメソッドがあります。

次の方法を使用して、ファイルをアセットとしてロードしたとき:

int open_asset(AAssetManager* mgr, char* filename, int samp)
{

    assert(NULL != mgr);
    AAsset *asset = AAssetManager_open(mgr, filename, AASSET_MODE_BUFFER);

    __android_log_write(ANDROID_LOG_DEBUG, "ASSET", "AAssetManager_open");

    if (NULL == asset)
    {
        __android_log_write(ANDROID_LOG_DEBUG, "ASSET", "Asset not found, loading aborted.");
        return JNI_FALSE;
    }

    oneshot_samples[samp].buffer_header = (unsigned short*) malloc(HEADER_SIZE);
    AAsset_read(asset, oneshot_samples[samp].buffer_header, HEADER_SIZE);

    unsigned short* fmttype;
    unsigned long* databytes;

    fmttype = (oneshot_samples[samp].buffer_header + 10);

    if (*fmttype != 0x1)
    {
        __android_log_write(ANDROID_LOG_DEBUG, "ASSET", "*fmttype not PCM, loading aborted.");
        return JNI_FALSE;
    }

    databytes = (oneshot_samples[samp].buffer_header + 20);

    oneshot_samples[samp].data_size = *databytes;

    oneshot_samples[samp].buffer_data = (unsigned short*) malloc(*databytes);
    AAsset_seek(asset, HEADER_SIZE, SEEK_SET);
    AAsset_read(asset, oneshot_samples[samp].buffer_data, oneshot_samples[samp].data_size);

    __android_log_print(ANDROID_LOG_DEBUG, "ASSET", "*fmttype: %x", *fmttype);
    __android_log_print(ANDROID_LOG_DEBUG, "ASSET", "*databytes: %x", *databytes);

    AAsset_close(asset);

    __android_log_write(ANDROID_LOG_DEBUG, "ASSET", "AAsset_close(asset)");

    return JNI_TRUE;
}

問題なくロードされます。しかし、私のアプリでは、ユーザーが SD カードからもサンプルを読み取れるようにしたいと考えています。ファイル パスを SD カードのハード コードされた場所に変更し (テスト用)、fopen() と fread() を使用して次の方法を試しました。

void open_external_file(char* filepath, int samp)
{

    FILE* fp;
    oneshot_samples[samp].buffer_header = (unsigned short*) malloc(HEADER_SIZE);

    __android_log_print(ANDROID_LOG_DEBUG, "open_external_file",
                        "filepath: %s", filepath);

    __android_log_print(ANDROID_LOG_DEBUG, "open_external_file",
                        "size of filepath: %d", sizeof filepath);

    if ((fp = fopen(filepath, "r")) != NULL)
    {
        __android_log_write(ANDROID_LOG_DEBUG, "open_external_file", "fopen()");

        fread(oneshot_samples[samp].buffer_header, sizeof(unsigned short), HEADER_SIZE, fp);
    }

    unsigned short* fmttype;
    unsigned long* databytes;

    fmttype = (oneshot_samples[samp].buffer_header + 10);

    if (*fmttype != 0x1)
    {
        __android_log_write(ANDROID_LOG_DEBUG, "open_external_file", "*fmttype not PCM, loading aborted.");
    }

    databytes = (oneshot_samples[samp].buffer_header + 20);
    oneshot_samples[samp].data_size = *databytes;
    oneshot_samples[samp].buffer_data = (unsigned short*) malloc(*databytes);

    __android_log_print(ANDROID_LOG_DEBUG, "open_external_file", "*fmttype: %x", *fmttype);
    __android_log_print(ANDROID_LOG_DEBUG, "open_external_file", "*databytes: %x", *databytes);


    fseek(fp , HEADER_SIZE , SEEK_SET);
    fread(oneshot_samples[samp].buffer_data, sizeof(unsigned short), oneshot_samples[samp].data_size, fp);

    fclose(fp);
    __android_log_write(ANDROID_LOG_DEBUG, "open_external_file", "fclose(fp);");
}

これにより、恐ろしい ANR と避けられないクラッシュが発生します。

06-06 11:42:30.915: I/dalvikvm(7222): threadid=3: シグナル 3 に反応 06-06 11:42:30.915: A/libc(7222): 致命的なシグナル 11 (SIGSEGV) at 0x0000000c (コード=1)

しかし、奇妙なことに、それは一見かなりランダムに発生するということです。36 個の奇妙なサンプルがあり、エラーは 4 回目以降に表示されることもあれば、20 回程度後に表示されることもあります。このスレッドを読んだ後、セグメンテーション違反の可能性があるようですが、どのように発生するのか、または2つの方法の違いが何であるかについて、私は途方に暮れています.

ファイル ヘッダーの値 *fmttype および *databytes は、毎回 100% 正しく返されます。

私はCに非常に慣れていないので、明らかに間違ったことをしている可能性が非常に高いです.経験豊富な誰かが原因を明らかにすることができれば、本当に感謝しています.

更新: AAsset_read() を使用して元に戻しましたが、まだ取得しています:

06-06 12:33:50.393: I/dalvikvm(9755): threadid=3: シグナル 3 に反応 06-06 12:33:50.393: I/dalvikvm(9755): スタック トレースを '/data/anr/ traces.txt'

ただし、ファイルは毎回正常に読み込まれ、アプリはクラッシュしません。テスト サンプルの合計サイズは、512 MB のテスト タブレットで 48.4 MB です。これが問題の原因でしょうか? それでも、AAsset_read() を使用するとどのように違いが生じるかわかりません。

4

1 に答える 1