歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android錄音時指針擺動的實現(附源碼)

Android錄音時指針擺動的實現(附源碼)

日期:2017/3/1 10:22:55   编辑:Linux編程

文中的Android代碼主要是移植SoundRecorder的。主要是其中的VUMeter類,VUMeter是通過Recorder.getMaxAmplitude()的值計算,畫出指針的偏移擺動。下面直接上代碼

  1. /*
  2. * Copyright (C) 2011 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.android.soundrecorder;
  17. import android.content.Context;
  18. import android.graphics.Canvas;
  19. import android.graphics.Color;
  20. import android.graphics.Paint;
  21. import android.graphics.drawable.Drawable;
  22. import android.util.AttributeSet;
  23. import android.view.View;
  24. public class VUMeter extends View {
  25. static final float PIVOT_RADIUS = 3.5f;
  26. static final float PIVOT_Y_OFFSET = 10f;
  27. static final float SHADOW_OFFSET = 2.0f;
  28. static final float DROPOFF_STEP = 0.18f;
  29. static final float SURGE_STEP = 0.35f;
  30. static final long ANIMATION_INTERVAL = 70;
  31. Paint mPaint, mShadow;
  32. float mCurrentAngle;
  33. Recorder mRecorder;
  34. public VUMeter(Context context) {
  35. super(context);
  36. init(context);
  37. }
  38. public VUMeter(Context context, AttributeSet attrs) {
  39. super(context, attrs);
  40. init(context);
  41. }
  42. void init(Context context) {
  43. Drawable background = context.getResources().getDrawable(R.drawable.vumeter);
  44. setBackgroundDrawable(background);
  45. mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  46. mPaint.setColor(Color.WHITE);
  47. mShadow = new Paint(Paint.ANTI_ALIAS_FLAG);
  48. mShadow.setColor(Color.argb(60, 0, 0, 0));
  49. mRecorder = null;
  50. mCurrentAngle = 0;
  51. }
  52. public void setRecorder(Recorder recorder) {
  53. mRecorder = recorder;
  54. invalidate();
  55. }
  56. @Override
  57. protected void onDraw(Canvas canvas) {
  58. super.onDraw(canvas);
  59. final float minAngle = (float)Math.PI/8;
  60. final float maxAngle = (float)Math.PI*7/8;
  61. float angle = minAngle;
  62. if (mRecorder != null)
  63. angle += (float)(maxAngle - minAngle)*mRecorder.getMaxAmplitude()/32768;
  64. if (angle > mCurrentAngle)
  65. mCurrentAngle = angle;
  66. else
  67. mCurrentAngle = Math.max(angle, mCurrentAngle - DROPOFF_STEP);
  68. mCurrentAngle = Math.min(maxAngle, mCurrentAngle);
  69. float w = getWidth();
  70. float h = getHeight();
  71. float pivotX = w/2;
  72. float pivotY = h - PIVOT_RADIUS - PIVOT_Y_OFFSET;
  73. float l = h*4/5;
  74. float sin = (float) Math.sin(mCurrentAngle);
  75. float cos = (float) Math.cos(mCurrentAngle);
  76. float x0 = pivotX - l*cos;
  77. float y0 = pivotY - l*sin;
  78. canvas.drawLine(x0 + SHADOW_OFFSET, y0 + SHADOW_OFFSET, pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, mShadow);
  79. canvas.drawCircle(pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, PIVOT_RADIUS, mShadow);
  80. canvas.drawLine(x0, y0, pivotX, pivotY, mPaint);
  81. canvas.drawCircle(pivotX, pivotY, PIVOT_RADIUS, mPaint);
  82. if (mRecorder != null && mRecorder.state() == Recorder.RECORDING_STATE)
  83. postInvalidateDelayed(ANIMATION_INTERVAL);
  84. }
  85. }

錄音類:RecordHelper.java

  1. package org.winplus.sh;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import android.content.Context;
  5. import android.media.AudioManager;
  6. import android.media.MediaPlayer;
  7. import android.media.MediaRecorder;
  8. import android.media.MediaPlayer.OnCompletionListener;
  9. import android.media.MediaPlayer.OnErrorListener;
  10. import android.os.Bundle;
  11. import android.os.Environment;
  12. public class RecordHelper implements OnCompletionListener, OnErrorListener {
  13. static final String SAMPLE_PREFIX = "recording";
  14. static final String SAMPLE_PATH_KEY = "sample_path";
  15. static final String SAMPLE_LENGTH_KEY = "sample_length";
  16. public static final int IDLE_STATE = 0;
  17. public static final int RECORDING_STATE = 1;
  18. public static final int PLAYING_STATE = 2;
  19. int mState = IDLE_STATE;
  20. public static final int NO_ERROR = 0;
  21. public static final int SDCARD_ACCESS_ERROR = 1;
  22. public static final int INTERNAL_ERROR = 2;
  23. public static final int IN_CALL_RECORD_ERROR = 3;
  24. public interface OnStateChangedListener {
  25. public void onStateChanged(int state);
  26. public void onError(int error);
  27. }
  28. OnStateChangedListener mOnStateChangedListener = null;
  29. long mSampleStart = 0; // time at which latest record or play operation started
  30. int mSampleLength = 0; // length of current sample
  31. File mSampleFile = null;
  32. MediaRecorder mRecorder = null;
  33. MediaPlayer mPlayer = null;
  34. public RecordHelper() {
  35. }
  36. public void saveState(Bundle recorderState) {
  37. recorderState.putString(SAMPLE_PATH_KEY, mSampleFile.getAbsolutePath());
  38. recorderState.putInt(SAMPLE_LENGTH_KEY, mSampleLength);
  39. }
  40. public int getMaxAmplitude() {
  41. if (mState != RECORDING_STATE)
  42. return 0;
  43. return mRecorder.getMaxAmplitude();
  44. }
  45. public void restoreState(Bundle recorderState) {
  46. String samplePath = recorderState.getString(SAMPLE_PATH_KEY);
  47. if (samplePath == null)
  48. return;
  49. int sampleLength = recorderState.getInt(SAMPLE_LENGTH_KEY, -1);
  50. if (sampleLength == -1)
  51. return;
  52. File file = new File(samplePath);
  53. if (!file.exists())
  54. return;
  55. if (mSampleFile != null
  56. && mSampleFile.getAbsolutePath().compareTo(file.getAbsolutePath()) == 0)
  57. return;
  58. delete();
  59. mSampleFile = file;
  60. mSampleLength = sampleLength;
  61. signalStateChanged(IDLE_STATE);
  62. }
  63. public void setOnStateChangedListener(OnStateChangedListener listener) {
  64. mOnStateChangedListener = listener;
  65. }
  66. public int state() {
  67. return mState;
  68. }
  69. public int progress() {
  70. if (mState == RECORDING_STATE || mState == PLAYING_STATE)
  71. return (int) ((System.currentTimeMillis() - mSampleStart)/1000);
  72. return 0;
  73. }
  74. public int sampleLength() {
  75. return mSampleLength;
  76. }
  77. public File sampleFile() {
  78. return mSampleFile;
  79. }
  80. /**
  81. * Resets the recorder state. If a sample was recorded, the file is deleted.
  82. */
  83. public void delete() {
  84. stop();
  85. if (mSampleFile != null)
  86. mSampleFile.delete();
  87. mSampleFile = null;
  88. mSampleLength = 0;
  89. signalStateChanged(IDLE_STATE);
  90. }
  91. /**
  92. * Resets the recorder state. If a sample was recorded, the file is left on disk and will
  93. * be reused for a new recording.
  94. */
  95. public void clear() {
  96. stop();
  97. mSampleLength = 0;
  98. signalStateChanged(IDLE_STATE);
  99. }
  100. public void startRecording(int outputfileformat, String extension, Context context) {
  101. stop();
  102. if (mSampleFile == null) {
  103. File sampleDir = Environment.getExternalStorageDirectory();
  104. if (!sampleDir.canWrite()) // Workaround for broken sdcard support on the device.
  105. sampleDir = new File("/sdcard/sdcard");
  106. try {
  107. mSampleFile = File.createTempFile(SAMPLE_PREFIX, extension, sampleDir);
  108. } catch (IOException e) {
  109. setError(SDCARD_ACCESS_ERROR);
  110. return;
  111. }
  112. }
  113. mRecorder = new MediaRecorder();
  114. mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
  115. mRecorder.setOutputFormat(outputfileformat);
  116. mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
  117. mRecorder.setOutputFile(mSampleFile.getAbsolutePath());
  118. // Handle IOException
  119. try {
  120. mRecorder.prepare();
  121. } catch(IOException exception) {
  122. setError(INTERNAL_ERROR);
  123. mRecorder.reset();
  124. mRecorder.release();
  125. mRecorder = null;
  126. return;
  127. }
  128. // Handle RuntimeException if the recording couldn't start
  129. try {
  130. mRecorder.start();
  131. } catch (RuntimeException exception) {
  132. AudioManager audioMngr = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
  133. boolean isInCall = ((audioMngr.getMode() == AudioManager.MODE_IN_CALL) ||
  134. (audioMngr.getMode() == AudioManager.MODE_IN_COMMUNICATION));
  135. if (isInCall) {
  136. setError(IN_CALL_RECORD_ERROR);
  137. } else {
  138. setError(INTERNAL_ERROR);
  139. }
  140. mRecorder.reset();
  141. mRecorder.release();
  142. mRecorder = null;
  143. return;
  144. }
  145. mSampleStart = System.currentTimeMillis();
  146. setState(RECORDING_STATE);
  147. }
  148. public void stopRecording() {
  149. if (mRecorder == null)
  150. return;
  151. mRecorder.stop();
  152. mRecorder.release();
  153. mRecorder = null;
  154. mSampleLength = (int)( (System.currentTimeMillis() - mSampleStart)/1000 );
  155. setState(IDLE_STATE);
  156. }
  157. public void startPlayback() {
  158. stop();
  159. mPlayer = new MediaPlayer();
  160. try {
  161. mPlayer.setDataSource(mSampleFile.getAbsolutePath());
  162. mPlayer.setOnCompletionListener(this);
  163. mPlayer.setOnErrorListener(this);
  164. mPlayer.prepare();
  165. mPlayer.start();
  166. } catch (IllegalArgumentException e) {
  167. setError(INTERNAL_ERROR);
  168. mPlayer = null;
  169. return;
  170. } catch (IOException e) {
  171. setError(SDCARD_ACCESS_ERROR);
  172. mPlayer = null;
  173. return;
  174. }
  175. mSampleStart = System.currentTimeMillis();
  176. setState(PLAYING_STATE);
  177. }
  178. public void stopPlayback() {
  179. if (mPlayer == null) // we were not in playback
  180. return;
  181. mPlayer.stop();
  182. mPlayer.release();
  183. mPlayer = null;
  184. setState(IDLE_STATE);
  185. }
  186. public void stop() {
  187. stopRecording();
  188. stopPlayback();
  189. }
  190. public boolean onError(MediaPlayer mp, int what, int extra) {
  191. stop();
  192. setError(SDCARD_ACCESS_ERROR);
  193. return true;
  194. }
  195. public void onCompletion(MediaPlayer mp) {
  196. stop();
  197. }
  198. private void setState(int state) {
  199. if (state == mState)
  200. return;
  201. mState = state;
  202. signalStateChanged(mState);
  203. }
  204. private void signalStateChanged(int state) {
  205. if (mOnStateChangedListener != null)
  206. mOnStateChangedListener.onStateChanged(state);
  207. }
  208. private void setError(int error) {
  209. if (mOnStateChangedListener != null)
  210. mOnStateChangedListener.onError(error);
  211. }
  212. }

