ultrastar

package module
v0.0.0-...-95630b3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2023 License: MIT Imports: 10 Imported by: 0

README

go-ultrastar

This project provides multiple Go packages for working with UltraStar songs. Have a look at the Docs.

Packages

The main ultrastar package implements the main types for programmatically interacting with karaoke songs.

The txt subpackage implements a parser and a serializer for the UltraStar TXT format.

Installation

go get github.com/Karaoke-Manager/go-ultrastar

Quick Start

package main

import (
  "github.com/Karaoke-Manager/go-ultrastar"
  "github.com/Karaoke-Manager/go-ultrastar/txt"
)

// Parse song from a file
file, _ := os.Open("some/song.txt")
defer file.Close()
song, err := txt.ReadSong(file)

// Do some transformations
song.Title = "Never Gonna Give You Up"
song.MusicP1.ConvertToLeadingSpaces()
// Work with GAP, VIDEOGAP, etc. using native Go types
song.Gap = 2 * time.Second
// The ultrastar package provides convenient types for Pitches, Beats, BPM, ...
song.MusicP1.Notes[2].Pitch = ultrastar.NamedPitch("F#2")

// Write song back to file
err = txt.WriteSong(file, song)

Have a look at the Docs to see everything you can do.

Documentation

Overview

Package ultrastar is a package for working with UltraStar songs. The package provides data types for working with songs and music as well as some methods for typical manipulations of music.

The github.com/Karaoke-Manager/go-ultrastar/txt subpackage implements a parser and serializer for the UltraStar TXT format.

Index

Examples

Constants

View Source
const MaxBeat = Beat(^uint(0) >> 1)

MaxBeat is the maximum value for the Beat type.

Variables

View Source
var (
	// ErrInvalidPitchName denotes that the named pitch was not recognized.
	ErrInvalidPitchName = errors.New("unknown pitch name")
)

These known errors might be returned by some of the functions and methods in this package.

Functions

This section is empty.

Types

type BPM

type BPM float64

BPM is a measurement of the 'speed' of a song. It counts the number of Beat's per minute.

func (BPM) Beats

func (b BPM) Beats(d time.Duration) Beat

Beats returns the number of beats in the specified duration. The result is rounded down to the nearest integer. If b is invalid the result is undefined.

func (BPM) Duration

func (b BPM) Duration(bs Beat) time.Duration

Duration returns the time it takes for bs beats to pass. If b is invalid the result is undefined.

func (BPM) IsValid

func (b BPM) IsValid() bool

IsValid indicates whether b is a valid BPM number.

type BPMChange

type BPMChange struct {
	Start Beat
	BPM   BPM
}

A BPMChange indicates that the BPM value of a Music changes at a certain point in time. BPM changes are one of the lesser known features of UltraStar songs and should be used with care as they are not very well known or well-supported.

A BPMChange is typically used as a value type.

func (*BPMChange) GobDecode

func (c *BPMChange) GobDecode(bs []byte) error

GobDecode updates c from the encoded byte slice.

func (*BPMChange) GobEncode

func (c *BPMChange) GobEncode() ([]byte, error)

GobEncode encodes c into a byte slice.

type Beat

type Beat int

A Beat is the measurement unit for notes in a song. A beat is not an absolute measurement of time but must be viewed relative to the BPM value of the Music.

type Music

type Music struct {
	// The notes of the music. Must be kept sorted by Start values.
	Notes Notes
	// The BPM changes of the music. Must be kept sorted by Start values.
	BPMs []BPMChange
}

Music is a single voice of a karaoke song. Naively a Music value can be viewed as a sequence of notes. However, Music values do support BPM changes, one of the lesser known features of UltraStar songs. In most cases tough, a Music value will only have a single BPM value valid for all Notes.

A Music value does not know about the relative mode of UltraStar files. All times in a Music value are absolute. The github.com/Karaoke-Manager/go-ultrastar/txt package can parse and write UltraStar files in absolute or relative mode.

