Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bitwig Studio 5.0.9 has distorted automation #56

Closed
lewloiwc opened this issue Oct 18, 2023 · 14 comments
Closed

Bitwig Studio 5.0.9 has distorted automation #56

lewloiwc opened this issue Oct 18, 2023 · 14 comments
Assignees
Labels
automation Issue related to parameter automation bitwig Bitwig Studio related bug Something isn't working critical This is a critical bug, that should be fixed ASAP. fixed This issue is now fixed and waiting for verification

Comments

@lewloiwc
Copy link

The content is the same as what I wrote here.
free-audio/clap#324
I was on Bitwig Studio 4.4.10 at the time, but when I just tried it with Bitwig Studio 5.0.9, it maintained exactly the same behavior.

https://nakst.gitlab.io/tutorial/clap-part-2.html
I have created a CLAP that outputs automation and modulation as DC signals, which I made based on this page, so you can use it if you like.
Automation is output on the left and modulation is output on the right as a DC signal.
https://drive.google.com/file/d/1056gHqgdpBMf8HgIYaqripdRtiRDHl52/view?usp=sharing

  • Windows 10 Home
  • Bitwig Studio 5.0.9

Translated with www.DeepL.com/Translator (free version)

@abique abique self-assigned this Oct 18, 2023
@abique abique added bug Something isn't working bitwig Bitwig Studio related automation Issue related to parameter automation critical This is a critical bug, that should be fixed ASAP. labels Oct 18, 2023
@abique
Copy link
Contributor

abique commented Oct 18, 2023

Can you try with bitwig 5.1 beta 1?
I did some changes there maybe it is fixed already.

@lewloiwc
Copy link
Author

Sorry, I only have Bitwig Studio 4.4.10 8-Track and Bitwig Studio 5.0.9 Trial, so I don't have access to the beta...
I will try Bitwig Studio 5.1 when it is released!

Translated with www.DeepL.com/Translator (free version)

@lewloiwc
Copy link
Author

lewloiwc commented Nov 2, 2023

Could this be the reason for the bug that keeps calling https://github.com/free-audio/clap/blob/094bb76c85366a13cc6c49292226d8608d6ae50c/src/plugin-template.c#L190C1-L194C8 even when the automation is horizontal and the value does not move during playback?

In such cases, there is no problem, but
image

In such cases, it continues to be called. The playback start position is also relevant.
image
image
image

I would like to check the beta version myself, but there is no way to access it, so I am writing it here just in case.

  • Windows 10 Home
  • Bitwig Studio 5.0.9

Translated with www.DeepL.com/Translator (free version)

@lewloiwc
Copy link
Author

lewloiwc commented Dec 6, 2023

I checked the latest version and it has not been corrected.

The video was filmed → https://youtu.be/XQvhnonthNE

Windows 10 Home
image

Translated with www.DeepL.com/Translator (free version)

@abique
Copy link
Contributor

abique commented Dec 6, 2023

I'm sorry it isn't fixed, I must have missed something.
I'll make it top priority.

@abique
Copy link
Contributor

abique commented Dec 14, 2023

Should be fixed for Bitwig Studio 5.1.1

@abique abique added the fixed This issue is now fixed and waiting for verification label Dec 14, 2023
@abique
Copy link
Contributor

abique commented Dec 21, 2023

@lewloiwc we just released 5.1.1, please can you verify the fix?
Thank you 👍

@lewloiwc
Copy link
Author

Sorry, I am late in noticing your reply!
But I happened to be searching for the release of Bitwig Studio 5.1.1 on the 22nd and Google's Generative AI told me that Bitwig Studio 5.1.1 was released on December 21, 2023. And I tried to find where to download it, but couldn't find it at that time.
Then I noticed your reply just now, and when I searched again, I noticed that it says (pre-release), so I guessed that perhaps my Bitwig Studio 4.4.10 8-Track license allows me to download it in a place I don't have access to.
I'm really sorry, but I can't afford to renew my license right now, so let me check when it's officially released...
I really appreciate the work you did on the fix. Thank you very much!

Translated with www.DeepL.com/Translator (free version)

@abique
Copy link
Contributor

abique commented Dec 27, 2023

I added a NFR license to your account.
Please when you have time, try again. And I hope that you'll enjoy Bitwig as well :-)

