Gruppe 1
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MicrophoneDetector.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. package com.example.ueberwachungssystem.Detection;
  2. import static java.lang.Math.*;
  3. import android.annotation.SuppressLint;
  4. import android.content.Context;
  5. import android.media.AudioFormat;
  6. import android.media.AudioRecord;
  7. import android.media.MediaRecorder;
  8. import android.os.AsyncTask;
  9. import android.util.Log;
  10. import com.example.ueberwachungssystem.Detection.Signalverarbeitung.Complex;
  11. import com.example.ueberwachungssystem.Detection.Signalverarbeitung.FFT;
  12. public class MicrophoneDetector extends Detector {
  13. /**
  14. * Constructor - takes context of current activity
  15. *
  16. * @param context
  17. */
  18. private AufnahmeTask aufnahmeTask;
  19. public boolean armed = false;
  20. public int schwellwertAlarm = 100;
  21. private Context context;
  22. public MicrophoneDetector(Context context) {
  23. super();
  24. this.context = context;
  25. }
  26. @Override
  27. public void startDetection() {
  28. aufnahmeTask = new AufnahmeTask();
  29. aufnahmeTask.execute();
  30. }
  31. @Override
  32. public void stopDetection() {
  33. if (aufnahmeTask != null) {
  34. aufnahmeTask.cancel(true);
  35. }
  36. }
  37. class AufnahmeTask extends AsyncTask<Long, Verarbeitungsergebnis, Void> {
  38. private AudioRecord recorder;
  39. private final int sampleRateInHz = 44100;
  40. private final int channelConfig = AudioFormat.CHANNEL_IN_MONO;
  41. private final int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
  42. private final int startDelay = 20000;
  43. private final int threadSleeptime = 10;
  44. private int minPufferGroesseInBytes;
  45. private int pufferGroesseInBytes;
  46. private RingPuffer ringPuffer = new RingPuffer(10);
  47. private float kalibierWert;
  48. private com.example.ueberwachungssystem.Detection.DetectionReport detectionReport;
  49. @SuppressLint("MissingPermission")
  50. AufnahmeTask() {
  51. minPufferGroesseInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
  52. pufferGroesseInBytes = minPufferGroesseInBytes * 2;
  53. try {
  54. recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConfig, audioFormat, pufferGroesseInBytes);
  55. } catch (Exception e) {
  56. e.printStackTrace();
  57. }
  58. Log.d("0","Puffergroeße: "+ minPufferGroesseInBytes + " " + pufferGroesseInBytes);
  59. Log.d("0","Recorder (SR, CH): "+ recorder.getSampleRate() + " " + recorder.getChannelCount());
  60. int anzahlBytesProAbtastwert;
  61. String s;
  62. switch (recorder.getAudioFormat()) {
  63. case AudioFormat.ENCODING_PCM_8BIT:
  64. s = "8 Bit PCM ";
  65. anzahlBytesProAbtastwert = 1;
  66. break;
  67. case AudioFormat.ENCODING_PCM_16BIT:
  68. s = "16 Bit PCM";
  69. anzahlBytesProAbtastwert = 2;
  70. break;
  71. case AudioFormat.ENCODING_PCM_FLOAT:
  72. s = "Float PCM";
  73. anzahlBytesProAbtastwert = 4;
  74. break;
  75. default:
  76. throw new IllegalArgumentException();
  77. }
  78. switch (recorder.getChannelConfiguration()) {
  79. case AudioFormat.CHANNEL_IN_MONO:
  80. s = "Mono";
  81. break;
  82. case AudioFormat.CHANNEL_IN_STEREO:
  83. s = "Stereo";
  84. anzahlBytesProAbtastwert *= 2;
  85. break;
  86. case AudioFormat.CHANNEL_INVALID:
  87. s = "ungültig";
  88. break;
  89. default:
  90. throw new IllegalArgumentException();
  91. }
  92. Log.d("0","Konfiguration: "+ s);
  93. }
  94. @Override
  95. protected Void doInBackground(Long... params) {
  96. recorder.startRecording();
  97. short[] puffer = new short[pufferGroesseInBytes / 2];
  98. long lastTime = System.currentTimeMillis();
  99. float verarbeitungsrate = 0;
  100. final int maxZaehlerZeitMessung = 10;
  101. int zaehlerZeitMessung = 0;
  102. int anzahlVerarbeitet = 0;
  103. GleitenderMittelwert gleitenderMittelwert = new GleitenderMittelwert(0.3f);
  104. //Kalibrierung
  105. try {
  106. Thread.sleep(startDelay); // Time to lay down the phone
  107. } catch (InterruptedException e) {
  108. e.printStackTrace();
  109. }
  110. int i = 0;
  111. for (i = 0; i < 20; i++) {
  112. int n = recorder.read(puffer, 0, puffer.length);
  113. Verarbeitungsergebnis kalibrierErgebnis = verarbeiten(puffer, n);
  114. kalibierWert += kalibrierErgebnis.maxAmp;
  115. try {
  116. Thread.sleep(threadSleeptime);
  117. } catch (InterruptedException e) {
  118. e.printStackTrace();
  119. }
  120. }
  121. kalibierWert = kalibierWert/i;
  122. // __Part of FFT__
  123. // Complex[] zeitSignal = new Complex[puffer.length];
  124. // for (int j = 0; j < puffer.length; j++) {
  125. // zeitSignal[j] = new Complex(puffer[j], 0);
  126. // }
  127. // Complex[] spektrum = FFT.fft(zeitSignal);
  128. // double[] spektrum = calculateFFT(puffer);
  129. // DataPoint AddPoint;
  130. // LineGraphSeries<DataPoint> series = new LineGraphSeries<DataPoint>(new DataPoint[]{});
  131. // for (i = 0; i < spektrum.length; i++) {
  132. // AddPoint = new DataPoint(i, spektrum[i]);
  133. // series.appendData(AddPoint, true, spektrum.length);
  134. // }
  135. // graph.addSeries(series);
  136. for (; ; ) {
  137. if (aufnahmeTask.isCancelled()) {
  138. break;
  139. } else {
  140. int n = recorder.read(puffer, 0, puffer.length);
  141. Verarbeitungsergebnis ergebnis = verarbeiten(puffer, n);
  142. anzahlVerarbeitet += n;
  143. // __Part of FFT__
  144. // spektrum = calculateFFT(puffer);
  145. // LineGraphSeries<DataPoint> newseries = new LineGraphSeries<DataPoint>(new DataPoint[]{});
  146. // for (i = 0; i < spektrum.length; i++) {
  147. // AddPoint = new DataPoint(i, spektrum[i]);
  148. // newseries.appendData(AddPoint, true, spektrum.length);
  149. // }
  150. zaehlerZeitMessung++;
  151. if (zaehlerZeitMessung == maxZaehlerZeitMessung) {
  152. long time = System.currentTimeMillis();
  153. long deltaTime = time - lastTime;
  154. verarbeitungsrate = 1000.0f * anzahlVerarbeitet / deltaTime;
  155. verarbeitungsrate = gleitenderMittelwert.mittel(verarbeitungsrate);
  156. zaehlerZeitMessung = 0;
  157. anzahlVerarbeitet = 0;
  158. lastTime = time;
  159. }
  160. ergebnis.verarbeitungsrate = (int) verarbeitungsrate;
  161. publishProgress(ergebnis);
  162. try {
  163. Thread.sleep(threadSleeptime);
  164. } catch (InterruptedException e) {
  165. e.printStackTrace();
  166. }
  167. }
  168. }
  169. recorder.release();
  170. return null;
  171. }
  172. private Verarbeitungsergebnis verarbeiten(short[] daten, int n) {
  173. String status;
  174. short maxAmp = -1;
  175. if (n == AudioRecord.ERROR_INVALID_OPERATION) {
  176. status = "ERROR_INVALID_OPERATION";
  177. } else if (n == AudioRecord.ERROR_BAD_VALUE) {
  178. status = "ERROR_BAD_VALUE";
  179. } else {
  180. status = "OK";
  181. short max = 0;
  182. for (int i = 0; i < n; i++) {
  183. if (daten[i] > max) {
  184. max = daten[i];
  185. }
  186. }
  187. ringPuffer.hinzufuegen(max);
  188. maxAmp = ringPuffer.maximum();
  189. if (maxAmp <= schwellwertAlarm + kalibierWert) {
  190. armed = true;
  191. }
  192. }
  193. return new Verarbeitungsergebnis(status, maxAmp, 0);
  194. }
  195. @Override
  196. protected void onProgressUpdate(Verarbeitungsergebnis... progress) {
  197. super.onProgressUpdate(progress);
  198. float maxAmpPrint = round(20*log10(abs(progress[0].maxAmp/1.0)));
  199. float kalibierWertPrint = round(20*log10(abs(kalibierWert)));
  200. Log.d("alarmAudio","VR: " + progress[0].verarbeitungsrate + ", Amp: " + maxAmpPrint
  201. + " dB, Kal: " + kalibierWertPrint + " dB");
  202. if (progress[0].maxAmp >= schwellwertAlarm + kalibierWert && armed == true) {
  203. armed = false;
  204. detectionReport = new DetectionReport(true, "Audio", maxAmpPrint);
  205. reportViolation("Audio", maxAmpPrint);
  206. Log.d("1",detectionReport.toString());
  207. }
  208. }
  209. }
  210. private double[] calculateFFT(short[] zeitsignal)
  211. {
  212. byte signal[] = new byte[zeitsignal.length];
  213. // loops through all the values of a Short
  214. for (int i = 0; i < zeitsignal.length-1; i++) {
  215. signal[i] = (byte) (zeitsignal[i]);
  216. signal[i+1] = (byte) (zeitsignal[i] >> 8);
  217. }
  218. final int mNumberOfFFTPoints =1024;
  219. double temp;
  220. Complex[] y;
  221. Complex[] complexSignal = new Complex[mNumberOfFFTPoints];
  222. double[] absSignal = new double[mNumberOfFFTPoints/2];
  223. for(int i = 0; i < mNumberOfFFTPoints; i++){
  224. temp = (double)((signal[2*i] & 0xFF) | (signal[2*i+1] << 8)) / 32768.0F;
  225. complexSignal[i] = new Complex(temp,0.0);
  226. }
  227. y = FFT.fft(complexSignal);
  228. for(int i = 0; i < (mNumberOfFFTPoints/2); i++)
  229. {
  230. absSignal[i] = y[i].abs();
  231. }
  232. return absSignal;
  233. }
  234. class Verarbeitungsergebnis {
  235. String status;
  236. short maxAmp;
  237. int verarbeitungsrate;
  238. Verarbeitungsergebnis(String status, short maxAmp, int verarbeitungsrate) {
  239. this.status = status;
  240. this.maxAmp = maxAmp;
  241. this.verarbeitungsrate = verarbeitungsrate;
  242. }
  243. }
  244. class RingPuffer {
  245. private short[] puffer;
  246. private final int laenge;
  247. private int anzahlEnthaltenerDaten;
  248. private int position;
  249. public RingPuffer(int n) {
  250. laenge = n;
  251. anzahlEnthaltenerDaten = 0;
  252. position = 0;
  253. puffer = new short[laenge];
  254. }
  255. public void hinzufuegen(short wert) {
  256. puffer[position] = wert;
  257. position++;
  258. if (position >= laenge) {
  259. position = 0;
  260. }
  261. if (anzahlEnthaltenerDaten < laenge) {
  262. anzahlEnthaltenerDaten++;
  263. }
  264. }
  265. public void hinzufuegen(short[] daten) {
  266. for (short d : daten) {
  267. puffer[position] = d;
  268. position++;
  269. if (position >= laenge) {
  270. position = 0;
  271. }
  272. }
  273. if (anzahlEnthaltenerDaten < laenge) {
  274. anzahlEnthaltenerDaten += daten.length;
  275. if (anzahlEnthaltenerDaten >= laenge) {
  276. anzahlEnthaltenerDaten = laenge;
  277. }
  278. }
  279. }
  280. public short maximum() {
  281. short max = 0;
  282. for (int i = 0; i < anzahlEnthaltenerDaten; i++) {
  283. if (puffer[i] > max) {
  284. max = puffer[i];
  285. }
  286. }
  287. return max;
  288. }
  289. public float mittelwert() {
  290. float summe = 0;
  291. for (int i = 0; i < anzahlEnthaltenerDaten; i++) {
  292. summe += puffer[i];
  293. }
  294. return summe / anzahlEnthaltenerDaten;
  295. }
  296. }
  297. class GleitenderMittelwert {
  298. private final float wichtungNeuerWert;
  299. private final float wichtungAlterWert;
  300. private float mittelwert = 0;
  301. private boolean istMittelwertGesetzt = false;
  302. GleitenderMittelwert(float wichtungNeuerWert) {
  303. this.wichtungNeuerWert = wichtungNeuerWert;
  304. this.wichtungAlterWert = 1 - this.wichtungNeuerWert;
  305. }
  306. float mittel(float wert) {
  307. if (istMittelwertGesetzt) {
  308. mittelwert = wert * wichtungNeuerWert + mittelwert * wichtungAlterWert;
  309. } else {
  310. mittelwert = wert;
  311. istMittelwertGesetzt = true;
  312. }
  313. return mittelwert;
  314. }
  315. }
  316. }