From 553ff99664bdb0daeb6f283254f11303c4182be9 Mon Sep 17 00:00:00 2001 From: TheBoxyBear <15822255+TheBoxyBear@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:51:25 -0500 Subject: [PATCH] Add api links to articles --- ChartTools/Song.cs | 4 +-- Docs/Program.cs | 2 +- Docs/articles/dynamic-syntax.md | 16 +++++------ Docs/articles/events.md | 10 +++---- Docs/articles/getting-started.md | 33 +++++++++++------------ Docs/articles/improving-performance.md | 37 ++++++++++++++------------ Docs/articles/lyrics.md | 23 ++++++---------- Docs/articles/tools.md | 16 +++++------ Docs/index.md | 10 +++++++ 9 files changed, 77 insertions(+), 74 deletions(-) diff --git a/ChartTools/Song.cs b/ChartTools/Song.cs index 5ce2a6cb..b1d66c1c 100644 --- a/ChartTools/Song.cs +++ b/ChartTools/Song.cs @@ -109,8 +109,8 @@ public static async Task FromDirectoryAsync(string directory, ReadingConfi /// /// /// - public void ToFile(string path, ChartWritingConfiguration? config = default) => ExtensionHandler.Write(path, this, (".chart", (path, song) => ChartFile.WriteSong(path, song, config))); - public async Task ToFileAsync(string path, ChartWritingConfiguration? config = default, CancellationToken cancellationToken = default) => await ExtensionHandler.WriteAsync(path, this, (".chart", (path, song) => ChartFile.WriteSongAsync(path, song, config, cancellationToken))); + public void ToFile(string path, WritingConfiguration? config = default) => ExtensionHandler.Write(path, this, (".chart", (path, song) => ChartFile.WriteSong(path, song, config?.Chart))); + public async Task ToFileAsync(string path, WritingConfiguration? config = default, CancellationToken cancellationToken = default) => await ExtensionHandler.WriteAsync(path, this, (".chart", (path, song) => ChartFile.WriteSongAsync(path, song, config?.Chart, cancellationToken))); /// /// Retrieves the lyrics from the global events. diff --git a/Docs/Program.cs b/Docs/Program.cs index 99e341fa..2c377df5 100644 --- a/Docs/Program.cs +++ b/Docs/Program.cs @@ -9,7 +9,7 @@ Console.WriteLine("------- Building site with DocFx -------"); // TODO Only build api if the assembly is more recent than the last site build -await DotnetApiCatalog.GenerateManagedReferenceYamlFiles(config); +//await DotnetApiCatalog.GenerateManagedReferenceYamlFiles(config); await Docset.Build(config); diff --git a/Docs/articles/dynamic-syntax.md b/Docs/articles/dynamic-syntax.md index 56c8ff93..87850d4a 100644 --- a/Docs/articles/dynamic-syntax.md +++ b/Docs/articles/dynamic-syntax.md @@ -14,23 +14,23 @@ Track easyBass = bass.GetTrack(Difficulty.Easy); The dynamic syntax uses three enums to get instruments: -- `StandardInstrumentIdentity` - Instruments using standard chords -- `GHLInstrumentIdentity` - Instruments using Guitar Hero Live chords -- `InstrumentIdentity` - All instruments including drums and vocals +- [StandardInstrumentIdentity](~/api/ChartTools.StandardInstrumentIdentity.yml) - Instruments using standard chords +- [GHLInstrumentIdentity](~/api/ChartTools.GHLInstrumentIdentity.yml) - Instruments using Guitar Hero Live chords +- [InstrumentIdentity](~/api/ChartTools.InstrumentIdentity.yml) - All instruments including drums and vocals Drums and vocals do not have an enum for their chord types as they are the only instrument using their respective chords. ## Generic vs. non-generic -When an instrument is obtained dynamically using the `InstrumentIdentity` enum, the returned object is of type `Instrument`. When a track is obtained from a non-generic instrument, either dynamically or explicitly through a property, the track will be of type `Track`. This concept extends to chords and notes. +When an instrument is obtained dynamically using the [InstrumentIdentity](~/api/ChartTools.InstrumentIdentity.yml) enum, the returned object is of type [Instrument](~/api/ChartTools.Instrument.yml). When a track is obtained from a non-generic instrument, either dynamically or explicitly through a property, the track will be of type [Track](~/api/ChartTools.Track.yml). This concept extends to chords and notes. When working with a non-generic track, the following rules apply: - Chords cannot be added or removed. The position of existing chords can be modified. - Local events and special phrases have no restrictions. -- A note's identity can be obtaines through the read-only `NoteIndex` property. In a future version, notes will be able to be added from a non-generic track. +- A note's identity can be obtained through the read-only [Index](~/api/ChartTools.INote.yml#ChartTools_INote_Index) property. Being the base types of the generic counterparts, non-generic instruments, tracks, chords and notes can be cast to a generic version. -The dynamic syntax can also be used to set amd read instruments and tracks. +The dynamic syntax can also be used to set and read instruments and tracks. ```C# // Setting components @@ -47,6 +47,6 @@ Track easyCoop = Track.FromFile(path, StandardInstrumentIdentity. Track easyKeys = Track.FromFile(path, InsturmentIdentity.Keys, Difficulty.Easy, , metadata.Formatting); ``` -When setting an instrument, the target is determined by the `InstrumentIdentity` property of the new instrument, which can be overridden using a `with` statement. Similarly, the target difficulty when setting a track is determined by the track's `Difficulty` property, also overridable through `with`. +When setting an instrument, the target is determined by the [InstrumentIdentity](~/api/ChartTools.Instrument.yml#ChartTools_Instrument_InstrumentIdentity) property of the new instrument, which can be overridden using a `with` statement. Similarly, the target difficulty when setting a track is determined by the track's [Difficulty](~/api/ChartTools.Track.html#ChartTools_Track_Difficulty) property, also overridable through `with`. -> **NOTE**: Unlike when setting an instrument explicitely, the existing identity is used when setting dynamically. This makes it safe to reuse the previous reference after the assignement unless a `with` statement is used. Tracks still need to be re-obtained when using the dynamic syntax as a copy is created to assign its `ParentInstrument`. In cases where a reference to an instrument or track needs to be re-obtained, this reference is passed through as the return of `InstrumentSet.Set` and `Instrument.SetTrack`. +> **NOTE**: Unlike when setting an instrument explicitely, the existing identity is used when setting dynamically. This makes it safe to reuse the previous reference after the assignement unless a `with` statement is used. Tracks still need to be re-obtained when using the dynamic syntax as a copy is created to assign its [ParentInstrument](~/api/ChartTools.Track.ymll#ChartTools_Track_ParentInstrument). In cases where a reference to an instrument or track needs to be re-obtained, this reference is passed through as the return of [InstrumentSet.Set](~/api/ChartTools.InstrumentSet.yml#ChartTools_InstrumentSet_Set_ChartTools_StandardInstrument_) and `Instrument.SetTrack`. diff --git a/Docs/articles/events.md b/Docs/articles/events.md index 0bc4e5b9..2e8429a2 100644 --- a/Docs/articles/events.md +++ b/Docs/articles/events.md @@ -2,27 +2,27 @@ Events are track objects with custom data that drive various elements of gameplay. This guide will cover how to use events as well as the helpers provided by ChartTools. ## Class structure -Events are stored using `Event` as a base class, containing the position, event type and an optional argument. The type and argument can also be set simultaneously through the `EventData` property. +Events are stored using [Event](~/api/ChartTools.Events.Event.yml) as a base class, containing the position, event type and an optional argument. The type and argument can also be set simultaneously through the [EventData](~/api/ChartTools.Events.Event.yml#ChartTools_Events_Event_EventData) property. -ChartTools distinguishes between global events (stored under `Song`) and local events (stored under `Track`) using the respective `GlobalEvent` and `LocalEvent` classes, both deriving from `Event`. This allows for better type safety and for the classes to provide helper properties for some complex event types. +ChartTools distinguishes between global events (stored under [Song](~/api/ChartTools.Song.yml)) and local events (stored under [Track](~/api/ChartTools.Track.yml)) using the respective [GlobalEvent](~/api/ChartTools.Events.GlobalEvent.yml) and [LocalEvent](~/api/ChartTools.Events.LocalEvent.yml) classes, both deriving from [Event](~/api/ChartTools.Events.Event.yml). This allows for better type safety and for the classes to provide helper properties for some complex event types. ## Event helpers Event types and arguments are stored as `string`, allowing for future-proofing and supporting custom events from sources that are not officially supported. -For event types which are supported, CharTools provides helpers in the form of string constants under the static `EventTypeHelper.Global` and `EventTypeHelper.Local` classes. In a future version, usage details of helpers will be accessible from the documentation included with the assembly. +For event types which are supported, CharTools provides helpers in the form of string constants under the static [EventTypeHelper.Global](~/api/ChartTools.Events.EventTypeHeaderHelper.Global.yml) and [EventTypeHelper.Local](~/api/ChartTools.Events.EventTypeHeaderHelper.Local.yml) classes. In a future version, usage details of helpers will be accessible from the documentation included with the assembly. ```c# var globalEvent = new GlobalEvent(0, EventTypeHelper.Global.MusicStart, null); ``` -Some event types are part of a category defined by a prefix to the type. Helpers are provided for these groups under the static `EventTypeHeaderHelper` class. Helper properties are also defined for groups from supported sources. +Some event types are part of a category defined by a prefix to the type. Helpers are provided for these groups under the static [EventTypeHeaderHelper](~/api/ChartTools.Events.EventTypeHeaderHelper.yml) class. Helper properties are also defined for groups from supported sources. ```c# bool isCrowd = globalEvent.EventType.StartsWith(EventTypeHeaderHelper.Global.Crowd); bool isCrowd2 = globalEvent.IsCrowdEvent; ``` -Some event types can be modified using predefined arguments. For such values, helpers are provided under the static `EventArgumentHelper` class. +Some event types can be modified using predefined arguments. For such values, helpers are provided under the static [EventArgumentHelper](~/api/ChartTools.Events.EventArgumentHelper.html) class. ```c# var globalEvent = new GlobalEvent(0, EventTypeHelper.Global.Lighting, EventArgumentHelper.Global.Lighting.Strobe); diff --git a/Docs/articles/getting-started.md b/Docs/articles/getting-started.md index 0b4292ea..6721f705 100644 --- a/Docs/articles/getting-started.md +++ b/Docs/articles/getting-started.md @@ -7,14 +7,14 @@ To add ChartTools to your project, you must first build the ChartTools project. Visual Studio: Right-click on your project from the solution explorer and select "Add Project References...". Click on "Browse" and select `ChartTools.dll` that was generated. If the dll file is moved, also move `ChartTools.xml` to the new directory for XML documentation. ## Supported file formats -ChartTools supports the parsing of .chart and .ini files, with .mid parsing in the works. [mdsitton's BChart](https://github.com/mdsitton/bchart) format is planned as a post-launch update. Unless written as `.chart`, the term "chart" refers to songs supported by ChartTools regardless of the file format. +ChartTools supports the parsing of .chart and .ini files, with .mid parsing in the works. Unless written as `.chart`, the term "chart" refers to songs supported by ChartTools regardless of the file format. For documentation on the formats themselves, refer to the [GuitarGame_ChartFormats](https://github.com/TheNathannator/GuitarGame_ChartFormats) repository. ## Working with charts ### Song -Every component of a chart is stored in an instance of the Song class. It can be initialized by reading a file that will be parsed based on the extension. +Every component of a chart is stored in an instance of the [Song](~/api/ChartTools.Song.yml) class. It can be initialized by reading a file that will be parsed based on the extension. ```csharp Song song = Song.FromFile(path); @@ -26,7 +26,7 @@ A configuration object may also be used to customize the error handling behavior Song song = Song.FromFile(path, new ReadingConfiguration()); ``` -Note: Some MIDI files may contain formatting information in the song.ini file. In order to account for custom formatting when reading, it is recommended to read from a directory instead. +Note: Some Midi files may contain formatting information in the song.ini file. In order to account for custom formatting when reading, it is recommended to read from a directory instead. ```csharp Song song = Song.FromDirectory(path, ); @@ -36,10 +36,10 @@ When reading from a directory, the metadata will be read from `song.ini`, follow A song contains four main components: -- Metadata - Miscellaneous info about the song, such as title, album, charter etc. -- Sync track - Markers that define time signature and tempo +- [Metadata](~/api/ChartTools.Metadata.yml) - Miscellaneous info about the song, such as title, album, charter etc. +- [Sync track](~/api/ChartTools.SyncTrack.yml) - Markers that define time signature and tempo - [Global events](events.md) - Events that are not tied to an instrument -- Instruments - The instrument track data +- [Instruments](~/api/ChartTools.InstrumentSet.yml) - The instrument track data ### Metadata Similar to reading a song, metadata is retrieved by reading a file: @@ -58,16 +58,16 @@ Metadata metadata = Metadata.FromFiles(path1, path2, path3...); When reading from multiple files, you can mix file types, and the priority of information is defined by the order of the files. -As a future-proofing method, all unsupported items can be found under UnidentifiedData. This data will only be written to the same file format as the one it was read from. +As a future-proofing method, all unsupported items can be found under [UnidentifiedData](~/api/ChartTools.Metadata.yml#ChartTools_Metadata_UnidentifiedData). This data will only be written to the same file format as the one it was read from. ### Instruments and Tracks -All instruments currently supported are represented using the generic `Instrument` class. This class contains an object of type `Track` class for every difficulty. A track can be retrieved from a song with the following code: +All instruments currently supported are represented using the generic [Instrument](~/api/ChartTools.Instrument.yml) class. This class contains an object of type [Track](~/api/ChartTools.Track.yml) class for every difficulty. A track can be retrieved from a song with the following code: ```csharp Track track = song.Instruments.LeadGuitar.Expert; ``` -Notice the use of StandardChord as a generic type. Instruments are divided into four categories based on the type of chords they use. These categories are: +Notice the use of [StandardChord](~/api/ChartTools.StandardChord.yml) as a generic type. Instruments are divided into four categories based on the type of chords they use. These categories are: - Standard - Five colored notes - Drums - Five colored with support for double kick and cymbal flags @@ -80,17 +80,12 @@ A track is composed of three components: - Special phrases (star power) - [Local events](events.md) -> **NOTE**: When setting an instrument in an `InstrumentSet` or a track in an instrument, a copy of the object is created that contains information about its identity. In order to have changes made to the object after the assignment be reflected, a reference must be re-obtained from the parent. +> **NOTE**: When setting an instrument in an [InstrumentSet](~/api/ChartTools.InstrumentSet.yml) or a track in an instrument, a copy of the object is created that contains information about its identity. In order to have changes made to the object after the assignment be reflected, a reference must be re-obtained from the parent. Instruments can also be obtained dynamically from a song, regardless of the type. [Learn more about the dynamic syntax](dynamic-syntax.md). ### Chords and Notes -A chord is a set of notes played at the same time. All supported instruments use the generic version of the Chord class, where the generic type defines the type of notes contained. The note types are the same as the types of instruments listed in the section. The types of notes are - -- `Note` -- `Note` -- `DrumsNote` -- `Syllable` (Vocals) +A chord is a set of notes played at the same time. For readability, most chords and notes have specific classes for each instrument type, deriving from [LaneChord](~/api/ChartTools.LaneChord-3.yml) and [LaneNode\](~/api/ChartTools.LaneNote-1.yml). The following adds an orange note to every chord on a track: @@ -103,6 +98,8 @@ foreach (StandardChord chord in song.Instruments.LeadGuitar.Expert) } ``` +Unlike other instrument, [Vocals](~/api/ChartTools.Vocals.yml) contain [Phrases](~/api/ChartTools.Lyrics.Phrase.yml) and [Syllables](~/api/ChartTools.Lyrics.Syllable.yml). Although bound to chords and notes in the backend, syllables in a phrase are not all at the same position, instead storing their positions as offsets from their parent. [Learn more about vocals](lyrics.md). + ## Optimizing Although still functional, some files may contain data that slows down the reading process or, in worse cases, may result in non-functional files when saved in certain formats. ChartTools provides various utilities to fix such issues. @@ -120,13 +117,13 @@ syncTrack.TimeSignatures.RemoveUnneeded(); ChartTools includes other utilities for various purposes. [Learn more](tools.md). ## Writing files -Finally, changes can be saved to a file using the `ToFile` method of the `Song` class, with the format determined by the file extension. +Finally, changes can be saved to a file using [Song.ToFile](~/api/ChartTools.Song.yml#ChartTools_Song_ToFile_System_String_ChartTools_IO_Chart_Configuration_ChartWritingConfiguration_), with the format determined by the file extension. ```csharp song.ToFile("output.chart", ); ``` -Due to limitations of certain file formats, only `Song` objects can be written to a file in this manner. Format-specific operations can be accessed through the respective static class, such as `ChartFile` for `.chart`. For example, here is how to replace an instrument in a `.chart` file. +Due to limitations of certain file formats, only [Song](~/api/ChartTools.Song.yml) objects can be written to a file in this manner. Format-specific operations can be accessed through the respective static class, such as [ChartFile](~/api/ChartTools.IO.Chart.ChartFile.yml) for `.chart`. For example, here is how to replace an instrument in a `.chart` file. ```csharp ChartFile.ReplaceInstrument("output.chart", guitar, ); diff --git a/Docs/articles/improving-performance.md b/Docs/articles/improving-performance.md index defc1ee9..84d5f9c4 100644 --- a/Docs/articles/improving-performance.md +++ b/Docs/articles/improving-performance.md @@ -1,6 +1,24 @@ # Improving Performance This guide will cover alternate techniques that will improve performance when using ChartTools. +## Configuration +By default, IO operations make multiple integrity checks to resolve errors. These checks can be configured or skipped by using a [Readingconfiguration](~/api/ChartTools.IO.Configuration.ReadingConfiguration.yml) or [WritingConfiguration](~/api/ChartTools.IO.Configuration.WritingConfiguration.yml) object. [Learn more about configuring IO operations](Configuration.md). + +```csharp +Song song = Song.FromDirectory(directory, new ReadingConfiguration { DuplicateTrackObjectPolicy = DuplicateTrackObjectPolicy.IncludeAll }); +``` + +## Targeted formats +By default, the target format of an IO operation is determined by the file extension. You can bypass the extension check by using the file classes located in [ChartTools.IO](~/api/ChartTools.IO.yml). + +```c#s +Song song = ChartFile.ReadSong(path); +Metadata metadata = IniFile.ReadMetadata(path); +``` + +When writing to a specific format, the configuration object used is specific for that format and can be found as a property of the format-independent configuration, such as [ReadingConfiguration.Chart](~/api/ChartTools.IO.Configuration.ReadingConfiguration.yml#ChartTools_IO_Configuration_ReadingConfiguration_Chart). + + ## Single components Rather than performing IO operation on entire songs, such operations can be made on individual components. When writing a component to an existing file, the parts of the file regarding the component will be modified. @@ -9,14 +27,7 @@ Metadata metadata = Metadata.FromFile(path); StandardInstrument guitar = ChartFile.ReadInstrument(path, , metadata.Formatting); ``` -> **NOTE**: Due to complications with implementing Midi support, operations on single instruments and tracks through their respective class have been deprecated. These operations must now be performed through the respective format class such as ChartFile. - -## Configuration -By default, IO operations make multiple integrity checks to resolve errors. These checks can be configured or skipped by using a `Configuration` object. [Learn more about configuring IO operations](Configuration.md). - -```csharp -Song song = Song.FromDirectory(directory, new ReadingConfiguration { DuplicateTrackObjectPolicy = DuplicateTrackObjectPolicy.IncludeAll }); -``` +> **NOTE**: Due to complications with implementing Midi support, operations on single instruments and tracks through their respective class have been deprecated. These operations must now be performed through the respective format class such as [ChartFile](~/api/ChartTools.IO.Chart.ChartFile.yml). ## Asynchronous operations Every IO operation can be performed asynchronously by appending `Async` to the name of a method. @@ -31,12 +42,4 @@ Asynchronous operations support a `CancellationToken` as an optional parameter. Task readTask = Song.FromDirectoryAsync(directory, , ); ``` -The asynchronous operations make heavy use of multi-threading and are beneficial even if the result is to be awaited immediately. - -## Targeted formats -By default, the target format of an IO operation is determined by the file extension. You can bypass the extension check by using the file classes located in `ChartTools.IO`. - -```c# -Song song = ChartFile.ReadSong(path); -Metadata metadata = IniFile.ReadMetadata(path); -``` +The asynchronous operations make heavy use of multi-threading and are beneficial even if the result is to be awaited immediately. \ No newline at end of file diff --git a/Docs/articles/lyrics.md b/Docs/articles/lyrics.md index ecb2fec4..b645a9d1 100644 --- a/Docs/articles/lyrics.md +++ b/Docs/articles/lyrics.md @@ -1,12 +1,12 @@ # Lyrics -Lyrics of a song are defined by the Vocals instrument in which chords are phrases and notes as syllables. Unlike with lane chords which are defined by notes at the same position, syllables in phrases are consecutive and arbitrarily grouped into phrases. Lyric classes are defined under the `ChartTools.Lyrics` namespace. +Lyrics of a song are defined by the [Vocals](~/api/ChartTools.Vocals.yml) instrument in which chords are [phrases](~/api/ChartTools.Lyrics.Phrase.yml) and notes as [syllables](~/api/ChartTools.Lyrics.Syllable.yml). Unlike with lane chords which are defined by notes at the same position, syllables in phrases are consecutive and arbitrarily grouped into phrases. Lyric classes are defined under the [ChartTools.Lyrics](~/api/ChartTools.Lyrics.yml) namespace. -Although Clone Hero does not support vocals as an instrument and typically stores lyric data as global events, the `ChartTools.Lyrics` namespace provides a more rigorous API for editing lyrics. ChartTools also provides methods to convert between global events and vocals. Clone Hero also uses vocals to read lyrics from legacy songs. +Although Clone Hero does not support vocals as an instrument and typically stores lyric data as global events, the [ChartTools.Lyrics](~/api/ChartTools.Lyrics.yml) namespace provides a more rigorous API for editing lyrics. ChartTools also provides methods to convert between global events and vocals. Clone Hero also uses vocals to read lyrics from legacy songs. ## Syllables -Syllables define a start and end position in the form of offsets from the start position of the parent phrase. This allows for phrases to be moved by changing their position without having to update the position of each syllable. +[Syllables](~/api/ChartTools.Lyrics.Syllable.yml) define a start and end position in the form of offsets from the start position of the parent phrase. This allows for phrases to be moved by changing their position without having to update the position of each syllable. -The note index of syllables represents a vocal pitch from the range C2 to C6 using the `VocalsPitchValue`, stored under the `VocalPitch` helper struct. The enum uses a binary representation to isolate keys and octaves while staying true to music theory with comparing values. +The note index of syllables represents a vocal pitch from the range C2 to C6 using the [VocalPitchValue](~/api/ChartTools.Lyrics.VocalPitchValue.yml), stored under the [VocalPitch](~/api/ChartTools.Lyrics.VocalsPitch.yml) helper struct. The enum uses a binary representation to isolate keys and octaves while staying true to music theory with comparing values. The following code creates a syllable with the pitch of D3. @@ -16,21 +16,15 @@ Phrase phrase = song.Instruments.Vocals.Expect.Phrases; phrase.Syllables.Add(new Syllable(0, new VocalsPitch(3 << 4 | VocalsPitch.D)); ``` -Vocals also store lyric text to appear in-game. The text for each phrase is divided between the syllables to define the timings of the karaoke system. Clone Hero defines special characters such as dashes for multi-syllable words that don't appear in-game. The raw text with special characters can be access through the `RawText` property while `DisplayedText` processes the special characters and returns the syllable text as it appears in-game. +[Vocals](~/api/ChartTools.Vocals.yml) also store lyric text to appear in-game. The text for each phrase is divided between the syllables to define the timings of the karaoke system. Clone Hero defines special characters such as dashes for multi-syllable words that don't appear in-game. The raw text with special characters can be access through the [RawText](~/api/ChartTools.Lyrics.Syllable.yml#ChartTools_Lyrics_Syllable_RawText) property while [DisplayedText](~/api/ChartTools.Lyrics.Syllable.yml#ChartTools_Lyrics_Syllable_DisplayedText) processes the special characters and returns the syllable text as it appears in-game. -> **NOTE**: Clone Hero also supports color data in the text. This is currently not supported in ChartTools and special characters related to color data will appear as part of `DisplayedText`. +> **NOTE**: Clone Hero also supports color data in the text. This is currently not supported in ChartTools and special characters related to color data will appear as part of [DisplayedText](~/api/ChartTools.Lyrics.Syllable.yml#ChartTools_Lyrics_Syllable_DisplayedText). ## Phrases -Unlike other chords, phrases define a length and end position in addition to a start position. The end position is driven by the end of the last syllable but can be replaced by setting the `LengthOverride` property. Phrases also define `RawText` and `DisplayedText` properties which combine the text from their syllables. +Unlike other chords, [phrases](~/api/ChartTools.Lyrics.Phrase.yml) define a length and end position in addition to a start position. The end position is driven by the end of the last syllable but can be replaced by setting the `LengthOverride` property. Phrases also define [RawText](~/api/ChartTools.Lyrics.Syllable.yml#ChartTools_Lyrics_Phrase_RawText) and [DisplayedText](~/api/ChartTools.Lyrics.Syllable.yml#ChartTools_Lyrics_Phrase_DisplayedText) properties which combine the text from their syllables. ## Reading and writing vocals -Vocals can be read like any other instrument using the `FromFile` method. - -```csharp -Vocals? vocals = Vocals.FromFile(path, , ); -``` - -Chart files define lyrics through global events that can be converted to a set of phrases. When reading a full song from a chart file, the vocals instrument will be null. +Chart files define lyrics through global events that can be converted to a set of phrases. When reading a full song from a chart file, the vocals instrument will be null. To benefit of the more advanced lyrics API, a dummy set of phrases instrument can be generated using the [GetLyrics](~/api/ChartTools.Events.EventExtensions.yml#ChartTools_Events_EventExtensions_GetLyrics_System_Collections_Generic_IEnumerable_ChartTools_Events_GlobalEvent__) extension method. ```csharp using ChartTools.Lyrics; @@ -47,4 +41,3 @@ lyrics.ToGlobalEvents(); // Creates a new set of global events events.SetLyrics(lyrics); // Replaces existing lyric-related events with new events making up the phrases ``` -It is also possible to edit lyrics directly from the global events, although syllable objects simplifies the editing process. When doing so, phrases must be converted back into events for the changes to be applied. diff --git a/Docs/articles/tools.md b/Docs/articles/tools.md index c2120ae9..3992dad5 100644 --- a/Docs/articles/tools.md +++ b/Docs/articles/tools.md @@ -4,7 +4,7 @@ ChartTools includes multiple utility methods for performing common operations on Fun fact: The name ChartTools comes from the original purpose of the library of only providing utility methods for charts. ## Accessing utilities -To start using utilities, add the `ChartTools.Tools` namespace to your usings. Once added, utilities can be called from their respective static class or as extension methods. +To start using utilities, add the [ChartTools.Tools](~/api/ChartTools.Tools.yml) namespace to your usings. Once added, utilities can be called from their respective static class or as extension methods. ```csharp using ChartTools.Tools; @@ -14,7 +14,7 @@ song.AwesomeUtility(); ``` ## Merging lengths -Some track objects define a length, such as special phrases and vocal phrases. `LengthMerger` takes a set of such objects and sets the first object in the sequence to cover the entire duration from the start position of the earliest object to the end position of the last. +Some track objects define a length, such as special phrases and vocal phrases. [LengthMerger](~/api/ChartTools.Tools.LengthMerger.yml) takes a set of such objects and sets the first object in the sequence to cover the entire duration from the start position of the earliest object to the end position of the last. ```csharp // T is the type of objects in the collection. @@ -30,14 +30,14 @@ target = LengthMerger.MergeLengths(longTrackObjects, target); If a sequence has an object covering positions 10-20 and another covering 22-30, the resulting object will have a start position of 10 and end position of 30. ## Cutting lengths and sustains -In some cases, tracks may be in a broken state where objects define lengths going part the start of the next matching objects. The Optimizer class provides methods for fixing such overlaps by cutting short lenghts going past the start of certain objects. This process involves ordering the objects by position, the result of which is provided as a return value. If the objects are known to already be in order, the ordering can be skipped with an optional parameter. +In some cases, tracks may be in a broken state where objects define lengths going part the start of the next matching objects. The Optimizer class provides methods for fixing such overlaps by cutting short lengths going past the start of certain objects. This process involves ordering the objects by position, the result of which is provided as a return value. If the objects are known to already be in order, the ordering can be skipped with an optional parameter. ### Cutting sustains ```csharp List ordered = Optimizer.CutSustains(guitarChords, ); ``` -Supports all chord types and simulates where sustains are foced to end due to another note of the same index or the presence of an open note and vice versa. Syllables are not modified, which may result in them falling outside the end position of the parent phrase. Part of the process of finding how to cut sustain involves ordering chords by position. The result of the ordering is provided as a return value. +Supports all chord types and simulates where sustains are forced to end due to another note of the same index or the presence of an open note and vice versa. Syllables are not modified, which may result in them falling outside the end position of the parent phrase. Part of the process of finding how to cut sustain involves ordering chords by position. The result of the ordering is provided as a return value. ### Cutting special phrases ```csharp @@ -49,14 +49,14 @@ Groups phrases by special type before applying the cutting to each group individ > **NOTE**: Due to the grouping being based on the numeric value of the special type, only collections of instruments and track special phrases are supported. Using an `IEnumerable` will result in an exception. ### Cutting other long track objects -When the type of long objects is not known, a base method using the `ILongTrackObject` interface can be used. This method only applies the base logic, treating each object equally compared to how note sustains and special phrase lenghts which are grouped by their respective methods, returning the objects ordered by length. +When the type of long objects is not known, a base method using the [ILongTrackObject](~/api/ChartTools.ILongTrackObject.yml) interface can be used. This method only applies the base logic, treating each object equally compared to how note sustains and special phrase lengths which are grouped by their respective methods, returning the objects ordered by length. ```csharp -List oredredObjects = Optimizer.CutLenghts(obejcts, ); +List oredredObjects = Optimizer.CutLenghts(objects, ); ``` ## Removing redundant sync track markers -The Optimizer class provides methods for removing tempo and time signature markers that have no effect on gameplay. Like with length cutting, the objects are ordered by position and provided as a return value. The ordering can also be skipped with an optional parameter. +The [Optimizer](~/api/ChartTools.Tools.Optimizer.yml) class provides methods for removing tempo and time signature markers that have no effect on gameplay. Like with length cutting, the objects are ordered by position and provided as a return value. The ordering can also be skipped with an optional parameter. ```csharp List orderedSignatures = Optimizer.RemoveUneeded(tempoMarkers, ); @@ -71,7 +71,7 @@ List orderedMarkers = Optimizer.RemoveUneeded(tempoMap, resolution, +``` + +where `PID` is the right-most ID in the output of `netstat`. + ## License and Attribution This project is licensed under the GNU General Public License 3.0. See [LICENSE](https://github.com/TheBoxyBear/charttools/blob/stable/LICENSE) for details.