The Notes fields of a Music value contains the sequence of notes. All Music methods expect the Notes and BPMs field to be sorted by their Start values. All custom functions that operate on Music values are expected to maintain this property. You can use the Music.Sort method to restore the sort property.

func NewMusic

func NewMusic() (m *Music)

NewMusic creates a new Music value with some default capacities for m.Notes and m.BPMs.

Note that m.BPMs is empty which may break the expectation of some methods.

func NewMusicWithBPM

func NewMusicWithBPM(bpm BPM) (m *Music)

NewMusicWithBPM creates a new Music value with a default capacity for m.Notes and a single BPM value that is valid for the entire Music.

func (*Music) AddNote

func (m *Music) AddNote(n Note)

AddNote inserts n into m.Notes white maintaining the sort property.

func (*Music) BPM

func (m *Music) BPM() BPM

BPM returns the BPM of m at beat 0. This method is intended for Music values that only have a single BPM value for the entire Music. On Music values without any BPM value this method returns NaN.

func (*Music) Clone

func (m *Music) Clone() *Music

Clone creates a deep copy of m. The returned Music value has a copy of the Notes and BPMs from m.

func (*Music) ConvertToLeadingSpaces

func (m *Music) ConvertToLeadingSpaces()

ConvertToLeadingSpaces ensures that the text of notes does not end with a whitespace. It does so by "moving" the whitespace to the neighboring notes. Spaces are not moved across line breaks, so Notes before line breaks and the last note will have trailing spaces removed.

Only the space character is understood as whitespace.

func (*Music) ConvertToTrailingSpaces

func (m *Music) ConvertToTrailingSpaces()

ConvertToTrailingSpaces ensures that the text of notes does not start with a whitespace. It does so by "moving" the whitespace to the neighboring notes. Spaces are not moved across line breaks, so Notes after line breaks and the first note will have leading spaces removed.

Only the space character is understood as whitespace.

func (*Music) Duration

func (m *Music) Duration() time.Duration

Duration calculates the absolute duration of m, respecting any BPM changes. The duration of a song only respects beats of m.Notes. Any BPM changes after Music.LastBeat do not influence the duration. If m contains invalid BPM values or no BPM at all the result is undefined.

The maximum duration of a Music value is realistically limited to about 2500h. Longer Music values may give inaccurate results because of floating point imprecision.

func (*Music) EnumerateLines

func (m *Music) EnumerateLines(f func([]Note, Beat))

EnumerateLines calls f for each line of a song. A line are the notes up to but not including a line break. The Start value of the line break is passed to f as a second parameter. If a song does not end with a line break the Music.LastBeat value will be passed to f.

func (*Music) FitBPM

func (m *Music) FitBPM(target BPM)

FitBPM recalculates note starts and durations to fit the specified target. Values are rounded to the nearest integer. This method tries to change the absolute timings of notes as little as possible while resulting in a single-BPM version of m.

If m contains invalid BPMs or no BPM values at all, this method panics.

func (*Music) LastBeat

func (m *Music) LastBeat() Beat

LastBeat calculates the last meaningful Beat in m, that is the last beat of the last non line break note.

func (*Music) Lyrics

func (m *Music) Lyrics() string

Lyrics generates the full lyrics of m. The full lyrics is the concatenation of the individual Note.Lyrics values.

func (*Music) Offset

func (m *Music) Offset(offset Beat)

Offset shifts all notes and BPM changes by the specified offset.

func (*Music) Scale

func (m *Music) Scale(factor float64)

Scale rescales all notes, durations and BPM changes by the specified factor. This will increase or decrease the duration of m by factor. All times will be rounded to the nearest integer.

func (*Music) SetBPM

func (m *Music) SetBPM(bpm BPM)

SetBPM sets the BPM of m at beat 0. This method is intended for Music values that only have a single BPM value for the entire Music.

func (*Music) Sort

func (m *Music) Sort()

Sort restores the sort property of m. After this method returns m.Notes and m.BPMs will both be sorted by their Start values.

func (*Music) Substitute

func (m *Music) Substitute(substitute string, texts ...string)

