public async Task <Unit> Handle(MoveNoteCommand request, CancellationToken cancellationToken) { if (request == null) { throw new ArgumentNullException(nameof(request)); } IReturnDbContext dbContext = this._returnDbContextFactory.CreateForEditContext(); // Get data Note?note = await dbContext.Notes .Include(x => x.Lane) .Include(x => x.Group) .Include(x => x.Retrospective) .FirstOrDefaultAsync(x => x.Id == request.NoteId, cancellationToken); if (note == null) { throw new NotFoundException(nameof(Note), request.NoteId); } NoteGroup?newTargetGroup = null; if (request.GroupId != null) { newTargetGroup = await dbContext.NoteGroups.Include(x => x.Lane). FirstOrDefaultAsync(x => x.Id == request.GroupId, cancellationToken); if (newTargetGroup == null) { throw new NotFoundException(nameof(NoteGroup), request.GroupId.Value); } } // Validate if (newTargetGroup != null && note.Lane.Id != newTargetGroup.Lane.Id) { throw new InvalidOperationException("Invalid move command: this would result in a lane change."); } NoteGroup involvedGroup = newTargetGroup ?? note.Group ?? throw new InvalidOperationException("Note move from ungrouped to ungrouped"); await this._securityValidator.EnsureAddOrUpdate(note.Retrospective, involvedGroup); // Update note.GroupId = newTargetGroup?.Id; note.Group = newTargetGroup; await dbContext.SaveChangesAsync(cancellationToken); // Broadcast var broadcast = new NoteMovedNotification(note.Retrospective.UrlId.StringId, (int)note.Lane.Id, note.Id, note.GroupId); await this._mediator.Publish(broadcast, cancellationToken); return(Unit.Value); }
public async Task <Note?> GetNoteAsyn(int noteId) { var response = await Client.GetStringAsync("https://localhost:44342/api/Notes/" + noteId.ToString()); Note?note = JsonConvert.DeserializeObject <Note>(response); return(note); }
public override Result Process(Note[] notes, Note?prev, Note?next, Note?prevNeighbour, Note?nextNeighbour) { // The overall logic is: // 1. Remove consonant: "duang" -> "uang". // 2. Lookup the trailing sound in vowel table: "uang" -> "_ang". // 3. Split the total duration and returns "duang" and "_ang". var note = notes[0]; string vowel = string.Empty; if (note.lyric.Length > 2 && cSet.Contains(note.lyric.Substring(0, 2))) { // First try to find consonant "zh", "ch" or "sh", and extract vowel. vowel = note.lyric.Substring(2); } else if (note.lyric.Length > 1 && cSet.Contains(note.lyric.Substring(0, 1))) { // Then try to find single character consonants, and extract vowel. vowel = note.lyric.Substring(1); } // Otherwise we don't need the vowel. string phoneme0 = note.lyric; // We will need to split the total duration for phonemes, so we compute it here. int totalDuration = notes.Sum(n => n.duration); // Lookup the vowel split table. For example, "uang" will match "_ang". if (vDict.TryGetValue(vowel, out var phoneme1)) { // Now phoneme0="duang" and phoneme1="_ang", // try to give "_ang" 120 ticks, but no more than half of the total duration. int length1 = 120; if (length1 > totalDuration / 2) { length1 = totalDuration / 2; } return(new Result { phonemes = new Phoneme[] { new Phoneme() { phoneme = phoneme0, }, new Phoneme() { phoneme = phoneme1, position = totalDuration - length1, } }, }); } // Not spliting is needed. Return as is. return(new Result { phonemes = new Phoneme[] { new Phoneme() { phoneme = phoneme0, } }, }); }
public double GetFrequency(Note?tuningNote = null) { if (tuningNote == null) { tuningNote = new Note?(Note.A4); } int dist = (int)(this.GetStep() - tuningNote.Value.GetStep()); return(440.0 * Math.Pow(1.0594630943592953, (double)dist)); }
private void popNextNote() { if (songNotes.Count > 0) { nextNote = songNotes[0]; songNotes.RemoveAt(0); } else { nextNote = null; } }
/// <summary> /// Calculates the note's frequency in Hz. /// </summary> /// <param name="tuningNote">Optional note to use for tuning, this is Note.A4 (440 Hz) by default.</param> /// <returns>Frequency in Hz.</returns> public double GetFrequency(Note?tuningNote = null) { if (!tuningNote.HasValue) { tuningNote = Note.A4; } int dist = GetStep() - tuningNote.Value.GetStep(); double freq = 440 * Math.Pow(1.0594630943592952645618252949463, dist); return(freq); }
public override Result Process(Note[] notes, Note?prev, Note?next, Note?prevNeighbour, Note?nextNeighbour) { // Note that even when input has multiple notes, only the leading note is used to produce phoneme. // This is because the 2nd+ notes will always be extender notes, i.e., with lyric "..." or "...<number>". // For this simple phonemizer, all these notes maps to a single phoneme. return(new Result { phonemes = new Phoneme[] { new Phoneme { phoneme = notes[0].lyric, } } }); }
private async void OnDeleteNoteClicked(object?sender, EventArgs e) { if (_currentNote is null) { return; } await _guiContext.InvokeAsync(async() => { DialogResult msg = MessageBox.Show("Delete selected note?", "Delete Note", MessageBoxButtons.YesNo); if (msg == DialogResult.Yes) { var current = await _noteRepository.GetAsync(_currentNote.Id); await _noteRepository.DeleteAsync(current); _currentNote = null; _eventService.Publish <RefreshListEvent>(new()); } }); }
private static void AddIntroApplauseEvent(InstrumentalArrangement arrangement, Action <string> Log) { Level firstPhraseLevel; if (arrangement.Levels.Count == 1) { firstPhraseLevel = arrangement.Levels[0]; } else { // Find the first phrase that has difficulty levels int firstPhraseId = arrangement.PhraseIterations .First(pi => arrangement.Phrases[pi.PhraseId].MaxDifficulty > 0) .PhraseId; var firstPhrase = arrangement.Phrases[firstPhraseId]; firstPhraseLevel = arrangement.Levels[firstPhrase.MaxDifficulty]; } Note?firstNote = null; if (firstPhraseLevel.Notes.Count > 0) { firstNote = firstPhraseLevel.Notes[0]; } Chord?firstChord = null; if (firstPhraseLevel.Chords.Count > 0) { firstChord = firstPhraseLevel.Chords[0]; } int applauseStartTime = GetMinTime(firstNote, firstChord) + IntroCrowdReactionDelay; int applauseEndTime = applauseStartTime + IntroApplauseLength; var startEvent = new Event("E3", applauseStartTime); var stopEvent = new Event("E13", applauseEndTime); arrangement.Events.InsertByTime(startEvent); arrangement.Events.InsertByTime(stopEvent); Log($"Added intro applause event (E3) at time: {applauseStartTime.TimeToString()}."); }
public NotePresenter( ILogger <NotePresenter> logger, INoteView view, IEventService eventService, IRepository <Note> noteRepository, IGuiContext guiContext) { _logger = logger; _view = view; _eventService = eventService; _noteRepository = noteRepository; _guiContext = guiContext; _view.SaveNoteClicked += OnSaveNoteClicked; _view.DeleteNoteClicked += OnDeleteNoteClicked; _eventService.Subscribe <NoteCreatedEvent>(e => { _currentNote = new Note(); _logger.LogInformation(nameof(NoteCreatedEvent)); _view.SetNote(_currentNote); _saved = false; _view.SaveButtonEnabled = true; _view.DeleteButtonEnabled = false; }); _eventService.Subscribe <SelectedNoteChangedEvent>(e => { _currentNote = e.SelectedNote; _logger.LogInformation(nameof(SelectedNoteChangedEvent)); if (_currentNote is not null) { _logger.LogWarning("current not is not null"); _view.SetNote(_currentNote); _saved = true; _view.SaveButtonEnabled = false; _view.DeleteButtonEnabled = true; } }); }
public async Task <Unit> Handle(UpdateNoteCommand request, CancellationToken cancellationToken) { if (request == null) { throw new ArgumentNullException(nameof(request)); } using IReturnDbContext editDbContext = this._returnDbContext.CreateForEditContext(); Note?note = await editDbContext.Notes .Include(x => x.Retrospective) .Include(x => x.Participant) .FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken); if (note == null) { throw new NotFoundException(nameof(Note), request.Id); } // Validate operation await this._securityValidator.EnsureAddOrUpdate(note.Retrospective, note); // Update the note note.Text = request.Text ?? String.Empty; await editDbContext.SaveChangesAsync(cancellationToken); var notification = new NoteUpdatedNotification(NoteUpdate.FromNote(note)); if (note.Retrospective.CurrentStage == RetrospectiveStage.Writing) { notification = new NoteUpdatedNotification(new NoteUpdate(note.Id, this._textAnonymizingService.AnonymizeText(notification.Note.Text))); } await this._mediator.Publish(notification, cancellationToken); return(Unit.Value); }
private async void OnSaveNoteClicked(object?sender, EventArgs e) { if (_currentNote is null) { return; } var current = await _noteRepository.GetAsync(_currentNote.Id); // If it doesnt exist, create if (current is null) { _currentNote.Notes = _view.GetNoteText(); await _noteRepository.InsertAsync(_currentNote); } else { current.Notes = _view.GetNoteText(); _currentNote = current; await _noteRepository.UpdateAsync(_currentNote); } _eventService.Publish <RefreshListEvent>(new(_currentNote)); }
public override Result Process(Note[] notes, Note?prev, Note?next, Note?prevNeighbour, Note?nextNeighbour) { var note = notes[0]; // Get the symbols of previous note. var prevSymbols = prevNeighbour == null ? null : GetSymbols(prevNeighbour.Value); // Get the symbols of current note. var symbols = GetSymbols(note); if (symbols == null || symbols.Length == 0) { // No symbol is found for current note. if (note.lyric == "-" && prevSymbols != null) { // The user is using a tail "-" note to produce a "<something> -" sound. return(new Result { phonemes = new Phoneme[] { new Phoneme() { phoneme = $"{prevSymbols.Last()} -", } }, }); } // Otherwise assumes the user put in an alias. return(new Result { phonemes = new Phoneme[] { new Phoneme() { phoneme = note.lyric, } }, }); } // Find phone types of symbols. var isVowel = symbols.Select(s => mergedG2p.IsVowel(s)).ToArray(); // Arpasing aligns the first vowel at 0 and shifts leading consonants to negative positions, // so we need to find the first vowel. int firstVowel = Array.IndexOf(isVowel, true); var phonemes = new Phoneme[symbols.Length]; // Creates the first diphone using info of the previous note. string prevSymbol = prevSymbols == null ? "-" : prevSymbols.Last(); string phoneme = $"{prevSymbol} {symbols[0]}"; if (!singer.TryGetMappedOto(phoneme, note.tone, out var _)) { // Arpasing voicebanks are often incomplete. If the voicebank doesn't have this diphone, fallback to use a more likely to exist one. phoneme = $"- {symbols[0]}"; } phonemes[0] = new Phoneme { phoneme = phoneme, }; // The 2nd+ diphones. for (int i = 1; i < symbols.Length; i++) { // The logic is very similar to creating the first diphone. phonemes[i] = new Phoneme { phoneme = GetPhonemeOrFallback(symbols[i - 1], symbols[i], note.tone), }; } // Alignments // Alignment is where a user use "...n" (n is a number) to align n-th phoneme with an extender note. // We build the aligment points first, these are the phonemes must be aligned to a certain position, // phonemes that are not aligment points are distributed in-between. alignments.Clear(); if (firstVowel > 0) { // If there are leading consonants, add the first vowel as an align point. alignments.Add(Tuple.Create(firstVowel, 0)); } else { firstVowel = 0; } int position = 0; for (int i = 0; i < notes.Length; ++i) { string alignmentHint = notes[i].lyric; if (alignmentHint.StartsWith("...")) { alignmentHint = alignmentHint.Substring(3); } else { position += notes[i].duration; continue; } // Parse the number n in "...n". if (int.TryParse(alignmentHint, out int index)) { index--; // Convert from 1-based index to 0-based index. if (index > 0 && (alignments.Count == 0 || alignments.Last().Item1 < index) && index < phonemes.Length) { // Adds a alignment point. // Some details in the if condition: // 1. The first phoneme cannot be user-aligned. // 2. The index must be incrementing, otherwise ignored. // 3. The index must be within range. alignments.Add(Tuple.Create(index, position)); } } position += notes[i].duration; } alignments.Add(Tuple.Create(phonemes.Length, position)); int startIndex = 0; int startTick = -ConsonantLength * firstVowel; foreach (var alignment in alignments) { // Distributes phonemes between two aligment points. DistributeDuration(isVowel, phonemes, startIndex, alignment.Item1, startTick, alignment.Item2); startIndex = alignment.Item1; startTick = alignment.Item2; } alignments.Clear(); MapPhonemes(notes, phonemes, singer); return(new Result { phonemes = phonemes, }); }
public KeyScoreCard(Note targetKey) { _targetKey = targetKey; Init(); }
/// <summary> /// Phonemize a consecutive sequence of notes. This is the main logic of a phonemizer. /// </summary> /// <param name="notes">A note and its extender notes. Always one or more.</param> /// <param name="prev">The note before the leading note, if exists.</param> /// <param name="next">The note after the last extender note, if exists.</param> /// <param name="prevNeighbour">Same as prev if is immediate neighbour, otherwise null.</param> /// <param name="nextNeighbour">Same as next if is immediate neighbour, otherwise null.</param> public abstract Result Process(Note[] notes, Note?prev, Note?next, Note?prevNeighbour, Note?nextNeighbour);
/// <inheritdoc /> public int CompareTo(Note?other) { return(0); }