Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/178.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
Java 我的申请赢了';我不能播放我录制的声音_Java_Android_Java Native Interface - Fatal编程技术网

Java 我的申请赢了';我不能播放我录制的声音

Java 我的申请赢了';我不能播放我录制的声音,java,android,java-native-interface,Java,Android,Java Native Interface,在我的应用程序中,我想使用AudioTrack类来播放我录制的一些声音。我通过AudioRecord对象录制音频,读取对象,然后播放录制的声音。但是,我现在编程的方式将导致AudioTrack JNI中出现错误,即“不支持缓冲区直接访问,无法录制” 代码如下所示: public class RecorderThread extends Thread{ private static AudioRecord mAudioRecorder; private final int USE_

在我的应用程序中,我想使用
AudioTrack
类来播放我录制的一些声音。我通过
AudioRecord
对象录制音频,读取对象,然后播放录制的声音。但是,我现在编程的方式将导致
AudioTrack JNI
中出现错误,即“不支持缓冲区直接访问,无法录制”

代码如下所示:

public class RecorderThread extends Thread{
    private static AudioRecord mAudioRecorder;
    private final int USE_MIC = MediaRecorder.AudioSource.MIC;
    private static final int FREQUENCY = 8000;
    private int mBuffSize, mChannel, mEncoding;
    private byte[] mBuffer;
    private Context mContext;
    private volatile boolean mContinueLoop = true,
                             mDataPresent = false,
                             mProcessData = false;

    private BroadcastReceiver mActionListener = new BroadcastReceiver(){
        @Override
        public void onReceive(Context context, Intent intent){
            if(intent.getAction().equals(mContext.getString(R.string.STOP_THREAD))){
                mContinueLoop = false;
                Thread.currentThread().interrupt();
            } else if(intent.getAction().equals(mContext.getString(R.string.START_RECORDING))){
                mAudioRecorder.startRecording();
            }  else if(intent.getAction().equals(mContext.getString(R.string.STOP_RECORDING))){
                mAudioRecorder.stop();
                mDataPresent = true;
            }  else if(intent.getAction().equals(mContext.getString(R.string.PROCESS_DATA))){
                if(mDataPresent){
                    mProcessData = true;
                    mDataPresent = false;
                }
            }  
        }
    };

    public RecorderThread(Context context){
        mContext = context;
        mChannel = AudioFormat.CHANNEL_IN_MONO;
        mEncoding = AudioFormat.ENCODING_PCM_16BIT;
        mBuffSize = AudioRecord.getMinBufferSize(FREQUENCY, mChannel, mEncoding);
        mBuffer = new byte[FREQUENCY * 10];
        mAudioRecorder = new AudioRecord(USE_MIC, FREQUENCY, mChannel, mEncoding, mBuffer.length);

        IntentFilter filter = new IntentFilter();
        filter.addAction(mContext.getString(R.string.START_RECORDING));
        filter.addAction(mContext.getString(R.string.STOP_RECORDING));
        filter.addAction(mContext.getString(R.string.PROCESS_DATA));
        filter.addAction(mContext.getString(R.string.STOP_THREAD));
        mContext.registerReceiver(mActionListener, filter);
    }

    @Override
    public void run(){
        while(mContinueLoop){
            if(mProcessData){
                // Process data.
                ByteBuffer sampledData = ByteBuffer.wrap(mBuffer);
                int readSamples = mAudioRecorder.read(sampledData, sampledData.limit());
                processData(sampledData, readSamples);
                mProcessData = false;
            }
            try{
                Thread.sleep(100);
            } catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        mAudioRecorder.release();
    }

    private void processData(ByteBuffer sampledData, int readSamples) {
        byte[] data = sampledData.array();
        AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,
                                          FREQUENCY,
                                          AudioFormat.CHANNEL_OUT_MONO,
                                          mEncoding,
                                          data.length,
                                          AudioTrack.MODE_STATIC);
        if(track != null){
            track.write(data, 0, data.length);
            track.play();
            track.release();
        }
    }
}

我已经浏览了制作
AudioTrack JNI的本机代码
(http://www.netmite.com/android/mydroid/1.6/frameworks/base/core/jni/android_media_AudioRecord.cpp),但这并不能让事情变得更清楚。只有当缓冲区容量音频曲目需要在wav或采样音频数据中时,才会出现此错误
乐器数字接口(MIDI)数据

我做了更多的调试,发现问题不在于
音轨
,而在于
AudioRecord.read()
方法。但仍然没有解决方案。。。有人吗?

使用AudioRecord.read(短[],int,int)或AudioRecord.read(字节[],int,int)
而不是AudioRecord.read(java.nio.ByteBuffer,int)

只是想澄清一下:这不是一个独立的类文件,它将用作另一个类中的
线程
对象。。。这个父类应该发送
广播
,让这个
线程
完成它的工作。这不是真的。下一位来自AudioTrack API:“AudioTrack类管理并播放Java应用程序的单个音频资源。它允许将PCM音频缓冲区流式传输到音频硬件以进行播放。”我想您正在考虑MediaRecorder,我通过调用
ByteBuffer sampledData=ByteBuffer.allocateDirect(mBuffer.length),创建了一个直接缓冲区,解决了这个错误。但现在我遇到另一个错误:
java.lang.UnsupportedOperationException
。这发生在我试图从
processData()
方法中的
ByteBuffer
中获取
byte[]
的那一行。。。。有人知道这件事吗?是的,我想我弄明白了是怎么回事。显然,由allocateDirect分配的ByteBuffer实际上没有实际的字节[],所以它不能给您一个。我只是使用了一个实际的字节[];在您的情况下,看起来您可以直接通过mBuffer,我认为它应该可以工作(只是为函数添加一个0偏移量,等等)。感谢您的帖子,但我早就放弃了这种方法。。。我已经开始使用OpenSL ES API,在我看来,它比这更好用。。。虽然你说的还是对的…:)