A simple XY-oscilloscope written in Go.
Install ontake-xyosc-git
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
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.
- XY mode and single channel mode (L/R/Mix modes) - can be toggled with the
F
key - particles
- MPRIS support
- frequency separation
- theming support
- shader support (using ebitengine's Kage shader language)
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
};
};
}
fpscounter: false
showfilterinfo: true
filterinfotextsize: 16
filterinfotextpaddingleft: 16
filterinfotextpaddingbottom: 4
showmpris: false
mpristextopacity: 255
targetfps: 240
windowwidth: 1000
windowheight: 1000
capturedeviceindex: 0
samplerate: 192000
audiocapturebuffersize: 64
ringbuffersize: 4194304
readbuffersize: 2048
xyoscilloscopereadbuffersize: 2048
readbufferdelay: 32
beatdetectreadbuffersize: 4194304
beatdetectdownsamplefactor: 4
gain: 1
lineopacity: 200
linebrightness: 1
linethickness: 3
lineinvsqrtopacitycontrol: true
lineinvsqrtopacitycontroluselogdecrement: true
lineinvsqrtopacitycontrollogdecrementbase: 200.0
lineinvsqrtopacitycontrollogdecrementoffset: 0.99
linetimedependentopacitycontrol: true
linetimedependentopacitycontrolbase: 0.999
lineopacitycontrolalsoappliestothickness: true
particles: false
particlegenperframeeveryxsamples: 4000
particlemaxcount: 100
particleminsize: 1.0
particlemaxsize: 3.0
particleacceleration: 0.2
particledrag: 5.0
defaultmode: 0
peakdetectseparator: 200
singlechannelwindow: 1200
periodcrop: true
periodcropcount: 2
periodcroploopovercount: 1
fftbufferoffset: 2000
forcecolors: true
accentcolor: "#C7C4DD"
firstcolor: "#C7C4DD"
thirdcolor: "#C7C4DD"
particlecolor: "#E4E0EF"
bgcolor: "#1F1F29"
disabletransparency: false
copypreviousframe: true
copypreviousframealphadecaybase: 0.0000001
copypreviousframealphadecayspeed: 2.0
beatdetect: true
beatdetectinterval: 100
beatdetectbpmcorrectionspeed: 2
beatdetecttimecorrectionspeed: 0.2
beatdetectmaxbpm: 500.0
beatdetecthalfdisplayedbpm: false
showmetronome: true
metronomeheight: 8
metronomepadding: 8
metronomethinlinemode: true
metronomethinlinethicknesschangewithvelocity: true
metronomethinlinethickness: 64
metronomethinlinehintthickness: 2
showbpm: true
bpmtextsize: 24
barswidth: 4
barspaddingedge: 4
barspaddingbetween: 4
barsautogain: true
barsautogainspeed: 0.5
barsautogainminvolume: 0.000000001
barsinterpolatepos: true
barsinterpolateaccel: 20
barsinterpolatedrag: 2
barsinterpolatedirect: 20
useshaders: true
shaders:
- name: glow
arguments:
Strength: 0.05
- name: glow
arguments:
Strength: 0.05
- name: chromaticabberation
arguments:
Strength: 0.005
- name: custom/noise
arguments:
Strength: 0.1
Scale: 1000.0
timescale: 4.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"
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";