Create a Spectrum Analyzer with an Android app that captures sound from a microphone, analyzes the frequency, and displays the spectrum. (I haven't released it, because I can't make something that will be released) ** Moreover, the problem remains. ** **
Graph drawing library [MPAndroidChart] is used.
Edit build.gradle to install MPAndroidChart. There are two types of build.gradle, directly under the root of the project and in the app folder. Add the following to build.gradle directly under the root
build.gradle(Project)
allprojects {
repositories {
maven {
url "https://jitpack.io"
}
}
}
Add the following to build.gradle in the app folder
build.gradle(app)
dependencies {
implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'
}
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;
//In MainActivity
public LineChart lineChart;
//in onCreate
lineChart = findViewById(R.id.line_chart);
initChart();
//Inside onCheckedChanged (because I'm using Switch)
fft = new Thread(new Runnable() {
@Override
public void run() {
//After processing such as Fourier transform
setData(decibelFrequencySpectrum);
}
});
fft.start();
InitChart method to initialize the graph
initChart
public void initChart() {
lineChart.setTouchEnabled(true);
lineChart.setDragEnabled(false);
//Grid background color
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 vertical line is broken line
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-axis maximum / minimum setting
leftAxis.setAxisMaximum(0f);
leftAxis.setAxisMinimum(-150f);
//Grid horizontal axis is broken line
leftAxis.enableGridDashedLine(10f, 10f, 0f);
leftAxis.setDrawZeroLine(true);
//Scale on the right
lineChart.getAxisRight().setEnabled(false);
}
SetData method that records with a microphone and draws the Fourier transformed data
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);
}
}
The graph is displayed properly. Press the Switch on the top left to start recording and draw the spectrum.
When I press Switch, recording starts but the graph is not drawn. Why?
It was drawn. The graph does not move when you release your hand. If you touch it, the graph will be updated. Why?
I changed lineChart.setTouchEnabled (True)
to False
in initChart, but this time it disappeared at all. There is no change even if you touch the graph.
~~ Please tell me how to improve ~~
Added lineChart.invalidate ()
to update the graph to the setData method in the fft thread.
I still got an error. The cause is an error caused by trying to change the UI in a thread other than the main thread.
Therefore, it is solved by requesting the main thread to process the setData method using Handler
.
Click here for new code
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;
//In MainActivity
public LineChart lineChart;
//in onCreate
lineChart = findViewById(R.id.line_chart);
initChart();
//Inside onCheckedChanged (because I'm using Switch)
fft = new Thread(new Runnable() {
@Override
public void run() {
//After processing such as Fourier transform
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);
}
}
Recommended Posts