图像类:

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 chunkSystem.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 chunkSystem.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 = 16offset += 4;System.arraycopy(new byte[]{1, 0}, 0, header, offset, 2);  // format = 1 for PCMoffset += 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 chunkSystem.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 headerheader[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 ' chunkheader[13] = 'm';header[14] = 't';header[15] = ' ';header[16] = 16; // 4 bytes: size of 'fmt ' chunkheader[17] = 0;header[18] = 0;header[19] = 0;header[20] = 1; // format = 1header[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 alignheader[33] = 0;header[34] = 16; // bits per sampleheader[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;@Overrideprotected 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();}@Overrideprotected 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");//文件长度 = 比特率*时间//= 采样率*位数*声道 / 8totalLength = (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();}}}@Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.button_start:try {mRecordingKeepGoing = true;new Thread() {@Overridepublic 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 stubmediaPlayer.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() {@Overridepublic void onChronometerTick(Chronometer chronometer) {}});seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic 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");}}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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) {}}@Overrideprotected void onPause() {super.onPause();stopRecord();}@Overrideprotected 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;}}

Android 录音声波图相关推荐

  1. Android录音转为MP2的实现

    Android录音转为MP2的实现 利用Android提供的AudioRecord类以及开源编码库twolame,实现了android手机边录音边编码,录音完成直接得到MP2音频文件.由于Androi ...

  2. Android录音下————AudioRecord源码分析

    Android录音下----AudioRecord源码分析 文章目录 Android录音下----AudioRecord源码分析 一.概述 1.主要分析点 2.储备知识 二.getMinBufferS ...

  3. android 录音的格式,Android录音mp3格式实例详解

    Android录音支持的格式有amr.aac,但这两种音频格式在跨平台上表现并不好. MP3显然才是跨平台的最佳选择. 项目地址 实现思路概述 在分析代码前,我们需要明确几个问题 1. 如何最终生成M ...

  4. Android音频录制方案,Android录音,录制其他App播放的声音

    Android录音,录制其他App播放的声音 从Android10(SDK 29)版本开始,可以设置录音App的源为其他App,这样就可以录制其他App播放的声音 此方案有以下注意几点 设置了源为其他 ...

  5. Android录音amr实时转成MP3格式

    文章目录 MP3 录音使用说明 步骤一:下载NDK,并配置(Mac) 步骤二:修改C代码相关路径,编译成so库 步骤三:应用层代码代码调用系统AudioRecord类开始录音 开始录音 start() ...

  6. Android录音并进行本地转码为MP3

    ** Android录音并进行本地转码 ** 通过安卓手机进行录音, 录音后,使用lame进行转码操作 开发中需要使用这个功能,只是一个简单的进行转码的工具,具体的代码信息如下 项目的基本结构图 1. ...

  7. Android录音-SoundTouch移植到Android

    Android录音-SoundTouch移植到Android 文章目录 Android录音-SoundTouch移植到Android 一.SoundTouch介绍 二.移植SoundTouch(And ...

  8. Androidの录音实现

    Androidの录音实现 1. 录音功能需要使用android.media.MediaRecorder来完成,这里我们列出几个重要的使用方法,也是最常用的录音接口. 1.MediaRecorder r ...

  9. Android录音控件

            做项目一直不得空,好不容易腾出时间,赶紧把过往的知识整理一下,以下是做项目时用到的录音控件,在同事写的基础上修改改成,支持后台录音,页面比较简单.写这个组件之前做了简单的调研,如果有不 ...

最新文章

  1. 5加载stm32 keil_快速入门STM32单片机-软件篇
  2. oracle监听静态注册,oracle监听器动态注册于静态注册的区别
  3. 互联网资讯简报2019-05-14
  4. noip2017初赛的一些知识点
  5. 虚拟地址空间及内存管理方式
  6. 贾跃亭向全体债权人道歉!个人资产曝光:总额14亿美元,国内三套房
  7. 大萧条来临前的几大征兆
  8. 如何使用SSH密钥登录你的云服务器?使用SSH密钥的好处
  9. sourcemointor评价代码
  10. php做图书管理系统绪论,基于PHP图书管理系统的设计与实现本科毕业论文
  11. 邮件服务器备案,关于企业邮箱域名备案事项通知
  12. React实现H5横屏电子签名板
  13. window10 tar解压
  14. MFC添加鼠标右键菜单
  15. 发送QQ邮件报证书不被信任 Error in certificate
  16. 高防服务器防御的原理是什么呢
  17. 1949-2020年各省全要素生产率(年度)
  18. element-ui清除表单验证提示语
  19. 杨辉三角fac的C语言代码,程序设计基础B(陈雪龙)-中国大学mooc-题库零氪
  20. office 和 wps 对于超链接的处理浅析

热门文章

  1. springboot-thymeleaf踩坑记录
  2. AC米兰球队一百年年鉴(1899-1999)
  3. 一堆被称之为大学的东西——思想和精神(送给不仅仅是计算机专业的同学)
  4. 嘀嗒出行一直显示服务器错误,嘀嗒出行注册账号,显示身份信息异常!
  5. 瑞萨单片机之Flash存储
  6. 应用WSDK-实现和使用DIME的Web Services(上)
  7. win10任务管理器网络使用率一直为0%的解决方法
  8. 【guava】 谷歌guava工具包的常用方法 双key的map 、驼峰转下划线等小结
  9. 大数据架构师应该做到的
  10. 23 - JavaScript 通过style对象设置行内样式