160 lines · 3.1 KB · Text
RawDownload
#+TITLE: phsclk* Overview=phsclk= is a utility that converts an incoming phasorsignal into a clock signal that will tick N times in onecycle. Using a phasor signal to generate a clock signal has theadvantage of arbitrarily subdiving a beat. If the phasor isthe master clock, parallel sequences can be subidvided indifferent ways while also remaining relatively in sync.There is no chance of accumulative drift. This algorithm is minimally stateful, only requiring memoryof the previous sample to work. A tick is registered when the phasor crosses a certainthreshold. Both the previous and current phasor signals arescaled by the subdivision amount, then floored. If they aredifferent, a tick is registered.* Generated Files=phsclk.c= and =phsclk.h= are the generated files. #+NAME: phsclk.c#+BEGIN_SRC c :tangle phsclk.c#include <math.h>#define SK_PHSCLK_PRIV#include "phsclk.h"<<funcs>>#+END_SRC #+NAME: phsclk.h#+BEGIN_SRC c :tangle phsclk.h#ifndef PHSCLK_H#define PHSCLK_H #ifndef SKFLT#define SKFLT float#endif <<typedefs>><<funcdefs>> #ifdef SK_PHSCLK_PRIV<<structs>>#endif #endif#+END_SRC* StructsThe state data is encapsulated in a struct called=sk_phsclk=. #+NAME: typedefs#+BEGIN_SRC ctypedef struct sk_phsclk sk_phsclk;#+END_SRC #+NAME: structs#+BEGIN_SRC cstruct sk_phsclk {    <<sk_phsclk>>};#+END_SRC #+NAME: sk_phsclk#+BEGIN_SRC cSKFLT prev;#+END_SRC #+NAME: init#+BEGIN_SRC cpc->prev = -1;#+END_SRC* Initphsclk is initialized with =sk_phsclk_init=. #+NAME: funcdefs#+BEGIN_SRC cvoid sk_phsclk_init(sk_phsclk *pc);#+END_SRC #+NAME: funcs#+BEGIN_SRC cvoid sk_phsclk_init(sk_phsclk *pc){    <<init>>}#+END_SRC* Setting Number of TicksThe number of ticks is set with the function=sk_phsclk_nticks=. #+NAME: funcdefs#+BEGIN_SRC cvoid sk_phsclk_nticks(sk_phsclk *pc, SKFLT nticks);#+END_SRC #+NAME: funcs#+BEGIN_SRC cvoid sk_phsclk_nticks(sk_phsclk *pc, SKFLT nticks){    pc->nticks = nticks;}#+END_SRC #+NAME: sk_phsclk#+BEGIN_SRC cSKFLT nticks;#+END_SRC 4 is a sensible starting value. Western music lovesmultiples of 4 and 8. #+NAME: init#+BEGIN_SRC csk_phsclk_nticks(pc, 4);#+END_SRC* ComputationThe function =sk_phsclk_tick= computes a single sample ofaudio from an input signal =in=. #+NAME: funcdefs#+BEGIN_SRC cSKFLT sk_phsclk_tick(sk_phsclk *pc, SKFLT in);#+END_SRC The algorithm for phsclk is quite simple: scale and floorthe previous and current input phasor signals, and ifthere is a difference, make a tick. =floor= will almost always truncate the decimal, and willalmost always ensure that the value is between 0 and=nticks - 1=. The exception to this is when =in= is exactly1. This can somes cause extra ticks to happen, so aconditional is added to avoid this. #+NAME: funcs#+BEGIN_SRC cSKFLT sk_phsclk_tick(sk_phsclk *pc, SKFLT in){    SKFLT out;    out = 0;     if (in < 1) {        int i, pi;        SKFLT s, ps;        s = in * pc->nticks;        ps = pc->prev * pc->nticks;         i = floor(s);        pi = floor(ps);         if (i != pi) out = 1;    }     pc->prev = in;     return out;}#+END_SRC

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t