您的位置:首页 > 移动开发 > Android开发

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

2015-05-29 18:11 447 查看
转自: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

<span style="font-size:16px;">/*

* Copyright (C) 2011 The Android Open Source Project

*

* 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.android.soundrecorder;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.drawable.Drawable;

import android.util.AttributeSet;

import android.view.View;

public class VUMeter extends View {

static final float PIVOT_RADIUS = 3.5f;

static final float PIVOT_Y_OFFSET = 10f;

static final float SHADOW_OFFSET = 2.0f;

static final float DROPOFF_STEP = 0.18f;

static final float SURGE_STEP = 0.35f;

static final long ANIMATION_INTERVAL = 70;

Paint mPaint, mShadow;

float mCurrentAngle;

Recorder mRecorder;

public VUMeter(Context context) {

super(context);

init(context);

}

public VUMeter(Context context, AttributeSet attrs) {

super(context, attrs);

init(context);

}

void init(Context context) {

Drawable background = context.getResources().getDrawable(R.drawable.vumeter);

setBackgroundDrawable(background);

mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

mPaint.setColor(Color.WHITE);

mShadow = new Paint(Paint.ANTI_ALIAS_FLAG);

mShadow.setColor(Color.argb(60, 0, 0, 0));

mRecorder = null;

mCurrentAngle = 0;

}

public void setRecorder(Recorder recorder) {

mRecorder = recorder;

invalidate();

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

final float minAngle = (float)Math.PI/8;

final float maxAngle = (float)Math.PI*7/8;

float angle = minAngle;

if (mRecorder != null)

angle += (float)(maxAngle - minAngle)*mRecorder.getMaxAmplitude()/32768;

if (angle > mCurrentAngle)

mCurrentAngle = angle;

else

mCurrentAngle = Math.max(angle, mCurrentAngle - DROPOFF_STEP);

mCurrentAngle = Math.min(maxAngle, mCurrentAngle);

float w = getWidth();

float h = getHeight();

float pivotX = w/2;

float pivotY = h - PIVOT_RADIUS - PIVOT_Y_OFFSET;

float l = h*4/5;

float sin = (float) Math.sin(mCurrentAngle);

float cos = (float) Math.cos(mCurrentAngle);

float x0 = pivotX - l*cos;

float y0 = pivotY - l*sin;

canvas.drawLine(x0 + SHADOW_OFFSET, y0 + SHADOW_OFFSET, pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, mShadow);

canvas.drawCircle(pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, PIVOT_RADIUS, mShadow);

canvas.drawLine(x0, y0, pivotX, pivotY, mPaint);

canvas.drawCircle(pivotX, pivotY, PIVOT_RADIUS, mPaint);

if (mRecorder != null && mRecorder.state() == Recorder.RECORDING_STATE)

postInvalidateDelayed(ANIMATION_INTERVAL);

}

}

</span>

录音类:RecordHelper.java

[java] view plaincopy

<span style="font-size:16px;">package org.winplus.sh;

import java.io.File;

import java.io.IOException;

import android.content.Context;

import android.media.AudioManager;

import android.media.MediaPlayer;

import android.media.MediaRecorder;

import android.media.MediaPlayer.OnCompletionListener;

import android.media.MediaPlayer.OnErrorListener;

import android.os.Bundle;

import android.os.Environment;

public class RecordHelper implements OnCompletionListener, OnErrorListener {

static final String SAMPLE_PREFIX = "recording";

static final String SAMPLE_PATH_KEY = "sample_path";

static final String SAMPLE_LENGTH_KEY = "sample_length";

public static final int IDLE_STATE = 0;

public static final int RECORDING_STATE = 1;

public static final int PLAYING_STATE = 2;

int mState = IDLE_STATE;

public static final int NO_ERROR = 0;

public static final int SDCARD_ACCESS_ERROR = 1;

public static final int INTERNAL_ERROR = 2;

public static final int IN_CALL_RECORD_ERROR = 3;

public interface OnStateChangedListener {

public void onStateChanged(int state);

public void onError(int error);

}

OnStateChangedListener mOnStateChangedListener = null;

long mSampleStart = 0; // time at which latest record or play operation started

int mSampleLength = 0; // length of current sample

File mSampleFile = null;

MediaRecorder mRecorder = null;

MediaPlayer mPlayer = null;

public RecordHelper() {

}

public void saveState(Bundle recorderState) {

recorderState.putString(SAMPLE_PATH_KEY, mSampleFile.getAbsolutePath());

recorderState.putInt(SAMPLE_LENGTH_KEY, mSampleLength);

}

public int getMaxAmplitude() {

if (mState != RECORDING_STATE)

return 0;

return mRecorder.getMaxAmplitude();

}

public void restoreState(Bundle recorderState) {

String samplePath = recorderState.getString(SAMPLE_PATH_KEY);

if (samplePath == null)

return;

int sampleLength = recorderState.getInt(SAMPLE_LENGTH_KEY, -1);

if (sampleLength == -1)

return;

File file = new File(samplePath);

if (!file.exists())

return;

if (mSampleFile != null

&& mSampleFile.getAbsolutePath().compareTo(file.getAbsolutePath()) == 0)

return;

delete();

mSampleFile = file;

mSampleLength = sampleLength;

signalStateChanged(IDLE_STATE);

}

public void setOnStateChangedListener(OnStateChangedListener listener) {

mOnStateChangedListener = listener;

}

public int state() {

return mState;

}

public int progress() {

if (mState == RECORDING_STATE || mState == PLAYING_STATE)

return (int) ((System.currentTimeMillis() - mSampleStart)/1000);

return 0;

}

public int sampleLength() {

return mSampleLength;

}

public File sampleFile() {

return mSampleFile;

}

/**

* Resets the recorder state. If a sample was recorded, the file is deleted.

*/

