internal static clsScore GetTopChordSeg(int[] inpercent, int[] basspercent, clsKeyTicks mkey, clsMTime.clsSegment segment, out string chordname, out List <int> chnotes) { int length = 0; foreach (int percent in inpercent) { if (percent > 0) { length++; } } //if (length <= 2) { if (length < (int)P.frmStart.nudMinChordSize.Value) //should be 0 unless advanced... { chordname = ""; chnotes = null; return(null); } List <clsScore> chlist = GetChordsSeg(inpercent, basspercent, mkey, segment); if (chlist.Count == 0) { chnotes = new List <int>(); chordname = ""; return(null); } chnotes = chlist[0].ChNotes; //highest score chordname = chlist[0].Desc; //chordname = ChordAnalysis.UTemplates[chlist[0].TIndex].Name; return(chlist[0]); }
internal clsSegments(clsNoteMap notemap) { //CSVFileConv = csvfileconv; //int barnum = 1; //tmp debugging clsMTime.clsSegment startbar = new clsMTime.clsSegBar(P.F.TicksPerQI, 0, P.F.MaxBBT.QI); for (clsMTime.clsSegment bar = startbar; !bar.OOR; bar++) { //Debug.WriteLine("Bar: " + barnum++ // + " TicksLo: " + bar.SegQILo * P.F.TicksPerQI // + " TicksHi: " + bar.SegQIHi * P.F.TicksPerQI); //temp debugging int[] seg = new int[12]; for (int qi = bar.SegQILo; qi <= bar.SegQIHi; qi++) { notemap.CalcKeys_CalcSegQI(seg, qi, ref indEmpty); //CalcSegQI(notemap, seg, qi, indEmpty); } Segs.Add(seg); } }
internal void FillSegments(eAlign align, int qilo, int qihi, int fillpercent, int qiwidth) { //* fill or empty segments (bars/halfbars/beats) by modded note if (align == eAlign.Interval && qiwidth == 0) { return; } int ticksperqi = P.F.TicksPerQI; for (int n = 0; n < 12; n++) { clsMTime.clsSegment startseg = GetStartSeg(align, qilo, qihi, qiwidth, ticksperqi); //* quantize for (clsMTime.clsSegment segment = startseg; !segment.OOR; segment++) { int totqiall = segment.SegQIWidth; int totqion = 0; int segqilo = segment.SegQILo; int segqihi = segment.SegQIHi; for (int qi = segqilo; qi <= segqihi; qi++) { if (IsF(qi, n)) { totqion++; } } int percent = (totqion * 100) / totqiall; bool fill = false; if (totqion > 0 && percent >= fillpercent) { fill = true; //fill segment (else clear) } for (int qi = segqilo; qi <= segqihi; qi++) { SetF(qi, n, fill); //fill or clear segment } } } }
internal int[] GetFillPercent(clsFileStream filestream, clsMTime.clsSegment segment, bool indbass) { //* return occupancy as a percent for each modded note in segment int offsetqi = 0; bool offsetpre = false; int swing = (int)P.frmCfgChords.trkSwing.Value - 50; if (segment is clsMTime.clsSegHalfBar && swing != 0) { offsetqi = swing * segment.SegQIWidth / 50; if (segment.SegBBTLo.BeatsRemBar > 0) { offsetpre = true; } } int[] ret = new int[12]; int maxpercent = 0; for (int n = 0; n < 12; n++) { int totqiall = 0; int totqion = 0; int segqilo = segment.SegQILo; int segqihi = segment.SegQIHi; if (offsetpre) { segqilo += offsetqi; } else { segqihi += offsetqi; } if (indbass || P.frmCfgChords.chkWeightedScores.Checked) { foreach (clsTrks.T trk in P.F.Chan.Next) { bool select = (indbass) ? P.F.FSTrackMap.TrkType[trk] == clsFileStream.eTrkType.Bass : filestream.TrkSelect[trk]; if (select && P.F.Chan[trk] != 9) //not percussion { totqiall += segment.SegQIWidth; //qi * num selectedtrks for (int qi = segqilo; qi <= segqihi; qi++) { //* may be trimmed - OK //* may be quantized - not recommended, but should still work if (IsF(qi, n) && this[qi, n, trk]) { totqion++; } } //if (indbass) trk = trk + 1 - 1; } } } else //unweighted { totqiall = segment.SegQIWidth; for (int qi = segqilo; qi <= segqihi; qi++) { if (IsF(qi, n)) { totqion++; } } } int percent = (totqiall == 0) ? 0 : (totqion * 100) / totqiall; maxpercent = Math.Max(maxpercent, percent); ret[n] = percent; } if (!indbass && maxpercent > 0) { for (int i = 0; i < 12; i++) { if (ret[i] > 0) { ret[i] = (ret[i] * 100) / maxpercent; } } } return(ret); }
internal void ApplyTrim(eAlign aligntrim, int qilo, int qihi, int qiquant, int qiinner, int qiouter) { //* trim syncopated notes //* uses OnOffPair - apply before other filters bool pretrim = P.frmCfgChords.chkTrimPre.Checked; bool posttrim = P.frmCfgChords.chkTrimPost.Checked; if (qiinner == 0 || qiouter == 0) { return; } if (!pretrim && !posttrim) { return; } int ticksperqi = P.F.TicksPerQI; if (OnOffPairs == null) { CreateOnOffPairs(); } for (int n = 0; n < 12; n++) { clsOnOffPairs pairs = OnOffPairs[n]; if (pretrim) { clsMTime.clsSegment startseg = GetStartSeg(aligntrim, qilo, qihi, qiquant, ticksperqi); for (clsMTime.clsSegment segment = startseg; !segment.OOR; segment++) { if (qiinner > segment.SegQIWidth / 2) { continue; //'before' too large } if (qiouter < segment.SegQIWidth / 8) { continue; //'after' too small } //* check if trim required int indexoffq = pairs.IndexOffQ(segment.SegQILo); //first ON at or after SeqQILo if (indexoffq < 0) { continue; //after last event } int offq = pairs.Off(indexoffq); if (offq > segment.SegQILo + qiinner) { continue; } int onq = pairs.On(indexoffq); if (onq > segment.SegQILo - qiouter) { continue; } //* trim //for (int q = offq; q >= segment.SegQILo; q--) SetF(q, n, false); for (int q = segment.SegQILo; q < segment.SegQILo + qiinner; q++) { SetF(q, n, false); } } } if (posttrim) { clsMTime.clsSegment startseg = GetStartSeg(aligntrim, qilo, qihi, qiquant, ticksperqi); for (clsMTime.clsSegment segment = startseg; !segment.OOR; segment++) { if (qiinner > segment.SegQIWidth / 2) { continue; //'before' too large } if (qiouter < segment.SegQIWidth / 8) { continue; //'after' too small } //* check if trim required int indexonq = pairs.IndexOnQ(segment.SegQIHi); //first ON at or before SeqQIHi if (indexonq < 0) { continue; //before first event } int onq = pairs.On(indexonq); if (onq < segment.SegQIHi + 1 - qiinner) { continue; } int offq = pairs.Off(indexonq); if (offq < segment.SegQIHi + 1 + qiouter) { continue; } //* trim //for (int q = onq; q <= segment.SegQIHi; q++) SetF(q, n, false) for (int q = segment.SegQIHi; q > segment.SegQIHi - qiouter; q--) { SetF(q, n, false); } } } } }
internal static List <clsScore> GetChordsSeg(int[] inpercent, int[] basspercent, clsKeyTicks mkey, clsMTime.clsSegment segment) { //* inpc = segment weights for each pitchclass (0 = not present, 100 = occupies whole segment //* calculate scores //* segment param only used by dumpscores List <clsScore> scores = new List <clsScore>(); bool[] prevpc = new bool[12]; int adder = (int)P.frmCfgChords.nudAdder.Value; //high value favours 3-note chords... int factor = (int)P.frmCfgChords.nudChordFactor.Value; //high value favours notes present for (int t = 0; t < USToTemplate.Count; t++) //each possible chord (template) { if (USToTemplate.Values[t].Rank > MaxType) { continue; } if (USToTemplate.Values[t].Length > MaxNotes) { continue; } if (USToTemplate.Values[t].PC.SequenceEqual(prevpc)) { continue; } for (int r = 0; r < 12; r++) //for each root { int score = 0; for (int p = 0; p < 12; p++) //each pitchclass { int pp = p - r; if (pp < 0) { pp += 12; } //* calc score for this t/r/p //* range: -50 to 50 //if (Templates[t].PC[pp]) score += factor * inpc[p] - adder; else score += adder - inpc[p]; if (USToTemplate.Values[t].PC[pp]) { score += (factor * inpercent[p]) / 10 - adder; } else { score += adder - inpercent[p]; } } //* calc template pc relative to current key bool[] temppc = new bool[12]; for (int i = 0; i < 12; i++) { if (USToTemplate.Values[t].PC[i]) { int tempi = (i + r - mkey.KeyNote).Mod12(); temppc[tempi] = true; } } clsScore newscore = new clsScore(score, t, r, mkey, temppc, basspercent); scores.Add(newscore); } prevpc = USToTemplate.Values[t].PC; } if (scores.Count == 0) { return(new List <clsScore>()); } scores.Sort(new SimpleScoreComparer()); //simple sort (score only) scores.Reverse(); //highest score first #if (DEBUG && DumpTopScores) clsMTime.clsBBT bbt = new clsMTime.clsBBT(segment.SegQILo * P.F.TicksPerQI); DumpScores(XSWDump, -1, mkey, bbt, scores, ""); #endif //* create list of top scores, sorted by other criteria List <clsScore> topscores = new List <clsScore>(9); topscores.Add(scores[0]); //top score for (int i = 1; i < scores.Count; i++) //start at second element { if (scores[i].Score <= scores[0].Score - (int)P.frmCfgChords.nudScoreRange.Value) { break; } topscores.Add(scores[i]); } //topscores.Sort(new SecondaryScoreComparer()); //secondary fields, then score topscores.Sort(new AggScoreComparer()); //aggregate score topscores.Reverse(); if (P.frmCfgChords.chkRemoveDups.Checked) { topscores = RemoveDups(topscores); } #if (DEBUG && DumpTopScores) DumpScores(XSWDumpTop, -1, mkey, bbt, topscores, ""); #endif return(topscores); }