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[])
短い配列でオーディオサンプルを取得することを含むメインプロジェクトでこのコードの一部を使用する必要があるため、関数を使用しません)。また、なぜ高速化されるのですか?