/// <summary> /// Read file. /// </summary> /// <param name="br">The reader.</param> public void Read(BinaryDataReader br) { var s = SoundArchiveReader.ReadSoundArchive(FilePath); Streams = s.Streams; WaveSoundDatas = s.WaveSoundDatas; Sequences = s.Sequences; SoundSets = s.SoundSets; Banks = s.Banks; WaveArchives = s.WaveArchives; Groups = s.Groups; Players = s.Players; Files = s.Files; MaxSequences = s.MaxSequences; MaxSequenceTracks = s.MaxSequenceTracks; MaxStreamSounds = s.MaxStreamSounds; MaxStreamTracks = s.MaxStreamTracks; MaxStreamChannels = s.MaxStreamChannels; MaxWaveSounds = s.MaxWaveSounds; MaxWaveTracks = s.MaxWaveTracks; StreamBufferTimes = s.StreamBufferTimes; Options = s.Options; WriteMode = s.WriteMode; Version = s.Version; CreateStrings = s.CreateStrings; }
/// <summary> /// Play a stream entry. /// </summary> /// <param name="a">Sound archive.</param> /// <param name="streamNumber">Stream number to play.</param> public static void PlayStream(SoundArchive a, int streamNumber) { //Try playing. Stop(); try { //Stream. CitraFileLoader.Stream s = (CitraFileLoader.Stream)SoundArchiveReader.ReadFile(File.ReadAllBytes(BasePath + "/" + a.Streams[streamNumber].File.ExternalFileName)); if (s.Stm.info.channels.Count > 2) { switch (s.Stm.info.streamSoundInfo.encoding) { case 0: s.Stm.data.pcm8 = new sbyte[][] { s.Stm.data.pcm8[0], s.Stm.data.pcm8[1] }; break; case 1: s.Stm.data.pcm16 = new short[][] { s.Stm.data.pcm16[0], s.Stm.data.pcm16[1] }; break; case 2: s.Stm.data.dspAdpcm = new byte[][] { s.Stm.data.dspAdpcm[0], s.Stm.data.dspAdpcm[1] }; break; } } for (int i = 2; i < s.Stm.info.channels.Count; i++) { s.Stm.info.channels.RemoveAt(i); } var m = new MemoryStream(s.Riff.ToBytes()); var n = new WaveFileReader(m); waveOut.Initialize(n); waveOut.Play(); CurrHash = "STM_" + streamNumber; Stopped = false; Paused = false; } catch { } }
public static SoundFile <ISoundFile> GetInfo(SoundArchive a, SoundArchive.NewFileEntryType type, int lastEntry, string filePath) { //File wizard. FileWizard w = new FileWizard(); w.type = type; //Add existing files. foreach (var f in a.Files) { w.existingFiles.Items.Add(f.FileName + "." + f.FileExtension); } //Prepare info. w.referenceFileExternally.Enabled = false; w.referenceFileExternally.Checked = type == SoundArchive.NewFileEntryType.Stream; w.blankFile.Enabled = type != SoundArchive.NewFileEntryType.Stream && type != SoundArchive.NewFileEntryType.Prefetch; w.useExistingFile.Checked = true; w.useExistingFile.Enabled = w.newFile.Checked = a.Files.Count == 0; w.useExistingFile.Enabled = !w.useExistingFile.Enabled; w.okButton.Enabled = false; //Stream specifics. if (type == SoundArchive.NewFileEntryType.Stream) { w.blankFile.Enabled = false; } //Show. w.ShowDialog(); //Return data. if (w.cancel) { return(new SoundFile <ISoundFile>() { FileId = -1 }); } else { //Get versions. byte maj = 1; byte min = 0; byte rev = 0; //Use existing file. if (w.useExistingFile.Checked) { return(new SoundFile <ISoundFile>() { Reference = a.Files[w.existingFiles.SelectedIndex] }); } //Use new file. else if (w.newFile.Checked) { if (w.referenceFileExternally.Checked) { return(new SoundFile <ISoundFile>() { Reference = a.AddNewFile(type, lastEntry, null, false, GetRelativePath(w.newFilePath.Text, Path.GetDirectoryName(filePath))) }); } else { return(new SoundFile <ISoundFile>() { Reference = a.AddNewFile(type, lastEntry, SoundArchiveReader.ReadFile(File.ReadAllBytes(w.newFilePath.Text))) }); } } //Blank file. else if (w.blankFile.Checked) { ISoundFile f = null; switch (type) { case SoundArchive.NewFileEntryType.Bank: foreach (var fi in a.Files) { if (fi != null) { if (fi.File != null) { var z = fi.File as SoundBank; if (z != null) { maj = z.Version.Major; min = z.Version.Minor; rev = z.Version.Revision; break; } } } } f = new SoundBank() { Version = new FileWriter.Version(maj, min, rev) }; break; case SoundArchive.NewFileEntryType.Group: foreach (var fi in a.Files) { if (fi != null) { if (fi.File != null) { var z = fi.File as Group; if (z != null) { maj = z.Version.Major; min = z.Version.Minor; rev = z.Version.Revision; break; } } } } f = new Group() { Version = new FileWriter.Version(maj, min, rev) }; break; case SoundArchive.NewFileEntryType.Sequence: foreach (var fi in a.Files) { if (fi != null) { if (fi.File != null) { var z = fi.File as SoundSequence; if (z != null) { maj = z.Version.Major; min = z.Version.Minor; rev = z.Version.Revision; break; } } } } f = new SoundSequence() { Version = new FileWriter.Version(maj, min, rev) }; break; case SoundArchive.NewFileEntryType.WaveArchive: foreach (var fi in a.Files) { if (fi != null) { if (fi.File != null) { var z = fi.File as SoundWaveArchive; if (z != null) { maj = z.Version.Major; min = z.Version.Minor; rev = z.Version.Revision; break; } } } } f = new SoundWaveArchive() { Version = new FileWriter.Version(maj, min, rev) }; break; case SoundArchive.NewFileEntryType.WaveSoundData: foreach (var fi in a.Files) { if (fi != null) { if (fi.File != null) { var z = fi.File as WaveSoundData; if (z != null) { maj = z.Version.Major; min = z.Version.Minor; rev = z.Version.Revision; break; } } } } f = new WaveSoundData() { Version = new FileWriter.Version(maj, min, rev) }; break; } return(new SoundFile <ISoundFile>() { Reference = a.AddNewFile(type, lastEntry, f) }); } //Null file. else { return(new SoundFile <ISoundFile>() { FileId = -2 }); } } }
/// <summary> /// Add a new sound file, and return it. /// </summary> /// <param name="type">New file entry type.</param> /// <param name="lastEntry">Last entry.</param> /// <param name="file">File to add.</param> /// <param name="keepReference">Whether or not to keep the reference to the ISoundFile provided.</param> /// <param name="externalPath">Use this if the file is a stream.</param> /// <returns>The new file.</returns> public SoundFile <ISoundFile> AddNewFile(NewFileEntryType type, int lastEntry, ISoundFile file, bool keepReference = false, string externalPath = null) { //Get proper file. ISoundFile f = file; if (f != null && !keepReference) { MemoryStream o = new MemoryStream(); BinaryDataWriter bw = new BinaryDataWriter(o); file.Write(WriteMode, bw); f = SoundArchiveReader.ReadFile(o.ToArray()); try { bw.Dispose(); } catch { } try { o.Dispose(); } catch { } } int index = 0; switch (type) { //Stream. case NewFileEntryType.Stream: while (lastEntry >= 0) { if (Streams[lastEntry].File == null) { lastEntry--; } else { index = Streams[lastEntry].File.FileId + 1; break; } } break; //Wave sound data. case NewFileEntryType.WaveSoundData: while (lastEntry >= 0) { if (WaveSoundDatas[lastEntry].File == null) { lastEntry--; } else { index = WaveSoundDatas[lastEntry].File.FileId + 1; break; } } break; //Sequence. case NewFileEntryType.Sequence: while (lastEntry >= 0) { if (Sequences[lastEntry].File == null) { lastEntry--; } else { index = Sequences[lastEntry].File.FileId + 1; break; } } break; //Bank. case NewFileEntryType.Bank: while (lastEntry >= 0) { if (Banks[lastEntry].File == null) { lastEntry--; } else { index = Banks[lastEntry].File.FileId + 1; break; } } break; //Wave archive. case NewFileEntryType.WaveArchive: while (lastEntry >= 0) { if (WaveArchives[lastEntry].File == null) { lastEntry--; } else { index = WaveArchives[lastEntry].File.FileId + 1; break; } } break; //Group. case NewFileEntryType.Group: while (lastEntry >= 0) { if (Groups[lastEntry].File == null) { lastEntry--; } else { index = Groups[lastEntry].File.FileId + 1; break; } } break; //Prefech. case NewFileEntryType.Prefetch: while (lastEntry >= 0) { if (Streams[lastEntry].PrefetchFile == null) { lastEntry--; } else { index = Streams[lastEntry].PrefetchFile.FileId + 1; break; } } break; } //Insert file at the proper index. var filef = new SoundFile <ISoundFile>() { ExternalFileName = externalPath, File = f, FileType = (externalPath == null ? EFileType.Internal : EFileType.External) }; if (externalPath != null) { filef.BackupExtension = "stm"; } Files.Insert(index, filef); //Recreate file Ids. RecreateFileIds(); //Programmed to fail if it messes up. return(Files[index]); }
/// <summary> /// Read a velocity region. /// </summary> /// <param name="br">The reader.</param> /// <returns>The velocity region.</returns> public VelocityRegion ReadVelocityInfo(BinaryDataReader br, FileReader FileReader) { //Start structure. FileReader.StartStructure(br); //New velocity region. VelocityRegion r = new VelocityRegion(); //First is the wave id index. r.WaveIndex = (int)br.ReadUInt32(); //Flags. FlagParameters f = new FlagParameters(ref br); //Original key. 0x000000KK. r.OriginalKey = (sbyte)(0xFF & SoundArchiveReader.GetFlagValue(f, 0, 60)); //Volume. 0x000000VV. r.Volume = (byte)(0xFF & SoundArchiveReader.GetFlagValue(f, 1, 127)); //Pan. 0x0000SSPP. S = Span, P = Pan. r.Pan = (sbyte)(0xFF & SoundArchiveReader.GetFlagValue(f, 2, 64)); r.SurroundPan = (sbyte)((0xFF00 & SoundArchiveReader.GetFlagValue(f, 2)) >> 8); //Pitch. r.Pitch = BitConverter.ToSingle(BitConverter.GetBytes(SoundArchiveReader.GetFlagValue(f, 3, 0x3F800000)), 0); //Note parameters. 0x00TTGGII. T = Interpolation Type, G = Key group, I = Ignore note off. uint noteParam = SoundArchiveReader.GetFlagValue(f, 4, 0); r.PercussionMode = (noteParam & 0xFF) > 0; r.KeyGroup = (byte)((noteParam & 0xFF00) >> 8); r.InterPolationType = (VelocityRegion.EInterPolationType)((noteParam & 0xFF0000) >> 16); //ADSHR curve offset. if (f.isFlagEnabled[9]) { //ADSHR not null. if (f.flagValues[9] != 0xFFFFFFFF) { //Jump to offset. FileReader.JumpToOffsetManually(br, (int)f.flagValues[9]); //Start structure. FileReader.StartStructure(br); //ADSHR curve reference is here. FileReader.OpenReference(br, "ADSHR"); //Not null reference. if (!FileReader.ReferenceIsNull("ADSHR")) { //Jump to position. FileReader.JumpToReference(br, "ADSHR"); //Read ADSHR curve. r.Attack = br.ReadByte(); r.Decay = br.ReadByte(); r.Sustain = br.ReadByte(); r.Hold = br.ReadByte(); r.Release = br.ReadByte(); } //End structure. FileReader.EndStructure(); //Close reference. FileReader.CloseReference("ADSHR"); } } //End structure. FileReader.EndStructure(); //Return the velocity region. return(r); }
/// <summary> /// Read a group file. /// </summary> /// <param name="br">The reader.</param> /// <param name="files">List of sound files to make a reference to.</param> public void Read(BinaryDataReader br, List <SoundFile <ISoundFile> > files) { //Open file. FileReader FileReader = new FileReader(); FileReader.OpenFile(br, out writeMode, out Version); //Open info block. FileReader.OpenBlock(br, 0); //Load reference table. FileReader.OpenReferenceTable(br, "FileRefs"); //Load each reference. SoundFiles = new List <SoundFile <ISoundFile> >(); List <SizedReference> sizedReferences = new List <SizedReference>(); for (int i = 0; i < FileReader.ReferenceTableCount("FileRefs"); i++) { //Null reference. if (FileReader.ReferenceTableReferenceIsNull(i, "FileRefs")) { SoundFiles.Add(null); sizedReferences.Add(null); } //Valid reference. else { //Jump to reference. FileReader.ReferenceTableJumpToReference(br, i, "FileRefs"); //Get file id. UInt32 fileId = br.ReadUInt32(); //Add the sized reference. sizedReferences.Add(new SizedReference(ref br)); //If the file references exist. if (files != null) { //If file id is found in the files. if (files.Where(x => x.FileId == (int)fileId).Count() > 0) { //Add sound file. SoundFiles.Add(new SoundFile <ISoundFile>()); files.Where(x => x.FileId == (int)fileId).ToList()[0].ReferencedBy.Add(SoundFiles[SoundFiles.Count - 1]); SoundFiles[SoundFiles.Count - 1].Reference = files.Where(x => x.FileId == (int)fileId).ToList()[0]; } //Independent mode. else { //Add sound file. SoundFiles.Add(new SoundFile <ISoundFile>() { FileId = (int)fileId }); } } //Independent mode. else { //Add sound file. SoundFiles.Add(new SoundFile <ISoundFile>() { FileId = (int)fileId }); } } } //Close table. FileReader.CloseReferenceTable("FileRefs"); //Close info block. FileReader.CloseBlock(br); //Open file block. FileReader.OpenBlock(br, 1); //Read the files. for (int i = 0; i < SoundFiles.Count; i++) { //File exist in first place. if (SoundFiles[i] != null) { //Sound file reference is null, so no embed. if (sizedReferences[i].offset == Reference.NULL_PTR) { SoundFiles[i].Embed = false; } //Sound file reference exist, embed and read it. else { //Embed file. SoundFiles[i].Embed = true; //Jump to file. FileReader.JumpToOffsetManually(br, sizedReferences[i].offset); //Read file. SoundFiles[i].File = SoundArchiveReader.ReadFile(br.ReadBytes((int)sizedReferences[i].size)); } } } //Close file block. FileReader.CloseBlock(br); //New extra info. ExtraInfo = new List <InfoExEntry>(); //Only open EX block if version is bigger than one. if (Version > new FileWriter.Version(1, 0, 0)) { //Open extended info block. FileReader.OpenBlock(br, 2); //Open the table. FileReader.OpenReferenceTable(br, "Ex"); //Reach each extra info entry. for (int i = 0; i < FileReader.ReferenceTableCount("Ex"); i++) { //Entry is null. if (FileReader.ReferenceTableReferenceIsNull(i, "Ex")) { ExtraInfo.Add(null); } //Entry exist. else { //Read data. Id id = new Id(ref br); UInt32 flags = br.ReadUInt32(); //New entry. InfoExEntry e = new InfoExEntry(); e.ItemIndex = (int)id.index; //Type. switch (id.type) { //Sound. case SoundTypes.Sound: e.ItemType = InfoExEntry.EItemType.Sound; break; //Seq sound set or wave data. case SoundTypes.SoundGroup: e.ItemType = InfoExEntry.EItemType.SequenceSetOrWaveData; break; //Bank. case SoundTypes.Bank: e.ItemType = InfoExEntry.EItemType.Bank; break; //Wave archive. case SoundTypes.WaveArchive: e.ItemType = InfoExEntry.EItemType.WaveArchive; break; } //Find flags. bool seq = (flags & 0b1) > 0; bool wsd = (flags & 0b10) > 0; bool bnk = (flags & 0b100) > 0; bool war = (flags & 0b1000) > 0; //Test for flags. if (flags == 0xFFFFFFFF) { e.LoadFlags = InfoExEntry.ELoadFlags.All; } else if (seq && bnk) { e.LoadFlags = InfoExEntry.ELoadFlags.SeqAndBank; } else if (seq && war) { e.LoadFlags = InfoExEntry.ELoadFlags.SeqAndWarc; } else if (bnk && war) { e.LoadFlags = InfoExEntry.ELoadFlags.BankAndWarc; } else if (seq) { e.LoadFlags = InfoExEntry.ELoadFlags.Seq; } else if (bnk) { e.LoadFlags = InfoExEntry.ELoadFlags.Bank; } else if (wsd) { e.LoadFlags = InfoExEntry.ELoadFlags.Wsd; } else if (war) { e.LoadFlags = InfoExEntry.ELoadFlags.Warc; } //Add entry. ExtraInfo.Add(e); } } //Close the table. FileReader.CloseReferenceTable("Ex"); //Close extended info block. FileReader.CloseBlock(br); } //Close file. FileReader.CloseFile(br); }
/// <summary> /// Read the file. ID War. U32 Index /// </summary> /// <param name="br">The reader.</param> public void Read(BinaryDataReader br) { //Open the file. FileReader FileReader = new FileReader(); FileReader.OpenFile(br, out writeMode, out Version); //Open the info block. FileReader.OpenBlock(br, 0); //Wave id table reference. FileReader.OpenReference(br, "WaveIdTableRef"); //Wave sound data reference table reference. FileReader.OpenReference(br, "WaveSoundDataRefTableRef"); //If table is null. if (FileReader.ReferenceIsNull("WaveIdTableRef")) { Waves = null; } //Go to table. else { //New wave list. Waves = new List <WaveArchivePair>(); //Jump to table. FileReader.JumpToReference(br, "WaveIdTableRef"); //Table is here. UInt32 count = br.ReadUInt32(); for (int i = 0; i < count; i++) { //New id. Id war = new Id(ref br); //Add entry. Waves.Add(new WaveArchivePair((int)war.index, (int)br.ReadUInt32())); } } //Close wave id table reference. FileReader.CloseReference("WaveIdTableRef"); //If reference table is null. if (FileReader.ReferenceIsNull("WaveSoundDataRefTableRef")) { DataItems = null; } //Read reference table. else { //New sound data list. DataItems = new List <WaveSoundDataItem>(); //Jump to the reference table. FileReader.JumpToReference(br, "WaveSoundDataRefTableRef"); //This is a structure. FileReader.StartStructure(br); //Open reference table. FileReader.OpenReferenceTable(br, "WaveSoundDataRefTable"); //Read each entry. for (int i = 0; i < FileReader.ReferenceTableCount("WaveSoundDataRefTable"); i++) { //Reference is null. if (FileReader.ReferenceTableReferenceIsNull(i, "WaveSoundDataRefTable")) { DataItems.Add(null); } //Valid item. else { //Jump to position. FileReader.ReferenceTableJumpToReference(br, i, "WaveSoundDataRefTable"); //Start structure. FileReader.StartStructure(br); //New data. WaveSoundDataItem d = new WaveSoundDataItem(); //Wave sound info reference. FileReader.OpenReference(br, "WaveSoundInfoRef"); //Track info reference table reference. FileReader.OpenReference(br, "TrackInfoRefTableRef"); //Note info reference table reference. FileReader.OpenReference(br, "NoteInfoRefTableRef"); //Wave sound info. if (!FileReader.ReferenceIsNull("WaveSoundInfoRef")) { //Jump to the structure. FileReader.JumpToReference(br, "WaveSoundInfoRef"); //Start structure. FileReader.StartStructure(br); //They are just flags. FlagParameters f = new FlagParameters(ref br); //Flag list: /* * 0 - Pan info. 0x0000SSPP S-Span P-Pan. * 1 - Pitch, float. * 2 - Biquad and LPF info. 0x00VVTTLL L-LPF T-Biquad Type V-Biquad Value. * 8 - Offset to send value. * 9 - Offset to ADSHR curve offset. */ //Pan info. d.Pan = (sbyte)(SoundArchiveReader.GetFlagValue(f, 0, (uint)d.Pan) & 0xFF); d.SurroundPan = (sbyte)(SoundArchiveReader.GetFlagValue(f, 0, (uint)d.SurroundPan & 0xFF00) >> 8); //Pitch. if (f.isFlagEnabled[1]) { d.Pitch = BitConverter.ToSingle(BitConverter.GetBytes(SoundArchiveReader.GetFlagValue(f, 1)), 0); } //LPF. d.LpfFrequency = (sbyte)SoundArchiveReader.GetFlagValue(f, 2, (uint)d.LpfFrequency); //Biquad type. d.BiquadType = (WaveSoundDataItem.EBiquadType)((SoundArchiveReader.GetFlagValue(f, 2, 0) & 0xFF00) >> 8); //Biquad value. d.BiquadValue = (sbyte)((SoundArchiveReader.GetFlagValue(f, 2, 0) & 0xFF0000) >> 16); //Offset to send value. uint sendValueOff = SoundArchiveReader.GetFlagValue(f, 8, 0xFFFFFFFF); if (sendValueOff != 0xFFFFFFFF) { //Send value. All bytes: (Main, Count (3), AuxA, AuxB, AuxC), followed by padding to 8 bytes. FileReader.JumpToOffsetManually(br, (int)sendValueOff); d.SendValue[0] = br.ReadByte(); int sendCount = br.ReadByte(); for (int j = 0; j < 3 && j < sendCount; j++) { d.SendValue[j + 1] = br.ReadByte(); } } //Offset to ADSHR curve. uint adshrOff = SoundArchiveReader.GetFlagValue(f, 9, 0xFFFFFFFF); if (adshrOff != 0xFFFFFFFF) { //Go to the reference. FileReader.JumpToOffsetManually(br, (int)adshrOff); //Start structure. FileReader.StartStructure(br); //Open the reference. FileReader.OpenReference(br, "AdshrRef"); //Jump to reference if not null. if (!FileReader.ReferenceIsNull("AdshrRef")) { //Jump. FileReader.JumpToReference(br, "AdshrRef"); //ADSHR curve. d.Attack = br.ReadByte(); d.Decay = br.ReadByte(); d.Sustain = br.ReadByte(); d.Hold = br.ReadByte(); d.Release = br.ReadByte(); } //Close the reference. FileReader.CloseReference("AdshrRef"); //End structure. FileReader.EndStructure(); } //Reference to ADSHR curve. //Read ADSHR curve. //End structure. FileReader.EndStructure(); } //Close wave sound info reference. FileReader.CloseReference("WaveSoundInfoRef"); //Go to the reference table for tracks. if (!FileReader.ReferenceIsNull("TrackInfoRefTableRef")) { //New list. d.NoteEvents = new List <List <NoteEvent> >(); //Go to offset. FileReader.JumpToReference(br, "TrackInfoRefTableRef"); //Start track info. FileReader.StartStructure(br); //Read the reference table. FileReader.OpenReferenceTable(br, "TrackInfoRefTable"); //Read each track. for (int j = 0; j < FileReader.ReferenceTableCount("TrackInfoRefTable"); j++) { //New null track. List <NoteEvent> track = null; //Reference is not null. if (!FileReader.ReferenceTableReferenceIsNull(j, "TrackInfoRefTable")) { //Jump to track info. FileReader.ReferenceTableJumpToReference(br, j, "TrackInfoRefTable"); //Start structure. FileReader.StartStructure(br); //Note event table reference. FileReader.OpenReference(br, "NoteEventRefTableRef"); //Reference is not null. if (!FileReader.ReferenceIsNull("NoteEventRefTableRef")) { //Make track valid. track = new List <NoteEvent>(); //Jump to the table. FileReader.JumpToReference(br, "NoteEventRefTableRef"); //Start structure. FileReader.StartStructure(br); //Read the reference table. FileReader.OpenReferenceTable(br, "NoteEventRefTable"); //Read each note event. for (int k = 0; k < FileReader.ReferenceTableCount("NoteEventRefTable"); k++) { //Null data. if (FileReader.ReferenceTableReferenceIsNull(j, "NoteEventRefTable")) { track.Add(null); } //Valid note event. else { //Jump to note event. FileReader.ReferenceTableJumpToReference(br, k, "NoteEventRefTable"); //Read note event. NoteEvent e = new NoteEvent(); e.Position = br.ReadSingle(); e.Length = br.ReadSingle(); e.NoteIndex = (int)br.ReadUInt32(); br.ReadUInt32(); //Add note event. track.Add(e); } } //Close the reference table. FileReader.CloseReferenceTable("NoteEventRefTable"); //End structure. FileReader.EndStructure(); } //Close note event table reference. FileReader.CloseReference("NoteEventRefTableRef"); //Ends structure. FileReader.EndStructure(); } //Add track. d.NoteEvents.Add(track); } //Close the reference table. FileReader.CloseReferenceTable("TrackInfoRefTable"); //End track info. FileReader.EndStructure(); } //Null track info. else { d.NoteEvents = null; } //Close track info reference table reference. FileReader.CloseReference("TrackInfoRefTableRef"); //Close note info reference. FileReader.CloseReference("NoteEventRefTableRef"); //Go to the reference table for notes. if (!FileReader.ReferenceIsNull("NoteInfoRefTableRef")) { //New list of notes. d.Notes = new List <NoteInfo>(); //Go to offset. FileReader.JumpToReference(br, "NoteInfoRefTableRef"); //Start note reference table info. FileReader.StartStructure(br); //Open the reference table. FileReader.OpenReferenceTable(br, "NoteInfoRefTable"); //Read each note info. for (int j = 0; j < FileReader.ReferenceTableCount("NoteInfoRefTable"); j++) { //If null info. if (FileReader.ReferenceTableReferenceIsNull(j, "NoteInfoRefTable")) { d.Notes.Add(null); } //Valid note info. else { //Jump to note info. FileReader.ReferenceTableJumpToReference(br, j, "NoteInfoRefTable"); //Read data. d.Notes.Add(ReadNoteInfo(br)); } } //Close the reference table. FileReader.CloseReferenceTable("NoteInfoRefTable"); //End track info. FileReader.EndStructure(); } //Null note info. else { d.Notes = null; } //Close note info reference. FileReader.CloseReference("NoteInfoRefTableRef"); //End structure. FileReader.EndStructure(); //Add data. DataItems.Add(d); } } //Close reference table. FileReader.CloseReferenceTable("WaveSoundDataRefTable"); //End structure. FileReader.EndStructure(); } //Close wave sound data reference table reference. FileReader.CloseReference("WaveSoundDataRefTableRef"); //Close the info block. FileReader.CloseBlock(br); //Close the file. FileReader.CloseFile(br); }