Xhip Synthesizer v8.1 (alpha & RC)

VST, AU, AAX, CLAP, etc. Plugin Virtual Instruments Discussion
Post Reply New Topic
RELATED
PRODUCTS
Xhip Effects Xhip Synthesizer

Post

Calandria wrote: Mon Dec 31, 2018 11:13 pm
AnX wrote: Mon Dec 31, 2018 10:42 pm oh man, the knobs are still touching the LEDs...
Stop Bitching Kriminal.
Anyone that cares that much will edit the skin.
It's the sound that matters and I note you aint got nout to say about that!

ok Mr 10 post sock puppet..... are you an xhip rep?

no

so ignore my post and move on, there's a good girl.

Post

AnX wrote: Mon Dec 31, 2018 10:42 pm oh man, the knobs are still touching the LEDs...
I looked at and fixed that issue already. The fact is there simply isn't enough space to satisfy you with this particular knob, this spacing (including text), font face, font size and these LEDs. It's possible to position the LEDs elsewhere but I prefer the way it is now.

So eventually you'll be able to configure the skin to use your own knobs/LEDs, fonts, spacings and so on, and you can do so yourself.

Here is a look at the widget/visible rectangles so you have an idea of what we're dealing with and that "making the LEDs not overlap the knobs" is in fact impossible: https://i.imgur.com/Rh8CDo0.png

I only trimmed their vertical position by +1 px and technically speaking the body of each component no longer "touches", although the anti-aliasing and shadow at lower resolutions does overlap slightly. At high resolution like 3x the overlap is only in the glare overlay for the LEDS.
Mutant wrote: Mon Dec 31, 2018 11:27 pm Happy 2019. :)

And a little feature request.
This was in some earlier version, got lost with the new UI.
Displaying the numerical value of a touched (and/or maybe even just hovered over) knob without having to turn the knob.

Solves the problem of wondering if i have the modulation set to 0.0 or 0.02. :)
Likewise, happy new year everyone!

I'm not sure which version I might have had hover working in... I suspect it is possible to enable that. I can probably add that to the skin/config file once it's working.

The workaround I use currently is to use the mousewheel in the opposite direction, then back. That only works if there is a mousewheel size step available, otherwise the value will get quantized (say it's at 0.98, if you add +0.625 you'll get 1.0 and moving back get 0.9375.)

Eventually a better solution might be to just add text displays (to a custom skin?) under every control that isn't self-documenting like the switches. With user configurable skins it would also be possible when you want to review preset settings you could just switch to the "everything is a text display" skin instead of the knobs.

Unfortunately I haven't focused on the skinning support yet as I've been 100% aiming at getting effects in presets, then "route" in presets before making the 8.1 release. Skinning will probably be a top aim after that release.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

if you drop the text down you can drop the LED down.

the text wont line up horizontally with the others, but it would look better imo.

as it is its too close

Post

The text can't be "dropped" everywhere, you'd need to change the over-all size of the regions and therefore the over-all size of the entire GUI. It would look way more ugly to have a couple instances of text that doesn't line up.

If someone said "I want to take the current skin but do X from a config file, how hard would that be and is it possible?" I'd be motivated to provide an accurate answer.

Currently every widget has a "widget rectangle". The text is added relative to this rectangle... this is something I'm still working on, so the code is a little bit dirty and will get cleaned up as I implement the skinning and find/solve the issues I haven't solved yet.

The purpose of the widget rect is to ensure every element with text on the GUI has an identical rectangle to which things can be aligned regardless of the size of the widget itself. Otherwise the text on the switches would be differently aligned than with the knobs, since they're different heights. In addition the widget rect allows each widget to be centered in that rectangle which means everything is flexible and stays roughly in position even with fractional scaling ratios. (At 1.5 every odd widget is 1 pixel off, but the even ones are correct since 1.5 + 1.5 = 3.)

The text is currently added to the widgets relative to their parent widget rect plus a static offset:

Code: Select all

	textflags mode(alignment_t::center, alignment_t::top);
	origin_t origin = origin_t::bottom;
	point text_offset = point(0, 2);
	bool skip = false;

	switch (i) {
		case xhip::parameter::glide_mode:
		case xhip::parameter::osc_a_invert:
		case xhip::parameter::osc_b_invert:
			skip = true;
			break;

		case xhip::parameter::sync_mode:
		case xhip::parameter::flt_mode:
		case xhip::parameter::shaper_type:
		case xhip::parameter::glide_type:
			origin = origin_t::top;
			mode.vertical = alignment_t::bottom;
			text_offset = point(0, -2);
			break;

		case xhip::parameter::lfo_a_sync:
		case xhip::parameter::lfo_b_sync:
			origin = origin_t::left;
			mode.horizontal = alignment_t::right;
			mode.vertical = alignment_t::center;
			text_offset = point(-8, 0);
			break;
	}
