From f2b85fb4e701d4bf4ceea8dcf550653b158def9a Mon Sep 17 00:00:00 2001 From: proelssju74689 Date: Wed, 7 Jun 2023 13:48:36 +0200 Subject: [PATCH] Mikrofon Activity commit im Nachhinein --- .../java/com/example/greenwatch/Mikrofon.java | 399 ++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 app/src/main/java/com/example/greenwatch/Mikrofon.java diff --git a/app/src/main/java/com/example/greenwatch/Mikrofon.java b/app/src/main/java/com/example/greenwatch/Mikrofon.java new file mode 100644 index 0000000..16dd0d2 --- /dev/null +++ b/app/src/main/java/com/example/greenwatch/Mikrofon.java @@ -0,0 +1,399 @@ +package com.example.greenwatch; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import android.Manifest; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.media.AudioFormat; +import android.media.AudioRecord; +import android.media.MediaRecorder; +import android.os.AsyncTask; +import android.os.Bundle; +import android.widget.TextView; + +import java.text.SimpleDateFormat; +import java.util.Date; + +public class Mikrofon extends AppCompatActivity { + + private AufnahmeTask aufnahmeTask; + private TextView textViewMaxAmp; + private TextView textViewMaxAmpdb; + private TextView textViewZeitstempel; + private static final int RECHTEANFORDERUNG_MIKROFON = 1; + + private boolean detection_mic = false; + private String zeit = "0"; + private boolean kalibrierung_do; + private float threshold = 40; + private float sensitivity = 5; + private final static String KEY_WERT = "KEY_WERT_" + Mikrofon.class.getSimpleName(); + private final static String KEY_KALIBRIERUNG = "KEY_KALIBRIERUNG_" + Mikrofon.class.getSimpleName(); + + + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_mikrofon); + textViewMaxAmp = (TextView) findViewById(R.id.textViewMaxAmp); + textViewMaxAmpdb = (TextView) findViewById(R.id.textViewMaxAmpdb); + textViewZeitstempel = (TextView) findViewById(R.id.textViewZeitstempel); + //kalibrierung_do = true; + + + } + + + @Override + protected void onResume() { + super.onResume(); + SharedPreferences p = getPreferences(Context.MODE_PRIVATE); + threshold = p.getFloat(KEY_WERT, 40); + kalibrierung_do = p.getBoolean(KEY_KALIBRIERUNG, true); + + if (!istZugriffAufMikrofonErlaubt()) { + zugriffAufMikrofonAnfordern(); + } + if (istZugriffAufMikrofonErlaubt()) { + aufnahmeTask = new AufnahmeTask(); + aufnahmeTask.execute(); + } + } + + @Override + protected void onPause() { + super.onPause(); + SharedPreferences p = getPreferences(Context.MODE_PRIVATE); + SharedPreferences.Editor editor = p.edit(); + editor.putFloat(KEY_WERT, threshold); + if(isFinishing()==true){ + editor.putBoolean(KEY_KALIBRIERUNG, true); + }else { + editor.putBoolean(KEY_KALIBRIERUNG, false); + } + editor.commit(); + if(aufnahmeTask!=null) { + aufnahmeTask.cancel(true); + aufnahmeTask = null; + } + } + + private boolean istZugriffAufMikrofonErlaubt() { + if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + return false; + } else { + return true; + } + } + + private void zugriffAufMikrofonAnfordern() { + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, RECHTEANFORDERUNG_MIKROFON); + } + + public static String Zeitpunkt(){ + Long tslong = System.currentTimeMillis(); + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); + Date date = new Date(tslong); + String resultdate = sdf.format(date); + + return resultdate; + } + + + 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; + private RingPuffer ringPuffer = new RingPuffer(10); + + AufnahmeTask() { + minPufferGroesseInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); + pufferGroesseInBytes = minPufferGroesseInBytes * 2; + recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConfig, audioFormat, pufferGroesseInBytes); + + int anzahlBytesProAbtastwert; + String s; + switch (recorder.getAudioFormat()) { + case AudioFormat.ENCODING_PCM_8BIT: + s = "8 Bit PCM "; + anzahlBytesProAbtastwert = 1; + break; + case AudioFormat.ENCODING_PCM_16BIT: + s = "16 Bit PCM"; + anzahlBytesProAbtastwert = 2; + break; + case AudioFormat.ENCODING_PCM_FLOAT: + s = "Float PCM"; + anzahlBytesProAbtastwert = 4; + break; + default: + throw new IllegalArgumentException(); + } + + switch (recorder.getChannelConfiguration()) { + case AudioFormat.CHANNEL_IN_MONO: + s = "Mono"; + break; + case AudioFormat.CHANNEL_IN_STEREO: + s = "Stereo"; + anzahlBytesProAbtastwert *= 2; + break; + case AudioFormat.CHANNEL_INVALID: + s = "ungültig"; + break; + default: + throw new IllegalArgumentException(); + } + + } + + + @Override + protected Void doInBackground(Long... params) { + + recorder.startRecording(); + short[] puffer = new short[pufferGroesseInBytes / 2]; + long lastTime = System.currentTimeMillis(); + float verarbeitungsrate = 0; + final int maxZaehlerZeitMessung = 10; + int zaehlerZeitMessung = 0; + int anzahlVerarbeitet = 0; + GleitenderMittelwert gleitenderMittelwert = new GleitenderMittelwert(0.3f); + GleitenderMittelwert gleitenderMittelwertdB = new GleitenderMittelwert(0.1f); + float db = 0; + boolean erlaubt_rise = true; + boolean erlaubt_fall = true; + + + + for (; ; ) { + if (isCancelled()) { + break; + } else { + int n = recorder.read(puffer, 0, puffer.length); + Verarbeitungsergebnis ergebnis = verarbeiten(puffer, n); + anzahlVerarbeitet += n; + + //kalibrierung + if(kalibrierung_do){ + // Warten für 3 Sekunden + /*long startTime = System.currentTimeMillis(); // Startzeit + while (System.currentTimeMillis() - startTime < 3000) { + //Warten + }*/ + //3s warten auf weitere Ausführung + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + //int z = recorder.read(puffer, 0, puffer.length); + //Verarbeitungsergebnis kalibrierung = verarbeiten(puffer, z); + int anzahlIterationen = 3000; + float sum = 0; + for(int i = 0; i < anzahlIterationen; i++){ + sum += ergebnis.db; + } + threshold = sum/anzahlIterationen; + kalibrierung_do = false; + } + + + zaehlerZeitMessung++; + if (zaehlerZeitMessung == maxZaehlerZeitMessung) { + long time = System.currentTimeMillis(); + long deltaTime = time - lastTime; + verarbeitungsrate = 1000.0f * anzahlVerarbeitet / deltaTime; + verarbeitungsrate = gleitenderMittelwert.mittel(verarbeitungsrate); + zaehlerZeitMessung = 0; + anzahlVerarbeitet = 0; + lastTime = time; + } + + db = (float) ergebnis.db; + db = gleitenderMittelwertdB.mittel(db); + ergebnis.db = (int) db; + ergebnis.verarbeitungsrate = (int) verarbeitungsrate; + + //Hysterese beim Setzen bzw. Rücksetzen ob detektiert + //beim ersten detektieren wird Zeitpunkt gespeichert + if(ergebnis.db >= (threshold+sensitivity)){ + detection_mic = true; + erlaubt_fall = true; + while(erlaubt_rise){ + erlaubt_rise = false; + zeit = Zeitpunkt() + " - " + ergebnis.db + " - " + (threshold+sensitivity); //Überschreiben des Zeitpunkts beim Erkennen der Detektion + //nur zum Testen in zeit noch ergebnis.db und threshold ausgegeben -> muss am Ende nur Zeitpunkt() rein, Rest weg + } + } else if (ergebnis.db <= (threshold)) { + detection_mic = false; + erlaubt_rise = true; + while(erlaubt_fall){ + erlaubt_fall = false; + zeit = Zeitpunkt(); //erneutes Überschreiben des Zeitpunkts beim Verschwinden der Detektion + } + } + + 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; + + 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 = (int) (20*Math.log10(maxAmp)); + + return new Verarbeitungsergebnis(status, maxAmp,0, db); + } + + ///////////////////////////////////////////// + @Override + protected void onProgressUpdate(Verarbeitungsergebnis... progress) { + super.onProgressUpdate(progress); + + + System.out.println(detection_mic); + System.out.println(zeit); + textViewZeitstempel.setText(zeit); + + textViewMaxAmpdb.setText("" + progress[0].db); + textViewMaxAmp.setText("" + progress[0].maxAmp); + + } + } + ///////////////////////////////////////////// + class Verarbeitungsergebnis { + String status; + short maxAmp; + int db; + int verarbeitungsrate; + + Verarbeitungsergebnis(String status, short maxAmp, int verarbeitungsrate, int db) { + this.status = status; + this.maxAmp = maxAmp; + this.db = db; + this.verarbeitungsrate = verarbeitungsrate; + } + } + + class RingPuffer { + private short[] puffer; + private final int laenge; + private int anzahlEnthaltenerDaten; + private int position; + + public RingPuffer(int n) { + laenge = n; + anzahlEnthaltenerDaten = 0; + position = 0; + puffer = new short[laenge]; + } + + public void hinzufuegen(short wert) { + puffer[position] = wert; + position++; + if (position >= laenge) { + position = 0; + } + if (anzahlEnthaltenerDaten < laenge) { + anzahlEnthaltenerDaten++; + } + } + + public void hinzufuegen(short[] daten) { + for (short d : daten) { + puffer[position] = d; + position++; + if (position >= laenge) { + position = 0; + } + } + if (anzahlEnthaltenerDaten < laenge) { + anzahlEnthaltenerDaten += daten.length; + if (anzahlEnthaltenerDaten >= laenge) { + anzahlEnthaltenerDaten = laenge; + } + } + } + + public short maximum() { + short max = 0; + for (int i = 0; i < anzahlEnthaltenerDaten; i++) { + if (puffer[i] > max) { + max = puffer[i]; + } + } + return max; + } + + public float mittelwert() { + float summe = 0; + for (int i = 0; i < anzahlEnthaltenerDaten; i++) { + summe += puffer[i]; + } + return summe / anzahlEnthaltenerDaten; + } + } + + class GleitenderMittelwert { + private final float wichtungNeuerWert; + private final float wichtungAlterWert; + private float mittelwert = 0; + private boolean istMittelwertGesetzt = false; + + GleitenderMittelwert(float wichtungNeuerWert) { + this.wichtungNeuerWert = wichtungNeuerWert; + this.wichtungAlterWert = 1 - this.wichtungNeuerWert; + } + + float mittel(float wert) { + if (istMittelwertGesetzt) { + mittelwert = wert * wichtungNeuerWert + mittelwert * wichtungAlterWert; + } else { + mittelwert = wert; + istMittelwertGesetzt = true; + } + return mittelwert; + } + + + } + +} \ No newline at end of file