@free-audio free-audio deleted a comment from lewloiwc Dec 27, 2023
@lewloiwc
Copy link
Author

Wow! Thanks for the license! I will check it as soon as possible!

I checked with the latest Bitwig Studio 5.1.2 and found that 99.99% of the CLAP automation bugs have been cured!
The remaining 0.01% are quite minor, to the point where I can say that this is no longer a problem, but I am reporting it just in case.

image
image
The video was filmed → https://youtu.be/EWT0E4wXy-s
The light blue line on the oscilloscope indicates that the parameter value has changed.

It also depends on whether there is an automation point before the playback start position.
image

I'm not sure if this is actually a bug or not, maybe this is the correct behavior? (I remember that sforzando had the same behavior, as I recall.)
image

CLAP used for verification -> https://drive.google.com/file/d/109C5bw5RSlXelXzG-9PrI5yIrIfhUYxH/view?usp=sharing

In fact, I think the impact of these bugs on the sound is close to zero, just a little extra updating of filters and other coefficients as the parameters change.

Anyway, the bugs I was concerned about were fixed! Thank you so much and I will enjoy Bitwig!

Translated with www.DeepL.com/Translator (free version)

@abique
Copy link
Contributor

abique commented Dec 27, 2023

Thank you again 👍
I'll take a look after the holidays.

@baconpaul
Copy link
Collaborator

that looks exactly like a float-vs-double thing. somewhere in the code path did a float cast happen?

@abique
Copy link
Contributor

abique commented Dec 27, 2023

that looks exactly like a float-vs-double thing. somewhere in the code path did a float cast happen?

That can be!

@abique abique closed this as completed Apr 8, 2024
@lewloiwc
Copy link
Author

lewloiwc commented Jun 13, 2024

Sorry, I was very busy so my reply is very late!
And I may have misunderstood!
Maybe you were saying something to the effect that the float cast is not happening on the Bitwig side of the code, but on my code?
If so, I should reply to you.
But I was mistaken and didn't say anything...
I think that's why the issue was closed.

The code for this CLAP is shown below. What do you think, perhaps a float cast is not occurring?
When I compile with CLAP 1.2.1 and test with Bitwig 5.1.9, this issue still occurs.
image
Translated with www.DeepL.com/Translator (free version)

code
#include <string.h>
#include <stdio.h>
#include <math.h>
#include "clap/clap.h"

struct MyPlugin {
	clap_plugin_t plugin;
	const clap_host_t *host;
	
	double parameters;
	double mainParameters;
	bool changed;
	bool mainChanged;
	
	double old_value;
};

static void my_plug_process_event(MyPlugin *plugin, const clap_event_header_t *event) {
	if (event->space_id == CLAP_CORE_EVENT_SPACE_ID) {
		if (event->type == CLAP_EVENT_PARAM_VALUE) {
			const clap_event_param_value_t *valueEvent = (const clap_event_param_value_t *) event;
			plugin->parameters = valueEvent->value;
			plugin->changed = true;
		}
	}
}

static void PluginSyncMainToAudio(MyPlugin *plugin, const clap_output_events_t *out) {
	if (plugin->mainChanged) {
		plugin->parameters = plugin->mainParameters;
		plugin->mainChanged = false;
		
		clap_event_param_value_t event = {};
		event.header.size = sizeof(event);
		event.header.time = 0;
		event.header.space_id = CLAP_CORE_EVENT_SPACE_ID;
		event.header.type = CLAP_EVENT_PARAM_VALUE;
		event.header.flags = 0;
		event.param_id = 0;
		event.cookie = NULL;
		event.note_id = -1;
		event.port_index = -1;
		event.channel = -1;
		event.key = -1;
		event.value = plugin->parameters;
		out->try_push(out, &event.header);
	}
}

static const clap_plugin_descriptor_t pluginDescriptor = {
	.clap_version = CLAP_VERSION_INIT,
	.id          = "bitwig_automation_test_2",
	.name        = "bitwig_automation_test_2",
	.vendor      = "bitwig_automation_test_2",
	.url         = "bitwig_automation_test_2",
	.manual_url  = "bitwig_automation_test_2",
	.support_url = "bitwig_automation_test_2",
	.version     = "bitwig_automation_test_2",
	.description = "bitwig_automation_test_2",
	
	.features = (const char *[]) {
		CLAP_PLUGIN_FEATURE_STEREO,
		NULL,
	},
};