As you can see this is already used internally to tweak the position of a few elements like the LFO sync switches or others with non-standard alignments.

In order to over-ride these settings a skin file would contain a hierarchy of rules like so:

Code: Select all

// everything inside skin is the top level "default" rule
skin
{
	knob { text { offset = (0, 12); }	}
	// sub categories can override the default rule
	filter
	{
		knob { text { offset = (0, -6); }	}
		// specific widgets can also override
		cutoff { knob { text { offset = (15, 4); color = red; } } }
	}
}
It might be nice to eventually add point notation so you could do:

Code: Select all

skin.filter.cutoff.knob.text.offset = (15, 4); 
... which would simplify cases where you have only a couple "tweaks" applied.

So this wouldn't be too hard to implement almost immediately, most of the work would be overhead related to setting up the skin file at all (which is the reason I haven't done it, maybe a couple days of work.)
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

ok, i didnt realise the skin was constructed that way, i thought it was image based with a config file or similar

my mistake

Post

If you're interested you should check out the skin configuration available for Xhip Effects.

I haven't documented it much directly but there is this thread viewtopic.php?f=6&t=491733

The effects already implement most of that sizing configuration. You can also override the type of knob (using knob strip bitmaps) and fonts. This is the same system I'll implement in Xhip Synthesizer.

Eventually the widget configuration (layouts) will be implemented this way too.

For example the current hard-coded implementation looks like (from envelopes/modulators):

Code: Select all

#include "branis_gui.h"

#include <ad/xhip/parameters.h>

#include <ad/gui/widgets/led.h>

using namespace ad;
using namespace ad::gui;
using namespace xhip;

namespace xhip
{
	void add_wave_icon(element_t *v);
	void select_lfo_wave_icon(element_t *v);

	const char *lfo_range_labels[] = 
	{
		"Low",
		"Audio",
		"Tempo",
	};

	gui::led_strip_layout lfo_range_layout =
	{
		point(42, 38),
		point(0, 20),
		point(0, -10),
		point(0, 0),
		lfo_range_labels,
		0,
		"led green",
		3,
	};

	const char *lfo_bias_labels[] = 
	{
		"-",
		"0",
		"+",
	};

	gui::led_strip_layout lfo_bias_layout =
	{
		point(42, 38),
		point(0, 20),
		point(0, -10),
		point(4, 0),
		lfo_bias_labels,
		0,
		"led green",
		3,
	};
};

void xhip::gui::populate_envelope(element_t *p, int i)
{
	element_t *main = add_group(p, point(0, 0), "main");

	int edelta = i * (parameter::env_b_attack - parameter::env_a_attack);
	add_knob(main, ga(0, 0), xhip::parameter(parameter::env_a_attack     + edelta));
	//add_knob(e, ga(0.5, 0),   xhip::parameter(parameter::env_a_peak       + edelta));
	add_knob(main, ga(1, 0), xhip::parameter(parameter::env_a_decay      + edelta));
	add_knob(main, ga(2, 0), xhip::parameter(parameter::env_a_sustain    + edelta));
	add_knob(main, ga(3, 0), xhip::parameter(parameter::env_a_release    + edelta));
	add_slsw(main, ga(0, 1), xhip::parameter(parameter::env_a_attacksync + edelta));
	add_knob(main, ga(1, 1), xhip::parameter(parameter::env_a_keytrack   + edelta));
	add_ddrp(main, ga(2, 1), xhip::parameter(parameter::env_a_trigger    + edelta));

	element_t *mleds = add_group(p, point(0, 0), "leds");

	point loffset = point(8, 25);
	add__led(mleds, ga(0, 0) + loffset, "led green",  "Aled");
	add__led(mleds, ga(1, 0) + loffset, "led green",  "Dled");
	add__led(mleds, ga(2, 0) + loffset, "led yellow", "Sled");
	add__led(mleds, ga(3, 0) + loffset, "led red",    "Rled");
	add__led(mleds, ga(2, 1) + point(28, 24), "led red",    "Gled");

	leds.env[i].attack  = (control *)mleds->find("Aled");
	leds.env[i].decay   = (control *)mleds->find("Dled");
	leds.env[i].sustain = (control *)mleds->find("Sled");
	leds.env[i].release = (control *)mleds->find("Rled");
	leds.env[i].gate    = (control *)mleds->find("Gled");

	main->expand_to_contain_children();

	//element_t *mu = add_group(p, point(0, 0), "mutant");
	//mu->hide();
	//add_knob(mu, ga(0, 0), 0, );

	p->expand_to_contain_children();
}

