public ActionResult AudioAndDictation(int resolutionType, string keySignature, double bpm, int numberOfMeasures) { // We'll add stuff to the Dictionary and return as JSON. var dict = new Dictionary <string, string>(); #region Audio //double bpm = double.Parse(ConfigurationManager.AppSettings["BPM"]); double quarterNoteMillis = (60 / bpm) * 1000; TimeSpan quarterNoteDuration = TimeSpan.FromMilliseconds(quarterNoteMillis); TimeSpan halfNoteDuration = TimeSpan.FromMilliseconds(quarterNoteMillis * 2); TimeSpan dottedHalfNoteDuration = TimeSpan.FromMilliseconds(quarterNoteMillis * 3); TimeSpan wholeNoteDuration = TimeSpan.FromMilliseconds(quarterNoteMillis * 4); // Setup the scale note numbers. int[] scaleNoteNumbers = new int[] { 38, 39, 41, 43, 44, 46, 48, 50, 51 }; // C Major, with a low TI. scaleNoteNumbers = NoteHelper.TransposeScaleNoteNumbers(scaleNoteNumbers, keySignature); // The initial DO. ISampleProvider wholeDoNote = NAudioHelper.GetSampleProvider(scaleNoteNumbers[1], wholeNoteDuration); // Four metronome ticks before the transcription part plays. ISampleProvider[] ticks = new ISampleProvider[4]; string tickFile = HostingEnvironment.MapPath($"~/Samples/Woodblock.wav"); for (int i = 0; i < ticks.Length; i++) { ticks[i] = NAudioHelper.GetSampleProviderFromFile(tickFile, quarterNoteDuration); } List <string> measureRhythms = GetNoteRhythms(); int randomInt = NoteHelper.GetRandomInt(0, measureRhythms.Count); string measureRhythm1 = measureRhythms[randomInt]; randomInt = NoteHelper.GetRandomInt(0, measureRhythms.Count); string measureRhythm2 = measureRhythms[randomInt]; if (numberOfMeasures == 2) { while ((measureRhythm1.Split(',').Count() + measureRhythm2.Split(',').Count()) % 2 == 1) // Ensure an even number of notes, so there's always a (reverse) resolution. { randomInt = NoteHelper.GetRandomInt(0, measureRhythms.Count); measureRhythm2 = measureRhythms[randomInt]; } } randomInt = NoteHelper.GetRandomInt(0, measureRhythms.Count); string measureRhythm3 = measureRhythms[randomInt]; randomInt = NoteHelper.GetRandomInt(0, measureRhythms.Count); string measureRhythm4 = measureRhythms[randomInt]; if (numberOfMeasures == 4) { while ((measureRhythm1.Split(',').Count() + measureRhythm2.Split(',').Count() + measureRhythm3.Split(',').Count() + measureRhythm4.Split(',').Count()) % 2 == 1) { randomInt = NoteHelper.GetRandomInt(0, measureRhythms.Count); measureRhythm4 = measureRhythms[randomInt]; } } string[] measureRhythmSplit1 = measureRhythm1.Split(','); int numberOfNotes1 = measureRhythmSplit1.Length; string[] measureRhythmSplit2 = measureRhythm2.Split(','); int numberOfNotes2 = measureRhythmSplit2.Length; string[] measureRhythmSplit3 = measureRhythm3.Split(','); int numberOfNotes3 = measureRhythmSplit3.Length; string[] measureRhythmSplit4 = measureRhythm4.Split(','); int numberOfNotes4 = measureRhythmSplit4.Length; ISampleProvider[] notes1 = new ISampleProvider[numberOfNotes1]; ISampleProvider[] notes2 = new ISampleProvider[numberOfNotes2]; ISampleProvider[] notes3 = new ISampleProvider[numberOfNotes3]; ISampleProvider[] notes4 = new ISampleProvider[numberOfNotes4]; Queue <int> noteNumberQueue; switch (resolutionType) { case 1: noteNumberQueue = GetResolutionIntQueue(scaleNoteNumbers, 16, 1); // 16 notes max. break; case 2: noteNumberQueue = GetResolutionIntQueue(scaleNoteNumbers, 16, 2); break; case 3: noteNumberQueue = GetResolutionIntQueue(scaleNoteNumbers, 16, 3); break; default: throw new NotSupportedException($"ResolutionType '{resolutionType}' is not supported."); } int[] measureNoteNumbers1 = NoteHelper.PopulateNoteNumbersFromQueue(numberOfNotes1, noteNumberQueue); int[] measureNoteNumbers2 = NoteHelper.PopulateNoteNumbersFromQueue(numberOfNotes2, noteNumberQueue); int[] measureNoteNumbers3 = NoteHelper.PopulateNoteNumbersFromQueue(numberOfNotes3, noteNumberQueue); int[] measureNoteNumbers4 = NoteHelper.PopulateNoteNumbersFromQueue(numberOfNotes4, noteNumberQueue); NoteHelper.CreateSamplesFromRhythmsAndNoteNames(new TimeSpan(), quarterNoteDuration, halfNoteDuration, dottedHalfNoteDuration, wholeNoteDuration, measureRhythmSplit1, notes1, measureNoteNumbers1); NoteHelper.CreateSamplesFromRhythmsAndNoteNames(new TimeSpan(), quarterNoteDuration, halfNoteDuration, dottedHalfNoteDuration, wholeNoteDuration, measureRhythmSplit2, notes2, measureNoteNumbers2); NoteHelper.CreateSamplesFromRhythmsAndNoteNames(new TimeSpan(), quarterNoteDuration, halfNoteDuration, dottedHalfNoteDuration, wholeNoteDuration, measureRhythmSplit3, notes3, measureNoteNumbers3); NoteHelper.CreateSamplesFromRhythmsAndNoteNames(new TimeSpan(), quarterNoteDuration, halfNoteDuration, dottedHalfNoteDuration, wholeNoteDuration, measureRhythmSplit4, notes4, measureNoteNumbers4); ISampleProvider phrase = wholeDoNote; foreach (var tick in ticks) { phrase = phrase.FollowedBy(tick); } foreach (var note1 in notes1) { phrase = phrase.FollowedBy(note1); } foreach (var note2 in notes2) { phrase = phrase.FollowedBy(note2); } if (numberOfMeasures == 4) { foreach (var note3 in notes3) { phrase = phrase.FollowedBy(note3); } foreach (var note4 in notes4) { phrase = phrase.FollowedBy(note4); } } // HACK: Use an empty note because without it, the audio gets cut short. ISampleProvider emptyNote = NAudioHelper.GetSampleProvider(0, 0, SignalGeneratorType.White, halfNoteDuration); phrase = phrase.FollowedBy(emptyNote); SampleToWaveProvider stwp = new SampleToWaveProvider(phrase); MixingSampleProvider msp = new MixingSampleProvider(stwp.WaveFormat); msp.AddMixerInput(stwp); int totalTicks = 8 + (4 * numberOfMeasures); ISampleProvider[] metronomeTicks = new ISampleProvider[totalTicks]; // The first two measures have zero gain, as this is the initial DO whole note and metronome ticks. for (int i = 0; i < 8; i++) { metronomeTicks[i] = NAudioHelper.GetSampleProvider(0, 0, SignalGeneratorType.White, quarterNoteDuration); } for (int i = 8; i < totalTicks; i++) { metronomeTicks[i] = NAudioHelper.GetSampleProviderFromFile(tickFile, quarterNoteDuration); } ISampleProvider metronomePhrase = metronomeTicks[0]; for (int i = 0; i < metronomeTicks.Length; i++) { metronomePhrase = metronomePhrase.FollowedBy(metronomeTicks[i]); } msp.AddMixerInput(metronomePhrase); IWaveProvider wp = msp.ToWaveProvider(); MemoryStream wavStream = new MemoryStream(); //WaveFileWriter.WriteWavFileToStream(wavStream, stwp); WaveFileWriter.WriteWavFileToStream(wavStream, wp); wavStream.Position = 0; wavStream.WavToMp3File(out string fileName); dict.Add("src", fileName); #endregion Audio #region Notation string[] noteNames1 = new string[numberOfNotes1]; NoteHelper.AdjustNoteNamesForKey(keySignature, measureNoteNumbers1, noteNames1); string[] noteNames2 = new string[numberOfNotes2]; NoteHelper.AdjustNoteNamesForKey(keySignature, measureNoteNumbers2, noteNames2); string[] noteNames3 = new string[numberOfNotes3]; NoteHelper.AdjustNoteNamesForKey(keySignature, measureNoteNumbers3, noteNames3); string[] noteNames4 = new string[numberOfNotes4]; NoteHelper.AdjustNoteNamesForKey(keySignature, measureNoteNumbers4, noteNames4); string script1 = NoteHelper.GetEasyScoreScript("transcription1", noteNames1, measureRhythmSplit1, keySignature, true); dict.Add("theScript1", script1); string script2 = NoteHelper.GetEasyScoreScript("transcription2", noteNames2, measureRhythmSplit2, keySignature, false); dict.Add("theScript2", script2); if (numberOfMeasures == 4) { string script3 = NoteHelper.GetEasyScoreScript("transcription3", noteNames3, measureRhythmSplit3, keySignature, false); dict.Add("theScript3", script3); string script4 = NoteHelper.GetEasyScoreScript("transcription4", noteNames4, measureRhythmSplit4, keySignature, false); dict.Add("theScript4", script4); } #endregion Notation var json = Json(dict, JsonRequestBehavior.AllowGet); return(json); }