void BindablePlatform::init_bindable_platform (int posx, int posy, std::string file_name) { m_pos.x = posx; m_pos.y = posy; file_name = PIC_STATICS_R + file_name; m_image = new Surface (file_name + ".png"); m_pos.h = m_image->h(); m_pos.w = m_image->w(); Analyser analyser; analyser.open (file_name + ".col"); m_collisions_matrix_w = analyser.read_int(); m_collisions_matrix_h = analyser.read_int(); m_collisions_matrix = new unsigned int*[m_collisions_matrix_w]; for (int i = 0; i < m_collisions_matrix_w; i++) { m_collisions_matrix[i] = new unsigned int[m_collisions_matrix_h]; } for (int j = 0; j < m_collisions_matrix_h; j++) { for (int i = 0; i < m_collisions_matrix_w; i++) { m_collisions_matrix[i][j] = analyser.read_int(); } } analyser.close(); }
static void check(Analyser& analyser, CastExpr const *expr) { if (expr->getSubExpr()->isNullPointerConstant( *analyser.context(), Expr::NPC_ValueDependentIsNotNull)) { return; // RETURN } if (expr->getCastKind() != CK_BitCast && expr->getCastKind() != CK_LValueBitCast && expr->getCastKind() != CK_IntegralToPointer) { return; // RETURN } CanQualType source(getType(expr->getSubExpr()->getType())); CanQualType target(getType(expr->getType())); std::string tt = static_cast<QualType>(target).getAsString(); if ((source != target && tt != "char" && tt != "unsigned char" && tt != "signed char" && tt != "void") || (expr->getType()->isPointerType() != expr->getSubExpr()->getType()->isPointerType())) { analyser.report(expr, check_name, "AL01", "Possible strict-aliasing violation") << expr->getSourceRange(); } }
static void member_definition_in_class_definition(Analyser& analyser, CXXMethodDecl const* decl) { member_definition& data = analyser.attachment<member_definition>(); if (decl->isTemplateInstantiation()) { if (CXXMethodDecl const* tplt = llvm::dyn_cast<CXXMethodDecl>( decl->getTemplateInstantiationPattern())) { decl = tplt; } } if (decl->getLexicalDeclContext() == decl->getDeclContext() && decl->hasInlineBody() && !decl->getParent()->isLocalClass() && !decl->isImplicit() && !data.reported_[decl->getCanonicalDecl()] && !analyser.is_test_driver() && !decl->getLocStart().isMacroID()) { analyser.report(decl, check_name, "CD01", "Member function '%0' is defined in the class definition.") << decl->getQualifiedNameAsString(); data.reported_[decl->getCanonicalDecl()] = true; } }
static inline void apply(Analyser & analyser, TurnIt first, TurnIt last) { if ( first == last ) return; for_preceding_rings(analyser, *first); //analyser.per_turn(*first); TurnIt prev = first; for ( ++first ; first != last ; ++first, ++prev ) { // same multi if ( prev->operations[OpId].seg_id.multi_index == first->operations[OpId].seg_id.multi_index ) { // same ring if ( prev->operations[OpId].seg_id.ring_index == first->operations[OpId].seg_id.ring_index ) { //analyser.per_turn(*first); } // same multi, next ring else { //analyser.end_ring(*prev); analyser.turns(prev, first); //if ( prev->operations[OpId].seg_id.ring_index + 1 // < first->operations[OpId].seg_id.ring_index) { for_no_turns_rings(analyser, *first, prev->operations[OpId].seg_id.ring_index + 1, first->operations[OpId].seg_id.ring_index); } //analyser.per_turn(*first); } } // next multi else { //analyser.end_ring(*prev); analyser.turns(prev, first); for_following_rings(analyser, *prev); for_preceding_rings(analyser, *first); //analyser.per_turn(*first); } if ( analyser.interrupt ) { return; } } //analyser.end_ring(*prev); analyser.turns(prev, first); // first == last for_following_rings(analyser, *prev); }
static void close_file(Analyser& analyser, SourceLocation where, std::string const&, std::string const& name) { if (analyser.is_component_header(name)) { analyser.attachment<data>().line_ = analyser.get_location(where).line(); } }
ZoneItem::ZoneItem (QGraphicsScene *scene, TriggerItem *parent, Analyser &analyser) : MyItem (NULL, ""), m_parent (parent) { Q_UNUSED (scene); int x, y; x = analyser.read_int(); y = analyser.read_int(); m_width = analyser.read_int() - x; m_height = analyser.read_int() - y; setItem (addRect (0, 0, m_width, m_height) ); setPos (x, y); }
static void process(Analyser& analyser, Expr const* expr, Decl const* decl) { if (const FunctionDecl* function = decl ? llvm::dyn_cast<FunctionDecl>(decl) : 0) { function = function->getCanonicalDecl(); std::string name; PrintingPolicy policy(analyser.context()->getLangOpts()); function->getNameForDiagnostic(name, policy, true); std::ostringstream out; out << name << "("; for (FunctionDecl::param_const_iterator it(function->param_begin()), end(function->param_end()); it != end; ++it) { if (it != function->param_begin()) { out << ", "; } ParmVarDecl const* param(*it); out << param->getType().getAsString(); if (param->isParameterPack()) { out << "..."; } } out << ")"; CXXMethodDecl const* method(llvm::dyn_cast<CXXMethodDecl>(function)); if (method && !method->isStatic()) { if (method->getTypeQualifiers() & Qualifiers::Const) { out << " const"; } if (method->getTypeQualifiers() & Qualifiers::Volatile) { out << " volatile"; } if (method->getTypeQualifiers() & Qualifiers::Restrict) { out << " restrict"; } } name += out.str(); //-dk:TODO analyser.report(expr, check_name, "function decl: '%0'") //-dk:TODO << expr->getSourceRange() //-dk:TODO << out.str() ; } else { analyser.report(expr, check_name, "UF01", "Unresolved function call") << expr->getSourceRange(); } }
static void check(Analyser& analyser, CXXThrowExpr const* expr) { const TypeDecl *e = analyser.lookup_type("::std::exception"); Expr *object(const_cast<Expr*>(expr->getSubExpr())); if (e && e->getTypeForDecl() && object) // else it is a rethrow... { QualType t = e->getTypeForDecl()->getCanonicalTypeInternal(); QualType ot = object->getType()->getCanonicalTypeInternal(); if (ot != t && !analyser.sema().IsDerivedFrom(ot, t)) { analyser.report(expr, check_name, "FE01", "Object of type %0 not derived from " "std::exception is thrown.") << ot; } } }
static inline void analyse_each_turn(Result & res, Analyser & analyser, TurnIt first, TurnIt last) { if ( first == last ) return; for ( TurnIt it = first ; it != last ; ++it ) { analyser.apply(res, it); if ( BOOST_GEOMETRY_CONDITION(res.interrupt) ) return; } analyser.apply(res); }
static void open_file(Analyser& analyser, SourceLocation where, const std::string&, const std::string& name) { FileName fn(name); std::string filename = fn.name(); if (analyser.is_component_header(filename) || name == analyser.toplevel()) { const SourceManager &m = analyser.manager(); llvm::StringRef buf = m.getBuffer(m.getFileID(where))->getBuffer(); if (buf.size() == 0) { return; } buf = buf.substr(0, buf.find('\n')).rtrim(); std::string expectcpp("// " + filename); expectcpp.resize(70, ' '); expectcpp += "-*-C++-*-"; std::string expectc("/* " + filename); expectc.resize(69, ' '); expectc += "-*-C-*- */"; if ( !buf.equals(expectcpp) && !buf.equals(expectc) && buf.find("GENERATED") == buf.npos) { std::pair<size_t, size_t> mcpp = mid_mismatch(buf, expectcpp); std::pair<size_t, size_t> mc = mid_mismatch(buf, expectc); std::pair<size_t, size_t> m; std::string expect; if (mcpp.first >= mc.first || mcpp.second >= mc.second) { m = mcpp; expect = expectcpp; } else { m = mc; expect = expectc; } analyser.report(where.getLocWithOffset(m.first), check_name, "HL01", "File headline incorrect", true); analyser.report(where.getLocWithOffset(m.first), check_name, "HL01", "Correct format is\n%0", true, DiagnosticIDs::Note) << expect; if (m.first == 0) { analyser.InsertTextAfter( where.getLocWithOffset(m.first), expect + "\n"); } else { analyser.ReplaceText(analyser.get_line_range(where), expect); } } } }
static inline void for_no_turns_rings(Analyser & analyser, Turn const& turn, signed_size_type first, signed_size_type last) { segment_identifier seg_id = turn.operations[OpId].seg_id; for ( seg_id.ring_index = first ; seg_id.ring_index < last ; ++seg_id.ring_index ) { analyser.no_turns(seg_id); } }
static void include_file(Analyser& analyser, SourceLocation where, bool, std::string const& name) { data& status(analyser.attachment<data>()); if (status.check_) { if (analyser.is_component_header(name) || analyser.is_component_header(analyser.toplevel())) { status.header_seen_ = true; } else if (!status.header_seen_ && analyser.toplevel() != name && builtin != name && command_line != name && "bdes_ident.h" != name && !analyser.is_main()) { analyser.report(where, check_name, "TR09", "Include files precede component header", true); status.check_ = false; } } }
static void check(Analyser& analyser, BinaryOperator const* expr) { if ((expr->getOpcode() == BO_Add || expr->getOpcode() == BO_Sub) && (is_addition( analyser, expr->getLHS(), expr->getRHS(), expr->getOpcode()) || is_addition( analyser, expr->getRHS(), expr->getLHS(), expr->getOpcode()))) { analyser.report(expr->getOperatorLoc(), check_name, "SA01", "%0 integer %1 string literal") << expr->getSourceRange() << (expr->getOpcode() == BO_Add? "Adding": "Subtracting") << (expr->getOpcode() == BO_Add? "to": "from"); } }
static bool is_addition(Analyser& analyser, Expr const* str, Expr const* value, BinaryOperatorKind op) { if (StringLiteral const* lit = llvm::dyn_cast<StringLiteral>(str->IgnoreParenCasts())) { llvm::APSInt length(32, false); llvm::APSInt zero(32, false); length = lit->getByteLength(); zero = 0u; value = value->IgnoreParenCasts(); llvm::APSInt result; return !value->isIntegerConstantExpr(result, *analyser.context()) || (op == BO_Add && (result < zero || length < result)) || (op == BO_Sub && (zero < result || length + result < zero)); } return false; }
static void declaration(Analyser& analyser, Decl const* decl) { data& status(analyser.attachment<data>()); if (status.check_) { if (!status.header_seen_ || analyser.is_component_header(analyser.toplevel())) { status.header_seen_ = true; status.line_ = 0; } Location loc(analyser.get_location(decl)); if ((analyser.toplevel() != loc.file() && status.header_seen_) || (analyser.toplevel() == loc.file() && status.line_ < loc.line())) { status.check_ = false; } else if (((analyser.toplevel() != loc.file() && !status.header_seen_) || loc.line() < status.line_) && builtin != loc.file() && command_line != loc.file() && (llvm::dyn_cast<NamedDecl>(decl) == 0 || utils::end(id_names) == std::find(utils::begin(id_names), utils::end(id_names), llvm::dyn_cast<NamedDecl>(decl) ->getNameAsString())) && !analyser.is_main()) { analyser.report(decl, check_name, "TR09", "Declarations precede component header", true); status.check_ = false; } } }
// This is called from the AnalyserQueue thread bool AnalyserQueue::doAnalysis(TrackPointer tio, SoundSourceProxy* pSoundSource) { int totalSamples = pSoundSource->length(); //qDebug() << tio->getFilename() << " has " << totalSamples << " samples."; int processedSamples = 0; QTime progressUpdateInhibitTimer; progressUpdateInhibitTimer.start(); // Inhibit Updates for 60 milliseconds int read = 0; bool dieflag = false; bool cancelled = false; int progress; // progress in 0 ... 100 do { ScopedTimer t("AnalyserQueue::doAnalysis block"); read = pSoundSource->read(kAnalysisBlockSize, m_pSamplesPCM); // To compare apples to apples, let's only look at blocks that are the // full block size. if (read != kAnalysisBlockSize) { t.cancel(); } // Safety net in case something later barfs on 0 sample input if (read == 0) { t.cancel(); break; } // If we get more samples than length, ask the analysers to process // up to the number we promised, then stop reading - AD if (read + processedSamples > totalSamples) { qDebug() << "While processing track of length " << totalSamples << " actually got " << read + processedSamples << " samples, truncating analysis at expected length"; read = totalSamples - processedSamples; dieflag = true; } // Normalize the samples from [SHRT_MIN, SHRT_MAX] to [-1.0, 1.0]. // TODO(rryan): Change the SoundSource API to do this for us. for (int i = 0; i < read; ++i) { m_pSamples[i] = static_cast<CSAMPLE>(m_pSamplesPCM[i]) / SHRT_MAX; } QListIterator<Analyser*> it(m_aq); while (it.hasNext()) { Analyser* an = it.next(); //qDebug() << typeid(*an).name() << ".process()"; an->process(m_pSamples, read); //qDebug() << "Done " << typeid(*an).name() << ".process()"; } // emit progress updates // During the doAnalysis function it goes only to 100% - FINALIZE_PERCENT // because the finalise functions will take also some time processedSamples += read; //fp div here prevents insane signed overflow progress = (int)(((float)processedSamples)/totalSamples * (1000 - FINALIZE_PERCENT)); if (m_progressInfo.track_progress != progress) { if (progressUpdateInhibitTimer.elapsed() > 60) { // Inhibit Updates for 60 milliseconds emitUpdateProgress(tio, progress); progressUpdateInhibitTimer.start(); } } // Since this is a background analysis queue, we should co-operatively // yield every now and then to try and reduce CPU contention. The // analyser queue is CPU intensive so we want to get out of the way of // the audio callback thread. //QThread::yieldCurrentThread(); //QThread::usleep(10); //has something new entered the queue? if (load_atomic(m_aiCheckPriorities)) { m_aiCheckPriorities = false; if (isLoadedTrackWaiting(tio)) { qDebug() << "Interrupting analysis to give preference to a loaded track."; dieflag = true; cancelled = true; } } if (m_exit) { dieflag = true; cancelled = true; } // Ignore blocks in which we decided to bail for stats purposes. if (dieflag || cancelled) { t.cancel(); } } while(read == kAnalysisBlockSize && !dieflag); return !cancelled; //don't return !dieflag or we might reanalyze over and over }
int main() { LR0_Analyser la; la.AddProduction("E", "E", "+", "E"); la.AddProduction("E", "E", "*", "E"); la.AddProduction("E", "(", "E", ")"); la.AddProduction("E", "i"); la.AddAction(0, "(", 'S', 2); la.AddAction(0, "i", 'S', 3); la.AddAction(1, "+", 'S', 4); la.AddAction(1, "*", 'S', 5); la.AddAction(1, LR0_Analyser::END_OF_INPUT, 'A', 0); la.AddAction(2, "(", 'S', 2); la.AddAction(2, "i", 'S', 3); la.AddAction(3, "+", 'r', 4); la.AddAction(3, "*", 'r', 4); la.AddAction(3, ")", 'r', 4); la.AddAction(3, LR0_Analyser::END_OF_INPUT, 'r', 4); la.AddAction(4, "(", 'S', 2); la.AddAction(4, "i", 'S', 3); la.AddAction(5, "(", 'S', 2); la.AddAction(5, "i", 'S', 3); la.AddAction(6, "+", 'S', 4); la.AddAction(6, "*", 'S', 5); la.AddAction(6, ")", 'S', 9); la.AddAction(7, "+", 'r', 1); la.AddAction(7, "*", 'S', 5); la.AddAction(7, ")", 'r', 1); la.AddAction(7, LR0_Analyser::END_OF_INPUT, 'r', 1); la.AddAction(8, "+", 'r', 2); la.AddAction(8, "*", 'r', 2); la.AddAction(8, ")", 'r', 2); la.AddAction(8, LR0_Analyser::END_OF_INPUT, 'r', 2); la.AddAction(9, "+", 'r', 3); la.AddAction(9, "*", 'r', 3); la.AddAction(9, ")", 'r', 3); la.AddAction(9, LR0_Analyser::END_OF_INPUT, 'r', 3); la.AddGoto(0, "E", 1); la.AddGoto(2, "E", 6); la.AddGoto(4, "E", 7); la.AddGoto(5, "E", 8); Analyser analyser; string input_string; while (cout << "Input expression: ", getline(cin, input_string)) { vector<pair<string, string>> lex_result = analyser.AnalyseLexical(input_string); int error_index = -1; for (size_t i = 0; i < lex_result.size(); ++i) { if (lex_result[i].second == "unknown") error_index = i; } if (error_index != -1) { cout << "Error on: " << lex_result[error_index].first << endl; continue; } vector<pair<string, string>> escape_result = Escape(lex_result); la.Input(escape_result); if ((error_index = la.Analyse()) != -1) { if (error_index == lex_result.size()) cout << "Error on: the end of input" << endl; else cout << "Error on: " << lex_result[error_index].first << endl; continue; } cout << "Right!" << endl;; } }
Leaf processImage(string currentImgName) { Leaf newLeaf; newLeaf.path = ""; newLeaf.filename = ""; newLeaf.filenameProcessed = ""; newLeaf.filenameSegmented = ""; newLeaf.isSick = false; newLeaf.sicknessLevel = 0.0; // on sépare le chemin et le nom de l'image string tmp = string(currentImgName); while (tmp[tmp.length()-1] != '/') { newLeaf.filename = tmp[tmp.length()-1] + newLeaf.filename; //tmp.pop_back(); tmp = tmp.substr(0,tmp.length()-1); } newLeaf.path = tmp; // on supprime l'extension de l'image tmp = string(newLeaf.filename); while (tmp[tmp.length()-1] != '.') tmp = tmp.substr(0,tmp.length()-1); //tmp.pop_back(); //tmp.pop_back(); tmp = tmp.substr(0,tmp.length()-1); // on crée les noms des nouvelles images newLeaf.filenameProcessed = tmp + "_processed.jpg"; newLeaf.filenameSegmented = tmp + "_segmented.jpg"; cout << "Loading: " << newLeaf.path << newLeaf.filename << endl; string dataPath = "../data/"; Analyser analyser; string histogramName = dataPath + "leafsample.png"; Mat leafHisto = analyser.getHSHistogram(histogramName); histogramName = dataPath + "injuredsample.png"; Mat injuriesHisto = analyser.getHSHistogram(histogramName); cout << "loaded histogram" << endl; Mat currentImg = imread(currentImgName, CV_LOAD_IMAGE_UNCHANGED); if (currentImg.empty()) //check whether the image is loaded or not { cout << "Error : Image cannot be loaded..!!" << endl; //system("pause"); //wait for a key press return newLeaf; } Mat origImg = currentImg; // La comparaison d'histogramme nous permet de faire un masque de probabilité Mat leafMask; analyser.compareToHistogram(origImg, leafHisto, leafMask); // Segmentation de la feuille Mat leafImg; analyser.segmentLeaf(origImg, leafMask, leafImg); // La détection de contours nous permet de faire ressortir les irrégularités Mat detailedEdges, coarseEdges; analyser.detectEdges(leafImg, detailedEdges, coarseEdges); Mat leafIrregularities; analyser.detectIrregularities(detailedEdges, coarseEdges, leafIrregularities); float irregularityScore = analyser.computeIrregularityScore(leafIrregularities, leafMask); // La comparaison d'histogramme nous permet de faire un masque de probabilité Mat injuriesMask; analyser.compareToHistogram(leafImg, injuriesHisto, injuriesMask); // Segmentation de la feuille Mat injuriesImg; analyser.segmentLeaf(origImg, injuriesMask, injuriesImg); float injuriesScore = analyser.computeInjuriesScore(injuriesImg, injuriesMask); float illnessScore = irregularityScore * injuriesScore * 100; cout << "injuriesScore: " << injuriesScore << endl; cout << "irregularityScore: " << irregularityScore << endl; cout << "score: " << illnessScore << endl; if (illnessScore > 0.5 && injuriesScore > 0.1) { cout << "Leaf is sick " << injuriesScore*100 << "%." << endl; newLeaf.isSick = true; newLeaf.sicknessLevel = injuriesScore*100; } else { cout << "Leaf is not sick." << endl; } Mat finalImg = analyser.createInfoImage(leafImg, leafMask, leafIrregularities); //outfilename = outfileprefix + "_processed.jpg"; imwrite(newLeaf.path + newLeaf.filenameProcessed, finalImg); //outfilename = outfileprefix + "_segmented.jpg"; imwrite(newLeaf.path + newLeaf.filenameSegmented, leafImg); return newLeaf; }
static void check(Analyser& analyser, Decl const* decl) { if (analyser.is_main() && analyser.config()->value("main_namespace_check") == "off") { return; // RETURN } if (analyser.is_global_package()) { return; // RETURN } Location location(analyser.get_location(decl)); NamedDecl const* named(llvm::dyn_cast<NamedDecl>(decl)); if (analyser.is_component(location.file()) && named) { if (llvm::dyn_cast<NamespaceDecl>(decl) || llvm::dyn_cast<UsingDirectiveDecl>(decl)) { // namespace declarations are permissible e.g. for forward declarations. return; // RETURN } else if (TagDecl const* tag = llvm::dyn_cast<TagDecl>(decl)) { // Forward declarations are always permissible but definitions are not. if (!tag->isThisDeclarationADefinition() && analyser.is_component_header(location.file())) { return; // RETURN } } else if (llvm::dyn_cast<NamespaceAliasDecl>(decl) && analyser.is_component_source(decl)) { return; // RETURN } DeclContext const* context(decl->getDeclContext()); std::string name = named->getNameAsString(); if (llvm::dyn_cast<TranslationUnitDecl>(context)) { if (name != "main" && name != "RCSId" && !llvm::dyn_cast<ClassTemplateSpecializationDecl>(decl) && !llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(decl) && name.find("operator new") == std::string::npos && name.find("operator delete") == std::string::npos ) { analyser.report(decl, check_name, "TR04", "Declaration of '%0' at global scope", true) << decl->getSourceRange() << name; } return; // RETURN } NamespaceDecl const* space = llvm::dyn_cast<NamespaceDecl>(context); if (!space) { return; // RETURN } std::string pkgns = analyser.package(); if ( space->isAnonymousNamespace() && llvm::dyn_cast<NamespaceDecl>(space->getDeclContext())) { space = llvm::dyn_cast<NamespaceDecl>(space->getDeclContext()); } if (space->getNameAsString() == analyser.config()->toplevel_namespace()) { // No package namespace. This is OK if no package namespace has // been seen, for the sake of legacy "package_name" components. DeclContext::decl_iterator b = space->decls_begin(); DeclContext::decl_iterator e = space->decls_end(); bool found = false; while (!found && b != e) { const NamespaceDecl *ns = llvm::dyn_cast<NamespaceDecl>(*b++); found = ns && ns->getNameAsString() == analyser.package(); } if (!found) { pkgns = analyser.config()->toplevel_namespace(); } } if (name.length() > 0) { std::string spname = space->getNameAsString(); NamespaceDecl const* outer = space; if (pkgns == analyser.package()) { outer = llvm::dyn_cast<NamespaceDecl>( space->getDeclContext()); } if ((spname != pkgns || !outer || outer->getNameAsString() != analyser.config()->toplevel_namespace()) && ( spname != analyser.config()->toplevel_namespace() || name.find(analyser.package() + '_') != 0 ) && to_lower(spname) != to_lower(analyser.component()) && !llvm::dyn_cast<ClassTemplateSpecializationDecl>(decl) && !llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(decl) && name.find("operator new") == std::string::npos && name.find("operator delete") == std::string::npos && !isSpecialFunction(named) && ( analyser.is_component_header(named) || named->hasLinkage() ) && !analyser.is_ADL_candidate(decl) ) { //-dk:TODO check if this happens in the correct namespace analyser.report(decl, check_name, "TR04", "Declaration of '%0' not within package namespace '%1'", true) << decl->getSourceRange() << name << (analyser.config()->toplevel_namespace() + "::" + analyser.package()) ; } } } }
// This is called from the AnalyserQueue thread bool AnalyserQueue::doAnalysis(TrackPointer tio, SoundSourceProxy* pSoundSource) { // TonalAnalyser requires a block size of 65536. Using a different value // breaks the tonal analyser. We need to use a smaller block size becuase on // Linux, the AnalyserQueue can starve the CPU of its resources, resulting // in xruns.. A block size of 8192 seems to do fine. const int ANALYSISBLOCKSIZE = 8192; int totalSamples = pSoundSource->length(); //qDebug() << tio->getFilename() << " has " << totalSamples << " samples."; int processedSamples = 0; SAMPLE* data16 = new SAMPLE[ANALYSISBLOCKSIZE]; CSAMPLE* samples = new CSAMPLE[ANALYSISBLOCKSIZE]; QTime progressUpdateInhibitTimer; progressUpdateInhibitTimer.start(); // Inhibit Updates for 60 milliseconds int read = 0; bool dieflag = false; bool cancelled = false; int progress; // progress in 0 ... 100 do { ScopedTimer t("AnalyserQueue::doAnalysis block"); read = pSoundSource->read(ANALYSISBLOCKSIZE, data16); // To compare apples to apples, let's only look at blocks that are the // full block size. if (read != ANALYSISBLOCKSIZE) { t.cancel(); } // Safety net in case something later barfs on 0 sample input if (read == 0) { t.cancel(); break; } // If we get more samples than length, ask the analysers to process // up to the number we promised, then stop reading - AD if (read + processedSamples > totalSamples) { qDebug() << "While processing track of length " << totalSamples << " actually got " << read + processedSamples << " samples, truncating analysis at expected length"; read = totalSamples - processedSamples; dieflag = true; } for (int i = 0; i < read; ++i) { samples[i] = ((float)data16[i])/32767.0f; } QListIterator<Analyser*> it(m_aq); while (it.hasNext()) { Analyser* an = it.next(); //qDebug() << typeid(*an).name() << ".process()"; an->process(samples, read); //qDebug() << "Done " << typeid(*an).name() << ".process()"; } // emit progress updates // During the doAnalysis function it goes only to 100% - FINALIZE_PERCENT // because the finalise functions will take also some time processedSamples += read; //fp div here prevents insane signed overflow progress = (int)(((float)processedSamples)/totalSamples * (1000 - FINALIZE_PERCENT)); if (m_progressInfo.track_progress != progress) { if (progressUpdateInhibitTimer.elapsed() > 60) { // Inhibit Updates for 60 milliseconds emitUpdateProgress(tio, progress); progressUpdateInhibitTimer.start(); } } // Since this is a background analysis queue, we should co-operatively // yield every now and then to try and reduce CPU contention. The // analyser queue is CPU intensive so we want to get out of the way of // the audio callback thread. //QThread::yieldCurrentThread(); //QThread::usleep(10); //has something new entered the queue? if (m_aiCheckPriorities) { m_aiCheckPriorities = false; if (isLoadedTrackWaiting(tio)) { qDebug() << "Interrupting analysis to give preference to a loaded track."; dieflag = true; cancelled = true; } } if (m_exit) { dieflag = true; cancelled = true; } // Ignore blocks in which we decided to bail for stats purposes. if (dieflag || cancelled) { t.cancel(); } } while(read == ANALYSISBLOCKSIZE && !dieflag); delete[] data16; delete[] samples; return !cancelled; //don't return !dieflag or we might reanalyze over and over }