public Project Load(string filename, int songIndex, int duration, int patternLength, int startFrame, bool removeIntroSilence) { nsf = NsfOpen(filename); if (nsf == null) { return(null); } var palSource = (NsfIsPal(nsf) & 1) == 1; var numFrames = duration * (palSource ? 50 : 60); project = new Project(); project.Name = Marshal.PtrToStringAnsi(NsfGetTitle(nsf)); project.Author = Marshal.PtrToStringAnsi(NsfGetArtist(nsf)); project.Copyright = Marshal.PtrToStringAnsi(NsfGetCopyright(nsf)); project.PalMode = palSource; switch (NsfGetExpansion(nsf)) { case EXTSOUND_VRC6: project.SetExpansionAudio(Project.ExpansionVrc6); break; case EXTSOUND_VRC7: project.SetExpansionAudio(Project.ExpansionVrc7); break; case EXTSOUND_FDS: project.SetExpansionAudio(Project.ExpansionFds); break; case EXTSOUND_MMC5: project.SetExpansionAudio(Project.ExpansionMmc5); break; case EXTSOUND_N163: project.SetExpansionAudio(Project.ExpansionN163, GetNumNamcoChannels(filename, songIndex, numFrames)); break; case EXTSOUND_S5B: project.SetExpansionAudio(Project.ExpansionS5B); break; case 0: break; default: NsfClose(nsf); // Unsupported expansion combination. return(null); } var songName = Marshal.PtrToStringAnsi(NsfGetTrackName(nsf, songIndex)); song = project.CreateSong(string.IsNullOrEmpty(songName) ? $"Song {songIndex + 1}" : songName); channelStates = new ChannelState[song.Channels.Length]; NsfSetTrack(nsf, songIndex); song.ResizeNotes(1, false); song.SetDefaultPatternLength(patternLength); for (int i = 0; i < song.Channels.Length; i++) { channelStates[i] = new ChannelState(); } var foundFirstNote = !removeIntroSilence; var p = 0; var n = 0; var f = startFrame; for (int i = 0; i < numFrames; i++) { p = f / song.PatternLength; n = f % song.PatternLength; if (p >= Song.MaxLength - 1) { break; } var playCalled = 0; do { playCalled = NsfRunFrame(nsf); }while (playCalled == 0); for (int c = 0; c < song.Channels.Length; c++) { foundFirstNote |= UpdateChannel(p, n, song.Channels[c], channelStates[c]); } if (foundFirstNote) { f++; } else { // Reset everything until we find our first note. project.DeleteAllInstrument(); project.DeleteAllSamples(); for (int c = 0; c < song.Channels.Length; c++) { channelStates[c] = new ChannelState(); } } } song.SetLength(p + 1); NsfClose(nsf); var factors = Utils.GetFactors(song.PatternLength, Song.MaxNoteLength); if (factors.Length > 0 && factors[0] <= Song.MaxNoteLength) { song.ResizeNotes(factors[0], false); } else { song.ResizeNotes(1, false); } song.SetSensibleBarLength(); song.DeleteEmptyPatterns(); song.UpdatePatternStartNotes(); project.DeleteUnusedInstruments(); project.UpdateAllLastValidNotesAndVolume(); return(project); }