Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在Flatter应用程序中使用Android NDK中的AssetManager类_C++_Flutter_Android Ndk_Oboe_Dart Ffi - Fatal编程技术网

C++ 在Flatter应用程序中使用Android NDK中的AssetManager类

C++ 在Flatter应用程序中使用Android NDK中的AssetManager类,c++,flutter,android-ndk,oboe,dart-ffi,C++,Flutter,Android Ndk,Oboe,Dart Ffi,我一直在尝试在我的Flitter应用程序中使用Android NDK类来访问音频文件。以下是双簧管存储库中的示例,我了解到他们从Java获取AssetManager,如下所示: JNIEXPORT void JNICALL Java_com_google_oboe_sample_rhythmgame_MainActivity_native_1onStart(JNIEnv *env, jobject instance,

我一直在尝试在我的Flitter应用程序中使用Android NDK类来访问音频文件。以下是双簧管存储库中的示例,我了解到他们从Java获取
AssetManager
,如下所示:

JNIEXPORT void JNICALL
Java_com_google_oboe_sample_rhythmgame_MainActivity_native_1onStart(JNIEnv *env, jobject instance,
                                                                     jobject jAssetManager) {

    AAssetManager *assetManager = AAssetManager_fromJava(env, jAssetManager);
    if (assetManager == nullptr) {
        LOGE("Could not obtain the AAssetManager");
        return;
    }

    game = std::make_unique<Game>(*assetManager);
    game->start();
}
下面是该函数的省道包装器:

EXTERNC void *engine_create(void) {
    AAssetManager *assetManager = AAssetManager_fromJava(env, jAssetManager);   // ERROR: How do I get these?
    if (assetManager == nullptr) {
        LOGE("Could not obtain the AAssetManager");
        return nullptr;
    }   

    return new DSPAudioEngine(*assetManager);
}
import 'dart:ffi';
import 'dart:typed_data';

import 'package:ffi/ffi.dart';
import 'package:flutter/services.dart';

typedef oboe_engine_init = Pointer<Void> Function();
typedef OboeEngineInit = Pointer<Void> Function();

class FfiGoogleOboe {
  static const MethodChannel _channel =
      const MethodChannel('ffi_google_oboe');

  static Future<String> get platformVersion async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }

  static FfiGoogleOboe _instance;

  factory FfiGoogleOboe() {
    if (_instance == null) {
      _instance = FfiGoogleOboe._();
    }
    return _instance;
  }


  OboeEngineInit _engineInit;

  FfiGoogleOboe._() {
    final oboeLib = DynamicLibrary.open('libffi_google_oboe.so');

    _engineInit = oboeLib
        .lookup<NativeFunction<oboe_engine_init>>('engine_create')
        .asFunction();
  }

}
最后,这里是来自双簧管的人员如何使用JNI和Java处理它:

package com.google.oboe.sample.rhythmgame;

import android.content.Context;
import android.content.res.AssetManager;
import androidx.appcompat.app.AppCompatActivity;

import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.view.WindowManager;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setDefaultStreamValues(this);
    }

    protected void onResume(){
        super.onResume();
        native_onStart(getAssets());
    }

    protected void onPause(){
        super.onPause();
        native_onStop();
    }

    static void setDefaultStreamValues(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
            AudioManager myAudioMgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
            String sampleRateStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
            int defaultSampleRate = Integer.parseInt(sampleRateStr);
            String framesPerBurstStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
            int defaultFramesPerBurst = Integer.parseInt(framesPerBurstStr);

            native_setDefaultStreamValues(defaultSampleRate, defaultFramesPerBurst);
        }
    }

    private native void native_onStart(AssetManager assetManager);
    private native void native_onStop();
    private static native void native_setDefaultStreamValues(int defaultSampleRate,
                                                      int defaultFramesPerBurst);
}

基本上,您需要从插件的Kotlin文件传递ASESTMAMER引用到C++库。这个答案解释了如何使Kotlin文件调用C++代码:

您需要使用methodChannel调用来触发此操作。您可以从
flatterpluginbinding.applicationContext.assets
获取onAttachedToEngine方法中的AssetManager引用

这是一个示例FLASH插件,它读取C++库中的一个资产:


我认为,您最初使用RootBundle加载资产,然后使用ffi将字节传递给C的方法要容易得多。我得出了相同的结论。我想消除读取错误文件的可能性(特别是如果文件像mp3一样被压缩),并且由于我在Dart中找不到库来从
.wav
.mp3
获取PCM数据,我想以双簧管为例。但是,我没有找到一种方法来处理颤动,所以我现在要做的是把一个字节缓冲区向下传递到C++,使用<代码> ROOT Cube ,然后从那里解码。基本上,我试图重新实现方法:(AAssetManager和assetManager、大小镜头、音频属性*输出属性)使用
float*buffer
而不是
AAssetManager&assetManager
。我指的方法是在文件第31行。从Dart中的WAV获取PCM很容易,mp3不是很多,因此您可能希望使用AMediaCodec,并使用资产字节支持的自定义数据源。请参阅:并且您希望使用uint_8 buffer作为t他输入,而不是浮动,因为这是您将从资产中读取并使用ffi传递的内容。
package com.google.oboe.sample.rhythmgame;

import android.content.Context;
import android.content.res.AssetManager;
import androidx.appcompat.app.AppCompatActivity;

import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.view.WindowManager;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setDefaultStreamValues(this);
    }

    protected void onResume(){
        super.onResume();
        native_onStart(getAssets());
    }

    protected void onPause(){
        super.onPause();
        native_onStop();
    }

    static void setDefaultStreamValues(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
            AudioManager myAudioMgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
            String sampleRateStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
            int defaultSampleRate = Integer.parseInt(sampleRateStr);
            String framesPerBurstStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
            int defaultFramesPerBurst = Integer.parseInt(framesPerBurstStr);

            native_setDefaultStreamValues(defaultSampleRate, defaultFramesPerBurst);
        }
    }

    private native void native_onStart(AssetManager assetManager);
    private native void native_onStop();
    private static native void native_setDefaultStreamValues(int defaultSampleRate,
                                                      int defaultFramesPerBurst);
}