private void DoNote() { DomainModel.Note cr = (DomainModel.Note)currentNote; if (cr.Pitch == "") { Rest r = new Rest(durriation[cr.Duration]); r.NumberOfDots = cr.Dotted; symbols.Add(r); return; } PSAMControlLibrary.Note n = new PSAMControlLibrary.Note(cr.Pitch.ToUpper(), semitones[cr.Semitone], 2 + cr.Octave, durriation[cr.Duration], NoteStemDirection.Up, NoteTieType.None, new List <NoteBeamType>() { NoteBeamType.Single }); n.NumberOfDots = cr.Dotted; float count = 1 / cr.Duration; float dur = (float)((Math.Pow(2, cr.Dotted) - 1) / Math.Pow(2, cr.Dotted)) + 1; barlinecount += (count * dur); symbols.Add(n); }
private void AddNote(Note note) { // set modifier; negative for flats, positive for sharp int modifier = 0; if (note.Modifier == Modifiers.Flat) { modifier = -1; } else if (note.Modifier == Modifiers.Sharp) { modifier = 1; } // set stem direction var direction = GetStemDirection(note); var amount = AmountOfBeams(note.Duration); if (amount > 0) { _buffer.Add(new NoteBeams { Note = note, Beams = Enumerable.Repeat(NoteBeamType.Single, amount).ToList() }); if (_buffer.Count > 3) { FlushBuffer(); } return; // don't add anything till buffer is full or flushed } // if buffer has items, flush before adding new notes if (_buffer.Count > 0) { FlushBuffer(); } var psamNote = new PSAMNote(note.Name.ToString(), modifier, (int)note.Octave, (MusicalSymbolDuration)note.Duration, direction, NoteTieType.None, new List <NoteBeamType> { NoteBeamType.Single }); // set dots psamNote.NumberOfDots = note.Dots; _notes.Add(psamNote); }
public override void AddSymbol(INote note) { int octave = note.Pitch / 12 - 1; Note staffNote = new Note(note.NoteName.ToString().ToUpper(), note.NoteAlteration, octave, (MusicalSymbolDuration)note.Duration, NoteStemDirection.Up, (NoteTieType)note.NoteTieType, new List <NoteBeamType>() { NoteBeamType.Single }); staffNote.NumberOfDots = note.Dots; Symbols.Add(staffNote); }
public static void getMusicSymbols(Staff staff, List <MusicalSymbol> WPFStaffs) { Clef clef = new Clef(ClefType.GClef, 2); if (staff.GetClef() == "bass") { clef = new Clef(ClefType.CClef, 4); } WPFStaffs.Add(clef); int[] time = staff.GetTime(); WPFStaffs.Add(new TimeSignature(TimeSignatureType.Numbers, (UInt32)time[0], (UInt32)time[1])); List <Bar> bars = staff.GetBars(); foreach (Bar bar in bars) { List <NoteRest> notes = bar.GetNotes(); foreach (NoteRest note in notes) { string pitch = ""; int octave = 0; int length = 0; int dots = 0; note.GetInfo(ref pitch, ref octave, ref length, ref dots); if (pitch.Equals("r")) { var rest = new PSAMControlLibrary.Rest((MusicalSymbolDuration)length); WPFStaffs.Add(rest); } else { int alter = 0; alter += Regex.Matches(pitch, "is").Count; alter -= Regex.Matches(pitch, "es|as").Count; var WPFNote = new PSAMControlLibrary.Note(pitch[0].ToString().ToUpper(), alter, octave, (MusicalSymbolDuration)length, NoteStemDirection.Up, NoteTieType.None, new List <NoteBeamType>() { NoteBeamType.Single }) { NumberOfDots = dots }; WPFStaffs.Add(WPFNote); } } WPFStaffs.Add(new Barline()); } }
public void DoRepeat() { DomainModel.BarLine br = (DomainModel.BarLine)currentNote; Barline b = new Barline(); if (br.Type == BarLine.TYPE.REPEAT) { int alt = 1; Barline startAlt = new Barline(); startAlt.AlternateRepeatGroup = alt; symbols.Add(startAlt); for (int i = 0; i < br.Alternatives.Count; i++) { Symbol temp = br.Alternatives[i]; while (temp != null) { DomainModel.Note cr = (DomainModel.Note)temp; PSAMControlLibrary.Note n = new PSAMControlLibrary.Note(cr.Pitch.ToUpper(), 0, 2 + cr.Octave, durriation[cr.Duration], NoteStemDirection.Up, NoteTieType.None, new List <NoteBeamType>() { NoteBeamType.Single }); symbols.Add(n); temp = temp.nextSymbol; } if (i == 0) { alt++; Barline blt = new Barline(); blt.RepeatSign = RepeatSignType.Backward; blt.AlternateRepeatGroup = alt; symbols.Add(blt); continue; } } return; } b.RepeatSign = reapeatType[br.Type]; symbols.Add(b); barlinecount = 0; }
private void HandleNote() { var note = (Models.Note)_element; // Octave if (_mustAlterOctave) { _previousOctave = _alterOctave; _mustAlterOctave = false; } else { CalculateOctave(note); } _previousNote = note.NoteType; // Note tie type var noteTieType = NoteTieType.None; if (note.IsTied) { noteTieType = NoteTieType.Start; _isTied = true; } else if (_isTied) { noteTieType = NoteTieType.Stop; _isTied = false; } // Create and add new note var newNote = new PSAMControlLibrary.Note(note.NoteType.ToString(), (int)note.AlterType, _previousOctave, (MusicalSymbolDuration)note.DurationType, NoteStemDirection.Up, noteTieType, new List <NoteBeamType> { NoteBeamType.Single }) { NumberOfDots = note.Dots }; _symbols.Add(newNote); }
private void AddBeamedNotes(List <NoteBeams> noteBeams) { // set same directions var direction = noteBeams.Select(note => GetStemDirection(note.Note)).Max(d => d); // last note to end var last = noteBeams[noteBeams.Count - 1]; for (var i = 0; i < last.Beams.Count; i++) { if (last.Beams[i] == NoteBeamType.Continue) { last.Beams[i] = NoteBeamType.End; } } foreach (var note in noteBeams) { // set modifier; negative for flats, positive for sharp int modifier = 0; if (note.Note.Modifier == Modifiers.Flat) { modifier = -1; } else if (note.Note.Modifier == Modifiers.Sharp) { modifier = 1; } var psamNote = new PSAMNote(note.Note.Name.ToString(), modifier, (int)note.Note.Octave, (MusicalSymbolDuration)note.Note.Duration, direction, NoteTieType.None, note.Beams); // set dots psamNote.NumberOfDots = note.Note.Dots; _notes.Add(psamNote); } }
/// <summary> /// We create MIDI from WPF staffs, 2 different dependencies, not a good practice. /// TODO: Create MIDI from our own domain classes. /// TODO: Our code doesn't support repeats (rendering notes multiple times) in midi yet. Maybe with a COMPOSITE this will be easier? /// </summary> /// <returns></returns> private Sequence GetSequenceFromWPFStaffs() { List <string> notesOrderWithCrosses = new List <string>() { "c", "cis", "d", "dis", "e", "f", "fis", "g", "gis", "a", "ais", "b" }; int absoluteTicks = 0; Sequence sequence = new Sequence(); Track metaTrack = new Track(); sequence.Add(metaTrack); // Calculate tempo int speed = (60000000 / _bpm); byte[] tempo = new byte[3]; tempo[0] = (byte)((speed >> 16) & 0xff); tempo[1] = (byte)((speed >> 8) & 0xff); tempo[2] = (byte)(speed & 0xff); metaTrack.Insert(0 /* Insert at 0 ticks*/, new MetaMessage(MetaType.Tempo, tempo)); Track notesTrack = new Track(); sequence.Add(notesTrack); for (int i = 0; i < WPFStaffs.Count; i++) { var musicalSymbol = WPFStaffs[i]; switch (musicalSymbol.Type) { case MusicalSymbolType.Note: Note note = musicalSymbol as Note; // Calculate duration double absoluteLength = 1.0 / (double)note.Duration; absoluteLength += (absoluteLength / 2.0) * note.NumberOfDots; double relationToQuartNote = _beatNote / 4.0; double percentageOfBeatNote = (1.0 / _beatNote) / absoluteLength; double deltaTicks = (sequence.Division / relationToQuartNote) / percentageOfBeatNote; // Calculate height int noteHeight = notesOrderWithCrosses.IndexOf(note.Step.ToLower()) + ((note.Octave + 1) * 12); noteHeight += note.Alter; notesTrack.Insert(absoluteTicks, new ChannelMessage(ChannelCommand.NoteOn, 1, noteHeight, 90)); // Data2 = volume absoluteTicks += (int)deltaTicks; notesTrack.Insert(absoluteTicks, new ChannelMessage(ChannelCommand.NoteOn, 1, noteHeight, 0)); // Data2 = volume break; case MusicalSymbolType.TimeSignature: byte[] timeSignature = new byte[4]; timeSignature[0] = (byte)_beatsPerBar; timeSignature[1] = (byte)(Math.Log(_beatNote) / Math.Log(2)); metaTrack.Insert(absoluteTicks, new MetaMessage(MetaType.TimeSignature, timeSignature)); break; default: break; } } notesTrack.Insert(absoluteTicks, MetaMessage.EndOfTrackMessage); metaTrack.Insert(absoluteTicks, MetaMessage.EndOfTrackMessage); return(sequence); }
private static IEnumerable <MusicalSymbol> GetStaffsFromTokens(LinkedList <LilypondToken> tokens) { List <MusicalSymbol> symbols = new List <MusicalSymbol>(); PSAMControlLibrary.Clef currentClef = null; int previousOctave = 4; char previousNote = 'c'; bool inRepeat = false; bool inAlternative = false; int alternativeRepeatNumber = 0; LilypondToken currentToken = tokens.First(); while (currentToken != null) { // TODO: There are a lot of switches based on LilypondTokenKind, can't those be eliminated en delegated? // HINT: Command, Decorator, Factory etc. // TODO: Repeats are somewhat weirdly done. Can we replace this with the COMPOSITE pattern? switch (currentToken.TokenKind) { case LilypondTokenKind.Unknown: break; case LilypondTokenKind.Repeat: inRepeat = true; symbols.Add(new Barline() { RepeatSign = RepeatSignType.Forward }); break; case LilypondTokenKind.SectionEnd: if (inRepeat && currentToken.NextToken?.TokenKind != LilypondTokenKind.Alternative) { inRepeat = false; symbols.Add(new Barline() { RepeatSign = RepeatSignType.Backward, AlternateRepeatGroup = alternativeRepeatNumber }); } else if (inAlternative && alternativeRepeatNumber == 1) { alternativeRepeatNumber++; symbols.Add(new Barline() { RepeatSign = RepeatSignType.Backward, AlternateRepeatGroup = alternativeRepeatNumber }); } else if (inAlternative && currentToken.NextToken.TokenKind == LilypondTokenKind.SectionEnd) { inAlternative = false; alternativeRepeatNumber = 0; } break; case LilypondTokenKind.SectionStart: if (inAlternative && currentToken.PreviousToken.TokenKind != LilypondTokenKind.SectionEnd) { alternativeRepeatNumber++; symbols.Add(new Barline() { AlternateRepeatGroup = alternativeRepeatNumber }); } break; case LilypondTokenKind.Alternative: inAlternative = true; inRepeat = false; currentToken = currentToken.NextToken; // Skip the first bracket open. break; case LilypondTokenKind.Note: // Tied // TODO: A tie, like a dot and cross or mole are decorations on notes. Is the DECORATOR pattern of use here? NoteTieType tie = NoteTieType.None; if (currentToken.Value.StartsWith("~")) { tie = NoteTieType.Stop; var lastNote = symbols.Last(s => s is PSAMControlLibrary.Note) as PSAMControlLibrary.Note; if (lastNote != null) { lastNote.TieType = NoteTieType.Start; } currentToken.Value = currentToken.Value.Substring(1); } // Length int noteLength = Int32.Parse(Regex.Match(currentToken.Value, @"\d+").Value); // Crosses and Moles int alter = 0; alter += Regex.Matches(currentToken.Value, "is").Count; alter -= Regex.Matches(currentToken.Value, "es|as").Count; // Octaves int distanceWithPreviousNote = notesorder.IndexOf(currentToken.Value[0]) - notesorder.IndexOf(previousNote); if (distanceWithPreviousNote > 3) // Shorter path possible the other way around { distanceWithPreviousNote -= 7; // The number of notes in an octave } else if (distanceWithPreviousNote < -3) { distanceWithPreviousNote += 7; // The number of notes in an octave } if (distanceWithPreviousNote + notesorder.IndexOf(previousNote) >= 7) { previousOctave++; } else if (distanceWithPreviousNote + notesorder.IndexOf(previousNote) < 0) { previousOctave--; } // Force up or down. previousOctave += currentToken.Value.Count(c => c == '\''); previousOctave -= currentToken.Value.Count(c => c == ','); previousNote = currentToken.Value[0]; var note = new PSAMControlLibrary.Note(currentToken.Value[0].ToString().ToUpper(), alter, previousOctave, (MusicalSymbolDuration)noteLength, NoteStemDirection.Up, tie, new List <NoteBeamType>() { NoteBeamType.Single }); note.NumberOfDots += currentToken.Value.Count(c => c.Equals('.')); symbols.Add(note); break; case LilypondTokenKind.Rest: var restLength = Int32.Parse(currentToken.Value[1].ToString()); symbols.Add(new PSAMControlLibrary.Rest((MusicalSymbolDuration)restLength)); break; case LilypondTokenKind.Bar: symbols.Add(new Barline() { AlternateRepeatGroup = alternativeRepeatNumber }); break; case LilypondTokenKind.Clef: currentToken = currentToken.NextToken; if (currentToken.Value == "treble") { currentClef = new PSAMControlLibrary.Clef(ClefType.GClef, 2); } else if (currentToken.Value == "bass") { currentClef = new PSAMControlLibrary.Clef(ClefType.FClef, 4); } else { throw new NotSupportedException($"Clef {currentToken.Value} is not supported."); } symbols.Add(currentClef); break; case LilypondTokenKind.Time: currentToken = currentToken.NextToken; var times = currentToken.Value.Split('/'); symbols.Add(new TimeSignature(TimeSignatureType.Numbers, UInt32.Parse(times[0]), UInt32.Parse(times[1]))); break; case LilypondTokenKind.Tempo: // Tempo not supported break; default: break; } currentToken = currentToken.NextToken; } return(symbols); }
private static IEnumerable <MusicalSymbol> GetStaffsFromTokens(LinkedList <LilypondToken> tokens, out string message) { List <MusicalSymbol> symbols = new List <MusicalSymbol>(); message = ""; try { Clef currentClef = null; int previousOctave = 4; char previousNote = 'c'; LilypondToken currentToken = tokens.First(); while (currentToken != null) { switch (currentToken.TokenKind) { case LilypondTokenKind.Unknown: break; case LilypondTokenKind.Note: // Length int noteLength = Int32.Parse(Regex.Match(currentToken.Value, @"\d+").Value); // Crosses and Moles int alter = 0; alter += Regex.Matches(currentToken.Value, "is").Count; alter -= Regex.Matches(currentToken.Value, "es|as").Count; // Octaves int distanceWithPreviousNote = notesorder.IndexOf(currentToken.Value[0]) - notesorder.IndexOf(previousNote); if (distanceWithPreviousNote > 3) // Shorter path possible the other way around { distanceWithPreviousNote -= 7; // The number of notes in an octave } else if (distanceWithPreviousNote < -3) { distanceWithPreviousNote += 7; // The number of notes in an octave } if (distanceWithPreviousNote + notesorder.IndexOf(previousNote) >= 7) { previousOctave++; } else if (distanceWithPreviousNote + notesorder.IndexOf(previousNote) < 0) { previousOctave--; } // Force up or down. previousOctave += currentToken.Value.Count(c => c == '\''); previousOctave -= currentToken.Value.Count(c => c == ','); previousNote = currentToken.Value[0]; var note = new PSAMControlLibrary.Note(currentToken.Value[0].ToString().ToUpper(), alter, previousOctave, (MusicalSymbolDuration)noteLength, NoteStemDirection.Up, NoteTieType.None, new List <NoteBeamType>() { NoteBeamType.Single }); note.NumberOfDots += currentToken.Value.Count(c => c.Equals('.')); symbols.Add(note); break; case LilypondTokenKind.Rest: var restLength = Int32.Parse(currentToken.Value[1].ToString()); symbols.Add(new Rest((MusicalSymbolDuration)restLength)); break; case LilypondTokenKind.Bar: symbols.Add(new Barline()); break; case LilypondTokenKind.Clef: currentToken = currentToken.NextToken; if (currentToken.Value == "treble") { currentClef = new Clef(ClefType.GClef, 2); } else if (currentToken.Value == "bass") { currentClef = new Clef(ClefType.FClef, 4); } else { throw new NotSupportedException($"Clef {currentToken.Value} is not supported."); } symbols.Add(currentClef); break; case LilypondTokenKind.Time: currentToken = currentToken.NextToken; var times = currentToken.Value.Split('/'); symbols.Add(new TimeSignature(TimeSignatureType.Numbers, UInt32.Parse(times[0]), UInt32.Parse(times[1]))); break; case LilypondTokenKind.Tempo: // Tempo not supported break; default: break; } currentToken = currentToken.NextToken; } } catch (Exception ex) { message = ex.Message; } return(symbols); }
public Sequence GetSequenceFromStaff(Staff staff) { List <string> notesOrderWithCrosses = new List <string>() { "c", "cis", "d", "dis", "e", "f", "fis", "g", "gis", "a", "ais", "b" }; int absoluteTicks = 0; Sequence sequence = new Sequence(); Track metaTrack = new Track(); sequence.Add(metaTrack); Track notesTrack = new Track(); sequence.Add(notesTrack); int speed = 60000000 / staff.GetTempo(); byte[] tempo = new byte[3]; tempo[0] = (byte)((speed >> 16) & 0xff); tempo[1] = (byte)((speed >> 8) & 0xff); tempo[2] = (byte)(speed & 0xff); metaTrack.Insert(0 /* Insert at 0 ticks*/, new MetaMessage(MetaType.Tempo, tempo)); List <MusicalSymbol> WPFStaffs = new List <MusicalSymbol>(); WPFManager.getMusicSymbols(staff, WPFStaffs); foreach (MusicalSymbol musicalSymbol in WPFStaffs) { int[] time; double absoluteLength; double relationToQuartNote; double percentageOfBeatNote; double deltaTicks; switch (musicalSymbol.Type) { case MusicalSymbolType.Note: Note note = musicalSymbol as Note; absoluteLength = 1.0 / (double)note.Duration; absoluteLength += (absoluteLength / 2.0) * note.NumberOfDots; time = staff.GetTime(); relationToQuartNote = time[1] / 4.0; percentageOfBeatNote = (1.0 / time[1]) / absoluteLength; deltaTicks = (sequence.Division / relationToQuartNote) / percentageOfBeatNote; // Calculate height int noteHeight = notesOrderWithCrosses.IndexOf(note.Step.ToLower()) + ((note.Octave + 1) * 12); noteHeight += note.Alter; notesTrack.Insert(absoluteTicks, new ChannelMessage(ChannelCommand.NoteOn, 1, noteHeight, 90)); // Data2 = volume absoluteTicks += (int)deltaTicks; notesTrack.Insert(absoluteTicks, new ChannelMessage(ChannelCommand.NoteOn, 1, noteHeight, 0)); // Data2 = volume break; case MusicalSymbolType.Rest: Rest rest = musicalSymbol as Rest; absoluteLength = 1.0 / (double)rest.Duration; absoluteLength += (absoluteLength / 2.0) * rest.NumberOfDots; time = staff.GetTime(); relationToQuartNote = time[1] / 4.0; percentageOfBeatNote = (1.0 / time[1]) / absoluteLength; deltaTicks = (sequence.Division / relationToQuartNote) / percentageOfBeatNote; absoluteTicks += (int)deltaTicks; break; case MusicalSymbolType.TimeSignature: time = staff.GetTime(); byte[] timeSignature = new byte[4]; timeSignature[0] = (byte)time[0]; timeSignature[1] = (byte)(Math.Log(time[1]) / Math.Log(2)); metaTrack.Insert(absoluteTicks, new MetaMessage(MetaType.TimeSignature, timeSignature)); break; default: break; } } notesTrack.Insert(absoluteTicks, MetaMessage.EndOfTrackMessage); metaTrack.Insert(absoluteTicks, MetaMessage.EndOfTrackMessage); return(sequence); }