private void GenerateBend(Note note, int noteStart, int noteDuration, int noteKey, DynamicValue dynamicValue) { var track = note.Beat.Voice.Bar.Track; var ticksPerPosition = ((double)noteDuration) / BendPoint.MaxPosition; for (int i = 0; i < note.BendPoints.Count - 1; i++) { var currentPoint = note.BendPoints[i]; var nextPoint = note.BendPoints[i + 1]; // calculate the midi pitchbend values start and end values var currentBendValue = DefaultBend + (currentPoint.Value * DefaultBendSemitone); var nextBendValue = DefaultBend + (nextPoint.Value * DefaultBendSemitone); // how many midi ticks do we have to spend between this point and the next one? var ticksBetweenPoints = ticksPerPosition * (nextPoint.Offset - currentPoint.Offset); // we will generate one pitchbend message for each value // for this we need to calculate how many ticks to offset per value var ticksPerValue = ticksBetweenPoints / Math.Abs(nextBendValue - currentBendValue); var tick = noteStart + (ticksPerPosition * currentPoint.Offset); // bend up if (currentBendValue < nextBendValue) { while (currentBendValue <= nextBendValue) { _handler.AddBend(track.Index, (int)tick, (byte)track.PlaybackInfo.PrimaryChannel, (byte)Math.Round(currentBendValue)); currentBendValue++; tick += ticksPerValue; } } // bend down else if (currentBendValue > nextBendValue) { while (currentBendValue >= nextBendValue) { _handler.AddBend(track.Index, (int)tick, (byte)track.PlaybackInfo.PrimaryChannel, (byte)Math.Round(currentBendValue)); currentBendValue--; tick += ticksPerValue; } } } // reset bend _handler.AddBend(track.Index, noteStart + noteDuration, (byte)track.PlaybackInfo.PrimaryChannel, DefaultBend); }
private void GenerateNote(Note note, int beatStart, int beatDuration, int[] brushInfo) { var track = note.Beat.Voice.Bar.Track; var noteKey = track.Capo + note.RealValue; var noteStart = beatStart + brushInfo[note.String - 1]; var noteDuration = GetNoteDuration(note, beatDuration) - brushInfo[note.String - 1]; var dynamicValue = GetDynamicValue(note); // TODO: enable second condition after whammy generation is implemented if (!note.HasBend /* && !note.Beat.HasWhammyBar */) { // reset bend _handler.AddBend(track.Index, noteStart, (byte)track.PlaybackInfo.PrimaryChannel, DefaultBend); } // // Fade in if (note.Beat.FadeIn) { GenerateFadeIn(note, noteStart, noteDuration, noteKey, dynamicValue); } // TODO: grace notes? // // Trill if (note.IsTrill && !track.IsPercussion) { GenerateTrill(note, noteStart, noteDuration, noteKey, dynamicValue); // no further generation needed return; } // // Tremolo Picking if (note.Beat.IsTremolo) { GenerateTremoloPicking(note, noteStart, noteDuration, noteKey, dynamicValue); // no further generation needed return; } // // All String Bending/Variation effects if (note.HasBend) { GenerateBend(note, noteStart, noteDuration, noteKey, dynamicValue); } else if (note.Beat.HasWhammyBar) { GenerateWhammyBar(note, noteStart, noteDuration, noteKey, dynamicValue); } else if (note.SlideType != SlideType.None) { GenerateSlide(note, noteStart, noteDuration, noteKey, dynamicValue); } else if (note.Vibrato != VibratoType.None) { GenerateVibrato(note, noteStart, noteDuration, noteKey, dynamicValue); } // // Harmonics if (note.HarmonicType != HarmonicType.None) { GenerateHarmonic(note, noteStart, noteDuration, noteKey, dynamicValue); } if (!note.IsTieDestination) { _handler.AddNote(track.Index, noteStart, noteDuration, (byte)noteKey, dynamicValue, (byte)track.PlaybackInfo.PrimaryChannel); } }
private void GenerateNote(Note note, int beatStart, int beatDuration, int[] brushInfo) { var track = note.Beat.Voice.Bar.Staff.Track; var staff = note.Beat.Voice.Bar.Staff; var noteKey = note.RealValue; var brushOffset = note.IsStringed && note.String <= brushInfo.Length ? brushInfo[note.String - 1] : 0; var noteStart = beatStart + brushOffset; var noteDuration = GetNoteDuration(note, beatDuration); noteDuration.UntilTieEnd -= brushOffset; noteDuration.NoteOnly -= brushOffset; noteDuration.LetRingEnd -= brushOffset; var dynamicValue = GetDynamicValue(note); var channel = note.HasBend || note.Beat.HasWhammyBar || note.Beat.Vibrato != VibratoType.None ? track.PlaybackInfo.SecondaryChannel : track.PlaybackInfo.PrimaryChannel; var initialBend = DefaultBend; if (note.HasBend) { initialBend += (int)Math.Round(note.BendPoints[0].Value * DefaultBendSemitone); } else if (note.Beat.HasWhammyBar) { initialBend += (int)Math.Round(note.Beat.WhammyBarPoints[0].Value * DefaultBendSemitone); } else if (note.IsTieDestination) { initialBend = 0; } if (initialBend > 0) { _handler.AddBend(track.Index, noteStart, (byte)channel, (byte)initialBend); } // // Fade in if (note.Beat.FadeIn) { GenerateFadeIn(note, noteStart, noteDuration, noteKey, dynamicValue); } // TODO: grace notes? // // Trill if (note.IsTrill && staff.StaffKind != StaffKind.Percussion) { GenerateTrill(note, noteStart, noteDuration, noteKey, dynamicValue, channel); // no further generation needed return; } // // Tremolo Picking if (note.Beat.IsTremolo) { GenerateTremoloPicking(note, noteStart, noteDuration, noteKey, dynamicValue, channel); // no further generation needed return; } // // All String Bending/Variation effects if (note.HasBend) { GenerateBend(note, noteStart, noteDuration, noteKey, dynamicValue, channel); } else if (note.Beat.HasWhammyBar && note.Index == 0) { GenerateWhammy(note.Beat, noteStart, noteDuration, noteKey, dynamicValue, channel); } else if (note.SlideType != SlideType.None) { GenerateSlide(note, noteStart, noteDuration, noteKey, dynamicValue, channel); } else if (note.Vibrato != VibratoType.None) { GenerateVibrato(note, noteStart, noteDuration, noteKey, dynamicValue, channel); } if (!note.IsTieDestination) { var noteSoundDuration = Math.Max(noteDuration.UntilTieEnd, noteDuration.LetRingEnd); _handler.AddNote(track.Index, noteStart, noteSoundDuration, (byte)noteKey, dynamicValue, (byte)channel); } }