Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 38 additions & 16 deletions src/Rocksmith2014.DD/EntityChooser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,18 @@ let private pruneChordNotes
if notesToRemove < 0 then
failwith $"Chord at time %O{float cn[0].Time / 1000.} has less chord notes than its chord template."

for i = cn.Count - notesToRemove to cn.Count - 1 do
if cn[i].IsLinkNext then
removedLinkNexts.Set(int cn[i].String, true)
// Remove the notes on the highest pitched strings (the seventh string is the lowest)
let removed =
cn
|> Seq.sortByDescending (fun n -> pitchRank n.String)
|> Seq.truncate notesToRemove
|> Seq.toArray

for n in removed do
if n.IsLinkNext then
removedLinkNexts.Set(int n.String, true)

cn.RemoveRange(cn.Count - notesToRemove, notesToRemove)
cn.Remove(n) |> ignore

for n in cn do
pruneTechniques diffPercent removedLinkNexts n
Expand Down Expand Up @@ -140,13 +147,14 @@ let private isFirstChordInHs (entities: XmlEntity list) (handShapes: HandShape l
let private chordNotesFromTemplate (template: ChordTemplate) (chord: Chord) =
let cn = ResizeArray<Note>()

for i = 0 to 5 do
if template.Frets[i] <> -1y then
for i = 0 to template.StringCount - 1 do
let fret = template.Frets[i]
if fret <> -1y then
cn.Add(
Note(
Time = chord.Time,
String = sbyte i,
Fret = template.Frets[i],
Fret = fret,
LeftHand = template.Fingers[i],
IsFretHandMute = chord.IsFretHandMute,
IsPalmMute = chord.IsPalmMute,
Expand All @@ -167,19 +175,33 @@ let private noteFromChord

if chord.HasChordNotes then
let cns = chord.ChordNotes
let noteIndex = if fromHighest then cns.Count - 1 else 0
let rank (n: Note) = pitchRank n.String

let selected =
if fromHighest then
cns |> Seq.maxBy rank
else
cns |> Seq.minBy rank

// Create the note from a chord note
for i = 0 to cns.Count - 1 do
if i <> noteIndex && cns[i].IsLinkNext then
removedLinkNexts.Set(int cns[i].String, true)
for cn in cns do
if not (Object.ReferenceEquals(cn, selected)) && cn.IsLinkNext then
removedLinkNexts.Set(int cn.String, true)

let note = Note(cns[noteIndex], LeftHand = -1y)
let note = Note(selected, LeftHand = -1y)
pruneTechniques diffPercent removedLinkNexts note
note
else
// Create the note from the chord template
let find = if fromHighest then Array.findIndexBack else Array.findIndex
let string = template.Frets |> find ((<>) -1y)
let usedStrings =
StringLayout.LowToHigh(template.StringCount)
|> Array.filter (fun stringIndex -> template.Frets[stringIndex] <> -1y)

let string =
if fromHighest then
Array.last usedStrings
else
Array.head usedStrings

Note(
Time = chord.Time,
Expand All @@ -200,8 +222,8 @@ let choose (diffPercent: float)
(maxChordNotes: int)
(entities: XmlEntity array) =
// Strings from which a linknext note has been removed
let removedLinkNexts = BitArray(6)
let pendingLinkNexts: PendingLinkNexts = Array.zeroCreate 6
let removedLinkNexts = BitArray(StringLayout.MaxStringCount)
let pendingLinkNexts: PendingLinkNexts = Array.zeroCreate StringLayout.MaxStringCount
let currentNotesWithScore = Dictionary<NoteScore, int>()

let incrementCount division =
Expand Down
26 changes: 13 additions & 13 deletions src/Rocksmith2014.DD/TemplateRequestApplier.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ type private NewData = { Fingers: sbyte array; Frets: sbyte array }
let private globalTemplatesLock = obj ()

/// Returns new finger and fret arrays for the chord template with the given number of notes removed.
let private removeNotes (notesToRemove: int) (fromHighest: bool) (template: ChordTemplate) =
/// Uses musical order because string 6 is below the stock strings.
let private removeNotes (notesToRemove: int) (fromHighest: bool) (template: ChordTemplate) : NewData =
let fingers = Array.copy template.Fingers
let frets = Array.copy template.Frets
let startIndex, change = if fromHighest then 0, 1 else frets.Length - 1, -1
let lowToHigh = StringLayout.LowToHigh(template.StringCount)
let removalOrder = if fromHighest then lowToHigh else Array.rev lowToHigh
let mutable leftToRemove = notesToRemove

let rec loop i leftToRemove =
if leftToRemove = 0 || i < 0 || i > 5 then
assert (leftToRemove = 0)
{ Fingers = fingers; Frets = frets }
elif frets[i] <> -1y then
fingers[i] <- -1y
frets[i] <- -1y
loop (i + change) (leftToRemove - 1)
else
loop (i + change) leftToRemove
for stringIndex in removalOrder do
if leftToRemove > 0 && frets[stringIndex] <> -1y then
fingers[stringIndex] <- -1y
frets[stringIndex] <- -1y
leftToRemove <- leftToRemove - 1

loop startIndex notesToRemove
assert (leftToRemove = 0)

{ Fingers = fingers; Frets = frets }

/// Returns the ID of an existing chord template if an identical one already exists, otherwise adds a new template to the global template list.
let private getChordId (templates: ResizeArray<ChordTemplate>) (template: ChordTemplate) (newData: NewData) =
Expand Down
11 changes: 8 additions & 3 deletions src/Rocksmith2014.DD/Utils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ let getNoteCount (template: ChordTemplate) =
template.Frets
|> Array.sumBy (fun fret -> Convert.ToInt32(fret >= 0y))

/// Orders strings low to high; string 6 precedes string 0.
let pitchRank (stringIndex: sbyte) =
StringLayout.MusicalRank(int stringIndex, StringLayout.MaxStringCount)

let getAllowedChordNotes (diffPercent: float) (maxChordNotesInPhrase: int) =
if maxChordNotesInPhrase = 0 then
0
Expand All @@ -21,9 +25,10 @@ let getAllowedChordNotes (diffPercent: float) (maxChordNotesInPhrase: int) =

/// For double and triple stops on the highest strings, start adding notes from the highest string.
let shouldStartFromHighestNote (totalNotes: int) (template: ChordTemplate) =
let fr = template.Frets
(totalNotes = 3 && fr[5] > -1y && fr[4] > -1y && fr[3] > -1y)
|| (totalNotes = 2 && fr[5] > -1y && fr[4] > -1y)
let fr = StringLayout.ToLowToHigh(template.Frets)
let length = fr.Length
(totalNotes = 3 && length >= 3 && fr[length - 1] > -1y && fr[length - 2] > -1y && fr[length - 3] > -1y)
|| (totalNotes = 2 && length >= 2 && fr[length - 1] > -1y && fr[length - 2] > -1y)

let createTemplateRequest (originalId: int16) (noteCount: int) (totalNotes: int) (template: ChordTemplate) (target: RequestTarget) =
let startFromHighestNote = shouldStartFromHighestNote totalNotes template
Expand Down
10 changes: 7 additions & 3 deletions src/Rocksmith2014.XML.Processing/Checkers/InstrumentalChecker.fs
Original file line number Diff line number Diff line change
Expand Up @@ -312,13 +312,17 @@ let private chordHasBarreOverOpenStrings (chordTemplates: ResizeArray<ChordTempl
chordTemplates
|> ResizeArray.tryItem (int chord.ChordId)
|> Option.exists (fun ct ->
// The barre span is determined in pitch order (the seventh string is the lowest)
let fingers = StringLayout.ToLowToHigh(ct.Fingers)
let frets = StringLayout.ToLowToHigh(ct.Frets)

[ 0y..4y ]
|> List.exists (fun finger ->
let low = Array.IndexOf(ct.Fingers, finger)
let high = Array.LastIndexOf(ct.Fingers, finger)
let low = Array.IndexOf(fingers, finger)
let high = Array.LastIndexOf(fingers, finger)

low <> -1 && high > low &&
ct.Frets.AsSpan(low, high - low).Contains(0y)))
frets.AsSpan(low, high - low).Contains(0y)))

let private chordHasMutedString (chord: Chord) =
not chord.IsFretHandMute
Expand Down
5 changes: 3 additions & 2 deletions src/Rocksmith2014.XML.Processing/Improvers/BasicFixes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ let removeMutedNotesFromChords (arrangement: InstrumentalArrangement) =
|> Option.iter (fun template ->
mutedNotes.ForEach(fun n ->
let i = int n.String
template.Frets[i] <- -1y
template.Fingers[i] <- -1y)
if i >= 0 && i < template.StringCount then
template.Frets[i] <- -1y
template.Fingers[i] <- -1y)
)

fixedChordTemplates.Add(chord.ChordId) |> ignore
Expand Down
10 changes: 7 additions & 3 deletions src/Rocksmith2014.XML.Processing/Improvers/CustomEvents.fs
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,16 @@ let improve (arrangement: InstrumentalArrangement) =
let chordId = int16 arrangement.ChordTemplates.Count
level.HandShapes.InsertByTime(HandShape(chordId, startTime, endTime))

// Create a new chord template for the handshape
let soChordTemplate = ChordTemplate()
// Create a new chord template for the handshape (same string count as the original template)
let soChordTemplate = ChordTemplate(originalChordTemplate.StringCount)
for note in notes do
let s = int note.String
if s >= soChordTemplate.StringCount then
soChordTemplate.EnsureStringCount(s + 1)

soChordTemplate.Frets[s] <- note.SlideUnpitchTo
soChordTemplate.Fingers[s] <- originalChordTemplate.Fingers[s]
soChordTemplate.Fingers[s] <-
if s < originalChordTemplate.StringCount then originalChordTemplate.Fingers[s] else -1y

arrangement.ChordTemplates.Add(soChordTemplate)

Expand Down
3 changes: 2 additions & 1 deletion src/Rocksmith2014.XML.Processing/Utils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ let findPreviousChordUsingSameString
else
templates
|> ResizeArray.tryItem (int chord.ChordId)
|> Option.exists (fun template -> template.Frets[int stringNum] > -1y))
|> Option.exists (fun template ->
stringNum >= 0y && int stringNum < template.StringCount && template.Frets[int stringNum] > -1y))
|> Option.map (fun chord ->
let fret =
chord.ChordNotes
Expand Down
Loading