我正在使用 AudioRecord 读取麦克风数据并使用 RandomAccessFile 将其写入 wav 文件。这是代码:
public class MainActivity extends Activity {
AudioManager am = null;
AudioRecord record =null;
// AudioTrack track =null;
final int SAMPLE_FREQUENCY = 44100;
final int SIZE_OF_RECORD_ARRAY = 1024; // 1024 ORIGINAL
final int WAV_SAMPLE_MULTIPLICATION_FACTOR = 1;
int i= 0;
boolean isPlaying = false;
private volatile boolean keepThreadRunning;
// private RandomAccessFile stateFile, stateFileTemp, savToDisk;
private RandomAccessFile savToDisk;
private FileDescriptor fd = new FileDescriptor();
private File delFile, renFile;
String stateFileLoc = Environment.getExternalStorageDirectory().getPath();
// To keep hederWriter() happy
private short nChannels = 1;
private int sRate = SAMPLE_FREQUENCY;
private short mBitsPersample = 16; // represents 16 bits of one PCM sample
private int payload;
class MyThread extends Thread{
private volatile boolean needsToPassThrough;
// /*
MyThread(){
super();
}
MyThread(boolean newPTV){
this.needsToPassThrough = newPTV;
}
// */
// /*
@Override
public void run(){
short[] lin = new short[SIZE_OF_RECORD_ARRAY];
// byte[] lin = new byte[SIZE_OF_RECORD_ARRAY];
int num = 0;
// /*
if(needsToPassThrough){
record.startRecording();
// track.play();
}
// */
while (keepThreadRunning) {
// while (!isInterrupted()) {
// num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
num = record.read(lin, 0, lin.length);
try {
// savToDisk.write(lin); // use only this line if lin is a byte array
// use the for loop block below if lin is an array of short
for(i=0;i <lin.length; i++)
savToDisk.writeShort(Short.reverseBytes(lin[i]));
// payload += lin.length; // use this line if lin is an array of byte
payload = payload + (lin.length)*2;
fd.sync();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
catch (SyncFailedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
}
// /*
record.stop();
// track.stop();
record.release();
// track.release();
// */
}
// */
// /*
public void stopThread(){
keepThreadRunning = false;
}
// */
}
MyThread newThread;
private void init() {
int min = AudioRecord.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
// Toast.makeText(getApplicationContext(), Integer.toString(min), Toast.LENGTH_SHORT).show(); // Shows 4096
record = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, min);
// int maxJitter = AudioTrack.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
// track = new AudioTrack(AudioManager.MODE_IN_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, maxJitter, AudioTrack.MODE_STREAM);
am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
am.setMode(AudioManager.MODE_IN_COMMUNICATION);
try {
savToDisk = new RandomAccessFile(stateFileLoc+"/audSampData.wav", "rw");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
fd = savToDisk.getFD();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void writeHeader(){
try {
savToDisk.setLength(0); // Set file length to 0, to prevent unexpected behavior in case the file already existed
savToDisk.writeBytes("RIFF");
savToDisk.writeInt(0); // Final file size not known yet, write 0
savToDisk.writeBytes("WAVE");
savToDisk.writeBytes("fmt ");
savToDisk.writeInt(Integer.reverseBytes(16)); // Sub-chunk size, 16 for PCM
savToDisk.writeShort(Short.reverseBytes((short) 1)); // AudioFormat, 1 for PCM
savToDisk.writeShort(Short.reverseBytes(nChannels));// Number of channels, 1 for mono, 2 for stereo
savToDisk.writeInt(Integer.reverseBytes(sRate)); // Sample rate
savToDisk.writeInt(Integer.reverseBytes(sRate*nChannels*mBitsPersample/8)); // Byte rate, SampleRate*NumberOfChannels*mBitsPersample/8
savToDisk.writeShort(Short.reverseBytes((short)(nChannels*mBitsPersample/8))); // Block align, NumberOfChannels*mBitsPersample/8
savToDisk.writeShort(Short.reverseBytes(mBitsPersample)); // Bits per sample
savToDisk.writeBytes("data");
savToDisk.writeInt(0); // Data chunk size not known yet, write 0
fd.sync();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
protected void onResume(){
super.onResume();
// newThread.stopThread();
Log.d("MYLOG", "onResume() called");
init();
writeHeader();
keepThreadRunning = true;
// */
// newThread = new MyThread(true);
newThread = new MyThread(isPlaying);
newThread.start();
}
@Override
protected void onPause(){
super.onPause();
Log.d("MYLOG", "onPause() called");
newThread.stopThread();
// android.os.Process.killProcess(android.os.Process.myPid());
try {
savToDisk.seek(4);
savToDisk.writeInt(Integer.reverseBytes(36+payload));
savToDisk.seek(40);
savToDisk.writeInt(Integer.reverseBytes(payload));
savToDisk.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setVolumeControlStream(AudioManager.MODE_IN_COMMUNICATION);
payload = 0;
Log.d("MYLOG","onCreate() called");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
protected void onDestroy() {
super.onDestroy();
newThread.stopThread();
// android.os.Process.killProcess(android.os.Process.myPid());
// killProcess(android.os.Process.myPid());
// newThread.interrupt();
// delFile.delete();
Log.d("MYLOG", "onDestroy() called");
/*
try {
savToDisk.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
}
public void passStop(View view){
Button playBtn = (Button) findViewById(R.id.button1);
// /*
if(!isPlaying){
record.startRecording();
// track.play();
isPlaying = true;
playBtn.setText("Pause");
}
else{
record.stop();
// track.pause();
isPlaying=false;
playBtn.setText("Pass through");
}
// */
}
}
当我在音频播放器中播放 wav 文件时,它听起来加快了速度,而且似乎还跳帧。这可能是什么原因?我相信跳帧问题可能是由于我使用writeShort()
函数写出单独存储音频样本数据的短数组的每个元素,但如果是这种情况,请建议一个涉及写入数据的解决方法作为短裤(并且不使用该write(byte[])
功能,因为我需要在我的主要项目中使用此代码的一部分,这涉及在一个短数组中获取音频样本)。还有为什么会加速?