Android录音时指针摆动的实现(附源码)

来源:互联网 发布:falcon猎鹰手表知乎 编辑:程序博客网 时间:2024/05/19 07:07

转自:http://blog.csdn.net/kazeik/article/details/7564323                    <请尊重作者的劳动成果>

转自:http://blog.csdn.net/tangcheng_ok/article/details/7561822                      <请尊重作者的劳动成果>


文中的代码主要是移植SoundRecorder的。主要是其中的VUMeter类,VUMeter是通过Recorder.getMaxAmplitude()的值计算,画出指针的偏移摆动。下面直接上代码

[java] view plaincopy
  1.     <span style="font-size:16px;">/*  
  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.         
  17.     package com.android.soundrecorder;    
  18.         
  19.     import android.content.Context;    
  20.     import android.graphics.Canvas;    
  21.     import android.graphics.Color;    
  22.     import android.graphics.Paint;    
  23.     import android.graphics.drawable.Drawable;    
  24.     import android.util.AttributeSet;    
  25.     import android.view.View;    
  26.         
  27.     public class VUMeter extends View {    
  28.         static final float PIVOT_RADIUS = 3.5f;    
  29.         static final float PIVOT_Y_OFFSET = 10f;    
  30.         static final float SHADOW_OFFSET = 2.0f;    
  31.         static final float DROPOFF_STEP = 0.18f;    
  32.         static final float SURGE_STEP = 0.35f;    
  33.         static final long  ANIMATION_INTERVAL = 70;    
  34.             
  35.         Paint mPaint, mShadow;    
  36.         float mCurrentAngle;    
  37.             
  38.         Recorder mRecorder;    
  39.         
  40.         public VUMeter(Context context) {    
  41.             super(context);    
  42.             init(context);    
  43.         }    
  44.         
  45.         public VUMeter(Context context, AttributeSet attrs) {    
  46.             super(context, attrs);    
  47.             init(context);    
  48.         }    
  49.         
  50.         void init(Context context) {    
  51.             Drawable background = context.getResources().getDrawable(R.drawable.vumeter);    
  52.             setBackgroundDrawable(background);    
  53.                 
  54.             mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);    
  55.             mPaint.setColor(Color.WHITE);    
  56.             mShadow = new Paint(Paint.ANTI_ALIAS_FLAG);    
  57.             mShadow.setColor(Color.argb(60000));    
  58.                 
  59.             mRecorder = null;    
  60.                 
  61.             mCurrentAngle = 0;    
  62.         }    
  63.         
  64.         public void setRecorder(Recorder recorder) {    
  65.             mRecorder = recorder;    
  66.             invalidate();    
  67.         }    
  68.             
  69.         @Override    
  70.         protected void onDraw(Canvas canvas) {    
  71.             super.onDraw(canvas);    
  72.         
  73.             final float minAngle = (float)Math.PI/8;    
  74.             final float maxAngle = (float)Math.PI*7/8;    
  75.                         
  76.             float angle = minAngle;    
  77.             if (mRecorder != null)    
  78.                 angle += (float)(maxAngle - minAngle)*mRecorder.getMaxAmplitude()/32768;    
  79.         
  80.             if (angle > mCurrentAngle)    
  81.                 mCurrentAngle = angle;    
  82.             else    
  83.                 mCurrentAngle = Math.max(angle, mCurrentAngle - DROPOFF_STEP);    
  84.         
  85.             mCurrentAngle = Math.min(maxAngle, mCurrentAngle);    
  86.         
  87.             float w = getWidth();    
  88.             float h = getHeight();    
  89.             float pivotX = w/2;    
  90.             float pivotY = h - PIVOT_RADIUS - PIVOT_Y_OFFSET;    
  91.             float l = h*4/5;    
  92.             float sin = (float) Math.sin(mCurrentAngle);    
  93.             float cos = (float) Math.cos(mCurrentAngle);    
  94.             float x0 = pivotX - l*cos;    
  95.             float y0 = pivotY - l*sin;    
  96.             canvas.drawLine(x0 + SHADOW_OFFSET, y0 + SHADOW_OFFSET, pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, mShadow);    
  97.             canvas.drawCircle(pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, PIVOT_RADIUS, mShadow);    
  98.             canvas.drawLine(x0, y0, pivotX, pivotY, mPaint);    
  99.             canvas.drawCircle(pivotX, pivotY, PIVOT_RADIUS, mPaint);    
  100.                 
  101.             if (mRecorder != null && mRecorder.state() == Recorder.RECORDING_STATE)    
  102.                 postInvalidateDelayed(ANIMATION_INTERVAL);    
  103.         }    
  104.     }    
  105.     </span>    
  106.   
  107.   
  108. 录音类:RecordHelper.java  
  109.   
  110. [java] view plaincopy  
  111.   
  112.     <span style="font-size:16px;">package org.winplus.sh;    
  113.         
  114.     import java.io.File;    
  115.     import java.io.IOException;    
  116.         
  117.     import android.content.Context;    
  118.     import android.media.AudioManager;    
  119.     import android.media.MediaPlayer;    
  120.     import android.media.MediaRecorder;    
  121.     import android.media.MediaPlayer.OnCompletionListener;    
  122.     import android.media.MediaPlayer.OnErrorListener;    
  123.     import android.os.Bundle;    
  124.     import android.os.Environment;    
  125.         
  126.     public class RecordHelper implements OnCompletionListener, OnErrorListener {    
  127.         static final String SAMPLE_PREFIX = "recording";    
  128.         static final String SAMPLE_PATH_KEY = "sample_path";    
  129.         static final String SAMPLE_LENGTH_KEY = "sample_length";    
  130.         
  131.         public static final int IDLE_STATE = 0;    
  132.         public static final int RECORDING_STATE = 1;    
  133.         public static final int PLAYING_STATE = 2;    
  134.             
  135.         int mState = IDLE_STATE;    
  136.         
  137.         public static final int NO_ERROR = 0;    
  138.         public static final int SDCARD_ACCESS_ERROR = 1;    
  139.         public static final int INTERNAL_ERROR = 2;    
  140.         public static final int IN_CALL_RECORD_ERROR = 3;    
  141.             
  142.         public interface OnStateChangedListener {    
  143.             public void onStateChanged(int state);    
  144.             public void onError(int error);    
  145.         }    
  146.         OnStateChangedListener mOnStateChangedListener = null;    
  147.             
  148.         long mSampleStart = 0;       // time at which latest record or play operation started    
  149.         int mSampleLength = 0;      // length of current sample    
  150.         File mSampleFile = null;    
  151.             
  152.         MediaRecorder mRecorder = null;    
  153.         MediaPlayer mPlayer = null;    
  154.             
  155.         public RecordHelper() {    
  156.         }    
  157.             
  158.         public void saveState(Bundle recorderState) {    
  159.             recorderState.putString(SAMPLE_PATH_KEY, mSampleFile.getAbsolutePath());    
  160.             recorderState.putInt(SAMPLE_LENGTH_KEY, mSampleLength);    
  161.         }    
  162.             
  163.         public int getMaxAmplitude() {    
  164.             if (mState != RECORDING_STATE)    
  165.                 return 0;    
  166.             return mRecorder.getMaxAmplitude();    
  167.         }    
  168.             
  169.         public void restoreState(Bundle recorderState) {    
  170.             String samplePath = recorderState.getString(SAMPLE_PATH_KEY);    
  171.             if (samplePath == null)    
  172.                 return;    
  173.             int sampleLength = recorderState.getInt(SAMPLE_LENGTH_KEY, -1);    
  174.             if (sampleLength == -1)    
  175.                 return;    
  176.         
  177.             File file = new File(samplePath);    
  178.             if (!file.exists())    
  179.                 return;    
  180.             if (mSampleFile != null    
  181.                     && mSampleFile.getAbsolutePath().compareTo(file.getAbsolutePath()) == 0)    
  182.                 return;    
  183.                 
  184.             delete();    
  185.             mSampleFile = file;    
  186.             mSampleLength = sampleLength;    
  187.         
  188.             signalStateChanged(IDLE_STATE);    
  189.         }    
  190.             
  191.         public void setOnStateChangedListener(OnStateChangedListener listener) {    
  192.             mOnStateChangedListener = listener;    
  193.         }    
  194.             
  195.         public int state() {    
  196.             return mState;    
  197.         }    
  198.             
  199.         public int progress() {    
  200.             if (mState == RECORDING_STATE || mState == PLAYING_STATE)    
  201.                 return (int) ((System.currentTimeMillis() - mSampleStart)/1000);    
  202.             return 0;    
  203.         }    
  204.             
  205.         public int sampleLength() {    
  206.             return mSampleLength;    
  207.         }    
  208.         
  209.         public File sampleFile() {    
  210.             return mSampleFile;    
  211.         }    
  212.             
  213.         /**  
  214.          * Resets the recorder state. If a sample was recorded, the file is deleted.  
  215.          */    
  216.         public void delete() {    
  217.             stop();    
  218.                 
  219.             if (mSampleFile != null)    
  220.                 mSampleFile.delete();    
  221.         
  222.             mSampleFile = null;    
  223.             mSampleLength = 0;    
  224.                 
  225.             signalStateChanged(IDLE_STATE);    
  226.         }    
  227.             
  228.         /**  
  229.          * Resets the recorder state. If a sample was recorded, the file is left on disk and will   
  230.          * be reused for a new recording.  
  231.          */    
  232.         public void clear() {    
  233.             stop();    
  234.                 
  235.             mSampleLength = 0;    
  236.                 
  237.             signalStateChanged(IDLE_STATE);    
  238.         }    
  239.             
  240.         public void startRecording(int outputfileformat, String extension, Context context) {    
  241.             stop();    
  242.                 
  243.             if (mSampleFile == null) {    
  244.                 File sampleDir = Environment.getExternalStorageDirectory();    
  245.                 if (!sampleDir.canWrite()) // Workaround for broken sdcard support on the device.    
  246.                     sampleDir = new File("/sdcard/sdcard");    
  247.                     
  248.                 try {    
  249.                     mSampleFile = File.createTempFile(SAMPLE_PREFIX, extension, sampleDir);    
  250.                 } catch (IOException e) {    
  251.                     setError(SDCARD_ACCESS_ERROR);    
  252.                     return;    
  253.                 }    
  254.             }    
  255.                 
  256.             mRecorder = new MediaRecorder();    
  257.             mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);    
  258.             mRecorder.setOutputFormat(outputfileformat);    
  259.             mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);    
  260.             mRecorder.setOutputFile(mSampleFile.getAbsolutePath());    
  261.         
  262.             // Handle IOException    
  263.             try {    
  264.                 mRecorder.prepare();    
  265.             } catch(IOException exception) {    
  266.                 setError(INTERNAL_ERROR);    
  267.                 mRecorder.reset();    
  268.                 mRecorder.release();    
  269.                 mRecorder = null;    
  270.                 return;    
  271.             }    
  272.             // Handle RuntimeException if the recording couldn't start    
  273.             try {    
  274.                 mRecorder.start();    
  275.             } catch (RuntimeException exception) {    
  276.                 AudioManager audioMngr = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);    
  277.                 boolean isInCall = ((audioMngr.getMode() == AudioManager.MODE_IN_CALL) ||    
  278.                         (audioMngr.getMode() == AudioManager.MODE_IN_COMMUNICATION));    
  279.                 if (isInCall) {    
  280.                     setError(IN_CALL_RECORD_ERROR);    
  281.                 } else {    
  282.                     setError(INTERNAL_ERROR);    
  283.                 }    
  284.                 mRecorder.reset();    
  285.                 mRecorder.release();    
  286.                 mRecorder = null;    
  287.                 return;    
  288.             }    
  289.             mSampleStart = System.currentTimeMillis();    
  290.             setState(RECORDING_STATE);    
  291.         }    
  292.             
  293.         public void stopRecording() {    
  294.             if (mRecorder == null)    
  295.                 return;    
  296.         
  297.             mRecorder.stop();    
  298.             mRecorder.release();    
  299.             mRecorder = null;    
  300.         
  301.             mSampleLength = (int)( (System.currentTimeMillis() - mSampleStart)/1000 );    
  302.             setState(IDLE_STATE);    
  303.         }    
  304.             
  305.         public void startPlayback() {    
  306.             stop();    
  307.                 
  308.             mPlayer = new MediaPlayer();    
  309.             try {    
  310.                 mPlayer.setDataSource(mSampleFile.getAbsolutePath());    
  311.                 mPlayer.setOnCompletionListener(this);    
  312.                 mPlayer.setOnErrorListener(this);    
  313.                 mPlayer.prepare();    
  314.                 mPlayer.start();    
  315.             } catch (IllegalArgumentException e) {    
  316.                 setError(INTERNAL_ERROR);    
  317.                 mPlayer = null;    
  318.                 return;    
  319.             } catch (IOException e) {    
  320.                 setError(SDCARD_ACCESS_ERROR);    
  321.                 mPlayer = null;    
  322.                 return;    
  323.             }    
  324.                 
  325.             mSampleStart = System.currentTimeMillis();    
  326.             setState(PLAYING_STATE);    
  327.         }    
  328.             
  329.         public void stopPlayback() {    
  330.             if (mPlayer == null// we were not in playback    
  331.                 return;    
  332.         
  333.             mPlayer.stop();    
  334.             mPlayer.release();    
  335.             mPlayer = null;    
  336.             setState(IDLE_STATE);    
  337.         }    
  338.             
  339.         public void stop() {    
  340.             stopRecording();    
  341.             stopPlayback();    
  342.         }    
  343.         
  344.         public boolean onError(MediaPlayer mp, int what, int extra) {    
  345.             stop();    
  346.             setError(SDCARD_ACCESS_ERROR);    
  347.             return true;    
  348.         }    
  349.         
  350.         public void onCompletion(MediaPlayer mp) {    
  351.             stop();    
  352.         }    
  353.             
  354.         private void setState(int state) {    
  355.             if (state == mState)    
  356.                 return;    
  357.                 
  358.             mState = state;    
  359.             signalStateChanged(mState);    
  360.         }    
  361.             
  362.         private void signalStateChanged(int state) {    
  363.             if (mOnStateChangedListener != null)    
  364.                 mOnStateChangedListener.onStateChanged(state);    
  365.         }    
  366.             
  367.         private void setError(int error) {    
  368.             if (mOnStateChangedListener != null)    
  369.                 mOnStateChangedListener.onError(error);    
  370.         }    
  371.     }    
  372.     </span>    

界面:

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

源码下载

0 0
原创粉丝点击