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

Detailed explanation of the tone generation algorithm #11

Open
splatpope opened this issue Apr 4, 2021 · 0 comments
Open

Detailed explanation of the tone generation algorithm #11

splatpope opened this issue Apr 4, 2021 · 0 comments

Comments

@splatpope
Copy link

The comments are somewhat vague, and the video only mentions that "the left and right channels are mapped to the x,y coordinates of the orbit points [...] sampled at 8000hz, then interpolated to 48000hz", iirc.

I understand that this is a POC and I wont hold it against you that it is not throughly documented, but a detailed explanation would be welcome.


I have studied the algorithm thoroughly, but the only conclusive statement I can make is that with the global constants defined in Main.cpp, the following behavior arises :

"steps" is computed as samplerate / max_freq -> steps = 48000/4000 = 12
I posit that this represents the number of samples necessary to represent a cycle of a sinusoidal of frequency max_freq.
Then, the audio buffer is filled. A time cursor named "m_audio_time" advances at half the rate of the buffer cursor, simply because we fill the two channels at every loop.

A cursor inside this "steps" window, called j, is made equal to m_audio_time % steps, meaning that it serves as a sample cursor inside the "steps" window. A new fractal point is computed every time j is zero, AKA we have spanned "steps" samples.

Meaning that every point in the orbit generates 12 samples. (Obviously, if they make a cycle, each point will generate way more)

Apparently, distance values, dx/y and dpx/y, are calculated relative either to the first point then normalized, either to the advancing mean of all previously computed point.

A time cursor named t is computed as j/steps, meaning it represents the relative advancement throughout the window.
Its value is then updated through the function : 0.5 - 0.5 cos(t *pi)
Thus, for every calculated point, t will represent 12 samples of half a cycle of a cosine, bounded between 1 and 0.

I suppose that the magic happens right after that, when you set the value of the output sample to be :
w = t * d + (1-t) * dp
or
w = dp + t * (d - dp)

What it seems to me is that, every time a new orbit point is calculated, it generates a cosine half cycle, spanning 12 samples, and its distance to the previous point is used to manipulate these samples so that their interleaving in the buffer somehow generate different frequencies.

I may certainly have misunderstood some things and would love to be englightened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant