- Go 90.4%
- Roff 6.7%
- Nix 2.7%
- Shell 0.2%
| align | ||
| audio | ||
| bars | ||
| beatdetect | ||
| config | ||
| fastsqrt | ||
| filter | ||
| fonts | ||
| icons | ||
| interpolate | ||
| kaiser | ||
| media | ||
| particles | ||
| shaders | ||
| slew | ||
| splash | ||
| utils | ||
| vendor | ||
| vu | ||
| waterfall | ||
| .gitignore | ||
| build.sh | ||
| flake.lock | ||
| flake.nix | ||
| go.mod | ||
| go.sum | ||
| main.go | ||
| out.png | ||
| README.md | ||
| wslbuild.sh | ||
| xyosc.1 | ||
| xyosc.desktop | ||
xyosc
A simple XY-oscilloscope written in Go.
Instalation
Arch
Install ontake-xyosc-git
NixOS
Use this repo as a flake. You can test xyosc out with nix run github:make-42/xyosc for example
Or, install permanantly with flakes:
Minimal flake.nix
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
xyosc.url = "github:make-42/xyosc";
};
# ...
outputs = inputs @ {
nixpkgs,
xyosc,
...
}: let
system = "x86_64-linux"; # change to whatever your system should be
in {
nixosConfigurations."${host}" = nixpkgs.lib.nixosSystem {
specialArgs = {
inherit system;
inherit inputs;
};
};
};
}
And to install
{ inputs, pkgs, ... }:
environment.systemPackages = [
inputs.xyosc.packages.${pkgs.system}.default
];
And the xyosc binary should be available
Configuration
The configuration file can be found at ~/.config/ontake/xyosc/config.yml
Note: xyosc might not chose the right device to get audio from by default. When you run xyosc it displays a list of capture devices with indices, change the capturedeviceindex option to the right index if it isn't the right one by default.
Features
- XY mode, single channel mode (L/R/Mix modes), bars - can be toggled with the
Fkey - particles
- MPRIS support
- frequency separation
- theming support
- shader support (using ebitengine's Kage shader language) - you can cycle through presets with the
Pkey - (soon: waterfall mode + keyboard vis (with fading anims))
NixOS
Here is an example of how to configure xyosc using Nix.
{ pkgs, lib, ... }:
{
xdg.configFile.xyosc = {
enable = true;
target = "ontake/xyosc/config.yml";
text = pkgs.lib.generators.toYAML { } {
fpscounter = false;
showfilterinfo = true;
showmpris = false;
mpristextopacity = 255;
targetfps = 120;
accentcolor = "#FF0000";
# rest of config below
};
};
}
Typical configuration file
app:
targetfps: 240
fpscounter: false
defaultmode: 0
splash:
enable: true
staticsecs: 1
transsecs: 1
window:
width: 1000
height: 1000
resizable: false
fonts:
usesystemfont: true
systemfont: Maple Mono NF
audio:
capturedevicematchindex: 2
capturedevicematchname: "Monitor of Easy Effects Sink"
capturedevicematchsamplerate: 0
samplerate: 192000
gain: 1
buffers:
audiocapturebuffersize: 512
ringbuffersize: 2097152
readbuffersize: 16384
readbufferdelay: 32
xyoscilloscopereadbuffersize: 8192
beatdetectreadbuffersize: 2097152
windowfn:
usekaiserinsteadofhann: true
kaiserparam: 8
line:
opacity: 255
brightness: 1
thicknessxy: 3
thicknesssinglechannel: 3
invsqrtopacitycontrol:
enable: true
linsens: 2
lincutofffrac: 0.02
uselogdecrement: true
logbase: 10
logoffset: 1
timedependentopacitycontrol:
enable: true
base: 0.9997
opacityalsoaffectsthickness: true
colors:
useconfigcolorsinsteadofpywal: true
palette:
accent: "#C1C7D2"
first: "#C1C7D2"
third: "#C1C7D2"
particle: "#DDE3EE"
bg: "#080F16"
bgopacity: 255
disablebgtransparency: true
imageretention:
enable: false
alphadecaybase: 0.1
alphadecayspeed: 10.0
singlechannelosc:
displaybuffersize: 8192
iffilteringshowunfiltered: true
periodcrop:
enable: false
displaycount: 2
loopovercount: 1
peakdetect:
enable: true
peakdetectseparator: 100
useacf: true
acfusewindowfn: true
usemedian: true
triggerthroughoutwindow: true
usecomplextrigger: true
aligntolastpossiblepeak: true
complextriggerusecorrelationtosinewave: true
fftbufferoffset: 0
edgeguardbuffersize: 30
quadratureoffsetpeak: true
centerpeak: true
smoothwave:
enable: true
invtau: 100
timeindependent: true
timeindependentfactor: 0.4
maxperiods: 10
slew:
enable: true
accel: 100
drag: 20
direct: 20
scale:
enable: false
mainaxisenable: true
textopacity: 255
mainaxisthickness: 2
horz:
textenable: true
textsize: 10
textpadding: 5
tickenable: true
ticktogrid: false
gridthickness: 0.5
tickthickness: 1
ticklength: 10
divs: 20
vert:
textenable: true
textsize: 10
textpadding: 5
tickenable: true
ticktogrid: false
gridthickness: 0.5
tickthickness: 1
ticklength: 10
divs: 20
horzdivdynamicpos: true
particles:
enable: false
geneveryxsamples: 4000
maxcount: 100
minsize: 1
maxsize: 3
acceleration: 0.2
drag: 5
bars:
usewindowfn: true
preserveparsevalenergy: true
preventleakageabovefreq: 160000
width: 0.5
paddingedge: 4
paddingbetween: 0
autogain:
enable: true
speed: 0.5
minvolume: 1e-09
interpolate:
enable: true
accel: 20
drag: 2
direct: 20
peakcursor:
enable: false
shownote: true
refnotefreq: 440
textsize: 24
textopacity: 255
textoffset: -4
bgwidth: 210
bgpadding: 2
interpolatepos:
enable: true
accel: 0.1
drag: 1
direct: 0.01
phasecolors:
enable: false
lmult: 0.8
cmult: 3
hmult: 1
interpolate:
enable: true
accel: 2
drag: 0.2
direct: 2
vu:
paddingbetween: 64
paddingedge: 8
preserveparsevalenergy: true
logscale: true
logmaxdb: 3
logmindb: -40
linmax: 1.1
interpolate:
enable: true
accel: 2
drag: 10
direct: 40
scale:
enable: true
textsize: 12
textoffset: -2
logdivisions:
- 3
- 2
- 1
- 0
- -1
- -2
- -3
- -4
- -5
- -6
- -8
- -10
- -15
- -20
- -30
- -40
lindivisions:
- 0
- 0.1
- 0.2
- 0.3
- 0.4
- 0.5
- 0.6
- 0.7
- 0.8
- 0.9
- 1
- 1.1
ticksouter: true
ticksinner: true
tickthickness: 1
ticklength: 2
tickpadding: 2
peak:
enable: true
historyseconds: 5
interpolate:
enable: true
accel: 2
drag: 10
direct: 40
thickness: 2
waterfall:
speed: 165.
targetpeakvaldecay: 0.4
interpolatepeakval:
enable: true
direct: 1
accel: 2
drag: 10
beatdetection:
enable: true
showbpm: true
bpmtextsize: 24
intervalms: 100
downsamplefactor: 4
bpmcorrectionspeed: 4
timecorrectionspeed: 0.4
maxbpm: 500
halfdisplayedbpm: false
metronome:
enable: true
height: 8
padding: 8
edgemode: false
edgethickness: 0.5
thinlinemode: true
thinlinethicknesschangewithvelocity: true
thinlinethickness: 64
thinlinehintthickness: 2
filterinfo:
enable: true
textsize: 16
textpaddingleft: 16
textpaddingbottom: 4
shaders:
enable: true
modepresetslist:
- - 2
- 4
- 5
- 0
- - 3
- 6
- 0
- - 3
- 6
- 0
- - 3
- 6
- 0
- - 3
- 6
- 0
- - 3
- 6
- 0
presets:
- - name: glow
arguments:
Strength: 0.05
timescale: 0
- name: chromaticabberation
arguments:
Strength: 0.001
timescale: 0
- - name: glow
arguments:
Strength: 0.05
timescale: 0
- name: gammacorrectionalphafriendly
arguments:
MidPoint: 0.1
Strength: 2.
timescale: 0
- name: gammacorrectionalphafriendly
arguments:
MidPoint: 0.45
Strength: 8.
timescale: 0
- name: chromaticabberation
arguments:
Strength: 0.001
timescale: 0
- - name: glow
arguments:
Strength: 0.1
timescale: 0
- name: gammacorrection
arguments:
MidPoint: 0.1
Strength: 2.
timescale: 0
- name: gammacorrection
arguments:
MidPoint: 0.45
Strength: 10.
timescale: 0
- name: chromaticabberation
arguments:
Strength: 0.001
timescale: 0
- - name: glow
arguments:
Strength: 0.04
timescale: 0
- name: gammacorrection
arguments:
MidPoint: 0.1
Strength: 4.
timescale: 0
- name: gammacorrection
arguments:
MidPoint: 0.45
Strength: 8.
timescale: 0
- name: chromaticabberation
arguments:
Strength: 0.001
timescale: 0
- - name: crtcurve
arguments:
Strength: 0.5
timescale: 0
- name: glow
arguments:
Strength: 0.1
timescale: 0
- name: gammacorrection
arguments:
MidPoint: 0.1
Strength: 2.
timescale: 0
- name: gammacorrection
arguments:
MidPoint: 0.45
Strength: 10.
timescale: 0
- name: chromaticabberation
arguments:
Strength: 0.001
timescale: 0
- - name: crt
arguments: {}
timescale: 0
- name: glow
arguments:
Strength: 0.05
timescale: 0
- name: gammacorrection
arguments:
MidPoint: 0.1
Strength: 4.
timescale: 0
- name: gammacorrection
arguments:
MidPoint: 0.45
Strength: 8.
timescale: 0
- name: chromaticabberation
arguments:
Strength: 0.001
timescale: 0
- - name: crtcurve
arguments:
Strength: 0.5
timescale: 0
- name: glow
arguments:
Strength: 0.04
timescale: 0
- name: gammacorrection
arguments:
MidPoint: 0.1
Strength: 4.
timescale: 0
- name: gammacorrection
arguments:
MidPoint: 0.45
Strength: 8.
timescale: 0
- name: chromaticabberation
arguments:
Strength: 0.001
timescale: 0
customshadercode:
noise: "//go:build ignore\n\n//kage:unit pixels\n\npackage main\n\nvar Strength
float\nvar Time float\nvar Scale float\n\nfunc Fragment(dstPos vec4, srcPos
vec2, color vec4) vec4 {\n\t\t\tvar clr vec4\n\t\t\tclr = imageSrc2At(srcPos)\n\t\t\tamount
:= abs(cos(sin(srcPos.x*Scale+Time+cos(srcPos.y*Scale+Time)*Scale)*Scale+sin(srcPos.x*Scale+Time)*Scale))
* Strength\n\t\t\tclr.r += amount\n\t\t\tclr.g += amount\n\t\t\tclr.b += amount\n\t\t\tclr.a
+= amount\n\t\t\treturn clr\n}\n\t\t\t"
mpris:
enable: false
texttitleyoffset: 0
textalbumyoffset: -7
textdurationyoffset: 0
textopacity: 255
Example aliases for running the setup seen in the screenshots
xyosc-s-1 = "xyosc -mix -lo=0 -hi=0.0015 -width=650 -height=650 -x=-1332 -y=0 -gain=2 &";
xyosc-s-2 = "xyosc -mix -lo=0.0015 -hi=0.0045 -width=650 -height=650 -x=-666 -y=0 -gain=3 &";
xyosc-s-3 = "xyosc -mix -lo=0.0045 -hi=0.0135 -width=650 -height=650 -x=0 -y=-333 -gain=3 &";
xyosc-s-4 = "xyosc -mix -lo=0.0135 -hi=0.1875 -width=650 -height=650 -x=666 -y=0 -gain=2 &";
xyosc-s-5 = "xyosc -mix -lo=0.1875 -hi=0.9375 -width=650 -height=650 -x=1332 -y=0 -gain=4 &";
xyosc-s-6 = "xyosc -mix -width=650 -height=650 -x=0 -y=333 &";
xyosc-sep = "xyosc-s-1 & xyosc-s-2 & xyosc-s-3 & xyosc-s-4 & xyosc-s-5 & xyosc-s-6";
Screenshots
https://github.com/user-attachments/assets/25415824-34aa-4e46-824f-699a99bb9cec
https://github.com/user-attachments/assets/a527369c-aa43-45d3-b790-9c0956e8d629
https://github.com/user-attachments/assets/8495da4f-dadc-44ab-9f8d-dc0331f0c421
https://github.com/user-attachments/assets/7b6c6545-5a93-4ba8-8a8a-a381d3e62672