void xhip::gui::populate_lfo(element_t *p, int i)
{
	element_t *main = add_group(p, point(0, 0), "main");
	element_t *mleds = add_group(p, point(0, 0), "leds");

	int mdelta = i * (parameter::lfo_b_frequency - parameter::lfo_a_frequency);
	add_slsw(main, ga(3, -0.5f), xhip::parameter(parameter::lfo_a_sync  + mdelta));
	add_knob(main, ga(0, 0), xhip::parameter(parameter::lfo_a_frequency + mdelta));
	add_knob(main, ga(1, 0), xhip::parameter(parameter::lfo_a_delay     + mdelta));
	element_t *wf = 
	add_ddrp(main, ga(2, 0), xhip::parameter(parameter::lfo_a_waveform  + mdelta), 0, &dp.lfo);
	add_knob(main, ga(0, 1), xhip::parameter(parameter::lfo_a_duty      + mdelta));
	add_knob(main, ga(1, 1), xhip::parameter(parameter::lfo_a_keytrack  + mdelta));

#if 1
	// slide switches
	element_t *lfo_range = add_slsw(main, ga(2, 1), xhip::parameter(parameter::lfo_a_range + mdelta));
	element_t *lfo_bias = add_slsw(main, ga(3, 1), xhip::parameter(parameter::lfo_a_bias   + mdelta)); 

	ASSERT(lfo_range);
	if (lfo_range) {
		add_text(lfo_range, "Low",   textflags(alignment_t::center, alignment_t::bottom), origin_t::left_top);
		add_text(lfo_range, "Audio", textflags(alignment_t::center, alignment_t::top),    origin_t::bottom, point(0, -2));
		add_text(lfo_range, "Tempo", textflags(alignment_t::center, alignment_t::bottom), origin_t::right_top);
	}
	
	ASSERT(lfo_bias);
	if (lfo_bias) {
		add_text(lfo_bias, "-",      textflags(alignment_t::left,   alignment_t::top),    origin_t::left_bottom, point(0, -2));
		add_text(lfo_bias, "0",      textflags(alignment_t::center, alignment_t::bottom), origin_t::top); 
		add_text(lfo_bias, "+",      textflags(alignment_t::right,  alignment_t::top),    origin_t::right_bottom, point(0, -2)); 
	}
#else
	// LED switches
	add_leds(p, ga(2, 1) + point(-4, 0), xhip::parameter(parameter::lfo_a_range       + mdelta), xhip::lfo_range_layout);
	add_leds(p, ga(3, 1), xhip::parameter(parameter::lfo_a_bias        + mdelta), xhip::lfo_bias_layout); 
#endif

	add_wave_icon(wf);
	select_lfo_wave_icon(wf);

	point loffset = point(8, 25);
	add__led(mleds, ga(0, 0) + loffset, "led red",    "Fled");
	add__led(mleds, ga(1, 0) + loffset, "led yellow", "Dled");

	leds.mod[i].on    = (control *)mleds->find("Fled");
	leds.mod[i].delay = (control *)mleds->find("Dled");

	element_t *vl = add_group(mleds, point(22, -12), "Vleds");
	vl->set_print_hide_children();
	for (int j = 0; j < 3; j++) {
		char name[16];
		sprintf(name, "%i", j+1);
		leds.mod[i].wave[j] = add__led(vl, point(7*j, 0), "led green", name);
	}
	vl->expand_to_contain_children();

	p->expand_to_contain_children();
}

void xhip::gui::populate_modulators(element_t *p)
{
	for (int i = 0; i < 2; i++) {
		populate_envelope(add_group(p, point(0, 127 * i), "adsr"), i);
		populate_lfo(add_group(p, point(0, 127 * (2 + i)), "lfo"), i);
	}

	p->expand_to_contain_children();
};
So you can see that's a little bit complicated because there is a bit more going on that just listing widgets and offsets. For other sections however it really is that simple (from filter):