Substitute replaces note texts that exactly match one of the texts by the specified substitute text. This can be useful to replace the text of holding notes.

type Note

type Note struct {
	// Type denotes the kind note.
	Type NoteType
	// Start is the start beat of the note.
	Start Beat
	// Duration is the length for which the note is held.
	Duration Beat
	// Pitch is the pitch of the note.
	Pitch Pitch
	// Text is the lyric of the note.
	Text string
}

A Note represents the smallest timed unit of text in a song. Usually this corresponds to a syllable of text.

func (*Note) GobDecode

func (n *Note) GobDecode(bs []byte) error

GobDecode updates n from the encoded byte slice.

func (*Note) GobEncode

func (n *Note) GobEncode() ([]byte, error)

GobEncode encodes n into a byte slice.

func (*Note) Lyrics

func (n *Note) Lyrics() string

Lyrics returns the lyrics of the note. This is either the note's Text or may be a special value depending on the note type.

func (*Note) String

func (n *Note) String() string

String returns a string representation of the note, inspired by the UltraStar TXT format. This format should not be relied upon. If you need consistent serialization use the github.com/Karaoke-Manager/go-ultrastar/txt subpackage.

Example
n := Note{
	Type:     NoteTypeGolden,
	Start:    15,
	Duration: 4,
	Pitch:    8,
	Text:     "Go",
}
fmt.Println(n.String())
Output:

* 15 4 8 Go

type NoteType

type NoteType byte

The NoteType of a Note specifies the input processing and rating for that note.

const (
	// NoteTypeLineBreak represents a line break.
	// Line Break notes do not have a Duration or Pitch.
	NoteTypeLineBreak NoteType = '-'
	// NoteTypeRegular represents a normal, sung note.
	NoteTypeRegular NoteType = ':'
	// NoteTypeGolden represents a golden note that can award additional points.
	NoteTypeGolden NoteType = '*'
	// NoteTypeFreestyle represents freestyle notes that are not graded.
	NoteTypeFreestyle NoteType = 'F'
	// NoteTypeRap represents rap notes, where the pitch is irrelevant.
	NoteTypeRap NoteType = 'R'
	// NoteTypeGoldenRap represents golden rap notes (also known as Gangsta notes)
	// that can award additional points.
	NoteTypeGoldenRap NoteType = 'G'
)

These are the note types supported by this package. These correspond to the note types supported by UltraStar.

func (NoteType) IsFreestyle

func (n NoteType) IsFreestyle() bool

IsFreestyle determines if a note is a freestyle note.

func (NoteType) IsGolden

func (n NoteType) IsGolden() bool

IsGolden determines if a note is a golden note (rap or regular).

func (NoteType) IsLineBreak

func (n NoteType) IsLineBreak() bool

IsLineBreak determines if a note is a line break.

func (NoteType) IsRap

func (n NoteType) IsRap() bool

IsRap determines if a note is a rap note (golden or not).

func (NoteType) IsSung

func (n NoteType) IsSung() bool

IsSung determines if a note is a normally sung note (golden or not).

func (NoteType) IsValid

func (n NoteType) IsValid() bool

IsValid determines if a note type is a valid UltraStar note type.

type Notes

type Notes []Note

Notes is an alias type for a slice of notes. This type implements the sort interface.

func (Notes) Len

func (n Notes) Len() int

Len returns the number of notes in the slice.

This is part of the implementation of sort.Interface.

func (Notes) Less

func (n Notes) Less(i int, j int) bool

The Less function returns a boolean value indicating whether the note at index i starts before note at index j.

This is part of the implementation of sort.Interface.

func (Notes) Swap

func (n Notes) Swap(i int, j int)

Swap swaps the notes at indexes i and j.

This is part of the implementation of sort.Interface.

type Pitch

type Pitch int

A Pitch represents the pitch of a note.

func NamedPitch

func NamedPitch(s string) Pitch

NamedPitch works like PitchFromString but panics if the pitch cannot be parsed. This can be useful for testing or for compile-time constant pitches.

func PitchFromString

func PitchFromString(s string) (p Pitch, err error)

