public string Encode(IEnumerable <BmsEvent> events, Func <BigRational?, string> encodeValue, BigRational measureLength, int quantize) { var eventList = events.AsList(); // round up and multiply for longer measures (100% minimoo-G would be a nightmare otherwise) var maxQ = Math.Max(quantize, (int)((measureLength + BigRational.OneHalf).GetWholePart() * quantize)); var q = _quantizer.GetQuantization(eventList.Select(e => e.Offset), BigInteger.One, maxQ); var buffer = Enumerable.Range(0, q).Select(i => (BigRational?)null).ToArray(); foreach (var ev in eventList) { var i = (int)(ev.Offset * q); buffer[i] = ev.Value; } var builder = new StringBuilder(); foreach (var i in buffer) { builder.Append(encodeValue(i)); } return(builder.ToString()); }
private IEnumerable <char[][]> EncodeMeasures(IEnumerable <Note> notes) { var notesList = notes.AsList(); if (!notesList.Any()) { yield break; } var columns = notesList.Max(n => n.Column) + 1; var measures = notesList.GroupBy(n => n.MetricOffset.GetWholePart()).AsList(); var maxMeasure = measures.Max(m => m.Key); for (var measureNumber = 0; measureNumber <= maxMeasure; measureNumber++) { var measure = measures.FirstOrDefault(m => m.Key == measureNumber) ?? Enumerable.Empty <Note>(); var measureNotes = measure.ToArray(); var quantization = _quantizer.GetQuantization(measureNotes.Select(n => n.MetricOffset), MinimumQuantization, MaximumQuantization); var half = new BigRational(1, quantization * 2); var grid = Enumerable.Range(0, quantization) .Select(i => Enumerable.Repeat(NoteType.None, columns).ToArray()).ToArray(); foreach (var note in measureNotes) { var row = (int)(note.MetricOffset.GetFractionPart() * quantization + half); if (row < 0) { row = 0; } if (row >= quantization) { row = quantization - 1; } grid[row][note.Column] = note.Type; } yield return(grid); } }