Beispiel #1
0
        /// <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));
        }
Beispiel #2
0
        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;
            }
        }
Beispiel #3
0
 public Note(NotePitch pitchIn, double timeIn, double durationIn, uint channelIn, int velocityIn)
 {
     pitch    = pitchIn;
     time     = timeIn;
     duration = durationIn;
     channel  = channelIn;
     velocity = velocityIn;
 }
Beispiel #4
0
        /// <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;
                }
            });
        }
Beispiel #6
0
 public void SetPitch(NotePitch pitch)
 {
     _pitch = pitch;
     if (_pitch < NotePitch.B5)
     {
         SwapToBottom();
     }
     else
     {
         SwapToTop();
     }
 }
Beispiel #7
0
        /// <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);
        }
Beispiel #8
0
        /// <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);
        }
Beispiel #10
0
 public Note(float spawnTime, NotePitch notePitch)
 {
     SpawnTime = spawnTime;
     NotePitch = notePitch;
 }
Beispiel #11
0
 /// <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())
 {
 }
Beispiel #12
0
 /// <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))
 {
 }
Beispiel #13
0
 /// <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);
 }
Beispiel #14
0
        /// <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);
        }
Beispiel #15
0
 public void SetPitch(NotePitch pitchIn)
 {
     pitch = pitchIn;
 }
Beispiel #16
0
 /// <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();
            }
        }
Beispiel #18
0
        /// <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);
        }
Beispiel #19
0
 /// <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);
Beispiel #20
0
 /// <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);