public void delete() {

stop();

if (mSampleFile != null)

mSampleFile.delete();

mSampleFile = null;

mSampleLength = 0;

signalStateChanged(IDLE_STATE);

}

/**

* Resets the recorder state. If a sample was recorded, the file is left on disk and will

* be reused for a new recording.

*/

public void clear() {

stop();

mSampleLength = 0;

signalStateChanged(IDLE_STATE);

}

public void startRecording(int outputfileformat, String extension, Context context) {

stop();

if (mSampleFile == null) {

File sampleDir = Environment.getExternalStorageDirectory();

if (!sampleDir.canWrite()) // Workaround for broken sdcard support on the device.

sampleDir = new File("/sdcard/sdcard");

try {

mSampleFile = File.createTempFile(SAMPLE_PREFIX, extension, sampleDir);

} catch (IOException e) {

setError(SDCARD_ACCESS_ERROR);

return;

}

}

mRecorder = new MediaRecorder();

mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);

mRecorder.setOutputFormat(outputfileformat);

mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

mRecorder.setOutputFile(mSampleFile.getAbsolutePath());

// Handle IOException

try {

mRecorder.prepare();

} catch(IOException exception) {

setError(INTERNAL_ERROR);

mRecorder.reset();

mRecorder.release();

mRecorder = null;

return;

}

// Handle RuntimeException if the recording couldn't start

try {

mRecorder.start();

} catch (RuntimeException exception) {

AudioManager audioMngr = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);

boolean isInCall = ((audioMngr.getMode() == AudioManager.MODE_IN_CALL) ||

(audioMngr.getMode() == AudioManager.MODE_IN_COMMUNICATION));

if (isInCall) {

setError(IN_CALL_RECORD_ERROR);

} else {

setError(INTERNAL_ERROR);

}

mRecorder.reset();

mRecorder.release();

mRecorder = null;

return;

}

mSampleStart = System.currentTimeMillis();

setState(RECORDING_STATE);

}

public void stopRecording() {

if (mRecorder == null)

return;

mRecorder.stop();

mRecorder.release();

mRecorder = null;

mSampleLength = (int)( (System.currentTimeMillis() - mSampleStart)/1000 );

setState(IDLE_STATE);

}

public void startPlayback() {

stop();

mPlayer = new MediaPlayer();

try {

mPlayer.setDataSource(mSampleFile.getAbsolutePath());

mPlayer.setOnCompletionListener(this);

mPlayer.setOnErrorListener(this);

mPlayer.prepare();

mPlayer.start();

} catch (IllegalArgumentException e) {

setError(INTERNAL_ERROR);

mPlayer = null;

return;

} catch (IOException e) {

setError(SDCARD_ACCESS_ERROR);

mPlayer = null;

return;

}

mSampleStart = System.currentTimeMillis();

setState(PLAYING_STATE);

}

public void stopPlayback() {

if (mPlayer == null) // we were not in playback

return;

mPlayer.stop();

mPlayer.release();

mPlayer = null;

setState(IDLE_STATE);

}

public void stop() {

stopRecording();

stopPlayback();

}

public boolean onError(MediaPlayer mp, int what, int extra) {

stop();

setError(SDCARD_ACCESS_ERROR);

return true;

}

public void onCompletion(MediaPlayer mp) {

stop();

}

private void setState(int state) {

if (state == mState)

return;

mState = state;

signalStateChanged(mState);

}

private void signalStateChanged(int state) {

if (mOnStateChangedListener != null)

mOnStateChangedListener.onStateChanged(state);

}

private void setError(int error) {

if (mOnStateChangedListener != null)

mOnStateChangedListener.onError(error);

}

}

</span>

界面:

[java] view
plaincopy

<span style="font-size:16px;">package org.winplus.sh;

import android.app.Activity;

import android.content.Context;

import android.media.MediaRecorder;

import android.os.Bundle;

import android.os.PowerManager;

import android.os.PowerManager.WakeLock;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

public class SoundHandActivity extends Activity implements OnClickListener,

RecordHelper.OnStateChangedListener {

private static final String TAG = "SoundHandActivity";

private VUMeter mVUMeter;

private RecordHelper mRecorder;

private Button btnStart;

private Button btnStop;

WakeLock mWakeLock;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

setupViews();

}

public void setupViews() {

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);

mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,

"SoundRecorder");

mRecorder = new RecordHelper();

mRecorder.setOnStateChangedListener(this);

mVUMeter = (VUMeter) findViewById(R.id.uvMeter);

mVUMeter.setRecorder(mRecorder);

btnStart = (Button) findViewById(R.id.button1);

btnStop = (Button) findViewById(R.id.button2);

btnStart.setOnClickListener(this);

btnStop.setOnClickListener(this);

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.button1:

mRecorder.startRecording(MediaRecorder.OutputFormat.AMR_NB, ".amr",

this);

break;

case R.id.button2:

mRecorder.stop();

break;

}

}

private void updateUi() {

Log.e(TAG, "=======================updateUi");

mVUMeter.invalidate();

}

@Override

public void onStateChanged(int state) {

if (state == RecordHelper.PLAYING_STATE

|| state == RecordHelper.RECORDING_STATE) {

mWakeLock.acquire(); // we don't want to go to sleep while recording

// or playing

} else {

if (mWakeLock.isHeld())

mWakeLock.release();

}

updateUi();

}

@Override

public void onError(int error) {

// TODO Auto-generated method stub

}

}</span>

源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: