feat(tracker): don't save instrument name in instrument files

The filename is used as the instrument name when it is loaded.
This commit is contained in:
5684185+vsariola@users.noreply.github.com
2025-10-05 14:00:58 +03:00
parent 55f9c36bd5
commit 7459437822
6 changed files with 77 additions and 14 deletions

View File

@ -105,6 +105,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
([#156][i156])
### Changed
- When saving instrument to a file, the instrument name is not saved to the name
field, as Sointu will anyway use the filename as the instrument's name when it
is loaded.
- Native version of the tracker/VSTi was removed. Instead, you can change
between the two versions of the synth on the fly, by clicking on the "Synth"
option under the CPU group in the song panel ([#200][i200])

View File

@ -114,13 +114,17 @@ func (m *Model) SaveInstrument(w io.WriteCloser) bool {
var extension = filepath.Ext(path)
var contents []byte
var err error
instr := m.d.Song.Patch[m.d.InstrIndex]
if _, ok := w.(*os.File); ok {
instr.Name = "" // don't save the instrument name to a file; we'll replace the instruments name with the filename when loading from a file
}
if extension == ".json" {
contents, err = json.Marshal(m.d.Song.Patch[m.d.InstrIndex])
contents, err = json.Marshal(instr)
} else {
contents, err = yaml.Marshal(m.d.Song.Patch[m.d.InstrIndex])
contents, err = yaml.Marshal(instr)
}
if err != nil {
m.Alerts().Add(fmt.Sprintf("Error marshaling a ínstrument file: %v", err), Error)
m.Alerts().Add(fmt.Sprintf("Error marshaling an instrument file: %v", err), Error)
return false
}
w.Write(contents)
@ -163,7 +167,7 @@ func (m *Model) LoadInstrument(r io.ReadCloser) bool {
success:
if f, ok := r.(*os.File); ok {
filename := f.Name()
// the 4klang instrument names are junk, replace them with the filename without extension
// the instrument names are generally junk, replace them with the filename without extension
instrument.Name = filepath.Base(filename[:len(filename)-len(filepath.Ext(filename))])
}
defer m.change("LoadInstrument", PatchChange, MajorChange)()

View File

@ -0,0 +1,47 @@
//go:build ignore
// +build ignore
package main
import (
"fmt"
"io/fs"
"os"
"path/filepath"
"github.com/vsariola/sointu"
"github.com/vsariola/sointu/tracker"
"gopkg.in/yaml.v3"
)
func main() {
filepath.WalkDir("presets", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
return nil
}
data, err := os.ReadFile(path)
if err != nil {
return nil
}
var instr sointu.Instrument
if yaml.Unmarshal(data, &instr) != nil {
fmt.Fprintf(os.Stderr, "could not unmarshal the preset file %v: %v\n", path, err)
return nil
}
tracker.RemoveUnusedUnitParameters(&instr) // remove invalid parameters
instr.Name = "" // we don't need the names in the preset files as they are derived from the file path
outData, err := yaml.Marshal(instr)
if err != nil {
fmt.Fprintf(os.Stderr, "could not marshal the preset file %v: %v\n", path, err)
return nil
}
if err := os.WriteFile(path, outData, 0644); err != nil {
fmt.Fprintf(os.Stderr, "could not write the preset file %v: %v\n", path, err)
return nil
}
return nil
})
}

View File

@ -521,21 +521,29 @@ func (m *Model) fixUnitParams() {
// loop over all instruments and units and check that unit parameter table
// only has the parameters that are defined in the unit type
fixed := false
for i, instr := range m.d.Song.Patch {
for j, unit := range instr.Units {
for paramName := range unit.Parameters {
if !validParameters[unit.Type][paramName] {
delete(m.d.Song.Patch[i].Units[j].Parameters, paramName)
fixed = true
}
}
}
for i := range m.d.Song.Patch {
fixed = RemoveUnusedUnitParameters(&m.d.Song.Patch[i]) || fixed
}
if fixed {
m.Alerts().AddNamed("InvalidUnitParameters", "Some units had invalid parameters, they were removed", Error)
}
}
// RemoveUnusedUnitParameters removes any parameters from the instrument that are not valid for the unit type.
// It returns true if any parameters were removed.
func RemoveUnusedUnitParameters(instr *sointu.Instrument) bool {
fixed := false
for _, unit := range instr.Units {
for paramName := range unit.Parameters {
if !validParameters[unit.Type][paramName] {
delete(unit.Parameters, paramName)
fixed = true
}
}
}
return fixed
}
func clamp(a, min, max int) int {
if a > max {
return max

View File

@ -14,7 +14,8 @@ import (
"gopkg.in/yaml.v2"
)
//go:generate go run generate/main.go
//go:generate go run generate/gmdls_entries.go
//go:generate go run generate/clean_presets.go
type (
// GmDlsEntry is a single sample entry from the gm.dls file