package de.tu.darmstadt.seemoo.ansian.tools.morse;
import android.os.AsyncTask;
import de.greenrobot.event.EventBus;
import de.greenrobot.event.Subscribe;
import de.tu.darmstadt.seemoo.ansian.control.events.morse.MorseCharPlayedEvent;
import de.tu.darmstadt.seemoo.ansian.control.events.morse.MorseDitDurationEvent;
import de.tu.darmstadt.seemoo.ansian.control.events.morse.MorseSendEvent;
import de.tu.darmstadt.seemoo.ansian.model.preferences.Preferences;
public class MorsePlayer extends AsyncTask<String, Integer, Boolean> {
@SuppressWarnings("unused")
private static final String LOGTAG = "MorsePlayer";
private char[] morseString;
private int dit, dah, word;
private MorseAudioTrack ditTrack, dahTrack;
private boolean running = true;
private void playDah() {
dahTrack.playSound();
}
private void playDit() {
ditTrack.playSound();
}
protected void onPostExecute(Boolean result) {
ditTrack.release();
dahTrack.release();
EventBus.getDefault().unregister(this);
}
@Override
protected void onPreExecute() {
EventBus.getDefault().register(this);
initTiming();
super.onPreExecute();
}
private void initTiming() {
dit = Preferences.MORSE_PREFERENCE.getDitDuration();
dah = 3 * dit;
word = 7 * dit;
ditTrack = generateTone(Preferences.MORSE_PREFERENCE.getMorseFrequency(), dit);
dahTrack = generateTone(Preferences.MORSE_PREFERENCE.getMorseFrequency(), dah);
}
@Override
protected Boolean doInBackground(String... params) {
morseString = params[0].toCharArray();
boolean result = true;
boolean lastSymbol = false;
int counter = 1;
for (char c : morseString) {
if (!running)
continue;
switch (c) {
case '.':
if (lastSymbol)
wait(dit);
playDit();
lastSymbol = true;
break;
case '-':
if (lastSymbol)
wait(dit);
playDah();
lastSymbol = true;
break;
case ' ':
wait(dah);
lastSymbol = false;
break;
case '/':
wait(word);
lastSymbol = false;
break;
default:
result = false;
}
EventBus.getDefault().post(new MorseCharPlayedEvent(counter));
counter++;
}
EventBus.getDefault().post(new MorseSendEvent(false));
return result;
}
private MorseAudioTrack generateTone(double freqHz, int durationMs) {
int samplingRate = 44100; /* in Hz */
int count = (int) (samplingRate * 2.0 * (durationMs / 1000.0)) & ~1;
short[] sound = new short[count];
for (int i = 0; i < count; i += 2) {
short sample = (short) (Math.sin(2 * Math.PI * i / (44100.0 / freqHz)) * 0x7FFF);
sound[i + 0] = sample;
sound[i + 1] = sample;
}
MorseAudioTrack track = new MorseAudioTrack(samplingRate, sound);
return track;
}
private void wait(int time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void stop() {
running = false;
}
@Subscribe
public void onEvent(MorseDitDurationEvent event) {
initTiming();
}
}