generic-step-sequencer

A purpose-agnostic step sequencer implementation

Installation

$ yarn add generic-step-sequencer

Usage

see https://github.com/youpy/generic-step-sequencer/blob/main/examples/basic/index.ts

implement a step executor

import {
  StepExecutor,
  Sequencer,
  State,
  PeriodicTicker,
  backward,
} from "generic-step-sequencer";

interface MyParameter {
  foo: string;
}

class MyStepExecutor implements StepExecutor<MyParameter> {
  execute(track: Track<MyParameter>): void {
    console.log(
      `executing step ${track.currentStep} on ${track.parameters.foo}`
    );
  }
}

create and start a sequencer

const sequencer = new Sequencer<MyParameter, MyStepExecutor>(
  new MyStepExecutor()
);
const ticker = new PeriodicTicker(sequencer);

sequencer.addTrack({ foo: "track1" }, 8, [0, 2, 4, 6]);
sequencer.addTrack({ foo: "track2" }, 8, [1, 3, 5, 7]);
ticker.bpm = 250;
ticker.start();

set step direction

// backward
sequencer.setNextStepStrategy(backward);

// random
const random = <T>(track: Track<T>): number => {
  return Math.floor(Math.random() * track.numberOfSteps);
};
sequencer.setNextStepStrategy(random);

Use with React

type Props = {
  seq: Sequencer<MyParameter, MyStepExecutor>;
  ticker: PeriodicTicker;
};

funcion App(props: Props) {
  const { seq, ticker } = props
  const [seqState, setSeqState] = useState<State<MyParameter>>({
    tracks: [],
  });

  useEffect(() => {
    seq.onStateChange(setSeqState);
    ticker.start()
  });

  // construct view from seqState
  return ...
}

Use custom timer

You can replace the default timer with a custom timer implementation that implements the Timer interface

const ticker = new PeriodicTicker(sequencer, new MyTimer());