04.11.2014 Views

Plugin Interface for (Afferent Stream) Processing Objects - IMTR

Plugin Interface for (Afferent Stream) Processing Objects - IMTR

Plugin Interface for (Afferent Stream) Processing Objects - IMTR

SHOW MORE
SHOW LESS

Transform your PDFs into Flipbooks and boost your revenue!

Leverage SEO-optimized Flipbooks, powerful backlinks, and multimedia content to professionally showcase your products and significantly increase your reach.

PiPo<br />

<strong>Plugin</strong> <strong>Interface</strong> <strong>for</strong> (<strong>Afferent</strong> <strong>Stream</strong>) <strong>Processing</strong> <strong>Objects</strong><br />

Norbert Schnell<br />

<strong>IMTR</strong>, Real-Time Musical Interactions<br />

IRCAM – Centre Pompidou<br />

03/04/2013<br />

1


Context<br />

Experimentation and Prototyping<br />

•<br />

•<br />

We don’t know exactly what we are doing<br />

We need everything ready-at-hand<br />

... in and off Max (MuBu <strong>for</strong> Max, IAE on iOS)<br />

•<br />

We have a lot of code to plug-in<br />

... and the simpler the better.<br />

2


Context<br />

Interactive Audio Systems<br />

per<strong>for</strong>mer<br />

listener<br />

user<br />

interface<br />

sensor<br />

data<br />

streams<br />

?<br />

computer<br />

sound<br />

streams<br />

3


Context<br />

Interactive Audio Systems<br />

our daily<br />

sensor<br />

data<br />

streams<br />

?<br />

sound<br />

streams<br />

4


Context<br />

Interactive Audio Systems<br />

sensor<br />

data<br />

streams<br />

extraction,<br />

filtering,<br />

segmentation,<br />

etc.<br />

action and sound<br />

analysis<br />

synthesis<br />

learning<br />

planning<br />

mixing,<br />

effects,<br />

spatialization,<br />

etc.<br />

sound<br />

streams<br />

5


Context<br />

Interactive Audio Systems<br />

sensor<br />

data<br />

streams<br />

afferent<br />

stream<br />

processing<br />

action and sound<br />

analysis<br />

synthesis<br />

learning<br />

planning<br />

efferent<br />

mixing,<br />

effects,<br />

spatialization, stream<br />

etc.<br />

processing<br />

sound<br />

streams<br />

⎧ ⎜⎟⎢⎥⎪⎨⎜⎟⎢⎥⎪⎩<br />

⎧<br />

⎜⎟⎢⎥⎪⎜⎟⎢⎥⎪⎜⎟⎢⎥⎪⎜⎟⎢⎥⎪<br />

<br />

⎜⎟⎢⎥⎪<br />

⎨⎜⎟⎢⎥⎪⎜⎟⎢⎥⎪⎜⎟⎢⎥⎪⎜⎟⎢⎥⎪⎜⎟⎢⎥⎪⎩<br />

VAMP plugins<br />

FEAPI<br />

VST plugins<br />

AudioUnits<br />

etc. etc.<br />

6


audio and<br />

motion input<br />

Context<br />

<strong>IMTR</strong> Audio Engine (IAE)<br />

stream<br />

processing<br />

filtering<br />

segmentation<br />

extraction<br />

visualization,<br />

editing, control<br />

MuBu <strong>for</strong> Max<br />

interaction<br />

models<br />

k-NN<br />

follower<br />

...<br />

MuBu data<br />

container<br />

audio files<br />

audio descriptors<br />

segmentations<br />

musical descriptions<br />

stream<br />

processing<br />

filtering<br />

segmentation<br />

extraction<br />

<br />

description files <br />

audio and<br />

motion data files<br />

<br />

audio files<br />

SDIF files<br />

text files<br />

MIDI standard files<br />

MusicXML files<br />

real-time audio rendering<br />

concatenative synthesis<br />

granular synthesis<br />

+ additive synthesis<br />

audio output<br />

7


