/// <summary> Returns the <see cref="NoteName"/> for the given pitch.</summary> /// <param name="notePitch"></param> /// <returns> The name of the given pitch</returns> private static NoteName GetNoteName(NotePitch notePitch) { var pitch = (SevenBitNumber)(int)(notePitch); var noteName = Melanchall.DryWetMidi.MusicTheory.Note.Get(pitch).NoteName; return(ConvertToInternalNoteName(noteName)); }
private void PlayNote(NotePitch notePitch) { switch (notePitch) { case NotePitch.A: SFXPlayer.Instance.Play(Sound.GuitarA); break; case NotePitch.D: SFXPlayer.Instance.Play(Sound.GuitarD); break; case NotePitch.E: SFXPlayer.Instance.Play(Sound.GuitarE); break; case NotePitch.F: SFXPlayer.Instance.Play(Sound.GuitarF); break; case NotePitch.G: SFXPlayer.Instance.Play(Sound.GuitarG); break; } }
public Note(NotePitch pitchIn, double timeIn, double durationIn, uint channelIn, int velocityIn) { pitch = pitchIn; time = timeIn; duration = durationIn; channel = channelIn; velocity = velocityIn; }
/// <inheritdoc cref="GetNotes(IChord, ChordNoteMappingSource, NotePitch, NotePitch)"/> internal static IEnumerable <NotePitch> GetNotes(IChord chord, ChordNoteMappingSource mappingSource, int minOctave = 0, int maxOctave = 9) { int basePitch = MusicTheoryServices.SemitonesInOctave; NotePitch minPitch = (NotePitch)(basePitch + (minOctave * MusicTheoryServices.SemitonesInOctave)); NotePitch maxPitch = (NotePitch)(basePitch + ((maxOctave + 1) * MusicTheoryServices.SemitonesInOctave) - 1); return(MusicTheoryServices.GetNotes(chord, mappingSource, minPitch, maxPitch)); }
public void AddPitch(NotePitch pitch) { IsPitchNote(); setters.Add(n => { if (n is PitchNote pn) { pn.Pitch = pitch; } }); }
public void SetPitch(NotePitch pitch) { _pitch = pitch; if (_pitch < NotePitch.B5) { SwapToBottom(); } else { SwapToTop(); } }
/// <summary> /// Evaluates fitness according to the melody's pitch range. /// This fitness is calculated as the ration between the user's requested pitch range, /// and the actual candidate's melody pitch range. /// </summary> /// <param name="candidate"> The melody candidate to evaluate. </param> /// <returns> The fitness outcome score for the requested evaluation. </returns> private protected double EvaluatePitchRange(MelodyCandidate candidate) { // get user preference for pitch range int requestedRange = MaxPitch - MinPitch; // calculate the actual pitch range in this candidate's melody IEnumerable <NotePitch> allPitches = candidate.Bars.GetAllPitches(); NotePitch actualMaxPitch = allPitches.Max(p => p); NotePitch actualMinPitch = allPitches.Min(p => p); int actualRange = actualMaxPitch - actualMinPitch; // return fitness as ration between the actual range and requested range return((double)actualRange / requestedRange); }
/// <summary> /// Returns the <see cref="NoteName"/> which corresponds to the /// given <paramref name="notePitch"/>. /// </summary> /// <param name="notePitch"> MIDI absolute pitch value</param> /// <returns> name of the note represented by the given pitch. </returns> private static NoteName?GetNoteNameByNotePitch(NotePitch notePitch) { // get the enum's underlying value int pitchValue = (int)notePitch; // ignore rest (silent) notes & hold notes if (pitchValue < MidiMinimumPitchValue || pitchValue > MidiMaximumPitchValue) { return(null); } // get the relevant note according to midi pitch values chart int remainder = pitchValue % Note.NumberOfUniqueChromaticNotes; switch (remainder) { case 0: return(NoteName.C); case 1: return(NoteName.CSharp); case 2: return(NoteName.D); case 3: return(NoteName.DSharp); case 4: return(NoteName.E); case 5: return(NoteName.F); case 6: return(NoteName.FSharp); case 7: return(NoteName.G); case 8: return(NoteName.GSharp); case 9: return(NoteName.A); case 10: return(NoteName.ASharp); case 11: return(NoteName.B); default: return(null); } }
private NotePitch GetPitch(Note note) { Vector3 pos = note.transform.position; float minDistance = Mathf.Infinity; NotePitch pitch = NotePitch.E4; for (int i = 0; i < _notePositions.Count; i++) { if (Mathf.Abs(note.transform.position.y - _notePositions[i].transform.position.y) < minDistance) { minDistance = Mathf.Abs(note.transform.position.y - _notePositions[i].transform.position.y); pitch = _notePositions[i].Pitch; pos.y = _notePositions[i].transform.position.y; } } note.transform.position = pos; return(pitch); }
public Note(float spawnTime, NotePitch notePitch) { SpawnTime = spawnTime; NotePitch = notePitch; }
/// <summary> /// Constructs a note with given <paramref name="pitch"/> and default duration. /// </summary> /// <param name="pitch">Absolute pitch of the constructed note. </param> public Note(NotePitch pitch) : this(pitch, MusicTheoryFactory.CreateDuration()) { }
/// <summary> /// Construct a note with given <paramref name="pitch"/> and a /// duration composed with the quotient of the numerator /// divided by the denominator. /// </summary> /// <param name="pitch">MIDI absolute pitch value.</param> /// <param name="numerator">Duration numerator.</param> /// <param name="denominator">Duration denominator.</param> public Note(NotePitch pitch, byte numerator, byte denominator) : this(pitch, MusicTheoryFactory.CreateDuration(numerator, denominator)) { }
/// <summary> /// <para > Basic Constructor. </para> /// Constructs a new <see cref="INote"/> instance with /// the given <paramref name="pitch"/> and <paramref name="duration"/>. /// </summary> /// <param name="pitch"> MIDI absolute pitch value. </param> /// <param name="duration"> Duration of new note. </param> public Note(NotePitch pitch, IDuration duration) { Pitch = pitch; Name = GetNoteNameByNotePitch(pitch); Duration = MusicTheoryFactory.CreateDuration(duration.Numerator, duration.Denominator); }
/// <summary> /// Composes a solo-melody over this composition's midi playback file and chord progression, /// using the additional preferences and constraints parameters. /// </summary> /// <returns> A new midi file containing the composed solo-melody. </returns> /// <param name="strategy">Requested composition strategy algorithm for composing the melody. </param> /// <param name="overallNoteDurationFeel">Requested generic density overall feeling of the outcome melody.</param> /// <param name="musicalInstrument">Requested virtual music instrumen tha would play the output melody.</param> /// <param name="pitchRangeSource">Determins whether to set the pitch range from the original melody in the /// midi file, or from the custom values mentiones in <paramref name="minPitch"/> /// and <paramref name="maxPitch"/>.</param> /// <param name="minPitch">Requested lowest available pitch that would can be used for the composition. /// This is relevant only if <paramref name="pitchRangeSource"/> was set to /// <see cref="PitchRangeSource.Custom"/>.</param> /// <param name="maxPitch">Requested highest available pitch that would can be used for the composition. /// This is relevant only if <paramref name="pitchRangeSource"/> was set to /// <see cref="PitchRangeSource.Custom"/>.</param> /// <param name="useExistingMelodyAsSeed">If set, then the original melody might be used in initialization phase /// of the compositon strategy algorithm. This is relevant only if the /// midi file contains an existing melody to begin with. /// Moreover, this feature is implementation dependent: some strategies /// might make high use of original melody as the main initialization seed /// and some may not use it at all.</param> /// <param name="customParams"> Currently unused. This a placeholder for additional parameters that could be used /// in the future to extened existing implementations and developing new ones without /// breaking the existing interface. </param> /// <returns></returns> public IMidiFile[] Compose( CompositionStrategy strategy = CompositionStrategy.GeneticAlgorithmStrategy, OverallNoteDurationFeel overallNoteDurationFeel = OverallNoteDurationFeel.Medium, MusicalInstrument musicalInstrument = MusicalInstrument.AcousticGrandPiano, PitchRangeSource pitchRangeSource = PitchRangeSource.Custom, NotePitch minPitch = DefaultMinPitch, NotePitch maxPitch = DefaultMaxPitch, bool useExistingMelodyAsSeed = true, params object[] customParams) { // set compositor according to composition strategy _composer = ComposerFactory.CreateComposer(strategy); // make a copy of the input midi file for the output file MidiOutputFile = MidiFactory.CreateMidiFile(_midiInputFilePath); /* if the midi file already contains a melody track, * extract it out of the intended midi output file * and if requested, save it in a separate bar sequence for further usage * as a melody initialization seed for the composition if needed. */ if (_melodyTrackIndex.HasValue && _melodyTrackIndex.Value != MelodyTrackIndex.NoMelodyTrackInFile) { /* if the existing melody should serve as a seed, * initialize a bar-sequence place-holder for it, * based on the chord progression structure */ _melodySeed = useExistingMelodyAsSeed ? CompositionContext.CloneChordProgressionBars(ChordProgression) : null; /* extract/remove the existing melody from midi file and * save it in the place holder if it was initialized */ MidiOutputFile.ExtractMelodyTrack((byte)_melodyTrackIndex, _melodySeed); } // initialize pitch range from midi file if requested if (pitchRangeSource == PitchRangeSource.MidiFile && _melodyTrackIndex.HasValue) { NotePitch?lowestPitch, highestPitch; MidiInputFile.GetPitchRangeForTrack((int)_melodyTrackIndex, out lowestPitch, out highestPitch); if (lowestPitch.HasValue && highestPitch.HasValue) { minPitch = (NotePitch)lowestPitch; maxPitch = (NotePitch)highestPitch; } } // validate pitch range is at least one octave long (12 semi-tones) if (!IsPitchRangeValid((int)minPitch, (int)maxPitch, out string errorMessage)) { throw new ArgumentException(errorMessage); } // compose a new melody IList <IBar>[] composedMelodies = _composer.Compose( chordProgression: ChordProgression, melodyInitializationSeed: _melodySeed, overallNoteDurationFeel: overallNoteDurationFeel, minPitch: minPitch, maxPitch: maxPitch, customParams: customParams) .ToArray(); // Embed each new generated melody into a new separate midi file IMidiFile[] midiOutputs = new IMidiFile[composedMelodies.Length]; for (int i = 0; i < composedMelodies.Length; i++) { midiOutputs[i] = MidiFactory.CreateMidiFile(_midiInputFilePath); midiOutputs[i].ExtractMelodyTrack((byte)_melodyTrackIndex); midiOutputs[i].EmbedMelody(composedMelodies[i], musicalInstrument); midiOutputs[i].FadeOut(); } // save first output in dedicated placeholder MidiOutputFile = midiOutputs[0]; // return the first composed melody from the output return(midiOutputs); }
public void SetPitch(NotePitch pitchIn) { pitch = pitchIn; }
/// <summary> /// Construct a note with given <paramref name="pitch"/> and a /// duration composed with the quotient of the numerator /// divided by the denominator. /// </summary> /// <param name="pitch"> MIDI absolute pitch value. </param> /// <param name="duration"> Duration of new note. </param> internal static INote CreateNote(NotePitch pitch, IDuration duration) => new Note(pitch, duration);
private protected override void InitializeCompositionParams(IList <IBar> chordProgression, IList <IBar> melodyInitializationSeed = null, OverallNoteDurationFeel overallNoteDurationFeel = OverallNoteDurationFeel.Medium, NotePitch minPitch = NotePitch.E2, NotePitch maxPitch = NotePitch.E6, params object[] additionalParams) { // delegate the general initialization to base class base.InitializeCompositionParams(chordProgression, melodyInitializationSeed, overallNoteDurationFeel, minPitch, maxPitch); // initialize custom settings of the genetic algorithm _currentGeneration = 0; _candidates = new List <MelodyCandidate>(MaxPopulationSize); if (additionalParams.Length > 0 && additionalParams[0] is MelodyEvaluatorsWeights) { EvaluatorsWeights = additionalParams[0] as MelodyEvaluatorsWeights; } else { EvaluatorsWeights = new MelodyEvaluatorsWeights(); } }
/// <summary> /// Returns notes that sound "good" under the given chord and pitch range restriction. /// </summary> /// <param name="chord"> he requested chrod to map the notes against. </param> /// <param name="mappingSource"> The mapping source - either scale notes or the chord's arpeggio notes. </param> /// <param name="minPitch"> Lower bound pitch range constraint for the mapped notes. </param> /// <param name="maxPitch"> Upper bound pitch range constraint for the mapped notes. </param> /// <returns> Notes that sound "good" under the given chord, mapping source, and pitch range restriction. </returns> internal static IEnumerable <NotePitch> GetNotes(IChord chord, ChordNoteMappingSource mappingSource, NotePitch minPitch, NotePitch maxPitch) { // build the scale (sequence of intervals from the chord's root note) var rootNote = ConvertToExternalNoteName(chord.ChordRoot); Scale scale = null; switch (chord.ChordType) { case ChordType.Diminished: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Three, Interval.Three, Interval.Six }, rootNote); } else // diminished arppeigo with added 9th { scale = new Scale(new Interval[] { Interval.One, Interval.Two, Interval.Three, Interval.Six }, rootNote); } break; case ChordType.Dominant7: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Three, Interval.Three, Interval.Two }, rootNote); } else // mixolydian scale with omitted 4th { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.Three, Interval.Two, Interval.One, Interval.Two }, rootNote); } break; case ChordType.Dominant7b9: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Three, Interval.Three, Interval.Three, Interval.FromHalfSteps(-1) }, rootNote); } else // harmonic minor v scale with 6th omitted { scale = new Scale(new Interval[] { Interval.One, Interval.Three, Interval.One, Interval.Two, Interval.Three, Interval.Two }, rootNote); } break; case ChordType.Dominant7Suspended4: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Five, Interval.Two, Interval.Three, Interval.Two }, rootNote); } else // mixolydian scale { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.One, Interval.Two, Interval.Two, Interval.One, Interval.Two }, rootNote); } break; case ChordType.Dominant7Augmented5: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Four, Interval.Two, Interval.Two }, rootNote); } else // whole tone scale { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.Two, Interval.Two, Interval.Two, Interval.Two }, rootNote); } break; case ChordType.Dominant7Sharped9: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Three, Interval.Three, Interval.Four, Interval.FromHalfSteps(-3) }, rootNote); } else // mixolydian #2 scale with omitted 4th { scale = new Scale(new Interval[] { Interval.Three, Interval.One, Interval.Three, Interval.Two, Interval.One, Interval.Two }, rootNote); } break; case ChordType.HalfDiminished: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Three, Interval.Three, Interval.Four, Interval.Two }, rootNote); } else // locrian mode scale with ommited 2nd { scale = new Scale(new Interval[] { Interval.Three, Interval.Two, Interval.One, Interval.Two, Interval.Two, Interval.Two }, rootNote); } break; case ChordType.Major: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Three, Interval.Five }, rootNote); } else // dorian major scale with omitted 4th and 7th { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.Three, Interval.Two, Interval.Three }, rootNote); } break; case ChordType.Major7: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Three, Interval.Four, Interval.One }, rootNote); } else // dorian major scale with omitted 4th { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.Three, Interval.Two, Interval.Two, Interval.One }, rootNote); } break; case ChordType.MajorAugmented5: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Four, Interval.Four }, rootNote); } else // lydian augmented scale { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.Two, Interval.Two, Interval.One, Interval.Two, Interval.One }, rootNote); } break; case ChordType.MajorSuspended4: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Five, Interval.Two, Interval.Five }, rootNote); } else // mixolydian scale { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.One, Interval.Two, Interval.Two, Interval.One, Interval.Two }, rootNote); } break; case ChordType.Minor: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Three, Interval.Four, Interval.Five }, rootNote); } else // aeolian minor scale with omitted 2nd and 6th { scale = new Scale(new Interval[] { Interval.Three, Interval.Two, Interval.Two, Interval.Three, Interval.Two }, rootNote); } break; case ChordType.Minor6: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Three, Interval.Four, Interval.Two, Interval.Three }, rootNote); } else // dorian minor scale with omitted 7th { scale = new Scale(new Interval[] { Interval.Two, Interval.One, Interval.Two, Interval.Two, Interval.Two, Interval.Three }, rootNote); } break; case ChordType.Minor7: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Three, Interval.Four, Interval.Three, Interval.Two }, rootNote); } else // aeolian minor scale with omitted 6th { scale = new Scale(new Interval[] { Interval.Two, Interval.One, Interval.Two, Interval.Two, Interval.Three, Interval.Two }, rootNote); } break; case ChordType.MinorMajor7: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Three, Interval.Four, Interval.Four, Interval.One }, rootNote); } else // harmonic minor scale { scale = new Scale(new Interval[] { Interval.Two, Interval.One, Interval.Two, Interval.Two, Interval.One, Interval.Three, Interval.One }, rootNote); } break; case ChordType.Major13: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Three, Interval.Two, Interval.Three }, rootNote); } else // dorian major scale with omitted 4th and 7th { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.Three, Interval.Two, Interval.Three }, rootNote); } break; default: break; } // get actual notes and filter out results according to range constraints var result = from note in scale.GetNotes() where (int)note.NoteNumber >= (byte)minPitch && (int)note.NoteNumber <= (byte) maxPitch select(NotePitch)(int) note.NoteNumber; return(result); }
/// <summary> /// Constructs a new <see cref="INote"/> instance with /// the given <paramref name="pitch"/> and <paramref name="duration"/>. /// </summary> /// <param name="pitch">MIDI absolute pitch value.</param> /// <param name="numerator">Duration numerator.</param> /// <param name="denominator">Duration denominator.</param> internal static INote CreateNote(NotePitch pitch, byte numerator, byte denominator) => new Note(pitch, numerator, denominator);
/// <summary> Constructs a note with given<paramref name="pitch"/> and default duration. </summary> /// <param name="pitch">MIDI Absolute pitch of the constructed note.</param> internal static INote CreateNote(NotePitch pitch) => new Note(pitch);