Code: Select all

#include "branis_gui.h"

#include <ad/xhip/parameters.h>

using namespace ad;
using namespace ad::gui;
using namespace xhip;

namespace xhip
{
	const char *filter_menu =
		"[68x12][lBypass]"
		"[60x48]-=0,"
#if 0
		"[68x12][lSallen-Key]"
		"[60x12]Low 12 dB,Band 6 dB,High 6 dB,"
#endif

		"[n]"

		"[68x12][lKHN]"
		"[60x12]Low 12 dB=1,High 12 dB,Band 6 dB,Notch,"

#if 0
		"[68x12][lFour-pole]"
		"[60x12]Low 24 dB=1,Low 18 dB,Low 12 dB,Low 6 dB,"
#endif
		"[n]"

		"[68x12][lKHN x2]"
		"[60x12]Low 24 dB=5,High 24 dB,Band 12 dB,Notch x2,"
		
		"[n]"
		;
};

void xhip::gui::populate_filter(element_t *p)
{
	add_knob(p, ga(0, 0),                parameter::flt_cutoff);
	add_knob(p, ga(1, 0),                parameter::flt_resonance, 0, 1);
	add_menu(p, ga(2, 0), drop_type_t::half_top, parameter::flt_mode, 0, xhip::filter_menu);
	add_drop(p, ga(2, 0), drop_type_t::half_bottom, parameter::flt_trigger);
	add_knob(p, ga(0, 1),                parameter::flt_fmod);
	add_knob(p, ga(1, 1),                parameter::flt_qmod);
	add_knob(p, ga(2, 1),                parameter::flt_keytrack);
	add_knob(p, ga(3, 1),                parameter::flt_saturation);
	add_knob(p, ga(0, 2),                parameter::flt_env_a, 0, 1);
	add_knob(p, ga(1, 2),                parameter::flt_env_b, 0, 1);
	add_knob(p, ga(2, 2),                parameter::flt_lfo_a, 0, 1);
	add_knob(p, ga(3, 2),                parameter::flt_lfo_b, 0, 1);
	p->expand_to_contain_children();
}
So in those cases it would be almost 1-to-1 mapping into a skin layout such as:

Code: Select all

filter
{
	cutoff = "knob, (0, 0)";
	resonance = "knob, (1, 0)";
	mode = "menu ..., (2, 0)";
	trigger = "menu ..., (2, 0)";
	// etc
}
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

I've uploaded a new alpha r1154 - same version as the last screenshot but that was mid-way through modifications and this revision still is.

Note the "INCOMPAT" in the filename. If you save stuff using this version it's risky business like going for a wee near an electric fence. Don't say I didn't warn you! (edit: https://youtu.be/0bme0JpXQUg )

This version (on the alpha page) supports storing effects in presets using the "preset" effects tab. You'll need to manually use the menu in the effects section "store to preset" because the code isn't finished yet.

Most of the work I've been doing is going to apply directly to the route stuff as well, so that's good. The route stuff will need a lot more work of its own though since I plan to support 128 preset route configurations which will work exactly like the effects and just add extra route rows. That will hopefully support multi-timbral "drum mode".

There are a couple presets with the effects to test on the alpha page. These should load fine in older versions but the effects will be lost when you load/save them in older versions.

I did a bunch of other stuff I can't be bothered to remember too.

Oh yeah there is that one, I guess I should mention it. Kind of important?

This version is highly optimized using runtime profiling and provides a "mod div" knob in the control section to use a reduced modulation rate. This will often have nasty effects on sounds but a large number of sounds are not significantly affected, usually pads and sounds you want a lot of unison for. So in those cases using mod div = 16 means you can get as much as 6 times as many voices. For example I can manage near 32 full voices normally, but with div = 16 I can get 200+.

This is never going to "sound the same" and some issues are impossible to fix. Others will eventually be fixed such as the obvious "interpolate amplitudes" and similar to eliminate the tones you hear during quick modulation. It's possible to anti-alias modulation but it tends to be more then 16x as expensive so would defeat the purpose.

This is mostly useless in my opinion since it's limited to cases where CPU becomes an issue which generally means only for heavy unisons. That said it is useful in that rare case or if you're one of those unisonhypermaniacs that applies unison to everything including plain sine waves.
Last edited by aciddose on Fri Feb 28, 2020 9:48 am, edited 1 time in total.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

