しばらく更新していませんでしたが、少し進展したのでソースを公開します。
ソースは2つに分かれています。
まず、マイクから音を受け取るスレッドです。
SoundSwitch.java
package jp.sakura;
import java.util.Arrays;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
public class SoundSwitch implements Runnable {
private OnReachedVolumeListener mListener;
private boolean isRecording = true;
private static final int SAMPLE_RATE = 8000; //8000, 11025, 22050
// graxyだと44100がちょうどいい感じです。なぜかは不明調査中です。
int bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSize * 4);
short[] buffer = new short[bufferSize];
public void stop(){
isRecording = false;
audioRecord.stop();
audioRecord.release();
}
public void setOnVolumeReachedListener(OnReachedVolumeListener listener){
mListener = listener;
}
public interface OnReachedVolumeListener {
void OnReachedVolum( short volume );
}
public void run() {
synchronized (this) {
audioRecord.startRecording();
int bufferCnt = 0;
while(isRecording){
bufferCnt += audioRecord.read(buffer, 0, bufferSize);
//audioRecord.read(buffer, 0, bufferSize);
short max = 0;
Arrays.sort(buffer);
short volts = buffer[buffer.length-1];
if( mListener != null){
// MeterAnima 37行目へ
// -30db 〜 0db
if( volts > 1000 ){
max = volts;
}
mListener.OnReachedVolum(max);
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
}
}
audioRecord.stop();
audioRecord.release();
}
}
次は画面側のソースです。
MeterAnima.java
package jp.sakura;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MeterAnima extends Activity {
// 最大値
float max;
// ハンドラー
Handler handler = new Handler();
// マイクからの入力
public float inputVolts;
private SoundSwitch mSoundSwitch;
// private CanvasView view;
private MySurfaceView view;
// 針の長さ
int needle = 150;
Thread mainLoop;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Canvasインスタンス
view = new MySurfaceView(this);
setContentView(view);
mSoundSwitch = new SoundSwitch();
mSoundSwitch
.setOnVolumeReachedListener(new SoundSwitch.OnReachedVolumeListener() {
public void OnReachedVolum(final short volume) {
handler.post(new Runnable() {
public void run() {
inputVolts = volume;
view.doDraw();
}
});
}
});
new Thread(mSoundSwitch).start();
}
class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private static final int LAYER_FLAGS = Canvas.MATRIX_SAVE_FLAG |
Canvas.CLIP_SAVE_FLAG |
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
Canvas.CLIP_TO_LAYER_SAVE_FLAG;
public MySurfaceView(Context context) {
super(context);
getHolder().addCallback(this);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.d("TEST", "surfaceChanged");
}
public void surfaceCreated(SurfaceHolder holder) {
// Log.d("TEST", "surfaceCreated");
Canvas canvas = holder.lockCanvas();
Path Path = new Path();
Path.moveTo(-needle, -0);
Path.lineTo(0, -3);
Path.lineTo(0, 0);
Path.lineTo(0, 3);
Path.close();
holder.unlockCanvasAndPost(canvas);
}
void doDraw() {
synchronized (this) {
Canvas canvas = getHolder().lockCanvas();
Paint paint = new Paint();
Path Path = new Path();
Path.moveTo(-needle, -0);
Path.lineTo(0, -3);
Path.lineTo(0, 0);
Path.lineTo(0, 3);
Path.close();
if (canvas != null) {
int w = canvas.getWidth();
int h = canvas.getHeight();
int cx = w / 2;
int cy = h / 2;
canvas.drawColor(Color.WHITE);
canvas.saveLayerAlpha(0, 0, w, h, 0x88, LAYER_FLAGS);
paint.setColor(Color.BLUE);
paint.setAntiAlias(true);
paint.setTextSize(20);
max = inputVolts;
// db(デシベルを求める)ウィキペディア「デシベル」参照
float val = (float) (20.0 * Math.log10(max / 32767.0));
// 180度 -30db 〜 0db
//float angle = 180 + val * (180 / 30);
float angle = 120 + val * (120 / 30);
paint.setStrokeWidth(5);
canvas.drawPoint(0, 0, paint);
canvas.drawText("inputVolts : " + inputVolts, 0, paint
.getTextSize(), paint);
canvas.drawText("val : " + val, 0, paint.getTextSize() * 2,
paint);
canvas.drawText("angle : " + angle, 0,
paint.getTextSize() * 3, paint);
float leftArc = cx - 160;
float topArc = cy - 160;
float rightArc = cx + 160;
float bottomArc = cy + 160;
paint.setColor(Color.RED);
RectF rect = new RectF(leftArc, topArc, rightArc, bottomArc);
canvas.drawArc(rect, 180, 180, true, paint);
float leftArcB = cx - needle;
float topArcB = cy - needle;
float rightArcB = cx + needle;
float bottomArcB = cy + needle;
paint.setColor(Color.BLUE);
RectF rectB = new RectF(leftArcB, topArcB, rightArcB, bottomArcB);
canvas.drawArc(rectB, 200, 140, true, paint);
// Paint paint = Paint;
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(cx, cy, 5, paint);
canvas.translate(cx, cy);
if (inputVolts != 0) {
canvas.rotate(angle + 30);
}else{
canvas.rotate(30);
}
canvas.drawPath(Path, paint);
getHolder().unlockCanvasAndPost(canvas);
}
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d("TEST", "surfaceDestroyed");
}
}
public void onPause() {
super.onPause();
mSoundSwitch.stop();
}// onpause
public void onStop() {
super.onStop();
mSoundSwitch.stop();
}// onstop
}
一応、それっぽい動きをするのですが、スムーズが動きにするのが次の課題ですかね。
コメントする