Ideas
Custom Tone and Modulation Waveforms
Adding Custom Waveforms (The Ability to define waveforms outside of the predefined ones) would enhance the ability to customize the sound of Binaural Beats, Monaural Beats and more. It could also make Isochronic Tones (Or the Pulse effect) more customizable than before. Even the spin effect (And maybe other effects) would be much more customizable.
This feature would make Synapseq much more Customizable than Sbagen+ ever was.
Here is a quick concept how a waveform could be defined:
waveform:(waveformname)
0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0
(This would create a more Pulse like wave)
9 replies
ruanklein replied
I like the suggestion, but we need to refine how custom waveforms would actually work inside SynapSeq, especially in terms of syntax and level of customization.
SynapSeq follows a few core design principles that we should not drift too far from:
- One way to do it - a single, clear approach for each task
- Clarity over cleverness - readable and straightforward syntax
- Intention over syntax - focus on what you want to achieve
- Less options, more focus - essential features only
Regarding the example provided:
waveform:(waveformname) 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0What exactly do these digits represent? Are they normalized amplitude values? What is the valid range? 0-1? -1-1?
As it stands, this syntax may conflict with the principle of Clarity over cleverness. If you could describe in more detail what these values represent, and what kind of creative control you are trying to achieve beyond the existing sine, square, triangle, and sawtooth waveforms, we could better evaluate whether this feature aligns with the project’s philosophy and possibly consider it for a future version.
XenoxYT replied
Yes the digits would represent amplitude values (it would be would better to make them range from 0 to 100). The degits define one cycle of the waveform. It would allow changing the sound of Isochronic tones for example without putting them into a external program. Some Sequences back in sbagen did work better with the Pulse wave described above. For example the Pulse wave could get put then in a Template Sequence file to make it usable for others.
Maybe there is a better option to do the definition of the custom waveforms in a more simple way to make it easier. This would follow the core design principles because it gives full control of the sound.
XenoxYT replied
This would also allow better balancing between a more relaxing sounding waveform and a more aggressive sounding waveform.
XenoxYT replied
Seems like Github had a bug last days (It automatically hided this Idea after I opened it on the mobile Github app)
ruanklein replied
That clarification helps a lot.
However, if custom waveforms are introduced, they need to fit naturally into SynapSeq’s design language. When someone reads a sequence file, they should immediately understand:
- "This is a preset."
- "This is a timeline."
- "This is a background configuration."
- "This is a waveform definition."
The syntax must be visually and conceptually consistent with the rest of SynapSeq. It should feel like part of the language.
If you’re open to it, I’d suggest proposing a few prototype syntaxes that follow the existing style of SynapSeq. For example:- Indentation-based blocks (like presets)
- Keyword-driven definitions
- Minimal ambiguity in value ranges and structure
If you can provide one or two alternative syntaxes that feel simple, readable, and aligned with the current format, that would be a good starting point for exploring a proof of concept using the current audio engine.
The key question is not only how to define the waveform numerically, but how to express it in a way that preserves clarity and intention.
XenoxYT replied
These are a few ideas.
Concept 1:
##Waveform (a single cycle) gets directly defined with the Amplitude values ranging from 0 to 100 percent separated by a space in the tone element.
waveform 0 0 0 0 0 100 100 100 100 0 0 0 0 0 0 0 tone 200 binaural 4 Amplitude 10Concept 2 (Waveform gets defined like a tone element in a preset, Maybe could be used like a template preset to integrade it into other sequences (Like using a waveform someone already made on the hub)):
Test
waveform pulselike add (Here are the Amplitude values ranging from 0 to 100% (values above 100 will scaled to fit in the range))
waveform pulselike tone 200 binaural 4 Amplitude 5Concept 3 (Waveform gets defined by a @ option)
@waveform pulselike 0 0 0 0 0 0 0 100 100 100 0 0 0 0 0 0 0 0
(Now it gets used in a preset like the predefined ones)
Documentation: The Pulselike example could get used for a example sequence (I used your waveform example sequence as base).
Here is one:
(A sample waveform sequence using Concept 3 as example)
Options
@waveform pulselike 0 0 0 0 0 0 0 100 100 100 0 0 0 0 0 0 0 0Presets
waveform-one
waveform pulselike tone 250 isochronic 8 amplitude 15
waveform-two
waveform sine tone 250 isochronic 8 amplitude 5
waveform-three
waveform pulselike tone 250 isochronic 8 amplitude 10
waveform-four
waveform sawtooth tone 250 isochronic 8 amplitude 10Timeline
00:00:00 silence
00:00:10 waveform-one
00:00:20 silence
00:00:30 waveform-two
00:00:40 silence
00:00:50 waveform-three
00:01:00 silence
00:01:10 waveform-four
00:01:20 silenceAnother Sequence using Concept 2:
Presets
waveform-one
waveform pulselike add 0 0 0 0 0 0 0 0 100 100 100 0 0 0 0 0 0
waveform pulselike tone 250 isochronic 8 amplitude 15
waveform-two
waveform square tone 250 isochronic 8 amplitude 5
waveform-three
waveform pulselike add 0 0 0 0 0 0 0 0 100 100 100 0 0 0 0 0 0
waveform pulselike tone 250 isochronic 8 amplitude 10
waveform-four
waveform sawtooth tone 250 isochronic 8 amplitude 10Timeline
00:00:00 silence
00:00:10 waveform-one
00:00:20 silence
00:00:30 waveform-two
00:00:40 silence
00:00:50 waveform-three
00:01:00 silence
00:01:10 waveform-four
00:01:20 silenceAnother Sequence using Concept 1:
Presets
waveform-one
waveform pulselike 0 0 0 0 0 0 0 100 100 100 0 0 0 0 0 0 0 0 tone 250 isochronic 8 amplitude 15
waveform-two
waveform square tone 250 isochronic 8 amplitude 5
waveform-three
waveform pulselike 0 0 0 0 0 0 0 100 100 100 0 0 0 0 0 0 0 0 tone 250 isochronic 8 amplitude 10
waveform-four
waveform sawtooth tone 250 isochronic 8 amplitude 10Timeline
00:00:00 silence
00:00:10 waveform-one
00:00:20 silence
00:00:30 waveform-two
00:00:40 silence
00:00:50 waveform-three
00:01:00 silence
00:01:10 waveform-four
00:01:20 silence(I removed the hashtags to make it better readable for github)
ruanklein replied
Thank you for taking the time to explore multiple syntax concepts. That definitely helps move the discussion forward.
After reviewing the ideas, I believe the only approach that remains consistent with SynapSeq overall design philosophy is a named waveform definition (like your Concept 3), similar to how presets and (future) named backgrounds work.
Instead of index-based definitions or inline numeric blocks inside tone elements, a more coherent approach would be something like:
@waveform pulselike 0 0 0 0 0 0 100 100 100 0 0 0 0 0 my-preset waveform pulselike tone 300 binaural 10 amplitude 10If this feature moves forward, this named-resource model is currently the only syntax I’ve found that fits naturally into SynapSeq without breaking its design principles.
The next step would be to clearly define constraints such as:
- Valid value range (e.g 0-100 or 0-1)
- Minimum and maximum number of points
- How normalization and interpolation would be handled internally
That said, this feature will not be part of the upcoming 3.6 release. If implemented, it would likely be considered in a later phase after further refinement of the syntax, constraints (value range, minimum/maximum points), and internal handling (normalization and interpolation).
For now, I want to ensure that any addition to the language remains fully aligned with SynapSeq core philosophy before moving forward.
XenoxYT replied
0 to 100 would get used to make it clear for everyone to understand it without having to use a comma/dot (It would still be supported but isnt needed) . the -1 to 1 was for the WebAudioAPI. In the old Sbagen when you made a wave definition it got smoothed using a sine function (The function the original sbagen used is still in your sbagen+ docs (But ignore the binaural beats calculation)). There was a minum number of 2 points and the maximum was the end of the current line (Only 1 line is supported). Everything above 100 and below 0 get normalized and scaled to fit in the 0 to 100 percent range.
I hope this helps.
ruanklein replied
Thanks for the suggestion and for the examples you provided earlier. I revisited this idea and ended up implementing support for custom waveforms.
Custom waveforms will be available in the next SynapSeq release.
They can be defined once using
@waveformand referenced by name anywhere a waveform is supported:@waveform softpulse 0 0 15 55 90 100 100 75 40 15 0 @waveform sharp-pulse 0 0 0 100 100 0 0 0 @waveform rounded-wave 50 70 88 100 88 70 50 30 12 0 12 30 tone-set-one waveform sharp-pulse tone 300 isochronic 10 amplitude 50 tone-set-two waveform softpulse tone 300 isochronic 10 amplitude 50 tone-set-three waveform rounded-wave tone 300 isochronic 10 amplitude 50Custom waveforms are also fully integrated with SynapSeq's existing ramp system. This means waveform transitions can be interpolated between:
- two custom waveforms
- a built-in waveform and a custom waveform
- a custom waveform and a built-in waveform
- two built-in waveforms, as before.
So, for example, a sequence can gradually transition from sharp-pulse to softpulse, or from a built-in waveform such as sine to a custom waveform, rather than switching abruptly between them.
Built-in waveforms such as
sine,square,triangle, andsawtoothremain unchanged, so the feature is completely optional and backward-compatible.Custom waveforms are also available through the public Go API, so sequences created programmatically have access to the same functionality:
builder, err := spsq.New(synapseq.NewAppContext()) if err != nil { t.Fatalf("New error: %v", err) } builder.Waveform( "softpulse", 0, 0, 20.5, 60, 100, 60, 20, 0, ) focus := builder.NewPreset("focus") focus. Tone(200). Waveform("softpulse"). Isochronic(10). Amplitude(20) loaded, err := builder. PresetAt(0, focus). PresetAt(time.Second, focus). Load() if err != nil { t.Fatalf("Load error: %v", err) }
This keeps the SPSQ DSL and the public Go API consistent: a waveform can be defined by name and then referenced by presets regardless of whether the sequence is written as SPSQ or constructed programmatically.
This is a static mirror of the SynapSeq GitHub Discussions.