void SignalAnalysisProcess(H_SIGNAL_ANALYSIS p, const DATATYPE *inSignal, double *outFormants, bool in_dB) { if(p) { int size = p->size; // Converting, filtering and downsampling. for (int i = 0; i < size; i++) p->input.realp[i] = (float)inSignal[i]/16777216.0; // From fixed 8.24 to float. size /= DFACTOR; double freq = SAMPRATE/DFACTOR; vDSP_zrdesampD(&(p->input), DFACTOR, filter, &(p->output), size, FTAPS); // Apply pre-emphasis. double preEmphasis = exp (-2.0*M_PI*PREEM/freq); for (int i = size; i >= 2; i--) p->output.realp[i] -= preEmphasis*p->output.realp[i - 1]; // Apply weigthing window for(int i = 0; i < size; i++) p->output.realp[i] *= p->window[i]; // Get linear prediction coefficients. double coefs[DEG]; // The number of the coefficients we need equals the degree of the polynomial findLPCoefs (p->output.realp, coefs); // Convert LP coefficients to polynomial. double pol[DEG + 1]; for (int i = 0; i < DEG; i++) pol[i] = coefs[DEG - i - 1]; // We put the coefficients in the correct order. pol[DEG] = 1.0; // This 1 appears in the all-pole filter polynomial 1 - ∑aᵢ*z⁻ⁱ. // Find the roots of the polynomial. __CLPK_doublecomplex roots[DEG]; int nroots = findRoots (pol, DEG, roots); if (nroots > 0) { fixIntoUnitCircle (roots, nroots); // Roots to unit circle. // Count and fill the formants. The roots come in conjugate pairs, so we need only count those above the real axis. double tempF1 = 0.0, tempF2 = 0.0; for (int j = 0; j < nroots; j++) if (roots[j].i >= 0) { double f = fabs (atan2 (roots[j].i, roots[j].r))*MAXFREQ/M_PI; if (f >= SAFETY && f <= MAXFREQ - SAFETY) { if (tempF1 == 0.0) tempF1 = f; else if (f < tempF1) { tempF2 = tempF1; tempF1 = f; } else if (tempF2 == 0.0 || f < tempF2) tempF2 = f; } } outFormants[F1] = tempF1; outFormants[F2] = tempF2; } } }
MGraph<ClusterAlg*, unsigned>* ClusterAlg::constructGraph(ClusterAlg* other, unsigned up) { std::list<ClusterAlg*> list_graph_nodes; ClusterAlg *p0 = this, *p1 = other; // search for roots of subtrees in the cluster tree findRoots (p0, p1); if (p0 == NULL || p1 == NULL) return NULL; if (p0->getDepth() < up || p1->getDepth() < up) return NULL; for (unsigned l=0; l<up; ++l) { p0 = (ClusterAlg*)p0->getParent(); p1 = (ClusterAlg*)p1->getParent(); } // fill list_graph_nodes with the appropriate graph nodes if (p0 == p1) p1->getNodes (depth, list_graph_nodes); else { p0->getNodes (depth, list_graph_nodes); p1->getNodes (depth, list_graph_nodes); } // create and fill vertex array for graph (adjacency matrix) unsigned row_size = list_graph_nodes.size(), idx = 0; ClusterAlg **graph_nodes = new ClusterAlg* [row_size]; std::list<ClusterAlg*>::iterator node_it = list_graph_nodes.begin (); while (node_it != list_graph_nodes.end()) { graph_nodes[idx++] = *node_it; node_it++; } // count nnz-elements, fill liA, ljA and lA std::list<unsigned> liA, ljA, lA; liA.push_back (0); unsigned col = 0, col_cnt; std::list<ClusterAlg*>::iterator it0(list_graph_nodes.begin ()), it1; while (it0 != list_graph_nodes.end()) { it1 = list_graph_nodes.begin (); col_cnt = 0; while (it1 != list_graph_nodes.end()) { if (it0 != it1) { unsigned nbr_size ((*it0)->hasNeighbour(*it1)); #ifdef VIRTUAL_DEPTH_WEIGHT if (nbr_size > 0) { ljA.push_back (col_cnt); col++; // determine weights if ((*it0)->isSeparator() && (*it1)->isSeparator()) { unsigned diff0 ((*it0)->getDepth()-(*it0)->getVirtualDepth()+1); unsigned diff1 ((*it1)->getDepth()-(*it1)->getVirtualDepth()+1); if (diff0 < diff1) lA.push_back (diff0); else lA.push_back(diff1); } else { if ((*it0)->isSeparator() && !(*it1)->isSeparator()) lA.push_back ((*it0)->getDepth()-(*it0)->getVirtualDepth()+1); else lA.push_back ((*it1)->getDepth()-(*it1)->getVirtualDepth()+1); } } #endif #ifdef NEIGHBOUR_SIZE_WEIGHT if (nbr_size) { ljA.push_back (col_cnt); col++; // determine weights if ((*it0)->isSeparator() && (*it1)->isSeparator()) { unsigned mnbr_size (nbr_size > (*it1)->hasNeighbour(*it0) ? nbr_size : (*it1)->hasNeighbour(*it0)); unsigned min_diam ((*it0)->getDiam() < (*it1)->getDiam() ? (*it0)->getDiam() : (*it1)->getDiam()); lA.push_back (ceil((double)min_diam / mnbr_size)); } else { if ((*it0)->isSeparator() && !(*it1)->isSeparator()) { if (ceil((double)(*it0)->getDiam()/nbr_size) == 1) lA.push_back (ceil(sqrt((double)(*it0)->getDiam()))); else lA.push_back (ceil((double)(*it0)->getDiam()/nbr_size)); } else { if (ceil((double)(*it1)->getDiam()/nbr_size) == 1) lA.push_back (ceil(sqrt((double)(*it1)->getDiam()))); else lA.push_back (ceil((double)(*it1)->getDiam()/nbr_size)); } } } #endif #ifdef UNWEIGHTED if (nbr_size > 0) { ljA.push_back (col_cnt); lA.push_back (1); col++; } #endif } it1++; col_cnt++; } liA.push_back (col); it0++; } // create AdjMat in CRS-format: iA, jA, A unsigned *iA = new unsigned[row_size+1]; unsigned col_ptr_size = ljA.size(); unsigned *jA = new unsigned[col_ptr_size]; unsigned *A = new unsigned[col_ptr_size]; // fill iA std::list<unsigned>::const_iterator it2 = liA.begin (); idx = 0; while (it2 != liA.end()) { iA[idx++] = *it2; it2++; } iA[row_size] = col_ptr_size; // fill jA and A it2 = ljA.begin (); std::list<unsigned>::const_iterator it3 (lA.begin()); idx = 0; while (it2 != ljA.end()) { jA[idx] = *it2; A[idx] = *it3; it2++; it3++; idx++; } AdjMat *tmp_adj(new AdjMat (row_size, iA, jA, A)); MGraph <ClusterAlg*, unsigned> *graph (new MGraph<ClusterAlg*, unsigned> (graph_nodes, tmp_adj)); delete [] graph_nodes; return graph; }