/// <summary> /// <see cref="GroorineFile"/> の新しいインスタンスを初期化します。 /// </summary> /// <param name="ct"></param> /// <param name="tracks"></param> /// <param name="resolution"></param> /// <param name="title"></param> /// <param name="copyright"></param> internal GroorineFile(ConductorTrack ct, ObservableCollection <Track> tracks, short resolution, string title, string copyright, long?loopStart = null) { Tracks = tracks; foreach (Track t in tracks) { foreach (NoteEvent ne in t.Events.OfType <NoteEvent>().Where(e => e.Channel == 9 && e.Gate < resolution)) { ne.Gate = resolution; } } Resolution = resolution; Title = title; Copyright = copyright; Conductor = ct; LoopStart = loopStart; if (Tracks?.Count > 0) { Length = Tracks.Max(mt => mt.Length); } }
public MidiFile Generate(int size) { var ct = new ConductorTrack(new ObservableCollection <MetaEvent>(new List <TempoEvent>() { new TempoEvent { Tempo = bpmCandidates.Random() } }), 480); var tracks = new ObservableCollection <Track>(); var drumIsAvailable = Extension.Random(10) < 5; var channels = Extension.Random(1, 17); if (units == null) { return(null); } for (int ch = 0; ch < channels; ch++) { var events = new ObservableCollection <MidiEvent>(); if (units[ch] == null) { continue; } events.Add(new ProgramEvent { Channel = (byte)ch, ProgramNo = (byte)pcCandidates[ch].Random() }); var unit = startUnitCandidates[ch].Random(); unit = unit ?? units[ch].ToList().Random().Value.Random(); if (unit == default) { continue; } var currentTick = 0L; for (int i = 0; i < size; i++) { if (unit.Notes.Length == 0) { break; } foreach (var note in unit.Notes) { events.Add(new NoteEvent { Note = note.Note, Gate = note.Gate, Velocity = note.Velocity, Channel = note.Channel, Tick = currentTick }); } // 候補がなくなったら終了 if (unit.Candidates.Count == 0) { break; } unit = units[ch][unit.Candidates.Random()].Random(); currentTick += unit.Notes[0].Gate + unit.Notes[0].Wait; } events.Add(new EndOfTrackEvent { Channel = (byte)ch, Tick = currentTick }); tracks.Add(new Track(events)); } // チャンネル数がドラムパートに届かなかった場合50%でドラムが入る if (channels < 9 && drumIsAvailable && units[9] != null && units[9].Count > 0) { var events = new ObservableCollection <MidiEvent>(); var unit = units[9].ToList().Random().Value?.Random(); var currentTick = 0L; for (int i = 0; i < size; i++) { if (unit.Notes.Length == 0) { continue; } foreach (var note in unit.Notes) { events.Add(new NoteEvent { Note = note.Note, Gate = note.Gate, Velocity = note.Velocity, Channel = note.Channel, Tick = currentTick }); } // 候補がなくなったら終了 if (unit.Candidates.Count == 0) { break; } unit = units[9][unit.Candidates.Random()].Random(); currentTick += unit.Notes[0].Gate + unit.Notes[0].Wait; } tracks.Add(new Track(events)); } return(new MidiFile(ct, tracks, 480, $"AI Generated Song {DateTime.Now.ToString()}", "")); }