Wusik 4000 Module SDK Docs Ready

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS
Wusik 8008

Post

Indeed, I was thinking the same thing... I will run some tests on things... Txs!

Post

WilliamK wrote: - The above opens up for 3rd party file-format converters. How? Well, let me see if I can explain better... ;-)

In the Extras folder, we would have multiple files named, let's say, SampleLoader001.dll, SampleLoader002.dll and so on.

The host sends to the first one: Hey, I have this file named c:\samples\sample.wav, can you handle it?
Heck NO!
Ok, so, SampleLoader002.dll, can you handle this file?
YEAH!
Yes. This is the "Chain of responsibility" pattern.
:cool:
Now I just need to figure out the dynamics of things. I read somewhere in the JUCE forum that I can't just create a structure in the dynamic library and pass a pointer to it and let the host manage it, is this really right? Can someone shine a light on this?
What they mean is that whoever calls malloc()/new() must also call free()/delete().

Post

Thanks bud! :hug: So, if the module creates the sample data with "new" and pass this to the host, the host can't do a "delete" on it? Just checking. If that is the case, I guess the module will have to pass the sample information and the host will have to relocate it, once done, the module deletes this data, and the host keeps it to send to sample-playback modules which will only read it, not delete it.

Thanks again.

Post

It's actually better for the plugin to make a request to the host to allocate the data, then the plugin fills it, then passes it back to the host which can at any time delete it freely.

ptr = host->allocate_sample(samples... etc)

ptr->member = data

host->give_sample(ptr)

or

host->free_sample(ptr)


then the host can change how the data is allocated freely outside the control of the plugin. For example you may want to align the data or otherwise.

The host can also put allocated blocks into a list associated with a plugin. When/if that plugin is unloaded the host can free any "leaked" data and inform the user "plugin X messed up!"
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

Indeed, I was thinking on something on those terms, thanks bud. :hug:

Post

This is very DRAFT, but still, I finally got how it will work and its simple and effective. :cool:

Code: Select all

// Checking sample data reading possible from module
setSpecialData(kSampleDataCanHandle, "path.filename", size); // in this case, *data is char* (utf8)
// If it can, it should set *size to 1 or leave as 0 if it can't.
// Now, if *size == 1, let's go
{
	// Now, the module should know that we are talking about the "path.filename" we just passed before, as we never call this without calling the above first
	setSpecialData(kSampleDataNextZone, null, size);
	// returns in *size the number of samples, (we don't know if it is stereo for now, so just pass samples*2 if it is stereo and later you tell the 
	// structure what it is, or set *size to 0 if there are no more zones, so we just keep calling ... (kSampleDataNextZone, ... until we get 0 in *size.
	
	// For each zone, we create the structure and pass it back so it can be filled
	setSpecialData(kSampleDataSetZone, *structure, size);

	// If there's any error during any process, return size as -1 and we call the following for the error message
	setSpecialData(kSampleDataError, *errorMessage, 0); // utf8
}
// Otherwise, try another module until no modules are left to handle sample data.
And here's the draft of the sample structure, I will check the Wusik Station structure later today to fill in the blanks...

Code: Select all

	class SampleData
	{
	public:
		SampleData(uint32 _totalSamples)
		{
			channels = 1;
			totalSamples = _totalSamples;
			samples = new float[totalSamples];
			root = 60;
			keyLow = 0;
			keyHigh = 127;
			velLow = 0;
			velHigh = 127;
			flags = 0;
			sampleRate = fT(44100.0);
			fine = fT(1.0);
			pan = fT(0.0);
		};
		~SampleData()
		{
			deleteAndZero(samples);
		};
		//
		float *samples;
		uint32 flags;
		fT sampleRate,
			fine,
			pan;
		uint32 totalSamples,
			channels,
			root,
			keyLow,
			keyHigh,
			velLow,
			velHigh;
	};

Post

This way the host always create and deletes all sample information, while modules can be open-source and handle the loading aspect. :party: Not to mention that adding a new sample format is just adding a new module or tweaking up an existing module. This helps me out a lot!

Post

And here is a more complete Sample Format Structure. :cool:

Code: Select all

	//=========================================================================
	/** Sample Data Zones

		Holds sample zone information so sample-playback modules can 
		handle sample playback
	*/
	class SampleDataZones
	{
	public:
		SampleDataZones(uint32 _totalSamples) :
			channels(1),
			totalSamples(totalSamples),
			root(60),
			keyLow(0),
			keyHigh(127),
			velLow(0),
			velHigh(127),
			flags(0),
			sampleRate(fT(44100.0)),
			fine(fT(1.0)),
			tune(0),
			pan(fT(0.0)),
			loopStart(0),
			loopEnd(0),
			group(0),
			roundRobin(0),
			keySwitch(0),
			extras1(nullptr),
			extras2(nullptr)
		{
			samples = new float[totalSamples];
		};
		~SampleDataZones()
		{
			deleteAndZero(samples);
			if (extras1 != nullptr) deleteAndZero(extras1);
			if (extras2 != nullptr) deleteAndZero(extras2);
		};
		//
		float *samples;
		uint32 flags;
		fT sampleRate,
			fine,
			pan,
			*extras1; // For future usage
		int32 totalSamples,
			channels,
			root,
			tune,
			group,
			loopStart,
			loopEnd,
			keyLow,
			keyHigh,
			velLow,
			velHigh,
			roundRobin,
			keySwitch,
			*extras2; // For future usage
		//
		enum Flags
		{
			kRelease,
			kLegato,
			kFixedPitch,
			kOneShot,
			kReverse
		};
	};

	//=========================================================================
	/** Sample Data Zones

		This is used to send sample information to modules
	*/
	class SampleData
	{
	public:
		SampleData(SampleDataZones **_zonesList, int32 _zones) : 
			zonesList(_zonesList), 
			zones(_zones),
			flags(0) 
		{
			for (int32 zone = 0; zone < zones; zone++)
			{
				if (zonesList[zone]->roundRobin > 0)
				{
					FlagOp::set(Flags::kHasRoundRobin, flags);
					break;
				}
				if (zonesList[zone]->keySwitch > 0)
				{
					FlagOp::set(Flags::kHasKeySwitch, flags);
					break;
				}
			}
		};
		//
		SampleDataZones **zonesList;
		int32 zones;
		uint32 flags;
		//
		enum Flags
		{
			kHasRoundRobin,
			kHasKeySwitch
		};
	};
The extras1 and extras2 is left for future usage. EG: when loading a SFZ file I add some bytes there to save special SFZ information that modules can use. (envelope, filter, etc... info)

Post

This structure is set in the Wusik4000 Module SDK file, I will upload this new file later one, once I test this and confirm it has everything the sample format needs.

Post

No fractional loop points? :)
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

Fractional? I never saw such thing, is this a new thing? :shrug: I guess it is time to check... :dog:

Post

honestly, don't bother IMHO.
In the old days, it was loop tuning not fractional loop points though.
Olivier Tristan
Developer - UVI Team
http://www.uvi.net

Post

Indeed, I did some searching and couldn't find much info about it and no software that could handle it, but it was a quick search. :hihi:

I'm ready to do the very first .WAV/.AIFF file loading, something simple, only one zone, just to test things out and find problems and such...

Post

RIFF has fractional loop points in it's SMPL chunk if I recall correctly. In any case it could be added later. My synth supports it :)
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, ok, ok... I'm just too "lazy" to care for it right now. :hihi:

In any event, still a lot of stuff to be done, mostly before March... :hyper:

Post Reply

Return to “DSP and Plugin Development”