界面:

  1. package org.winplus.sh;
  2. import android.app.Activity;
  3. import android.content.Context;
  4. import android.media.MediaRecorder;
  5. import android.os.Bundle;
  6. import android.os.PowerManager;
  7. import android.os.PowerManager.WakeLock;
  8. import android.util.Log;
  9. import android.view.View;
  10. import android.view.View.OnClickListener;
  11. import android.widget.Button;
  12. public class SoundHandActivity extends Activity implements OnClickListener,
  13. RecordHelper.OnStateChangedListener {
  14. private static final String TAG = "SoundHandActivity";
  15. private VUMeter mVUMeter;
  16. private RecordHelper mRecorder;
  17. private Button btnStart;
  18. private Button btnStop;
  19. WakeLock mWakeLock;
  20. @Override
  21. public void onCreate(Bundle savedInstanceState) {
  22. super.onCreate(savedInstanceState);
  23. setContentView(R.layout.main);
  24. setupViews();
  25. }
  26. public void setupViews() {
  27. PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
  28. mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,
  29. "SoundRecorder");
  30. mRecorder = new RecordHelper();
  31. mRecorder.setOnStateChangedListener(this);
  32. mVUMeter = (VUMeter) findViewById(R.id.uvMeter);
  33. mVUMeter.setRecorder(mRecorder);
  34. btnStart = (Button) findViewById(R.id.button1);
  35. btnStop = (Button) findViewById(R.id.button2);
  36. btnStart.setOnClickListener(this);
  37. btnStop.setOnClickListener(this);
  38. }
  39. @Override
  40. public void onClick(View v) {
  41. switch (v.getId()) {
  42. case R.id.button1:
  43. mRecorder.startRecording(MediaRecorder.OutputFormat.AMR_NB, ".amr",
  44. this);
  45. break;
  46. case R.id.button2:
  47. mRecorder.stop();
  48. break;
  49. }
  50. }
  51. private void updateUi() {
  52. Log.e(TAG, "=======================updateUi");
  53. mVUMeter.invalidate();
  54. }
  55. @Override
  56. public void onStateChanged(int state) {
  57. if (state == RecordHelper.PLAYING_STATE
  58. || state == RecordHelper.RECORDING_STATE) {
  59. mWakeLock.acquire(); // we don't want to go to sleep while recording
  60. // or playing
  61. } else {
  62. if (mWakeLock.isHeld())
  63. mWakeLock.release();
  64. }
  65. updateUi();
  66. }
  67. @Override
  68. public void onError(int error) {
  69. // TODO Auto-generated method stub
  70. }
  71. }

OK,沒有什麼特別的。

Android錄音時指針擺動的實現源碼下載

免費下載地址在 http://linux.linuxidc.com/

用戶名與密碼都是www.linuxidc.com

具體下載目錄在 /2012年資料/5月/13日/Android錄音時指針擺動的實現(附源碼)/

更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11

Copyright © Linux教程網 All Rights Reserved