static const clap_plugin_audio_ports_t extensionAudioPorts = {
	.count = [] (const clap_plugin_t *plugin, bool isInput) -> uint32_t { 
		return isInput ? 0 : 1; 
	},
	
	.get = [] (const clap_plugin_t *plugin, uint32_t index, bool isInput, clap_audio_port_info_t *info) -> bool {
		if (isInput || index) return false;
		info->id = 0;
		info->channel_count = 2;
		info->flags = CLAP_AUDIO_PORT_IS_MAIN;
		info->port_type = CLAP_PORT_STEREO;
		info->in_place_pair = CLAP_INVALID_ID;
		snprintf(info->name, sizeof(info->name), "%s", "Audio Output");
		return true;
	},
};

static const clap_plugin_params_t extensionParams = {
	.count = [] (const clap_plugin_t *plugin) -> uint32_t {
		return 1;
	},
	
	.get_info = [] (const clap_plugin_t *PLUGIN, uint32_t index, clap_param_info_t *information) -> bool {
		if (index == 0) {
			memset(information, 0, sizeof(clap_param_info_t));
			information->id = index;
			information->flags = CLAP_PARAM_IS_AUTOMATABLE;
			information->min_value = 0.0;
			information->max_value = 1.0;
			information->default_value = 0.5;
			strcpy(information->name, "DC");
			return true;
		} else {
			return false;
		}
	},
	
	.get_value = [] (const clap_plugin_t *PLUGIN, clap_id id, double *value) -> bool {
		MyPlugin *plugin = (MyPlugin *) PLUGIN->plugin_data;
		if (id >= 1) return false;
		*value = plugin->mainChanged ? plugin->mainParameters : plugin->parameters;
		return true;
	},
	
	.value_to_text = [] (const clap_plugin_t *PLUGIN, clap_id id, double value, char *display, uint32_t size) {
		if (id >= 1) return false;
		snprintf(display, size, "%.20f", value);
		return true;
	},
	
	.text_to_value = [] (const clap_plugin_t *PLUGIN, clap_id param_id, const char *display, double *value) {
		return false;
	},
	
	.flush = [] (const clap_plugin_t *PLUGIN, const clap_input_events_t *in, const clap_output_events_t *out) {
		MyPlugin *plugin = (MyPlugin *) PLUGIN->plugin_data;
		const uint32_t eventCount = in->size(in);
		PluginSyncMainToAudio(plugin, out);
		
		for (uint32_t eventIndex = 0; eventIndex < eventCount; eventIndex++) {
			my_plug_process_event(plugin, in->get(in, eventIndex));
		}
	},
};

static const clap_plugin_state_t extensionState = {
	.save = [] (const clap_plugin_t *PLUGIN, const clap_ostream_t *stream) -> bool {
		MyPlugin *plugin = (MyPlugin *) PLUGIN->plugin_data;
		if (plugin->changed) {
			plugin->mainParameters = plugin->parameters;
			plugin->changed = false;
		}
		double temp[1] = {plugin->mainParameters};
		return sizeof(double) == stream->write(stream, temp, sizeof(double));
	},
	
	.load = [] (const clap_plugin_t *PLUGIN, const clap_istream_t *stream) -> bool {
		MyPlugin *plugin = (MyPlugin *) PLUGIN->plugin_data;
		double temp[1] = {plugin->mainParameters};
		bool success = sizeof(double) == stream->read(stream, temp, sizeof(double));
		plugin->mainParameters = temp[0];
		plugin->mainChanged = true;
		return success;
	},
};

