Browse Source

Kapselung in Funktionen;

Mikrofon
Franziska Bausewein 1 year ago
parent
commit
144b8eb676

+ 23
- 0
app/src/main/java/com/example/greenwatch/GleitenderMittelwert.java View File

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;
}}

+ 52
- 211
app/src/main/java/com/example/greenwatch/Mikrofon.java View File

private final static String KEY_WERT = "KEY_WERT_" + Mikrofon.class.getSimpleName(); private final static String KEY_WERT = "KEY_WERT_" + Mikrofon.class.getSimpleName();
private final static String KEY_KALIBRIERUNG = "KEY_KALIBRIERUNG_" + Mikrofon.class.getSimpleName(); private final static String KEY_KALIBRIERUNG = "KEY_KALIBRIERUNG_" + Mikrofon.class.getSimpleName();


//zu speichernde Daten: detection_mic, zeit,
// kalibrierung_do (Unterscheidung, ob Activity aus Benutzersicht (back-Taste --> erneuter Start führt zu erneutem Kalbireren) oder durch Kippen beendet (isFinishing()==false und nicht ernuet kalbrieren),
//threshold + sensitivity speichern, damit beim Kippen das nicht verloren geht,
//Verarbeitungsergebnis ergebnis in der doInBackground Funktion muss auch gespeichert werden, da dort der aktuelle db-Wert enthalten ist --> sonst machen Werte kurz nach dem Kippen keinen Sinn mehr
//aktuell noch SharedPref bei kalibrierung_do und threshold implementiert --> kann nach erfolgreichem Einbinden in Model entfernt werden
//Infos zu Variablen:
//detection_mic: solange true, solange ergebnis.db > threshold+sensitivity -> wird false, sobald ergebnis.db < threshold
//zeit: wird sowohl bei Beginn der Detektion als auch beim Ende der Detektion aktualisiert
//Funktion der App: nach Start 3s Thread.sleep, damit man das Handy positionieren kann -> Kalibrierung folgt, dauert mehrere Sekunden, erst nach Kalbrierung werden Werte angezeigt
//offenes Problem: beim allerersten Start nach der Installation wird der alte Kalbrierwert verwendet und nicht erneut kalibriert --> nach Einbinden Verhalten erneut prüfen






textViewMaxAmp = (TextView) findViewById(R.id.textViewMaxAmp); textViewMaxAmp = (TextView) findViewById(R.id.textViewMaxAmp);
textViewMaxAmpdb = (TextView) findViewById(R.id.textViewMaxAmpdb); textViewMaxAmpdb = (TextView) findViewById(R.id.textViewMaxAmpdb);
textViewZeitstempel = (TextView) findViewById(R.id.textViewZeitstempel); textViewZeitstempel = (TextView) findViewById(R.id.textViewZeitstempel);
//kalibrierung_do = true;



} }



@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
private int minPufferGroesseInBytes; private int minPufferGroesseInBytes;
private int pufferGroesseInBytes; private int pufferGroesseInBytes;
private RingPuffer ringPuffer = new RingPuffer(10); private RingPuffer ringPuffer = new RingPuffer(10);
private boolean erlaubt_rise = true;
private boolean erlaubt_fall = true;