PitchFromString returns a new pitch based on the string representation of a pitch.

func (Pitch) NoteName

func (p Pitch) NoteName() string

NoteName returns the human-readable name of the pitch. The note naming is not very sophisticated. Only whole and half steps are supported and note names use sharps exclusively. So a D flat and a C sharp will both return "C#" as their note name.

Example
fmt.Println(NamedPitch("Gb4").NoteName())
Output:

F#

func (Pitch) Octave

func (p Pitch) Octave() int

Octave returns the scientific octave of a pitch.

Example
fmt.Println(Pitch(0).Octave())
Output:

4

func (Pitch) String

func (p Pitch) String() string

String returns a human-readable string representation of the pitch.

type Song

type Song struct {
	// References to other files.
	AudioFile      string
	VideoFile      string
	CoverFile      string
	BackgroundFile string

	// A delay until Beat 0 of the Music.
	Gap time.Duration
	// A delay until the video starts.
	VideoGap time.Duration
	// An offset to the beats of the Music.
	NotesGap Beat
	// UltraStar will jump into the song at this time.
	Start time.Duration
	// UltraStar will stop the song at this time.
	End time.Duration
	// If specified the preview will start at this time.
	PreviewStart time.Duration
	// In medley mode this is the start of the song.
	MedleyStartBeat Beat
	// If medley mode this is the end of the song.
	MedleyEndBeat Beat
	// If set to false the medley start and end beat are not calculated automatically.
	// If medley start and end beat are set manually this has no effect.
	CalcMedley bool
	// The resolution of the song.
	// Defaults to 4 and has probably no effect.
	Resolution int

	// Song metadata
	Title    string
	Artist   string
	Genre    string
	Edition  string
	Creator  string
	Language string
	Year     int
	Comment  string

	// Name of player 1
	DuetSinger1 string
	// Name of player 2
	DuetSinger2 string

	// Any custom tags that are not supported by this package.
	CustomTags map[string]string

	// Music of player 1
	MusicP1 *Music
	// Music of player 2. Any non-nil value indicates that this is a duet.
	MusicP2 *Music
}

A Song is an implementation of an UltraStar song. This implementation directly supports many of the known fields for songs, making it convenient to work with. Known fields are normalized to standard Go types, so you don't have to deal with the specifics of #GAP, #VIDEOGAP and so on.

The Song type does not support parsing or serialization. To parse and write songs use the github.com/Karaoke-Manager/go-ultrastar/txt package.

func NewDuet

func NewDuet() (s *Song)

NewDuet creates a new duet. Note that neither s.MusicP1 nor s.MusicP2 have a BPM value set.

func NewDuetWithBPM

func NewDuetWithBPM(bpm BPM) (s *Song)

NewDuetWithBPM creates a new duet and sets the BPM of s.MusicP1 and s.MusicP2 to bpm.

func NewSong

func NewSong() (s *Song)

NewSong creates a new (single-player) song. Note that s.Music does not have a BPM value set.

func NewSongWithBPM

func NewSongWithBPM(bpm BPM) (s *Song)

NewSongWithBPM creates a new (single-player) song and sets the BPM of s.MusicP1 to bpm.

func (*Song) BPM

func (s *Song) BPM() BPM

BPM returns the BPM of s at time 0. This is intended for songs with a single BPM value. Calling this method on a song without BPM or with different BPMs for the players will return NaN.

func (*Song) Duration

func (s *Song) Duration() time.Duration

Duration calculates the singing duration of s. The singing duration is the time from the beginning of the song until the last sung note.

func (*Song) IsDuet

func (s *Song) IsDuet() bool

IsDuet indicates whether a song is duet. Accessing s.MusicP2 is only valid for duets.

func (*Song) SetBPM

func (s *Song) SetBPM(bpm BPM)

SetBPM sets the BPM of s at time 0. This is intended for songs with a single BPM value.

Directories

Path Synopsis
Package txt implements parsing and writing the UltraStar TXT file format.
Package txt implements parsing and writing the UltraStar TXT file format.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL