#メトロノームの作成とその大まかな構成
先日よりandroidでの音ゲーを作成するために、メトロノームを作成している。
そのメトロノームの大まかな構成は、
・BPMを自分で設定できる
・動作は4拍子固定
・1拍ずつ音と対応したランプが光る。
といったものです。
##プログラムの作成
上記の構成を元にアプリのGUIを作成した。
mainactivity.xml
<ImageView
android:id="@+id/image1"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="67dp"
android:layout_marginLeft="67dp"
android:layout_marginTop="200dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
app:layout_constraintEnd_toStartOf="@+id/image2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/en" />
<ImageView
android:id="@+id/image2"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="24dp"
android:layout_marginLeft="24dp"
android:layout_marginTop="200dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
app:layout_constraintEnd_toStartOf="@+id/image3"
app:layout_constraintStart_toEndOf="@+id/image1"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/en" />
<ImageView
android:id="@+id/image3"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="24dp"
android:layout_marginLeft="24dp"
android:layout_marginTop="200dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
app:layout_constraintEnd_toStartOf="@+id/image4"
app:layout_constraintStart_toEndOf="@+id/image2"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/en" />
<ImageView
android:id="@+id/image4"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="24dp"
android:layout_marginLeft="24dp"
android:layout_marginTop="200dp"
android:layout_marginEnd="67dp"
android:layout_marginRight="67dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/image3"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/en" />
<EditText
android:id="@+id/BpM"
android:layout_width="192dp"
android:layout_height="50dp"
android:layout_marginTop="95dp"
android:layout_marginEnd="54dp"
android:layout_marginRight="54dp"
android:ems="10"
android:inputType="textPersonName"
android:text="120"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:text="BPM:"
android:textSize="26sp"
app:layout_constraintEnd_toStartOf="@+id/BpM"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/strat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="67dp"
android:layout_marginLeft="67dp"
android:layout_marginBottom="102dp"
android:text="Start"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/End"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="68dp"
android:layout_marginRight="68dp"
android:layout_marginBottom="102dp"
android:text="END"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
次に作成したプログラムを下記に記載する。
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorManager;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.InputType;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
ImageView Image1,Image2,Image3,Image4;
int i,Delay;
float X_Data,Y_Data,Z_Data;
TextView text1;
private Timer timer;
private CountUpTimerTask timerTask;
private Handler handler = new Handler();
SoundPool soundPool;
int mp3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
Image1 = findViewById(R.id.image1);
Image2 = findViewById(R.id.image2);
Image3 = findViewById(R.id.image3);
Image4 = findViewById(R.id.image4);
Button startButton = findViewById(R.id.strat);
Button endButton = findViewById(R.id.End);
EditText et = findViewById(R.id.BpM);
Image1.setImageResource(R.drawable.en);
Image2.setImageResource(R.drawable.en);
Image3.setImageResource(R.drawable.en);
Image4.setImageResource(R.drawable.en);
//EditTextに数字しか入力できないようにする
et.setInputType(InputType.TYPE_CLASS_NUMBER);
//入力された値をint型に変換
String bpm = ((EditText)findViewById(R.id.BpM)).getText().toString();
int BPM = Integer.parseInt((bpm));
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
} else {
AudioAttributes attr = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build();
soundPool = new SoundPool.Builder()
.setAudioAttributes(attr)
.setMaxStreams(5)
.build();
}
mp3 = soundPool.load(this,R.raw.pop,1);
//STARTButton
startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
i=0;
String bpm = ((EditText)findViewById(R.id.BpM)).getText().toString();
int BPM = Integer.parseInt((bpm));
Delay = 60000/BPM;
Image1.setImageResource(R.drawable.en);
Image2.setImageResource(R.drawable.en);
Image3.setImageResource(R.drawable.en);
Image4.setImageResource(R.drawable.en);
if(null != timer){
timer.cancel();
timer = null;
}
timer = new Timer();
timerTask = new CountUpTimerTask();
timer.schedule(timerTask,0,Delay);
}
});
//ENDButton
endButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(null != timer){
timer.cancel();
timer=null;
}
Image1.setImageResource(R.drawable.en);
Image2.setImageResource(R.drawable.en);
Image3.setImageResource(R.drawable.en);
Image4.setImageResource(R.drawable.en);
}
});
}
class CountUpTimerTask extends TimerTask{
@Override
public void run(){
handler.post(new Runnable() {
@Override
public void run() {
if (i == 0) {
Image1.setImageResource(R.drawable.eng);
Image4.setImageResource(R.drawable.en);
soundPool.play(mp3,2 , 2, 0, 0, 1f);
i++;
}
else if (i == 1) {
Image1.setImageResource(R.drawable.en);
Image2.setImageResource(R.drawable.eng);
soundPool.play(mp3,2 , 2, 0, 0, 1f);
i++;
}
else if (i == 2) {
Image2.setImageResource(R.drawable.en);
Image3.setImageResource(R.drawable.eng);
soundPool.play(mp3,2 , 2, 0, 0, 1f);
i++;
}
else {
Image3.setImageResource(R.drawable.en);
Image4.setImageResource(R.drawable.eng);
soundPool.play(mp3,2 , 2, 0, 0, 1f);
i = 0;
}
}
});
}
}
}
##プログラムの欠点と次に追加するもの
このプログラムでは、androidのせいなのかプログラムのせいか分からないのだが、動作途中に少しラグが発生する。そこを改善できればしたいと思う。
次に追加するものは、androidを様々な方向に振るとその都度音が出るようにしたいと思っており、現在加速度センサの変化をメトロノームの中に組み込めるかどうかを試みている。