package com.example.greenwatch.sensors; import android.media.AudioFormat; import android.media.AudioRecord; import android.media.MediaRecorder; import android.os.AsyncTask; import androidx.lifecycle.MutableLiveData; import com.example.greenwatch.sensors.MicrofonHelperClasses.GleitenderMittelwert; import com.example.greenwatch.sensors.MicrofonHelperClasses.RingPuffer; import com.example.greenwatch.sensors.MicrofonHelperClasses.Verarbeitungsergebnis; public class MicrofonSensor { private MutableLiveData mMicrofonAlarmDetected = new MutableLiveData<>(); private AufnahmeTask aufnahmeTask; private static MicrofonSensor microfonSensorInstance; private boolean microfonAlarmDetected = false; private boolean kalibrierung_do = true; private float threshold = 40; private float sensitivity = 10; private float amplitudeInDB = 0; private RingPuffer ringPuffer = new RingPuffer(10); private MicrofonSensor() { } public static synchronized MicrofonSensor getInstance() { if (microfonSensorInstance == null){ microfonSensorInstance = new MicrofonSensor(); } return microfonSensorInstance; } public void start() { aufnahmeTask = new AufnahmeTask(); aufnahmeTask.execute(); } public void stop() { if(aufnahmeTask !=null) { aufnahmeTask.cancel(true); aufnahmeTask = null; } } public void doRecalibration() { stop(); microfonAlarmDetected = false; kalibrierung_do = true; threshold = 40; sensitivity = 10; amplitudeInDB = 0; } public float getAmplitudeInDB() { return amplitudeInDB; } private void setAmplitudeInDB(float amplitudeInDB) { this.amplitudeInDB = amplitudeInDB; } public MutableLiveData getAccelerometerAlarmDetected() { setMutableLiveDataMicrofonAlarmDetected(); return mMicrofonAlarmDetected; } private void setMutableLiveDataMicrofonAlarmDetected() { mMicrofonAlarmDetected.setValue(microfonAlarmDetected); } class AufnahmeTask extends AsyncTask { private AudioRecord recorder; private final int sampleRateInHz = 44100; private final int channelConfig = AudioFormat.CHANNEL_IN_MONO; private final int audioFormat = AudioFormat.ENCODING_PCM_16BIT; private int minPufferGroesseInBytes; private int pufferGroesseInBytes; public AufnahmeTask() { minPufferGroesseInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); pufferGroesseInBytes = minPufferGroesseInBytes * 2; recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConfig, audioFormat, pufferGroesseInBytes); } public float kalibrieren(short[] puffer){ try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } int anzahlIterationen = 100; float sum = 0.0f; for(int i = 0; i < anzahlIterationen; i++){ int z = recorder.read(puffer, 0, puffer.length); Verarbeitungsergebnis kalibrierung = verarbeiten(puffer, z); sum += kalibrierung.getDB(); } return sum/anzahlIterationen; } public void Detektion(Verarbeitungsergebnis ergebnis){ if(ergebnis.getDB() >= (threshold+sensitivity)){ microfonAlarmDetected = true; } else if (ergebnis.getDB() <= (threshold)) { microfonAlarmDetected = false; } } @Override protected Void doInBackground(Long... params) { recorder.startRecording(); short[] puffer = new short[pufferGroesseInBytes / 2]; GleitenderMittelwert gleitenderMittelwertdB = new GleitenderMittelwert(0.2f); float db = 0.0f; //kalibrierung if(kalibrierung_do){ threshold = kalibrieren(puffer); kalibrierung_do = false; } for (; ; ) { if (isCancelled()) { break; } else { //ergebnis ermitteln int n = recorder.read(puffer, 0, puffer.length); Verarbeitungsergebnis ergebnis = verarbeiten(puffer, n); //Mittelwertberechnnung db = ergebnis.getDB(); db = gleitenderMittelwertdB.mittel(db); ergebnis.setDB(db); //Db Wert mit Schwellwert vergleichen und Warnung setzen Detektion(ergebnis); publishProgress(ergebnis); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } recorder.release(); return null; } private Verarbeitungsergebnis verarbeiten(short[] daten, int n) { String status; short maxAmp = -1; int db = 0, db_wert = 0; if (n == AudioRecord.ERROR_INVALID_OPERATION) { status = "ERROR_INVALID_OPERATION"; } else if (n == AudioRecord.ERROR_BAD_VALUE) { status = "ERROR_BAD_VALUE"; } else { status = "OK"; short max = 0; for (int i = 0; i < n; i++) { if (daten[i] > max) { max = daten[i]; } } ringPuffer.hinzufuegen(max); maxAmp = ringPuffer.maximum(); } //Umwandlung Amplitudenwert in dB db_wert = (int) (20*Math.log10(maxAmp)); if (db_wert > 0){ db = db_wert; } return new Verarbeitungsergebnis(status, maxAmp, db); } @Override protected void onProgressUpdate(Verarbeitungsergebnis... progress) { super.onProgressUpdate(progress); setAmplitudeInDB(progress[0].getDB()); if (microfonAlarmDetected != mMicrofonAlarmDetected.getValue()){ setMutableLiveDataMicrofonAlarmDetected(); } //textViewMaxAmpdb.setText("" + progress[0].db); } } }