import java.io.*; import java.util.*; class MorseFilter { private Map morseTable = new HashMap(); private void add(char c1, String s1, char c2, String s2) { morseTable.put(s1, c1); morseTable.put(s2, c2); } private void initializeMorseTable() { add('A', ".-", 'B', "-..."); add('C', "-.-.", 'D', "-.."); add('E', ".", 'F', "..-."); add('G', "--.", 'H', "...."); add('I', "..", 'J', ".---"); add('K', "-.-", 'L', ".-.."); add('M', "--", 'N', "-."); add('O', "---", 'P', ".--."); add('Q', "--.-", 'R', ".-."); add('S', "...", 'T', "-"); add('U', "..-", 'V', "...-"); add('W', ".--", 'X', "-..-"); add('Y', "-.--", 'Z', "--.."); add('0', "-----", '1', ".----"); add('2', "..---", '3', "...--"); add('4', "....-", '5', "....."); add('6', "-....", '7', "--..."); add('8', "---..", '9', "----."); add('.', ".-.-.-", ',', "--..--"); add('?', "..--..", '=', "-...-"); } public MorseFilter() { initializeMorseTable(); } char translateMorseCodeToChar(String code) { Character c = morseTable.get(code); if(c == null) { return '?'; } else { return c; } } // return array r[] of 1s and 0s. // r[i]=0 if a[i] is nearer to mean[0], r[i]=1 if nearer to mean[1] double[] threshold(double a[], double mean[]) { assert mean.length == 2; int n = a.length; double result[] = new double[n]; int diff = 0; for (int i = 0; i < n; i++) { if (Math.abs(mean[0] - a[i]) < Math.abs(mean[1] - a[i])) { diff = diff - 1; } else { diff = diff + 1; } final int d = 10; if (diff > d) { diff = d; result[i] = 1; } if (diff < -d) { diff = -d; result[i] = 0; } } return result; } // compute lengths of runs of zeros and ones // E.g. let a[] = [0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0] // Then the result is [-3, 4, -2, 3, -2] // Runs of zeroes use negative, runs of positive numbers positive counts List cummulate(double a[]) { int n = a.length, count = 0; List result = new ArrayList(); for (int i = 1; i < n; i++) { if((a[i] > 0) != (a[i-1] > 0)) { result.add(count); count = 0; } if(a[i] > 0) { count = count + 1; } else { count = count - 1; } } result.add(count); return result; } // return an array of all values in list that have the // same sign as sing (i.e. are negative or positive numbers). double[] signFilter(int sign, List list) { List result = new ArrayList(); for (int n: list) { if ((sign > 0) == (n > 0)) { result.add(n); } } double r[] = new double[result.size()]; for(int i=0; i list = new ArrayList(); while (dataStream.available() > 0) { double w = dataStream.readDouble(); list.add(w); } int n = list.size(); result = new double[n]; for (int i = 0; i < n; i++) { result[i] = list.get(i); } } catch (Exception e) { e.printStackTrace(); } return result; } // Compute the averages of all windows of // length k. Returns an array of the same // length as a. double[] average(int k, double a[]) { int n = a.length; assert n > k; double sum[] = new double[n]; sum[0] = a[0]; for (int i = 1; i < n; i++) { sum[i] = sum[i - 1] + Math.abs(a[i]); } double mittel[] = new double[n]; for (int i = k; i < n; i++) { mittel[i] = (sum[i] - sum[i - k]) / k; } for (int i = 0; i < k; i++) { mittel[i] = mittel[k]; } return mittel; } // Convert an array of lengths of pauses (by negative numbers) // and active signals (by positive numbers) in Morse code to // a String of symbols. // Example: [-800,500,-800,1500,-5000,1500,-800,1500,-800,500[ // becomes ".- --.". // Using the k-Means algorithm, the approximate length of "." // and "-" as well as pauses between symbols and pauses between // characters are automatically determined. String symbolize(List len) { String s = ""; double pulse[] = kMeans.getCenters(2, signFilter(+1, len)); double pause[] = kMeans.getCenters(2, signFilter(-1, len)); for(int dur: len) { if(dur < 0) { if(Math.abs(pause[0]-dur) < Math.abs(pause[1]-dur)) { s = s + " "; } } else { if(Math.abs(pulse[0]-dur) < Math.abs(pulse[1]-dur)) { s = s + "."; } else { s = s + "-"; } } } return s; } // Convert a String of Morse code ".- --. ... ---" separated by // spaces into a List of tokens ".-", "--.", "...". "---". List tokenize(String dotdashs) { List tokens = new ArrayList(); String z = ""; for (int i = 0; i < dotdashs.length(); i++) { if (dotdashs.charAt(i) == ' ') { tokens.add(z); z = ""; } else { z = z + dotdashs.charAt(i); } } tokens.add(z); return tokens; } // Decode a list of Morse code for single characters into a // decoded string: ["...", "---", "..."] becomes "SOS". String decode(List tokens) { String result = ""; for (String morseToken : tokens) { result += translateMorseCodeToChar(morseToken); } return result; } } class Morse { static public void main(String args[]) { MorseFilter filter = new MorseFilter(); double buffer[] = filter.readFile("withnoise.raw"); buffer = filter.average(200, buffer); double mean[]; mean = kMeans.getCenters(2, buffer); buffer = filter.threshold(buffer, mean); List durations = filter.cummulate(buffer); String dotdashs = filter.symbolize(durations); List tokens = filter.tokenize(dotdashs); String cleartext = filter.decode(tokens); System.out.println(cleartext); } }