mirror of
https://github.com/vsariola/sointu.git
synced 2026-04-12 17:14:43 -04:00
feat!: both native & Go synths are included in the same executables
Closes #200
This commit is contained in:
parent
13102aa7d6
commit
3163f46447
36
.github/workflows/binaries.yml
vendored
36
.github/workflows/binaries.yml
vendored
@ -39,33 +39,19 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
config:
|
config:
|
||||||
- os: windows-latest
|
|
||||||
asmnasm: C:\Users\runneradmin\nasm\nasm
|
|
||||||
output: sointu-track.exe
|
|
||||||
params: cmd/sointu-track/main.go
|
|
||||||
ldflags: -H=windowsgui
|
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
asmnasm: C:\Users\runneradmin\nasm\nasm
|
asmnasm: C:\Users\runneradmin\nasm\nasm
|
||||||
output: sointu-compile.exe
|
output: sointu-compile.exe
|
||||||
params: cmd/sointu-compile/main.go
|
params: cmd/sointu-compile/main.go
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
asmnasm: C:\Users\runneradmin\nasm\nasm
|
asmnasm: C:\Users\runneradmin\nasm\nasm
|
||||||
output: sointu-track-native.exe
|
output: sointu-track.exe
|
||||||
params: -tags=native cmd/sointu-track/main.go
|
params: -tags=native cmd/sointu-track/main.go
|
||||||
ldflags: -H=windowsgui
|
ldflags: -H=windowsgui
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
asmnasm: C:\Users\runneradmin\nasm\nasm
|
asmnasm: C:\Users\runneradmin\nasm\nasm
|
||||||
output: sointu-vsti.dll
|
output: sointu-vsti.dll
|
||||||
params: -buildmode=c-shared -tags=plugin ./cmd/sointu-vsti/
|
|
||||||
- os: windows-latest
|
|
||||||
asmnasm: C:\Users\runneradmin\nasm\nasm
|
|
||||||
output: sointu-vsti-native.dll
|
|
||||||
params: -buildmode=c-shared -tags="plugin,native" ./cmd/sointu-vsti/
|
params: -buildmode=c-shared -tags="plugin,native" ./cmd/sointu-vsti/
|
||||||
- os: ubuntu-latest
|
|
||||||
asmnasm: /home/runner/nasm/nasm
|
|
||||||
output: sointu-track
|
|
||||||
params: cmd/sointu-track/main.go
|
|
||||||
packages: libegl-dev libvulkan-dev libxkbcommon-x11-dev libwayland-dev libasound2-dev libx11-xcb-dev libxcursor-dev libxfixes-dev
|
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
asmnasm: /home/runner/nasm/nasm
|
asmnasm: /home/runner/nasm/nasm
|
||||||
output: sointu-compile
|
output: sointu-compile
|
||||||
@ -73,43 +59,27 @@ jobs:
|
|||||||
packages: libegl-dev libvulkan-dev libxkbcommon-x11-dev libwayland-dev libasound2-dev libx11-xcb-dev libxcursor-dev libxfixes-dev
|
packages: libegl-dev libvulkan-dev libxkbcommon-x11-dev libwayland-dev libasound2-dev libx11-xcb-dev libxcursor-dev libxfixes-dev
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
asmnasm: /home/runner/nasm/nasm
|
asmnasm: /home/runner/nasm/nasm
|
||||||
output: sointu-track-native
|
output: sointu-track
|
||||||
params: -tags=native cmd/sointu-track/main.go
|
params: -tags=native cmd/sointu-track/main.go
|
||||||
packages: libegl-dev libvulkan-dev libxkbcommon-x11-dev libwayland-dev libasound2-dev libx11-xcb-dev libxcursor-dev libxfixes-dev
|
packages: libegl-dev libvulkan-dev libxkbcommon-x11-dev libwayland-dev libasound2-dev libx11-xcb-dev libxcursor-dev libxfixes-dev
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
asmnasm: /home/runner/nasm/nasm
|
asmnasm: /home/runner/nasm/nasm
|
||||||
output: sointu-vsti.so
|
output: sointu-vsti.so
|
||||||
params: -buildmode=c-shared -tags=plugin ./cmd/sointu-vsti/
|
|
||||||
packages: libegl-dev libvulkan-dev libxkbcommon-x11-dev libwayland-dev libasound2-dev libx11-xcb-dev libxcursor-dev libxfixes-dev
|
|
||||||
- os: ubuntu-latest
|
|
||||||
asmnasm: /home/runner/nasm/nasm
|
|
||||||
output: sointu-vsti-native.so
|
|
||||||
params: -buildmode=c-shared -tags="plugin,native" ./cmd/sointu-vsti/
|
params: -buildmode=c-shared -tags="plugin,native" ./cmd/sointu-vsti/
|
||||||
packages: libegl-dev libvulkan-dev libxkbcommon-x11-dev libwayland-dev libasound2-dev libx11-xcb-dev libxcursor-dev libxfixes-dev
|
packages: libegl-dev libvulkan-dev libxkbcommon-x11-dev libwayland-dev libasound2-dev libx11-xcb-dev libxcursor-dev libxfixes-dev
|
||||||
- os: macos-latest
|
|
||||||
asmnasm: /Users/runner/nasm/nasm
|
|
||||||
output: sointu-track
|
|
||||||
params: cmd/sointu-track/main.go
|
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
asmnasm: /Users/runner/nasm/nasm
|
asmnasm: /Users/runner/nasm/nasm
|
||||||
output: sointu-compile
|
output: sointu-compile
|
||||||
params: cmd/sointu-compile/main.go
|
params: cmd/sointu-compile/main.go
|
||||||
- os: macos-13
|
- os: macos-13
|
||||||
asmnasm: /Users/runner/nasm/nasm
|
asmnasm: /Users/runner/nasm/nasm
|
||||||
output: sointu-track-native
|
output: sointu-track
|
||||||
params: -tags=native cmd/sointu-track/main.go
|
params: -tags=native cmd/sointu-track/main.go
|
||||||
- os: macos-13
|
- os: macos-13
|
||||||
asmnasm: /Users/runner/nasm/nasm
|
asmnasm: /Users/runner/nasm/nasm
|
||||||
output: sointu-vsti.a
|
output: sointu-vsti.a
|
||||||
bundleoutput: sointu-vsti
|
bundleoutput: sointu-vsti
|
||||||
MACOSX_DEPLOYMENT_TARGET: 11
|
MACOSX_DEPLOYMENT_TARGET: 11
|
||||||
params: -buildmode=c-archive -tags=plugin ./cmd/sointu-vsti/
|
|
||||||
bundle: true
|
|
||||||
- os: macos-13
|
|
||||||
asmnasm: /Users/runner/nasm/nasm
|
|
||||||
output: sointu-vsti-native.a
|
|
||||||
bundleoutput: sointu-vsti-native
|
|
||||||
MACOSX_DEPLOYMENT_TARGET: 11
|
|
||||||
params: -buildmode=c-archive -tags="plugin,native" ./cmd/sointu-vsti/
|
params: -buildmode=c-archive -tags="plugin,native" ./cmd/sointu-vsti/
|
||||||
bundle: true
|
bundle: true
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@ -109,6 +109,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
([#156][i156])
|
([#156][i156])
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- 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])
|
||||||
- Send amount defaults to 64 = 0.0 ([#178][i178])
|
- Send amount defaults to 64 = 0.0 ([#178][i178])
|
||||||
- BREAKING CHANGE: the negbandpass and neghighpass parameters of the filter unit
|
- BREAKING CHANGE: the negbandpass and neghighpass parameters of the filter unit
|
||||||
were removed. Setting bandpass or highpass to -1 achieves now the same end
|
were removed. Setting bandpass or highpass to -1 achieves now the same end
|
||||||
@ -360,3 +363,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
[i186]: https://github.com/vsariola/sointu/issues/186
|
[i186]: https://github.com/vsariola/sointu/issues/186
|
||||||
[i192]: https://github.com/vsariola/sointu/issues/192
|
[i192]: https://github.com/vsariola/sointu/issues/192
|
||||||
[i196]: https://github.com/vsariola/sointu/issues/196
|
[i196]: https://github.com/vsariola/sointu/issues/196
|
||||||
|
[i200]: https://github.com/vsariola/sointu/issues/200
|
||||||
|
|||||||
10
README.md
10
README.md
@ -82,7 +82,7 @@ for the audio, so the portability is currently limited by these.
|
|||||||
#### Prerequisites
|
#### Prerequisites
|
||||||
|
|
||||||
- [go](https://golang.org/)
|
- [go](https://golang.org/)
|
||||||
- If you want to use the x86 assembly written synthesizer, to test that the
|
- If you want to also use the x86 assembly written synthesizer, to test that the
|
||||||
patch also works once compiled:
|
patch also works once compiled:
|
||||||
- Follow the instructions to build the [x86 native virtual machine](#native-virtual-machine)
|
- Follow the instructions to build the [x86 native virtual machine](#native-virtual-machine)
|
||||||
before building the tracker.
|
before building the tracker.
|
||||||
@ -110,7 +110,7 @@ go build -o sointu-track.exe cmd/sointu-track/main.go
|
|||||||
On other platforms than Windows, replace `-o sointu-track.exe` with
|
On other platforms than Windows, replace `-o sointu-track.exe` with
|
||||||
`-o sointu-track`.
|
`-o sointu-track`.
|
||||||
|
|
||||||
If you want to use the [x86 native virtual machine](#native-virtual-machine),
|
If you want to include the [x86 native virtual machine](#native-virtual-machine),
|
||||||
add `-tags=native` to all the commands e.g.
|
add `-tags=native` to all the commands e.g.
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -133,7 +133,7 @@ a dynamically linked library and ran inside a VST host.
|
|||||||
if it is not set and go fails to find the compiler, go just excludes
|
if it is not set and go fails to find the compiler, go just excludes
|
||||||
all files with `import "C"` from the build, resulting in lots of
|
all files with `import "C"` from the build, resulting in lots of
|
||||||
errors about missing types.
|
errors about missing types.
|
||||||
- If you want to use the x86 assembly written synthesizer:
|
- If you want to build the VSTI with the native x86 assembly written synthesizer:
|
||||||
- Follow the instructions to build the [x86 native virtual machine](#native-virtual-machine)
|
- Follow the instructions to build the [x86 native virtual machine](#native-virtual-machine)
|
||||||
before building the plugin itself
|
before building the plugin itself
|
||||||
|
|
||||||
@ -218,7 +218,9 @@ machine, through cgo, instead of using the Go written bytecode interpreter. With
|
|||||||
the latest Go compiler, the native virtual machine is actually slower than the
|
the latest Go compiler, the native virtual machine is actually slower than the
|
||||||
Go-written one, but importantly, the native virtual machine allows you to test
|
Go-written one, but importantly, the native virtual machine allows you to test
|
||||||
that the patch also works within the stack limits of the x87 virtual machine,
|
that the patch also works within the stack limits of the x87 virtual machine,
|
||||||
which is the VM used in the compiled intros.
|
which is the VM used in the compiled intros. In the tracker/VSTi, you can switch
|
||||||
|
between the native synth and the Go synth under the CPU panel in the Song
|
||||||
|
settings.
|
||||||
|
|
||||||
Before you can actually run it, you need to build the bridge using CMake (thus,
|
Before you can actually run it, you need to build the bridge using CMake (thus,
|
||||||
***this will not work with go get***).
|
***this will not work with go get***).
|
||||||
|
|||||||
1
audio.go
1
audio.go
@ -67,6 +67,7 @@ type (
|
|||||||
// Synther compiles a given Patch into a Synth, throwing errors if the
|
// Synther compiles a given Patch into a Synth, throwing errors if the
|
||||||
// Patch is malformed.
|
// Patch is malformed.
|
||||||
Synther interface {
|
Synther interface {
|
||||||
|
Name() string // Name of the synther, e.g. "Go" or "Native"
|
||||||
Synth(patch Patch, bpm int) (Synth, error)
|
Synth(patch Patch, bpm int) (Synth, error)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
//go:build !native
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import "github.com/vsariola/sointu/vm"
|
|
||||||
|
|
||||||
var MainSynther = vm.GoSynther{}
|
|
||||||
@ -4,12 +4,13 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/vsariola/sointu/cmd"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/vsariola/sointu/cmd"
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
"github.com/vsariola/sointu"
|
"github.com/vsariola/sointu"
|
||||||
@ -29,12 +30,20 @@ func main() {
|
|||||||
wavOut := flag.Bool("w", false, "Output the rendered song as .wav file. By default, saves stereo float32 buffer to disk.")
|
wavOut := flag.Bool("w", false, "Output the rendered song as .wav file. By default, saves stereo float32 buffer to disk.")
|
||||||
pcm := flag.Bool("c", false, "Convert audio to 16-bit signed PCM when outputting.")
|
pcm := flag.Bool("c", false, "Convert audio to 16-bit signed PCM when outputting.")
|
||||||
versionFlag := flag.Bool("v", false, "Print version.")
|
versionFlag := flag.Bool("v", false, "Print version.")
|
||||||
|
syntherInt := flag.Int("synth", 0, "Select the synther to use. By default, uses the first one in the list of available synthers.")
|
||||||
flag.Usage = printUsage
|
flag.Usage = printUsage
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if *versionFlag {
|
if *versionFlag {
|
||||||
fmt.Println(version.VersionOrHash)
|
fmt.Println(version.VersionOrHash)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
if *syntherInt < 0 || *syntherInt >= len(cmd.Synthers) {
|
||||||
|
fmt.Fprintf(os.Stderr, "synth index %d is out of range; available synthers:\n", *syntherInt)
|
||||||
|
for i, s := range cmd.Synthers {
|
||||||
|
fmt.Fprintf(os.Stderr, " %d: %s\n", i, s.Name())
|
||||||
|
}
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
if flag.NArg() == 0 || *help {
|
if flag.NArg() == 0 || *help {
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
@ -93,7 +102,7 @@ func main() {
|
|||||||
return fmt.Errorf("the song could not be parsed as .json (%v) or .yml (%v)", errJSON, errYaml)
|
return fmt.Errorf("the song could not be parsed as .json (%v) or .yml (%v)", errJSON, errYaml)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer, err := sointu.Play(cmd.MainSynther, song, nil) // render the song to calculate its length
|
buffer, err := sointu.Play(cmd.Synthers[*syntherInt], song, nil) // render the song to calculate its length
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("sointu.Play failed: %v", err)
|
return fmt.Errorf("sointu.Play failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,8 +49,8 @@ func main() {
|
|||||||
midiContext := cmd.NewMidiContext(broker)
|
midiContext := cmd.NewMidiContext(broker)
|
||||||
defer midiContext.Close()
|
defer midiContext.Close()
|
||||||
midiContext.TryToOpenBy(*defaultMidiInput, *firstMidiInput)
|
midiContext.TryToOpenBy(*defaultMidiInput, *firstMidiInput)
|
||||||
model := tracker.NewModel(broker, cmd.MainSynther, midiContext, recoveryFile)
|
model := tracker.NewModel(broker, cmd.Synthers, midiContext, recoveryFile)
|
||||||
player := tracker.NewPlayer(broker, cmd.MainSynther)
|
player := tracker.NewPlayer(broker, cmd.Synthers[0])
|
||||||
detector := tracker.NewDetector(broker)
|
detector := tracker.NewDetector(broker)
|
||||||
go detector.Run()
|
go detector.Run()
|
||||||
|
|
||||||
|
|||||||
@ -46,8 +46,8 @@ func init() {
|
|||||||
recoveryFile = filepath.Join(configDir, "sointu", "sointu-vsti-recovery-"+hex.EncodeToString(randBytes))
|
recoveryFile = filepath.Join(configDir, "sointu", "sointu-vsti-recovery-"+hex.EncodeToString(randBytes))
|
||||||
}
|
}
|
||||||
broker := tracker.NewBroker()
|
broker := tracker.NewBroker()
|
||||||
model := tracker.NewModel(broker, cmd.MainSynther, cmd.NewMidiContext(broker), recoveryFile)
|
model := tracker.NewModel(broker, cmd.Synthers, cmd.NewMidiContext(broker), recoveryFile)
|
||||||
player := tracker.NewPlayer(broker, cmd.MainSynther)
|
player := tracker.NewPlayer(broker, cmd.Synthers[0])
|
||||||
detector := tracker.NewDetector(broker)
|
detector := tracker.NewDetector(broker)
|
||||||
go detector.Run()
|
go detector.Run()
|
||||||
|
|
||||||
@ -63,11 +63,11 @@ func init() {
|
|||||||
buf := make(sointu.AudioBuffer, 1024)
|
buf := make(sointu.AudioBuffer, 1024)
|
||||||
var totalFrames int64 = 0
|
var totalFrames int64 = 0
|
||||||
return vst2.Plugin{
|
return vst2.Plugin{
|
||||||
UniqueID: PLUGIN_ID,
|
UniqueID: [4]byte{'S', 'n', 't', 'u'},
|
||||||
Version: version,
|
Version: version,
|
||||||
InputChannels: 0,
|
InputChannels: 0,
|
||||||
OutputChannels: 2,
|
OutputChannels: 2,
|
||||||
Name: PLUGIN_NAME,
|
Name: "Sointu",
|
||||||
Vendor: "vsariola/sointu",
|
Vendor: "vsariola/sointu",
|
||||||
Category: vst2.PluginCategorySynth,
|
Category: vst2.PluginCategorySynth,
|
||||||
Flags: vst2.PluginIsSynth,
|
Flags: vst2.PluginIsSynth,
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
//go:build native
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
var PLUGIN_ID = [4]byte{'S', 'n', 't', 'N'}
|
|
||||||
var PLUGIN_NAME = "Sointu Native"
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
//go:build !native
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
var PLUGIN_ID = [4]byte{'S', 'n', 't', 'u'}
|
|
||||||
var PLUGIN_NAME = "Sointu"
|
|
||||||
10
cmd/synthers.go
Normal file
10
cmd/synthers.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/vsariola/sointu"
|
||||||
|
"github.com/vsariola/sointu/vm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Synthers = []sointu.Synther{
|
||||||
|
vm.GoSynther{},
|
||||||
|
}
|
||||||
@ -4,4 +4,6 @@ package cmd
|
|||||||
|
|
||||||
import "github.com/vsariola/sointu/vm/compiler/bridge"
|
import "github.com/vsariola/sointu/vm/compiler/bridge"
|
||||||
|
|
||||||
var MainSynther = bridge.NativeSynther{}
|
func init() {
|
||||||
|
Synthers = append(Synthers, bridge.NativeSynther{})
|
||||||
|
}
|
||||||
@ -82,7 +82,7 @@ func (m *Model) WriteWav(w io.WriteCloser, pcm16 bool) {
|
|||||||
b := make([]byte, 32+2)
|
b := make([]byte, 32+2)
|
||||||
rand.Read(b)
|
rand.Read(b)
|
||||||
name := fmt.Sprintf("%x", b)[2 : 32+2]
|
name := fmt.Sprintf("%x", b)[2 : 32+2]
|
||||||
data, err := sointu.Play(m.synther, song, func(p float32) {
|
data, err := sointu.Play(m.synthers[m.syntherIndex], song, func(p float32) {
|
||||||
txt := fmt.Sprintf("Exporting song: %.0f%%", p*100)
|
txt := fmt.Sprintf("Exporting song: %.0f%%", p*100)
|
||||||
TrySend(m.broker.ToModel, MsgToModel{Data: Alert{Message: txt, Priority: Info, Name: name, Duration: defaultAlertDuration}})
|
TrySend(m.broker.ToModel, MsgToModel{Data: Alert{Message: txt, Priority: Info, Name: name, Duration: defaultAlertDuration}})
|
||||||
}) // render the song to calculate its length
|
}) // render the song to calculate its length
|
||||||
|
|||||||
@ -21,9 +21,11 @@ type SongPanel struct {
|
|||||||
ScopeExpander *Expander
|
ScopeExpander *Expander
|
||||||
LoudnessExpander *Expander
|
LoudnessExpander *Expander
|
||||||
PeakExpander *Expander
|
PeakExpander *Expander
|
||||||
|
CPUExpander *Expander
|
||||||
|
|
||||||
WeightingTypeBtn *Clickable
|
WeightingTypeBtn *Clickable
|
||||||
OversamplingBtn *Clickable
|
OversamplingBtn *Clickable
|
||||||
|
SynthBtn *Clickable
|
||||||
|
|
||||||
BPM *NumericUpDownState
|
BPM *NumericUpDownState
|
||||||
RowsPerPattern *NumericUpDownState
|
RowsPerPattern *NumericUpDownState
|
||||||
@ -50,11 +52,13 @@ func NewSongPanel(tr *Tracker) *SongPanel {
|
|||||||
|
|
||||||
WeightingTypeBtn: new(Clickable),
|
WeightingTypeBtn: new(Clickable),
|
||||||
OversamplingBtn: new(Clickable),
|
OversamplingBtn: new(Clickable),
|
||||||
|
SynthBtn: new(Clickable),
|
||||||
|
|
||||||
SongSettingsExpander: &Expander{Expanded: true},
|
SongSettingsExpander: &Expander{Expanded: true},
|
||||||
ScopeExpander: &Expander{},
|
ScopeExpander: &Expander{},
|
||||||
LoudnessExpander: &Expander{},
|
LoudnessExpander: &Expander{},
|
||||||
PeakExpander: &Expander{},
|
PeakExpander: &Expander{},
|
||||||
|
CPUExpander: &Expander{},
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@ -66,6 +70,10 @@ func (s *SongPanel) Update(gtx C, t *Tracker) {
|
|||||||
for s.OversamplingBtn.Clicked(gtx) {
|
for s.OversamplingBtn.Clicked(gtx) {
|
||||||
t.Model.Oversampling().SetValue(!t.Oversampling().Value())
|
t.Model.Oversampling().SetValue(!t.Oversampling().Value())
|
||||||
}
|
}
|
||||||
|
for s.SynthBtn.Clicked(gtx) {
|
||||||
|
r := t.Model.SyntherIndex().Range()
|
||||||
|
t.Model.SyntherIndex().SetValue((t.SyntherIndex().Value()+1)%(r.Max-r.Min+1) + r.Min)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SongPanel) Layout(gtx C) D {
|
func (s *SongPanel) Layout(gtx C) D {
|
||||||
@ -102,6 +110,14 @@ func (t *SongPanel) layoutSongOptions(gtx C) D {
|
|||||||
}
|
}
|
||||||
oversamplingBtn := Btn(tr.Theme, &tr.Theme.Button.Text, t.OversamplingBtn, oversamplingTxt, "")
|
oversamplingBtn := Btn(tr.Theme, &tr.Theme.Button.Text, t.OversamplingBtn, oversamplingTxt, "")
|
||||||
|
|
||||||
|
cpuload := tr.Model.CPULoad()
|
||||||
|
cpuLabel := Label(tr.Theme, &tr.Theme.SongPanel.RowValue, fmt.Sprintf("%.0f %%", cpuload*100))
|
||||||
|
if cpuload >= 1 {
|
||||||
|
cpuLabel.Color = tr.Theme.SongPanel.ErrorColor
|
||||||
|
}
|
||||||
|
|
||||||
|
synthBtn := Btn(tr.Theme, &tr.Theme.Button.Text, t.SynthBtn, tr.Model.SyntherName(), "")
|
||||||
|
|
||||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
return t.SongSettingsExpander.Layout(gtx, tr.Theme, "Song",
|
return t.SongSettingsExpander.Layout(gtx, tr.Theme, "Song",
|
||||||
@ -130,17 +146,19 @@ func (t *SongPanel) layoutSongOptions(gtx C) D {
|
|||||||
step := NumUpDown(tr.Step(), tr.Theme, t.Step, "Cursor step")
|
step := NumUpDown(tr.Step(), tr.Theme, t.Step, "Cursor step")
|
||||||
return layoutSongOptionRow(gtx, tr.Theme, "Cursor step", step.Layout)
|
return layoutSongOptionRow(gtx, tr.Theme, "Cursor step", step.Layout)
|
||||||
}),
|
}),
|
||||||
layout.Rigid(func(gtx C) D {
|
|
||||||
cpuload := tr.Model.CPULoad()
|
|
||||||
label := Label(tr.Theme, &tr.Theme.SongPanel.RowValue, fmt.Sprintf("%.0f %%", cpuload*100))
|
|
||||||
if cpuload >= 1 {
|
|
||||||
label.Color = tr.Theme.SongPanel.ErrorColor
|
|
||||||
}
|
|
||||||
return layoutSongOptionRow(gtx, tr.Theme, "CPU load", label.Layout)
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
layout.Rigid(func(gtx C) D {
|
||||||
|
return t.CPUExpander.Layout(gtx, tr.Theme, "CPU", cpuLabel.Layout,
|
||||||
|
func(gtx C) D {
|
||||||
|
return layout.Flex{Axis: layout.Vertical, Alignment: layout.End}.Layout(gtx,
|
||||||
|
layout.Rigid(func(gtx C) D { return layoutSongOptionRow(gtx, tr.Theme, "Load", cpuLabel.Layout) }),
|
||||||
|
layout.Rigid(func(gtx C) D { return layoutSongOptionRow(gtx, tr.Theme, "Synth", synthBtn.Layout) }),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}),
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
return t.LoudnessExpander.Layout(gtx, tr.Theme, "Loudness",
|
return t.LoudnessExpander.Layout(gtx, tr.Theme, "Loudness",
|
||||||
func(gtx C) D {
|
func(gtx C) D {
|
||||||
|
|||||||
@ -113,7 +113,6 @@ func NewTracker(model *tracker.Model) *Tracker {
|
|||||||
Duration: 10 * time.Second,
|
Duration: 10 * time.Second,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
t.TrackEditor.scrollTable.Focus()
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,7 @@ type (
|
|||||||
Step Model
|
Step Model
|
||||||
Octave Model
|
Octave Model
|
||||||
DetectorWeighting Model
|
DetectorWeighting Model
|
||||||
|
SyntherIndex Model
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeInt(value IntValue) Int {
|
func MakeInt(value IntValue) Int {
|
||||||
@ -81,6 +82,7 @@ func (m *Model) RowsPerBeat() Int { return MakeInt((*RowsPerBeat)(m)) }
|
|||||||
func (m *Model) Step() Int { return MakeInt((*Step)(m)) }
|
func (m *Model) Step() Int { return MakeInt((*Step)(m)) }
|
||||||
func (m *Model) Octave() Int { return MakeInt((*Octave)(m)) }
|
func (m *Model) Octave() Int { return MakeInt((*Octave)(m)) }
|
||||||
func (m *Model) DetectorWeighting() Int { return MakeInt((*DetectorWeighting)(m)) }
|
func (m *Model) DetectorWeighting() Int { return MakeInt((*DetectorWeighting)(m)) }
|
||||||
|
func (m *Model) SyntherIndex() Int { return MakeInt((*SyntherIndex)(m)) }
|
||||||
|
|
||||||
// BeatsPerMinuteInt
|
// BeatsPerMinuteInt
|
||||||
|
|
||||||
@ -205,3 +207,17 @@ func (v *TrackVoices) Range() IntRange {
|
|||||||
}
|
}
|
||||||
return IntRange{1, (*Model)(v).remainingVoices(v.linkInstrTrack, true) + v.d.Song.Score.Tracks[t].NumVoices}
|
return IntRange{1, (*Model)(v).remainingVoices(v.linkInstrTrack, true) + v.d.Song.Score.Tracks[t].NumVoices}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyntherIndex
|
||||||
|
|
||||||
|
func (v *SyntherIndex) Value() int { return v.syntherIndex }
|
||||||
|
func (v *SyntherIndex) Range() IntRange { return IntRange{0, len(v.synthers) - 1} }
|
||||||
|
func (v *Model) SyntherName() string { return v.synthers[v.syntherIndex].Name() }
|
||||||
|
func (v *SyntherIndex) SetValue(value int) bool {
|
||||||
|
if value < 0 || value >= len(v.synthers) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
v.syntherIndex = value
|
||||||
|
TrySend(v.broker.ToPlayer, any(v.synthers[value]))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@ -77,7 +77,9 @@ type (
|
|||||||
|
|
||||||
alerts []Alert
|
alerts []Alert
|
||||||
dialog Dialog
|
dialog Dialog
|
||||||
synther sointu.Synther // the synther used to create new synths
|
|
||||||
|
syntherIndex int // the index of the synther used to create new synths
|
||||||
|
synthers []sointu.Synther // the synther used to create new synths
|
||||||
|
|
||||||
broker *Broker
|
broker *Broker
|
||||||
|
|
||||||
@ -171,9 +173,9 @@ func (m *Model) Quitted() bool { return m.quitted }
|
|||||||
func (m *Model) DetectorResult() DetectorResult { return m.detectorResult }
|
func (m *Model) DetectorResult() DetectorResult { return m.detectorResult }
|
||||||
|
|
||||||
// NewModelPlayer creates a new model and a player that communicates with it
|
// NewModelPlayer creates a new model and a player that communicates with it
|
||||||
func NewModel(broker *Broker, synther sointu.Synther, midiContext MIDIContext, recoveryFilePath string) *Model {
|
func NewModel(broker *Broker, synthers []sointu.Synther, midiContext MIDIContext, recoveryFilePath string) *Model {
|
||||||
m := new(Model)
|
m := new(Model)
|
||||||
m.synther = synther
|
m.synthers = synthers
|
||||||
m.MIDI = midiContext
|
m.MIDI = midiContext
|
||||||
m.broker = broker
|
m.broker = broker
|
||||||
m.d.Octave = 4
|
m.d.Octave = 4
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/vsariola/sointu"
|
||||||
"github.com/vsariola/sointu/tracker"
|
"github.com/vsariola/sointu/tracker"
|
||||||
"github.com/vsariola/sointu/vm"
|
"github.com/vsariola/sointu/vm"
|
||||||
)
|
)
|
||||||
@ -251,10 +252,10 @@ func FuzzModel(f *testing.F) {
|
|||||||
f.Add(seed)
|
f.Add(seed)
|
||||||
f.Fuzz(func(t *testing.T, slice []byte) {
|
f.Fuzz(func(t *testing.T, slice []byte) {
|
||||||
reader := bytes.NewReader(slice)
|
reader := bytes.NewReader(slice)
|
||||||
synther := vm.GoSynther{}
|
synthers := []sointu.Synther{vm.GoSynther{}}
|
||||||
broker := tracker.NewBroker()
|
broker := tracker.NewBroker()
|
||||||
model := tracker.NewModel(broker, synther, tracker.NullMIDIContext{}, "")
|
model := tracker.NewModel(broker, synthers, tracker.NullMIDIContext{}, "")
|
||||||
player := tracker.NewPlayer(broker, synther)
|
player := tracker.NewPlayer(broker, synthers[0])
|
||||||
buf := make([][2]float32, 2048)
|
buf := make([][2]float32, 2048)
|
||||||
closeChan := make(chan struct{})
|
closeChan := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
|
|||||||
@ -268,6 +268,10 @@ loop:
|
|||||||
}
|
}
|
||||||
p.recording = Recording{} // reset recording
|
p.recording = Recording{} // reset recording
|
||||||
}
|
}
|
||||||
|
case sointu.Synther:
|
||||||
|
p.synther = m
|
||||||
|
p.synth = nil
|
||||||
|
p.compileOrUpdateSynth()
|
||||||
default:
|
default:
|
||||||
// ignore unknown messages
|
// ignore unknown messages
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,8 @@ type NativeSynther struct {
|
|||||||
|
|
||||||
type NativeSynth C.Synth
|
type NativeSynth C.Synth
|
||||||
|
|
||||||
|
func (s NativeSynther) Name() string { return "Native" }
|
||||||
|
|
||||||
func (s NativeSynther) Synth(patch sointu.Patch, bpm int) (sointu.Synth, error) {
|
func (s NativeSynther) Synth(patch sointu.Patch, bpm int) (sointu.Synth, error) {
|
||||||
synth, err := Synth(patch, bpm)
|
synth, err := Synth(patch, bpm)
|
||||||
return synth, err
|
return synth, err
|
||||||
|
|||||||
@ -93,6 +93,8 @@ success:
|
|||||||
f.Read(su_sample_table[:])
|
f.Read(su_sample_table[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s GoSynther) Name() string { return "Go" }
|
||||||
|
|
||||||
func (s GoSynther) Synth(patch sointu.Patch, bpm int) (sointu.Synth, error) {
|
func (s GoSynther) Synth(patch sointu.Patch, bpm int) (sointu.Synth, error) {
|
||||||
bytecode, err := NewBytecode(patch, AllFeatures{}, bpm)
|
bytecode, err := NewBytecode(patch, AllFeatures{}, bpm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user