Phase problem

Hello, I would like to kick this problem. I will create one wave over the entire sample buffer, for example like this:

function sine(nr_samples)
	local sin = math.sin
	local pi = math.pi
	local buffer = {}
	for i=0, nr_samples do
		buffer[#buffer + 1] = sin(2 * pi * i / nr_samples)
	end
	return buffer
end

Then I try to create 256 harmonies on this wave using this. input is buffer with created sine wave HARMONIC_SERIES is table with 256 values for harmonies

function wave_calc(samples)
	local abs = math.abs
	local cos=math.cos
	local sin=math.sin
	local pi = math.pi
	local buffer = {}
	local series = HARMONIC_SERIES

	-- speedup for rendering
    -- use only active harmonies
	local active = {}
	for i=1, 256 do
		if series[i] ~= 0 then
			active[#active + 1] = i
		end
	end

	for i=1, #samples do
		local normalize, out = 0, 0
		for k=1, #active do
			local j = active[k]
			local harm = series[j]
			local pos = samples[((i * j - 1) % #samples) + 1] * harm
			out = out + pos 
			normalize = normalize + abs(harm)
		end
		buffer[#buffer + 1] = out / normalize
	end
	return buffer
end

I also have an extra table for the 256 phase values for each of the 256 harmonics.And now the problem I can’t figure out. How do I apply the phase shift for each harmony separately to this function? So for harmony 2 I will use the phase shift from the table of phases 2? Will it be applied to this function like this or am I going about it completely wrong?

here’s what I’m trying to do, unfortunately no phase shifts yet :frowning: Thanks.

Is that a typo? shouldn’t it be #buffer + i ?

similarly here, shouldn’t this be k instead of 1?

wouldn’t it be more normal for(int i=0; i< #sample; ++i)?

What language is this in? also, in the first function you fill #buffer, then in the next one you overwrite buffer? Anyways, when you index into the sine array, add the phase to the index. Scaled appropriately.

But, really, why aren’t you using an FFT for this? It would be nearly trivial…

Also, that normalization code looks pretty funky… shouldn’t in the loop it should be normalize = std::max(normalize, abs(harm))?

hello, it’s adding a value to the end of the buffer. ‘buffer’ is the buffer, ‘#buffer’ is the size of the buffer.

ok. In what language is #buffer a valid variable name? maybe call it sizeOfBuffer?

it is Lua. lua tables indexing from ‘1’ so loop must be (1… #samples), or (0 … #samples - 1). I’m trying to run it in Renoise and at the same time as a script in the Lua VCV module from Wrong People.

ok, sry, my Lua is pretty rusty.

No prob, I’m not skilled with FFT, but one thing i know. FFT in Lua is really sloooow. In pure Lua. In LuaJIT i don’t know :frowning: because Renoise not using LuaJIT. So i must improvize.

FFT in c is very fast, and there is one in the Vcv sdk already.

Anyway, phase is just the sample position.

Another idea, Calculate all values on the go and sum waves.

local i = 1
local buffer = {}
while i <= number_of_samples do
    local j = 1
    local sum = 0
    while j <= 256 do
        local sample = math.sin(2 * math.pi * j * (i / number_of_samples) + table_of_phases[j])
        sum = sum + sample
        j = j + 1
    end
    buffer[#buffer + 1] = sum / 256
    i = i + 1
end

Do you think the result would be the same? so that the result is not white noise.

visible slowdown but seems to be working for now.

Doing that on the fly will, as you note, waste a huge amount of cpu.

Are you sure Fourier decomposition is best for the information conserving task at hand? Is order best represented by increasing sines? Seems like sin is the biggest cycles in the loop. And aliasing? I guess it depends on the harmonic amplitude graph.