我的应用程序不会播放录制的声音

时间:2011-02-22 14:39:21

标签: java android java-native-interface

在我的应用程序中,我想使用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),但这并没有让它更清楚。弹出此错误的唯一情况是缓冲区容量<= 0或此缓冲区的地址为空时。

所以是的,我不知道为什么这不起作用......任何有更多经验的人都可能......所以请赐教我?提前谢谢......

3 个答案:

答案 0 :(得分:0)

音轨必须采用wav或采样音频数据 乐器数字接口(MIDI)数据

答案 1 :(得分:0)

我已经做了一些调试,发现问题不是AudioTrack,而是使用AudioRecord.read()方法。尽管如此,仍然没有得到解决方案......任何人?

答案 2 :(得分:0)

使用AudioRecord.read(short [],int,int)或AudioRecord.read(byte [],int,int) 而不是AudioRecord.read(java.nio.ByteBuffer,int);