diff --git a/player/intf/channel.go b/channel.go similarity index 94% rename from player/intf/channel.go rename to channel.go index 948d11b..69b17c0 100644 --- a/player/intf/channel.go +++ b/channel.go @@ -1,4 +1,4 @@ -package intf +package playback import ( "github.com/gotracker/gomixing/panning" @@ -6,9 +6,9 @@ import ( "github.com/gotracker/gomixing/volume" "github.com/gotracker/voice" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" "github.com/gotracker/playback/player/output" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" ) // Channel is an interface for channel state diff --git a/player/intf/effect.go b/effect.go similarity index 99% rename from player/intf/effect.go rename to effect.go index fabb3c2..81c686e 100644 --- a/player/intf/effect.go +++ b/effect.go @@ -1,4 +1,4 @@ -package intf +package playback import "fmt" diff --git a/format/internal/filter/amigafilter.go b/filter/amigafilter.go similarity index 95% rename from format/internal/filter/amigafilter.go rename to filter/amigafilter.go index 513149e..167b217 100644 --- a/format/internal/filter/amigafilter.go +++ b/filter/amigafilter.go @@ -4,7 +4,6 @@ import ( "math" "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/filter" "github.com/gotracker/voice/period" ) @@ -33,7 +32,7 @@ func NewAmigaLPF(instrument, playback period.Frequency) *AmigaLPF { return &lpf } -func (f *AmigaLPF) Clone() filter.Filter { +func (f *AmigaLPF) Clone() Filter { c := *f c.channels = make([]channelData, len(f.channels)) for i := range f.channels { diff --git a/format/internal/filter/echofilter.go b/filter/echofilter.go similarity index 92% rename from format/internal/filter/echofilter.go rename to filter/echofilter.go index 6778e7c..f548e28 100644 --- a/format/internal/filter/echofilter.go +++ b/filter/echofilter.go @@ -3,7 +3,6 @@ package filter import ( "math" - "github.com/gotracker/playback/filter" "github.com/gotracker/voice/period" "github.com/gotracker/gomixing/volume" @@ -22,8 +21,8 @@ type EchoFilterFactory struct { EchoFilterSettings } -func (e *EchoFilterFactory) Factory() filter.Factory { - return func(instrument, playback period.Frequency) filter.Filter { +func (e *EchoFilterFactory) Factory() Factory { + return func(instrument, playback period.Frequency) Filter { echo := EchoFilter{ EchoFilterSettings: e.EchoFilterSettings, sampleRate: playback, @@ -48,7 +47,7 @@ type EchoFilter struct { delay [2]delayInfo // L,R } -func (e *EchoFilter) Clone() filter.Filter { +func (e *EchoFilter) Clone() Filter { clone := EchoFilter{ EchoFilterSettings: e.EchoFilterSettings, sampleRate: e.sampleRate, diff --git a/player/intf/format.go b/format.go similarity index 53% rename from player/intf/format.go rename to format.go index a14c64e..1c54bb7 100644 --- a/player/intf/format.go +++ b/format.go @@ -1,8 +1,13 @@ -package intf +package playback -import "github.com/gotracker/playback/format/settings" +import ( + "io" + + "github.com/gotracker/playback/settings" +) // Format is an interface to a music file format loader type Format[TChannelData any] interface { Load(filename string, s *settings.Settings) (Playback, error) + LoadFromReader(r io.Reader, s *settings.Settings) (Playback, error) } diff --git a/format/common/loadformat.go b/format/common/loadformat.go new file mode 100644 index 0000000..c52c8a0 --- /dev/null +++ b/format/common/loadformat.go @@ -0,0 +1,22 @@ +package common + +import ( + "io" + + "github.com/gotracker/playback/settings" +) + +type ReaderFunc[TSong any] func(r io.Reader, s *settings.Settings) (*TSong, error) + +type ManagerFactory[TSong, TManager any] func(*TSong) (*TManager, error) + +func Load[TSong, TManager any](r io.Reader, reader ReaderFunc[TSong], factory ManagerFactory[TSong, TManager], s *settings.Settings) (*TManager, error) { + song, err := reader(r, s) + if err != nil { + return nil, err + } + + m, err := factory(song) + + return m, err +} diff --git a/format/format.go b/format/format.go index 9ac1377..5726127 100644 --- a/format/format.go +++ b/format/format.go @@ -2,23 +2,24 @@ package format import ( "errors" + "io" "os" + "github.com/gotracker/playback" "github.com/gotracker/playback/format/it" "github.com/gotracker/playback/format/mod" "github.com/gotracker/playback/format/s3m" - "github.com/gotracker/playback/format/settings" "github.com/gotracker/playback/format/xm" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback/settings" "github.com/gotracker/playback/song" ) var ( - supportedFormats = make(map[string]intf.Format[song.ChannelData]) + supportedFormats = make(map[string]playback.Format[song.ChannelData]) ) // Load loads the a file into a playback manager -func Load(filename string, options ...settings.OptionFunc) (intf.Playback, intf.Format[song.ChannelData], error) { +func Load(filename string, options ...settings.OptionFunc) (playback.Playback, playback.Format[song.ChannelData], error) { s := &settings.Settings{} for _, opt := range options { if err := opt(s); err != nil { @@ -27,8 +28,40 @@ func Load(filename string, options ...settings.OptionFunc) (intf.Playback, intf. } for _, f := range supportedFormats { - if playback, err := f.Load(filename, s); err == nil { - return playback, f, nil + if pb, err := f.Load(filename, s); err == nil { + return pb, f, nil + } else if os.IsNotExist(err) { + return nil, nil, err + } + } + return nil, nil, errors.New("unsupported format") +} + +// LoadFromReader loads a song file on a reader into a playback manager +func LoadFromReader(format string, r io.Reader, options ...settings.OptionFunc) (playback.Playback, playback.Format[song.ChannelData], error) { + s := &settings.Settings{} + for _, opt := range options { + if err := opt(s); err != nil { + return nil, nil, err + } + } + + if format != "" { + f, ok := supportedFormats[format] + if !ok { + return nil, nil, errors.New("unsupported format") + } + + if pb, err := f.LoadFromReader(r, s); err == nil { + return pb, f, nil + } else { + return nil, nil, err + } + } + + for _, f := range supportedFormats { + if pb, err := f.LoadFromReader(r, s); err == nil { + return pb, f, nil } else if os.IsNotExist(err) { return nil, nil, err } diff --git a/format/it/layout/channel/channel.go b/format/it/channel/data.go similarity index 83% rename from format/it/layout/channel/channel.go rename to format/it/channel/data.go index eb22739..d155676 100644 --- a/format/it/layout/channel/channel.go +++ b/format/it/channel/data.go @@ -7,10 +7,10 @@ import ( itfile "github.com/gotracker/goaudiofile/music/tracked/it" "github.com/gotracker/gomixing/volume" - itNote "github.com/gotracker/playback/format/it/conversion/note" - itVolume "github.com/gotracker/playback/format/it/conversion/volume" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" + itNote "github.com/gotracker/playback/format/it/note" + itVolume "github.com/gotracker/playback/format/it/volume" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" ) const MaxTotalChannels = 64 @@ -18,21 +18,6 @@ const MaxTotalChannels = 64 // DataEffect is the type of a channel's EffectParameter value type DataEffect uint8 -// SampleID is an InstrumentID that is a combination of InstID and SampID -type SampleID struct { - InstID uint8 - Semitone note.Semitone -} - -// IsEmpty returns true if the sample ID is empty -func (s SampleID) IsEmpty() bool { - return s.InstID == 0 -} - -func (s SampleID) String() string { - return fmt.Sprint(s.InstID) -} - // Data is the data for the channel type Data struct { What itfile.ChannelDataFlags diff --git a/format/it/layout/channel/memory.go b/format/it/channel/memory.go similarity index 86% rename from format/it/layout/channel/memory.go rename to format/it/channel/memory.go index 5dd61c3..660668c 100644 --- a/format/it/layout/channel/memory.go +++ b/format/it/channel/memory.go @@ -3,29 +3,12 @@ package channel import ( "github.com/gotracker/voice/oscillator" - "github.com/gotracker/playback/format/internal/effect" - "github.com/gotracker/playback/format/internal/memory" - formatutil "github.com/gotracker/playback/format/internal/util" + "github.com/gotracker/playback/memory" oscillatorImpl "github.com/gotracker/playback/oscillator" + "github.com/gotracker/playback/tremor" + formatutil "github.com/gotracker/playback/util" ) -type SharedMemory struct { - // LinearFreqSlides is true if linear frequency slides are enabled (false = amiga-style period-based slides) - LinearFreqSlides bool - // OldEffectMode performs somewhat different operations for some effects: - // On: - // - Vibrato does not operate on tick 0 and has double depth - // - Sample Offset will ignore the command if it would exceed the length - // Off: - // - Vibrato is updated every frame - // - Sample Offset will set the offset to the end of the sample if it would exceed the length - OldEffectMode bool - // EFGLinkMode will make effects Exx, Fxx, and Gxx share the same memory - EFGLinkMode bool - // ResetMemoryAtStartOfOrder0 if true will reset the memory registers when the first tick of the first row of the first order pattern plays - ResetMemoryAtStartOfOrder0 bool -} - // Memory is the storage object for custom effect/effect values type Memory struct { volumeSlide memory.Value[DataEffect] `usage:"Dxy"` @@ -46,7 +29,7 @@ type Memory struct { panbrello memory.Value[DataEffect] `usage:"Yxy"` volChanVolumeSlide memory.Value[DataEffect] `usage:"vDxy"` - tremorMem effect.Tremor + tremorMem tremor.Tremor vibratoOscillator oscillator.Oscillator tremoloOscillator oscillator.Oscillator panbrelloOscillator oscillator.Oscillator @@ -155,7 +138,7 @@ func (m *Memory) Panbrello(input DataEffect) DataEffect { } // TremorMem returns the Tremor object -func (m *Memory) TremorMem() *effect.Tremor { +func (m *Memory) TremorMem() *tremor.Tremor { return &m.tremorMem } diff --git a/format/it/channel/sampleid.go b/format/it/channel/sampleid.go new file mode 100644 index 0000000..b529a24 --- /dev/null +++ b/format/it/channel/sampleid.go @@ -0,0 +1,22 @@ +package channel + +import ( + "fmt" + + "github.com/gotracker/playback/note" +) + +// SampleID is an InstrumentID that is a combination of InstID and SampID +type SampleID struct { + InstID uint8 + Semitone note.Semitone +} + +// IsEmpty returns true if the sample ID is empty +func (s SampleID) IsEmpty() bool { + return s.InstID == 0 +} + +func (s SampleID) String() string { + return fmt.Sprint(s.InstID) +} diff --git a/format/it/channel/sharedmem.go b/format/it/channel/sharedmem.go new file mode 100644 index 0000000..7422540 --- /dev/null +++ b/format/it/channel/sharedmem.go @@ -0,0 +1,18 @@ +package channel + +type SharedMemory struct { + // LinearFreqSlides is true if linear frequency slides are enabled (false = amiga-style period-based slides) + LinearFreqSlides bool + // OldEffectMode performs somewhat different operations for some effects: + // On: + // - Vibrato does not operate on tick 0 and has double depth + // - Sample Offset will ignore the command if it would exceed the length + // Off: + // - Vibrato is updated every frame + // - Sample Offset will set the offset to the end of the sample if it would exceed the length + OldEffectMode bool + // EFGLinkMode will make effects Exx, Fxx, and Gxx share the same memory + EFGLinkMode bool + // ResetMemoryAtStartOfOrder0 if true will reset the memory registers when the first tick of the first row of the first order pattern plays + ResetMemoryAtStartOfOrder0 bool +} diff --git a/format/it/it.go b/format/it/it.go index 2f9f4fe..f1d72c3 100644 --- a/format/it/it.go +++ b/format/it/it.go @@ -2,9 +2,12 @@ package it import ( + "io" + + "github.com/gotracker/playback" "github.com/gotracker/playback/format/it/load" - "github.com/gotracker/playback/format/settings" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback/settings" + "github.com/gotracker/playback/util" ) type format struct{} @@ -15,6 +18,16 @@ var ( ) // Load loads an IT file into a playback system -func (f format) Load(filename string, s *settings.Settings) (intf.Playback, error) { - return load.IT(filename, s) +func (f format) Load(filename string, s *settings.Settings) (playback.Playback, error) { + r, err := util.ReadFile(filename) + if err != nil { + return nil, err + } + + return f.LoadFromReader(r, s) +} + +// LoadFromReader loads an IT file on a reader into a playback system +func (f format) LoadFromReader(r io.Reader, s *settings.Settings) (playback.Playback, error) { + return load.IT(r, s) } diff --git a/format/it/layout/channelsetting.go b/format/it/layout/channelsetting.go new file mode 100644 index 0000000..925128e --- /dev/null +++ b/format/it/layout/channelsetting.go @@ -0,0 +1,17 @@ +package layout + +import ( + "github.com/gotracker/gomixing/panning" + "github.com/gotracker/gomixing/volume" + "github.com/gotracker/playback/format/it/channel" +) + +// ChannelSetting is settings specific to a single channel +type ChannelSetting struct { + Enabled bool + OutputChannelNum int + InitialVolume volume.Volume + ChannelVolume volume.Volume + InitialPanning panning.Position + Memory channel.Memory +} diff --git a/format/it/layout/header.go b/format/it/layout/header.go new file mode 100644 index 0000000..57b70d4 --- /dev/null +++ b/format/it/layout/header.go @@ -0,0 +1,12 @@ +package layout + +import "github.com/gotracker/gomixing/volume" + +// Header is a mildly-decoded IT header definition +type Header struct { + Name string + InitialSpeed int + InitialTempo int + GlobalVolume volume.Volume + MixingVolume volume.Volume +} diff --git a/format/it/layout/noteinstrument.go b/format/it/layout/noteinstrument.go new file mode 100644 index 0000000..00b82bd --- /dev/null +++ b/format/it/layout/noteinstrument.go @@ -0,0 +1,12 @@ +package layout + +import ( + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" +) + +// NoteInstrument is the note remapping and instrument pair +type NoteInstrument struct { + NoteRemap note.Semitone + Inst *instrument.Instrument +} diff --git a/format/it/layout/it.go b/format/it/layout/song.go similarity index 56% rename from format/it/layout/it.go rename to format/it/layout/song.go index 55a2a7d..1b8e247 100644 --- a/format/it/layout/it.go +++ b/format/it/layout/song.go @@ -1,43 +1,15 @@ package layout import ( - "github.com/gotracker/gomixing/panning" - "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/filter" - "github.com/gotracker/playback/format/it/layout/channel" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" + "github.com/gotracker/playback/pattern" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" - "github.com/gotracker/playback/song/pattern" ) -// Header is a mildly-decoded XM header definition -type Header struct { - Name string - InitialSpeed int - InitialTempo int - GlobalVolume volume.Volume - MixingVolume volume.Volume -} - -// ChannelSetting is settings specific to a single channel -type ChannelSetting struct { - Enabled bool - OutputChannelNum int - InitialVolume volume.Volume - ChannelVolume volume.Volume - InitialPanning panning.Position - Memory channel.Memory -} - -// NoteInstrument is the note remapping and instrument pair -type NoteInstrument struct { - NoteRemap note.Semitone - Inst *instrument.Instrument -} - // Song is the full definition of the song data of an Song file type Song struct { Head Header @@ -50,12 +22,12 @@ type Song struct { } // GetOrderList returns the list of all pattern orders for the song -func (s *Song) GetOrderList() []index.Pattern { +func (s Song) GetOrderList() []index.Pattern { return s.OrderList } // GetPattern returns an interface to a specific pattern indexed by `patNum` -func (s *Song) GetPattern(patNum index.Pattern) song.Pattern[channel.Data] { +func (s Song) GetPattern(patNum index.Pattern) song.Pattern[channel.Data] { if int(patNum) >= len(s.Patterns) { return nil } @@ -63,22 +35,22 @@ func (s *Song) GetPattern(patNum index.Pattern) song.Pattern[channel.Data] { } // IsChannelEnabled returns true if the channel at index `channelNum` is enabled -func (s *Song) IsChannelEnabled(channelNum int) bool { +func (s Song) IsChannelEnabled(channelNum int) bool { return s.ChannelSettings[channelNum].Enabled } // GetOutputChannel returns the output channel for the channel at index `channelNum` -func (s *Song) GetOutputChannel(channelNum int) int { +func (s Song) GetOutputChannel(channelNum int) int { return s.ChannelSettings[channelNum].OutputChannelNum } // NumInstruments returns the number of instruments in the song -func (s *Song) NumInstruments() int { +func (s Song) NumInstruments() int { return len(s.Instruments) } // IsValidInstrumentID returns true if the instrument exists -func (s *Song) IsValidInstrumentID(instNum instrument.ID) bool { +func (s Song) IsValidInstrumentID(instNum instrument.ID) bool { if instNum.IsEmpty() { return false } @@ -91,7 +63,7 @@ func (s *Song) IsValidInstrumentID(instNum instrument.ID) bool { } // GetInstrument returns the instrument interface indexed by `instNum` (0-based) -func (s *Song) GetInstrument(instNum instrument.ID) (*instrument.Instrument, note.Semitone) { +func (s Song) GetInstrument(instNum instrument.ID) (*instrument.Instrument, note.Semitone) { if instNum.IsEmpty() { return nil, note.UnchangedSemitone } @@ -107,6 +79,6 @@ func (s *Song) GetInstrument(instNum instrument.ID) (*instrument.Instrument, not } // GetName returns the name of the song -func (s *Song) GetName() string { +func (s Song) GetName() string { return s.Head.Name } diff --git a/format/it/load/formatutils.go b/format/it/load/formatutils.go deleted file mode 100644 index 707779a..0000000 --- a/format/it/load/formatutils.go +++ /dev/null @@ -1,20 +0,0 @@ -package load - -import ( - "github.com/gotracker/playback/format/it/layout" - "github.com/gotracker/playback/format/it/playback" - "github.com/gotracker/playback/format/settings" -) - -type readerFunc func(filename string, s *settings.Settings) (*layout.Song, error) - -func load(filename string, reader readerFunc, s *settings.Settings) (*playback.Manager, error) { - itSong, err := reader(filename, s) - if err != nil { - return nil, err - } - - m, err := playback.NewManager(itSong) - - return m, err -} diff --git a/format/it/load/instrument.go b/format/it/load/instrument.go index 5423b97..52dddb9 100644 --- a/format/it/load/instrument.go +++ b/format/it/load/instrument.go @@ -19,12 +19,12 @@ import ( "github.com/gotracker/voice/period" "github.com/gotracker/playback/filter" - itNote "github.com/gotracker/playback/format/it/conversion/note" + itNote "github.com/gotracker/playback/format/it/note" itfilter "github.com/gotracker/playback/format/it/playback/filter" - "github.com/gotracker/playback/format/settings" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" oscillatorImpl "github.com/gotracker/playback/oscillator" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/settings" ) type convInst struct { diff --git a/format/it/load/itformat.go b/format/it/load/itformat.go index 8cc5e49..36e08a1 100644 --- a/format/it/load/itformat.go +++ b/format/it/load/itformat.go @@ -5,6 +5,7 @@ import ( "encoding/binary" "errors" "fmt" + "io" "strconv" itfile "github.com/gotracker/goaudiofile/music/tracked/it" @@ -12,16 +13,14 @@ import ( "github.com/gotracker/gomixing/volume" "github.com/gotracker/playback/filter" - fmtfilter "github.com/gotracker/playback/format/internal/filter" - formatutil "github.com/gotracker/playback/format/internal/util" - itPanning "github.com/gotracker/playback/format/it/conversion/panning" + "github.com/gotracker/playback/format/it/channel" "github.com/gotracker/playback/format/it/layout" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/format/settings" - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" - "github.com/gotracker/playback/song/pattern" + itPanning "github.com/gotracker/playback/format/it/panning" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" + "github.com/gotracker/playback/pattern" + "github.com/gotracker/playback/settings" ) func moduleHeaderToHeader(fh *itfile.ModuleHeader) (*layout.Header, error) { @@ -204,7 +203,7 @@ func decodeFilter(f *itblock.FX) (filter.Factory, error) { switch { case lib == "Echo" && name == "Echo": r := bytes.NewReader(f.Data) - e := fmtfilter.EchoFilterFactory{} + e := filter.EchoFilterFactory{} if err := binary.Read(r, binary.LittleEndian, &e); err != nil { return nil, err } @@ -246,13 +245,8 @@ func addSampleWithNoteMapToSong(song *layout.Song, sample *instrument.Instrument } } -func readIT(filename string, s *settings.Settings) (*layout.Song, error) { - buffer, err := formatutil.ReadFile(filename) - if err != nil { - return nil, err - } - - f, err := itfile.Read(buffer) +func readIT(r io.Reader, s *settings.Settings) (*layout.Song, error) { + f, err := itfile.Read(r) if err != nil { return nil, err } diff --git a/format/it/load/load.go b/format/it/load/load.go index f5ea263..a97c6c7 100644 --- a/format/it/load/load.go +++ b/format/it/load/load.go @@ -1,11 +1,15 @@ package load import ( - "github.com/gotracker/playback/format/settings" - "github.com/gotracker/playback/player/intf" + "io" + + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/common" + itPlayback "github.com/gotracker/playback/format/it/playback" + "github.com/gotracker/playback/settings" ) -// IT loads an IT file -func IT(filename string, s *settings.Settings) (intf.Playback, error) { - return load(filename, readIT, s) +// IT loads an IT file from a reader +func IT(r io.Reader, s *settings.Settings) (playback.Playback, error) { + return common.Load(r, readIT, itPlayback.NewManager, s) } diff --git a/format/it/conversion/note/note.go b/format/it/note/note.go similarity index 91% rename from format/it/conversion/note/note.go rename to format/it/note/note.go index 27c5ecc..3a99598 100644 --- a/format/it/conversion/note/note.go +++ b/format/it/note/note.go @@ -3,7 +3,7 @@ package note import ( itfile "github.com/gotracker/goaudiofile/music/tracked/it" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" ) // FromItNote converts an it file note into a player note diff --git a/format/it/conversion/panning/panning.go b/format/it/panning/panning.go similarity index 100% rename from format/it/conversion/panning/panning.go rename to format/it/panning/panning.go diff --git a/format/it/conversion/period/amiga.go b/format/it/period/amiga.go similarity index 95% rename from format/it/conversion/period/amiga.go rename to format/it/period/amiga.go index 69800c7..bcb6bb4 100644 --- a/format/it/conversion/period/amiga.go +++ b/format/it/period/amiga.go @@ -4,8 +4,8 @@ import ( "fmt" "math" - per "github.com/gotracker/playback/format/internal/period" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" + per "github.com/gotracker/playback/period" "github.com/heucuva/comparison" "github.com/gotracker/voice/period" diff --git a/format/it/conversion/period/linear.go b/format/it/period/linear.go similarity index 98% rename from format/it/conversion/period/linear.go rename to format/it/period/linear.go index ca22c4f..5421167 100644 --- a/format/it/conversion/period/linear.go +++ b/format/it/period/linear.go @@ -4,7 +4,7 @@ import ( "fmt" "math" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" "github.com/heucuva/comparison" "github.com/gotracker/voice/period" diff --git a/format/it/conversion/period/util.go b/format/it/period/util.go similarity index 98% rename from format/it/conversion/period/util.go rename to format/it/period/util.go index 99f7d66..3642f95 100644 --- a/format/it/conversion/period/util.go +++ b/format/it/period/util.go @@ -1,7 +1,7 @@ package period import ( - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" "github.com/gotracker/voice/period" ) diff --git a/format/it/playback/channeldata_transaction.go b/format/it/playback/channeldata_transaction.go index 43f921a..e387c61 100644 --- a/format/it/playback/channeldata_transaction.go +++ b/format/it/playback/channeldata_transaction.go @@ -3,12 +3,12 @@ package playback import ( "github.com/gotracker/gomixing/sampling" "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/format/it/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" "github.com/gotracker/playback/format/it/playback/effect" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback/note" "github.com/gotracker/playback/player/state" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/note" ) type channelDataConverter struct{} @@ -92,14 +92,14 @@ type channelDataTransaction struct { state.ChannelDataTxnHelper[channel.Memory, channel.Data, channelDataConverter] } -func (d *channelDataTransaction) CommitPreRow(p intf.Playback, cs *state.ChannelState[channel.Memory, channel.Data], semitoneSetterFactory state.SemitoneSetterFactory[channel.Memory, channel.Data]) error { +func (d *channelDataTransaction) CommitPreRow(p playback.Playback, cs *state.ChannelState[channel.Memory, channel.Data], semitoneSetterFactory state.SemitoneSetterFactory[channel.Memory, channel.Data]) error { e := effect.Factory(cs.GetMemory(), d.Data) cs.SetActiveEffect(e) if e != nil { if onEff := p.GetOnEffect(); onEff != nil { onEff(e) } - if err := intf.EffectPreStart[channel.Memory, channel.Data](e, cs, p); err != nil { + if err := playback.EffectPreStart[channel.Memory, channel.Data](e, cs, p); err != nil { return err } } @@ -107,7 +107,7 @@ func (d *channelDataTransaction) CommitPreRow(p intf.Playback, cs *state.Channel return nil } -func (d *channelDataTransaction) CommitRow(p intf.Playback, cs *state.ChannelState[channel.Memory, channel.Data], semitoneSetterFactory state.SemitoneSetterFactory[channel.Memory, channel.Data]) error { +func (d *channelDataTransaction) CommitRow(p playback.Playback, cs *state.ChannelState[channel.Memory, channel.Data], semitoneSetterFactory state.SemitoneSetterFactory[channel.Memory, channel.Data]) error { if pos, ok := d.TargetPos.Get(); ok { cs.SetTargetPos(pos) } diff --git a/format/it/playback/effect/effect_arpeggio.go b/format/it/playback/effect/effect_arpeggio.go index f680ccb..b877d45 100644 --- a/format/it/playback/effect/effect_arpeggio.go +++ b/format/it/playback/effect/effect_arpeggio.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // Arpeggio defines an arpeggio effect type Arpeggio channel.DataEffect // 'J' // Start triggers on the first tick, but before the Tick() function is called -func (e Arpeggio) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e Arpeggio) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() cs.SetPos(cs.GetTargetPos()) @@ -19,7 +19,7 @@ func (e Arpeggio) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Pl } // Tick is called on every tick -func (e Arpeggio) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e Arpeggio) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.Arpeggio(channel.DataEffect(e)) return doArpeggio(cs, currentTick, int8(x), int8(y)) diff --git a/format/it/playback/effect/effect_channelvolumeslide.go b/format/it/playback/effect/effect_channelvolumeslide.go index 421af53..f3a815a 100644 --- a/format/it/playback/effect/effect_channelvolumeslide.go +++ b/format/it/playback/effect/effect_channelvolumeslide.go @@ -5,15 +5,15 @@ import ( "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // ChannelVolumeSlide defines a set channel volume effect type ChannelVolumeSlide channel.DataEffect // 'Nxy' // Start triggers on the first tick, but before the Tick() function is called -func (e ChannelVolumeSlide) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e ChannelVolumeSlide) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() mem := cs.GetMemory() @@ -39,7 +39,7 @@ func (e ChannelVolumeSlide) Start(cs intf.Channel[channel.Memory, channel.Data], } // Tick is called on every tick -func (e ChannelVolumeSlide) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e ChannelVolumeSlide) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.ChannelVolumeSlide(channel.DataEffect(e)) diff --git a/format/it/playback/effect/effect_extrafineportadown.go b/format/it/playback/effect/effect_extrafineportadown.go index 822dd54..99d6582 100644 --- a/format/it/playback/effect/effect_extrafineportadown.go +++ b/format/it/playback/effect/effect_extrafineportadown.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // ExtraFinePortaDown defines an extra-fine portamento down effect type ExtraFinePortaDown channel.DataEffect // 'EEx' // Start triggers on the first tick, but before the Tick() function is called -func (e ExtraFinePortaDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e ExtraFinePortaDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() diff --git a/format/it/playback/effect/effect_extrafineportaup.go b/format/it/playback/effect/effect_extrafineportaup.go index 47458a2..ff36996 100644 --- a/format/it/playback/effect/effect_extrafineportaup.go +++ b/format/it/playback/effect/effect_extrafineportaup.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // ExtraFinePortaUp defines an extra-fine portamento up effect type ExtraFinePortaUp channel.DataEffect // 'FEx' // Start triggers on the first tick, but before the Tick() function is called -func (e ExtraFinePortaUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e ExtraFinePortaUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() diff --git a/format/it/playback/effect/effect_finepatterndelay.go b/format/it/playback/effect/effect_finepatterndelay.go index 04d39ce..b8855e4 100644 --- a/format/it/playback/effect/effect_finepatterndelay.go +++ b/format/it/playback/effect/effect_finepatterndelay.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" effectIntf "github.com/gotracker/playback/format/it/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // FinePatternDelay defines an fine pattern delay effect type FinePatternDelay channel.DataEffect // 'S6x' // Start triggers on the first tick, but before the Tick() function is called -func (e FinePatternDelay) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FinePatternDelay) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := channel.DataEffect(e) & 0xf diff --git a/format/it/playback/effect/effect_fineportadown.go b/format/it/playback/effect/effect_fineportadown.go index a141f9f..2ac702d 100644 --- a/format/it/playback/effect/effect_fineportadown.go +++ b/format/it/playback/effect/effect_fineportadown.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // FinePortaDown defines an fine portamento down effect type FinePortaDown channel.DataEffect // 'EFx' // Start triggers on the first tick, but before the Tick() function is called -func (e FinePortaDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FinePortaDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() diff --git a/format/it/playback/effect/effect_fineportaup.go b/format/it/playback/effect/effect_fineportaup.go index 6a1d8b8..73df0a2 100644 --- a/format/it/playback/effect/effect_fineportaup.go +++ b/format/it/playback/effect/effect_fineportaup.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // FinePortaUp defines an fine portamento up effect type FinePortaUp channel.DataEffect // 'FFx' // Start triggers on the first tick, but before the Tick() function is called -func (e FinePortaUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FinePortaUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() diff --git a/format/it/playback/effect/effect_finevibrato.go b/format/it/playback/effect/effect_finevibrato.go index 8348255..7673b4b 100644 --- a/format/it/playback/effect/effect_finevibrato.go +++ b/format/it/playback/effect/effect_finevibrato.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // FineVibrato defines an fine vibrato effect type FineVibrato channel.DataEffect // 'U' // Start triggers on the first tick, but before the Tick() function is called -func (e FineVibrato) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FineVibrato) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() return nil } // Tick is called on every tick -func (e FineVibrato) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e FineVibrato) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.Vibrato(channel.DataEffect(e)) if currentTick != 0 { diff --git a/format/it/playback/effect/effect_finevolslidedown.go b/format/it/playback/effect/effect_finevolslidedown.go index 4978116..dff0e00 100644 --- a/format/it/playback/effect/effect_finevolslidedown.go +++ b/format/it/playback/effect/effect_finevolslidedown.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // FineVolumeSlideDown defines a fine volume slide down effect type FineVolumeSlideDown channel.DataEffect // 'D' // Start triggers on the first tick, but before the Tick() function is called -func (e FineVolumeSlideDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FineVolumeSlideDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e FineVolumeSlideDown) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e FineVolumeSlideDown) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() _, y := mem.VolumeSlide(channel.DataEffect(e)) @@ -37,7 +37,7 @@ func (e FineVolumeSlideDown) String() string { type VolChanFineVolumeSlideDown channel.DataEffect // 'd' // Start triggers on the first tick, but before the Tick() function is called -func (e VolChanFineVolumeSlideDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e VolChanFineVolumeSlideDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { mem := cs.GetMemory() y := mem.VolChanVolumeSlide(channel.DataEffect(e)) diff --git a/format/it/playback/effect/effect_finevolslideup.go b/format/it/playback/effect/effect_finevolslideup.go index 39d3f59..f18c795 100644 --- a/format/it/playback/effect/effect_finevolslideup.go +++ b/format/it/playback/effect/effect_finevolslideup.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // FineVolumeSlideUp defines a fine volume slide up effect type FineVolumeSlideUp channel.DataEffect // 'D' // Start triggers on the first tick, but before the Tick() function is called -func (e FineVolumeSlideUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FineVolumeSlideUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e FineVolumeSlideUp) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e FineVolumeSlideUp) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, _ := mem.VolumeSlide(channel.DataEffect(e)) @@ -37,7 +37,7 @@ func (e FineVolumeSlideUp) String() string { type VolChanFineVolumeSlideUp channel.DataEffect // 'd' // Start triggers on the first tick, but before the Tick() function is called -func (e VolChanFineVolumeSlideUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e VolChanFineVolumeSlideUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { mem := cs.GetMemory() x := mem.VolChanVolumeSlide(channel.DataEffect(e)) diff --git a/format/it/playback/effect/effect_globalvolumeslide.go b/format/it/playback/effect/effect_globalvolumeslide.go index 5f9415f..1a984dc 100644 --- a/format/it/playback/effect/effect_globalvolumeslide.go +++ b/format/it/playback/effect/effect_globalvolumeslide.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" effectIntf "github.com/gotracker/playback/format/it/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // GlobalVolumeSlide defines a global volume slide effect type GlobalVolumeSlide channel.DataEffect // 'W' // Start triggers on the first tick, but before the Tick() function is called -func (e GlobalVolumeSlide) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e GlobalVolumeSlide) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e GlobalVolumeSlide) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e GlobalVolumeSlide) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.GlobalVolumeSlide(channel.DataEffect(e)) diff --git a/format/it/playback/effect/effect_highoffset.go b/format/it/playback/effect/effect_highoffset.go index 2d7e7d3..912a23c 100644 --- a/format/it/playback/effect/effect_highoffset.go +++ b/format/it/playback/effect/effect_highoffset.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // HighOffset defines a sample high offset effect type HighOffset channel.DataEffect // 'SAx' // Start triggers on the first tick, but before the Tick() function is called -func (e HighOffset) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e HighOffset) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() mem := cs.GetMemory() diff --git a/format/it/playback/effect/effect_newnoteactionnotecontinue.go b/format/it/playback/effect/effect_newnoteactionnotecontinue.go index 6c9c8a1..aa84905 100644 --- a/format/it/playback/effect/effect_newnoteactionnotecontinue.go +++ b/format/it/playback/effect/effect_newnoteactionnotecontinue.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/note" ) // NewNoteActionNoteContinue defines a NewNoteAction: Note Continue effect type NewNoteActionNoteContinue channel.DataEffect // 'S74' // Start triggers on the first tick, but before the Tick() function is called -func (e NewNoteActionNoteContinue) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e NewNoteActionNoteContinue) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.SetNewNoteAction(note.ActionContinue) return nil } diff --git a/format/it/playback/effect/effect_newnoteactionnotecut.go b/format/it/playback/effect/effect_newnoteactionnotecut.go index 2d0a0fd..03e39f7 100644 --- a/format/it/playback/effect/effect_newnoteactionnotecut.go +++ b/format/it/playback/effect/effect_newnoteactionnotecut.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/note" ) // NewNoteActionNoteCut defines a NewNoteAction: Note Cut effect type NewNoteActionNoteCut channel.DataEffect // 'S73' // Start triggers on the first tick, but before the Tick() function is called -func (e NewNoteActionNoteCut) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e NewNoteActionNoteCut) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.SetNewNoteAction(note.ActionCut) return nil } diff --git a/format/it/playback/effect/effect_newnoteactionnotefade.go b/format/it/playback/effect/effect_newnoteactionnotefade.go index 0d32661..d6cff6a 100644 --- a/format/it/playback/effect/effect_newnoteactionnotefade.go +++ b/format/it/playback/effect/effect_newnoteactionnotefade.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/note" ) // NewNoteActionNoteFade defines a NewNoteAction: Note Fade effect type NewNoteActionNoteFade channel.DataEffect // 'S76' // Start triggers on the first tick, but before the Tick() function is called -func (e NewNoteActionNoteFade) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e NewNoteActionNoteFade) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.SetNewNoteAction(note.ActionFadeout) return nil } diff --git a/format/it/playback/effect/effect_newnoteactionnoteoff.go b/format/it/playback/effect/effect_newnoteactionnoteoff.go index d488b70..9899615 100644 --- a/format/it/playback/effect/effect_newnoteactionnoteoff.go +++ b/format/it/playback/effect/effect_newnoteactionnoteoff.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/note" ) // NewNoteActionNoteOff defines a NewNoteAction: Note Off effect type NewNoteActionNoteOff channel.DataEffect // 'S75' // Start triggers on the first tick, but before the Tick() function is called -func (e NewNoteActionNoteOff) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e NewNoteActionNoteOff) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.SetNewNoteAction(note.ActionRelease) return nil } diff --git a/format/it/playback/effect/effect_notecut.go b/format/it/playback/effect/effect_notecut.go index 7e53a58..5e02c82 100644 --- a/format/it/playback/effect/effect_notecut.go +++ b/format/it/playback/effect/effect_notecut.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // NoteCut defines a note cut effect type NoteCut channel.DataEffect // 'SCx' // Start triggers on the first tick, but before the Tick() function is called -func (e NoteCut) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e NoteCut) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e NoteCut) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e NoteCut) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { x := channel.DataEffect(e) & 0xf if x != 0 && currentTick == int(x) { diff --git a/format/it/playback/effect/effect_notedelay.go b/format/it/playback/effect/effect_notedelay.go index 9da9416..34aae9e 100644 --- a/format/it/playback/effect/effect_notedelay.go +++ b/format/it/playback/effect/effect_notedelay.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/note" ) // NoteDelay defines a note delay effect type NoteDelay channel.DataEffect // 'SDx' // PreStart triggers when the effect enters onto the channel state -func (e NoteDelay) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e NoteDelay) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.SetNotePlayTick(true, note.ActionRetrigger, int(channel.DataEffect(e)&0x0F)) return nil } // Start triggers on the first tick, but before the Tick() function is called -func (e NoteDelay) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e NoteDelay) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/it/playback/effect/effect_orderjump.go b/format/it/playback/effect/effect_orderjump.go index e6771cc..6188862 100644 --- a/format/it/playback/effect/effect_orderjump.go +++ b/format/it/playback/effect/effect_orderjump.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/index" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/index" ) // OrderJump defines an order jump effect type OrderJump channel.DataEffect // 'B' // Start triggers on the first tick, but before the Tick() function is called -func (e OrderJump) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e OrderJump) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Stop is called on the last tick of the row, but after the Tick() function is called -func (e OrderJump) Stop(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, lastTick int) error { +func (e OrderJump) Stop(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, lastTick int) error { return p.SetNextOrder(index.Order(e)) } diff --git a/format/it/playback/effect/effect_panningenvelopeoff.go b/format/it/playback/effect/effect_panningenvelopeoff.go index a22ebb2..f43b14b 100644 --- a/format/it/playback/effect/effect_panningenvelopeoff.go +++ b/format/it/playback/effect/effect_panningenvelopeoff.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // PanningEnvelopeOff defines a panning envelope: off effect type PanningEnvelopeOff channel.DataEffect // 'S79' // Start triggers on the first tick, but before the Tick() function is called -func (e PanningEnvelopeOff) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PanningEnvelopeOff) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.SetPanningEnvelopeEnable(false) diff --git a/format/it/playback/effect/effect_panningenvelopeon.go b/format/it/playback/effect/effect_panningenvelopeon.go index 9aefaed..99dc7a6 100644 --- a/format/it/playback/effect/effect_panningenvelopeon.go +++ b/format/it/playback/effect/effect_panningenvelopeon.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // PanningEnvelopeOn defines a panning envelope: on effect type PanningEnvelopeOn channel.DataEffect // 'S7A' // Start triggers on the first tick, but before the Tick() function is called -func (e PanningEnvelopeOn) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PanningEnvelopeOn) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.SetPanningEnvelopeEnable(true) diff --git a/format/it/playback/effect/effect_pastnotecut.go b/format/it/playback/effect/effect_pastnotecut.go index d016cc0..7f1202f 100644 --- a/format/it/playback/effect/effect_pastnotecut.go +++ b/format/it/playback/effect/effect_pastnotecut.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/note" ) // PastNoteCut defines a past note cut effect type PastNoteCut channel.DataEffect // 'S70' // Start triggers on the first tick, but before the Tick() function is called -func (e PastNoteCut) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PastNoteCut) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.DoPastNoteEffect(note.ActionCut) return nil } diff --git a/format/it/playback/effect/effect_pastnotefadeout.go b/format/it/playback/effect/effect_pastnotefadeout.go index f9a117a..4272248 100644 --- a/format/it/playback/effect/effect_pastnotefadeout.go +++ b/format/it/playback/effect/effect_pastnotefadeout.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/note" ) // PastNoteFade defines a past note fadeout effect type PastNoteFade channel.DataEffect // 'S72' // Start triggers on the first tick, but before the Tick() function is called -func (e PastNoteFade) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PastNoteFade) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.DoPastNoteEffect(note.ActionFadeout) return nil } diff --git a/format/it/playback/effect/effect_pastnoteoff.go b/format/it/playback/effect/effect_pastnoteoff.go index b13c3ce..da0bdb1 100644 --- a/format/it/playback/effect/effect_pastnoteoff.go +++ b/format/it/playback/effect/effect_pastnoteoff.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/note" ) // PastNoteOff defines a past note off effect type PastNoteOff channel.DataEffect // 'S71' // Start triggers on the first tick, but before the Tick() function is called -func (e PastNoteOff) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PastNoteOff) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.DoPastNoteEffect(note.ActionRelease) return nil } diff --git a/format/it/playback/effect/effect_patterndelay.go b/format/it/playback/effect/effect_patterndelay.go index 8717882..1a21346 100644 --- a/format/it/playback/effect/effect_patterndelay.go +++ b/format/it/playback/effect/effect_patterndelay.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" effectIntf "github.com/gotracker/playback/format/it/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // PatternDelay defines a pattern delay effect type PatternDelay channel.DataEffect // 'SEx' // PreStart triggers when the effect enters onto the channel state -func (e PatternDelay) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PatternDelay) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { m := p.(effectIntf.IT) return m.SetPatternDelay(int(channel.DataEffect(e) & 0x0F)) } // Start triggers on the first tick, but before the Tick() function is called -func (e PatternDelay) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PatternDelay) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/it/playback/effect/effect_patternloop.go b/format/it/playback/effect/effect_patternloop.go index cab0730..dd5d1a4 100644 --- a/format/it/playback/effect/effect_patternloop.go +++ b/format/it/playback/effect/effect_patternloop.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // PatternLoop defines a pattern loop effect type PatternLoop channel.DataEffect // 'SBx' // Start triggers on the first tick, but before the Tick() function is called -func (e PatternLoop) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PatternLoop) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Stop is called on the last tick of the row, but after the Tick() function is called -func (e PatternLoop) Stop(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, lastTick int) error { +func (e PatternLoop) Stop(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, lastTick int) error { x := uint8(e) & 0xF mem := cs.GetMemory() diff --git a/format/it/playback/effect/effect_pitchenvelopeoff.go b/format/it/playback/effect/effect_pitchenvelopeoff.go index f076fb1..0a269a7 100644 --- a/format/it/playback/effect/effect_pitchenvelopeoff.go +++ b/format/it/playback/effect/effect_pitchenvelopeoff.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // PitchEnvelopeOff defines a panning envelope: off effect type PitchEnvelopeOff channel.DataEffect // 'S7B' // Start triggers on the first tick, but before the Tick() function is called -func (e PitchEnvelopeOff) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PitchEnvelopeOff) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.SetPitchEnvelopeEnable(false) diff --git a/format/it/playback/effect/effect_pitchenvelopeon.go b/format/it/playback/effect/effect_pitchenvelopeon.go index 89ca7ea..0131a82 100644 --- a/format/it/playback/effect/effect_pitchenvelopeon.go +++ b/format/it/playback/effect/effect_pitchenvelopeon.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // PitchEnvelopeOn defines a panning envelope: on effect type PitchEnvelopeOn channel.DataEffect // 'S7C' // Start triggers on the first tick, but before the Tick() function is called -func (e PitchEnvelopeOn) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PitchEnvelopeOn) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.SetPitchEnvelopeEnable(true) diff --git a/format/it/playback/effect/effect_portadown.go b/format/it/playback/effect/effect_portadown.go index b522d94..10bdf2b 100644 --- a/format/it/playback/effect/effect_portadown.go +++ b/format/it/playback/effect/effect_portadown.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // PortaDown defines a portamento down effect type PortaDown channel.DataEffect // 'E' // Start triggers on the first tick, but before the Tick() function is called -func (e PortaDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PortaDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() return nil } // Tick is called on every tick -func (e PortaDown) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e PortaDown) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() xx := mem.PortaDown(channel.DataEffect(e)) diff --git a/format/it/playback/effect/effect_portatonote.go b/format/it/playback/effect/effect_portatonote.go index 32cb94e..89733d9 100644 --- a/format/it/playback/effect/effect_portatonote.go +++ b/format/it/playback/effect/effect_portatonote.go @@ -3,9 +3,9 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/note" "github.com/heucuva/comparison" ) @@ -13,7 +13,7 @@ import ( type PortaToNote channel.DataEffect // 'G' // Start triggers on the first tick, but before the Tick() function is called -func (e PortaToNote) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PortaToNote) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() if cmd := cs.GetData(); cmd != nil && cmd.HasNote() { @@ -24,7 +24,7 @@ func (e PortaToNote) Start(cs intf.Channel[channel.Memory, channel.Data], p intf } // Tick is called on every tick -func (e PortaToNote) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e PortaToNote) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() xx := mem.PortaToNote(channel.DataEffect(e)) diff --git a/format/it/playback/effect/effect_portaup.go b/format/it/playback/effect/effect_portaup.go index 05bbc3a..7a1fbdf 100644 --- a/format/it/playback/effect/effect_portaup.go +++ b/format/it/playback/effect/effect_portaup.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // PortaUp defines a portamento up effect type PortaUp channel.DataEffect // 'F' // Start triggers on the first tick, but before the Tick() function is called -func (e PortaUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PortaUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() return nil } // Tick is called on every tick -func (e PortaUp) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e PortaUp) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() xx := mem.PortaUp(channel.DataEffect(e)) diff --git a/format/it/playback/effect/effect_portavolslide.go b/format/it/playback/effect/effect_portavolslide.go index afe81a6..37b7576 100644 --- a/format/it/playback/effect/effect_portavolslide.go +++ b/format/it/playback/effect/effect_portavolslide.go @@ -3,13 +3,13 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // PortaVolumeSlide defines a portamento-to-note combined with a volume slide effect type PortaVolumeSlide struct { // 'L' - intf.CombinedEffect[channel.Memory, channel.Data] + playback.CombinedEffect[channel.Memory, channel.Data] } // NewPortaVolumeSlide creates a new PortaVolumeSlide object diff --git a/format/it/playback/effect/effect_retrigvolslide.go b/format/it/playback/effect/effect_retrigvolslide.go index c99ca74..ac82f73 100644 --- a/format/it/playback/effect/effect_retrigvolslide.go +++ b/format/it/playback/effect/effect_retrigvolslide.go @@ -5,21 +5,21 @@ import ( "github.com/gotracker/gomixing/sampling" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // RetrigVolumeSlide defines a retriggering volume slide effect type RetrigVolumeSlide channel.DataEffect // 'Q' // Start triggers on the first tick, but before the Tick() function is called -func (e RetrigVolumeSlide) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e RetrigVolumeSlide) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e RetrigVolumeSlide) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e RetrigVolumeSlide) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.RetrigVolumeSlide(channel.DataEffect(e)) if y == 0 { diff --git a/format/it/playback/effect/effect_rowjump.go b/format/it/playback/effect/effect_rowjump.go index 0d188df..eb0cfc6 100644 --- a/format/it/playback/effect/effect_rowjump.go +++ b/format/it/playback/effect/effect_rowjump.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/index" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/index" ) // RowJump defines a row jump effect type RowJump channel.DataEffect // 'C' // Start triggers on the first tick, but before the Tick() function is called -func (e RowJump) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e RowJump) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Stop is called on the last tick of the row, but after the Tick() function is called -func (e RowJump) Stop(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, lastTick int) error { +func (e RowJump) Stop(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, lastTick int) error { r := channel.DataEffect(e) rowIdx := index.Row(r) return p.SetNextRow(rowIdx) diff --git a/format/it/playback/effect/effect_sampleoffset.go b/format/it/playback/effect/effect_sampleoffset.go index a264bbc..ae5733f 100644 --- a/format/it/playback/effect/effect_sampleoffset.go +++ b/format/it/playback/effect/effect_sampleoffset.go @@ -5,15 +5,15 @@ import ( "github.com/gotracker/gomixing/sampling" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // SampleOffset defines a sample offset effect type SampleOffset channel.DataEffect // 'O' // Start triggers on the first tick, but before the Tick() function is called -func (e SampleOffset) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SampleOffset) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() mem := cs.GetMemory() xx := mem.SampleOffset(channel.DataEffect(e)) diff --git a/format/it/playback/effect/effect_setchannelvolume.go b/format/it/playback/effect/effect_setchannelvolume.go index 38b4f22..1427c23 100644 --- a/format/it/playback/effect/effect_setchannelvolume.go +++ b/format/it/playback/effect/effect_setchannelvolume.go @@ -6,15 +6,15 @@ import ( itfile "github.com/gotracker/goaudiofile/music/tracked/it" "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // SetChannelVolume defines a set channel volume effect type SetChannelVolume channel.DataEffect // 'Mxx' // Start triggers on the first tick, but before the Tick() function is called -func (e SetChannelVolume) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetChannelVolume) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() xx := channel.DataEffect(e) diff --git a/format/it/playback/effect/effect_setcoarsepanposition.go b/format/it/playback/effect/effect_setcoarsepanposition.go index 3afc737..f283ff2 100644 --- a/format/it/playback/effect/effect_setcoarsepanposition.go +++ b/format/it/playback/effect/effect_setcoarsepanposition.go @@ -5,16 +5,16 @@ import ( itfile "github.com/gotracker/goaudiofile/music/tracked/it" - itPanning "github.com/gotracker/playback/format/it/conversion/panning" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + itPanning "github.com/gotracker/playback/format/it/panning" ) // SetCoarsePanPosition defines a set coarse pan position effect type SetCoarsePanPosition channel.DataEffect // 'S8x' // Start triggers on the first tick, but before the Tick() function is called -func (e SetCoarsePanPosition) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetCoarsePanPosition) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := channel.DataEffect(e) & 0xf diff --git a/format/it/playback/effect/effect_setfinetune.go b/format/it/playback/effect/effect_setfinetune.go index 8f33e8c..3ce3790 100644 --- a/format/it/playback/effect/effect_setfinetune.go +++ b/format/it/playback/effect/effect_setfinetune.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/note" ) // SetFinetune defines a mod-style set finetune effect type SetFinetune channel.DataEffect // 'S2x' // PreStart triggers when the effect enters onto the channel state -func (e SetFinetune) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetFinetune) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { x := channel.DataEffect(e) & 0xf inst := cs.GetTargetInst() @@ -24,7 +24,7 @@ func (e SetFinetune) PreStart(cs intf.Channel[channel.Memory, channel.Data], p i } // Start triggers on the first tick, but before the Tick() function is called -func (e SetFinetune) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetFinetune) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/it/playback/effect/effect_setglobalvolume.go b/format/it/playback/effect/effect_setglobalvolume.go index cb17c73..81f413d 100644 --- a/format/it/playback/effect/effect_setglobalvolume.go +++ b/format/it/playback/effect/effect_setglobalvolume.go @@ -5,15 +5,15 @@ import ( "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // SetGlobalVolume defines a set global volume effect type SetGlobalVolume channel.DataEffect // 'V' // PreStart triggers when the effect enters onto the channel state -func (e SetGlobalVolume) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetGlobalVolume) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { v := volume.Volume(channel.DataEffect(e)) / 0x80 if v > 1 { v = 1 @@ -23,7 +23,7 @@ func (e SetGlobalVolume) PreStart(cs intf.Channel[channel.Memory, channel.Data], } // Start triggers on the first tick, but before the Tick() function is called -func (e SetGlobalVolume) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetGlobalVolume) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/it/playback/effect/effect_setpanbrellowaveform.go b/format/it/playback/effect/effect_setpanbrellowaveform.go index e8bbee2..6111daa 100644 --- a/format/it/playback/effect/effect_setpanbrellowaveform.go +++ b/format/it/playback/effect/effect_setpanbrellowaveform.go @@ -5,15 +5,15 @@ import ( "github.com/gotracker/voice/oscillator" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // SetPanbrelloWaveform defines a set panbrello waveform effect type SetPanbrelloWaveform channel.DataEffect // 'S5x' // Start triggers on the first tick, but before the Tick() function is called -func (e SetPanbrelloWaveform) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetPanbrelloWaveform) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := channel.DataEffect(e) & 0xf diff --git a/format/it/playback/effect/effect_setpanposition.go b/format/it/playback/effect/effect_setpanposition.go index b1c4c5c..db60a4d 100644 --- a/format/it/playback/effect/effect_setpanposition.go +++ b/format/it/playback/effect/effect_setpanposition.go @@ -5,16 +5,16 @@ import ( itfile "github.com/gotracker/goaudiofile/music/tracked/it" - itPanning "github.com/gotracker/playback/format/it/conversion/panning" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" + itPanning "github.com/gotracker/playback/format/it/panning" ) // SetPanPosition defines a set pan position effect type SetPanPosition channel.DataEffect // 'Xxx' // Start triggers on the first tick, but before the Tick() function is called -func (e SetPanPosition) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetPanPosition) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := channel.DataEffect(e) diff --git a/format/it/playback/effect/effect_setspeed.go b/format/it/playback/effect/effect_setspeed.go index 497ef2c..0a650e2 100644 --- a/format/it/playback/effect/effect_setspeed.go +++ b/format/it/playback/effect/effect_setspeed.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" effectIntf "github.com/gotracker/playback/format/it/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // SetSpeed defines a set speed effect type SetSpeed channel.DataEffect // 'A' // PreStart triggers when the effect enters onto the channel state -func (e SetSpeed) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetSpeed) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { if e != 0 { m := p.(effectIntf.IT) if err := m.SetTicks(int(e)); err != nil { @@ -23,7 +23,7 @@ func (e SetSpeed) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf } // Start triggers on the first tick, but before the Tick() function is called -func (e SetSpeed) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetSpeed) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/it/playback/effect/effect_settempo.go b/format/it/playback/effect/effect_settempo.go index 8130915..93d36ca 100644 --- a/format/it/playback/effect/effect_settempo.go +++ b/format/it/playback/effect/effect_settempo.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" effectIntf "github.com/gotracker/playback/format/it/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // SetTempo defines a set tempo effect type SetTempo channel.DataEffect // 'T' // PreStart triggers when the effect enters onto the channel state -func (e SetTempo) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetTempo) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { if e > 0x20 { m := p.(effectIntf.IT) if err := m.SetTempo(int(e)); err != nil { @@ -23,13 +23,13 @@ func (e SetTempo) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf } // Start triggers on the first tick, but before the Tick() function is called -func (e SetTempo) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetTempo) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e SetTempo) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e SetTempo) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { m := p.(effectIntf.IT) switch channel.DataEffect(e >> 4) { case 0: // decrease tempo diff --git a/format/it/playback/effect/effect_settremolowaveform.go b/format/it/playback/effect/effect_settremolowaveform.go index e41d6d3..10b8722 100644 --- a/format/it/playback/effect/effect_settremolowaveform.go +++ b/format/it/playback/effect/effect_settremolowaveform.go @@ -5,15 +5,15 @@ import ( "github.com/gotracker/voice/oscillator" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // SetTremoloWaveform defines a set tremolo waveform effect type SetTremoloWaveform channel.DataEffect // 'S4x' // Start triggers on the first tick, but before the Tick() function is called -func (e SetTremoloWaveform) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetTremoloWaveform) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := channel.DataEffect(e) & 0xf diff --git a/format/it/playback/effect/effect_setvibratowaveform.go b/format/it/playback/effect/effect_setvibratowaveform.go index 184965a..a36e951 100644 --- a/format/it/playback/effect/effect_setvibratowaveform.go +++ b/format/it/playback/effect/effect_setvibratowaveform.go @@ -5,15 +5,15 @@ import ( "github.com/gotracker/voice/oscillator" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // SetVibratoWaveform defines a set vibrato waveform effect type SetVibratoWaveform channel.DataEffect // 'S3x' // Start triggers on the first tick, but before the Tick() function is called -func (e SetVibratoWaveform) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetVibratoWaveform) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := channel.DataEffect(e) & 0xf diff --git a/format/it/playback/effect/effect_tremolo.go b/format/it/playback/effect/effect_tremolo.go index 7d3573a..56abe48 100644 --- a/format/it/playback/effect/effect_tremolo.go +++ b/format/it/playback/effect/effect_tremolo.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // Tremolo defines a tremolo effect type Tremolo channel.DataEffect // 'R' // Start triggers on the first tick, but before the Tick() function is called -func (e Tremolo) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e Tremolo) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e Tremolo) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e Tremolo) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.Tremolo(channel.DataEffect(e)) // NOTE: JBC - IT dos not update on tick 0, but MOD does. diff --git a/format/it/playback/effect/effect_tremor.go b/format/it/playback/effect/effect_tremor.go index a1ce5be..3972b2a 100644 --- a/format/it/playback/effect/effect_tremor.go +++ b/format/it/playback/effect/effect_tremor.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // Tremor defines a tremor effect type Tremor channel.DataEffect // 'I' // Start triggers on the first tick, but before the Tick() function is called -func (e Tremor) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e Tremor) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e Tremor) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e Tremor) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.Tremor(channel.DataEffect(e)) return doTremor(cs, currentTick, int(x)+1, int(y)+1) diff --git a/format/it/playback/effect/effect_vibrato.go b/format/it/playback/effect/effect_vibrato.go index 080ba80..ef775c1 100644 --- a/format/it/playback/effect/effect_vibrato.go +++ b/format/it/playback/effect/effect_vibrato.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // Vibrato defines a vibrato effect type Vibrato channel.DataEffect // 'H' // Start triggers on the first tick, but before the Tick() function is called -func (e Vibrato) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e Vibrato) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() return nil } // Tick is called on every tick -func (e Vibrato) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e Vibrato) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.Vibrato(channel.DataEffect(e)) if mem.Shared.OldEffectMode { diff --git a/format/it/playback/effect/effect_vibratovolslide.go b/format/it/playback/effect/effect_vibratovolslide.go index 5c7d0d9..0efe5c3 100644 --- a/format/it/playback/effect/effect_vibratovolslide.go +++ b/format/it/playback/effect/effect_vibratovolslide.go @@ -3,13 +3,13 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // VibratoVolumeSlide defines a combination vibrato and volume slide effect type VibratoVolumeSlide struct { // 'K' - intf.CombinedEffect[channel.Memory, channel.Data] + playback.CombinedEffect[channel.Memory, channel.Data] } // NewVibratoVolumeSlide creates a new VibratoVolumeSlide object diff --git a/format/it/playback/effect/effect_volslidedown.go b/format/it/playback/effect/effect_volslidedown.go index 6fdfab7..c461fb5 100644 --- a/format/it/playback/effect/effect_volslidedown.go +++ b/format/it/playback/effect/effect_volslidedown.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // VolumeSlideDown defines a volume slide down effect type VolumeSlideDown channel.DataEffect // 'D' // Start triggers on the first tick, but before the Tick() function is called -func (e VolumeSlideDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e VolumeSlideDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e VolumeSlideDown) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e VolumeSlideDown) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() _, y := mem.VolumeSlide(channel.DataEffect(e)) @@ -34,7 +34,7 @@ func (e VolumeSlideDown) String() string { type VolChanVolumeSlideDown channel.DataEffect // 'd' // Tick is called on every tick -func (e VolChanVolumeSlideDown) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e VolChanVolumeSlideDown) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() y := mem.VolChanVolumeSlide(channel.DataEffect(e)) diff --git a/format/it/playback/effect/effect_volslideup.go b/format/it/playback/effect/effect_volslideup.go index 262dd82..343ce4e 100644 --- a/format/it/playback/effect/effect_volslideup.go +++ b/format/it/playback/effect/effect_volslideup.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // VolumeSlideUp defines a volume slide up effect type VolumeSlideUp channel.DataEffect // 'D' // Start triggers on the first tick, but before the Tick() function is called -func (e VolumeSlideUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e VolumeSlideUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e VolumeSlideUp) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e VolumeSlideUp) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, _ := mem.VolumeSlide(channel.DataEffect(e)) @@ -34,7 +34,7 @@ func (e VolumeSlideUp) String() string { type VolChanVolumeSlideUp channel.DataEffect // 'd' // Tick is called on every tick -func (e VolChanVolumeSlideUp) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e VolChanVolumeSlideUp) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x := mem.VolChanVolumeSlide(channel.DataEffect(e)) diff --git a/format/it/playback/effect/effect_volumeenvelopeoff.go b/format/it/playback/effect/effect_volumeenvelopeoff.go index cd0870a..aab597b 100644 --- a/format/it/playback/effect/effect_volumeenvelopeoff.go +++ b/format/it/playback/effect/effect_volumeenvelopeoff.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // VolumeEnvelopeOff defines a volume envelope: off effect type VolumeEnvelopeOff channel.DataEffect // 'S77' // Start triggers on the first tick, but before the Tick() function is called -func (e VolumeEnvelopeOff) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e VolumeEnvelopeOff) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.SetVolumeEnvelopeEnable(false) diff --git a/format/it/playback/effect/effect_volumeenvelopeon.go b/format/it/playback/effect/effect_volumeenvelopeon.go index a39a753..4262709 100644 --- a/format/it/playback/effect/effect_volumeenvelopeon.go +++ b/format/it/playback/effect/effect_volumeenvelopeon.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) // VolumeEnvelopeOn defines a volume envelope: on effect type VolumeEnvelopeOn channel.DataEffect // 'S78' // Start triggers on the first tick, but before the Tick() function is called -func (e VolumeEnvelopeOn) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e VolumeEnvelopeOn) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.SetVolumeEnvelopeEnable(true) diff --git a/format/it/playback/effect/effectfactory.go b/format/it/playback/effect/effectfactory.go index 596e4c2..26cf937 100644 --- a/format/it/playback/effect/effectfactory.go +++ b/format/it/playback/effect/effectfactory.go @@ -3,17 +3,17 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" ) type EffectIT interface { - intf.Effect + playback.Effect } // VolEff is a combined effect that includes a volume effect and a standard effect type VolEff struct { - intf.CombinedEffect[channel.Memory, channel.Data] + playback.CombinedEffect[channel.Memory, channel.Data] eff EffectIT } diff --git a/format/it/playback/effect/effectfactory_volume.go b/format/it/playback/effect/effectfactory_volume.go index 5cc146e..6c0fd56 100644 --- a/format/it/playback/effect/effectfactory_volume.go +++ b/format/it/playback/effect/effectfactory_volume.go @@ -1,12 +1,12 @@ package effect import ( - "github.com/gotracker/playback/format/it/layout/channel" + "github.com/gotracker/playback/format/it/channel" ) func volPanEffectFactory(mem *channel.Memory, v uint8) EffectIT { switch { - case v >= 0x00 && v <= 0x40: // volume set - handled elsewhere + case v <= 0x40: // volume set - handled elsewhere return nil case v >= 0x41 && v <= 0x4a: // fine volume slide up return VolChanFineVolumeSlideUp(v - 0x41) diff --git a/format/it/playback/effect/intf/intf.go b/format/it/playback/effect/intf/intf.go index 757a1a5..e586579 100644 --- a/format/it/playback/effect/intf/intf.go +++ b/format/it/playback/effect/intf/intf.go @@ -2,7 +2,7 @@ package intf import ( "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/song/index" + "github.com/gotracker/playback/index" ) // IT is an interface to IT effect operations diff --git a/format/it/playback/effect/unhandled.go b/format/it/playback/effect/unhandled.go index 32beee5..d1dc7c1 100644 --- a/format/it/playback/effect/unhandled.go +++ b/format/it/playback/effect/unhandled.go @@ -3,9 +3,9 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/it/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" effectIntf "github.com/gotracker/playback/format/it/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // UnhandledCommand is an unhandled command @@ -15,7 +15,7 @@ type UnhandledCommand struct { } // PreStart triggers when the effect enters onto the channel state -func (e UnhandledCommand) PreStart(cs intf.Channel[channel.Memory, channel.Data], m effectIntf.IT) error { +func (e UnhandledCommand) PreStart(cs playback.Channel[channel.Memory, channel.Data], m effectIntf.IT) error { if !m.IgnoreUnknownEffect() { panic(fmt.Sprintf("unhandled command: ce:%0.2X cp:%0.2X", e.Command, e.Info)) } @@ -24,7 +24,7 @@ func (e UnhandledCommand) PreStart(cs intf.Channel[channel.Memory, channel.Data] func (e UnhandledCommand) String() string { switch { - case e.Command >= 0x00 && e.Command <= 0x09: + case e.Command <= 0x09: return fmt.Sprintf("%c%0.2x", e.Command+'0', e.Info) case e.Command >= 0x0A && e.Command <= 0x23: return fmt.Sprintf("%c%0.2x", e.Command+'A', e.Info) @@ -39,7 +39,7 @@ type UnhandledVolCommand struct { } // PreStart triggers when the effect enters onto the channel state -func (e UnhandledVolCommand) PreStart(cs intf.Channel[channel.Memory, channel.Data], m effectIntf.IT) error { +func (e UnhandledVolCommand) PreStart(cs playback.Channel[channel.Memory, channel.Data], m effectIntf.IT) error { if !m.IgnoreUnknownEffect() { panic(fmt.Sprintf("unhandled command: volCmd:%0.2X", e.Vol)) } diff --git a/format/it/playback/effect/util.go b/format/it/playback/effect/util.go index 1794de2..d3cbf5d 100644 --- a/format/it/playback/effect/util.go +++ b/format/it/playback/effect/util.go @@ -4,15 +4,15 @@ import ( itfile "github.com/gotracker/goaudiofile/music/tracked/it" "github.com/gotracker/voice/oscillator" - itVolume "github.com/gotracker/playback/format/it/conversion/volume" - "github.com/gotracker/playback/format/it/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" effectIntf "github.com/gotracker/playback/format/it/playback/effect/intf" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + itVolume "github.com/gotracker/playback/format/it/volume" + "github.com/gotracker/playback/note" "github.com/heucuva/comparison" ) -func doVolSlide(cs intf.Channel[channel.Memory, channel.Data], delta float32, multiplier float32) error { +func doVolSlide(cs playback.Channel[channel.Memory, channel.Data], delta float32, multiplier float32) error { av := cs.GetActiveVolume() v := itVolume.ToItVolume(av) vol := int16((float32(v) + delta) * multiplier) @@ -44,7 +44,7 @@ func doGlobalVolSlide(m effectIntf.IT, delta float32, multiplier float32) error return nil } -func doPortaByDeltaAmiga(cs intf.Channel[channel.Memory, channel.Data], delta int) error { +func doPortaByDeltaAmiga(cs playback.Channel[channel.Memory, channel.Data], delta int) error { period := cs.GetPeriod() if period == nil { return nil @@ -56,7 +56,7 @@ func doPortaByDeltaAmiga(cs intf.Channel[channel.Memory, channel.Data], delta in return nil } -func doPortaByDeltaLinear(cs intf.Channel[channel.Memory, channel.Data], delta int) error { +func doPortaByDeltaLinear(cs playback.Channel[channel.Memory, channel.Data], delta int) error { period := cs.GetPeriod() if period == nil { return nil @@ -68,7 +68,7 @@ func doPortaByDeltaLinear(cs intf.Channel[channel.Memory, channel.Data], delta i return nil } -func doPortaUp(cs intf.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, linearFreqSlides bool) error { +func doPortaUp(cs playback.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, linearFreqSlides bool) error { delta := int(amount * multiplier) if linearFreqSlides { return doPortaByDeltaLinear(cs, delta) @@ -76,7 +76,7 @@ func doPortaUp(cs intf.Channel[channel.Memory, channel.Data], amount float32, mu return doPortaByDeltaAmiga(cs, -delta) } -func doPortaUpToNote(cs intf.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, target note.Period, linearFreqSlides bool) error { +func doPortaUpToNote(cs playback.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, target note.Period, linearFreqSlides bool) error { if err := doPortaUp(cs, amount, multiplier, linearFreqSlides); err != nil { return err } @@ -86,7 +86,7 @@ func doPortaUpToNote(cs intf.Channel[channel.Memory, channel.Data], amount float return nil } -func doPortaDown(cs intf.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, linearFreqSlides bool) error { +func doPortaDown(cs playback.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, linearFreqSlides bool) error { delta := int(amount * multiplier) if linearFreqSlides { return doPortaByDeltaLinear(cs, -delta) @@ -94,7 +94,7 @@ func doPortaDown(cs intf.Channel[channel.Memory, channel.Data], amount float32, return doPortaByDeltaAmiga(cs, delta) } -func doPortaDownToNote(cs intf.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, target note.Period, linearFreqSlides bool) error { +func doPortaDownToNote(cs playback.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, target note.Period, linearFreqSlides bool) error { if err := doPortaDown(cs, amount, multiplier, linearFreqSlides); err != nil { return err } @@ -104,7 +104,7 @@ func doPortaDownToNote(cs intf.Channel[channel.Memory, channel.Data], amount flo return nil } -func doVibrato(cs intf.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32) error { +func doVibrato(cs playback.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32) error { mem := cs.GetMemory() vib := calculateWaveTable(cs, currentTick, speed, depth, multiplier, mem.VibratoOscillator()) delta := note.PeriodDelta(vib) @@ -112,7 +112,7 @@ func doVibrato(cs intf.Channel[channel.Memory, channel.Data], currentTick int, s return nil } -func doTremor(cs intf.Channel[channel.Memory, channel.Data], currentTick int, onTicks int, offTicks int) error { +func doTremor(cs playback.Channel[channel.Memory, channel.Data], currentTick int, onTicks int, offTicks int) error { mem := cs.GetMemory() tremor := mem.TremorMem() if tremor.IsActive() { @@ -128,7 +128,7 @@ func doTremor(cs intf.Channel[channel.Memory, channel.Data], currentTick int, on return nil } -func doArpeggio(cs intf.Channel[channel.Memory, channel.Data], currentTick int, arpSemitoneADelta int8, arpSemitoneBDelta int8) error { +func doArpeggio(cs playback.Channel[channel.Memory, channel.Data], currentTick int, arpSemitoneADelta int8, arpSemitoneBDelta int8) error { ns := cs.GetNoteSemitone() var arpSemitoneTarget note.Semitone switch currentTick % 3 { @@ -153,7 +153,7 @@ var ( } ) -func doVolSlideTwoThirds(cs intf.Channel[channel.Memory, channel.Data]) error { +func doVolSlideTwoThirds(cs playback.Channel[channel.Memory, channel.Data]) error { vol := itVolume.ToItVolume(cs.GetActiveVolume()) if vol >= 0x10 && vol <= 0x50 { vol -= 0x10 @@ -172,13 +172,13 @@ func doVolSlideTwoThirds(cs intf.Channel[channel.Memory, channel.Data]) error { return nil } -func doTremolo(cs intf.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32) error { +func doTremolo(cs playback.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32) error { mem := cs.GetMemory() delta := calculateWaveTable(cs, currentTick, speed, depth, multiplier, mem.TremoloOscillator()) return doVolSlide(cs, delta, 1.0) } -func calculateWaveTable(cs intf.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32, o oscillator.Oscillator) float32 { +func calculateWaveTable(cs playback.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32, o oscillator.Oscillator) float32 { delta := o.GetWave(float32(depth) * multiplier) o.Advance(int(speed)) return delta diff --git a/format/it/playback/playback.go b/format/it/playback/playback.go index fca10db..bfe4d82 100644 --- a/format/it/playback/playback.go +++ b/format/it/playback/playback.go @@ -4,19 +4,19 @@ import ( "github.com/gotracker/gomixing/volume" device "github.com/gotracker/gosound" - itPeriod "github.com/gotracker/playback/format/it/conversion/period" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/it/channel" "github.com/gotracker/playback/format/it/layout" - "github.com/gotracker/playback/format/it/layout/channel" + itPeriod "github.com/gotracker/playback/format/it/period" "github.com/gotracker/playback/format/it/playback/state/pattern" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/note" + playpattern "github.com/gotracker/playback/pattern" "github.com/gotracker/playback/player" "github.com/gotracker/playback/player/feature" - "github.com/gotracker/playback/player/intf" "github.com/gotracker/playback/player/output" "github.com/gotracker/playback/player/state" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/note" - playpattern "github.com/gotracker/playback/song/pattern" ) // Manager is a playback manager for IT music @@ -34,7 +34,7 @@ type Manager struct { premix *device.PremixData rowRenderState *rowRenderState - OnEffect func(intf.Effect) + OnEffect func(playback.Effect) longChannelOutput bool enableNewNoteActions bool } @@ -336,11 +336,11 @@ func (m *Manager) GetName() string { } // SetOnEffect sets the callback for an effect being generated for a channel -func (m *Manager) SetOnEffect(fn func(intf.Effect)) { +func (m *Manager) SetOnEffect(fn func(playback.Effect)) { m.OnEffect = fn } -func (m Manager) GetOnEffect() func(intf.Effect) { +func (m Manager) GetOnEffect() func(playback.Effect) { return m.OnEffect } diff --git a/format/it/playback/playback_command.go b/format/it/playback/playback_command.go index a746914..d5cf3f9 100644 --- a/format/it/playback/playback_command.go +++ b/format/it/playback/playback_command.go @@ -1,12 +1,12 @@ package playback import ( - "github.com/gotracker/playback/format/internal/filter" - itPeriod "github.com/gotracker/playback/format/it/conversion/period" - "github.com/gotracker/playback/format/it/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/filter" + "github.com/gotracker/playback/format/it/channel" + itPeriod "github.com/gotracker/playback/format/it/period" + "github.com/gotracker/playback/note" "github.com/gotracker/playback/player/state" - "github.com/gotracker/playback/song/note" "github.com/gotracker/voice/period" ) @@ -15,7 +15,7 @@ type doNoteCalc struct { UpdateFunc state.PeriodUpdateFunc } -func (o doNoteCalc) Process(p intf.Playback, cs *state.ChannelState[channel.Memory, channel.Data]) error { +func (o doNoteCalc) Process(p playback.Playback, cs *state.ChannelState[channel.Memory, channel.Data]) error { if o.UpdateFunc == nil { return nil } diff --git a/format/it/playback/playback_pattern.go b/format/it/playback/playback_pattern.go index f954ba8..0257f26 100644 --- a/format/it/playback/playback_pattern.go +++ b/format/it/playback/playback_pattern.go @@ -4,7 +4,7 @@ import ( "errors" "time" - "github.com/gotracker/playback/format/it/layout/channel" + "github.com/gotracker/playback/format/it/channel" "github.com/gotracker/playback/player/state" "github.com/gotracker/playback/song" ) diff --git a/format/it/playback/playback_test.go b/format/it/playback/playback_test.go deleted file mode 100644 index 17cf7ad..0000000 --- a/format/it/playback/playback_test.go +++ /dev/null @@ -1,141 +0,0 @@ -package playback_test - -import ( - "flag" - "math" - "os" - "testing" - "time" - - "github.com/gotracker/playback/format/it" - "github.com/gotracker/playback/format/settings" - "github.com/gotracker/playback/player/feature" - "github.com/gotracker/playback/song" -) - -var ( - enableTremor bool - enablePortaLinkMem bool -) - -func TestTremor(t *testing.T) { - if !enableTremor { - t.Skip() - } - - fn := "../../../../test/Tremor.it" - - sampleRate := 44100 - channels := 2 - bitsPerSample := 16 - - performChannelComparison(t, fn, sampleRate, channels, bitsPerSample) -} - -func TestPortaLinkMem(t *testing.T) { - if !enablePortaLinkMem { - t.Skip() - } - - fn := "../../../../test/Porta-LinkMem.it" - - sampleRate := 44100 - channels := 2 - bitsPerSample := 16 - - performChannelComparison(t, fn, sampleRate, channels, bitsPerSample) -} - -func performChannelComparison(t *testing.T, fn string, sampleRate int, channels int, bitsPerSample int) { - t.Helper() - - s := &settings.Settings{} - playback, err := it.IT.Load(fn, s) - if err != nil { - t.Fatalf("Could not create song state! err[%v]", err) - } - - if err := playback.SetupSampler(sampleRate, channels, bitsPerSample); err != nil { - t.Fatalf("Could not setup playback sampler! err[%v]", err) - } - - if err := playback.Configure([]feature.Feature{feature.SongLoop{Count: 0}}); err != nil { - t.Fatalf("Could not setup player! err[%v]", err) - } - - for { - premixData, err := playback.Generate(time.Duration(0)) - if err != nil { - if err == song.ErrStopSong { - break - } - t.Fatal(err) - } - - if len(premixData.Data) == 0 { - continue - } - - if len(premixData.Data) < 2 { - t.Fatal("Not enough tracks of data in premix buffer") - } else if len(premixData.Data) > 2 { - t.Fatal("Too many tracks of data in premix buffer") - } - - test := premixData.Data[0] - control := premixData.Data[1] - - if len(test) < 1 { - t.Fatal("Not enough blocks of premixed track data in premix buffer") - } else if len(test) > 1 { - t.Fatal("Too many blocks of premixed track data in premix buffer") - } - - tc := test[0] - cc := control[0] - - if tc.Data == nil && cc.Data == nil { - continue - } else if tc.Data == nil { - t.Fatal("Not enough channel data provided in test track premix buffer") - } else if cc.Data == nil { - t.Fatal("Not enough channel data provided in test track premix buffer") - } - - if len(tc.Data) < channels { - t.Fatal("Not enough output channels of premixed track data in test track premix buffer") - } else if len(tc.Data) > channels { - t.Fatal("Too many output channels of premixed track data in test track premix buffer") - } - - if len(cc.Data) < channels { - t.Fatal("Not enough output channels of premixed track data in control track premix buffer") - } else if len(cc.Data) > channels { - t.Fatal("Too many output channels of premixed track data in control track premix buffer") - } - - for c := 0; c < channels; c++ { - td := tc.Data[c] - cd := cc.Data[c] - - if td.Channels != cd.Channels { - t.Fatal("test track premix buffer length is not the same as for the control track") - } - - for i := 0; i < td.Channels; i++ { - ts := td.StaticMatrix[i] - cs := cd.StaticMatrix[i] - if math.Abs(float64(ts-cs)) >= 0.15 { - t.Fatal("test track premix buffer data is not the same as for the control track") - } - } - } - } -} - -func TestMain(m *testing.M) { - flag.BoolVar(&enableTremor, "Tremor", false, "Enable Tremor test") - flag.BoolVar(&enablePortaLinkMem, "PortaLinkMem", false, "Enable PortaLinkMem test") - flag.Parse() - os.Exit(m.Run()) -} diff --git a/format/it/playback/playback_textoutput.go b/format/it/playback/playback_textoutput.go index bdc6929..5a22f57 100644 --- a/format/it/playback/playback_textoutput.go +++ b/format/it/playback/playback_textoutput.go @@ -1,7 +1,7 @@ package playback import ( - "github.com/gotracker/playback/format/it/layout/channel" + "github.com/gotracker/playback/format/it/channel" "github.com/gotracker/playback/player/render" ) diff --git a/format/it/playback/state/pattern/pattern.go b/format/it/playback/state/pattern/pattern.go index 0e7a414..2269251 100644 --- a/format/it/playback/state/pattern/pattern.go +++ b/format/it/playback/state/pattern/pattern.go @@ -3,12 +3,12 @@ package pattern import ( "errors" - formatutil "github.com/gotracker/playback/format/internal/util" - "github.com/gotracker/playback/format/it/layout/channel" + "github.com/gotracker/playback/format/it/channel" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/pattern" "github.com/gotracker/playback/player/feature" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/pattern" + formatutil "github.com/gotracker/playback/util" "github.com/heucuva/optional" ) diff --git a/format/it/conversion/volume/volume.go b/format/it/volume/volume.go similarity index 100% rename from format/it/conversion/volume/volume.go rename to format/it/volume/volume.go diff --git a/format/mod/mod.go b/format/mod/mod.go index fcbce63..c6e745e 100644 --- a/format/mod/mod.go +++ b/format/mod/mod.go @@ -1,9 +1,12 @@ package mod import ( - "github.com/gotracker/playback/format/s3m" - "github.com/gotracker/playback/format/settings" - "github.com/gotracker/playback/player/intf" + "io" + + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/load" + "github.com/gotracker/playback/settings" + "github.com/gotracker/playback/util" ) type format struct{} @@ -13,8 +16,18 @@ var ( MOD = format{} ) -// Load loads an MOD file into the song state -func (f format) Load(filename string, s *settings.Settings) (intf.Playback, error) { +// Load loads an MOD file into a playback system +func (f format) Load(filename string, s *settings.Settings) (playback.Playback, error) { + r, err := util.ReadFile(filename) + if err != nil { + return nil, err + } + + return f.LoadFromReader(r, s) +} + +// LoadFromReader loads a MOD file on a reader into a playback system +func (f format) LoadFromReader(r io.Reader, s *settings.Settings) (playback.Playback, error) { // we really just load the mod into an S3M layout, since S3M is essentially a superset - return s3m.LoadMOD(filename, s) + return load.MOD(r, s) } diff --git a/format/s3m/layout/channel/channel.go b/format/s3m/channel/data.go similarity index 78% rename from format/s3m/layout/channel/channel.go rename to format/s3m/channel/data.go index fa4b0d8..ce440d9 100644 --- a/format/s3m/layout/channel/channel.go +++ b/format/s3m/channel/data.go @@ -7,24 +7,12 @@ import ( s3mfile "github.com/gotracker/goaudiofile/music/tracked/s3m" "github.com/gotracker/gomixing/volume" - s3mNote "github.com/gotracker/playback/format/s3m/conversion/note" - s3mVolume "github.com/gotracker/playback/format/s3m/conversion/volume" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" + s3mNote "github.com/gotracker/playback/format/s3m/note" + s3mVolume "github.com/gotracker/playback/format/s3m/volume" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" ) -// S3MInstrumentID is an instrument ID in S3M world -type S3MInstrumentID uint8 - -// IsEmpty returns true if the instrument ID is 'nothing' -func (s S3MInstrumentID) IsEmpty() bool { - return s == 0 -} - -func (s S3MInstrumentID) String() string { - return fmt.Sprint(uint8(s)) -} - // DataEffect is the type of a channel's EffectParameter value type DataEffect uint8 @@ -32,7 +20,7 @@ type DataEffect uint8 type Data struct { What s3mfile.PatternFlags Note s3mfile.Note - Instrument S3MInstrumentID + Instrument InstID Volume s3mfile.Volume Command uint8 Info DataEffect diff --git a/format/s3m/channel/instid.go b/format/s3m/channel/instid.go new file mode 100644 index 0000000..9a9b079 --- /dev/null +++ b/format/s3m/channel/instid.go @@ -0,0 +1,15 @@ +package channel + +import "fmt" + +// InstID is an instrument ID in S3M world +type InstID uint8 + +// IsEmpty returns true if the instrument ID is 'nothing' +func (s InstID) IsEmpty() bool { + return s == 0 +} + +func (s InstID) String() string { + return fmt.Sprint(uint8(s)) +} diff --git a/format/s3m/layout/channel/memory.go b/format/s3m/channel/memory.go similarity index 84% rename from format/s3m/layout/channel/memory.go rename to format/s3m/channel/memory.go index d989dc3..f3bcafc 100644 --- a/format/s3m/layout/channel/memory.go +++ b/format/s3m/channel/memory.go @@ -3,27 +3,12 @@ package channel import ( "github.com/gotracker/voice/oscillator" - "github.com/gotracker/playback/format/internal/effect" - "github.com/gotracker/playback/format/internal/memory" - formatutil "github.com/gotracker/playback/format/internal/util" + "github.com/gotracker/playback/memory" oscillatorImpl "github.com/gotracker/playback/oscillator" + "github.com/gotracker/playback/tremor" + formatutil "github.com/gotracker/playback/util" ) -type SharedMemory struct { - VolSlideEveryFrame bool - LowPassFilterEnable bool - // ResetMemoryAtStartOfOrder0 if true will reset the memory registers when the first tick of the first row of the first order pattern plays - ResetMemoryAtStartOfOrder0 bool - // ST2/Amiga quirks - ST2Vibrato bool - ST2Tempo bool - AmigaSlides bool - ZeroVolOptimization bool - AmigaLimits bool - // Mod quirks mode - ModCompatibility bool -} - // Memory is the storage object for custom effect/command values type Memory struct { portaToNote memory.Value[DataEffect] @@ -36,7 +21,7 @@ type Memory struct { tempoIncrease memory.Value[DataEffect] lastNonZero memory.Value[DataEffect] - tremorMem effect.Tremor + tremorMem tremor.Tremor vibratoOscillator oscillator.Oscillator tremoloOscillator oscillator.Oscillator patternLoop formatutil.PatternLoop @@ -98,7 +83,7 @@ func (m *Memory) LastNonZeroXY(input DataEffect) (DataEffect, DataEffect) { } // TremorMem returns the Tremor object -func (m *Memory) TremorMem() *effect.Tremor { +func (m *Memory) TremorMem() *tremor.Tremor { return &m.tremorMem } diff --git a/format/s3m/channel/sharedmem.go b/format/s3m/channel/sharedmem.go new file mode 100644 index 0000000..fdc4f8f --- /dev/null +++ b/format/s3m/channel/sharedmem.go @@ -0,0 +1,16 @@ +package channel + +type SharedMemory struct { + VolSlideEveryFrame bool + LowPassFilterEnable bool + // ResetMemoryAtStartOfOrder0 if true will reset the memory registers when the first tick of the first row of the first order pattern plays + ResetMemoryAtStartOfOrder0 bool + // ST2/Amiga quirks + ST2Vibrato bool + ST2Tempo bool + AmigaSlides bool + ZeroVolOptimization bool + AmigaLimits bool + // Mod quirks mode + ModCompatibility bool +} diff --git a/format/s3m/layout/channelsetting.go b/format/s3m/layout/channelsetting.go new file mode 100644 index 0000000..f844173 --- /dev/null +++ b/format/s3m/layout/channelsetting.go @@ -0,0 +1,18 @@ +package layout + +import ( + s3mfile "github.com/gotracker/goaudiofile/music/tracked/s3m" + "github.com/gotracker/gomixing/panning" + "github.com/gotracker/gomixing/volume" + "github.com/gotracker/playback/format/s3m/channel" +) + +// ChannelSetting is settings specific to a single channel +type ChannelSetting struct { + Enabled bool + OutputChannelNum int + Category s3mfile.ChannelCategory + InitialVolume volume.Volume + InitialPanning panning.Position + Memory channel.Memory +} diff --git a/format/s3m/layout/header.go b/format/s3m/layout/header.go new file mode 100644 index 0000000..a3b6e73 --- /dev/null +++ b/format/s3m/layout/header.go @@ -0,0 +1,13 @@ +package layout + +import "github.com/gotracker/gomixing/volume" + +// Header is a mildly-decoded S3M header definition +type Header struct { + Name string + InitialSpeed int + InitialTempo int + GlobalVolume volume.Volume + MixingVolume volume.Volume + Stereo bool +} diff --git a/format/s3m/layout/s3m.go b/format/s3m/layout/song.go similarity index 51% rename from format/s3m/layout/s3m.go rename to format/s3m/layout/song.go index ec0f8e7..5ff5769 100644 --- a/format/s3m/layout/s3m.go +++ b/format/s3m/layout/song.go @@ -1,38 +1,14 @@ package layout import ( - s3mfile "github.com/gotracker/goaudiofile/music/tracked/s3m" - "github.com/gotracker/gomixing/panning" - "github.com/gotracker/gomixing/volume" - - "github.com/gotracker/playback/format/s3m/layout/channel" + "github.com/gotracker/playback/format/s3m/channel" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" + "github.com/gotracker/playback/pattern" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" - "github.com/gotracker/playback/song/pattern" ) -// Header is a mildly-decoded S3M header definition -type Header struct { - Name string - InitialSpeed int - InitialTempo int - GlobalVolume volume.Volume - MixingVolume volume.Volume - Stereo bool -} - -// ChannelSetting is settings specific to a single channel -type ChannelSetting struct { - Enabled bool - OutputChannelNum int - Category s3mfile.ChannelCategory - InitialVolume volume.Volume - InitialPanning panning.Position - Memory channel.Memory -} - // Song is the full definition of the song data of an Song file type Song struct { Head Header @@ -43,12 +19,12 @@ type Song struct { } // GetOrderList returns the list of all pattern orders for the song -func (s *Song) GetOrderList() []index.Pattern { +func (s Song) GetOrderList() []index.Pattern { return s.OrderList } // GetPattern returns an interface to a specific pattern indexed by `patNum` -func (s *Song) GetPattern(patNum index.Pattern) song.Pattern[channel.Data] { +func (s Song) GetPattern(patNum index.Pattern) song.Pattern[channel.Data] { if int(patNum) >= len(s.Patterns) { return nil } @@ -56,27 +32,27 @@ func (s *Song) GetPattern(patNum index.Pattern) song.Pattern[channel.Data] { } // IsChannelEnabled returns true if the channel at index `channelNum` is enabled -func (s *Song) IsChannelEnabled(channelNum int) bool { +func (s Song) IsChannelEnabled(channelNum int) bool { return s.ChannelSettings[channelNum].Enabled } // GetOutputChannel returns the output channel for the channel at index `channelNum` -func (s *Song) GetOutputChannel(channelNum int) int { +func (s Song) GetOutputChannel(channelNum int) int { return s.ChannelSettings[channelNum].OutputChannelNum } // NumInstruments returns the number of instruments in the song -func (s *Song) NumInstruments() int { +func (s Song) NumInstruments() int { return len(s.Instruments) } // IsValidInstrumentID returns true if the instrument exists -func (s *Song) IsValidInstrumentID(instNum instrument.ID) bool { +func (s Song) IsValidInstrumentID(instNum instrument.ID) bool { if instNum.IsEmpty() { return false } switch id := instNum.(type) { - case channel.S3MInstrumentID: + case channel.InstID: iid := int(id) return iid > 0 && iid <= len(s.Instruments) } @@ -84,12 +60,12 @@ func (s *Song) IsValidInstrumentID(instNum instrument.ID) bool { } // GetInstrument returns the instrument interface indexed by `instNum` (0-based) -func (s *Song) GetInstrument(instID instrument.ID) (*instrument.Instrument, note.Semitone) { +func (s Song) GetInstrument(instID instrument.ID) (*instrument.Instrument, note.Semitone) { if instID.IsEmpty() { return nil, note.UnchangedSemitone } switch id := instID.(type) { - case channel.S3MInstrumentID: + case channel.InstID: return s.Instruments[int(id)-1], note.UnchangedSemitone } @@ -97,6 +73,6 @@ func (s *Song) GetInstrument(instID instrument.ID) (*instrument.Instrument, note } // GetName returns the name of the song -func (s *Song) GetName() string { +func (s Song) GetName() string { return s.Head.Name } diff --git a/format/s3m/load/formatutils.go b/format/s3m/load/formatutils.go deleted file mode 100644 index 81dadd5..0000000 --- a/format/s3m/load/formatutils.go +++ /dev/null @@ -1,20 +0,0 @@ -package load - -import ( - "github.com/gotracker/playback/format/s3m/layout" - "github.com/gotracker/playback/format/s3m/playback" - "github.com/gotracker/playback/format/settings" -) - -type readerFunc func(filename string, s *settings.Settings) (*layout.Song, error) - -func load(filename string, reader readerFunc, s *settings.Settings) (*playback.Manager, error) { - s3mSong, err := reader(filename, s) - if err != nil { - return nil, err - } - - m, err := playback.NewManager(s3mSong) - - return m, err -} diff --git a/format/s3m/load/load.go b/format/s3m/load/load.go index 115e3df..d8b6a86 100644 --- a/format/s3m/load/load.go +++ b/format/s3m/load/load.go @@ -1,20 +1,18 @@ package load import ( - formatutil "github.com/gotracker/playback/format/internal/util" + "io" + + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/common" "github.com/gotracker/playback/format/s3m/layout" "github.com/gotracker/playback/format/s3m/load/modconv" - "github.com/gotracker/playback/format/settings" - "github.com/gotracker/playback/player/intf" + s3mPlayback "github.com/gotracker/playback/format/s3m/playback" + "github.com/gotracker/playback/settings" ) -func readMOD(filename string, s *settings.Settings) (*layout.Song, error) { - buffer, err := formatutil.ReadFile(filename) - if err != nil { - return nil, err - } - - f, err := modconv.Read(buffer) +func readMOD(r io.Reader, s *settings.Settings) (*layout.Song, error) { + f, err := modconv.Read(r) if err != nil { return nil, err } @@ -25,11 +23,11 @@ func readMOD(filename string, s *settings.Settings) (*layout.Song, error) { } // MOD loads a MOD file and upgrades it into an S3M file internally -func MOD(filename string, s *settings.Settings) (intf.Playback, error) { - return load(filename, readMOD, s) +func MOD(r io.Reader, s *settings.Settings) (playback.Playback, error) { + return common.Load(r, readMOD, s3mPlayback.NewManager, s) } // S3M loads an S3M file into a new Playback object -func S3M(filename string, s *settings.Settings) (intf.Playback, error) { - return load(filename, readS3M, s) +func S3M(r io.Reader, s *settings.Settings) (playback.Playback, error) { + return common.Load(r, readS3M, s3mPlayback.NewManager, s) } diff --git a/format/s3m/load/modconv/modconverter.go b/format/s3m/load/modconv/modconverter.go index 0a595aa..e7e475c 100644 --- a/format/s3m/load/modconv/modconverter.go +++ b/format/s3m/load/modconv/modconverter.go @@ -9,7 +9,7 @@ import ( modfile "github.com/gotracker/goaudiofile/music/tracked/mod" s3mfile "github.com/gotracker/goaudiofile/music/tracked/s3m" - "github.com/gotracker/playback/format/s3m/layout/channel" + "github.com/gotracker/playback/format/s3m/channel" ) func convertMODPatternToS3M(mp *modfile.Pattern) (*s3mfile.PackedPattern, error) { @@ -28,7 +28,7 @@ func convertMODPatternToS3M(mp *modfile.Pattern) (*s3mfile.PackedPattern, error) *u = channel.Data{ What: s3mfile.PatternFlags(c & 0x1F), Note: s3mfile.EmptyNote, - Instrument: channel.S3MInstrumentID(sampleNumber), + Instrument: channel.InstID(sampleNumber), Volume: s3mfile.EmptyVolume, Command: uint8(0), Info: channel.DataEffect(0), diff --git a/format/s3m/load/s3mformat.go b/format/s3m/load/s3mformat.go index 4d312b1..07049ba 100644 --- a/format/s3m/load/s3mformat.go +++ b/format/s3m/load/s3mformat.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/binary" "errors" + "io" s3mfile "github.com/gotracker/goaudiofile/music/tracked/s3m" "github.com/gotracker/gomixing/panning" @@ -12,16 +13,15 @@ import ( "github.com/gotracker/voice/loop" "github.com/gotracker/voice/pcm" - formatutil "github.com/gotracker/playback/format/internal/util" - s3mPanning "github.com/gotracker/playback/format/s3m/conversion/panning" - s3mVolume "github.com/gotracker/playback/format/s3m/conversion/volume" + "github.com/gotracker/playback/format/s3m/channel" "github.com/gotracker/playback/format/s3m/layout" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/format/settings" - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" - "github.com/gotracker/playback/song/pattern" + s3mPanning "github.com/gotracker/playback/format/s3m/panning" + s3mVolume "github.com/gotracker/playback/format/s3m/volume" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" + "github.com/gotracker/playback/pattern" + "github.com/gotracker/playback/settings" ) func moduleHeaderToHeader(fh *s3mfile.ModuleHeader) (*layout.Header, error) { @@ -295,7 +295,7 @@ func convertS3MFileToSong(f *s3mfile.File, getPatternLen func(patNum int) uint8, if sample == nil { continue } - sample.Static.ID = channel.S3MInstrumentID(uint8(instNum + 1)) + sample.Static.ID = channel.InstID(uint8(instNum + 1)) song.Instruments[instNum] = sample } @@ -365,13 +365,8 @@ func convertS3MFileToSong(f *s3mfile.File, getPatternLen func(patNum int) uint8, return &song, nil } -func readS3M(filename string, s *settings.Settings) (*layout.Song, error) { - buffer, err := formatutil.ReadFile(filename) - if err != nil { - return nil, err - } - - f, err := s3mfile.Read(buffer) +func readS3M(r io.Reader, s *settings.Settings) (*layout.Song, error) { + f, err := s3mfile.Read(r) if err != nil { return nil, err } diff --git a/format/s3m/conversion/note/note.go b/format/s3m/note/note.go similarity index 92% rename from format/s3m/conversion/note/note.go rename to format/s3m/note/note.go index ebf6aed..a3815e0 100644 --- a/format/s3m/conversion/note/note.go +++ b/format/s3m/note/note.go @@ -2,7 +2,7 @@ package note import ( s3mfile "github.com/gotracker/goaudiofile/music/tracked/s3m" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" ) // NoteFromS3MNote converts an S3M file note into a player note diff --git a/format/s3m/conversion/panning/panning.go b/format/s3m/panning/panning.go similarity index 100% rename from format/s3m/conversion/panning/panning.go rename to format/s3m/panning/panning.go diff --git a/format/s3m/conversion/period/amiga.go b/format/s3m/period/amiga.go similarity index 96% rename from format/s3m/conversion/period/amiga.go rename to format/s3m/period/amiga.go index b4bd6b8..2522d6d 100644 --- a/format/s3m/conversion/period/amiga.go +++ b/format/s3m/period/amiga.go @@ -4,8 +4,8 @@ import ( "fmt" "math" - per "github.com/gotracker/playback/format/internal/period" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" + per "github.com/gotracker/playback/period" "github.com/heucuva/comparison" "github.com/gotracker/voice/period" diff --git a/format/s3m/conversion/period/util.go b/format/s3m/period/util.go similarity index 97% rename from format/s3m/conversion/period/util.go rename to format/s3m/period/util.go index 507ede2..ba22ace 100644 --- a/format/s3m/conversion/period/util.go +++ b/format/s3m/period/util.go @@ -2,7 +2,7 @@ package period import ( s3mfile "github.com/gotracker/goaudiofile/music/tracked/s3m" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" "github.com/gotracker/voice/period" ) diff --git a/format/s3m/playback/channeldata_transaction.go b/format/s3m/playback/channeldata_transaction.go index ca3fe38..e10b078 100644 --- a/format/s3m/playback/channeldata_transaction.go +++ b/format/s3m/playback/channeldata_transaction.go @@ -3,13 +3,13 @@ package playback import ( "github.com/gotracker/gomixing/sampling" "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/format/s3m/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" "github.com/gotracker/playback/format/s3m/playback/effect" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" "github.com/gotracker/playback/player/state" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" ) type channelDataConverter struct{} @@ -85,14 +85,14 @@ type channelDataTransaction struct { state.ChannelDataTxnHelper[channel.Memory, channel.Data, channelDataConverter] } -func (d *channelDataTransaction) CommitPreRow(p intf.Playback, cs *state.ChannelState[channel.Memory, channel.Data], semitoneSetterFactory state.SemitoneSetterFactory[channel.Memory, channel.Data]) error { +func (d *channelDataTransaction) CommitPreRow(p playback.Playback, cs *state.ChannelState[channel.Memory, channel.Data], semitoneSetterFactory state.SemitoneSetterFactory[channel.Memory, channel.Data]) error { e := effect.Factory(cs.GetMemory(), d.Data) cs.SetActiveEffect(e) if e != nil { if onEff := p.GetOnEffect(); onEff != nil { onEff(e) } - if err := intf.EffectPreStart[channel.Memory, channel.Data](e, cs, p); err != nil { + if err := playback.EffectPreStart[channel.Memory, channel.Data](e, cs, p); err != nil { return err } } @@ -100,7 +100,7 @@ func (d *channelDataTransaction) CommitPreRow(p intf.Playback, cs *state.Channel return nil } -func (d *channelDataTransaction) CommitRow(p intf.Playback, cs *state.ChannelState[channel.Memory, channel.Data], semitoneSetterFactory state.SemitoneSetterFactory[channel.Memory, channel.Data]) error { +func (d *channelDataTransaction) CommitRow(p playback.Playback, cs *state.ChannelState[channel.Memory, channel.Data], semitoneSetterFactory state.SemitoneSetterFactory[channel.Memory, channel.Data]) error { if pos, ok := d.TargetPos.Get(); ok { cs.SetTargetPos(pos) } diff --git a/format/s3m/playback/effect/effect_arpeggio.go b/format/s3m/playback/effect/effect_arpeggio.go index aafc714..f70136c 100644 --- a/format/s3m/playback/effect/effect_arpeggio.go +++ b/format/s3m/playback/effect/effect_arpeggio.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // Arpeggio defines an arpeggio effect type Arpeggio ChannelCommand // 'J' // Start triggers on the first tick, but before the Tick() function is called -func (e Arpeggio) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e Arpeggio) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() cs.SetPos(cs.GetTargetPos()) @@ -19,7 +19,7 @@ func (e Arpeggio) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Pl } // Tick is called on every tick -func (e Arpeggio) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e Arpeggio) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.LastNonZeroXY(channel.DataEffect(e)) return doArpeggio(cs, currentTick, int8(x), int8(y)) diff --git a/format/s3m/playback/effect/effect_enablefilter.go b/format/s3m/playback/effect/effect_enablefilter.go index f53f5c4..dda4021 100644 --- a/format/s3m/playback/effect/effect_enablefilter.go +++ b/format/s3m/playback/effect/effect_enablefilter.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" effectIntf "github.com/gotracker/playback/format/s3m/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // EnableFilter defines a set filter enable effect type EnableFilter ChannelCommand // 'S0x' // Start triggers on the first tick, but before the Tick() function is called -func (e EnableFilter) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e EnableFilter) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := channel.DataEffect(e) & 0xf diff --git a/format/s3m/playback/effect/effect_extrafineportadown.go b/format/s3m/playback/effect/effect_extrafineportadown.go index de91124..f83af89 100644 --- a/format/s3m/playback/effect/effect_extrafineportadown.go +++ b/format/s3m/playback/effect/effect_extrafineportadown.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // ExtraFinePortaDown defines an extra-fine portamento down effect type ExtraFinePortaDown ChannelCommand // 'EEx' // Start triggers on the first tick, but before the Tick() function is called -func (e ExtraFinePortaDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e ExtraFinePortaDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() diff --git a/format/s3m/playback/effect/effect_extrafineportaup.go b/format/s3m/playback/effect/effect_extrafineportaup.go index d5e0219..d42a3b7 100644 --- a/format/s3m/playback/effect/effect_extrafineportaup.go +++ b/format/s3m/playback/effect/effect_extrafineportaup.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // ExtraFinePortaUp defines an extra-fine portamento up effect type ExtraFinePortaUp ChannelCommand // 'FEx' // Start triggers on the first tick, but before the Tick() function is called -func (e ExtraFinePortaUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e ExtraFinePortaUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() diff --git a/format/s3m/playback/effect/effect_finepatterndelay.go b/format/s3m/playback/effect/effect_finepatterndelay.go index 22b351c..4bb2214 100644 --- a/format/s3m/playback/effect/effect_finepatterndelay.go +++ b/format/s3m/playback/effect/effect_finepatterndelay.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" effectIntf "github.com/gotracker/playback/format/s3m/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // FinePatternDelay defines an fine pattern delay effect type FinePatternDelay ChannelCommand // 'S6x' // Start triggers on the first tick, but before the Tick() function is called -func (e FinePatternDelay) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FinePatternDelay) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := channel.DataEffect(e) & 0xf diff --git a/format/s3m/playback/effect/effect_fineportadown.go b/format/s3m/playback/effect/effect_fineportadown.go index ba7cc07..00e965f 100644 --- a/format/s3m/playback/effect/effect_fineportadown.go +++ b/format/s3m/playback/effect/effect_fineportadown.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // FinePortaDown defines an fine portamento down effect type FinePortaDown ChannelCommand // 'EFx' // Start triggers on the first tick, but before the Tick() function is called -func (e FinePortaDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FinePortaDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() diff --git a/format/s3m/playback/effect/effect_fineportaup.go b/format/s3m/playback/effect/effect_fineportaup.go index cd3690b..1735c4b 100644 --- a/format/s3m/playback/effect/effect_fineportaup.go +++ b/format/s3m/playback/effect/effect_fineportaup.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // FinePortaUp defines an fine portamento up effect type FinePortaUp ChannelCommand // 'FFx' // Start triggers on the first tick, but before the Tick() function is called -func (e FinePortaUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FinePortaUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() diff --git a/format/s3m/playback/effect/effect_finevibrato.go b/format/s3m/playback/effect/effect_finevibrato.go index 3b0d31f..2f0223d 100644 --- a/format/s3m/playback/effect/effect_finevibrato.go +++ b/format/s3m/playback/effect/effect_finevibrato.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // FineVibrato defines an fine vibrato effect type FineVibrato ChannelCommand // 'U' // Start triggers on the first tick, but before the Tick() function is called -func (e FineVibrato) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FineVibrato) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() return nil } // Tick is called on every tick -func (e FineVibrato) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e FineVibrato) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.Vibrato(channel.DataEffect(e)) // NOTE: JBC - S3M does not update on tick 0, but MOD does. diff --git a/format/s3m/playback/effect/effect_finevolslidedown.go b/format/s3m/playback/effect/effect_finevolslidedown.go index 8c016e6..e72e582 100644 --- a/format/s3m/playback/effect/effect_finevolslidedown.go +++ b/format/s3m/playback/effect/effect_finevolslidedown.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // FineVolumeSlideDown defines a fine volume slide down effect type FineVolumeSlideDown ChannelCommand // 'DFy' // Start triggers on the first tick, but before the Tick() function is called -func (e FineVolumeSlideDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FineVolumeSlideDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e FineVolumeSlideDown) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e FineVolumeSlideDown) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { y := channel.DataEffect(e) & 0x0F if y != 0x0F && currentTick == 0 { diff --git a/format/s3m/playback/effect/effect_finevolslideup.go b/format/s3m/playback/effect/effect_finevolslideup.go index edceab5..db37718 100644 --- a/format/s3m/playback/effect/effect_finevolslideup.go +++ b/format/s3m/playback/effect/effect_finevolslideup.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // FineVolumeSlideUp defines a fine volume slide up effect type FineVolumeSlideUp ChannelCommand // 'DxF' // Start triggers on the first tick, but before the Tick() function is called -func (e FineVolumeSlideUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FineVolumeSlideUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e FineVolumeSlideUp) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e FineVolumeSlideUp) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { x := channel.DataEffect(e) >> 4 if x != 0x0F && currentTick == 0 { diff --git a/format/s3m/playback/effect/effect_notecut.go b/format/s3m/playback/effect/effect_notecut.go index 18bc23d..0ab9c05 100644 --- a/format/s3m/playback/effect/effect_notecut.go +++ b/format/s3m/playback/effect/effect_notecut.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // NoteCut defines a note cut effect type NoteCut ChannelCommand // 'SCx' // Start triggers on the first tick, but before the Tick() function is called -func (e NoteCut) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e NoteCut) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e NoteCut) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e NoteCut) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { x := channel.DataEffect(e) & 0xf if x != 0 && currentTick == int(x) { diff --git a/format/s3m/playback/effect/effect_notedelay.go b/format/s3m/playback/effect/effect_notedelay.go index d6aa70b..4b595a7 100644 --- a/format/s3m/playback/effect/effect_notedelay.go +++ b/format/s3m/playback/effect/effect_notedelay.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" + "github.com/gotracker/playback/note" ) // NoteDelay defines a note delay effect type NoteDelay ChannelCommand // 'SDx' // PreStart triggers when the effect enters onto the channel state -func (e NoteDelay) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e NoteDelay) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.SetNotePlayTick(true, note.ActionRetrigger, int(channel.DataEffect(e)&0x0F)) return nil } // Start triggers on the first tick, but before the Tick() function is called -func (e NoteDelay) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e NoteDelay) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/s3m/playback/effect/effect_orderjump.go b/format/s3m/playback/effect/effect_orderjump.go index f6c2b86..58168f2 100644 --- a/format/s3m/playback/effect/effect_orderjump.go +++ b/format/s3m/playback/effect/effect_orderjump.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/index" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" + "github.com/gotracker/playback/index" ) // OrderJump defines an order jump effect type OrderJump ChannelCommand // 'B' // Start triggers on the first tick, but before the Tick() function is called -func (e OrderJump) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e OrderJump) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Stop is called on the last tick of the row, but after the Tick() function is called -func (e OrderJump) Stop(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, lastTick int) error { +func (e OrderJump) Stop(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, lastTick int) error { return p.SetNextOrder(index.Order(e)) } diff --git a/format/s3m/playback/effect/effect_patterndelay.go b/format/s3m/playback/effect/effect_patterndelay.go index d97bf53..b311e43 100644 --- a/format/s3m/playback/effect/effect_patterndelay.go +++ b/format/s3m/playback/effect/effect_patterndelay.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" effectIntf "github.com/gotracker/playback/format/s3m/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // PatternDelay defines a pattern delay effect type PatternDelay ChannelCommand // 'SEx' // PreStart triggers when the effect enters onto the channel state -func (e PatternDelay) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PatternDelay) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { m := p.(effectIntf.S3M) return m.SetPatternDelay(int(channel.DataEffect(e) & 0x0F)) } // Start triggers on the first tick, but before the Tick() function is called -func (e PatternDelay) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PatternDelay) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/s3m/playback/effect/effect_patternloop.go b/format/s3m/playback/effect/effect_patternloop.go index 9a1392c..e0c5ade 100644 --- a/format/s3m/playback/effect/effect_patternloop.go +++ b/format/s3m/playback/effect/effect_patternloop.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // PatternLoop defines a pattern loop effect type PatternLoop ChannelCommand // 'SBx' // Start triggers on the first tick, but before the Tick() function is called -func (e PatternLoop) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PatternLoop) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Stop is called on the last tick of the row, but after the Tick() function is called -func (e PatternLoop) Stop(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, lastTick int) error { +func (e PatternLoop) Stop(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, lastTick int) error { x := channel.DataEffect(e) & 0xF mem := cs.GetMemory() diff --git a/format/s3m/playback/effect/effect_portadown.go b/format/s3m/playback/effect/effect_portadown.go index af78e2c..da0b32a 100644 --- a/format/s3m/playback/effect/effect_portadown.go +++ b/format/s3m/playback/effect/effect_portadown.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // PortaDown defines a portamento down effect type PortaDown ChannelCommand // 'E' // Start triggers on the first tick, but before the Tick() function is called -func (e PortaDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PortaDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() return nil } // Tick is called on every tick -func (e PortaDown) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e PortaDown) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() xx := mem.LastNonZero(channel.DataEffect(e)) diff --git a/format/s3m/playback/effect/effect_portatonote.go b/format/s3m/playback/effect/effect_portatonote.go index 518e1a4..091248c 100644 --- a/format/s3m/playback/effect/effect_portatonote.go +++ b/format/s3m/playback/effect/effect_portatonote.go @@ -3,9 +3,9 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" + "github.com/gotracker/playback/note" "github.com/heucuva/comparison" ) @@ -13,7 +13,7 @@ import ( type PortaToNote ChannelCommand // 'G' // Start triggers on the first tick, but before the Tick() function is called -func (e PortaToNote) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PortaToNote) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() if cmd := cs.GetData(); cmd != nil && cmd.HasNote() { @@ -24,7 +24,7 @@ func (e PortaToNote) Start(cs intf.Channel[channel.Memory, channel.Data], p intf } // Tick is called on every tick -func (e PortaToNote) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e PortaToNote) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() xx := mem.PortaToNote(channel.DataEffect(e)) diff --git a/format/s3m/playback/effect/effect_portaup.go b/format/s3m/playback/effect/effect_portaup.go index bd97c15..b214bd4 100644 --- a/format/s3m/playback/effect/effect_portaup.go +++ b/format/s3m/playback/effect/effect_portaup.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // PortaUp defines a portamento up effect type PortaUp ChannelCommand // 'F' // Start triggers on the first tick, but before the Tick() function is called -func (e PortaUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PortaUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() return nil } // Tick is called on every tick -func (e PortaUp) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e PortaUp) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() xx := mem.LastNonZero(channel.DataEffect(e)) diff --git a/format/s3m/playback/effect/effect_portavolslide.go b/format/s3m/playback/effect/effect_portavolslide.go index d5c83da..f7dff38 100644 --- a/format/s3m/playback/effect/effect_portavolslide.go +++ b/format/s3m/playback/effect/effect_portavolslide.go @@ -3,13 +3,13 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // PortaVolumeSlide defines a portamento-to-note combined with a volume slide effect type PortaVolumeSlide struct { // 'L' - intf.CombinedEffect[channel.Memory, channel.Data] + playback.CombinedEffect[channel.Memory, channel.Data] } // NewPortaVolumeSlide creates a new PortaVolumeSlide object diff --git a/format/s3m/playback/effect/effect_retrigvolslide.go b/format/s3m/playback/effect/effect_retrigvolslide.go index dbbe7e0..dea8389 100644 --- a/format/s3m/playback/effect/effect_retrigvolslide.go +++ b/format/s3m/playback/effect/effect_retrigvolslide.go @@ -5,21 +5,21 @@ import ( "github.com/gotracker/gomixing/sampling" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // RetrigVolumeSlide defines a retriggering volume slide effect type RetrigVolumeSlide ChannelCommand // 'Q' // Start triggers on the first tick, but before the Tick() function is called -func (e RetrigVolumeSlide) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e RetrigVolumeSlide) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e RetrigVolumeSlide) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e RetrigVolumeSlide) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { x := channel.DataEffect(e) >> 4 y := channel.DataEffect(e) & 0x0F if y == 0 { diff --git a/format/s3m/playback/effect/effect_rowjump.go b/format/s3m/playback/effect/effect_rowjump.go index a17a610..5e5669d 100644 --- a/format/s3m/playback/effect/effect_rowjump.go +++ b/format/s3m/playback/effect/effect_rowjump.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/index" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" + "github.com/gotracker/playback/index" ) // RowJump defines a row jump effect type RowJump ChannelCommand // 'C' // Start triggers on the first tick, but before the Tick() function is called -func (e RowJump) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e RowJump) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Stop is called on the last tick of the row, but after the Tick() function is called -func (e RowJump) Stop(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, lastTick int) error { +func (e RowJump) Stop(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, lastTick int) error { r := channel.DataEffect(e) rowIdx := index.Row((r >> 4) * 10) rowIdx += index.Row(r & 0xf) diff --git a/format/s3m/playback/effect/effect_sampleoffset.go b/format/s3m/playback/effect/effect_sampleoffset.go index 83d9087..66e745a 100644 --- a/format/s3m/playback/effect/effect_sampleoffset.go +++ b/format/s3m/playback/effect/effect_sampleoffset.go @@ -5,15 +5,15 @@ import ( "github.com/gotracker/gomixing/sampling" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // SampleOffset defines a sample offset effect type SampleOffset ChannelCommand // 'O' // Start triggers on the first tick, but before the Tick() function is called -func (e SampleOffset) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SampleOffset) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() mem := cs.GetMemory() xx := mem.SampleOffset(channel.DataEffect(e)) diff --git a/format/s3m/playback/effect/effect_setfinetune.go b/format/s3m/playback/effect/effect_setfinetune.go index 8326e15..01c85ce 100644 --- a/format/s3m/playback/effect/effect_setfinetune.go +++ b/format/s3m/playback/effect/effect_setfinetune.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" + "github.com/gotracker/playback/note" ) // SetFinetune defines a mod-style set finetune effect type SetFinetune ChannelCommand // 'S2x' // PreStart triggers when the effect enters onto the channel state -func (e SetFinetune) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetFinetune) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { x := channel.DataEffect(e) & 0xf inst := cs.GetTargetInst() @@ -24,7 +24,7 @@ func (e SetFinetune) PreStart(cs intf.Channel[channel.Memory, channel.Data], p i } // Start triggers on the first tick, but before the Tick() function is called -func (e SetFinetune) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetFinetune) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/s3m/playback/effect/effect_setglobalvolume.go b/format/s3m/playback/effect/effect_setglobalvolume.go index 2292ab5..ec7f4d4 100644 --- a/format/s3m/playback/effect/effect_setglobalvolume.go +++ b/format/s3m/playback/effect/effect_setglobalvolume.go @@ -5,22 +5,22 @@ import ( s3mfile "github.com/gotracker/goaudiofile/music/tracked/s3m" - s3mVolume "github.com/gotracker/playback/format/s3m/conversion/volume" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" + s3mVolume "github.com/gotracker/playback/format/s3m/volume" ) // SetGlobalVolume defines a set global volume effect type SetGlobalVolume ChannelCommand // 'V' // PreStart triggers when the effect enters onto the channel state -func (e SetGlobalVolume) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetGlobalVolume) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { p.SetGlobalVolume(s3mVolume.VolumeFromS3M(s3mfile.Volume(channel.DataEffect(e)))) return nil } // Start triggers on the first tick, but before the Tick() function is called -func (e SetGlobalVolume) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetGlobalVolume) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/s3m/playback/effect/effect_setpanposition.go b/format/s3m/playback/effect/effect_setpanposition.go index 7f9c8bc..e276d9d 100644 --- a/format/s3m/playback/effect/effect_setpanposition.go +++ b/format/s3m/playback/effect/effect_setpanposition.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - s3mPanning "github.com/gotracker/playback/format/s3m/conversion/panning" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" + s3mPanning "github.com/gotracker/playback/format/s3m/panning" ) // SetPanPosition defines a set pan position effect type SetPanPosition ChannelCommand // 'S8x' // Start triggers on the first tick, but before the Tick() function is called -func (e SetPanPosition) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetPanPosition) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := uint8(e) & 0xf diff --git a/format/s3m/playback/effect/effect_setspeed.go b/format/s3m/playback/effect/effect_setspeed.go index 63d1e65..7afcb65 100644 --- a/format/s3m/playback/effect/effect_setspeed.go +++ b/format/s3m/playback/effect/effect_setspeed.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" effectIntf "github.com/gotracker/playback/format/s3m/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // SetSpeed defines a set speed effect type SetSpeed ChannelCommand // 'A' // PreStart triggers when the effect enters onto the channel state -func (e SetSpeed) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetSpeed) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { if e != 0 { m := p.(effectIntf.S3M) if err := m.SetTicks(int(e)); err != nil { @@ -23,7 +23,7 @@ func (e SetSpeed) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf } // Start triggers on the first tick, but before the Tick() function is called -func (e SetSpeed) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetSpeed) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/s3m/playback/effect/effect_settempo.go b/format/s3m/playback/effect/effect_settempo.go index 6ae0667..fd58816 100644 --- a/format/s3m/playback/effect/effect_settempo.go +++ b/format/s3m/playback/effect/effect_settempo.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" effectIntf "github.com/gotracker/playback/format/s3m/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // SetTempo defines a set tempo effect type SetTempo ChannelCommand // 'T' // PreStart triggers when the effect enters onto the channel state -func (e SetTempo) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetTempo) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { if e > 0x20 { m := p.(effectIntf.S3M) if err := m.SetTempo(int(e)); err != nil { @@ -23,13 +23,13 @@ func (e SetTempo) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf } // Start triggers on the first tick, but before the Tick() function is called -func (e SetTempo) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetTempo) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e SetTempo) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e SetTempo) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { m := p.(effectIntf.S3M) switch channel.DataEffect(e >> 4) { case 0: // decrease tempo diff --git a/format/s3m/playback/effect/effect_settremolowaveform.go b/format/s3m/playback/effect/effect_settremolowaveform.go index 68d39d2..fcc7173 100644 --- a/format/s3m/playback/effect/effect_settremolowaveform.go +++ b/format/s3m/playback/effect/effect_settremolowaveform.go @@ -5,15 +5,15 @@ import ( "github.com/gotracker/voice/oscillator" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // SetTremoloWaveform defines a set tremolo waveform effect type SetTremoloWaveform ChannelCommand // 'S4x' // Start triggers on the first tick, but before the Tick() function is called -func (e SetTremoloWaveform) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetTremoloWaveform) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := channel.DataEffect(e) & 0xf diff --git a/format/s3m/playback/effect/effect_setvibratowaveform.go b/format/s3m/playback/effect/effect_setvibratowaveform.go index d18be2a..0abceab 100644 --- a/format/s3m/playback/effect/effect_setvibratowaveform.go +++ b/format/s3m/playback/effect/effect_setvibratowaveform.go @@ -5,15 +5,15 @@ import ( "github.com/gotracker/voice/oscillator" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // SetVibratoWaveform defines a set vibrato waveform effect type SetVibratoWaveform ChannelCommand // 'S3x' // Start triggers on the first tick, but before the Tick() function is called -func (e SetVibratoWaveform) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetVibratoWaveform) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := channel.DataEffect(e) & 0xf diff --git a/format/s3m/playback/effect/effect_stereocontrol.go b/format/s3m/playback/effect/effect_stereocontrol.go index b3a4c50..e59f5fa 100644 --- a/format/s3m/playback/effect/effect_stereocontrol.go +++ b/format/s3m/playback/effect/effect_stereocontrol.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - s3mPanning "github.com/gotracker/playback/format/s3m/conversion/panning" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" + s3mPanning "github.com/gotracker/playback/format/s3m/panning" ) // StereoControl defines a set stereo control effect type StereoControl ChannelCommand // 'SAx' // Start triggers on the first tick, but before the Tick() function is called -func (e StereoControl) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e StereoControl) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := uint8(e) & 0xf diff --git a/format/s3m/playback/effect/effect_tremolo.go b/format/s3m/playback/effect/effect_tremolo.go index ef8f1f0..866e4d9 100644 --- a/format/s3m/playback/effect/effect_tremolo.go +++ b/format/s3m/playback/effect/effect_tremolo.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // Tremolo defines a tremolo effect type Tremolo ChannelCommand // 'R' // Start triggers on the first tick, but before the Tick() function is called -func (e Tremolo) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e Tremolo) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e Tremolo) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e Tremolo) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.Tremolo(channel.DataEffect(e)) // NOTE: JBC - S3M does not update on tick 0, but MOD does. diff --git a/format/s3m/playback/effect/effect_tremor.go b/format/s3m/playback/effect/effect_tremor.go index 3aace79..51f0bc8 100644 --- a/format/s3m/playback/effect/effect_tremor.go +++ b/format/s3m/playback/effect/effect_tremor.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // Tremor defines a tremor effect type Tremor ChannelCommand // 'I' // Start triggers on the first tick, but before the Tick() function is called -func (e Tremor) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e Tremor) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e Tremor) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e Tremor) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.LastNonZeroXY(channel.DataEffect(e)) return doTremor(cs, currentTick, int(x)+1, int(y)+1) diff --git a/format/s3m/playback/effect/effect_vibrato.go b/format/s3m/playback/effect/effect_vibrato.go index 846b61d..ace0713 100644 --- a/format/s3m/playback/effect/effect_vibrato.go +++ b/format/s3m/playback/effect/effect_vibrato.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // Vibrato defines a vibrato effect type Vibrato ChannelCommand // 'H' // Start triggers on the first tick, but before the Tick() function is called -func (e Vibrato) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e Vibrato) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() return nil } // Tick is called on every tick -func (e Vibrato) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e Vibrato) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.Vibrato(channel.DataEffect(e)) // NOTE: JBC - S3M dos not update on tick 0, but MOD does. diff --git a/format/s3m/playback/effect/effect_vibratovolslide.go b/format/s3m/playback/effect/effect_vibratovolslide.go index 6962b68..6a40643 100644 --- a/format/s3m/playback/effect/effect_vibratovolslide.go +++ b/format/s3m/playback/effect/effect_vibratovolslide.go @@ -3,13 +3,13 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // VibratoVolumeSlide defines a combination vibrato and volume slide effect type VibratoVolumeSlide struct { // 'K' - intf.CombinedEffect[channel.Memory, channel.Data] + playback.CombinedEffect[channel.Memory, channel.Data] } // NewVibratoVolumeSlide creates a new VibratoVolumeSlide object diff --git a/format/s3m/playback/effect/effect_volslidedown.go b/format/s3m/playback/effect/effect_volslidedown.go index a04c435..453cf28 100644 --- a/format/s3m/playback/effect/effect_volslidedown.go +++ b/format/s3m/playback/effect/effect_volslidedown.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // VolumeSlideDown defines a volume slide down effect type VolumeSlideDown ChannelCommand // 'D0y' // Start triggers on the first tick, but before the Tick() function is called -func (e VolumeSlideDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e VolumeSlideDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e VolumeSlideDown) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e VolumeSlideDown) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() y := channel.DataEffect(e) & 0x0F diff --git a/format/s3m/playback/effect/effect_volslideup.go b/format/s3m/playback/effect/effect_volslideup.go index ee55da3..7cdcef6 100644 --- a/format/s3m/playback/effect/effect_volslideup.go +++ b/format/s3m/playback/effect/effect_volslideup.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) // VolumeSlideUp defines a volume slide up effect type VolumeSlideUp ChannelCommand // 'Dx0' // Start triggers on the first tick, but before the Tick() function is called -func (e VolumeSlideUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e VolumeSlideUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e VolumeSlideUp) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e VolumeSlideUp) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x := channel.DataEffect(e) >> 4 diff --git a/format/s3m/playback/effect/effectfactory.go b/format/s3m/playback/effect/effectfactory.go index 88de6f5..fb93093 100644 --- a/format/s3m/playback/effect/effectfactory.go +++ b/format/s3m/playback/effect/effectfactory.go @@ -1,12 +1,12 @@ package effect import ( - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" ) type EffectS3M interface { - intf.Effect + playback.Effect } type ChannelCommand channel.DataEffect diff --git a/format/s3m/playback/effect/intf/intf.go b/format/s3m/playback/effect/intf/intf.go index 909ee1b..158fd40 100644 --- a/format/s3m/playback/effect/intf/intf.go +++ b/format/s3m/playback/effect/intf/intf.go @@ -2,7 +2,7 @@ package intf import ( "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/song/index" + "github.com/gotracker/playback/index" ) // S3M is an interface to S3M effect operations diff --git a/format/s3m/playback/effect/unhandled.go b/format/s3m/playback/effect/unhandled.go index c46e7eb..83d3bb8 100644 --- a/format/s3m/playback/effect/unhandled.go +++ b/format/s3m/playback/effect/unhandled.go @@ -3,9 +3,9 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/s3m/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" effectIntf "github.com/gotracker/playback/format/s3m/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // UnhandledCommand is an unhandled command @@ -15,7 +15,7 @@ type UnhandledCommand struct { } // PreStart triggers when the effect enters onto the channel state -func (e UnhandledCommand) PreStart(cs intf.Channel[channel.Memory, channel.Data], m effectIntf.S3M) error { +func (e UnhandledCommand) PreStart(cs playback.Channel[channel.Memory, channel.Data], m effectIntf.S3M) error { if !m.IgnoreUnknownEffect() { panic("unhandled command") } diff --git a/format/s3m/playback/effect/util.go b/format/s3m/playback/effect/util.go index a4b9bbd..1f30569 100644 --- a/format/s3m/playback/effect/util.go +++ b/format/s3m/playback/effect/util.go @@ -4,14 +4,14 @@ import ( s3mfile "github.com/gotracker/goaudiofile/music/tracked/s3m" "github.com/gotracker/voice/oscillator" - s3mVolume "github.com/gotracker/playback/format/s3m/conversion/volume" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" + s3mVolume "github.com/gotracker/playback/format/s3m/volume" + "github.com/gotracker/playback/note" "github.com/heucuva/comparison" ) -func doVolSlide(cs intf.Channel[channel.Memory, channel.Data], delta float32, multiplier float32) error { +func doVolSlide(cs playback.Channel[channel.Memory, channel.Data], delta float32, multiplier float32) error { av := cs.GetActiveVolume() v := s3mVolume.VolumeToS3M(av) vol := int16((float32(v) + delta) * multiplier) @@ -27,7 +27,7 @@ func doVolSlide(cs intf.Channel[channel.Memory, channel.Data], delta float32, mu return nil } -func doPortaUp(cs intf.Channel[channel.Memory, channel.Data], amount float32, multiplier float32) error { +func doPortaUp(cs playback.Channel[channel.Memory, channel.Data], amount float32, multiplier float32) error { period := cs.GetPeriod() if period == nil { return nil @@ -40,7 +40,7 @@ func doPortaUp(cs intf.Channel[channel.Memory, channel.Data], amount float32, mu return nil } -func doPortaUpToNote(cs intf.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, target note.Period) error { +func doPortaUpToNote(cs playback.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, target note.Period) error { period := cs.GetPeriod() if period == nil { return nil @@ -56,7 +56,7 @@ func doPortaUpToNote(cs intf.Channel[channel.Memory, channel.Data], amount float return nil } -func doPortaDown(cs intf.Channel[channel.Memory, channel.Data], amount float32, multiplier float32) error { +func doPortaDown(cs playback.Channel[channel.Memory, channel.Data], amount float32, multiplier float32) error { period := cs.GetPeriod() if period == nil { return nil @@ -69,7 +69,7 @@ func doPortaDown(cs intf.Channel[channel.Memory, channel.Data], amount float32, return nil } -func doPortaDownToNote(cs intf.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, target note.Period) error { +func doPortaDownToNote(cs playback.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, target note.Period) error { period := cs.GetPeriod() if period == nil { return nil @@ -85,14 +85,14 @@ func doPortaDownToNote(cs intf.Channel[channel.Memory, channel.Data], amount flo return nil } -func doVibrato(cs intf.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32) error { +func doVibrato(cs playback.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32) error { mem := cs.GetMemory() delta := calculateWaveTable(cs, currentTick, channel.DataEffect(speed), channel.DataEffect(depth), multiplier, mem.VibratoOscillator()) cs.SetPeriodDelta(note.PeriodDelta(delta)) return nil } -func doTremor(cs intf.Channel[channel.Memory, channel.Data], currentTick int, onTicks int, offTicks int) error { +func doTremor(cs playback.Channel[channel.Memory, channel.Data], currentTick int, onTicks int, offTicks int) error { mem := cs.GetMemory() tremor := mem.TremorMem() if tremor.IsActive() { @@ -108,7 +108,7 @@ func doTremor(cs intf.Channel[channel.Memory, channel.Data], currentTick int, on return nil } -func doArpeggio(cs intf.Channel[channel.Memory, channel.Data], currentTick int, arpSemitoneADelta int8, arpSemitoneBDelta int8) error { +func doArpeggio(cs playback.Channel[channel.Memory, channel.Data], currentTick int, arpSemitoneADelta int8, arpSemitoneBDelta int8) error { ns := cs.GetNoteSemitone() var arpSemitoneTarget note.Semitone switch currentTick % 3 { @@ -133,7 +133,7 @@ var ( } ) -func doVolSlideTwoThirds(cs intf.Channel[channel.Memory, channel.Data]) error { +func doVolSlideTwoThirds(cs playback.Channel[channel.Memory, channel.Data]) error { vol := s3mVolume.VolumeToS3M(cs.GetActiveVolume()) if vol >= 64 { vol = 63 @@ -142,13 +142,13 @@ func doVolSlideTwoThirds(cs intf.Channel[channel.Memory, channel.Data]) error { return nil } -func doTremolo(cs intf.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32) error { +func doTremolo(cs playback.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32) error { mem := cs.GetMemory() delta := calculateWaveTable(cs, currentTick, speed, depth, multiplier, mem.TremoloOscillator()) return doVolSlide(cs, delta, 1.0) } -func calculateWaveTable(cs intf.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32, o oscillator.Oscillator) float32 { +func calculateWaveTable(cs playback.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32, o oscillator.Oscillator) float32 { delta := o.GetWave(float32(depth)) * multiplier o.Advance(int(speed)) return delta diff --git a/format/s3m/playback/playback.go b/format/s3m/playback/playback.go index 63a0c99..704b0d5 100644 --- a/format/s3m/playback/playback.go +++ b/format/s3m/playback/playback.go @@ -6,19 +6,19 @@ import ( "github.com/gotracker/gomixing/volume" device "github.com/gotracker/gosound" - s3mPeriod "github.com/gotracker/playback/format/s3m/conversion/period" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/s3m/channel" "github.com/gotracker/playback/format/s3m/layout" - "github.com/gotracker/playback/format/s3m/layout/channel" + s3mPeriod "github.com/gotracker/playback/format/s3m/period" "github.com/gotracker/playback/format/s3m/playback/state/pattern" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/note" + playpattern "github.com/gotracker/playback/pattern" "github.com/gotracker/playback/player" "github.com/gotracker/playback/player/feature" - "github.com/gotracker/playback/player/intf" "github.com/gotracker/playback/player/output" "github.com/gotracker/playback/player/state" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/note" - playpattern "github.com/gotracker/playback/song/pattern" ) // Manager is a playback manager for S3M music @@ -35,7 +35,7 @@ type Manager struct { premix *device.PremixData rowRenderState *rowRenderState - OnEffect func(intf.Effect) + OnEffect func(playback.Effect) chOrder [4][]*state.ChannelState[channel.Memory, channel.Data] } @@ -341,11 +341,11 @@ func (m *Manager) GetName() string { } // SetOnEffect sets the callback for an effect being generated for a channel -func (m *Manager) SetOnEffect(fn func(intf.Effect)) { +func (m *Manager) SetOnEffect(fn func(playback.Effect)) { m.OnEffect = fn } -func (m Manager) GetOnEffect() func(intf.Effect) { +func (m Manager) GetOnEffect() func(playback.Effect) { return m.OnEffect } diff --git a/format/s3m/playback/playback_command.go b/format/s3m/playback/playback_command.go index 55c284e..a0ff0ff 100644 --- a/format/s3m/playback/playback_command.go +++ b/format/s3m/playback/playback_command.go @@ -1,12 +1,12 @@ package playback import ( - "github.com/gotracker/playback/format/internal/filter" - s3mPeriod "github.com/gotracker/playback/format/s3m/conversion/period" - "github.com/gotracker/playback/format/s3m/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/filter" + "github.com/gotracker/playback/format/s3m/channel" + s3mPeriod "github.com/gotracker/playback/format/s3m/period" + "github.com/gotracker/playback/note" "github.com/gotracker/playback/player/state" - "github.com/gotracker/playback/song/note" ) type doNoteCalc struct { @@ -14,7 +14,7 @@ type doNoteCalc struct { UpdateFunc state.PeriodUpdateFunc } -func (o doNoteCalc) Process(p intf.Playback, cs *state.ChannelState[channel.Memory, channel.Data]) error { +func (o doNoteCalc) Process(p playback.Playback, cs *state.ChannelState[channel.Memory, channel.Data]) error { if o.UpdateFunc == nil { return nil } diff --git a/format/s3m/playback/playback_pattern.go b/format/s3m/playback/playback_pattern.go index c4efb00..2f5f09e 100644 --- a/format/s3m/playback/playback_pattern.go +++ b/format/s3m/playback/playback_pattern.go @@ -4,7 +4,7 @@ import ( "errors" "time" - "github.com/gotracker/playback/format/s3m/layout/channel" + "github.com/gotracker/playback/format/s3m/channel" "github.com/gotracker/playback/player/state" "github.com/gotracker/playback/song" ) diff --git a/format/s3m/playback/playback_test.go b/format/s3m/playback/playback_test.go deleted file mode 100644 index 739ff7a..0000000 --- a/format/s3m/playback/playback_test.go +++ /dev/null @@ -1,256 +0,0 @@ -package playback_test - -import ( - "flag" - "math" - "os" - "testing" - "time" - - "github.com/gotracker/playback/format/s3m" - "github.com/gotracker/playback/format/settings" - "github.com/gotracker/playback/player/feature" - "github.com/gotracker/playback/song" -) - -var ( - enableOxxMemory bool - enablePeriodLimit bool - enablePortaAfterArp bool - enableRetrigAfterNoteCut bool - enableVibratoTypeChange bool -) - -func TestOxxMemory(t *testing.T) { - if !enableOxxMemory { - t.Skip() - } - - fn := "../../../../test/OxxMemory.s3m" - - sampleRate := 44100 - channels := 2 - bitsPerSample := 16 - - performSilentChannelsTest(t, fn, sampleRate, channels, bitsPerSample) -} - -func TestPeriodLimit(t *testing.T) { - if !enablePeriodLimit { - t.Skip() - } - - fn := "../../../../test/PeriodLimit.s3m" - - sampleRate := 44100 - channels := 2 - bitsPerSample := 16 - - performChannelComparison(t, fn, sampleRate, channels, bitsPerSample) -} - -func TestPortaAfterArp(t *testing.T) { - if !enablePortaAfterArp { - t.Skip() - } - - fn := "../../../../test/PortaAfterArp.s3m" - - sampleRate := 44100 - channels := 2 - bitsPerSample := 16 - - performChannelComparison(t, fn, sampleRate, channels, bitsPerSample) -} - -func TestRetrigAfterNoteCut(t *testing.T) { - if !enableRetrigAfterNoteCut { - t.Skip() - } - - fn := "../../../../test/RetrigAfterNoteCut.s3m" - - sampleRate := 44100 - channels := 2 - bitsPerSample := 16 - - performChannelComparison(t, fn, sampleRate, channels, bitsPerSample) -} - -func TestVibratoTypeChange(t *testing.T) { - if !enableVibratoTypeChange { - t.Skip() - } - - fn := "../../../../test/VibratoTypeChange.s3m" - - sampleRate := 44100 - channels := 2 - bitsPerSample := 16 - - performSilentChannelsTest(t, fn, sampleRate, channels, bitsPerSample) -} - -func performSilentChannelsTest(t *testing.T, fn string, sampleRate int, channels int, bitsPerSample int) { - t.Helper() - - s := &settings.Settings{} - playback, err := s3m.S3M.Load(fn, s) - if err != nil { - t.Fatalf("Could not create song state! err[%v]", err) - } - - if err := playback.SetupSampler(sampleRate, channels, bitsPerSample); err != nil { - t.Fatalf("Could not setup playback sampler! err[%v]", err) - } - - if err := playback.Configure([]feature.Feature{feature.SongLoop{Count: 0}}); err != nil { - t.Fatalf("Could not setup player! err[%v]", err) - } - - for { - premixData, err := playback.Generate(time.Duration(0)) - if err != nil { - if err == song.ErrStopSong { - break - } - t.Fatal(err) - } - - if len(premixData.Data) == 0 { - continue - } - - if len(premixData.Data) < 1 { - t.Fatal("Not enough channels of data in premix buffer") - } - - for _, test := range premixData.Data { - - if len(test) < 1 { - t.Fatal("Not enough blocks of premixed track data in premix buffer") - } else if len(test) > 1 { - t.Fatal("Too many blocks of premixed track data in premix buffer") - } - - pm := test[0] - - data := pm.Data - if data == nil { - continue - } - - if len(data) < channels { - t.Fatal("Not enough output channels of premixed track data in premix buffer") - } else if len(data) > channels { - t.Fatal("Too many output channels of premixed track data in premix buffer") - } - - for _, chdata := range data { - for i := 0; i < chdata.Channels; i++ { - s := chdata.StaticMatrix[i] - if math.Abs(float64(s)) >= 0.5 { - t.Fatal("expected relative silence, got waveform") - } - } - } - } - } -} - -func performChannelComparison(t *testing.T, fn string, sampleRate int, channels int, bitsPerSample int) { - t.Helper() - - s := &settings.Settings{} - playback, err := s3m.S3M.Load(fn, s) - if err != nil { - t.Fatalf("Could not create song state! err[%v]", err) - } - - if err := playback.SetupSampler(sampleRate, channels, bitsPerSample); err != nil { - t.Fatalf("Could not setup playback sampler! err[%v]", err) - } - - if err := playback.Configure([]feature.Feature{feature.SongLoop{Count: 0}}); err != nil { - t.Fatalf("Could not setup player! err[%v]", err) - } - - for { - premixData, err := playback.Generate(time.Duration(0)) - if err != nil { - if err == song.ErrStopSong { - break - } - t.Fatal(err) - } - - if len(premixData.Data) == 0 { - continue - } - - if len(premixData.Data) < 2 { - t.Fatal("Not enough tracks of data in premix buffer") - } else if len(premixData.Data) > 2 { - t.Fatal("Too many tracks of data in premix buffer") - } - - test := premixData.Data[0] - control := premixData.Data[1] - - if len(test) < 1 { - t.Fatal("Not enough blocks of premixed track data in premix buffer") - } else if len(test) > 1 { - t.Fatal("Too many blocks of premixed track data in premix buffer") - } - - tc := test[0] - cc := control[0] - - if tc.Data == nil && cc.Data == nil { - continue - } else if tc.Data == nil { - t.Fatal("Not enough channel data provided in test track premix buffer") - } else if cc.Data == nil { - t.Fatal("Not enough channel data provided in test track premix buffer") - } - - if len(tc.Data) < channels { - t.Fatal("Not enough output channels of premixed track data in test track premix buffer") - } else if len(tc.Data) > channels { - t.Fatal("Too many output channels of premixed track data in test track premix buffer") - } - - if len(cc.Data) < channels { - t.Fatal("Not enough output channels of premixed track data in control track premix buffer") - } else if len(cc.Data) > channels { - t.Fatal("Too many output channels of premixed track data in control track premix buffer") - } - - for c := 0; c < channels; c++ { - td := tc.Data[c] - cd := cc.Data[c] - - if td.Channels != cd.Channels { - t.Fatal("test track premix buffer length is not the same as for the control track") - } - - for i := 0; i < td.Channels; i++ { - ts := td.StaticMatrix[i] - cs := cd.StaticMatrix[i] - if math.Abs(float64(ts-cs)) >= 0.15 { - t.Fatal("test track premix buffer data is not the same as for the control track") - } - } - } - } -} - -func TestMain(m *testing.M) { - flag.BoolVar(&enableOxxMemory, "OxxMemory", false, "Enable OxxMemory test") - flag.BoolVar(&enablePeriodLimit, "PeriodLimit", false, "Enable PeriodLimit test") - flag.BoolVar(&enablePortaAfterArp, "PortaAfterArp", false, "Enable PortaAfterArp test") - flag.BoolVar(&enableRetrigAfterNoteCut, "RetrigAfterNoteCut", false, "Enable RetrigAfterNoteCut test") - flag.BoolVar(&enableVibratoTypeChange, "VibratoTypeChange", false, "Enable VibratoTypeChange test") - flag.Parse() - os.Exit(m.Run()) -} diff --git a/format/s3m/playback/playback_textoutput.go b/format/s3m/playback/playback_textoutput.go index 8f18758..086b0ff 100644 --- a/format/s3m/playback/playback_textoutput.go +++ b/format/s3m/playback/playback_textoutput.go @@ -1,7 +1,7 @@ package playback import ( - "github.com/gotracker/playback/format/s3m/layout/channel" + "github.com/gotracker/playback/format/s3m/channel" "github.com/gotracker/playback/player/render" ) diff --git a/format/s3m/playback/state/pattern/pattern.go b/format/s3m/playback/state/pattern/pattern.go index 97d090a..cb99b75 100644 --- a/format/s3m/playback/state/pattern/pattern.go +++ b/format/s3m/playback/state/pattern/pattern.go @@ -3,12 +3,12 @@ package pattern import ( "errors" - formatutil "github.com/gotracker/playback/format/internal/util" - "github.com/gotracker/playback/format/s3m/layout/channel" + "github.com/gotracker/playback/format/s3m/channel" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/pattern" "github.com/gotracker/playback/player/feature" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/pattern" + formatutil "github.com/gotracker/playback/util" "github.com/heucuva/optional" ) diff --git a/format/s3m/s3m.go b/format/s3m/s3m.go index 1bd210b..195a4a6 100644 --- a/format/s3m/s3m.go +++ b/format/s3m/s3m.go @@ -2,9 +2,12 @@ package s3m import ( + "io" + + "github.com/gotracker/playback" "github.com/gotracker/playback/format/s3m/load" - "github.com/gotracker/playback/format/settings" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback/settings" + "github.com/gotracker/playback/util" ) type format struct{} @@ -14,12 +17,17 @@ var ( S3M = format{} ) -// LoadMOD loads a MOD file and upgrades it into an S3M file internally -func LoadMOD(filename string, s *settings.Settings) (intf.Playback, error) { - return load.MOD(filename, s) +// Load loads an S3M file into a playback system +func (f format) Load(filename string, s *settings.Settings) (playback.Playback, error) { + r, err := util.ReadFile(filename) + if err != nil { + return nil, err + } + + return f.LoadFromReader(r, s) } -// Load loads an S3M file into a playback system -func (f format) Load(filename string, s *settings.Settings) (intf.Playback, error) { - return load.S3M(filename, s) +// Load loads an S3M file on a reader into a playback system +func (f format) LoadFromReader(r io.Reader, s *settings.Settings) (playback.Playback, error) { + return load.S3M(r, s) } diff --git a/format/s3m/conversion/volume/volume.go b/format/s3m/volume/volume.go similarity index 100% rename from format/s3m/conversion/volume/volume.go rename to format/s3m/volume/volume.go diff --git a/format/xm/layout/channel/channel.go b/format/xm/channel/data.go similarity index 83% rename from format/xm/layout/channel/channel.go rename to format/xm/channel/data.go index 1826aec..99b6413 100644 --- a/format/xm/layout/channel/channel.go +++ b/format/xm/channel/data.go @@ -7,30 +7,15 @@ import ( xmfile "github.com/gotracker/goaudiofile/music/tracked/xm" "github.com/gotracker/gomixing/volume" - xmNote "github.com/gotracker/playback/format/xm/conversion/note" - xmVolume "github.com/gotracker/playback/format/xm/conversion/volume" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" + xmNote "github.com/gotracker/playback/format/xm/note" + xmVolume "github.com/gotracker/playback/format/xm/volume" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" ) // DataEffect is the type of a channel's EffectParameter value type DataEffect uint8 -// SampleID is an InstrumentID that is a combination of InstID and SampID -type SampleID struct { - InstID uint8 - Semitone note.Semitone -} - -// IsEmpty returns true if the sample ID is empty -func (s SampleID) IsEmpty() bool { - return s.InstID == 0 -} - -func (s SampleID) String() string { - return fmt.Sprint(s.InstID) -} - // Data is the data for the channel type Data struct { What xmfile.ChannelFlags diff --git a/format/xm/layout/channel/memory.go b/format/xm/channel/memory.go similarity index 91% rename from format/xm/layout/channel/memory.go rename to format/xm/channel/memory.go index 79293fb..40b5cd6 100644 --- a/format/xm/layout/channel/memory.go +++ b/format/xm/channel/memory.go @@ -3,19 +3,12 @@ package channel import ( "github.com/gotracker/voice/oscillator" - "github.com/gotracker/playback/format/internal/effect" - "github.com/gotracker/playback/format/internal/memory" - formatutil "github.com/gotracker/playback/format/internal/util" + "github.com/gotracker/playback/memory" oscillatorImpl "github.com/gotracker/playback/oscillator" + "github.com/gotracker/playback/tremor" + formatutil "github.com/gotracker/playback/util" ) -type SharedMemory struct { - // LinearFreqSlides is true if linear frequency slides are enabled (false = amiga-style period-based slides) - LinearFreqSlides bool - // ResetMemoryAtStartOfOrder0 if true will reset the memory registers when the first tick of the first row of the first order pattern plays - ResetMemoryAtStartOfOrder0 bool -} - // Memory is the storage object for custom effect/effect values type Memory struct { portaToNote memory.Value[DataEffect] @@ -37,7 +30,7 @@ type Memory struct { extraFinePortaUp memory.Value[DataEffect] extraFinePortaDown memory.Value[DataEffect] - tremorMem effect.Tremor + tremorMem tremor.Tremor vibratoOscillator oscillator.Oscillator tremoloOscillator oscillator.Oscillator patternLoop formatutil.PatternLoop @@ -142,7 +135,7 @@ func (m *Memory) ExtraFinePortaDown(input DataEffect) DataEffect { } // TremorMem returns the Tremor object -func (m *Memory) TremorMem() *effect.Tremor { +func (m *Memory) TremorMem() *tremor.Tremor { return &m.tremorMem } diff --git a/format/xm/channel/sampid.go b/format/xm/channel/sampid.go new file mode 100644 index 0000000..b529a24 --- /dev/null +++ b/format/xm/channel/sampid.go @@ -0,0 +1,22 @@ +package channel + +import ( + "fmt" + + "github.com/gotracker/playback/note" +) + +// SampleID is an InstrumentID that is a combination of InstID and SampID +type SampleID struct { + InstID uint8 + Semitone note.Semitone +} + +// IsEmpty returns true if the sample ID is empty +func (s SampleID) IsEmpty() bool { + return s.InstID == 0 +} + +func (s SampleID) String() string { + return fmt.Sprint(s.InstID) +} diff --git a/format/xm/channel/sharedmem.go b/format/xm/channel/sharedmem.go new file mode 100644 index 0000000..1201595 --- /dev/null +++ b/format/xm/channel/sharedmem.go @@ -0,0 +1,8 @@ +package channel + +type SharedMemory struct { + // LinearFreqSlides is true if linear frequency slides are enabled (false = amiga-style period-based slides) + LinearFreqSlides bool + // ResetMemoryAtStartOfOrder0 if true will reset the memory registers when the first tick of the first row of the first order pattern plays + ResetMemoryAtStartOfOrder0 bool +} diff --git a/format/xm/layout/channelsetting.go b/format/xm/layout/channelsetting.go new file mode 100644 index 0000000..c0f8f96 --- /dev/null +++ b/format/xm/layout/channelsetting.go @@ -0,0 +1,16 @@ +package layout + +import ( + "github.com/gotracker/gomixing/panning" + "github.com/gotracker/gomixing/volume" + "github.com/gotracker/playback/format/xm/channel" +) + +// ChannelSetting is settings specific to a single channel +type ChannelSetting struct { + Enabled bool + OutputChannelNum int + InitialVolume volume.Volume + InitialPanning panning.Position + Memory channel.Memory +} diff --git a/format/xm/layout/header.go b/format/xm/layout/header.go new file mode 100644 index 0000000..12fa550 --- /dev/null +++ b/format/xm/layout/header.go @@ -0,0 +1,12 @@ +package layout + +import "github.com/gotracker/gomixing/volume" + +// Header is a mildly-decoded XM header definition +type Header struct { + Name string + InitialSpeed int + InitialTempo int + GlobalVolume volume.Volume + MixingVolume volume.Volume +} diff --git a/format/xm/layout/xm.go b/format/xm/layout/song.go similarity index 58% rename from format/xm/layout/xm.go rename to format/xm/layout/song.go index 4228c9b..d122a1c 100644 --- a/format/xm/layout/xm.go +++ b/format/xm/layout/song.go @@ -1,35 +1,14 @@ package layout import ( - "github.com/gotracker/gomixing/panning" - "github.com/gotracker/gomixing/volume" - - "github.com/gotracker/playback/format/xm/layout/channel" + "github.com/gotracker/playback/format/xm/channel" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" + "github.com/gotracker/playback/pattern" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" - "github.com/gotracker/playback/song/pattern" ) -// Header is a mildly-decoded XM header definition -type Header struct { - Name string - InitialSpeed int - InitialTempo int - GlobalVolume volume.Volume - MixingVolume volume.Volume -} - -// ChannelSetting is settings specific to a single channel -type ChannelSetting struct { - Enabled bool - OutputChannelNum int - InitialVolume volume.Volume - InitialPanning panning.Position - Memory channel.Memory -} - // Song is the full definition of the song data of an Song file type Song struct { Head Header @@ -41,12 +20,12 @@ type Song struct { } // GetOrderList returns the list of all pattern orders for the song -func (s *Song) GetOrderList() []index.Pattern { +func (s Song) GetOrderList() []index.Pattern { return s.OrderList } // GetPattern returns an interface to a specific pattern indexed by `patNum` -func (s *Song) GetPattern(patNum index.Pattern) song.Pattern[channel.Data] { +func (s Song) GetPattern(patNum index.Pattern) song.Pattern[channel.Data] { if int(patNum) >= len(s.Patterns) { return nil } @@ -54,22 +33,22 @@ func (s *Song) GetPattern(patNum index.Pattern) song.Pattern[channel.Data] { } // IsChannelEnabled returns true if the channel at index `channelNum` is enabled -func (s *Song) IsChannelEnabled(channelNum int) bool { +func (s Song) IsChannelEnabled(channelNum int) bool { return s.ChannelSettings[channelNum].Enabled } // GetOutputChannel returns the output channel for the channel at index `channelNum` -func (s *Song) GetOutputChannel(channelNum int) int { +func (s Song) GetOutputChannel(channelNum int) int { return s.ChannelSettings[channelNum].OutputChannelNum } // NumInstruments returns the number of instruments in the song -func (s *Song) NumInstruments() int { +func (s Song) NumInstruments() int { return len(s.Instruments) } // IsValidInstrumentID returns true if the instrument exists -func (s *Song) IsValidInstrumentID(instNum instrument.ID) bool { +func (s Song) IsValidInstrumentID(instNum instrument.ID) bool { if instNum.IsEmpty() { return false } @@ -82,7 +61,7 @@ func (s *Song) IsValidInstrumentID(instNum instrument.ID) bool { } // GetInstrument returns the instrument interface indexed by `instNum` (0-based) -func (s *Song) GetInstrument(instNum instrument.ID) (*instrument.Instrument, note.Semitone) { +func (s Song) GetInstrument(instNum instrument.ID) (*instrument.Instrument, note.Semitone) { if instNum.IsEmpty() { return nil, note.UnchangedSemitone } @@ -98,6 +77,6 @@ func (s *Song) GetInstrument(instNum instrument.ID) (*instrument.Instrument, not } // GetName returns the name of the song -func (s *Song) GetName() string { +func (s Song) GetName() string { return s.Head.Name } diff --git a/format/xm/load/formatutils.go b/format/xm/load/formatutils.go deleted file mode 100644 index 9830f8b..0000000 --- a/format/xm/load/formatutils.go +++ /dev/null @@ -1,20 +0,0 @@ -package load - -import ( - "github.com/gotracker/playback/format/settings" - "github.com/gotracker/playback/format/xm/layout" - "github.com/gotracker/playback/format/xm/playback" -) - -type readerFunc func(filename string, s *settings.Settings) (*layout.Song, error) - -func load(filename string, reader readerFunc, s *settings.Settings) (*playback.Manager, error) { - xmSong, err := reader(filename, s) - if err != nil { - return nil, err - } - - m, err := playback.NewManager(xmSong) - - return m, err -} diff --git a/format/xm/load/load.go b/format/xm/load/load.go index 1ab4ee2..de7fa60 100644 --- a/format/xm/load/load.go +++ b/format/xm/load/load.go @@ -1,11 +1,15 @@ package load import ( - "github.com/gotracker/playback/format/settings" - "github.com/gotracker/playback/player/intf" + "io" + + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/common" + xmPlayback "github.com/gotracker/playback/format/xm/playback" + "github.com/gotracker/playback/settings" ) // XM loads an XM file and upgrades it into an XM file internally -func XM(filename string, s *settings.Settings) (intf.Playback, error) { - return load(filename, readXM, s) +func XM(r io.Reader, s *settings.Settings) (playback.Playback, error) { + return common.Load(r, readXM, xmPlayback.NewManager, s) } diff --git a/format/xm/load/xmformat.go b/format/xm/load/xmformat.go index de35139..8a988ba 100644 --- a/format/xm/load/xmformat.go +++ b/format/xm/load/xmformat.go @@ -2,6 +2,7 @@ package load import ( "errors" + "io" "math" xmfile "github.com/gotracker/goaudiofile/music/tracked/xm" @@ -13,18 +14,17 @@ import ( "github.com/gotracker/voice/loop" "github.com/gotracker/voice/pcm" - formatutil "github.com/gotracker/playback/format/internal/util" - "github.com/gotracker/playback/format/settings" - xmPanning "github.com/gotracker/playback/format/xm/conversion/panning" - xmPeriod "github.com/gotracker/playback/format/xm/conversion/period" - xmVolume "github.com/gotracker/playback/format/xm/conversion/volume" + "github.com/gotracker/playback/format/xm/channel" "github.com/gotracker/playback/format/xm/layout" - "github.com/gotracker/playback/format/xm/layout/channel" + xmPanning "github.com/gotracker/playback/format/xm/panning" + xmPeriod "github.com/gotracker/playback/format/xm/period" + xmVolume "github.com/gotracker/playback/format/xm/volume" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" "github.com/gotracker/playback/oscillator" - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" - "github.com/gotracker/playback/song/pattern" + "github.com/gotracker/playback/pattern" + "github.com/gotracker/playback/settings" ) func moduleHeaderToHeader(fh *xmfile.ModuleHeader) (*layout.Header, error) { @@ -370,13 +370,8 @@ func convertXmFileToSong(f *xmfile.File, s *settings.Settings) (*layout.Song, er return &song, nil } -func readXM(filename string, s *settings.Settings) (*layout.Song, error) { - buffer, err := formatutil.ReadFile(filename) - if err != nil { - return nil, err - } - - f, err := xmfile.Read(buffer) +func readXM(r io.Reader, s *settings.Settings) (*layout.Song, error) { + f, err := xmfile.Read(r) if err != nil { return nil, err } diff --git a/format/xm/conversion/note/note.go b/format/xm/note/note.go similarity index 88% rename from format/xm/conversion/note/note.go rename to format/xm/note/note.go index 2671279..4ae1e41 100644 --- a/format/xm/conversion/note/note.go +++ b/format/xm/note/note.go @@ -1,7 +1,7 @@ package note import ( - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" ) // FromXmNote converts an xm file note into a player note diff --git a/format/xm/conversion/panning/panning.go b/format/xm/panning/panning.go similarity index 100% rename from format/xm/conversion/panning/panning.go rename to format/xm/panning/panning.go diff --git a/format/xm/conversion/period/amiga.go b/format/xm/period/amiga.go similarity index 95% rename from format/xm/conversion/period/amiga.go rename to format/xm/period/amiga.go index 00d6b37..49cb56e 100644 --- a/format/xm/conversion/period/amiga.go +++ b/format/xm/period/amiga.go @@ -4,8 +4,8 @@ import ( "fmt" "math" - per "github.com/gotracker/playback/format/internal/period" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" + per "github.com/gotracker/playback/period" "github.com/heucuva/comparison" "github.com/gotracker/voice/period" diff --git a/format/xm/conversion/period/linear.go b/format/xm/period/linear.go similarity index 98% rename from format/xm/conversion/period/linear.go rename to format/xm/period/linear.go index 141fb77..aa9db33 100644 --- a/format/xm/conversion/period/linear.go +++ b/format/xm/period/linear.go @@ -4,7 +4,7 @@ import ( "fmt" "math" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" "github.com/heucuva/comparison" "github.com/gotracker/voice/period" diff --git a/format/xm/conversion/period/util.go b/format/xm/period/util.go similarity index 97% rename from format/xm/conversion/period/util.go rename to format/xm/period/util.go index 1155346..0c7ec6c 100644 --- a/format/xm/conversion/period/util.go +++ b/format/xm/period/util.go @@ -1,7 +1,7 @@ package period import ( - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" "github.com/gotracker/voice/period" ) diff --git a/format/xm/playback/channeldata_transaction.go b/format/xm/playback/channeldata_transaction.go index 510cf2a..0943c4c 100755 --- a/format/xm/playback/channeldata_transaction.go +++ b/format/xm/playback/channeldata_transaction.go @@ -3,13 +3,13 @@ package playback import ( "github.com/gotracker/gomixing/sampling" "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/format/xm/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" "github.com/gotracker/playback/format/xm/playback/effect" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" "github.com/gotracker/playback/player/state" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" ) type channelDataConverter struct{} @@ -85,14 +85,14 @@ type channelDataTransaction struct { state.ChannelDataTxnHelper[channel.Memory, channel.Data, channelDataConverter] } -func (d *channelDataTransaction) CommitPreRow(p intf.Playback, cs *state.ChannelState[channel.Memory, channel.Data], semitoneSetterFactory state.SemitoneSetterFactory[channel.Memory, channel.Data]) error { +func (d *channelDataTransaction) CommitPreRow(p playback.Playback, cs *state.ChannelState[channel.Memory, channel.Data], semitoneSetterFactory state.SemitoneSetterFactory[channel.Memory, channel.Data]) error { e := effect.Factory(cs.GetMemory(), d.Data) cs.SetActiveEffect(e) if e != nil { if onEff := p.GetOnEffect(); onEff != nil { onEff(e) } - if err := intf.EffectPreStart[channel.Memory, channel.Data](e, cs, p); err != nil { + if err := playback.EffectPreStart[channel.Memory, channel.Data](e, cs, p); err != nil { return err } } @@ -100,7 +100,7 @@ func (d *channelDataTransaction) CommitPreRow(p intf.Playback, cs *state.Channel return nil } -func (d *channelDataTransaction) CommitRow(p intf.Playback, cs *state.ChannelState[channel.Memory, channel.Data], semitoneSetterFactory state.SemitoneSetterFactory[channel.Memory, channel.Data]) error { +func (d *channelDataTransaction) CommitRow(p playback.Playback, cs *state.ChannelState[channel.Memory, channel.Data], semitoneSetterFactory state.SemitoneSetterFactory[channel.Memory, channel.Data]) error { if pos, ok := d.TargetPos.Get(); ok { cs.SetTargetPos(pos) } diff --git a/format/xm/playback/effect/effect_arpeggio.go b/format/xm/playback/effect/effect_arpeggio.go index 621d659..dbc4503 100644 --- a/format/xm/playback/effect/effect_arpeggio.go +++ b/format/xm/playback/effect/effect_arpeggio.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // Arpeggio defines an arpeggio effect type Arpeggio channel.DataEffect // '0' // Start triggers on the first tick, but before the Tick() function is called -func (e Arpeggio) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e Arpeggio) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() cs.SetPos(cs.GetTargetPos()) @@ -19,7 +19,7 @@ func (e Arpeggio) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Pl } // Tick is called on every tick -func (e Arpeggio) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e Arpeggio) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { xy := channel.DataEffect(e) if xy == 0 { return nil diff --git a/format/xm/playback/effect/effect_extrafineportadown.go b/format/xm/playback/effect/effect_extrafineportadown.go index 42310c5..4f1ced8 100644 --- a/format/xm/playback/effect/effect_extrafineportadown.go +++ b/format/xm/playback/effect/effect_extrafineportadown.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // ExtraFinePortaDown defines an extra-fine portamento down effect type ExtraFinePortaDown channel.DataEffect // 'X2x' // Start triggers on the first tick, but before the Tick() function is called -func (e ExtraFinePortaDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e ExtraFinePortaDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() diff --git a/format/xm/playback/effect/effect_extrafineportaup.go b/format/xm/playback/effect/effect_extrafineportaup.go index bb020c5..9281ad5 100644 --- a/format/xm/playback/effect/effect_extrafineportaup.go +++ b/format/xm/playback/effect/effect_extrafineportaup.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // ExtraFinePortaUp defines an extra-fine portamento up effect type ExtraFinePortaUp channel.DataEffect // 'X1x' // Start triggers on the first tick, but before the Tick() function is called -func (e ExtraFinePortaUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e ExtraFinePortaUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() diff --git a/format/xm/playback/effect/effect_fineportadown.go b/format/xm/playback/effect/effect_fineportadown.go index 0dceb46..551da99 100644 --- a/format/xm/playback/effect/effect_fineportadown.go +++ b/format/xm/playback/effect/effect_fineportadown.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // FinePortaDown defines an fine portamento down effect type FinePortaDown channel.DataEffect // 'E2x' // Start triggers on the first tick, but before the Tick() function is called -func (e FinePortaDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FinePortaDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() diff --git a/format/xm/playback/effect/effect_fineportaup.go b/format/xm/playback/effect/effect_fineportaup.go index 4febf05..657a8ca 100644 --- a/format/xm/playback/effect/effect_fineportaup.go +++ b/format/xm/playback/effect/effect_fineportaup.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // FinePortaUp defines an fine portamento up effect type FinePortaUp channel.DataEffect // 'E1x' // Start triggers on the first tick, but before the Tick() function is called -func (e FinePortaUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FinePortaUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() diff --git a/format/xm/playback/effect/effect_finevolslidedown.go b/format/xm/playback/effect/effect_finevolslidedown.go index aaee3ac..27b843c 100644 --- a/format/xm/playback/effect/effect_finevolslidedown.go +++ b/format/xm/playback/effect/effect_finevolslidedown.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // FineVolumeSlideDown defines a volume slide effect type FineVolumeSlideDown channel.DataEffect // 'EAx' // Start triggers on the first tick, but before the Tick() function is called -func (e FineVolumeSlideDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FineVolumeSlideDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() mem := cs.GetMemory() diff --git a/format/xm/playback/effect/effect_finevolslideup.go b/format/xm/playback/effect/effect_finevolslideup.go index f4bef1c..0c10ed6 100644 --- a/format/xm/playback/effect/effect_finevolslideup.go +++ b/format/xm/playback/effect/effect_finevolslideup.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // FineVolumeSlideUp defines a volume slide effect type FineVolumeSlideUp channel.DataEffect // 'EAx' // Start triggers on the first tick, but before the Tick() function is called -func (e FineVolumeSlideUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e FineVolumeSlideUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() mem := cs.GetMemory() diff --git a/format/xm/playback/effect/effect_globalvolumeslide.go b/format/xm/playback/effect/effect_globalvolumeslide.go index 9c6ec22..67e1800 100644 --- a/format/xm/playback/effect/effect_globalvolumeslide.go +++ b/format/xm/playback/effect/effect_globalvolumeslide.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" effectIntf "github.com/gotracker/playback/format/xm/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // GlobalVolumeSlide defines a global volume slide effect type GlobalVolumeSlide channel.DataEffect // 'H' // Start triggers on the first tick, but before the Tick() function is called -func (e GlobalVolumeSlide) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e GlobalVolumeSlide) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e GlobalVolumeSlide) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e GlobalVolumeSlide) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.GlobalVolumeSlide(channel.DataEffect(e)) diff --git a/format/xm/playback/effect/effect_notecut.go b/format/xm/playback/effect/effect_notecut.go index 0582b4f..a343c3e 100644 --- a/format/xm/playback/effect/effect_notecut.go +++ b/format/xm/playback/effect/effect_notecut.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // NoteCut defines a note cut effect type NoteCut channel.DataEffect // 'ECx' // Start triggers on the first tick, but before the Tick() function is called -func (e NoteCut) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e NoteCut) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e NoteCut) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e NoteCut) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { x := channel.DataEffect(e) & 0xf if x != 0 && currentTick == int(x) { diff --git a/format/xm/playback/effect/effect_notedelay.go b/format/xm/playback/effect/effect_notedelay.go index ec85734..559e884 100644 --- a/format/xm/playback/effect/effect_notedelay.go +++ b/format/xm/playback/effect/effect_notedelay.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" + "github.com/gotracker/playback/note" ) // NoteDelay defines a note delay effect type NoteDelay channel.DataEffect // 'EDx' // PreStart triggers when the effect enters onto the channel state -func (e NoteDelay) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e NoteDelay) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.SetNotePlayTick(true, note.ActionRetrigger, int(channel.DataEffect(e)&0x0F)) return nil } // Start triggers on the first tick, but before the Tick() function is called -func (e NoteDelay) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e NoteDelay) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/xm/playback/effect/effect_orderjump.go b/format/xm/playback/effect/effect_orderjump.go index 5c3c649..fa62293 100644 --- a/format/xm/playback/effect/effect_orderjump.go +++ b/format/xm/playback/effect/effect_orderjump.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/index" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" + "github.com/gotracker/playback/index" ) // OrderJump defines an order jump effect type OrderJump channel.DataEffect // 'B' // Start triggers on the first tick, but before the Tick() function is called -func (e OrderJump) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e OrderJump) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Stop is called on the last tick of the row, but after the Tick() function is called -func (e OrderJump) Stop(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, lastTick int) error { +func (e OrderJump) Stop(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, lastTick int) error { return p.SetNextOrder(index.Order(e)) } diff --git a/format/xm/playback/effect/effect_panslide.go b/format/xm/playback/effect/effect_panslide.go index 6aa908b..fc10d2b 100644 --- a/format/xm/playback/effect/effect_panslide.go +++ b/format/xm/playback/effect/effect_panslide.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - xmPanning "github.com/gotracker/playback/format/xm/conversion/panning" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" + xmPanning "github.com/gotracker/playback/format/xm/panning" ) // PanSlide defines a pan slide effect type PanSlide channel.DataEffect // 'Pxx' // Start triggers on the first tick, but before the Tick() function is called -func (e PanSlide) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PanSlide) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { xx := channel.DataEffect(e) x := xx >> 4 y := xx & 0x0F diff --git a/format/xm/playback/effect/effect_patterndelay.go b/format/xm/playback/effect/effect_patterndelay.go index 61ea3a5..dccb5c8 100644 --- a/format/xm/playback/effect/effect_patterndelay.go +++ b/format/xm/playback/effect/effect_patterndelay.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" effectIntf "github.com/gotracker/playback/format/xm/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // PatternDelay defines a pattern delay effect type PatternDelay channel.DataEffect // 'SEx' // PreStart triggers when the effect enters onto the channel state -func (e PatternDelay) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PatternDelay) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { m := p.(effectIntf.XM) return m.SetPatternDelay(int(channel.DataEffect(e) & 0x0F)) } // Start triggers on the first tick, but before the Tick() function is called -func (e PatternDelay) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PatternDelay) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/xm/playback/effect/effect_patternloop.go b/format/xm/playback/effect/effect_patternloop.go index 66f772a..1be3284 100644 --- a/format/xm/playback/effect/effect_patternloop.go +++ b/format/xm/playback/effect/effect_patternloop.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // PatternLoop defines a pattern loop effect type PatternLoop channel.DataEffect // 'E6x' // Start triggers on the first tick, but before the Tick() function is called -func (e PatternLoop) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PatternLoop) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := channel.DataEffect(e) & 0xF diff --git a/format/xm/playback/effect/effect_portadown.go b/format/xm/playback/effect/effect_portadown.go index 5e42050..b379bb4 100644 --- a/format/xm/playback/effect/effect_portadown.go +++ b/format/xm/playback/effect/effect_portadown.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // PortaDown defines a portamento down effect type PortaDown channel.DataEffect // '2' // Start triggers on the first tick, but before the Tick() function is called -func (e PortaDown) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PortaDown) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() return nil } // Tick is called on every tick -func (e PortaDown) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e PortaDown) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() xx := mem.PortaDown(channel.DataEffect(e)) diff --git a/format/xm/playback/effect/effect_portatonote.go b/format/xm/playback/effect/effect_portatonote.go index ec77a28..b0ae30e 100644 --- a/format/xm/playback/effect/effect_portatonote.go +++ b/format/xm/playback/effect/effect_portatonote.go @@ -3,9 +3,9 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" + "github.com/gotracker/playback/note" "github.com/heucuva/comparison" ) @@ -13,7 +13,7 @@ import ( type PortaToNote channel.DataEffect // '3' // Start triggers on the first tick, but before the Tick() function is called -func (e PortaToNote) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PortaToNote) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() if cmd := cs.GetData(); cmd != nil && cmd.HasNote() { @@ -24,7 +24,7 @@ func (e PortaToNote) Start(cs intf.Channel[channel.Memory, channel.Data], p intf } // Tick is called on every tick -func (e PortaToNote) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e PortaToNote) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { if currentTick == 0 { return nil } diff --git a/format/xm/playback/effect/effect_portaup.go b/format/xm/playback/effect/effect_portaup.go index 404299b..3f65ea3 100644 --- a/format/xm/playback/effect/effect_portaup.go +++ b/format/xm/playback/effect/effect_portaup.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // PortaUp defines a portamento up effect type PortaUp channel.DataEffect // '1' // Start triggers on the first tick, but before the Tick() function is called -func (e PortaUp) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e PortaUp) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() return nil } // Tick is called on every tick -func (e PortaUp) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e PortaUp) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() xx := mem.PortaUp(channel.DataEffect(e)) diff --git a/format/xm/playback/effect/effect_portavolslide.go b/format/xm/playback/effect/effect_portavolslide.go index e056dbc..9e62e9c 100644 --- a/format/xm/playback/effect/effect_portavolslide.go +++ b/format/xm/playback/effect/effect_portavolslide.go @@ -3,13 +3,13 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // PortaVolumeSlide defines a portamento-to-note combined with a volume slide effect type PortaVolumeSlide struct { // '5' - intf.CombinedEffect[channel.Memory, channel.Data] + playback.CombinedEffect[channel.Memory, channel.Data] } // NewPortaVolumeSlide creates a new PortaVolumeSlide object diff --git a/format/xm/playback/effect/effect_retriggernote.go b/format/xm/playback/effect/effect_retriggernote.go index 457ad00..127d1f0 100644 --- a/format/xm/playback/effect/effect_retriggernote.go +++ b/format/xm/playback/effect/effect_retriggernote.go @@ -5,21 +5,21 @@ import ( "github.com/gotracker/gomixing/sampling" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // RetriggerNote defines a retriggering effect type RetriggerNote channel.DataEffect // 'E9x' // Start triggers on the first tick, but before the Tick() function is called -func (e RetriggerNote) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e RetriggerNote) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e RetriggerNote) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e RetriggerNote) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { y := channel.DataEffect(e) & 0x0F if y == 0 { return nil diff --git a/format/xm/playback/effect/effect_retrigvolslide.go b/format/xm/playback/effect/effect_retrigvolslide.go index cbc03f1..04ef253 100644 --- a/format/xm/playback/effect/effect_retrigvolslide.go +++ b/format/xm/playback/effect/effect_retrigvolslide.go @@ -5,21 +5,21 @@ import ( "github.com/gotracker/gomixing/sampling" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // RetrigVolumeSlide defines a retriggering volume slide effect type RetrigVolumeSlide channel.DataEffect // 'R' // Start triggers on the first tick, but before the Tick() function is called -func (e RetrigVolumeSlide) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e RetrigVolumeSlide) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e RetrigVolumeSlide) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e RetrigVolumeSlide) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { x := channel.DataEffect(e) >> 4 y := channel.DataEffect(e) & 0x0F if y == 0 { diff --git a/format/xm/playback/effect/effect_rowjump.go b/format/xm/playback/effect/effect_rowjump.go index 09d970d..f9b37ee 100644 --- a/format/xm/playback/effect/effect_rowjump.go +++ b/format/xm/playback/effect/effect_rowjump.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/index" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" + "github.com/gotracker/playback/index" ) // RowJump defines a row jump effect type RowJump channel.DataEffect // 'D' // Start triggers on the first tick, but before the Tick() function is called -func (e RowJump) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e RowJump) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Stop is called on the last tick of the row, but after the Tick() function is called -func (e RowJump) Stop(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, lastTick int) error { +func (e RowJump) Stop(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, lastTick int) error { xy := channel.DataEffect(e) x := xy >> 4 y := xy & 0x0f diff --git a/format/xm/playback/effect/effect_sampleoffset.go b/format/xm/playback/effect/effect_sampleoffset.go index 5b72bdc..b8b1256 100644 --- a/format/xm/playback/effect/effect_sampleoffset.go +++ b/format/xm/playback/effect/effect_sampleoffset.go @@ -5,15 +5,15 @@ import ( "github.com/gotracker/gomixing/sampling" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // SampleOffset defines a sample offset effect type SampleOffset channel.DataEffect // '9' // Start triggers on the first tick, but before the Tick() function is called -func (e SampleOffset) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SampleOffset) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() mem := cs.GetMemory() xx := mem.SampleOffset(channel.DataEffect(e)) diff --git a/format/xm/playback/effect/effect_setcoarsepanposition.go b/format/xm/playback/effect/effect_setcoarsepanposition.go index 320b124..925a283 100644 --- a/format/xm/playback/effect/effect_setcoarsepanposition.go +++ b/format/xm/playback/effect/effect_setcoarsepanposition.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - xmPanning "github.com/gotracker/playback/format/xm/conversion/panning" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" + xmPanning "github.com/gotracker/playback/format/xm/panning" ) // SetCoarsePanPosition defines a set pan position effect type SetCoarsePanPosition channel.DataEffect // 'E8x' // Start triggers on the first tick, but before the Tick() function is called -func (e SetCoarsePanPosition) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetCoarsePanPosition) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() xy := channel.DataEffect(e) diff --git a/format/xm/playback/effect/effect_setenvelopeposition.go b/format/xm/playback/effect/effect_setenvelopeposition.go index 3ce113e..7bd2a17 100644 --- a/format/xm/playback/effect/effect_setenvelopeposition.go +++ b/format/xm/playback/effect/effect_setenvelopeposition.go @@ -3,15 +3,15 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // SetEnvelopePosition defines a set envelope position effect type SetEnvelopePosition channel.DataEffect // 'Lxx' // Start triggers on the first tick, but before the Tick() function is called -func (e SetEnvelopePosition) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetEnvelopePosition) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() xx := channel.DataEffect(e) diff --git a/format/xm/playback/effect/effect_setfinetune.go b/format/xm/playback/effect/effect_setfinetune.go index 4a556fa..a0f1fbc 100644 --- a/format/xm/playback/effect/effect_setfinetune.go +++ b/format/xm/playback/effect/effect_setfinetune.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" + "github.com/gotracker/playback/note" ) // SetFinetune defines a mod-style set finetune effect type SetFinetune channel.DataEffect // 'E5x' // PreStart triggers when the effect enters onto the channel state -func (e SetFinetune) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetFinetune) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { x := channel.DataEffect(e) & 0xf inst := cs.GetTargetInst() @@ -24,7 +24,7 @@ func (e SetFinetune) PreStart(cs intf.Channel[channel.Memory, channel.Data], p i } // Start triggers on the first tick, but before the Tick() function is called -func (e SetFinetune) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetFinetune) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/xm/playback/effect/effect_setglobalvolume.go b/format/xm/playback/effect/effect_setglobalvolume.go index 9369ea6..f024f3c 100644 --- a/format/xm/playback/effect/effect_setglobalvolume.go +++ b/format/xm/playback/effect/effect_setglobalvolume.go @@ -3,23 +3,23 @@ package effect import ( "fmt" - xmVolume "github.com/gotracker/playback/format/xm/conversion/volume" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" + xmVolume "github.com/gotracker/playback/format/xm/volume" ) // SetGlobalVolume defines a set global volume effect type SetGlobalVolume channel.DataEffect // 'G' // PreStart triggers when the effect enters onto the channel state -func (e SetGlobalVolume) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetGlobalVolume) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { v := xmVolume.XmVolume(e) p.SetGlobalVolume(v.Volume()) return nil } // Start triggers on the first tick, but before the Tick() function is called -func (e SetGlobalVolume) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetGlobalVolume) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/xm/playback/effect/effect_setpanposition.go b/format/xm/playback/effect/effect_setpanposition.go index f5131c7..8c36a20 100644 --- a/format/xm/playback/effect/effect_setpanposition.go +++ b/format/xm/playback/effect/effect_setpanposition.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - xmPanning "github.com/gotracker/playback/format/xm/conversion/panning" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" + xmPanning "github.com/gotracker/playback/format/xm/panning" ) // SetPanPosition defines a set pan position effect type SetPanPosition channel.DataEffect // '8xx' // Start triggers on the first tick, but before the Tick() function is called -func (e SetPanPosition) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetPanPosition) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() xx := uint8(e) diff --git a/format/xm/playback/effect/effect_setspeed.go b/format/xm/playback/effect/effect_setspeed.go index 889ca04..964e868 100644 --- a/format/xm/playback/effect/effect_setspeed.go +++ b/format/xm/playback/effect/effect_setspeed.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" effectIntf "github.com/gotracker/playback/format/xm/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // SetSpeed defines a set speed effect type SetSpeed channel.DataEffect // 'F' // PreStart triggers when the effect enters onto the channel state -func (e SetSpeed) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetSpeed) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { if e != 0 { m := p.(effectIntf.XM) if err := m.SetTicks(int(e)); err != nil { @@ -23,7 +23,7 @@ func (e SetSpeed) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf } // Start triggers on the first tick, but before the Tick() function is called -func (e SetSpeed) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetSpeed) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } diff --git a/format/xm/playback/effect/effect_settempo.go b/format/xm/playback/effect/effect_settempo.go index 3a7470b..d9b210a 100644 --- a/format/xm/playback/effect/effect_settempo.go +++ b/format/xm/playback/effect/effect_settempo.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" effectIntf "github.com/gotracker/playback/format/xm/playback/effect/intf" - "github.com/gotracker/playback/player/intf" ) // SetTempo defines a set tempo effect type SetTempo channel.DataEffect // 'F' // PreStart triggers when the effect enters onto the channel state -func (e SetTempo) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetTempo) PreStart(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { if e > 0x20 { m := p.(effectIntf.XM) if err := m.SetTempo(int(e)); err != nil { @@ -23,13 +23,13 @@ func (e SetTempo) PreStart(cs intf.Channel[channel.Memory, channel.Data], p intf } // Start triggers on the first tick, but before the Tick() function is called -func (e SetTempo) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetTempo) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e SetTempo) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e SetTempo) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { m := p.(effectIntf.XM) return m.SetTempo(int(e)) } diff --git a/format/xm/playback/effect/effect_settremolowaveform.go b/format/xm/playback/effect/effect_settremolowaveform.go index 90c135b..b1149b9 100644 --- a/format/xm/playback/effect/effect_settremolowaveform.go +++ b/format/xm/playback/effect/effect_settremolowaveform.go @@ -5,15 +5,15 @@ import ( "github.com/gotracker/voice/oscillator" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // SetTremoloWaveform defines a set tremolo waveform effect type SetTremoloWaveform channel.DataEffect // 'E7x' // Start triggers on the first tick, but before the Tick() function is called -func (e SetTremoloWaveform) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetTremoloWaveform) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := channel.DataEffect(e) & 0xf diff --git a/format/xm/playback/effect/effect_setvibratowaveform.go b/format/xm/playback/effect/effect_setvibratowaveform.go index 3fe86de..53183c3 100644 --- a/format/xm/playback/effect/effect_setvibratowaveform.go +++ b/format/xm/playback/effect/effect_setvibratowaveform.go @@ -5,15 +5,15 @@ import ( "github.com/gotracker/voice/oscillator" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // SetVibratoWaveform defines a set vibrato waveform effect type SetVibratoWaveform channel.DataEffect // 'E4x' // Start triggers on the first tick, but before the Tick() function is called -func (e SetVibratoWaveform) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetVibratoWaveform) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() x := channel.DataEffect(e) & 0xf diff --git a/format/xm/playback/effect/effect_setvolume.go b/format/xm/playback/effect/effect_setvolume.go index e112060..d98f85f 100644 --- a/format/xm/playback/effect/effect_setvolume.go +++ b/format/xm/playback/effect/effect_setvolume.go @@ -3,16 +3,16 @@ package effect import ( "fmt" - xmVolume "github.com/gotracker/playback/format/xm/conversion/volume" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" + xmVolume "github.com/gotracker/playback/format/xm/volume" ) // SetVolume defines a volume slide effect type SetVolume channel.DataEffect // 'C' // Start triggers on the first tick, but before the Tick() function is called -func (e SetVolume) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e SetVolume) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() xx := xmVolume.XmVolume(e) diff --git a/format/xm/playback/effect/effect_tremolo.go b/format/xm/playback/effect/effect_tremolo.go index 5a1c9d0..13bd2fa 100644 --- a/format/xm/playback/effect/effect_tremolo.go +++ b/format/xm/playback/effect/effect_tremolo.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // Tremolo defines a tremolo effect type Tremolo channel.DataEffect // '7' // Start triggers on the first tick, but before the Tick() function is called -func (e Tremolo) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e Tremolo) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e Tremolo) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e Tremolo) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.Tremolo(channel.DataEffect(e)) // NOTE: JBC - XM updates on tick 0, but MOD does not. diff --git a/format/xm/playback/effect/effect_tremor.go b/format/xm/playback/effect/effect_tremor.go index 42a3570..dd6ffc9 100644 --- a/format/xm/playback/effect/effect_tremor.go +++ b/format/xm/playback/effect/effect_tremor.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // Tremor defines a tremor effect type Tremor channel.DataEffect // 'T' // Start triggers on the first tick, but before the Tick() function is called -func (e Tremor) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e Tremor) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e Tremor) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e Tremor) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { if currentTick != 0 { mem := cs.GetMemory() x, y := mem.Tremor(channel.DataEffect(e)) diff --git a/format/xm/playback/effect/effect_vibrato.go b/format/xm/playback/effect/effect_vibrato.go index f0fa0fe..583caaf 100644 --- a/format/xm/playback/effect/effect_vibrato.go +++ b/format/xm/playback/effect/effect_vibrato.go @@ -3,22 +3,22 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // Vibrato defines a vibrato effect type Vibrato channel.DataEffect // '4' // Start triggers on the first tick, but before the Tick() function is called -func (e Vibrato) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e Vibrato) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() cs.UnfreezePlayback() return nil } // Tick is called on every tick -func (e Vibrato) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e Vibrato) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.Vibrato(channel.DataEffect(e)) // NOTE: JBC - XM updates on tick 0, but MOD does not. diff --git a/format/xm/playback/effect/effect_vibratovolslide.go b/format/xm/playback/effect/effect_vibratovolslide.go index f7e2aaa..caf9f06 100644 --- a/format/xm/playback/effect/effect_vibratovolslide.go +++ b/format/xm/playback/effect/effect_vibratovolslide.go @@ -3,13 +3,13 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // VibratoVolumeSlide defines a combination vibrato and volume slide effect type VibratoVolumeSlide struct { // '6' - intf.CombinedEffect[channel.Memory, channel.Data] + playback.CombinedEffect[channel.Memory, channel.Data] } // NewVibratoVolumeSlide creates a new VibratoVolumeSlide object diff --git a/format/xm/playback/effect/effect_volslide.go b/format/xm/playback/effect/effect_volslide.go index 3a31fb9..54cd068 100644 --- a/format/xm/playback/effect/effect_volslide.go +++ b/format/xm/playback/effect/effect_volslide.go @@ -3,21 +3,21 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) // VolumeSlide defines a volume slide effect type VolumeSlide channel.DataEffect // 'A' // Start triggers on the first tick, but before the Tick() function is called -func (e VolumeSlide) Start(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback) error { +func (e VolumeSlide) Start(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback) error { cs.ResetRetriggerCount() return nil } // Tick is called on every tick -func (e VolumeSlide) Tick(cs intf.Channel[channel.Memory, channel.Data], p intf.Playback, currentTick int) error { +func (e VolumeSlide) Tick(cs playback.Channel[channel.Memory, channel.Data], p playback.Playback, currentTick int) error { mem := cs.GetMemory() x, y := mem.VolumeSlide(channel.DataEffect(e)) diff --git a/format/xm/playback/effect/effectfactory.go b/format/xm/playback/effect/effectfactory.go index 66833c0..9fdddf8 100644 --- a/format/xm/playback/effect/effectfactory.go +++ b/format/xm/playback/effect/effectfactory.go @@ -3,17 +3,17 @@ package effect import ( "fmt" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" ) type EffectXM interface { - intf.Effect + playback.Effect } // VolEff is a combined effect that includes a volume effect and a standard effect type VolEff struct { - intf.CombinedEffect[channel.Memory, channel.Data] + playback.CombinedEffect[channel.Memory, channel.Data] eff EffectXM } diff --git a/format/xm/playback/effect/effectfactory_standard.go b/format/xm/playback/effect/effectfactory_standard.go index 114eac8..5fb66ea 100644 --- a/format/xm/playback/effect/effectfactory_standard.go +++ b/format/xm/playback/effect/effectfactory_standard.go @@ -1,7 +1,7 @@ package effect import ( - "github.com/gotracker/playback/format/xm/layout/channel" + "github.com/gotracker/playback/format/xm/channel" ) func standardEffectFactory(mem *channel.Memory, cd *channel.Data) EffectXM { diff --git a/format/xm/playback/effect/effectfactory_volume.go b/format/xm/playback/effect/effectfactory_volume.go index bc0fc39..4a57234 100644 --- a/format/xm/playback/effect/effectfactory_volume.go +++ b/format/xm/playback/effect/effectfactory_volume.go @@ -1,8 +1,8 @@ package effect import ( - xmVolume "github.com/gotracker/playback/format/xm/conversion/volume" - "github.com/gotracker/playback/format/xm/layout/channel" + "github.com/gotracker/playback/format/xm/channel" + xmVolume "github.com/gotracker/playback/format/xm/volume" ) func volumeEffectFactory(mem *channel.Memory, v xmVolume.VolEffect) EffectXM { diff --git a/format/xm/playback/effect/intf/intf.go b/format/xm/playback/effect/intf/intf.go index 6a849be..7935606 100644 --- a/format/xm/playback/effect/intf/intf.go +++ b/format/xm/playback/effect/intf/intf.go @@ -2,7 +2,7 @@ package intf import ( "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/song/index" + "github.com/gotracker/playback/index" ) // XM is an interface to XM effect operations diff --git a/format/xm/playback/effect/unhandled.go b/format/xm/playback/effect/unhandled.go index d0a15e9..a0f65f6 100644 --- a/format/xm/playback/effect/unhandled.go +++ b/format/xm/playback/effect/unhandled.go @@ -3,10 +3,10 @@ package effect import ( "fmt" - xmVolume "github.com/gotracker/playback/format/xm/conversion/volume" - "github.com/gotracker/playback/format/xm/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" effectIntf "github.com/gotracker/playback/format/xm/playback/effect/intf" - "github.com/gotracker/playback/player/intf" + xmVolume "github.com/gotracker/playback/format/xm/volume" ) // UnhandledCommand is an unhandled command @@ -16,7 +16,7 @@ type UnhandledCommand struct { } // PreStart triggers when the effect enters onto the channel state -func (e UnhandledCommand) PreStart(cs intf.Channel[channel.Memory, channel.Data], m effectIntf.XM) error { +func (e UnhandledCommand) PreStart(cs playback.Channel[channel.Memory, channel.Data], m effectIntf.XM) error { if !m.IgnoreUnknownEffect() { panic("unhandled command") } @@ -40,7 +40,7 @@ type UnhandledVolCommand struct { } // PreStart triggers when the effect enters onto the channel state -func (e UnhandledVolCommand) PreStart(cs intf.Channel[channel.Memory, channel.Data], m effectIntf.XM) error { +func (e UnhandledVolCommand) PreStart(cs playback.Channel[channel.Memory, channel.Data], m effectIntf.XM) error { if !m.IgnoreUnknownEffect() { panic("unhandled command") } diff --git a/format/xm/playback/effect/util.go b/format/xm/playback/effect/util.go index b7cff1a..ef7076e 100644 --- a/format/xm/playback/effect/util.go +++ b/format/xm/playback/effect/util.go @@ -3,15 +3,15 @@ package effect import ( "github.com/gotracker/voice/oscillator" - xmVolume "github.com/gotracker/playback/format/xm/conversion/volume" - "github.com/gotracker/playback/format/xm/layout/channel" + "github.com/gotracker/playback" + "github.com/gotracker/playback/format/xm/channel" effectIntf "github.com/gotracker/playback/format/xm/playback/effect/intf" - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song/note" + xmVolume "github.com/gotracker/playback/format/xm/volume" + "github.com/gotracker/playback/note" "github.com/heucuva/comparison" ) -func doVolSlide(cs intf.Channel[channel.Memory, channel.Data], delta float32, multiplier float32) error { +func doVolSlide(cs playback.Channel[channel.Memory, channel.Data], delta float32, multiplier float32) error { av := cs.GetActiveVolume() v := xmVolume.ToVolumeXM(av) vol := int16((float32(v) + delta) * multiplier) @@ -41,7 +41,7 @@ func doGlobalVolSlide(m effectIntf.XM, delta float32, multiplier float32) error return nil } -func doPortaByDeltaAmiga(cs intf.Channel[channel.Memory, channel.Data], delta int) error { +func doPortaByDeltaAmiga(cs playback.Channel[channel.Memory, channel.Data], delta int) error { period := cs.GetPeriod() if period == nil { return nil @@ -53,7 +53,7 @@ func doPortaByDeltaAmiga(cs intf.Channel[channel.Memory, channel.Data], delta in return nil } -func doPortaByDeltaLinear(cs intf.Channel[channel.Memory, channel.Data], delta int) error { +func doPortaByDeltaLinear(cs playback.Channel[channel.Memory, channel.Data], delta int) error { period := cs.GetPeriod() if period == nil { return nil @@ -65,7 +65,7 @@ func doPortaByDeltaLinear(cs intf.Channel[channel.Memory, channel.Data], delta i return nil } -func doPortaUp(cs intf.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, linearFreqSlides bool) error { +func doPortaUp(cs playback.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, linearFreqSlides bool) error { delta := int(amount * multiplier) if linearFreqSlides { return doPortaByDeltaLinear(cs, delta) @@ -73,7 +73,7 @@ func doPortaUp(cs intf.Channel[channel.Memory, channel.Data], amount float32, mu return doPortaByDeltaAmiga(cs, -delta) } -func doPortaUpToNote(cs intf.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, target note.Period, linearFreqSlides bool) error { +func doPortaUpToNote(cs playback.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, target note.Period, linearFreqSlides bool) error { if err := doPortaUp(cs, amount, multiplier, linearFreqSlides); err != nil { return err } @@ -83,7 +83,7 @@ func doPortaUpToNote(cs intf.Channel[channel.Memory, channel.Data], amount float return nil } -func doPortaDown(cs intf.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, linearFreqSlides bool) error { +func doPortaDown(cs playback.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, linearFreqSlides bool) error { delta := int(amount * multiplier) if linearFreqSlides { return doPortaByDeltaLinear(cs, -delta) @@ -91,7 +91,7 @@ func doPortaDown(cs intf.Channel[channel.Memory, channel.Data], amount float32, return doPortaByDeltaAmiga(cs, delta) } -func doPortaDownToNote(cs intf.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, target note.Period, linearFreqSlides bool) error { +func doPortaDownToNote(cs playback.Channel[channel.Memory, channel.Data], amount float32, multiplier float32, target note.Period, linearFreqSlides bool) error { if err := doPortaDown(cs, amount, multiplier, linearFreqSlides); err != nil { return err } @@ -101,7 +101,7 @@ func doPortaDownToNote(cs intf.Channel[channel.Memory, channel.Data], amount flo return nil } -func doVibrato(cs intf.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32) error { +func doVibrato(cs playback.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32) error { mem := cs.GetMemory() vib := calculateWaveTable(cs, currentTick, speed, depth, multiplier, mem.VibratoOscillator()) delta := note.PeriodDelta(vib) @@ -109,7 +109,7 @@ func doVibrato(cs intf.Channel[channel.Memory, channel.Data], currentTick int, s return nil } -func doTremor(cs intf.Channel[channel.Memory, channel.Data], currentTick int, onTicks int, offTicks int) error { +func doTremor(cs playback.Channel[channel.Memory, channel.Data], currentTick int, onTicks int, offTicks int) error { mem := cs.GetMemory() tremor := mem.TremorMem() if tremor.IsActive() { @@ -125,7 +125,7 @@ func doTremor(cs intf.Channel[channel.Memory, channel.Data], currentTick int, on return nil } -func doArpeggio(cs intf.Channel[channel.Memory, channel.Data], currentTick int, arpSemitoneADelta int8, arpSemitoneBDelta int8) error { +func doArpeggio(cs playback.Channel[channel.Memory, channel.Data], currentTick int, arpSemitoneADelta int8, arpSemitoneBDelta int8) error { ns := cs.GetNoteSemitone() var arpSemitoneTarget note.Semitone switch currentTick % 3 { @@ -150,7 +150,7 @@ var ( } ) -func doVolSlideTwoThirds(cs intf.Channel[channel.Memory, channel.Data]) error { +func doVolSlideTwoThirds(cs playback.Channel[channel.Memory, channel.Data]) error { vol := xmVolume.ToVolumeXM(cs.GetActiveVolume()) if vol >= 64 { vol = 63 @@ -165,13 +165,13 @@ func doVolSlideTwoThirds(cs intf.Channel[channel.Memory, channel.Data]) error { return nil } -func doTremolo(cs intf.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32) error { +func doTremolo(cs playback.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32) error { mem := cs.GetMemory() delta := calculateWaveTable(cs, currentTick, speed, depth, multiplier, mem.TremoloOscillator()) return doVolSlide(cs, delta, 1.0) } -func calculateWaveTable(cs intf.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32, o oscillator.Oscillator) float32 { +func calculateWaveTable(cs playback.Channel[channel.Memory, channel.Data], currentTick int, speed channel.DataEffect, depth channel.DataEffect, multiplier float32, o oscillator.Oscillator) float32 { delta := o.GetWave(float32(depth) * multiplier) o.Advance(int(speed)) return delta diff --git a/format/xm/playback/playback.go b/format/xm/playback/playback.go index 32e4da0..007e39e 100644 --- a/format/xm/playback/playback.go +++ b/format/xm/playback/playback.go @@ -3,20 +3,20 @@ package playback import ( "github.com/gotracker/gomixing/volume" device "github.com/gotracker/gosound" + "github.com/gotracker/playback" - xmPeriod "github.com/gotracker/playback/format/xm/conversion/period" + "github.com/gotracker/playback/format/xm/channel" "github.com/gotracker/playback/format/xm/layout" - "github.com/gotracker/playback/format/xm/layout/channel" + xmPeriod "github.com/gotracker/playback/format/xm/period" "github.com/gotracker/playback/format/xm/playback/state/pattern" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/note" + playpattern "github.com/gotracker/playback/pattern" "github.com/gotracker/playback/player" "github.com/gotracker/playback/player/feature" - "github.com/gotracker/playback/player/intf" "github.com/gotracker/playback/player/output" "github.com/gotracker/playback/player/state" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/note" - playpattern "github.com/gotracker/playback/song/pattern" ) // Manager is a playback manager for XM music @@ -33,7 +33,7 @@ type Manager struct { premix *device.PremixData rowRenderState *rowRenderState - OnEffect func(intf.Effect) + OnEffect func(playback.Effect) } // NewManager creates a new manager for an XM song @@ -312,11 +312,11 @@ func (m *Manager) GetName() string { } // SetOnEffect sets the callback for an effect being generated for a channel -func (m *Manager) SetOnEffect(fn func(intf.Effect)) { +func (m *Manager) SetOnEffect(fn func(playback.Effect)) { m.OnEffect = fn } -func (m Manager) GetOnEffect() func(intf.Effect) { +func (m Manager) GetOnEffect() func(playback.Effect) { return m.OnEffect } diff --git a/format/xm/playback/playback_command.go b/format/xm/playback/playback_command.go index e6ae68d..f6ecb5f 100644 --- a/format/xm/playback/playback_command.go +++ b/format/xm/playback/playback_command.go @@ -1,14 +1,14 @@ package playback import ( + "github.com/gotracker/playback" "github.com/gotracker/voice" - "github.com/gotracker/playback/format/internal/filter" - xmPeriod "github.com/gotracker/playback/format/xm/conversion/period" - "github.com/gotracker/playback/format/xm/layout/channel" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback/filter" + "github.com/gotracker/playback/format/xm/channel" + xmPeriod "github.com/gotracker/playback/format/xm/period" + "github.com/gotracker/playback/note" "github.com/gotracker/playback/player/state" - "github.com/gotracker/playback/song/note" "github.com/gotracker/voice/period" ) @@ -17,7 +17,7 @@ type doNoteCalc struct { UpdateFunc state.PeriodUpdateFunc } -func (o doNoteCalc) Process(p intf.Playback, cs *state.ChannelState[channel.Memory, channel.Data]) error { +func (o doNoteCalc) Process(p playback.Playback, cs *state.ChannelState[channel.Memory, channel.Data]) error { if o.UpdateFunc == nil { return nil } diff --git a/format/xm/playback/playback_pattern.go b/format/xm/playback/playback_pattern.go index a324084..163af39 100644 --- a/format/xm/playback/playback_pattern.go +++ b/format/xm/playback/playback_pattern.go @@ -4,7 +4,7 @@ import ( "errors" "time" - "github.com/gotracker/playback/format/xm/layout/channel" + "github.com/gotracker/playback/format/xm/channel" "github.com/gotracker/playback/player/state" "github.com/gotracker/playback/song" ) diff --git a/format/xm/playback/playback_test.go b/format/xm/playback/playback_test.go deleted file mode 100644 index 46ecaca..0000000 --- a/format/xm/playback/playback_test.go +++ /dev/null @@ -1,141 +0,0 @@ -package playback_test - -import ( - "flag" - "math" - "os" - "testing" - "time" - - "github.com/gotracker/playback/format/settings" - "github.com/gotracker/playback/format/xm" - "github.com/gotracker/playback/player/feature" - "github.com/gotracker/playback/song" -) - -var ( - enableTremor bool - enablePortaLinkMem bool -) - -func TestTremor(t *testing.T) { - if !enableTremor { - t.Skip() - } - - fn := "../../../../test/Tremor.xm" - - sampleRate := 44100 - channels := 2 - bitsPerSample := 16 - - performChannelComparison(t, fn, sampleRate, channels, bitsPerSample) -} - -func TestPortaLinkMem(t *testing.T) { - if !enablePortaLinkMem { - t.Skip() - } - - fn := "../../../../test/Porta-LinkMem.xm" - - sampleRate := 44100 - channels := 2 - bitsPerSample := 16 - - performChannelComparison(t, fn, sampleRate, channels, bitsPerSample) -} - -func performChannelComparison(t *testing.T, fn string, sampleRate int, channels int, bitsPerSample int) { - t.Helper() - - s := &settings.Settings{} - playback, err := xm.XM.Load(fn, s) - if err != nil { - t.Fatalf("Could not create song state! err[%v]", err) - } - - if err := playback.SetupSampler(sampleRate, channels, bitsPerSample); err != nil { - t.Fatalf("Could not setup playback sampler! err[%v]", err) - } - - if err := playback.Configure([]feature.Feature{feature.SongLoop{Count: 0}}); err != nil { - t.Fatalf("Could not setup player! err[%v]", err) - } - - for { - premixData, err := playback.Generate(time.Duration(0)) - if err != nil { - if err == song.ErrStopSong { - break - } - t.Fatal(err) - } - - if len(premixData.Data) == 0 { - continue - } - - if len(premixData.Data) < 2 { - t.Fatal("Not enough tracks of data in premix buffer") - } else if len(premixData.Data) > 2 { - t.Fatal("Too many tracks of data in premix buffer") - } - - test := premixData.Data[0] - control := premixData.Data[1] - - if len(test) < 1 { - t.Fatal("Not enough blocks of premixed track data in premix buffer") - } else if len(test) > 1 { - t.Fatal("Too many blocks of premixed track data in premix buffer") - } - - tc := test[0] - cc := control[0] - - if tc.Data == nil && cc.Data == nil { - continue - } else if tc.Data == nil { - t.Fatal("Not enough channel data provided in test track premix buffer") - } else if cc.Data == nil { - t.Fatal("Not enough channel data provided in test track premix buffer") - } - - if len(tc.Data) < channels { - t.Fatal("Not enough output channels of premixed track data in test track premix buffer") - } else if len(tc.Data) > channels { - t.Fatal("Too many output channels of premixed track data in test track premix buffer") - } - - if len(cc.Data) < channels { - t.Fatal("Not enough output channels of premixed track data in control track premix buffer") - } else if len(cc.Data) > channels { - t.Fatal("Too many output channels of premixed track data in control track premix buffer") - } - - for c := 0; c < channels; c++ { - td := tc.Data[c] - cd := cc.Data[c] - - if td.Channels != cd.Channels { - t.Fatal("test track premix buffer length is not the same as for the control track") - } - - for i := 0; i < td.Channels; i++ { - ts := td.StaticMatrix[i] - cs := cd.StaticMatrix[i] - if math.Abs(float64(ts-cs)) >= 0.15 { - t.Fatal("test track premix buffer data is not the same as for the control track") - } - } - } - } -} - -func TestMain(m *testing.M) { - flag.BoolVar(&enableTremor, "Tremor", false, "Enable Tremor test") - flag.BoolVar(&enablePortaLinkMem, "PortaLinkMem", false, "Enable PortaLinkMem test") - flag.Parse() - os.Exit(m.Run()) -} diff --git a/format/xm/playback/playback_textoutput.go b/format/xm/playback/playback_textoutput.go index b1e07b2..ee5cdc9 100644 --- a/format/xm/playback/playback_textoutput.go +++ b/format/xm/playback/playback_textoutput.go @@ -1,7 +1,7 @@ package playback import ( - "github.com/gotracker/playback/format/xm/layout/channel" + "github.com/gotracker/playback/format/xm/channel" "github.com/gotracker/playback/player/render" ) diff --git a/format/xm/playback/state/pattern/pattern.go b/format/xm/playback/state/pattern/pattern.go index 46a70f2..5c19be6 100644 --- a/format/xm/playback/state/pattern/pattern.go +++ b/format/xm/playback/state/pattern/pattern.go @@ -3,12 +3,12 @@ package pattern import ( "errors" - formatutil "github.com/gotracker/playback/format/internal/util" - "github.com/gotracker/playback/format/xm/layout/channel" + "github.com/gotracker/playback/format/xm/channel" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/pattern" "github.com/gotracker/playback/player/feature" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/pattern" + formatutil "github.com/gotracker/playback/util" "github.com/heucuva/optional" ) diff --git a/format/xm/conversion/volume/voleffect.go b/format/xm/volume/voleffect.go similarity index 100% rename from format/xm/conversion/volume/voleffect.go rename to format/xm/volume/voleffect.go diff --git a/format/xm/conversion/volume/volume.go b/format/xm/volume/volume.go similarity index 100% rename from format/xm/conversion/volume/volume.go rename to format/xm/volume/volume.go diff --git a/format/xm/xm.go b/format/xm/xm.go index 3ea78d0..935991d 100644 --- a/format/xm/xm.go +++ b/format/xm/xm.go @@ -2,9 +2,12 @@ package xm import ( - "github.com/gotracker/playback/format/settings" + "io" + + "github.com/gotracker/playback" "github.com/gotracker/playback/format/xm/load" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback/settings" + "github.com/gotracker/playback/util" ) type format struct{} @@ -15,6 +18,16 @@ var ( ) // Load loads an XM file into a playback system -func (f format) Load(filename string, s *settings.Settings) (intf.Playback, error) { - return load.XM(filename, s) +func (f format) Load(filename string, s *settings.Settings) (playback.Playback, error) { + r, err := util.ReadFile(filename) + if err != nil { + return nil, err + } + + return f.LoadFromReader(r, s) +} + +// LoadFromReader loads an XM file on a reader into a playback system +func (f format) LoadFromReader(r io.Reader, s *settings.Settings) (playback.Playback, error) { + return load.XM(r, s) } diff --git a/song/index/order.go b/index/order.go similarity index 100% rename from song/index/order.go rename to index/order.go diff --git a/song/index/pattern.go b/index/pattern.go similarity index 100% rename from song/index/pattern.go rename to index/pattern.go diff --git a/song/index/row.go b/index/row.go similarity index 100% rename from song/index/row.go rename to index/row.go diff --git a/song/instrument/instrument.go b/instrument/instrument.go similarity index 98% rename from song/instrument/instrument.go rename to instrument/instrument.go index 0a28053..8ceb566 100644 --- a/song/instrument/instrument.go +++ b/instrument/instrument.go @@ -8,7 +8,7 @@ import ( "github.com/gotracker/voice" "github.com/gotracker/playback/filter" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" "github.com/heucuva/optional" ) diff --git a/song/instrument/instrument_opl2.go b/instrument/instrument_opl2.go similarity index 100% rename from song/instrument/instrument_opl2.go rename to instrument/instrument_opl2.go diff --git a/song/instrument/instrument_pcm.go b/instrument/instrument_pcm.go similarity index 100% rename from song/instrument/instrument_pcm.go rename to instrument/instrument_pcm.go diff --git a/song/instrument/sample.go b/instrument/sample.go similarity index 95% rename from song/instrument/sample.go rename to instrument/sample.go index cf6bc82..fd3c2f0 100644 --- a/song/instrument/sample.go +++ b/instrument/sample.go @@ -4,7 +4,7 @@ import ( "github.com/gotracker/gomixing/volume" "github.com/gotracker/voice/pcm" - "github.com/gotracker/playback/format/settings" + "github.com/gotracker/playback/settings" ) func NewSample(data []byte, length int, channels int, format pcm.SampleDataFormat, s *settings.Settings) (pcm.Sample, error) { diff --git a/song/instrument/util.go b/instrument/util.go similarity index 100% rename from song/instrument/util.go rename to instrument/util.go diff --git a/format/internal/memory/value.go b/memory/value.go similarity index 100% rename from format/internal/memory/value.go rename to memory/value.go diff --git a/song/note/action.go b/note/action.go similarity index 100% rename from song/note/action.go rename to note/action.go diff --git a/song/note/keyoct.go b/note/keyoct.go similarity index 100% rename from song/note/keyoct.go rename to note/keyoct.go diff --git a/song/note/note.go b/note/note.go similarity index 100% rename from song/note/note.go rename to note/note.go diff --git a/song/note/note_test.go b/note/note_test.go similarity index 98% rename from song/note/note_test.go rename to note/note_test.go index 681b7e2..0fc3cbd 100644 --- a/song/note/note_test.go +++ b/note/note_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" "github.com/heucuva/comparison" "github.com/gotracker/voice/period" diff --git a/song/note/period.go b/note/period.go similarity index 100% rename from song/note/period.go rename to note/period.go diff --git a/song/note/semitone.go b/note/semitone.go similarity index 100% rename from song/note/semitone.go rename to note/semitone.go diff --git a/song/note/util.go b/note/util.go similarity index 100% rename from song/note/util.go rename to note/util.go diff --git a/song/pattern/pattern.go b/pattern/pattern.go similarity index 96% rename from song/pattern/pattern.go rename to pattern/pattern.go index 10a52c2..13d9b8f 100644 --- a/song/pattern/pattern.go +++ b/pattern/pattern.go @@ -1,8 +1,8 @@ package pattern import ( + "github.com/gotracker/playback/index" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/index" ) // RowData is the data for each row diff --git a/song/pattern/transaction.go b/pattern/transaction.go similarity index 98% rename from song/pattern/transaction.go rename to pattern/transaction.go index 24df3d1..b2abbeb 100644 --- a/song/pattern/transaction.go +++ b/pattern/transaction.go @@ -1,7 +1,7 @@ package pattern import ( - "github.com/gotracker/playback/song/index" + "github.com/gotracker/playback/index" "github.com/heucuva/optional" ) diff --git a/format/internal/period/protracker.go b/period/protracker.go similarity index 92% rename from format/internal/period/protracker.go rename to period/protracker.go index 9117ca7..a188284 100644 --- a/format/internal/period/protracker.go +++ b/period/protracker.go @@ -1,8 +1,8 @@ package period import ( - "github.com/gotracker/playback/format/internal/util" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" + "github.com/gotracker/playback/util" "github.com/gotracker/voice/period" ) diff --git a/player/intf/playback.go b/playback.go similarity index 89% rename from player/intf/playback.go rename to playback.go index 228e89b..e3adeca 100644 --- a/player/intf/playback.go +++ b/playback.go @@ -1,15 +1,15 @@ -package intf +package playback import ( "time" device "github.com/gotracker/gosound" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/pattern" "github.com/gotracker/playback/player/feature" "github.com/gotracker/playback/player/output" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/pattern" ) // Playback is an interface for rendering a song to output data diff --git a/player/player.go b/player/player.go deleted file mode 100644 index e0fd38d..0000000 --- a/player/player.go +++ /dev/null @@ -1,233 +0,0 @@ -package player - -import ( - "context" - "errors" - "log" - "time" - - device "github.com/gotracker/gosound" - - "github.com/gotracker/playback/player/intf" - "github.com/gotracker/playback/song" -) - -type playerState int - -const ( - playerStateIdle = playerState(iota) - playerStatePlaying - playerStatePaused - playerStateStopped -) - -// Player is a player of fine tracked musics -type Player struct { - output chan<- *device.PremixData - ctx context.Context - cancel context.CancelFunc - state playerState - playCh chan struct{} - playRespCh chan error - pauseCh chan struct{} - pauseRespCh chan error - resumeCh chan struct{} - resumeRespCh chan error - stopCh chan struct{} - stopRespCh chan error - lastUpdateTime time.Time - playback intf.Playback - ticker *time.Ticker - tickerCh <-chan time.Time - myTickerCh chan time.Time -} - -// NewPlayer returns a new Player instance -func NewPlayer(ctx context.Context, output chan<- *device.PremixData, tickInterval time.Duration) (*Player, error) { - if ctx == nil { - ctx = context.Background() - } - - if output == nil { - return nil, errors.New("a valid output channel must be provided") - } - - myCtx, cancel := context.WithCancel(ctx) - - p := Player{ - output: output, - ctx: myCtx, - cancel: cancel, - state: playerStateIdle, - playCh: make(chan struct{}, 1), - playRespCh: make(chan error, 1), - pauseCh: make(chan struct{}, 1), - pauseRespCh: make(chan error, 1), - resumeCh: make(chan struct{}, 1), - resumeRespCh: make(chan error, 1), - stopCh: make(chan struct{}, 1), - stopRespCh: make(chan error, 1), - } - - if tickInterval != time.Duration(0) { - p.ticker = time.NewTicker(tickInterval) - p.tickerCh = p.ticker.C - } else { - p.myTickerCh = make(chan time.Time, 1) - p.tickerCh = p.myTickerCh - p.myTickerCh <- time.Now() - } - - go func() { - defer p.cancel() - if err := p.runStateMachine(); err != nil { - if err != song.ErrStopSong { - log.Fatalln(err) - } - } - p.state = playerStateStopped - }() - - return &p, nil -} - -// Play starts a player playing -func (p *Player) Play(playback intf.Playback) error { - if err := p.ctx.Err(); err != nil { - return err - } - - p.playback = playback - - p.playCh <- struct{}{} - return <-p.playRespCh -} - -// WaitUntilDone waits until the player is done -func (p *Player) WaitUntilDone() error { - <-p.ctx.Done() - return p.ctx.Err() -} - -func (p *Player) runStateMachine() error { - defer func() { - err := errors.New("end") - p.playRespCh <- err - p.pauseRespCh <- err - p.resumeRespCh <- err - p.stopRespCh <- err - - close(p.playCh) - close(p.playRespCh) - close(p.pauseCh) - close(p.pauseRespCh) - close(p.resumeCh) - close(p.resumeRespCh) - close(p.stopCh) - close(p.stopRespCh) - - if p.ticker != nil { - p.ticker.Stop() - } else { - close(p.myTickerCh) - } - }() - for { - var stateFunc func() error - switch p.state { - case playerStateIdle: - stateFunc = p.runStateIdle - case playerStatePlaying: - stateFunc = p.runStatePlaying - case playerStatePaused: - stateFunc = p.runStatePaused - default: - return song.ErrStopSong - } - if stateFunc == nil { - return song.ErrStopSong - } - if err := stateFunc(); err != nil { - return err - } - } -} - -func (p *Player) runStateIdle() error { - select { - case <-p.ctx.Done(): - return p.ctx.Err() - case <-p.playCh: - p.lastUpdateTime = time.Now() - p.state = playerStatePlaying - p.playRespCh <- nil - case <-p.pauseCh: - // eat it if we're idle. - p.pauseRespCh <- nil - case <-p.resumeCh: - // eat it if we're idle. - p.resumeRespCh <- nil - case <-p.stopCh: - p.stopRespCh <- nil - return song.ErrStopSong - } - return nil -} - -func (p *Player) runStatePaused() error { - select { - case <-p.ctx.Done(): - return p.ctx.Err() - case <-p.playCh: - p.playRespCh <- errors.New("already playing") - case <-p.pauseCh: - // eat it if we're already paused. - p.pauseRespCh <- nil - case <-p.resumeCh: - p.resumeRespCh <- nil - p.lastUpdateTime = time.Now() - p.state = playerStatePlaying - case <-p.stopCh: - p.stopRespCh <- nil - return song.ErrStopSong - } - return nil -} - -func (p *Player) runStatePlaying() error { - select { - case <-p.ctx.Done(): - return p.ctx.Err() - case <-p.playCh: - p.playRespCh <- errors.New("already playing") - return nil - case <-p.pauseCh: - p.pauseRespCh <- nil - p.state = playerStatePaused - return nil - case <-p.resumeCh: - // eat it if we're already playing. - p.resumeRespCh <- nil - case <-p.stopCh: - p.stopRespCh <- nil - return song.ErrStopSong - case <-p.tickerCh: - if p.ticker == nil { - // give ourselves something to hit the next time through - p.myTickerCh <- time.Now() - } - } - - // run our update - now := time.Now() - delta := now.Sub(p.lastUpdateTime) - if err := p.update(delta); err != nil { - return err - } - p.lastUpdateTime = now - return nil -} - -func (p *Player) update(delta time.Duration) error { - return p.playback.Update(delta, p.output) -} diff --git a/player/state/active.go b/player/state/active.go index bf6df0b..a238657 100644 --- a/player/state/active.go +++ b/player/state/active.go @@ -8,7 +8,7 @@ import ( "github.com/gotracker/gomixing/volume" "github.com/gotracker/voice" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" ) // Active is the active state of a channel diff --git a/player/state/channel.go b/player/state/channel.go index 1dcbc49..e920da7 100644 --- a/player/state/channel.go +++ b/player/state/channel.go @@ -7,11 +7,11 @@ import ( "github.com/gotracker/gomixing/volume" "github.com/gotracker/voice" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" "github.com/gotracker/playback/player/output" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" voiceImpl "github.com/gotracker/playback/voice" "github.com/heucuva/optional" ) @@ -22,11 +22,11 @@ type NoteTrigger struct { } type VolOp[TMemory, TChannelData any] interface { - Process(p intf.Playback, cs *ChannelState[TMemory, TChannelData]) error + Process(p playback.Playback, cs *ChannelState[TMemory, TChannelData]) error } type NoteOp[TMemory, TChannelData any] interface { - Process(p intf.Playback, cs *ChannelState[TMemory, TChannelData]) error + Process(p playback.Playback, cs *ChannelState[TMemory, TChannelData]) error } type PeriodUpdateFunc func(note.Period) @@ -39,7 +39,7 @@ type ChannelState[TMemory, TChannelData any] struct { targetState Playback prevState Active - ActiveEffect intf.Effect + ActiveEffect playback.Effect s song.Data txn ChannelDataTransaction[TMemory, TChannelData] @@ -105,11 +105,11 @@ func (cs *ChannelState[TMemory, TChannelData]) ResetStates() { cs.prevState.Reset() } -func (cs *ChannelState[TMemory, TChannelData]) GetActiveEffect() intf.Effect { +func (cs *ChannelState[TMemory, TChannelData]) GetActiveEffect() playback.Effect { return cs.ActiveEffect } -func (cs *ChannelState[TMemory, TChannelData]) SetActiveEffect(e intf.Effect) { +func (cs *ChannelState[TMemory, TChannelData]) SetActiveEffect(e playback.Effect) { cs.ActiveEffect = e } diff --git a/player/state/channel_transaction.go b/player/state/channel_transaction.go index 9ca4db5..2a43a7f 100644 --- a/player/state/channel_transaction.go +++ b/player/state/channel_transaction.go @@ -3,10 +3,10 @@ package state import ( "github.com/gotracker/gomixing/sampling" "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/player/intf" + "github.com/gotracker/playback" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" "github.com/gotracker/playback/song" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" "github.com/heucuva/optional" ) @@ -14,13 +14,13 @@ type ChannelDataTransaction[TMemory, TChannelData any] interface { GetData() *TChannelData SetData(data *TChannelData, s song.Data, cs *ChannelState[TMemory, TChannelData]) error - CommitPreRow(p intf.Playback, cs *ChannelState[TMemory, TChannelData], semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error - CommitRow(p intf.Playback, cs *ChannelState[TMemory, TChannelData], semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error - CommitPostRow(p intf.Playback, cs *ChannelState[TMemory, TChannelData], semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error + CommitPreRow(p playback.Playback, cs *ChannelState[TMemory, TChannelData], semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error + CommitRow(p playback.Playback, cs *ChannelState[TMemory, TChannelData], semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error + CommitPostRow(p playback.Playback, cs *ChannelState[TMemory, TChannelData], semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error - CommitPreTick(p intf.Playback, cs *ChannelState[TMemory, TChannelData], currentTick int, lastTick bool, semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error - CommitTick(p intf.Playback, cs *ChannelState[TMemory, TChannelData], currentTick int, lastTick bool, semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error - CommitPostTick(p intf.Playback, cs *ChannelState[TMemory, TChannelData], currentTick int, lastTick bool, semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error + CommitPreTick(p playback.Playback, cs *ChannelState[TMemory, TChannelData], currentTick int, lastTick bool, semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error + CommitTick(p playback.Playback, cs *ChannelState[TMemory, TChannelData], currentTick int, lastTick bool, semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error + CommitPostTick(p playback.Playback, cs *ChannelState[TMemory, TChannelData], currentTick int, lastTick bool, semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error AddVolOp(op VolOp[TMemory, TChannelData]) AddNoteOp(op NoteOp[TMemory, TChannelData]) @@ -62,19 +62,19 @@ func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) Set return converter.Process(&d.ChannelDataActions, cd, s, cs) } -func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) CommitPreRow(p intf.Playback, cs *ChannelState[TMemory, TChannelData], semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error { +func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) CommitPreRow(p playback.Playback, cs *ChannelState[TMemory, TChannelData], semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error { return nil } -func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) CommitRow(p intf.Playback, cs *ChannelState[TMemory, TChannelData], semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error { +func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) CommitRow(p playback.Playback, cs *ChannelState[TMemory, TChannelData], semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error { return nil } -func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) CommitPostRow(p intf.Playback, cs *ChannelState[TMemory, TChannelData], semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error { +func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) CommitPostRow(p playback.Playback, cs *ChannelState[TMemory, TChannelData], semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error { return nil } -func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) CommitPreTick(p intf.Playback, cs *ChannelState[TMemory, TChannelData], currentTick int, lastTick bool, semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error { +func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) CommitPreTick(p playback.Playback, cs *ChannelState[TMemory, TChannelData], currentTick int, lastTick bool, semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error { // pre-effect if err := d.ProcessVolOps(p, cs); err != nil { return err @@ -86,15 +86,15 @@ func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) Com return nil } -func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) CommitTick(p intf.Playback, cs *ChannelState[TMemory, TChannelData], currentTick int, lastTick bool, semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error { - if err := intf.DoEffect[TMemory, TChannelData](cs.ActiveEffect, cs, p, currentTick, lastTick); err != nil { +func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) CommitTick(p playback.Playback, cs *ChannelState[TMemory, TChannelData], currentTick int, lastTick bool, semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error { + if err := playback.DoEffect[TMemory, TChannelData](cs.ActiveEffect, cs, p, currentTick, lastTick); err != nil { return err } return nil } -func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) CommitPostTick(p intf.Playback, cs *ChannelState[TMemory, TChannelData], currentTick int, lastTick bool, semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error { +func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) CommitPostTick(p playback.Playback, cs *ChannelState[TMemory, TChannelData], currentTick int, lastTick bool, semitoneSetterFactory SemitoneSetterFactory[TMemory, TChannelData]) error { // post-effect if err := d.ProcessVolOps(p, cs); err != nil { return err @@ -110,7 +110,7 @@ func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) Add d.VolOps = append(d.VolOps, op) } -func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) ProcessVolOps(p intf.Playback, cs *ChannelState[TMemory, TChannelData]) error { +func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) ProcessVolOps(p playback.Playback, cs *ChannelState[TMemory, TChannelData]) error { for _, op := range d.VolOps { if op == nil { continue @@ -128,7 +128,7 @@ func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) Add d.NoteOps = append(d.NoteOps, op) } -func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) ProcessNoteOps(p intf.Playback, cs *ChannelState[TMemory, TChannelData]) error { +func (d *ChannelDataTxnHelper[TMemory, TChannelData, TChannelDataConverter]) ProcessNoteOps(p playback.Playback, cs *ChannelState[TMemory, TChannelData]) error { for _, op := range d.NoteOps { if op == nil { continue diff --git a/player/state/pastnotes.go b/player/state/pastnotes.go index 5d09b22..ddcf971 100644 --- a/player/state/pastnotes.go +++ b/player/state/pastnotes.go @@ -1,7 +1,7 @@ package state import ( - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/note" "github.com/heucuva/optional" ) diff --git a/player/state/playback.go b/player/state/playback.go index 439ce76..120d686 100644 --- a/player/state/playback.go +++ b/player/state/playback.go @@ -5,8 +5,8 @@ import ( "github.com/gotracker/gomixing/sampling" "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" ) // Playback is the information needed to make an instrument play diff --git a/player/tracker_tracing.go b/player/tracker_tracing.go index f98bf3f..c832f22 100644 --- a/player/tracker_tracing.go +++ b/player/tracker_tracing.go @@ -123,14 +123,8 @@ func (t *Tracker) OutputTraces() { t.tracingState.wg.Add(1) defer t.tracingState.wg.Done() - for { - select { - case tr, ok := <-t.tracingState.c: - if !ok { - return - } - tr(t.tracingFile) - } + for tr := range t.tracingState.c { + tr(t.tracingFile) } }() } diff --git a/format/settings/settings.go b/settings/settings.go similarity index 93% rename from format/settings/settings.go rename to settings/settings.go index b82f5fa..4c45813 100644 --- a/format/settings/settings.go +++ b/settings/settings.go @@ -20,7 +20,7 @@ type Settings struct { } // GetOption returns the current option by name -func (s *Settings) GetOption(name string) *optional.Value[any] { +func (s Settings) GetOption(name string) *optional.Value[any] { if s.Values == nil { return nil } @@ -31,7 +31,7 @@ func (s *Settings) GetOption(name string) *optional.Value[any] { } // Get returns the current value by name -func (s *Settings) Get(name string) (any, bool) { +func (s Settings) Get(name string) (any, bool) { if v := s.GetOption(name); v != nil { return v.Get() } diff --git a/song/channel.go b/song/channel.go index 7a1d180..b43bd9e 100644 --- a/song/channel.go +++ b/song/channel.go @@ -5,8 +5,8 @@ import ( "github.com/gotracker/gomixing/volume" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" ) // ChannelData is an interface for channel data diff --git a/song/pattern.go b/song/pattern.go index e432aed..b922cc9 100644 --- a/song/pattern.go +++ b/song/pattern.go @@ -3,7 +3,7 @@ package song import ( "errors" - "github.com/gotracker/playback/song/index" + "github.com/gotracker/playback/index" ) var ( diff --git a/song/song.go b/song/song.go index 03d610d..3b53bf3 100644 --- a/song/song.go +++ b/song/song.go @@ -1,9 +1,9 @@ package song import ( - "github.com/gotracker/playback/song/index" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/index" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" ) // Data is an interface to the song data diff --git a/format/internal/effect/tremor.go b/tremor/tremor.go similarity index 97% rename from format/internal/effect/tremor.go rename to tremor/tremor.go index 63058b5..b1dffd4 100644 --- a/format/internal/effect/tremor.go +++ b/tremor/tremor.go @@ -1,4 +1,4 @@ -package effect +package tremor // Tremor is the storage object for the tremor values type Tremor struct { diff --git a/format/internal/util/lerp.go b/util/lerp.go similarity index 100% rename from format/internal/util/lerp.go rename to util/lerp.go diff --git a/format/internal/util/loopdetect.go b/util/loopdetect.go similarity index 95% rename from format/internal/util/loopdetect.go rename to util/loopdetect.go index 146282c..b85daf1 100644 --- a/format/internal/util/loopdetect.go +++ b/util/loopdetect.go @@ -1,6 +1,6 @@ package util -import "github.com/gotracker/playback/song/index" +import "github.com/gotracker/playback/index" type loopDetectNode map[index.Row]struct{} diff --git a/format/internal/util/patternloop.go b/util/patternloop.go similarity index 90% rename from format/internal/util/patternloop.go rename to util/patternloop.go index 0d19ccb..fe97015 100644 --- a/format/internal/util/patternloop.go +++ b/util/patternloop.go @@ -1,6 +1,6 @@ package util -import "github.com/gotracker/playback/song/index" +import "github.com/gotracker/playback/index" // PatternLoop is a state machine for pattern loops type PatternLoop struct { diff --git a/format/internal/util/util.go b/util/util.go similarity index 100% rename from format/internal/util/util.go rename to util/util.go diff --git a/voice/opl2.go b/voice/opl2.go index e4f957b..cf1b27f 100644 --- a/voice/opl2.go +++ b/voice/opl2.go @@ -11,8 +11,8 @@ import ( "github.com/gotracker/voice/period" "github.com/gotracker/voice/render" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" ) // OPL2 is an OPL2 voice interface diff --git a/voice/pcm.go b/voice/pcm.go index b0c8152..b7d5af9 100644 --- a/voice/pcm.go +++ b/voice/pcm.go @@ -12,9 +12,9 @@ import ( "github.com/gotracker/voice/period" "github.com/gotracker/playback/filter" + "github.com/gotracker/playback/instrument" + "github.com/gotracker/playback/note" "github.com/gotracker/playback/pan" - "github.com/gotracker/playback/song/instrument" - "github.com/gotracker/playback/song/note" ) // PCM is a PCM voice interface diff --git a/voice/voice.go b/voice/voice.go index 2168420..57f0ae6 100644 --- a/voice/voice.go +++ b/voice/voice.go @@ -4,8 +4,8 @@ import ( "github.com/gotracker/voice" "github.com/gotracker/playback/filter" + "github.com/gotracker/playback/instrument" "github.com/gotracker/playback/player/output" - "github.com/gotracker/playback/song/instrument" ) // New returns a new Voice from the instrument and output channel provided