Compare commits

..
7 Commits
Author SHA1 Message Date
bauseweinfr74630 144b8eb676 Kapselung in Funktionen; 2023-06-20 16:23:42 +02:00
proelssju74689 d3d7def833 Mikrofon Activity Ausbesserung Kalibrierung;
Speicherung der dB-Werte nur, wenn positiv + Kommentare zum Verständnis der zu speichernden Variablen
2023-06-12 13:28:45 +02:00
proelssju74689 c61e56c3b5 Mikrofon Activity kalibrierung_do initialisiert 2023-06-07 15:17:28 +02:00
proelssju74689 f2b85fb4e7 Mikrofon Activity commit im Nachhinein 2023-06-07 13:48:36 +02:00
proelssju74689 32decab687 Mikrofon XML commit im Nachhinein 2023-06-07 13:47:56 +02:00
proelssju74689 f98a3580a6 Mikrofon Manifest angepasst - App läuft 2023-06-07 13:46:53 +02:00
proelssju74689 5b920359a1 Mikrofon als Activity 2023-06-07 13:39:57 +02:00
15 changed files with 450 additions and 158 deletions

No files matched your search

-7
View File
@@ -25,7 +25,6 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
namespace 'com.example.greenwatch'
}
dependencies {
@@ -36,10 +35,4 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
def camerax_version = "1.2.3"
implementation "androidx.camera:camera-camera2:${camerax_version}"
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
implementation "androidx.camera:camera-view:${camerax_version}"
}
+6 -13
View File
@@ -1,15 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.camera"/>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.greenwatch">
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
@@ -17,6 +10,9 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.GreenWatch">
<activity
android:name=".Mikrofon"
android:exported="false" />
<activity
android:name=".MainActivity"
android:exported="true">
@@ -26,9 +22,6 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".KameraAktivitaet" />
</application>
</manifest>
@@ -0,0 +1,23 @@
package com.example.greenwatch;
public 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;
}}
@@ -1,59 +0,0 @@
package com.example.greenwatch;
import android.graphics.ImageFormat;
import android.media.Image;
import android.os.Bundle;
import android.util.Size;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.content.ContextCompat;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.ExecutionException;
public class KameraAktivitaet extends AppCompatActivity {
private PreviewView previewView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo_kamera2_nebenaktivitaet);
previewView = findViewById(R.id.previewView);
final ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
cameraProviderFuture.addListener(() -> {
try {
bindImageAnalysis(cameraProviderFuture.get());
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}, ContextCompat.getMainExecutor(this));
}
private void bindImageAnalysis(ProcessCameraProvider cameraProvider) {
ImageAnalysis.Builder builder = new ImageAnalysis.Builder();
builder.setTargetResolution(new Size(640, 480));
builder.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST);
ImageAnalysis imageAnalysis = builder.build();
imageAnalysis.setAnalyzer(
ContextCompat.getMainExecutor(this),
imageProxy -> {
int imageFormat = imageProxy.getFormat();
if (imageFormat == ImageFormat.YUV_420_888) {
Image image = imageProxy.getImage();
}
imageProxy.close();
});
Preview preview = new Preview.Builder().build();
CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
preview.setSurfaceProvider(previewView.getSurfaceProvider());
cameraProvider.bindToLifecycle(this, cameraSelector, imageAnalysis, preview);
}
}
@@ -1,40 +1,25 @@
package com.example.greenwatch;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class MainActivity extends AppCompatActivity {
private static final int RECHTEANFORDERUNG_KAMERA = 10;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button kameraStarten = findViewById(R.id.button_camera);
kameraStarten.setOnClickListener(v -> {
if (istZugriffAufKameraErlaubt()) {
starteKameraAktivitaet();
} else {
zugriffAufKameraAnfordern();
((Button)findViewById(R.id.buttonstartmicdetection)).setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent i = new Intent(MainActivity.this, Mikrofon.class);
startActivity(i);
}
});
}
private boolean istZugriffAufKameraErlaubt() {
return ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
}
private void zugriffAufKameraAnfordern() {
ActivityCompat.requestPermissions(this,new String[]{android.Manifest.permission.CAMERA}, RECHTEANFORDERUNG_KAMERA);
}
private void starteKameraAktivitaet() {
startActivity(new Intent(this, KameraAktivitaet.class));
}
}
@@ -1,4 +1,254 @@
package com.example.greenwatch;
public class Mikrofon {
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 = true;
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<Long, Verarbeitungsergebnis, Void> {
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);
private boolean erlaubt_rise = true;
private boolean erlaubt_fall = true;
AufnahmeTask() {
minPufferGroesseInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
pufferGroesseInBytes = minPufferGroesseInBytes * 2;
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConfig, audioFormat, pufferGroesseInBytes);
}
//hi
public float kalibrieren(short[] puffer){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int anzahlIterationen = 100;
float sum = 0;
for(int i = 0; i < anzahlIterationen; i++){
int z = recorder.read(puffer, 0, puffer.length);
Verarbeitungsergebnis kalibrierung = verarbeiten(puffer, z);
sum += (float) kalibrierung.db;
System.out.println("Aktueller_Wert Kalibrierung" +kalibrierung.db);
}
System.out.println("Summe:"+sum);
return sum/anzahlIterationen;
}
public void Detektion(Verarbeitungsergebnis ergebnis){
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
}
}
}
@Override
protected Void doInBackground(Long... params) {
recorder.startRecording();
short[] puffer = new short[pufferGroesseInBytes / 2];
GleitenderMittelwert gleitenderMittelwertdB = new GleitenderMittelwert(0.2f);
float db = 0;
//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 = (float) ergebnis.db;
db = gleitenderMittelwertdB.mittel(db);
ergebnis.db = (int) 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);
System.out.println(detection_mic);
System.out.println(zeit);
textViewZeitstempel.setText(zeit);
textViewMaxAmpdb.setText("" + progress[0].db);
textViewMaxAmp.setText("" + progress[0].maxAmp);
}
}
/////////////////////////////////////////////
}
@@ -0,0 +1,63 @@
package com.example.greenwatch;
public 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;
}*/
}
@@ -0,0 +1,13 @@
package com.example.greenwatch;
public class Verarbeitungsergebnis {
String status;
short maxAmp;
int db;
//
Verarbeitungsergebnis(String status, short maxAmp, int db) {
this.status = status;
this.maxAmp = maxAmp;
this.db = db;
}
}
@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".KameraAktivitaet">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/erklaerung">
<androidx.camera.view.PreviewView
android:id="@+id/previewView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/alarm"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="" />
<TextView
android:id="@+id/luminanz"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_gravity="center"
android:gravity="center"
android:textSize="100sp"
android:textColor="#9999ff"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
+3 -7
View File
@@ -7,16 +7,12 @@
tools:context=".MainActivity">
<Button
android:id="@+id/button_camera"
android:id="@+id/buttonstartmicdetection"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Kamera starten"
android:text="Starte Mikrofon Detection"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.129"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.931" />
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
tools:activity="com.example.greenwatch">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="max. Amp: "
android:id="@+id/labelMaxAmp"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textViewMaxAmp"
android:text=" "
android:layout_alignBaseline="@+id/labelMaxAmp"
android:layout_toEndOf="@+id/labelMaxAmpdb"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="max. Amp in dB: "
android:id="@+id/labelMaxAmpdb"
android:layout_below="@+id/labelMaxAmp"
android:layout_alignParentStart="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textViewMaxAmpdb"
android:text=" "
android:layout_alignBaseline="@+id/labelMaxAmpdb"
android:layout_toEndOf="@+id/labelMaxAmpdb"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Meldung: "
android:id="@+id/labelZeitstempel"
android:layout_below="@+id/labelMaxAmpdb"
android:layout_alignParentStart="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textViewZeitstempel"
android:text=" "
android:layout_alignBaseline="@+id/labelZeitstempel"
android:layout_toEndOf="@+id/labelMaxAmpdb"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/scrollView3"
android:layout_below="@+id/labelMaxAmpdb"
android:layout_alignParentStart="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textViewLogger"/>
</ScrollView>
</RelativeLayout>
+2 -2
View File
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '8.0.0' apply false
id 'com.android.library' version '8.0.0' apply false
id 'com.android.application' version '7.1.3' apply false
id 'com.android.library' version '7.1.3' apply false
}
task clean(type: Delete) {
+1 -3
View File
@@ -18,6 +18,4 @@ android.useAndroidX=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
android.defaults.buildfeatures.buildconfig=true
android.nonFinalResIds=false
android.nonTransitiveRClass=true
+1 -1
View File
@@ -1,6 +1,6 @@
#Thu May 11 14:50:16 CEST 2023
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
Vendored Executable → Regular
View File
File mode changed.