3template <size_t peakCount>
4void FFTVoiceDetection<peakCount>::SetThreshold(float threshold) {
5 this->threshold = threshold;
8template <size_t peakCount>
9float FFTVoiceDetection<peakCount>::GetViseme(MouthShape viseme) {
10 return *visRatios[viseme];
13template <size_t peakCount>
14void FFTVoiceDetection<peakCount>::PrintVisemes() {
18 for (uint8_t i = 0; i < visemeCount; i++) {
19 if (max < *visRatios[i]) {
55 // Serial.println("?");
60template <size_t peakCount>
61void FFTVoiceDetection<peakCount>::ResetVisemes() {
62 for (uint8_t i = 0; i < visemeCount; i++) *visRatios[i] = 0.0f;
65template <size_t peakCount>
66void FFTVoiceDetection<peakCount>::Update(float* peaks, float maxFrequency) {
67 CalculateFormants(peaks, 5);
69 f1 = f1 / float(peakCount) * (maxFrequency / 2.0f);
70 f2 = f2 / float(peakCount) * (maxFrequency / 2.0f);
72 CalculateVisemeGroup();
75template <size_t peakCount>
76void FFTVoiceDetection<peakCount>::CalculateFormants(float* peaks, uint8_t bandwidth) {
77 // calculate forward and backward of bandwidth of sum for each peak for kernel density estimation
78 for (int16_t i = 0; i < int16_t(peakCount); i++) {
82 for (int16_t j = 0; j < int16_t(bandwidth); j++) {
83 if (i < int16_t(bandwidth)) {
84 density += peaks[i + j];
86 if (i - j > 0) density += peaks[i - j];
87 } else if (i > int16_t(peakCount - bandwidth)) {
88 density += peaks[i - j];
90 if (i + j < int16_t(peakCount)) density += peaks[i + j];
92 density += peaks[i + j];
93 density += peaks[i - j];
97 peakDensity[i] = peakSmoothing.Filter(density);
100 peakDetection.Calculate(peakDensity, peaksBinary);
102 // check two largest consecutive peak blocks, find center
104 uint8_t tempCount = 0;
105 uint8_t firstStart = 0;
106 uint8_t firstCount = 0;
107 uint8_t secondStart = 0;
108 uint8_t secondCount = 0;
110 for (uint8_t i = 0; i < peakCount; i++) {
111 if (peaksBinary[i]) {
114 if (firstCount < tempCount) {
115 secondCount = firstCount;
116 secondStart = firstStart;
117 firstCount = tempCount;
118 firstStart = i - tempCount;
119 } else if (secondCount < tempCount) {
120 secondCount = tempCount;
121 secondStart = i - tempCount;
128 if (firstCount < 8) {
129 secondStart = firstStart;
130 secondCount = firstCount;
133 if (secondCount < 8) {
134 secondStart = firstStart;
135 secondCount = firstCount;
138 if (firstStart < secondStart) {
139 f1 = float(firstStart + firstCount / 2);
140 f2 = float(secondStart + secondCount / 2);
142 f1 = float(secondStart + secondCount / 2);
143 f2 = float(firstStart + firstCount / 2);
147template <size_t peakCount>
148void FFTVoiceDetection<peakCount>::CalculateVisemeGroup(){
149 //update all viseme values
150 for(uint8_t i = 0; i < visemeCount; i++) *visRatios[i] = 0.0f;
152 if(f1 > threshold || f2 > threshold){
153 Vector2D formant = Vector2D(f1, f2);
154 uint8_t firstClosest = 0;
155 float firstDistance = 1000000.0f;//arbitrary large value
157 for(uint8_t i = 0; i < visemeCount; i++){//find two smallest values
158 float distance = formant.CalculateEuclideanDistance(*coordinates[i]);
160 if(distance < firstDistance){
162 firstDistance = distance;
166 *visRatios[firstClosest] = 1.0f;