audio and<br />

motion input<br />

Context<br />

<strong>IMTR</strong> Audio Engine (IAE)<br />

classical real-time streams<br />

real-time random access<br />

stream<br />

processing<br />

filtering<br />

segmentation<br />

extraction<br />

interaction<br />

models<br />

k-NN<br />

follower<br />

...<br />

real-time audio rendering<br />

concatenative synthesis<br />

granular synthesis<br />

+ additive synthesis<br />

visualization,<br />

editing, control<br />

MuBu<br />

container<br />

audio files<br />

audio descriptors<br />

segmentations<br />

musical descriptions<br />

asynchronous (random) access<br />

stream<br />

processing<br />

filtering<br />

segmentation<br />

extraction<br />

description files<br />

MuBu <strong>for</strong> Max<br />

audio and<br />

motion data files<br />

audio files<br />

SDIF files<br />

text files<br />

MIDI standard files<br />

<br />

MusicXML files<br />

audio output<br />

8


Summary<br />

<strong>Afferent</strong> <strong>Stream</strong>s<br />

• Real-Time and offline processing<br />

• Synchronous and asynchronous processing<br />

• Multi-dimensional / -modal / -<strong>for</strong>mat<br />

• Data conditioning, reduction, annotation<br />

- filtering<br />

- extraction<br />

- segmentation<br />

- temporal modeling<br />

- classification<br />

9


What is PiPo?<br />

• Very compact <strong>for</strong>malization of streams<br />

• Module API (C++)<br />

• Experimental host integration (Max and IAE)<br />

• First set of modules<br />

• First applications (MuBu <strong>for</strong> Max, VoiceFollower, iOS proto)<br />

10


PiPo Constraints and Motivations<br />

• Extremely simple framework (in a single .h !!!)<br />

• Easily integrate modules into applications<br />

• Easily reuse code (cf. openFrameworks)<br />

• Inhomogeneous module size and granularity<br />

- elementary (e.g. slice, fft, bands, dct, scale, sum)<br />

- compact (e.g. mel, mfcc, loudseg)<br />

- integrated (i.e. extract + filter + segment + temporal modeling + classify)<br />

• Integrate existing code (FTM & Co., MnM, etc.)<br />

11


PiPo Formalization (roughly SDIF inspired)<br />

• Chain or graph of modules<br />

• One in, one out, multiple branches<br />

• Two mutually exclusive phases of streaming<br />

1. (setup stream): propagate stream attributes<br />

2. (real-time processing): propagate frames<br />

• <strong>Stream</strong> attributes<br />

- stream timing (time-tagged, sample rate and offset, ...)<br />

- frame dimensions (scalars/vectors/2dim-matrices, ...)<br />

• Module attributes (real-time or require setup)<br />

12


PiPo Implementation<br />

PiPo.h<br />

class PiPo<br />

