Ejemplo n.º 1
0
        public async Task <ActionResult> Create(SongViewModel songViewModel)
        {
            // if model is invalid return back the view again
            if (!ModelState.IsValid)
            {
                return(View(songViewModel));
            }

            // get current timestamp
            DateTime timestamp = DateTime.Now;

            // Create a new song instance based on the form data from the view model
            Song song = new Song
            {
                Created          = timestamp,
                Modified         = timestamp,
                Title            = songViewModel.Title,
                Artist           = songViewModel.Artist,
                MidiFileName     = songViewModel.MidiFileHandler.FileName,
                ChordsFileName   = songViewModel.ChordsFileHandler.FileName,
                MelodyTrackIndex = songViewModel.MelodyTrackIndex,
                IsPublic         = songViewModel.IsPublic && User.IsInRole(RoleName.Admin),
                UserId           = this.User.Identity.GetUserId(),
            };

            // set name for the playback file to be created based on the midi file
            song.SetPlaybackName();

            // save the new song in the database
            _databaseGateway.Songs.Add(song);
            await _databaseGateway.CommitChangesAsync();

            // save the files of the new song on the file server
            IMidiFile playbackFile = null;

            try
            {
                // create a new directory for the new song
                string directoryPath = await GetSongPath(song.Id);

                Directory.CreateDirectory(directoryPath);

                // save the midi file in the new directory
                string midiFileFullPath = directoryPath + song.MidiFileName;
                songViewModel.MidiFileHandler.SaveAs(midiFileFullPath);

                // save the midi playback file in the new directory
                string midiPlaybackFullPath = directoryPath + song.MidiPlaybackFileName;
                playbackFile = CompositionContext.CreateMidiPlayback(songViewModel.MidiFileHandler.InputStream, song.MelodyTrackIndex);
                playbackFile.SaveFile(outputPath: midiPlaybackFullPath, pathIncludesFileName: true);

                // save the chord progression file in the new directory
                string chordsFilefullPath = directoryPath + song.ChordsFileName;
                songViewModel.ChordsFileHandler.SaveAs(chordsFilefullPath);
            }
            catch (Exception ex)
            {
                // in case of failure, rollback DB changes and log error message
                _databaseGateway.Songs.Remove(song);
                await _databaseGateway.CommitChangesAsync();

                HomeController.WriteErrorToLog(HttpContext, ex.Message);
            }
            finally
            {
                // release open unmanaged resources
                songViewModel.ChordsFileHandler?.InputStream?.Dispose();
                songViewModel.MidiFileHandler?.InputStream?.Dispose();
                playbackFile?.Stream?.Dispose();
            }

            // If creation was successful, redirect to new song details page
            string successMessage = $"The Song '{song.Title}' by '{song.Artist}' was successfully uploaded.";

            return(RedirectToAction(nameof(Details), new { Id = song.Id, message = successMessage }));
        }
Ejemplo n.º 2
0
        public async Task <ActionResult> Compose(CompositionViewModel model)
        {
            // validate that sum of weights is equal to 100
            double weightSum = model.WeightSum;

            if (weightSum != 100)
            {
                string errorMessage =
                    $"The total weights of all fitness function " +
                    $"evaluators must sum up to 100.\n" +
                    $"The current sum is {weightSum}";
                this.ModelState.AddModelError(nameof(model.AccentedBeats), errorMessage);
            }

            // assure all other validations passed okay
            if (!ModelState.IsValid)
            {
                CompositionViewModel viewModel = new CompositionViewModel
                {
                    SongSelectList  = new SelectList(_databaseGateway.Songs.GetAll().OrderBy(s => s.Title), nameof(Song.Id), nameof(Song.Title)),
                    PitchSelectList = new SelectList(_pitchSelectList, nameof(PitchRecord.Pitch), nameof(PitchRecord.Description)),
                };
                return(View(viewModel));
            }

            // fetch song from datasource
            Song song = _databaseGateway.Songs.Get(model.SongId);

            // get the chord and file paths on the file server
            string chordFilePath = await SongsController.GetSongPath(song.Id, _databaseGateway, User, SongFileType.ChordProgressionFile);

            string midiFilePath = await SongsController.GetSongPath(song.Id, _databaseGateway, User, SongFileType.MidiOriginalFile);

            // create a compositon instance
            CompositionContext composition = new CompositionContext(
                chordProgressionFilePath: chordFilePath,
                midiFilePath: midiFilePath,
                melodyTrackIndex: song.MelodyTrackIndex);

            // build evaluators weights
            MelodyEvaluatorsWeights weights = new MelodyEvaluatorsWeights
            {
                AccentedBeats    = model.AccentedBeats,
                ContourDirection = model.ContourDirection,
                ContourStability = model.ContourStability,
                DensityBalance   = model.DensityBalance,
                ExtremeIntervals = model.ExtremeIntervals,
                PitchRange       = model.PitchRange,
                PitchVariety     = model.PitchVariety,
                SmoothMovement   = model.SmoothMovement,
                Syncopation      = model.Syncopation
            };

            // Compose some melodies and fetch the best one
            IMidiFile midiFile = composition.Compose(
                strategy: CompositionStrategy.GeneticAlgorithmStrategy,
                overallNoteDurationFeel: model.OverallNoteDurationFeel,
                musicalInstrument: model.MusicalInstrument,
                minPitch: model.MinPitch,
                maxPitch: model.MaxPitch,
                useExistingMelodyAsSeed: model.useExistingMelodyAsSeed,
                customParams: weights)
                                 .FirstOrDefault();

            // save the midifile output internally
            _midiFile        = midiFile;
            ViewBag.MidiFile = midiFile;

            // save file on the file server
            string directoryPath = HomeController.GetFileServerPath() + "Outputs" +
                                   Path.DirectorySeparatorChar + song.Id + Path.DirectorySeparatorChar;

            Directory.CreateDirectory(directoryPath);
            string filePath = _midiFile.SaveFile(outputPath: directoryPath);

            // return the file to the client client for downloading
            string fileName = Path.GetFileName(filePath);

            byte[] fileBytes = System.IO.File.ReadAllBytes(filePath);
            return(File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName));
        }