Autor Wątek: [DSP] Morphing sine wave -> sawtooth, square, triangle, noise wave  (Przeczytany 2458 razy)

Offline komorra

  • Użytkownik
    • Blog naszego teamu (o grze Voxelfield)

# Sierpień 06, 2013, 23:22:55
Może niecodzienny problem, bo nie do końca związany z gamedevem, ale wiem że tu znajdę łebskich ludzi to postuję.

Otóż mam sobie jeden przebieg sinusa ( [0;2Pi] ), zwyczajny sinus. To czego potrzebuje to wystawić parametr (przyjmujący współczynnik 0..1) który reguluje morphing tego sinusa w falę typu sawtooth (dołączyłem obrazek do posta). Niby proste, a jednak zwykłe zmiksowanie przebiegu sinusa i przebiegu piłokształtnego (sawtooth właśnie) np. 0.3*sine(t) + 0.7*saw(t) powduje że są słyszalne już dwa dźwięki a nie jeden.

Doszedłem do wniosku że tutaj trzeba sterować jakoś zapodawaną dziedziną (t), odpowiednio przyspieszać lub spowalniać narastanie jej wartości. Niestety jak już mi się to udało okazało się, że funkcja *(t) musi być funkcją gładką (czy jak to się tam zwie, pochodna ma być ciągła), bo na wykresie widać "łamania" się sinusa - chociaż ciągłość zachowuje.

Kolejny problem to to, że sinusoida wykonując swój jeden przebieg zalicza górkę i dołek. Piłokształtna fala w czasie tego samego okresu zalicza tylko jedno narastanie i na końcu jeden uskok.

Jak wykonać taki morphing, tak żeby również łatwo sparametryzować morfowanie to triangle i pulse/square? (szum chyba będzie prosty). Nie wiem w ogóle jak podejść do tematu...

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Xender

  • Użytkownik

# Sierpień 06, 2013, 23:43:37
Nie znam się na psychoakustyce, ale zacząłbym od tego, że skoro sawtooth składa się z wielu harmonicznych, to czy sam w sobie nie jest słyszalny jako więcej niż jeden dźwięk?

A co do modyfikowania dziedziny sinusa - szukasz f(x) takiego, żeby sin(f(x)) == sawtooth(x). Skoro sawtooth jest piecewise* liniowe, to szukaną funkcją będzie arcsin.
Oczywiście arcsin ma załamanie, którego nie chcesz - ale sawtooth też ma załamanie, więc chyba nie da się go osiągnąć, modyfikuąc dziedzinę sinusa inną gładką funkcją.

Nawet jeśli wersja z arcsin przejdzie, to przypadek dla parametru morphingu == 1. Nie mam pojęcia, czy w ogóle da się to sensownie zmorphować, i jak.

*(uwaga: terminologia o nieznanym stopniu poprawności)

A tak w ogóle, to można wiedzieć, do czego jest to potrzebne? Konieczność zmorphowania ciągłego sinusa i sniwciągłego sawtooth tak, aby wynik był ciągły (rozumiem, że z tym "załamaniem sinusa" chodzi właśnie o ciągłość?) brzmi jak źle sformułowany problem.

//EDIT - o co chodzi z tym załamaniem sinusa i dlaczego jest to problem? To mi wygląda na dość istotną kwestię.

Offline komorra

  • Użytkownik
    • Blog naszego teamu (o grze Voxelfield)

# Sierpień 07, 2013, 00:00:53
Załamanie na pewno dodaje jakiś nieporządany efekt, bardziej to może nie załamanie co zmiana szybkości narastania sinusa, która widoczna jest na zboczu.

A do czego to.. a no robię sobie VSTka w FlowStone, być może temat powinien być w dziale off-topic.

Dzięki za podpowiedź. A co do:

szukasz f(x) takiego, żeby sin(f(x)) == sawtooth(x)

Jeżeli się da spróbuje tutaj równaniami pojechać, może coś z tego wyjdzie.

Offline koirat

  • Użytkownik

# Sierpień 07, 2013, 00:03:46
Jedno pytanie czy dla krańcowej wartości ma być matematycznie poprawny sawtooth czy jego dokładna aproksymacja jest wystarczająca.

Zawsze możesz "morfować" pochodne może być trochu dokładniej, oczywiście dla sawtooth musisz je policzyć dyskretnie.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

  • +1
# Sierpień 07, 2013, 00:13:34
Możesz w osi Y morphować sinusa do trójkąta liniowo, a w dziedzinie czasu modulować wypełnienie.

A że parę linii kodu jest wartych więcej niż tysiąc słów, poniżej program do przetestowania w EvalDraw:
(x)
x /= 8;

a = mousx/xres;
b = mousy/yres*.5+.5;

x = fmod(x,1);
if(x<b/2) x=x/(b/2);
else if(x<1-b/2) x=1-2*(x-b/2)/(1-b);
else x=-(1-x)/(b/2);

s = sin(x*pi/2);

return s+(x-s)*a;

Mysz w poziomie moduluje kształt amplitudy sinus<-->trójkat.
Mysz w pionie góra-dół moduluje czas sinus/trójkąt<-->piła.

Najlepiej wcisnąć Enter na numerycznej by przejść na pianinko, przytrzymać jakiś grający klawisz i pomachać myszą, czy brzmi akceptowalnie.

Na wyniki dla t<0 nie zwracać uwagi. :)

No i oczywiście dla wyższych tonów (a nawet może i dla niższych) bez oversamplingu się nie obejdzie. :)

Cytuj
Jedno pytanie czy dla krańcowej wartości ma być matematycznie poprawny sawtooth
Ideałem byłby band-limited sawtooth, ale to chyba już za dużo chcieć.

Cytuj
czy jego dokładna aproksymacja jest wystarczająca.
Zdecyduj się w tym stwierdzeniu. :)

Offline komorra

  • Użytkownik
    • Blog naszego teamu (o grze Voxelfield)

# Sierpień 07, 2013, 00:13:51
Myślę że jego dokładna aproksymacja wystarczy. Generalnie proces samego tworzenia przebiegu tutaj wygląda tak że mam zmienną "t" którą co każdy cykl przetwarzania inkrementuję o pewną wartość "pitch" (jak uda mi się to wszystko ukończyć, to oczywiście będzie dostosowane to do częstotliwości próbkowania). Następnie wyrzucam na wyjście wartość "sin(t)".

Offline komorra

  • Użytkownik
    • Blog naszego teamu (o grze Voxelfield)

# Sierpień 07, 2013, 00:21:09
@Krzysiek K.: Dzięki za bardzo pomocą odpowiedź ! :) No i fajny ten evaldraw, a wcześniej go nie znałem.

Nie no rewelka, brzmi super ten morphing i funkcja pianinko z wykresem też bardzo mi się podoba :)
« Ostatnia zmiana: Sierpień 07, 2013, 00:24:27 wysłana przez komorra »

Offline Xender

  • Użytkownik

# Sierpień 07, 2013, 00:25:30
EvalDraw
<offtop>Dzięki! Szukałem tego z rok, po tym, jak kiedyś zobaczyłem i zapomniałem nazwy. Jak wyszukałem nazwę, to się okazało, że widziałem kiedyś na blogu Regedita.