{<br />

private:<br />

std::list receivers; /**< list of receivers */<br />

std::vector attrs; /**< list of attributes */<br />

public:<br />

PiPo(PiPo *receiver = NULL);<br />

~PiPo(void);<br />

// make connections<br />

virtual void setReceiver(PiPo *receiver, bool add = false);<br />

// setup module and propagate stream attributes<br />

virtual int streamAttributes(bool hasTimeTags, double rate, double offset,<br />

unsigned int width, unsigned int size,<br />

const char **labels, bool hasVarSize,<br />

double domain, unsigned int maxFrames);<br />

// signal stream attributes changed<br />

virtual int streamAttributesChanged(unsigned int unitId = 0);<br />

// reset streaming, propagate frames, finalize streaming<br />

virtual int reset(void);<br />

virtual int frames(double time, double weight, PiPoValue *values, unsigned int size, unsigned int num);<br />

virtual int finalize(double inputEnd);<br />

...<br />

// attribute base class, template, and specializations<br />

13


PiPo Module PiPoScale<br />

#include "PiPo.h"<br />

class PiPoScale : public PiPo<br />

{<br />

private:<br />

... // internal stuff<br />

public:<br />

enum ScaleFun { ScaleLin, ScaleLog, ScaleExp };<br />

PiPoVarSizeAttr inMin;<br />

PiPoVarSizeAttr inMax;<br />

PiPoVarSizeAttr outMin;<br />

PiPoVarSizeAttr outMax;<br />

PiPoScalarAttr clip;<br />

PiPoScalarAttr func;<br />

PiPoScalarAttr base;<br />

PiPoScale(PiPo *receiver = NULL) :<br />

PiPo(receiver),<br />

inMin(this, "inmin", "Input Minimum", true),<br />

inMax(this, "inmax", "Input Maximum", true),<br />

outMin(this, "outmin", "Output Minimum", true),<br />

outMax(this, "outmax", "Output Maximum", true),<br />

clip(this, "clip", "Clip Values", false, false),<br />

func(this, "func", "Scaling Function", true, ScaleLin),<br />

base(this, "base", "Scaling Base", true, 1.0),<br />

...<br />

{<br />

...<br />

module attribute declaration<br />

module attribute instantiation<br />

}<br />

this->func.addEnumItem("lin", "Linear scaling");<br />

this->func.addEnumItem("log", "Logarithmic scaling");<br />

this->func.addEnumItem("exp", "Exponential scaling");<br />

func attribute enum declaration<br />

14


PiPo Module PiPoOnseg<br />

#include "PiPo.h"<br />

class PiPoOnseg : public PiPo<br />

{<br />

private:<br />

... // internal stuff<br />

public:<br />

PiPoScalarAttr fltsize;<br />

PiPoScalarAttr threshold;<br />

PiPoScalarAttr mininter;<br />

module attribute declaration<br />

PiPoOnseg(PiPo *receiver = NULL) :<br />

PiPo(receiver),<br />

fltsize(this, "filtersize", "Onset Filter Size", true, 3),<br />

threshold(this, "threshold", "Onset Threshold", false, 5),<br />

mininter(this, "mininter", "Minimum Onset Interval", false, 50.0)<br />

{<br />

...<br />

}<br />

module attribute instantiation<br />

15


Propagate <strong>Stream</strong> Attributes<br />

int PiPoOnseg::streamAttributes(bool hasTimeTags, double rate, double offset,<br />

unsigned int width, unsigned int size, const char **labels, bool hasVarSize,<br />

double domain, unsigned int maxFrames)<br />

{<br />

unsigned int filterSize = this->fltsize.get();<br />

unsigned int inputSize = width * size;<br />

this->offset = -1000.0 / rate; // we are one frame off<br />

if(filterSize < 1)<br />

filterSize = 1;<br />

if(filterSize != this->filterSize || inputSize != this->inputSize)<br />

{<br />

// configure internal state<br />

this->buffer.resize(inputSize, filterSize);<br />

this->temp.resize(inputSize * filterSize);<br />

this->lastFrame.resize(inputSize);<br />

}<br />

this->filterSize = filterSize;<br />

this->inputSize = inputSize;<br />

}<br />

return propagate<strong>Stream</strong>Attributes(true, rate, 0.0, 1, 1, NULL, false, 0.0, 1);<br />

stream attribute propagation<br />

16


Propagate Frames<br />

int PiPoOnseg::frames(double time, double weight, PiPoValue *values, unsigned int size, unsigned int num)<br />

{<br />

double onsetThreshold = this->threshold.get();<br />

double minimumInterval = this->mininter.get();<br />

<strong>for</strong>(unsigned int i = 0; i < num; i++) // iterate over input frames<br />

{<br />

PiPoValue onset;<br />

bool isOnset = frameIsOnset(values, size, onsetThreshold, minimumInterval, onset);<br />

if(isOnset && !this->lastWasOnset && time >= this->lastOnsetTime + minimumInterval)<br />

{<br />

// we have an onset here<br />

int ret = propagateFrames(this->offset + time, weight, &onset, 1, 1); // propagate output frames<br />

if(ret != 0)<br />

return ret;<br />

}<br />

this->lastOnsetTime = time;<br />

this->lastWasOnset = onset;<br />

}<br />

values += size;<br />

}<br />

return 0;<br />

17


Reset and Finalize <strong>Stream</strong>ing<br />

int PiPoOnseg::reset(void) // reset module be<strong>for</strong>e streaming<br />

{<br />

this->buffer.reset();<br />

this->lastWasOnset = false;<br />

this->lastOnsetTime = -DBL_MAX;<br />

return propagateReset();<br />

};<br />

int PiPoOnseg::finalize(double inputEnd) // finalize stream at end (if any)<br />

{<br />

return propagateFinalize(inputEnd);<br />

}<br />

18


PiPoMel.h<br />

Compose PiPo Modules<br />

#include "PiPoSlice.h"<br />

#include "PiPoFft.h"<br />

#include "PiPoBands.h"<br />

class PiPoMel: public PiPoSlice // inherit first PiPo in the chain (mel = slice + fft + bands)<br />

{<br />

private:<br />

PiPoFft fft; // internal PiPo (2nd in chain)<br />

PiPoBands bands; // internal PiPo (3rd in chain)<br />

public:<br />

PiPoMel(PiPo *receiver = NULL) :<br />

PiPoSlice(&this->fft), // instantiate 1st and connect to 2nd<br />

fft(&this->bands), // instantiate 2nd and connect to 3rd<br />

bands(receiver) // instantiate 3rd and connect to receiver<br />

{<br />

// steal attributes from internal PiPos<br />

this->addAttr(this, "windsize", "FFT Window Size", &this->size, true);<br />

this->addAttr(this, "hopsize", "FFT Hop Size", &this->hop);<br />

this->addAttr(this, "numbands", "Number Of Bands", &this->bands.num);<br />

this->addAttr(this, "log", "Logarithmic Scale Output", &this->bands.log);<br />

}<br />

// set internal PiPo attributes<br />

this->wind.set(PiPoSlice::BlackmanWindow);<br />

this->norm.set(PiPoSlice::PowerNorm);<br />

this->fft.mode.set(PiPoFft::PowerFft);<br />

this->bands.mode.set(PiPoBands::MelBands);<br />

this->bands.log.set(false);<br />

// overload set receiver to connect to last PiPo (bands)<br />

void setReceiver(PiPo *receiver, bool add) { this->bands.setReceiver(receiver, add); };<br />

};<br />

19


Max <strong>Plugin</strong>s (Externals)<br />

#include "PiPoScale.h"<br />

#include "MaxPiPo.h"<br />

// generate pipo.scale (“NOBOX”) Max external<br />

PIPO_MAX_CLASS("scale", PiPoScale);<br />

#include "PiPoMel.h"<br />

#include "MaxPiPo.h"<br />

// generate pipo.mel (“NOBOX”) Max external<br />

PIPO_MAX_CLASS("mel", PiPoMel);<br />

20


Available PiPo Hosts (3/4/2013)<br />

• Max externals pipo and pipo~<br />

• Max external mubu.process (MuBu <strong>for</strong> Max)<br />

• IAE method applyPiPo() (Max, Unity 3D, iOS proto)<br />

21


Available PiPo Modules (3/4/2013)<br />

• psy ... pitch synchronous yin<br />

• mvavrg, median, biquad ... simple filters<br />

• scale, sum ... misc modules<br />

• slice, fft, bands, dct ... spectral description building blocks<br />

• mel, mfcc ... spectral description<br />

• onseg ... onset detector (yet to be released)<br />

• ircamdescriptor ... similar to ircamdescriptor~ (yet to be released) 22


Pi... Po... Perspectives (3/4/2013)<br />

• More modules<br />

• Integration of temporal modeling<br />

• Consolidate API<br />

• Share PiPo framework<br />

• Share PiPo modules<br />

23


http://imtr.ircam.fr/imtr/PiPo<br />

24

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!