Android实现录音声波图 本文实例为大家分享了Android实现录音声波图的具体代码,供大家参考,具体内容如下 图像类: 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
本文实例为大家分享了Android实现录音声波图的具体代码,供大家参考,具体内容如下
图像类:
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;
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
沃梦达教程
本文标题为:Android实现录音声波图
基础教程推荐
猜你喜欢
- MVVMLight项目Model View结构及全局视图模型注入器 2023-05-07
- IOS获取系统相册中照片的示例代码 2023-01-03
- Flutter进阶之实现动画效果(三) 2022-10-28
- iOS开发 全机型适配解决方法 2023-01-14
- Android实现短信验证码输入框 2023-04-29
- Android Compose自定义TextField实现自定义的输入框 2023-05-13
- iOS中如何判断当前网络环境是2G/3G/4G/5G/WiFi 2023-06-18
- iOS开发使用XML解析网络数据 2022-11-12
- Android开发Compose集成高德地图实例 2023-06-15
- iOS Crash常规跟踪方法及Bugly集成运用详细介绍 2023-01-18