AufnahmeTask() { AufnahmeTask() {
minPufferGroesseInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); minPufferGroesseInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
pufferGroesseInBytes = minPufferGroesseInBytes * 2; pufferGroesseInBytes = minPufferGroesseInBytes * 2;
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConfig, audioFormat, pufferGroesseInBytes); recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConfig, audioFormat, pufferGroesseInBytes);
}
//hi
public float kalibrieren(short[] puffer){
try {
Thread.sleep(3000);


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();
} catch (InterruptedException e) {
e.printStackTrace();
} }

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();
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 @Override
protected Void doInBackground(Long... params) { protected Void doInBackground(Long... params) {


recorder.startRecording(); recorder.startRecording();
short[] puffer = new short[pufferGroesseInBytes / 2]; 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.2f); GleitenderMittelwert gleitenderMittelwertdB = new GleitenderMittelwert(0.2f);
float db = 0; float db = 0;
boolean erlaubt_rise = true;
boolean erlaubt_fall = true;



//kalibrierung //kalibrierung
if(kalibrierung_do){ if(kalibrierung_do){
//3s warten auf weitere Ausführung
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}

int anzahlIterationen = 100;
float sum = 0;
//Mittelwertbildung für kalibrierten threshold
for(int i = 0; i < anzahlIterationen; i++){
if (isCancelled()) {
break;
} else {
int z = recorder.read(puffer, 0, puffer.length);
Verarbeitungsergebnis kalibrierung = verarbeiten(puffer, z);
sum += (float) kalibrierung.db;
System.out.println("Kalibrierungswert zum Testen" + kalibrierung.db);
}

}
threshold = sum/anzahlIterationen;
threshold = kalibrieren(puffer);
kalibrierung_do = false; kalibrierung_do = false;
} }


if (isCancelled()) { if (isCancelled()) {
break; break;
} else { } else {
//ergebnis ermitteln
int n = recorder.read(puffer, 0, puffer.length); int n = recorder.read(puffer, 0, puffer.length);
Verarbeitungsergebnis ergebnis = verarbeiten(puffer, n); Verarbeitungsergebnis ergebnis = verarbeiten(puffer, n);
anzahlVerarbeitet += n;

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;
}


//Mittelwertberechnnung
db = (float) ergebnis.db; db = (float) ergebnis.db;
db = gleitenderMittelwertdB.mittel(db); db = gleitenderMittelwertdB.mittel(db);
ergebnis.db = (int) 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; //solange true, solange ergebnis.db > threshold+sensitivity
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
//Amplitude zum Zeitpunkt der Detektion steht in ergebnis.db, wird zyklisch bei jedem Durchlauf der for-Schleife überschrieben
}
} 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
}
}


//Db Wert mit Schwellwert vergleichen und Warnung setzen
Detektion(ergebnis);
publishProgress(ergebnis); publishProgress(ergebnis);



try { try {
Thread.sleep(10); Thread.sleep(10);
} catch (InterruptedException e) { } catch (InterruptedException e) {
private Verarbeitungsergebnis verarbeiten(short[] daten, int n) { private Verarbeitungsergebnis verarbeiten(short[] daten, int n) {
String status; String status;
short maxAmp = -1; short maxAmp = -1;
int db = 0, wert_db = 0;
int db = 0, db_wert = 0;


if (n == AudioRecord.ERROR_INVALID_OPERATION) { if (n == AudioRecord.ERROR_INVALID_OPERATION) {
status = "ERROR_INVALID_OPERATION"; status = "ERROR_INVALID_OPERATION";
maxAmp = ringPuffer.maximum(); maxAmp = ringPuffer.maximum();
} }
//Umwandlung Amplitudenwert in dB //Umwandlung Amplitudenwert in dB
wert_db = (int) (20*Math.log10(maxAmp));

if(wert_db > 0){
db = wert_db;
db_wert = (int) (20*Math.log10(maxAmp));
if (db_wert > 0){
db = db_wert;
} }




return new Verarbeitungsergebnis(status, maxAmp,0, db);
return new Verarbeitungsergebnis(status, maxAmp, db);
} }


///////////////////////////////////////////// /////////////////////////////////////////////
} }
} }
///////////////////////////////////////////// /////////////////////////////////////////////
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;
}


}


}
}

+ 63
- 0
app/src/main/java/com/example/greenwatch/RingPuffer.java View File

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;
}*/
}


+ 13
- 0
app/src/main/java/com/example/greenwatch/Verarbeitungsergebnis.java View File

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;
}
}

+ 0
- 0
gradlew View File


Loading…
Cancel
Save