static const clap_plugin_t pluginClass = {
	.desc = &pluginDescriptor,
	.plugin_data = nullptr,
	
	.init = [] (const clap_plugin *PLUGIN) -> bool {
		MyPlugin *plugin = (MyPlugin *) PLUGIN->plugin_data;
		clap_param_info_t information = {};
		extensionParams.get_info(PLUGIN, 0, &information);
		plugin->mainParameters = plugin->parameters = information.default_value;
		return true;
	},
	
	.destroy = [] (const clap_plugin *PLUGIN) {
		MyPlugin *plugin = (MyPlugin *) PLUGIN->plugin_data;
		free(plugin);
	},
	
	.activate = [] (const clap_plugin *PLUGIN, double sampleRate, uint32_t minimumFramesCount, uint32_t maximumFramesCount) -> bool {
		return true;
	},
	
	.deactivate = [] (const clap_plugin *PLUGIN) {
	},
	
	.start_processing = [] (const clap_plugin *PLUGIN) -> bool {
		return true;
	},
	
	.stop_processing = [] (const clap_plugin *PLUGIN) {
	},
	
	.reset = [] (const clap_plugin *PLUGIN) {
	},
	
	.process = [] (const clap_plugin    *PLUGIN,
	               const clap_process_t *process) -> clap_process_status {
		MyPlugin *plugin = (MyPlugin *) PLUGIN->plugin_data;
		const uint32_t nframes = process->frames_count;
		const uint32_t nev = process->in_events->size(process->in_events);
		uint32_t       ev_index = 0;
		uint32_t       next_ev_frame = nev > 0 ? 0 : nframes;
		
		for (uint32_t i = 0; i < nframes;) {
			/* handle every events that happrens at the frame "i" */
			while (ev_index < nev && next_ev_frame == i) {
				const clap_event_header_t *hdr = process->in_events->get(process->in_events, ev_index);
				if (hdr->time != i) {
					next_ev_frame = hdr->time;
					break;
				}
				
				my_plug_process_event(plugin, hdr);
				++ev_index;
				
				if (ev_index == nev) {
					// we reached the end of the event list
					next_ev_frame = nframes;
					break;
				}
			}
			
			/* process every samples until the next event */
			for (; i < next_ev_frame; ++i) {
				/* TODO: process samples, here we simply swap left and right channels */
				const double out_l = plugin->parameters;
				const double out_r = plugin->parameters - plugin->old_value;
				plugin->old_value = plugin->parameters;
				
				// store output samples
				process->audio_outputs[0].data32[0][i] = out_l;
				process->audio_outputs[0].data32[1][i] = out_r;
			}
		}
		
		return CLAP_PROCESS_CONTINUE;
	},
	
	.get_extension = [] (const clap_plugin *plugin, const char *id) -> const void * {
		if (0 == strcmp(id, CLAP_EXT_AUDIO_PORTS)) return &extensionAudioPorts;
		if (0 == strcmp(id, CLAP_EXT_PARAMS     )) return &extensionParams;
		if (0 == strcmp(id, CLAP_EXT_STATE      )) return &extensionState;
		return nullptr;
	},
	
	.on_main_thread = [] (const clap_plugin *PLUGIN) {
	},
};

static const clap_plugin_factory_t pluginFactory = {
	.get_plugin_count = [] (const clap_plugin_factory *factory) -> uint32_t { 
		return 1; 
	},
	
	.get_plugin_descriptor = [] (const clap_plugin_factory *factory, uint32_t index) -> const clap_plugin_descriptor_t * { 
		return index == 0 ? &pluginDescriptor : nullptr; 
	},
	
	.create_plugin = [] (const clap_plugin_factory *factory, const clap_host_t *host, const char *pluginID) -> const clap_plugin_t * {
		if (!clap_version_is_compatible(host->clap_version) || strcmp(pluginID, pluginDescriptor.id)) {
			return nullptr;
		}
		
		MyPlugin *plugin = (MyPlugin *) calloc(1, sizeof(MyPlugin));
		plugin->host = host;
		plugin->plugin = pluginClass;
		plugin->plugin.plugin_data = plugin;
		return &plugin->plugin;
	},
};

extern "C" const clap_plugin_entry_t clap_entry = {
	.clap_version = CLAP_VERSION_INIT,
	
	.init = [] (const char *path) -> bool { 
		return true; 
	},
	
	.deinit = [] () {},
	
	.get_factory = [] (const char *factoryID) -> const void * {
		return strcmp(factoryID, CLAP_PLUGIN_FACTORY_ID) ? nullptr : &pluginFactory;
	},
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automation Issue related to parameter automation bitwig Bitwig Studio related bug Something isn't working critical This is a critical bug, that should be fixed ASAP. fixed This issue is now fixed and waiting for verification
Projects
None yet
Development

No branches or pull requests

3 participants