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,在我看来,它比这更好用。。。虽然你说的还是对的…:)