Apply Fade To Sample

Is it possible to apply a fade to the end of a sample (like done in the sample editor) through the API?

I want to automatically try and remove all the clicks from the ends of destructively rendered slices.

If I’m not mistaken, you can loop through the last n samples, and multiply their value by (n-i)/n (where i is the iteration). For fades in, you just do the inverse.

On my phone now, so coding it out is a pain, but if you need when I get back to a computer I can show you in code.

Edit : fixed erroneous logic

1 Like

Ok, guessed I might need to do that thankyou.

Is there definitely not a means of selecting sample data and applying the Fade In/Fade Out (or indeed Maximise, Smooth etc)?

function fade_sample (sample, fade_length, bool_fade_in)
--[[--------------------|
	--]]
	bool_fade_in = (bool_fade_in ~= false) -- default: fade out
	fade_length = fade_length or 15 -- frames

	local b = sample.sample_buffer
	local sample_length = b.number_of_frames
	local data = 0
	for c = 1, b.number_of_channels do

		if bool_fade_in then
			-- fade in
			for n = 1, fade_length do
				if n <= sample_length then
					data = b:sample_data(c, n)
					data = ((n - 1) / fade_length) * data -- linear fade in
					b:set_sample_data(c, n, data)
				end
			end
		else
			-- fade out
			for n = 1, fade_length do
				local curr_frame = sample_length - fade_length + n
				if n <= sample_length then
					data = b:sample_data(c, curr_frame)
					data = (1 - (n / fade_length)) * data -- linear fade out
					b:set_sample_data(c, curr_frame, data)
				end
			end
		end

	end
	return sample
end

--[[=====================================
Usage:

Fade IN selected sample over 25 frames (~0.5 ms):
  fade_sample( renoise.song().selected_sample, 25, true )

Fade OUT selected sample over 500 frames (~10 ms):
  fade_sample( renoise.song().selected_sample, 500 )
--===================================--]]

If you wanted to figure out fade times in ms instead of samples, you could do something like this:

function ms_to_frames( sample, milliseconds )
	local frame_length_in_ms = (1000 / sample.sample_buffer.sample_rate)
	return math.ceil( milliseconds / frame_length_in_ms )
end

Happy hacking!

1 Like

As far as I know, there’s nothing in the API for calling these functions directly, so you’d need to roll your own.

Maximizing/normalizing a sample is easy enough: loop through the sample to find the highest value, then multiply every frame’s value in the sample by 1/highest_sample_value to set the sample’s peak to 1 (0dB).

For smoothing, I guess you could look at every odd sample and set the even samples’ values to the midpoint/average between the surrounding odd samples. Or you could pick every n samples to read values from and then evenly ramp the values of the samples between them. The greater the value for n, the “mushier” the sample smoothing.

Honestly, you could spend days writing algorithms here to get the effect you want, but these should basically work without having to do a terrible amount of math.

1 Like

Thanks very much for this. Saved me a fair bit of work man! Probably should get this stuffed in a tool!

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.