VOOZH about

URL: https://qiita.com/tcb78/items/50442c6527930f7b0c8e

⇱ Androidアプリ Spectrum Analyzer #Java - Qiita


👁 Image
3

Go to list of users who liked

2

Share on X(Twitter)

Share on Facebook

Add to Hatena Bookmark

More than 5 years have passed since last update.

Androidアプリ Spectrum Analyzer

3
Last updated at Posted at 2019-06-21

0. はじめに

マイクから音を取得して周波数解析し、スペクトルを表示するSpectrum AnalyzerをAndroidアプリで作成。(リリースはしていません、リリースするレベルの物を作れないので)
しかも問題点が残ったまま。

グラフ描画ライブラリ【 MPAndroidChart 】を使用。

1. プロジェクトにMPAndroidChartを導入

build.gradleを編集してMPAndroidChartを導入する。
build.gradleはプロジェクトのルート直下とappフォルダ内の2種類がある。
ルート直下のbuild.gradleには以下を追加

build.gradle(Project)
allprojects {
 repositories {
 maven {
 url "https://jitpack.io"
 }
 }
}

appフォルダ内のbuild.gradleには以下を追加

build.gradle(app)
dependencies {
 implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'
}

2. ソースコード

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;

//MainActivity内
public LineChart lineChart;

//onCreate内
lineChart = findViewById(R.id.line_chart);
initChart();

//onCheckedChanged内(Switchを使っているので)
fft = new Thread(new Runnable() {
 @Override 
 public void run() {

 //フーリエ変換等処理後
 setData(decibelFrequencySpectrum);
 }
});
fft.start();

3. 初期化

グラフを初期化するinitChartメソッド

initChart
public void initChart() {

 lineChart.setTouchEnabled(true);
 lineChart.setDragEnabled(false);

 // Grid背景色
 lineChart.setDrawGridBackground(true);

 // no description text
 lineChart.getDescription().setEnabled(true);

 lineChart.setBackgroundColor(Color.LTGRAY);

 LineData data = new LineData();
 data.setValueTextColor(Color.BLACK);

 // add empty data
 lineChart.setData(data);

 // Grid縦軸を破線
 XAxis xAxis = lineChart.getXAxis();
 xAxis.setAxisMaximum(2048);
 xAxis.setAxisMinimum(0);
 xAxis.enableGridDashedLine(10f, 10f, 0f);
 xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
 YAxis leftAxis = lineChart.getAxisLeft();
 // Y軸最大最小設定
 leftAxis.setAxisMaximum(0f);
 leftAxis.setAxisMinimum(-150f);
 // Grid横軸を破線
 leftAxis.enableGridDashedLine(10f, 10f, 0f);
 leftAxis.setDrawZeroLine(true);

 // 右側の目盛り
 lineChart.getAxisRight().setEnabled(false);
}

4. 描画

マイクで録音し、フーリエ変換したデータを描画するsetDataメソッド

setData
public void setData(double[] data) {

 ArrayList<Entry> values = new ArrayList<>();

 for (int i = 0; i < data.length; i++) {
 values.add(new Entry(i, (int)data[i], null, null));
 }

 LineDataSet set1;

 if (lineChart.getData() != null && lineChart.getData().getDataSetCount() > 0) {
 set1 = (LineDataSet) lineChart.getData().getDataSetByIndex(0);
 set1.setValues(values);
 lineChart.getData().notifyDataChanged();
 lineChart.notifyDataSetChanged();
 } else {
 // create a dataset and give it a type
 set1 = new LineDataSet(values, "Spectrum");

 set1.setDrawIcons(false);
 set1.setColor(Color.rgb(0, 0, 240));
 set1. setDrawCircles(false);
 set1.setLineWidth(0.5f);
 set1.setValueTextSize(0f);
 set1.setDrawFilled(false);
 set1.setFormLineWidth(1f);
 set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f));
 set1.setFormSize(15.f);
 set1.setDrawValues(true);

 ArrayList<ILineDataSet> dataSets = new ArrayList<>();
 dataSets.add(set1); // add the datasets

 // create a data object with the datasets
 LineData lineData = new LineData(dataSets);

 // set data
 lineChart.setData(lineData);
 }
}

5. アプリ画面

5-1. 開始画面

ちゃんとグラフが表示。左上のSwitchを押すと録音が開始されてスペクトルが描画される。
👁 Image

5-2. 録音時画面

Switchを押すと録音が開始されたがグラフが描画されない。Why?
👁 Image

5-3. グラフを触ってみると

描画された。手を離すとグラフが動かなくなる。また手を触れるとグラフが更新される。Why?
👁 Image

6. 改善方法を知りたい

initChart内のlineChart.setTouchEnabled(True)Falseに変えてみたら、今度は全く表示されなくなった。グラフを触っても変化なし。

7. 改善した (2019/07/29)

fftスレッド内のsetDataメソッドにグラフを更新するlineChart.invalidate()を追加。
それでもエラーが出た。原因はメインスレッド以外のスレッドでUIを変更しようとしたことによるエラー。
そこでHandlerを使用してメインスレッドにsetDataメソッドの処理を依頼することで解決。

新しいコードはこちら

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;

//MainActivity内
public LineChart lineChart;

//onCreate内
lineChart = findViewById(R.id.line_chart);
initChart();

//onCheckedChanged内(Switchを使っているので)
fft = new Thread(new Runnable() {
 @Override 
 public void run() {

 //フーリエ変換等処理後
 handler.post(new Runnable() {
 @Override 
 public void run() {
 setData(decibelFrequencySpectrum);
 }
 });
 }
});
fft.start();
setData
public void setData(double[] data) {

 ArrayList<Entry> values = new ArrayList<>();

 for (int i = 0; i < data.length; i++) {
 values.add(new Entry(i, (int)data[i], null, null));
 }

 LineDataSet set1;

 if (lineChart.getData() != null && lineChart.getData().getDataSetCount() > 0) {
 set1 = (LineDataSet) lineChart.getData().getDataSetByIndex(0);
 set1.setValues(values);
 lineChart.getData().notifyDataChanged();
 lineChart.notifyDataSetChanged();
 lineChart.invalidate();
 } else {
 // create a dataset and give it a type
 set1 = new LineDataSet(values, "Spectrum");

 set1.setDrawIcons(false);
 set1.setColor(Color.rgb(0, 0, 240));
 set1. setDrawCircles(false);
 set1.setLineWidth(0.5f);
 set1.setValueTextSize(0f);
 set1.setDrawFilled(false);
 set1.setFormLineWidth(1f);
 set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f));
 set1.setFormSize(15.f);
 set1.setDrawValues(true);

 ArrayList<ILineDataSet> dataSets = new ArrayList<>();
 dataSets.add(set1); // add the datasets

 // create a data object with the datasets
 LineData lineData = new LineData(dataSets);

 // set data
 lineChart.setData(lineData);
 }
}
3

Go to list of users who liked

2
0

Go to list of comments

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3

Go to list of users who liked

2