/** * use this method to get a hold on max amplitudes -- returns true when it's best to update the * display */ public boolean needUpdate(int p, int m, int n, TextView display) { if (max[p] > threshold) { // threshold if ((double) max[p] > ((double) primaryMax[p] + 0.5)) { if (MainActivity.analyzeMode) { if (max[p] > threshold * 1.2) { getNew[0] = false; } } primaryMax[p] = max[p]; primaryFreq[p] = topFreq[p]; return false; } else if ((double) max[p] < (double) (primaryMax[p] - 0.5)) { note[p] = noteFinder.getNote(primaryFreq[p]); // display.setText(Integer.toString(primaryFreq[p])+" Hz - "+note[p]); // setPianoKey(); getNew[0] = true; primaryMax[p] = 0; return true; } else { return false; } } else { getNew[0] = true; primaryMax[p] = 0; return false; } }
/** * First, fill up the storedMaxFreq with values Once filled, get a new value every time this * function runs -- move all the values down a slot -- put in a new value, and remove the oldest * value Loop through storedValueAmounts, a 2D array, within each loop iteration of storedMaxFreq * in order to fill the 2D array ([frequency value][number of occurrences]) -- check if the slot * has duplicate values. if so, add 1 to the second dimension of that slot -- otherwise, check if * slot is empty. if so, fill it in with the new storedMaxFreq value Using the data in * storedMaxFreq, find a frequency to display -- Loop to sum up and average all the values in * storedMaxFreq -- Loop to compare this average with each value in storedMaxFreq. take the value * closest to the average (least difference between it and the average) -- Loop through * storedValueAmounts to sum up recurrent frequencies (mostCommonSum) and their weight * (amountOfCommonSums) -- -- sum up the frequencies that occur more than once * (storedValueAmounts[i][1] > 0) -- -- then, amountOfCommonSums += (storedValueAmounts[i][1]+1) * to add weight -- -- otherwise, add all unpreferred frequencies to the array list: * unpreferredFrequencies -- Loop to remove bad values from the recurrent frequencies that we just * added -- -- if statement ensures that the already selected "most usable" frequency isn't * accounted for when removing bad frequencies -- -- if a value is outside a 21% margin of the * most usable frequency, subtract it and its weight -- Loop through unpreferredFrequencies * (frequencies that only occur once) to find decently valid values -- -- if an unpreferred value * is still within a 10% margin of the most usable frequency, add it and weight it as 1 -- * Finally, divide the total sum by the weights (mostCommonSum/amountOfCommonSums) to get an * average that represents the most accurate frequency -- -- return 0 if amountOfCommonSums > 0 to * avoid accidentally dividing by 0 Update visualization display -- Get note based on the returned * frequency -- Fill previousNotes (an ArrayList) with the previous 3 notes using the same method * as step 1 and 2 of this function -- Loop through previousNotes to check if all notes are the * same or not -- -- if not all the same, changeNote will be false. vice versa -- If changeNote is * true: -- -- update previousNote to be currentNote, then update currentNote to the actual * currentNote (previousNote is always one step behind) -- -- if currentNote != previousNote, * meaning there is a need to update the display, then update! */ public void updateText(int p, int m, int n, TextView display) { if (max[p] > threshold) { // threshold if (storedMaxFreq.size() < 6) { // fills the array storedMaxFreq.add(topFreq[p]); } else { // if storedMaxFreq is full // DEFINITIONS int mostCommonSum = 0; int amountOfCommonSums = 0; boolean changeNote = true; int[][] storedValueAmounts = new int[8][2]; ArrayList<Integer> preferredFrequencies = new ArrayList<Integer>(); int mostUsable = 0; int overallAverage = 0; ArrayList<Integer> unpreferredFrequencies = new ArrayList<Integer>(); // UPDATES ARRAY ArrayList<Integer> tempStorage = new ArrayList<Integer>(); tempStorage.addAll(storedMaxFreq); storedMaxFreq.clear(); storedMaxFreq.add(0, topFreq[p]); storedMaxFreq.addAll(1, tempStorage); storedMaxFreq.remove(6); // FINDS RECURRING FREQUENCIES for (int i = 0; i < storedMaxFreq.size(); i++) { // loop through the storedMaxFreq for (int x = 0; x < storedValueAmounts.length; x++) { // loop to check for empty slots in storedValueAmounts and fill them if (storedValueAmounts[x][0] != 0 && storedMaxFreq.get(i) == storedValueAmounts[x][ 0]) { // if slot is filled and contents are the same, just increase the // count by 1 storedValueAmounts[x][1] += 1; break; } else if (storedValueAmounts[x][0] == 0) { // if slot is empty, take it storedValueAmounts[x][0] = storedMaxFreq.get(i); break; } } } // GETS FREQUENCY TO DISPLAY for (int i = 0; i < storedMaxFreq.size(); i++) { // gets overall average overallAverage += storedMaxFreq.get(i); } overallAverage /= storedMaxFreq.size(); int difference = 100000; for (int i = 0; i < storedMaxFreq.size(); i++) { // finds mostUsable if (Math.abs(overallAverage - storedMaxFreq.get(i)) < difference) { difference = Math.abs(overallAverage - storedMaxFreq.get(i)); mostUsable = storedMaxFreq.get(i); } } for (int i = 0; i < storedValueAmounts.length; i++) { // loop to sum up the most common frequencies if (storedValueAmounts[i][1] > 0) { preferredFrequencies.add(i); mostCommonSum += storedValueAmounts[i][0] * (storedValueAmounts[i][1] + 1); // adds weight to the summing amountOfCommonSums += (storedValueAmounts[i][1] + 1); } else { unpreferredFrequencies.add(storedValueAmounts[i][0]); } } for (int i = 0; i < (preferredFrequencies.size()); i++) { // loop to remove bad values from the most common frequencies if (storedValueAmounts[preferredFrequencies.get(i)][0] != mostUsable) { if (storedValueAmounts[preferredFrequencies.get(i)][0] < (double) mostUsable * 0.79 || storedValueAmounts[preferredFrequencies.get(i)][0] > (double) mostUsable * 1.21) { mostCommonSum -= storedValueAmounts[preferredFrequencies.get(i)][0] * (storedValueAmounts[preferredFrequencies.get(i)][1] + 1); amountOfCommonSums -= (storedValueAmounts[preferredFrequencies.get(i)][1] + 1); } } } for (int i = 0; i < unpreferredFrequencies.size(); i++) { // adds back in previously removed values that were, in hindsight, pretty good if (unpreferredFrequencies.get(i) > mostUsable * 0.9 && unpreferredFrequencies.get(i) < mostUsable * 1.1) { mostCommonSum += unpreferredFrequencies.get(i); amountOfCommonSums++; } } if (amountOfCommonSums > 0) { mostCommonSum = (int) Math.round((double) (mostCommonSum / amountOfCommonSums)); } else { mostCommonSum = 0; } // UPDATES NOTE & TEXT // previousNote[p] = note[p]; note[p] = noteFinder.getNote(mostCommonSum); int noteIndex = noteFinder.getIndex(mostCommonSum); ; if (previousNotes.size() < 3) { // sets how many times each note must be detected in a row before changing the // piano visualization previousNotes.add(note[p]); } else { ArrayList<String> tempStorage2 = new ArrayList<String>(); tempStorage2.addAll(previousNotes); previousNotes.clear(); previousNotes.add(0, note[p]); previousNotes.addAll(1, tempStorage2); previousNotes.remove(3); for (int i = 1; i < (previousNotes.size()); i++) { if (previousNotes.get(i) == previousNotes.get(i - 1)) { changeNote = true; } else { changeNote = false; break; } } } if (changeNote) { // if note change required, update currentNote & previous note previousNote[p] = currentNote[p]; currentNote[p] = note[p]; if (currentNote[p] != previousNote[p]) { // check if display update needed display.setText(Integer.toString(mostCommonSum) + " Hz - " + note[p]); setPianoKey(); writeToFile(timeCount + ":" + noteIndex + ";", true); previousNoteIndex = noteIndex; } else { writeToFile(timeCount + ":" + previousNoteIndex + ";", true); } } // OPTIONAL LOGGING /* String logList = "Member name: "; for (int i = 0; i<storedMaxFreq.size(); i++){ logList += storedMaxFreq.get(i) + ", "; } logList += "\nstoredValueAmounts: " + Arrays.deepToString(storedValueAmounts); Log.w("Davis", logList + "\n"+mostCommonSum+" Hz - "+note[p]); */ } // OPTIONAL BOLDING if (max[p] > 5) { display.setTypeface(Typeface.create("sans-serif", Typeface.BOLD)); } else { display.setTypeface(Typeface.create("sans-serif-light", Typeface.NORMAL)); } } }