メモ書き、その他色々。

androidに挑戦中2

| コメント(0) | トラックバック(0)
しばらく更新していませんでしたが、少し進展したのでソースを公開します。
ソースは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
}


一応、それっぽい動きをするのですが、スムーズが動きにするのが次の課題ですかね。

トラックバック(0)

トラックバックURL: http://big-band.sakura.ne.jp/mt/mt-tb.cgi/55

コメントする

このブログ記事について

このページは、minetakeが2011年3月28日 23:00に書いたブログ記事です。

ひとつ前のブログ記事は「androidに挑戦中」です。

次のブログ記事は「MacでPHP開発環境1」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。