/extras/zjb-mp3recorder/src/main/java/com/buihha/audiorecorder/Mp3Recorder.java

https://github.com/pinguo-sunjianfei/Android-Application-ZJB · Java · 233 lines · 160 code · 41 blank · 32 comment · 26 complexity · 7128d97fd49778d5109fdcac87863a53 MD5 · raw file

  1. package com.buihha.audiorecorder;
  2. import android.media.AudioFormat;
  3. import android.media.AudioRecord;
  4. import android.media.MediaRecorder;
  5. import android.os.Message;
  6. import android.text.TextUtils;
  7. import android.util.Log;
  8. import java.io.File;
  9. import java.io.FileOutputStream;
  10. import java.io.IOException;
  11. public class Mp3Recorder {
  12. private static final String TAG = Mp3Recorder.class.getSimpleName();
  13. String audioOutputPath;
  14. static {
  15. System.loadLibrary("mp3lame");
  16. }
  17. private static final int DEFAULT_SAMPLING_RATE = 22050;
  18. private static final int FRAME_COUNT = 160;
  19. /* Encoded bit rate. MP3 file will be encoded with bit rate 32kbps */
  20. private static final int BIT_RATE = 32;
  21. private AudioRecord audioRecord = null;
  22. private int bufferSize;
  23. private File mp3File;
  24. private RingBuffer ringBuffer;
  25. private byte[] buffer;
  26. private FileOutputStream os = null;
  27. private DataEncodeThread encodeThread;
  28. private int samplingRate;
  29. private int channelConfig;
  30. private PCMFormat audioFormat;
  31. private boolean isRecording = false;
  32. private VolumeChangeListener mVolumeChangeListener;
  33. private static final int LEVEL_1 = 1;
  34. private static final int LEVEL_2 = 2;
  35. private static final int LEVEL_3 = 3;
  36. private static final int LEVEL_4 = 4;
  37. private static final int LEVEL_5 = 5;
  38. public Mp3Recorder(int samplingRate, int channelConfig,
  39. PCMFormat audioFormat) {
  40. this.samplingRate = samplingRate;
  41. this.channelConfig = channelConfig;
  42. this.audioFormat = audioFormat;
  43. }
  44. /**
  45. * Default constructor. Setup recorder with default sampling rate 1 channel,
  46. * 16 bits pcm
  47. */
  48. public Mp3Recorder() {
  49. this(DEFAULT_SAMPLING_RATE, AudioFormat.CHANNEL_IN_MONO,
  50. PCMFormat.PCM_16BIT);
  51. }
  52. public void setAudioOutputPath(String audioOutputPath) {
  53. this.audioOutputPath = audioOutputPath;
  54. }
  55. public String getAudioOutputPath() {
  56. return audioOutputPath;
  57. }
  58. public void setVolumeChangeListener(VolumeChangeListener listener) {
  59. this.mVolumeChangeListener = listener;
  60. }
  61. /**
  62. * Start recording. Create an encoding thread. Start record from this
  63. * thread.
  64. *
  65. * @throws IOException
  66. */
  67. public void startRecording() throws IOException {
  68. if (isRecording) return;
  69. Log.d(TAG, "Start recording");
  70. Log.d(TAG, "BufferSize = " + bufferSize);
  71. // Initialize audioRecord if it's null.
  72. if (audioRecord == null) {
  73. initAudioRecorder();
  74. }
  75. audioRecord.startRecording();
  76. new Thread() {
  77. @Override
  78. public void run() {
  79. isRecording = true;
  80. long time1 = System.currentTimeMillis();
  81. while (isRecording) {
  82. int bytes = audioRecord.read(buffer, 0, bufferSize);
  83. if (bytes > 0) {
  84. ringBuffer.write(buffer, bytes);
  85. }
  86. int v = 0;
  87. for (int i = 0; i < bytes; i++) {
  88. v += buffer[i] * buffer[i];
  89. }
  90. long time2 = System.currentTimeMillis();
  91. if (null != mVolumeChangeListener) {
  92. if (time2 - time1 > 100) {
  93. // 平方和除以数据总长度,得到音量大小。
  94. double mean = v / (float) bytes;
  95. double f = 10 * Math.log10(mean);
  96. Log.e("音量 = ", f + "");
  97. if (f <= 30) {
  98. mVolumeChangeListener.onVolumeChange(LEVEL_1);
  99. Log.e("音量", "音量 >> 1");
  100. } else if (f <= 80 && f > 30) {
  101. mVolumeChangeListener.onVolumeChange(LEVEL_2);
  102. Log.e("音量", "音量 >> 2");
  103. } else if (f <= 120 && f > 80) {
  104. mVolumeChangeListener.onVolumeChange(LEVEL_3);
  105. Log.e("音量", "音量 >> 3");
  106. } else if (f <= 160 && f > 120) {
  107. mVolumeChangeListener.onVolumeChange(LEVEL_4);
  108. Log.e("音量", "音量 >> 4");
  109. } else if (f > 160) {
  110. mVolumeChangeListener.onVolumeChange(LEVEL_5);
  111. Log.e("音量", "音量 >> 5");
  112. }
  113. time1 = time2;
  114. }
  115. }
  116. }
  117. // release and finalize audioRecord
  118. try {
  119. audioRecord.stop();
  120. audioRecord.release();
  121. audioRecord = null;
  122. // stop the encoding thread and try to wait
  123. // until the thread finishes its job
  124. Message msg = Message.obtain(encodeThread.getHandler(),
  125. DataEncodeThread.PROCESS_STOP);
  126. msg.sendToTarget();
  127. Log.d(TAG, "waiting for encoding thread");
  128. encodeThread.join();
  129. Log.d(TAG, "done encoding thread");
  130. } catch (InterruptedException e) {
  131. Log.d(TAG, "Faile to join encode thread");
  132. } finally {
  133. if (os != null) {
  134. try {
  135. os.close();
  136. } catch (IOException e) {
  137. e.printStackTrace();
  138. }
  139. }
  140. }
  141. }
  142. }.start();
  143. }
  144. /**
  145. * @throws IOException
  146. */
  147. public void stopRecording() throws IOException {
  148. Log.d(TAG, "stop recording");
  149. isRecording = false;
  150. }
  151. /**
  152. * Initialize audio recorder
  153. */
  154. private void initAudioRecorder() throws IOException {
  155. int bytesPerFrame = audioFormat.getBytesPerFrame();
  156. /* Get number of samples. Calculate the buffer size (round up to the
  157. factor of given frame size) */
  158. int frameSize = AudioRecord.getMinBufferSize(samplingRate,
  159. channelConfig, audioFormat.getAudioFormat()) / bytesPerFrame;
  160. if (frameSize % FRAME_COUNT != 0) {
  161. frameSize = frameSize + (FRAME_COUNT - frameSize % FRAME_COUNT);
  162. Log.d(TAG, "Frame size: " + frameSize);
  163. }
  164. bufferSize = frameSize * bytesPerFrame;
  165. /* Setup audio recorder */
  166. audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
  167. samplingRate, channelConfig, audioFormat.getAudioFormat(),
  168. bufferSize);
  169. // Setup RingBuffer. Currently is 10 times size of hardware buffer
  170. // Initialize buffer to hold data
  171. ringBuffer = new RingBuffer(10 * bufferSize);
  172. buffer = new byte[bufferSize];
  173. // Initialize lame buffer
  174. // mp3 sampling rate is the same as the recorded pcm sampling rate
  175. // The bit rate is 32kbps
  176. SimpleLame.init(samplingRate, 1, samplingRate, BIT_RATE);
  177. if (TextUtils.isEmpty(audioOutputPath)) {
  178. throw new NullPointerException("please set the audio output path!");
  179. }
  180. mp3File = new File(audioOutputPath);
  181. os = new FileOutputStream(mp3File);
  182. // Create and run thread used to encode data
  183. // The thread will
  184. encodeThread = new DataEncodeThread(ringBuffer, os, bufferSize);
  185. encodeThread.start();
  186. audioRecord.setRecordPositionUpdateListener(encodeThread, encodeThread.getHandler());
  187. audioRecord.setPositionNotificationPeriod(FRAME_COUNT);
  188. }
  189. public interface VolumeChangeListener {
  190. void onVolumeChange(int level);
  191. }
  192. }