Android录音声波图
aikongmeng 人气:0图像类:
package com.akm.test; /** * Created by toge on 15/12/9. */ import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.SurfaceView; import java.util.LinkedList; /** * A view that displays audio data on the screen as a waveform. */ public class WaveformView extends SurfaceView { // The number of buffer frames to keep around (for a nice fade-out visualization). private static final int HISTORY_SIZE = 6; // To make quieter sounds still show up well on the display, we use +/- 8192 as the amplitude // that reaches the top/bottom of the view instead of +/- 32767. Any samples that have // magnitude higher than this limit will simply be clipped during drawing. private static final float MAX_AMPLITUDE_TO_DRAW = 8192.0f; // The queue that will hold historical audio data. private final LinkedList<short[]> mAudioData; private final Paint mPaint; public WaveformView(Context context) { this(context, null, 0); } public WaveformView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public WaveformView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mAudioData = new LinkedList<short[]>(); mPaint = new Paint(); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.WHITE); mPaint.setStrokeWidth(0); mPaint.setAntiAlias(true); } /** * Updates the waveform view with a new "frame" of samples and renders it. The new frame gets * added to the front of the rendering queue, pushing the previous frames back, causing them to * be faded out visually. * * @param buffer the most recent buffer of audio samples */ public synchronized void updateAudioData(short[] buffer) { short[] newBuffer; // We want to keep a small amount of history in the view to provide a nice fading effect. // We use a linked list that we treat as a queue for this. if (mAudioData.size() == HISTORY_SIZE) { newBuffer = mAudioData.removeFirst(); System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); } else { newBuffer = buffer.clone(); } mAudioData.addLast(newBuffer); // Update the display. Canvas canvas = getHolder().lockCanvas(); if (canvas != null) { drawWaveform(canvas); getHolder().unlockCanvasAndPost(canvas); } } /** * Repaints the view's surface. * * @param canvas the {@link Canvas} object on which to draw */ private void drawWaveform(Canvas canvas) { // Clear the screen each time because SurfaceView won't do this for us. canvas.drawColor(Color.BLACK); float width = getWidth(); float height = getHeight(); float centerY = height / 2; // We draw the history from oldest to newest so that the older audio data is further back // and darker than the most recent data. int colorDelta = 255 / (HISTORY_SIZE + 1); int brightness = colorDelta; for (short[] buffer : mAudioData) { mPaint.setColor(Color.argb(brightness, 128, 255, 192)); float lastX = -1; float lastY = -1; // For efficiency, we don't draw all of the samples in the buffer, but only the ones // that align with pixel boundaries. for (int x = 0; x < width; x++) { int index = (int) ((x / width) * buffer.length); short sample = buffer[index]; float y = (sample / MAX_AMPLITUDE_TO_DRAW) * centerY + centerY; if (lastX != -1) { canvas.drawLine(lastX, lastY, x, y, mPaint); } lastX = x; lastY = y; } brightness += colorDelta; } } }
头文件:
/* * Copyright (C) 2015 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.akm.test; import java.io.FileOutputStream; import java.io.IOException; /** * Created by Akm at 15/12/1 上午10:07 * 文件制作 */ public class WAVHeader { private byte[] mHeader; // the complete header. private int mSampleRate; // sampling frequency in Hz (e.g. 44100). private int mChannels; // number of channels. private int mNumSamples; // total number of samples per channel. private int mNumBytesPerSample; // number of bytes per sample, all channels included. public WAVHeader(int sampleRate, int numChannels, int numSamples) { mSampleRate = sampleRate; mChannels = numChannels; mNumSamples = numSamples; mNumBytesPerSample = 2 * mChannels; // assuming 2 bytes per sample (for 1 channel) mHeader = null; setHeader(); } public byte[] getWAVHeader() { return mHeader; } public static byte[] getWAVHeader(int sampleRate, int numChannels, int numSamples) { return new WAVHeader(sampleRate, numChannels, numSamples).mHeader; } public String toString() { String str = ""; if (mHeader == null) { return str; } int num_32bits_per_lines = 8; int count = 0; for (byte b : mHeader) { boolean break_line = count > 0 && count % (num_32bits_per_lines * 4) == 0; boolean insert_space = count > 0 && count % 4 == 0 && !break_line; if (break_line) { str += '\n'; } if (insert_space) { str += ' '; } str += String.format("%02X", b); count++; } return str; } private void setHeader() { byte[] header = new byte[46]; int offset = 0; int size; // set the RIFF chunk System.arraycopy(new byte[]{'R', 'I', 'F', 'F'}, 0, header, offset, 4); offset += 4; size = 36 + mNumSamples * mNumBytesPerSample; header[offset++] = (byte) (size & 0xFF); header[offset++] = (byte) ((size >> 8) & 0xFF); header[offset++] = (byte) ((size >> 16) & 0xFF); header[offset++] = (byte) ((size >> 24) & 0xFF); System.arraycopy(new byte[]{'W', 'A', 'V', 'E'}, 0, header, offset, 4); offset += 4; // set the fmt chunk System.arraycopy(new byte[]{'f', 'm', 't', ' '}, 0, header, offset, 4); offset += 4; System.arraycopy(new byte[]{0x10, 0, 0, 0}, 0, header, offset, 4); // chunk size = 16 offset += 4; System.arraycopy(new byte[]{1, 0}, 0, header, offset, 2); // format = 1 for PCM offset += 2; header[offset++] = (byte) (mChannels & 0xFF); header[offset++] = (byte) ((mChannels >> 8) & 0xFF); header[offset++] = (byte) (mSampleRate & 0xFF); header[offset++] = (byte) ((mSampleRate >> 8) & 0xFF); header[offset++] = (byte) ((mSampleRate >> 16) & 0xFF); header[offset++] = (byte) ((mSampleRate >> 24) & 0xFF); int byteRate = mSampleRate * mNumBytesPerSample; header[offset++] = (byte) (byteRate & 0xFF); header[offset++] = (byte) ((byteRate >> 8) & 0xFF); header[offset++] = (byte) ((byteRate >> 16) & 0xFF); header[offset++] = (byte) ((byteRate >> 24) & 0xFF); header[offset++] = (byte) (mNumBytesPerSample & 0xFF); header[offset++] = (byte) ((mNumBytesPerSample >> 8) & 0xFF); System.arraycopy(new byte[]{0x10, 0}, 0, header, offset, 2); offset += 2; // set the beginning of the data chunk System.arraycopy(new byte[]{'d', 'a', 't', 'a'}, 0, header, offset, 4); offset += 4; size = mNumSamples * mNumBytesPerSample; header[offset++] = (byte) (size & 0xFF); header[offset++] = (byte) ((size >> 8) & 0xFF); header[offset++] = (byte) ((size >> 16) & 0xFF); header[offset++] = (byte) ((size >> 24) & 0xFF); mHeader = header; } public static byte[] getHeader( long totalAudioLen, long totalDataLen, long longSampleRate, int channels, long byteRate) throws IOException { byte[] header = new byte[44]; header[0] = 'R'; // RIFF/WAVE header header[1] = 'I'; header[2] = 'F'; header[3] = 'F'; header[4] = (byte) (totalDataLen & 0xff); header[5] = (byte) ((totalDataLen >> 8) & 0xff); header[6] = (byte) ((totalDataLen >> 16) & 0xff); header[7] = (byte) ((totalDataLen >> 24) & 0xff); header[8] = 'W'; header[9] = 'A'; header[10] = 'V'; header[11] = 'E'; header[12] = 'f'; // 'fmt ' chunk header[13] = 'm'; header[14] = 't'; header[15] = ' '; header[16] = 16; // 4 bytes: size of 'fmt ' chunk header[17] = 0; header[18] = 0; header[19] = 0; header[20] = 1; // format = 1 header[21] = 0; header[22] = (byte) channels; header[23] = 0; header[24] = (byte) (longSampleRate & 0xff); header[25] = (byte) ((longSampleRate >> 8) & 0xff); header[26] = (byte) ((longSampleRate >> 16) & 0xff); header[27] = (byte) ((longSampleRate >> 24) & 0xff); header[28] = (byte) (byteRate & 0xff); header[29] = (byte) ((byteRate >> 8) & 0xff); header[30] = (byte) ((byteRate >> 16) & 0xff); header[31] = (byte) ((byteRate >> 24) & 0xff); header[32] = (byte) (2 * 16 / 8); // block align header[33] = 0; header[34] = 16; // bits per sample header[35] = 0; header[36] = 'd'; header[37] = 'a'; header[38] = 't'; header[39] = 'a'; header[40] = (byte) (totalAudioLen & 0xff); header[41] = (byte) ((totalAudioLen >> 8) & 0xff); header[42] = (byte) ((totalAudioLen >> 16) & 0xff); header[43] = (byte) ((totalAudioLen >> 24) & 0xff); return header; } }
测试:
package com.akm.test; import android.app.Activity; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioRecord; import android.media.AudioTrack; import android.media.MediaPlayer; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.os.Message; import android.os.SystemClock; import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Chronometer; import android.widget.SeekBar; import android.widget.TextView; import com.ringdroid.R; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.ShortBuffer; import java.nio.channels.FileChannel; /** * Created by toge on 15/11/30. */ public class Test extends Activity implements View.OnClickListener { WaveformView waveformView; private Button btnStart; private Button btnStop; private String filePath; private boolean mRecordingKeepGoing; private SoundFile soundFile; private RandomAccessFile randomAccessFile; private int totalLength;//总长 private int duration;//时长 private int rate;//采样率 private int channelConfig;//声道 private int samples; private int startPos; private int bufferSize;//缓冲区大小 private int minBufferSize;//最小缓冲区 private AudioRecord audioRecord; private AudioTrack audioTrack; private boolean mThreadFlag; private int i; private int j; private int STATUS = 1; private int STATUS_PAUSE = 2; private int STATUS_PREPARED = 1; private int STATUS_RECORDING = 1; private Thread audioTrackThread; private Thread thread; private int endPos; private int curFileLength; OnFileChangedListener onFileChangedListener; private boolean isRewrite; private boolean audioTrackFlag; private int frequency = 22050;//22050; private int recBufSize; private String outPath; private byte[] bytes; private int time; private Button btnPasue; private Button btnPlay; private Button btnPlay2; private long startTime; private long restOfTime; private int audioFormat;//采集 private int bufferSizeInBytes;//缓冲区大小 private Button btnSave; // private ByteBuffer mDecodedBytes; // private ByteBuffer mDecodedSamples; private byte[] sampleBytes; private MediaPlayer mediaPlayer; private SeekBar seekBar; private android.os.Handler handler = new android.os.Handler(); Runnable updateThread = new Runnable() { public void run() { // 获得歌曲现在播放位置并设置成播放进度条的值 if (mediaPlayer != null) { seekBar.setProgress(mediaPlayer.getCurrentPosition()); Log.e("Test", "run------ updateThread:getCurrentPosition " + mediaPlayer.getCurrentPosition()); // 每次延迟100毫秒再启动线程 handler.postDelayed(updateThread, 100); } } }; private Chronometer et_time; private long falgTime; private long pauseTime; private long subtime; private long beginTime; private TextView currentTime; private int currentProgress; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test); waveformView = (WaveformView) findViewById(R.id.waveform); btnStart = (Button) findViewById(R.id.button_start); btnPasue = (Button) findViewById(R.id.button_pasue); btnStop = (Button) findViewById(R.id.button2_stop); btnPlay = (Button) findViewById(R.id.button_play); btnPlay2 = (Button) findViewById(R.id.button_play2); btnSave = (Button) findViewById(R.id.button_save); seekBar = (SeekBar) findViewById(R.id.sb); et_time = (Chronometer) this.findViewById(R.id.et_time); currentTime = (TextView) this.findViewById(R.id.currentTime); btnStart.setOnClickListener(this); btnPasue.setOnClickListener(this); btnStop.setOnClickListener(this); btnPlay.setOnClickListener(this); btnPlay2.setOnClickListener(this); btnSave.setOnClickListener(this); initPar(); initRecorder(true); initAudioTack(); } @Override protected void onResume() { super.onResume(); initRecorder(false); } private void initAudioTack() { minBufferSize = AudioTrack.getMinBufferSize(rate, 3, audioFormat); Log.e("Test", "initAudioTack------ minBufferSize:" + minBufferSize); audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, rate, 1, audioFormat, minBufferSize, AudioTrack.MODE_STREAM); } private void initPar() { duration = 60 * 1000;//毫秒 rate = 44100;//声卡一般提供11.025kHz、22.05kHz和44.1kHz等不同的采样频率 channelConfig = AudioFormat.CHANNEL_IN_DEFAULT; audioFormat = AudioFormat.ENCODING_PCM_16BIT; restOfTime = duration; } private void initRecorder(boolean isNew) { initAudioFile(isNew); bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat); Log.d("Test", "initRecorder: bufferSize:" + bufferSize);//44100 1 2 = v fc // int k = audioFormat * rate / 25; // if (bufferSize % k != 0) { // bufferSize = (k * (channelConfig + bufferSize / k)); // } audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, rate, channelConfig, audioFormat, bufferSize); } public boolean isRecording() { return audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING; } private void initAudioFile(boolean isNew) { filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/akm/t.wav"; new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/akm").mkdir(); File f = new File(filePath); try { if (f.exists() && isNew) { f.delete(); } randomAccessFile = new RandomAccessFile(filePath, "rw"); //文件长度 = 比特率*时间 //= 采样率*位数*声道 / 8 totalLength = (rate * 1 * 16 / 8) * (duration / 1000); // totalLength = (int) (4l * (duration * rate / 1000l)); createWaveFile(randomAccessFile, true, totalLength); totalLength = 44 + totalLength; randomAccessFile = new RandomAccessFile(filePath, "rw"); } catch (Exception e) { e.printStackTrace(); } } private void createWaveFile(RandomAccessFile randomAccessFile, boolean b, int totalLength) { if (b) { try { // randomAccessFile.write(WAVHeader.getHeader(rate,channels,samples)); // long totalAudioLen,long totalDataLen, long longSampleRate, int channels, long byteRate //数据长度 文件长度 采样率 声道 比特率 //比特率(字节/秒)= (采样频率(Hz)× 采样位数(bit) × 声道数)/ 8 // long byteRate = (channelConfig * audioFormat * rate) / 8; byte[] bytes = WAVHeader.getHeader(totalLength - 36l, totalLength, rate, channelConfig, byteRate); FileChannel localFileChannel = randomAccessFile.getChannel(); localFileChannel.map(FileChannel.MapMode.READ_WRITE, 0l, 44l).put(bytes); localFileChannel.close(); Log.e("Test", "createWaveFile------ OK "); } catch (IOException e) { e.printStackTrace(); } } } @Override public void onClick(View view) { switch (view.getId()) { case R.id.button_start: try { mRecordingKeepGoing = true; new Thread() { @Override public void run() { startRecording(); } }.start(); } catch (Exception e) { e.printStackTrace(); } break; case R.id.button_pasue: mRecordingKeepGoing = false; pauseRecord(); try {//暂停后,设置文件索引为末尾 startPos = (int) randomAccessFile.getFilePointer(); } catch (IOException e) { e.printStackTrace(); } pausePlay(); break; case R.id.button_play: startReview(true); break; case R.id.button2_stop: mRecordingKeepGoing = false; stopRecord(); stopPlay(); break; case R.id.button_save: startPos = currentProgress; if (randomAccessFile==null){ try { randomAccessFile = new RandomAccessFile(filePath, "rw"); } catch (IOException e) { e.printStackTrace(); } } try { Log.e("Test", "onClick: pos" + randomAccessFile.getFilePointer()); int size = ((rate * 1 * 16 / 8) * (currentProgress / 1000)); Log.e("Test", "onClick------ size "+size); if (size<44){ size = 44; } randomAccessFile.seek(size); randomAccessFile.write(sampleBytes); randomAccessFile.close(); } catch (IOException e) { e.printStackTrace(); } Log.e("Test", "onClick------pos "+currentProgress); break; case R.id.button_play2: play(); break; } } private void pausePlay() { if (mediaPlayer != null && mediaPlayer.isPlaying()) { // 暂停音乐播放器 mediaPlayer.pause(); btnPasue.setText("续播"); seekBar.setEnabled(false); et_time.stop(); pauseTime = SystemClock.elapsedRealtime(); // System.out.println("1 pauseTime" + pauseTime); } else if (mediaPlayer != null && "续播".equals(btnPasue.getText().toString())) { subtime += SystemClock.elapsedRealtime() - pauseTime; // System.out.println("2 subtime:" + subtime); mediaPlayer.start(); btnPasue.setText("暂停"); seekBar.setEnabled(true); beginTime = falgTime + subtime; // System.out.println("3 beginTime" + beginTime); et_time.setBase(beginTime); et_time.start(); } } private void stopPlay() { if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.stop(); mediaPlayer = null; et_time.setBase(SystemClock.elapsedRealtime()); et_time.start(); et_time.stop(); btnPlay2.setEnabled(true); btnPlay2.setClickable(true); } falgTime = 0; subtime = 0; seekBar.setProgress(0); seekBar.setEnabled(false); } private void play() { mediaPlayer = new MediaPlayer(); try { mediaPlayer.setDataSource(filePath); mediaPlayer.prepareAsync(); // 为播放器注册 mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { public void onPrepared(MediaPlayer mp) { // TODO Auto-generated method stub mediaPlayer.start(); btnPlay2.setEnabled(false); btnPlay2.setClickable(false); seekBar.setMax(mediaPlayer.getDuration()); handler.post(updateThread); seekBar.setEnabled(true); } }); // 注册播放完毕后的监听事件 mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { // mediaPlayer.release(); // mediaPlayer = null; btnPlay2.setEnabled(true); btnPlay2.setClickable(true); et_time.setBase(SystemClock.elapsedRealtime()); et_time.start(); et_time.stop(); seekBar.setProgress(0); } }); falgTime = SystemClock.elapsedRealtime(); et_time.setBase(falgTime); et_time.start(); et_time.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() { @Override public void onChronometerTick(Chronometer chronometer) { } }); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (fromUser == true && mediaPlayer != null) { Log.e("Test", "onProgressChanged------ progress "+progress); mediaPlayer.seekTo(progress); falgTime = SystemClock.elapsedRealtime(); beginTime = falgTime - seekBar.getProgress(); et_time.setBase(beginTime); // et_time.start(); // final int ctime = mediaPlayer.getDuration() / progress; //时间*比特率 = 大小 (rate * 1 * 16 / 8) * (duration / 1000); //时间 = 大小/比特率 int ctime = progress/((rate * 1 * 16 / 8) * (duration / 1000)); currentTime.setText( ctime+ "s"); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { // startPos = seekBar.getProgress(); currentProgress = seekBar.getProgress(); } }); } catch (IOException e) { e.printStackTrace(); } // mediaPlayer.prepare(); // c/c++ 播放器引擎的初始化 // 同步方法 // 采用异步的方式 } private OnEventListener onEventListener; public void setOnEventListener(OnEventListener onEventListener) { this.onEventListener = onEventListener; } android.os.Handler errorHandler = new android.os.Handler() { @Override public void handleMessage(Message msg) { if (onEventListener != null) { onEventListener.onError("error"); } } }; private void startThread() { if (startPos == 0) {//开始位置 try { randomAccessFile.seek(44); } catch (IOException e) { e.printStackTrace(); } } mThreadFlag = true; i = 0; j = -1; STATUS = 1; thread = new Thread() { @Override public void run() { if (startTime == 0) { startTime = System.currentTimeMillis(); } byte[] arrayOfByte = new byte[bufferSize]; short[] arrayOfShort = new short[bufferSize]; while (mThreadFlag) { try { if (audioRecord == null || STATUS != 1) { continue; } int bufferReadResult = audioRecord.read(arrayOfByte, 0, bufferSize); int bufferReadResult2 = audioRecord.read(arrayOfShort, 0, bufferSize); Log.e("Test", "run------ bufferReadResult "+bufferReadResult); Log.e("Test", "run------ bufferReadResult2 "+bufferReadResult2); if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING || bufferReadResult <= 0) { break; } i = 1; randomAccessFile.write(arrayOfByte); waveformView.updateAudioData(arrayOfShort); byte[] tmpBuf = new byte[bufferReadResult]; System.arraycopy(arrayOfByte, 0, tmpBuf, 0, bufferReadResult); audioTrack.write(tmpBuf, 0, tmpBuf.length); pjByteBuffer(tmpBuf); curFileLength = (int) randomAccessFile.length() / 1024; Log.e("Test", "run------ curFilelength:" + curFileLength + ",startPos:" + startPos + ",endPos:" + endPos + ",isRewrite:" + isRewrite); int time = (int) (System.currentTimeMillis() - startTime); Log.e("Test", "run------ time: " + time); Log.e("Test", "run------ bytes:" + arrayOfByte.length); Log.e("Test", "run------ getFilePointer:" + randomAccessFile.getFilePointer()); startPos = (int) randomAccessFile.getFilePointer(); if (time >= restOfTime) { stopRecord(); } onFileChangedListener.onBufferRecevied(startPos, endPos, arrayOfByte, curFileLength, isRewrite); // Test t1 = Test.this; // t1.i = 1+t1.i; // // long length = randomAccessFile.getFilePointer() + arrayOfByte.length; // xxx(this,length); // if (endPos>curFileLength){ // xxx(this,endPos); // } // randomAccessFile.write(arrayOfByte); // onFileChangedListener.onBufferRecevied(startPos,endPos,arrayOfByte,curFileLength,isRewrite); // // Test t2 =Test.this; // t2.j = 1+t2.j; // if (i!=0||j!=0){ // continue; // } // xxx(this,false); // errorHandler.sendEmptyMessage(0); } catch (Exception e) { e.printStackTrace(); errorHandler.sendEmptyMessage(0); } } } }; thread.start(); } private byte[] pjArray(byte[] src, byte[] dest) { byte[] newBytes = new byte[src.length + dest.length]; System.arraycopy(src, 0, newBytes, 0, src.length); System.arraycopy(dest, 0, newBytes, src.length, dest.length); return newBytes; } private void pjByteBuffer(byte[] tmpBuf) { if (sampleBytes == null) { sampleBytes = tmpBuf; } else { sampleBytes = pjArray(sampleBytes, tmpBuf); } } private void pauseReview() { audioTrackFlag = false; audioTrack.pause(); audioTrack.flush(); Log.e("Test", "pauseReview------ "); } private void startReview(boolean b) { if (audioTrack == null) { initAudioTack(); } audioTrack.play(); audioTrackFlag = true; audioTrackThread = new Thread() { @Override public void run() { try { bytes = new byte[minBufferSize]; while (randomAccessFile.read(bytes) != -1 && audioTrackFlag) { Log.e("Test", "run------ "); Log.e("Test", "run------audiotrackflag is " + audioTrackFlag); Log.e("Test", "run------wrtie data in audiotrack "); } Log.e("Test", "run------ audiotrack end."); } catch (Exception e) { } } }; audioTrackThread.start(); } public void pauseRecord() { if (audioRecord != null) { audioRecord.stop(); mThreadFlag = false; } } private void reset() { startPos = 0; endPos = 0; curFileLength = 44; isRewrite = false; } private void resumeRecord() { while (isRewrite) {//写文件 try { if (randomAccessFile.getFilePointer() != endPos || !isRewrite) {//不可写 ,或者选中位置不是文件指针所在位置 startPos = (int) randomAccessFile.getFilePointer(); // 从文件指针位置开始 } if (!isRewrite) {//不写文件 if (44 + startPos >= endPos) {// continue; } isRewrite = true; } } catch (IOException e) { e.printStackTrace(); } audioRecord.startRecording(); if (thread == null || !mThreadFlag) { startThread(); } } } private void startRecording() { try { audioRecord.startRecording(); // if (thread==null||!mThreadFlag){ // startThread(); // } startThread(); Log.e("Test", "startRecording------ "); } catch (Exception e) { initRecorder(true); } } public int getMinBufferSize() { return minBufferSize; } public void getMinBufSize() { recBufSize = AudioRecord.getMinBufferSize(frequency, 12, 2); } public void setOnFileChangedListener(OnFileChangedListener onFileChangedListener) { this.onFileChangedListener = onFileChangedListener; } public void setDuration(int duration) { this.duration = duration; } interface OnFileChangedListener { void onBufferRecevied(long startPos, long endPos, byte[] b1, long currenFileLength, boolean isRew); } interface OnEventListener { void onError(String s); void onRecordComplete(); void onVolumnChanged(double vl); } public String creatFile() { // copyWaveFile(filePath,filePath,true); return outPath; } private void moveToPrevious(long pl) { try { long l = 44 + 4 * (pl * rate / 1000l); randomAccessFile.seek(l); Log.e("Test", "moveToPrevious------ offset:" + l + " length:" + randomAccessFile.length()); } catch (Exception e) { } } @Override protected void onPause() { super.onPause(); stopRecord(); } @Override protected void onStop() { super.onStop(); closeStream(); } private void stopRecord() { try { mThreadFlag = false; time = 0; thread = null; if (audioRecord != null) { if (audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) { audioRecord.stop(); Log.e("Test", "stopRecord------ "); } audioRecord.release(); audioRecord = null; } closeStream(); } catch (Exception e) { } } private void closeStream() { try { if (randomAccessFile != null) { randomAccessFile.close(); } } catch (Exception e) { } } float getDensity() { DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); return metrics.density; } }
加载全部内容