aciddose wrote: Wed Jan 16, 2019 8:14 pm This version (on the alpha page) supports storing effects in presets using the "preset" effects tab. You'll need to manually use the menu in the effects section "store to preset" because the code isn't finished yet.

...

Most of the work I've been doing is going to apply directly to the route stuff as well, so that's good. The route stuff will need a lot more work of its own though since I plan to support 128 preset route configurations which will work exactly like the effects and just add extra route rows.

...

This version is highly optimized using runtime profiling and provides a "mod div" knob in the control section to use a reduced modulation rate. This will often have nasty effects on sounds but a large number of sounds are not significantly affected, usually pads and sounds you want a lot of unison for. So in those cases using mod div = 16 means you can get as much as 6 times as many voices. For example I can manage near 32 full voices normally, but with div = 16 I can get 200+.
:tu: :)
[====[\\\\\\\\]>------,

Ay caramba !

Post

https://soundcloud.com/xhip/xhandom

You can hear how awful it sounds without even bothering to do amplitude interpolation. It also doesn't make as big a difference if you use audio-rate mod in the filter or xmod on the oscillators, of course. That's the xhipylophone.xhippreset

I'm quite proud of trumpaloompa_fm5.xhippreset but shouldn't be... but it is pretty cool to be able to get such sounds. I've been thinking I should really add some switch to enable other modulator delay modes (like delay vs. decay) since that would allow breath via noise modulation.

In addition however I've wanted to implement keymapping and layering which would allow a huge world of new layered sounds and part of those would be breath sounds of course which could then simply be layered on top. A multi-timbral dynamically layerable voice allocator is not so simple however.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

I would also like to learn to cast spells such as "automaticatus deliciacatus" which summons a giant robotic cat that delivers any sort of food you want at any time. He's also a super genius programmer that can magically make programs delicious.

Here he is in action:
https://youtu.be/ffWG0jv_PKw
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

> old deleted soundcloud link https://soundcloud.com/xhip/trumper
> same preset used:
https://soundcloud.com/xhip/lsl
Last edited by aciddose on Mon Jul 19, 2021 6:24 am, edited 2 times in total.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

Oh shxt that Trumper presets sounds really good. After some reverb, delay and saturation it'd be a great main to a song.

Post

That one should work perfectly in the official v8 release, just load the preset and set oscs range to 16 and you're good to go.

I also used stereo unison (2x) with 6 cents detune, since unless you get the phase exactly right with width < 100 it sounds muffled. So most likely a reverb/stereowidener/monotostereo effect would be way better there with it playing mono.

Hopefully it'll be possible to add breath control once I work out how to get the preset routing set up... no ETA on that one though. All works fine in v8 you just need to do it manually to set it up yourself.

edit: uh oh, nevermind. I've mucked something up in the preset and it loads fine but the parameters aren't loaded in v8... because of a bug in v8. That's... sort of good.

I've uploaded a "forxhip8" version of the preset with that fixed to the alpha page.

Internally the file has a "vals", size, version = 6 and the bug is v8 refuses to load version>5. That'll be no problem once v8 gets upgraded to v8.1

'v' 'a' 'l' 's' 70 01 00 00 06 00 00 00 ; change 6 to 5

MIDI needs fixup but meh; (the sound was destined for this render I think)
https://soundcloud.com/xhip/lsl
(rendered with single instance Xhip v8 + xfx mdelay, reverb, multiplier and compressor)
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

Nice synth. I guess you're the developer, so I've got a question for you.
In the route section, is 'release' supposed to refer to release velocity?
I've tried it both with live playing, and by putting high and low note-off velocities in a DAW,
using both add and multiply, with positive and negative amounts, and routing it to amp env release.
Neither seems to have any effect.

I normally start out giving a sound a long release time, and then using a negative
amount of release velocity applied to the amp envelope release to control the
amount of time with a quick or slow release of a key.
And then start applying release to other parameters.

Probably not too many others do this in order to test it for you.
Have you tested it to see if it works, or have you possibly implemented it in some other way?
Or maybe by 'release', you don't mean release velocity at all, and I've just misunderstood something.
Last edited by felis on Mon Feb 11, 2019 5:40 pm, edited 1 time in total.

Post

realy cool synth man. If u made the knobs better the synth will be more cool!

Post Reply

Return to “Instruments”