Plugin Interface for (Afferent Stream) Processing Objects - IMTR
Plugin Interface for (Afferent Stream) Processing Objects - IMTR
Plugin Interface for (Afferent Stream) Processing Objects - IMTR
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