mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
Added sound library
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
*.o
|
||||
*.class
|
||||
.DS_Store
|
||||
/distribution
|
||||
/bin
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0"?>
|
||||
<project name="Processing Serial Library" default="build">
|
||||
|
||||
<target name="clean" description="Clean the build directories">
|
||||
<delete dir="bin" />
|
||||
<delete file="library/sound.jar" />
|
||||
</target>
|
||||
|
||||
<target name="compile" description="Compile sources">
|
||||
<condition property="core-built">
|
||||
<available file="../../../core/library/core.jar" />
|
||||
</condition>
|
||||
<fail unless="core-built" message="Please build the core library first and make sure it sits in ../../../core/library/core.jar" />
|
||||
|
||||
<mkdir dir="bin" />
|
||||
<javac source="1.6"
|
||||
target="1.6"
|
||||
srcdir="src" destdir="bin"
|
||||
encoding="UTF-8"
|
||||
includeAntRuntime="false"
|
||||
classpath="../../../core/library/core.jar; library/sound.jar"
|
||||
nowarn="true"
|
||||
compiler="org.eclipse.jdt.core.JDTCompilerAdapter">
|
||||
<compilerclasspath path="../../mode/ecj.jar" />
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<target name="build" depends="compile" description="Build sound library">
|
||||
<jar basedir="bin" destfile="library/sound.jar" />
|
||||
</target>
|
||||
</project>
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
This example shows how to use the RMS amplitude tracker. The tracker
|
||||
calculates the Root Mean Square over a block of audio and returns
|
||||
the mean as a float between 0 and 1.
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
SoundFile sample;
|
||||
Amplitude rms;
|
||||
|
||||
int scale=1;
|
||||
|
||||
public void setup() {
|
||||
size(350,350);
|
||||
|
||||
// Create and start the sound renderer
|
||||
stream = new Sound(this, 44100, 512);
|
||||
|
||||
//Load and play a soundfile and loop it
|
||||
sample = new SoundFile(this, "beat.aiff");
|
||||
sample.loop();
|
||||
|
||||
// Create and patch the rms tracker
|
||||
rms = new Amplitude(this);
|
||||
rms.input(sample);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
background(125,255,125);
|
||||
|
||||
// rms.process() return a value between 0 and 1. To adjust
|
||||
// the scaling and mapping of an ellipse we scale from 0 to 0.5
|
||||
scale=int(map(rms.process(), 0, 0.5, 1, 350));
|
||||
noStroke();
|
||||
|
||||
fill(255,0,150);
|
||||
// We draw an ellispe coupled to the audio analysis
|
||||
ellipse(width/2, height/2, 1*scale, 1*scale);
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
This example shows how to use the Fast Fourier Transform function to get the spectrum
|
||||
of a sound. This function calculates the FFT of a signal and returns the positive normalized
|
||||
magnitude spectrum. This means we pass it the number of bands we want (the actual FFT size is
|
||||
two times that size) and a float array with the same size.
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
SoundFile sample;
|
||||
FFT fft;
|
||||
|
||||
int scale=1;
|
||||
int bands=512;
|
||||
float[] spec = new float[bands];
|
||||
|
||||
public void setup() {
|
||||
size(bands,350);
|
||||
background(255);
|
||||
|
||||
// Create and start the sound renderer
|
||||
stream = new Sound(this, 44100, 256);
|
||||
|
||||
//Load and play a soundfile and loop it. This has to be called
|
||||
// before the FFT is created.
|
||||
sample = new SoundFile(this, "beat.aiff");
|
||||
sample.loop();
|
||||
|
||||
// Create and patch the rms tracker
|
||||
fft = new FFT(this);
|
||||
fft.input(sample, bands);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
background(255);
|
||||
|
||||
fft.process(spec);
|
||||
|
||||
for(int i = 0; i < bands; i++)
|
||||
{
|
||||
// The result of the FFT is normalized
|
||||
// draw the line for frequency band i scaling it up by 5 to get more amplitude.
|
||||
line( i, height, i, height - spec[i]*height*5 );
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
This is a simple WhiteNoise generator. It can be started with .play(float amp).
|
||||
In this example it is started and stopped by clicking into the renderer window.
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
WhiteNoise noise;
|
||||
BPF bandPass;
|
||||
|
||||
float amp=0.0;
|
||||
|
||||
void setup() {
|
||||
size(350,350);
|
||||
background(255);
|
||||
|
||||
// Create and start the sound renderer and the noise generator
|
||||
stream = new Sound(this);
|
||||
noise = new WhiteNoise(this);
|
||||
bandPass = new BPF(this);
|
||||
noise.play(0.5);
|
||||
bandPass.play(noise, 100);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
|
||||
bandPass.freq(map(mouseX, 0, 350, 20, 10000));
|
||||
|
||||
bandPass.res(map(mouseY, 0, 350, 0.05, 1.0));
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
This is a simple WhiteNoise generator. It can be started with .play(float amp).
|
||||
In this example it is started and stopped by clicking into the renderer window.
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
WhiteNoise noise;
|
||||
HPF highPass;
|
||||
|
||||
float amp=0.0;
|
||||
|
||||
void setup() {
|
||||
size(350,350);
|
||||
background(255);
|
||||
|
||||
// Create and start the sound renderer and the noise generator
|
||||
stream = new Sound(this);
|
||||
noise = new WhiteNoise(this);
|
||||
highPass = new HPF(this);
|
||||
noise.play(0.5);
|
||||
highPass.play(noise, 100);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
|
||||
highPass.freq(map(mouseX, 0, 350, 20, 10000));
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
This is a simple WhiteNoise generator. It can be started with .play(float amp).
|
||||
In this example it is started and stopped by clicking into the renderer window.
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
WhiteNoise noise;
|
||||
LPF lowPass;
|
||||
|
||||
|
||||
float amp=0.0;
|
||||
|
||||
void setup() {
|
||||
size(350,350);
|
||||
background(255);
|
||||
|
||||
// Create and start the sound renderer and the noise generator
|
||||
stream = new Sound(this);
|
||||
noise = new WhiteNoise(this);
|
||||
lowPass = new LPF(this);
|
||||
noise.play(0.5);
|
||||
lowPass.play(noise, 100);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
|
||||
lowPass.freq(map(mouseX, 0, 350, 20, 10000));
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
This is a sound file player.
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
SoundFile soundfile;
|
||||
Delay delay;
|
||||
|
||||
void setup() {
|
||||
size(350,350);
|
||||
background(255);
|
||||
|
||||
// Create and start the sound renderer
|
||||
stream = new Sound(this);
|
||||
|
||||
//Load a soundfile
|
||||
soundfile = new SoundFile(this, "vibraphon.aiff");
|
||||
|
||||
// create a Delay Effect
|
||||
delay = new Delay(this);
|
||||
|
||||
// These methods return useful infos about the file
|
||||
println("SFSampleRate= " + soundfile.sampleRate() + " Hz");
|
||||
println("SFSamples= " + soundfile.frames() + " samples");
|
||||
println("SFDuration= " + soundfile.duration() + " seconds");
|
||||
|
||||
// Play the file in a loop
|
||||
soundfile.loop();
|
||||
|
||||
// Patch the delay
|
||||
delay.play(soundfile, 5);
|
||||
}
|
||||
|
||||
|
||||
void draw() {
|
||||
// Map mouseX from 0.25 to 4.0 for playback rate. 1 equals original playback
|
||||
// speed 2 is an octave up 0.5 is an octave down.
|
||||
soundfile.rate(map(mouseX, 0, 350, 0.25, 4.0));
|
||||
|
||||
// Map mouseY from 0.2 to 1.0 for amplitude
|
||||
soundfile.amp(map(mouseY, 0, 350, 0.2, 1.0));
|
||||
|
||||
// Map mouseY from -1.0 to 1.0 for left to right
|
||||
soundfile.pan(map(mouseY, 0, 350, -1.0, 1.0));
|
||||
|
||||
// Map mouseY from 0.001 to 2.0 seconds for the delaytime
|
||||
delay.time(map(mouseY, 0, 350, 0.001, 2.0));
|
||||
|
||||
// Map mouseX from 0 to 0.8 for the delay feedback
|
||||
delay.feedback(map(mouseX, 0, 350, 0.0, 0.8));
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
This example shows how to make a simple sampler and sequencer with the Sound library. In this
|
||||
sketch 5 different short samples are loaded and played back at different pitches, in this
|
||||
case 5 different octaves. The sequencer triggers and event every 200-1000 mSecs randomly.
|
||||
Each time a sound is played a colored rect with a random color is displayed.
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
SoundFile[] file;
|
||||
|
||||
// Define the number of samples
|
||||
int numsounds = 5;
|
||||
|
||||
int value[] = {0,0,0};
|
||||
|
||||
|
||||
void setup(){
|
||||
size(500, 500);
|
||||
background(255);
|
||||
|
||||
// Create a Sound renderer and an array of empty soundfiles
|
||||
stream = new Sound(this, 44100, 32);
|
||||
file = new SoundFile[numsounds];
|
||||
|
||||
// Load 5 soundfiles from a folder in a for loop. By naming the files 1., 2., 3., n.aif it is easy to iterate
|
||||
// through the folder and load all files in one line of code.
|
||||
for (int i = 0; i < numsounds; i++){
|
||||
file[i] = new SoundFile(this, (i+1) + ".aif");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void draw(){
|
||||
|
||||
background(value[0],value[1],value[2]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void keyPressed() {
|
||||
for (int i=0; i < 3; i++) {
|
||||
value[i]=int(random(255));
|
||||
};
|
||||
|
||||
|
||||
switch(key){
|
||||
case 'a':
|
||||
file[0].play(0.5, 1.0);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
file[1].play(0.5, 1.0);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
file[2].play(0.5, 1.0);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
file[3].play(0.5, 1.0);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
file[4].play(0.5, 1.0);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
file[0].play(1.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
file[1].play(1.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
file[2].play(1.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
file[3].play(1.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'ö':
|
||||
file[4].play(1.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'ä':
|
||||
file[0].play(2.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
file[1].play(2.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
file[2].play(2.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
file[3].play(2.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
file[4].play(2.0, 1.0);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
file[0].play(3.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
file[1].play(3.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
file[2].play(3.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
file[3].play(3.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
file[4].play(3.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
file[0].play(4.0, 1.0);
|
||||
break;
|
||||
|
||||
case 'ü':
|
||||
file[1].play(4.0, 1.0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
This is a simple WhiteNoise generator. It can be started with .play(float amp).
|
||||
In this example it is started and stopped by clicking into the renderer window.
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
WhiteNoise noise;
|
||||
|
||||
float amp=0.0;
|
||||
|
||||
void setup() {
|
||||
size(350,350);
|
||||
background(255);
|
||||
|
||||
// Create and start the sound renderer and the noise generator
|
||||
stream = new Sound(this);
|
||||
noise = new WhiteNoise(this);
|
||||
noise.play();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
// Map mouseX from 0.0 to 1.0 for amplitude
|
||||
noise.amp(map(mouseX, 0, 350, 0.0, 1.0));
|
||||
|
||||
// Map mouseY from -1.0 to 1.0 for left to right
|
||||
noise.pan(map(mouseY, 0, 350, -1.0, 1.0));
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
This is a pulse-wave oscillator. The method .play() starts the oscillator.
|
||||
There are several setters like .amp(), .freq(), .width(), .pan() and .add().
|
||||
If you want to set all of them at the same time use
|
||||
.set(float freq, float width, float amp, float add, float pan)
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
Pulse pulse;
|
||||
|
||||
void setup() {
|
||||
size(350,350);
|
||||
background(255);
|
||||
|
||||
// Create and start the sound renderer and the pulse wave oscillator
|
||||
stream = new Sound(this);
|
||||
pulse = new Pulse(this);
|
||||
pulse.play();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
// Map mouseX from 20Hz to 500Hz for frequency
|
||||
pulse.freq(map(mouseX, 0, width, 20.0, 500.0));
|
||||
// Map mouseX from 0.0 to 0.5 for amplitude
|
||||
pulse.pan(map(mouseX, 0, width, -1.0, 1.0));
|
||||
// Map mouseY from 0.0 to 0.5 for amplitude
|
||||
pulse.amp(map(mouseY, 0, height, 0.0, 0.5));
|
||||
// Map mouseY from 0.0 to 0.5 for amplitude
|
||||
pulse.width(map(mouseY, 0, height, 0.0, 1.0));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
This is a saw-wave oscillator. The method .play() starts the oscillator. There
|
||||
are several setters like .amp(), .freq(), .pan() and .add(). If you want to set all of them at
|
||||
the same time use .set(float freq, float amp, float add, float pan)
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
SawOsc saw;
|
||||
|
||||
void setup() {
|
||||
size(350,350);
|
||||
background(255);
|
||||
|
||||
// Create and start the sound renderer and the sine oscillator.
|
||||
// Second and Third arguments are optional, default is 44100 / 512
|
||||
// for Sample Rate and Buffer Size
|
||||
stream = new Sound(this, 44100, 256);
|
||||
saw = new SawOsc(this);
|
||||
|
||||
//Start the Sine Oscillator. There will be no sound in the beginning
|
||||
//unless the mouse enters the
|
||||
saw.play();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
// Map mouseY from 0.0 to 1.0 for amplitude
|
||||
saw.amp(map(mouseY, 0, height, 1.0, 0.0));
|
||||
|
||||
// Map mouseX from 20Hz to 1000Hz for frequency
|
||||
saw.freq(map(mouseX, 0, width, 80.0, 200.0));
|
||||
|
||||
// Map mouseX from -1.0 to 1.0 for left to right
|
||||
saw.pan(map(mouseX, 0, width, -1.0, 1.0));
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
This is a sine-wave oscillator. The method .play() starts the oscillator. There
|
||||
are several setters like .amp(), .freq(), .pan() and .add(). If you want to set all of them at
|
||||
the same time use .set(float freq, float amp, float add, float pan)
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
SinOsc sine;
|
||||
|
||||
float freq=400;
|
||||
float amp=0.5;
|
||||
float pos;
|
||||
|
||||
void setup() {
|
||||
size(350,350);
|
||||
background(255);
|
||||
|
||||
// Create and start the sound renderer and the sine oscillator.
|
||||
// Second and Third arguments are optional, default is 44100 / 512
|
||||
// for Sample Rate and Buffer Size
|
||||
stream = new Sound(this, 44100, 256);
|
||||
sine = new SinOsc(this);
|
||||
|
||||
//Start the Sine Oscillator.
|
||||
sine.play();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
|
||||
// Map mouseY from 0.0 to 1.0 for amplitude
|
||||
amp=map(mouseY, 0, height, 1.0, 0.0);
|
||||
sine.amp(amp);
|
||||
|
||||
// Map mouseX from 20Hz to 1000Hz for frequency
|
||||
freq=map(mouseX, 0, width, 80.0, 1000.0);
|
||||
sine.freq(freq);
|
||||
|
||||
// Map mouseX from -1.0 to 1.0 for left to right
|
||||
pos=map(mouseX, 0, width, -1.0, 1.0);
|
||||
sine.pan(pos);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
This is a saw-wave oscillator. The method .play() starts the oscillator. There
|
||||
are several setters like .amp(), .freq(), .pan() and .add(). If you want to set all of them at
|
||||
the same time use .set(float freq, float amp, float add, float pan)
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
SqrOsc sqr;
|
||||
|
||||
void setup() {
|
||||
size(350,350);
|
||||
background(255);
|
||||
|
||||
// Create and start the sound renderer and the sine oscillator.
|
||||
// Second and Third arguments are optional, default is 44100 / 512
|
||||
// for Sample Rate and Buffer Size
|
||||
stream = new Sound(this, 44100, 256);
|
||||
sqr = new SqrOsc(this);
|
||||
|
||||
//Start the Sine Oscillator. There will be no sound in the beginning
|
||||
//unless the mouse enters the
|
||||
sqr.play();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
// Map mouseY from 0.0 to 1.0 for amplitude
|
||||
sqr.amp(map(mouseY, 0, height, 1.0, 0.0));
|
||||
|
||||
// Map mouseX from 20Hz to 1000Hz for frequency
|
||||
sqr.freq(map(mouseX, 0, width, 80.0, 200.0));
|
||||
|
||||
// Map mouseX from -1.0 to 1.0 for left to right
|
||||
sqr.pan(map(mouseX, 0, width, -1.0, 1.0));
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
This is a saw-wave oscillator. The method .play() starts the oscillator. There
|
||||
are several setters like .amp(), .freq(), .pan() and .add(). If you want to set all of them at
|
||||
the same time use .set(float freq, float amp, float add, float pan)
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
TriOsc tri;
|
||||
|
||||
void setup() {
|
||||
size(350,350);
|
||||
background(255);
|
||||
|
||||
// Create and start the sound renderer and the sine oscillator.
|
||||
// Second and Third arguments are optional, default is 44100 / 512
|
||||
// for Sample Rate and Buffer Size
|
||||
stream = new Sound(this, 44100, 256);
|
||||
tri = new TriOsc(this);
|
||||
|
||||
//Start the Sine Oscillator. There will be no sound in the beginning
|
||||
//unless the mouse enters the
|
||||
tri.play();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
// Map mouseY from 0.0 to 1.0 for amplitude
|
||||
tri.amp(map(mouseY, 0, height, 1.0, 0.0));
|
||||
|
||||
// Map mouseX from 20Hz to 1000Hz for frequency
|
||||
tri.freq(map(mouseX, 0, width, 80.0, 1000.0));
|
||||
|
||||
// Map mouseX from -1.0 to 1.0 for left to right
|
||||
tri.pan(map(mouseX, 0, width, -1.0, 1.0));
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
This is a sound file player.
|
||||
*/
|
||||
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
SoundFile soundfile;
|
||||
|
||||
void setup() {
|
||||
size(350,350);
|
||||
background(255);
|
||||
|
||||
// Create and start the sound renderer
|
||||
stream = new Sound(this);
|
||||
|
||||
//Load a soundfile
|
||||
soundfile = new SoundFile(this, "vibraphon.aiff");
|
||||
|
||||
// These methods return useful infos about the file
|
||||
println("SFSampleRate= " + soundfile.sampleRate() + " Hz");
|
||||
println("SFSamples= " + soundfile.frames() + " samples");
|
||||
println("SFDuration= " + soundfile.duration() + " seconds");
|
||||
|
||||
// Play the file in a loop
|
||||
soundfile.loop();
|
||||
}
|
||||
|
||||
|
||||
void draw() {
|
||||
// Map mouseX from 0.25 to 4.0 for playback rate. 1 equals original playback
|
||||
// speed 2 is an octave up 0.5 is an octave down.
|
||||
soundfile.rate(map(mouseX, 0, 350, 0.25, 4.0));
|
||||
|
||||
// Map mouseY from 0.2 to 1.0 for amplitude
|
||||
soundfile.amp(map(mouseY, 0, 350, 0.2, 1.0));
|
||||
|
||||
// Map mouseY from -1.0 to 1.0 for left to right
|
||||
soundfile.pan(map(mouseY, 0, 350, -1.0, 1.0));
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
This example shows how to create a cluster of sine oscillators, change the frequency and detune them
|
||||
depending on the position of the mouse in the renderer window. The Y position determines the basic
|
||||
frequency of the oscillator and X the detuning of the oscillator. The basic frequncy ranges between
|
||||
150 and 1150 Hz.
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
SinOsc[] sineWaves;
|
||||
|
||||
// The number of oscillators
|
||||
int numSines = 5;
|
||||
|
||||
// A float for calculating the amplitudes
|
||||
float[] sineVolume;
|
||||
|
||||
void setup() {
|
||||
size(500, 500);
|
||||
background(255);
|
||||
|
||||
//Create and start the Sound renderer
|
||||
stream = new Sound(this);
|
||||
|
||||
// Create the oscillators and amplitudes
|
||||
sineWaves = new SinOsc[numSines];
|
||||
sineVolume = new float[numSines];
|
||||
|
||||
for (int i = 0; i < numSines; i++) {
|
||||
|
||||
// The overall amplitude shouldn't exceed 1.0 which is prevented by 1.0/numSines.
|
||||
// The ascending waves will get lower in volume the higher the frequency
|
||||
sineVolume[i] = (1.0 / numSines) / (i + 1);
|
||||
|
||||
// Create the Sine Oscillators and start them
|
||||
sineWaves[i] = new SinOsc(this);
|
||||
sineWaves[i].play();
|
||||
}
|
||||
}
|
||||
|
||||
void draw() {
|
||||
noStroke();
|
||||
|
||||
// Map mouseY to get values from 0.0 to 1.0
|
||||
float yoffset = (height - mouseY) / float(height);
|
||||
|
||||
// Map that value logarithmically to 150 - 1150 Hz
|
||||
float frequency = pow(1000, yoffset) + 150;
|
||||
|
||||
// Map mouseX from -0.5 to 0.5 to get a multiplier for detuning the oscillators
|
||||
float detune = float(mouseX) / width - 0.5;
|
||||
|
||||
// Set the frequencies, detuning and volume
|
||||
for (int i = 0; i < numSines; i++) {
|
||||
sineWaves[i].freq(frequency * (i + 1 + i * detune));
|
||||
sineWaves[i].amp(sineVolume[i]);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
This sketch shows how to use envelopes and oscillators. Envelopes are pre-defined amplitude
|
||||
distribution over time. The sound library provides an ASR envelope which stands for attach,
|
||||
sustain, release. The amplitude rises then sustains at the maximum level and decays slowly
|
||||
depending on pre defined time segments.
|
||||
|
||||
.________
|
||||
. ---
|
||||
. ---
|
||||
. ---
|
||||
A S R
|
||||
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
TriOsc triOsc;
|
||||
Env env;
|
||||
|
||||
// Times and levels for the ASR envelope
|
||||
float attackTime = 0.001;
|
||||
float sustainTime = 0.004;
|
||||
float sustainLevel = 0.3;
|
||||
float releaseTime = 0.4;
|
||||
|
||||
// This is an octave in MIDI notes.
|
||||
int[] midiSequence = { 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72};
|
||||
int duration = 200;
|
||||
// Set the note trigger
|
||||
int trigger = millis();
|
||||
|
||||
// An index to count up the notes
|
||||
int note=0;
|
||||
|
||||
void setup() {
|
||||
size(200, 200);
|
||||
background(255);
|
||||
|
||||
//Create and start the Sound renderer
|
||||
stream = new Sound(this);
|
||||
|
||||
// Create triangle wave and start it
|
||||
triOsc = new TriOsc(this);
|
||||
//triOsc.play();
|
||||
|
||||
// Create the envelope
|
||||
env = new Env(this);
|
||||
|
||||
}
|
||||
|
||||
void draw() {
|
||||
|
||||
// If the determined trigger moment in time matches up with the computer clock and we if the
|
||||
// sequence of notes hasn't been finished yet the next note gets played.
|
||||
if ((millis() > trigger) && (note<midiSequence.length)){
|
||||
|
||||
// midiToFreq transforms the MIDI value into a frequency in Hz which we use to control the triangle oscillator
|
||||
// with an amplitute of 0.8
|
||||
triOsc.play(midiToFreq(midiSequence[note]),0.8);
|
||||
|
||||
// The envelope gets triggered with the oscillator as input and the times and levels we defined earlier
|
||||
env.play(triOsc, attackTime, sustainTime, sustainLevel, releaseTime);
|
||||
|
||||
// Create the new trigger according to predefined durations and speed it up by deviding by 1.5
|
||||
trigger = millis() + duration;
|
||||
|
||||
// Advance by one note in the midiSequence;
|
||||
note++;
|
||||
|
||||
// Loop the sequence, notice the jitter
|
||||
if(note == 12) {note = 0;}
|
||||
}
|
||||
}
|
||||
|
||||
// This function calculates the respective frequency of a MIDI note
|
||||
float midiToFreq(int note){
|
||||
return (pow(2, ((note-69)/12.0)))*440;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
This example shows how to make a simple sampler and sequencer with the Sound library. In this
|
||||
sketch 5 different short samples are loaded and played back at different pitches, in this
|
||||
case 5 different octaves. The sequencer triggers and event every 200-1000 mSecs randomly.
|
||||
Each time a sound is played a colored rect with a random color is displayed.
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
SoundFile[] file;
|
||||
|
||||
// Define the number of samples
|
||||
int numsounds = 5;
|
||||
|
||||
// Create an array of values which represent the octaves. 1.0 is playback at normal speed, 0.5 is half and
|
||||
// therefore one octave down. 2.0 is double so one octave up.
|
||||
float[] octave = {0.25, 0.5, 1.0, 2.0, 4.0};
|
||||
|
||||
// The playSound array is defining how many samples will be played at each trigger event
|
||||
int[] playSound = {1,1,1,1,1};
|
||||
|
||||
// The trigger is an integer number in milliseconds so we can schedule new events in the draw loop
|
||||
int trigger;
|
||||
|
||||
// This array holds the pixel positions of the rectangles which are drawn each event
|
||||
int[] posx = {0, 100, 200, 300, 400};
|
||||
|
||||
|
||||
void setup(){
|
||||
size(500, 300);
|
||||
background(255);
|
||||
|
||||
// Create a Sound renderer and an array of empty soundfiles
|
||||
stream = new Sound(this);
|
||||
file = new SoundFile[numsounds];
|
||||
|
||||
// Load 5 soundfiles from a folder in a for loop. By naming the files 1., 2., 3., n.aif it is easy to iterate
|
||||
// through the folder and load all files in one line of code.
|
||||
for (int i = 0; i < numsounds; i++){
|
||||
file[i] = new SoundFile(this, (i+1) + ".aif");
|
||||
}
|
||||
|
||||
// Create a trigger which will be the basis for our random sequencer.
|
||||
trigger = millis();
|
||||
}
|
||||
|
||||
void draw(){
|
||||
|
||||
// If the determined trigger moment in time matches up with the computer clock events get triggered.
|
||||
if (millis() > trigger){
|
||||
// Redraw the background every time to erase old rects
|
||||
background(255);
|
||||
|
||||
// By iterating through the playSound array we check for 1 or 0, 1 plays a sound and draws a rect,
|
||||
// for 0 nothing happens.
|
||||
|
||||
for (int i = 0; i < numsounds; i++){
|
||||
// Check which indexes are 1 and 0.
|
||||
if (playSound[i] == 1){
|
||||
float rate;
|
||||
// Choose a random color and get set to noStroke()
|
||||
fill(int(random(255)),int(random(255)),int(random(255)));
|
||||
noStroke();
|
||||
// Draw the rect in the positions we defined earlier in posx
|
||||
rect(posx[i], 50, 100, 200);
|
||||
// Choose a random index of the octave array
|
||||
rate = octave[int(random(0,5))];
|
||||
// Play the soundfile from the array with the respective rate and loop set to false
|
||||
file[i].play(rate, 1.0);
|
||||
}
|
||||
|
||||
// Renew the indexes of playSound so that at the next event the order is different and randomized.
|
||||
playSound[i] = int(random(0,2));
|
||||
};
|
||||
|
||||
// Create a new triggertime in the future, with a random offset between 200 and 1000 milliseconds
|
||||
trigger = millis() + int(random(200,1000));
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
This example shows how to use the Fast Fourier Transform function to get the spectrum
|
||||
of a sound. This function calculates the FFT of a signal and returns the positive normalized
|
||||
magnitude spectrum. This means we pass it the number of bands we want (the actual FFT size is
|
||||
two times that size) and a float array with the same size.
|
||||
*/
|
||||
|
||||
import processing.sound.*;
|
||||
|
||||
Sound stream;
|
||||
SoundFile sample;
|
||||
FFT fft;
|
||||
|
||||
int scale=1;
|
||||
int bands=512;
|
||||
float[] spec = new float[bands];
|
||||
|
||||
public void setup() {
|
||||
size(bands,350);
|
||||
background(255);
|
||||
|
||||
// Create and start the sound renderer
|
||||
stream = new Sound(this, 44100, 256);
|
||||
|
||||
//Load and play a soundfile and loop it. This has to be called
|
||||
// before the FFT is created.
|
||||
sample = new SoundFile(this, "beat.aiff");
|
||||
sample.play(true);
|
||||
|
||||
// Create and patch the rms tracker
|
||||
fft = new FFT(this);
|
||||
fft.input(sample, bands);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
background(255);
|
||||
|
||||
fft.process(spec);
|
||||
|
||||
for(int i = 0; i < bands; i++)
|
||||
{
|
||||
// The result of the FFT is normalized
|
||||
// draw the line for frequency band i scaling it up by 5 to get more amplitude.
|
||||
line( i, height, i, height - spec[i]*height*5 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
|
||||
|
||||
# Processing MethCla Interface
|
||||
|
||||
This is a processing interface and a collection of plugins for MethCla, a leight-weight, efficient sound engine for mobile devices [methcla](http://methc.la).
|
||||
|
||||
## Executable
|
||||
|
||||
Download the current version of the library here:
|
||||
|
||||
[Sound](https://github.com/wirsing/ProcessingSound/releases)
|
||||
|
||||
|
||||
## Building the libMethClaInterface
|
||||
|
||||
The library requires a compiled shared library of MethCla for each platform. There are specific Makefile in the src folder which compile the JNI library. For the moment this library is OsX only.
|
||||
|
||||
The Java Library is to be compiled with ant. Please install the latest version on ant on your computer. The build.xml file is in resources. To compile do
|
||||
|
||||
$ cd resources
|
||||
$ ant
|
||||
@@ -0,0 +1,12 @@
|
||||
all:
|
||||
|
||||
gcc -fPIC -I/usr/local/java/jdk1.7.0_60/include/linux -I./include -I/usr/local/java/jdk1.7.0_60/include -std=c++11 -g -c processing_sound_MethClaInterface.cpp;
|
||||
gcc -shared -o libMethClaInterface.so *.o -lmethcla;
|
||||
|
||||
clean:
|
||||
rm *.o
|
||||
rm *.jnilib
|
||||
|
||||
install:
|
||||
cp libMethClaInterface.so ../../library/linux
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
all:
|
||||
|
||||
g++ -Ic:/Java/jdk1.7.0_60/include -Ic:/Java/jdk1.7.0_60/include/win32 -I./include -std=c++11 -g -c processing_sound_MethClaInterface.cpp;
|
||||
g++ -dynamiclib -lmethcla -L../../library/macosx/ -o libMethClaInterface.jnilib *.o;
|
||||
|
||||
clean:
|
||||
rm *.o
|
||||
rm *.jnilib
|
||||
|
||||
install:
|
||||
cp libMethClaInterface.jnilib ../../lib/macosx
|
||||
@@ -0,0 +1,10 @@
|
||||
all:
|
||||
g++ -I/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers -I./include -std=c++11 -g -c processing_sound_MethClaInterface.cpp;
|
||||
g++ -dynamiclib -lmethcla -L../../library/macosx/ -o libMethClaInterface.jnilib *.o;
|
||||
|
||||
clean:
|
||||
rm *.o
|
||||
rm *.jnilib
|
||||
|
||||
install:
|
||||
cp libMethClaInterface.jnilib ../../library/macosx
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_COMMON_H_INCLUDED
|
||||
#define METHCLA_COMMON_H_INCLUDED
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# define METHCLA_C_LINKAGE extern "C"
|
||||
#else
|
||||
# define METHCLA_C_LINKAGE
|
||||
#endif
|
||||
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#if defined(BUILDING_DLL)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define METHCLA_VISIBLE __attribute__ ((dllexport))
|
||||
#else
|
||||
#define METHCLA_VISIBLE __declspec(dllexport) // Note: actually gcc seems to also supports this syntax.
|
||||
#endif
|
||||
#else
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define METHCLA_VISIBLE __attribute__ ((dllimport))
|
||||
#else
|
||||
#define METHCLA_VISIBLE __declspec(dllimport) // Note: actually gcc seems to also supports this syntax.
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#if (__GNUC__ >= 4) || (defined(__clang__) && (__clang_major__ >= 4))
|
||||
#define METHCLA_VISIBLE __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define METHCLA_VISIBLE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define METHCLA_EXPORT METHCLA_C_LINKAGE METHCLA_VISIBLE
|
||||
|
||||
//* Time in seconds.
|
||||
typedef double Methcla_Time;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const void* data;
|
||||
size_t size;
|
||||
} Methcla_OSCPacket;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kMethcla_NoError = 0,
|
||||
|
||||
/* Generic error codes */
|
||||
kMethcla_UnspecifiedError,
|
||||
kMethcla_LogicError,
|
||||
kMethcla_ArgumentError,
|
||||
kMethcla_MemoryError,
|
||||
kMethcla_UnimplementedError,
|
||||
kMethcla_SystemError,
|
||||
|
||||
/* Engine errors */
|
||||
kMethcla_SynthDefNotFoundError = 1000,
|
||||
kMethcla_NodeIdError,
|
||||
kMethcla_NodeTypeError,
|
||||
|
||||
/* File errors */
|
||||
kMethcla_FileNotFoundError = 2000,
|
||||
kMethcla_FileExistsError,
|
||||
kMethcla_PermissionsError,
|
||||
kMethcla_UnsupportedFileTypeError,
|
||||
kMethcla_UnsupportedDataFormatError,
|
||||
kMethcla_InvalidFileError,
|
||||
|
||||
/* Audio driver errors */
|
||||
kMethcla_DeviceUnavailableError = 3000,
|
||||
} Methcla_ErrorCode;
|
||||
|
||||
METHCLA_EXPORT const char* methcla_error_code_description(Methcla_ErrorCode code);
|
||||
|
||||
typedef struct Methcla_Error
|
||||
{
|
||||
Methcla_ErrorCode error_code;
|
||||
char* error_message;
|
||||
} Methcla_Error;
|
||||
|
||||
static inline bool methcla_is_ok(const Methcla_Error error)
|
||||
{
|
||||
return error.error_code == kMethcla_NoError;
|
||||
}
|
||||
|
||||
static inline bool methcla_is_error(const Methcla_Error error)
|
||||
{
|
||||
return error.error_code != kMethcla_NoError;
|
||||
}
|
||||
|
||||
static inline bool methcla_error_has_code(const Methcla_Error error, Methcla_ErrorCode code)
|
||||
{
|
||||
return error.error_code == code;
|
||||
}
|
||||
|
||||
static inline Methcla_ErrorCode methcla_error_code(const Methcla_Error error)
|
||||
{
|
||||
return error.error_code;
|
||||
}
|
||||
|
||||
static inline const char* methcla_error_message(const Methcla_Error error)
|
||||
{
|
||||
return error.error_message;
|
||||
}
|
||||
|
||||
//* Create a new Methcla_Error with a specific error code.
|
||||
// The error message is set to NULL.
|
||||
METHCLA_EXPORT Methcla_Error methcla_error_new(Methcla_ErrorCode code);
|
||||
|
||||
//* Create a new Methcla_Error with a specific error code and message.
|
||||
METHCLA_EXPORT Methcla_Error methcla_error_new_with_message(Methcla_ErrorCode code, const char* message);
|
||||
|
||||
//* Free the resources associated with a Methcla_Error.
|
||||
METHCLA_EXPORT void methcla_error_free(Methcla_Error error);
|
||||
|
||||
//* Return a Methcla_Error indicating that no error has occurred.
|
||||
static inline Methcla_Error methcla_no_error()
|
||||
{
|
||||
return methcla_error_new(kMethcla_NoError);
|
||||
}
|
||||
|
||||
//* Audio sample type
|
||||
typedef float Methcla_AudioSample;
|
||||
|
||||
METHCLA_EXPORT void methcla_init();
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* METHCLA_COMMON_H_INCLUDED */
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright 2013 Samplecount S.L.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef METHCLA_DETAIL_HPP_INCLUDED
|
||||
#define METHCLA_DETAIL_HPP_INCLUDED
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <methcla/engine.h>
|
||||
|
||||
namespace Methcla
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <class D, typename T> class Id
|
||||
{
|
||||
public:
|
||||
explicit Id(T id)
|
||||
: m_id(id)
|
||||
{ }
|
||||
Id(const D& other)
|
||||
: m_id(other.m_id)
|
||||
{ }
|
||||
|
||||
T id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
bool operator==(const D& other) const
|
||||
{
|
||||
return m_id == other.m_id;
|
||||
}
|
||||
|
||||
bool operator!=(const D& other) const
|
||||
{
|
||||
return m_id != other.m_id;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_id;
|
||||
};
|
||||
|
||||
inline static void throwError(Methcla_Error err)
|
||||
{
|
||||
if (methcla_is_error(err))
|
||||
{
|
||||
if (methcla_error_has_code(err, kMethcla_ArgumentError)) {
|
||||
std::string msg(methcla_error_message(err));
|
||||
methcla_error_free(err);
|
||||
throw std::invalid_argument(msg);
|
||||
} else if (methcla_error_has_code(err, kMethcla_LogicError)) {
|
||||
std::string msg(methcla_error_message(err));
|
||||
methcla_error_free(err);
|
||||
throw std::logic_error(msg);
|
||||
} else if (methcla_error_has_code(err, kMethcla_MemoryError)) {
|
||||
methcla_error_free(err);
|
||||
throw std::bad_alloc();
|
||||
} else {
|
||||
std::string msg( methcla_error_message(err)
|
||||
? methcla_error_message(err)
|
||||
: methcla_error_code_description(methcla_error_code(err)));
|
||||
methcla_error_free(err);
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline static void checkReturnCode(Methcla_Error err)
|
||||
{
|
||||
throwError(err);
|
||||
}
|
||||
|
||||
template <typename T> T combineFlags(T a, T b)
|
||||
{
|
||||
// FIXME: Not available in GCC 4.6, Clang 3.3
|
||||
// typedef typename std::underlying_type<T>::type enum_type;
|
||||
typedef int enum_type;
|
||||
static_assert(sizeof(T) <= sizeof(enum_type), "combineFlags: Cannot determine underlying enum type");
|
||||
return static_cast<T>(static_cast<enum_type>(a) | static_cast<enum_type>(b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // METHCLA_DETAIL_HPP_INCLUDED
|
||||
@@ -0,0 +1,171 @@
|
||||
// Copyright 2013 Samplecount S.L.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef METHCLA_DETAIL_RESULT_HPP_INCLUDED
|
||||
#define METHCLA_DETAIL_RESULT_HPP_INCLUDED
|
||||
|
||||
#include <methcla/common.h>
|
||||
#include <oscpp/server.hpp>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
namespace Methcla
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class ResultBase
|
||||
{
|
||||
std::condition_variable m_cond_var;
|
||||
|
||||
protected:
|
||||
std::mutex m_mutex;
|
||||
bool m_cond;
|
||||
Methcla_ErrorCode m_error;
|
||||
std::string m_errorMessage;
|
||||
|
||||
public:
|
||||
ResultBase()
|
||||
: m_cond(false)
|
||||
, m_error(kMethcla_NoError)
|
||||
{ }
|
||||
|
||||
ResultBase(const ResultBase&) = delete;
|
||||
ResultBase& operator=(const ResultBase&) = delete;
|
||||
|
||||
void checkResponse(const char* requestAddress, const OSCPP::Server::Message& msg)
|
||||
{
|
||||
if (msg == "/error")
|
||||
{
|
||||
auto args(msg.args());
|
||||
Methcla_ErrorCode errorCode = static_cast<Methcla_ErrorCode>(args.int32());
|
||||
const char* errorMessage = args.string();
|
||||
setError(errorCode, errorMessage);
|
||||
}
|
||||
else if (msg != requestAddress)
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "Unexpected response message address " << msg.address() << " (expected " << requestAddress << ")";
|
||||
setError(kMethcla_LogicError, s.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
inline void notify()
|
||||
{
|
||||
m_cond = true;
|
||||
m_cond_var.notify_one();
|
||||
}
|
||||
|
||||
inline void wait()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
while (!m_cond) {
|
||||
m_cond_var.wait(lock);
|
||||
}
|
||||
if (m_error != kMethcla_NoError) {
|
||||
throwError(methcla_error_new_with_message(m_error, m_errorMessage.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
void setError(Methcla_ErrorCode error, const char* message)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (m_cond)
|
||||
{
|
||||
m_error = kMethcla_LogicError;
|
||||
m_errorMessage = "Result error already set";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_error = error;
|
||||
m_errorMessage = message;
|
||||
}
|
||||
notify();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> class Result : public ResultBase
|
||||
{
|
||||
public:
|
||||
void set(Methcla_ErrorCode error, const char* message)
|
||||
{
|
||||
setError(error, message);
|
||||
}
|
||||
|
||||
void set(const T& value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (m_error == kMethcla_NoError)
|
||||
{
|
||||
if (m_cond)
|
||||
{
|
||||
m_error = kMethcla_LogicError;
|
||||
m_errorMessage = "Result already set";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_value = value;
|
||||
notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const T& get()
|
||||
{
|
||||
wait();
|
||||
return m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_value;
|
||||
};
|
||||
|
||||
template <> class Result<void> : public ResultBase
|
||||
{
|
||||
public:
|
||||
void set(Methcla_ErrorCode error, const char* message)
|
||||
{
|
||||
setError(error, message);
|
||||
}
|
||||
|
||||
void set()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (m_error == kMethcla_NoError)
|
||||
{
|
||||
if (m_cond)
|
||||
{
|
||||
m_error = kMethcla_LogicError;
|
||||
m_errorMessage = "Result already set";
|
||||
}
|
||||
else
|
||||
{
|
||||
notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void get()
|
||||
{
|
||||
wait();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // METHCLA_DETAIL_RESULT_HPP_INCLUDED
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_ENGINE_H_INCLUDED
|
||||
#define METHCLA_ENGINE_H_INCLUDED
|
||||
|
||||
#include <methcla/common.h>
|
||||
#include <methcla/file.h>
|
||||
#include <methcla/log.h>
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//* Return library version string.
|
||||
const char* methcla_version();
|
||||
|
||||
//* Return true if using the pro version of methcla.
|
||||
static inline bool methcla_version_is_pro()
|
||||
{
|
||||
return strstr(methcla_version(), "pro") != NULL;
|
||||
}
|
||||
|
||||
//* Common audio driver options.
|
||||
typedef struct Methcla_AudioDriverOptions
|
||||
{
|
||||
int sample_rate;
|
||||
int num_inputs;
|
||||
int num_outputs;
|
||||
int buffer_size;
|
||||
} Methcla_AudioDriverOptions;
|
||||
|
||||
//* Abstract audio driver type.
|
||||
typedef struct Methcla_AudioDriver Methcla_AudioDriver;
|
||||
|
||||
//* Initialize audio options.
|
||||
METHCLA_EXPORT void methcla_audio_driver_options_init(Methcla_AudioDriverOptions* options);
|
||||
|
||||
//* Return default audio driver for this platform.
|
||||
METHCLA_EXPORT Methcla_Error methcla_default_audio_driver(const Methcla_AudioDriverOptions* options, Methcla_AudioDriver** outDriver);
|
||||
|
||||
//* An integral type for uniquely identifying requests sent to the engine.
|
||||
typedef int32_t Methcla_RequestId;
|
||||
|
||||
enum
|
||||
{
|
||||
//* Request id reserved for asynchronous notifications.
|
||||
// Clients should not use this id when sending requests to the engine.
|
||||
kMethcla_Notification = 0
|
||||
};
|
||||
|
||||
//* Callback closure type for handling OSC packets coming from the engine.
|
||||
// Packets can be either responses to previously issued requests, or, if request_id is equal to kMethcla_Notification, an asynchronous notification.
|
||||
typedef struct Methcla_PacketHandler
|
||||
{
|
||||
void* handle;
|
||||
void (*handle_packet)(void* handle, Methcla_RequestId request_id, const void* packet, size_t size);
|
||||
} Methcla_PacketHandler;
|
||||
|
||||
typedef struct Methcla_EngineOptions Methcla_EngineOptions;
|
||||
|
||||
struct Methcla_EngineOptions
|
||||
{
|
||||
Methcla_LogHandler log_handler;
|
||||
Methcla_PacketHandler packet_handler;
|
||||
|
||||
size_t sample_rate;
|
||||
size_t block_size;
|
||||
|
||||
size_t realtime_memory_size;
|
||||
size_t max_num_nodes;
|
||||
size_t max_num_audio_buses;
|
||||
|
||||
//* NULL terminated array of plugin library functions.
|
||||
Methcla_LibraryFunction* plugin_libraries;
|
||||
};
|
||||
|
||||
METHCLA_EXPORT void methcla_engine_options_init(Methcla_EngineOptions* options);
|
||||
|
||||
//* Abstract type for the sound engine.
|
||||
typedef struct Methcla_Engine Methcla_Engine;
|
||||
|
||||
//* Create a new engine with the given options and an audio driver.
|
||||
METHCLA_EXPORT Methcla_Error methcla_engine_new_with_driver(
|
||||
const Methcla_EngineOptions* options,
|
||||
Methcla_AudioDriver* driver,
|
||||
Methcla_Engine** engine
|
||||
);
|
||||
|
||||
//* Free the resources associated with engine.
|
||||
//
|
||||
// Dereferencing engine after this function returns results in undefined behavior.
|
||||
METHCLA_EXPORT void methcla_engine_free(Methcla_Engine* engine);
|
||||
|
||||
//* Return the last error code.
|
||||
// METHCLA_EXPORT Methcla_Error methcla_engine_error(const Methcla_Engine* engine);
|
||||
|
||||
//* Start the engine.
|
||||
METHCLA_EXPORT Methcla_Error methcla_engine_start(Methcla_Engine* engine);
|
||||
|
||||
//* Stop the engine.
|
||||
METHCLA_EXPORT Methcla_Error methcla_engine_stop(Methcla_Engine* engine);
|
||||
|
||||
enum Methcla_EngineLogFlags
|
||||
{
|
||||
kMethcla_EngineLogDefault = 0x00,
|
||||
kMethcla_EngineLogDebug = 0x01,
|
||||
kMethcla_EngineLogRequests = 0x02
|
||||
};
|
||||
|
||||
//* Set flags for debug logging.
|
||||
METHCLA_EXPORT void methcla_engine_set_log_flags(Methcla_Engine* engine, Methcla_EngineLogFlags flags);
|
||||
|
||||
//* Log a line using the registered log handler.
|
||||
METHCLA_EXPORT void methcla_engine_log_line(Methcla_Engine* engine, Methcla_LogLevel level, const char* message);
|
||||
|
||||
//* Encode a Methcla_Time value as a 64 bit unsigned integer.
|
||||
METHCLA_EXPORT uint64_t methcla_time_to_uint64(Methcla_Time time);
|
||||
|
||||
//* Decode a Methcla_Time value from a 64 bit unsigned integer.
|
||||
METHCLA_EXPORT Methcla_Time methcla_time_from_uint64(uint64_t time);
|
||||
|
||||
//* Get the current time.
|
||||
METHCLA_EXPORT Methcla_Time methcla_engine_current_time(Methcla_Engine* engine);
|
||||
|
||||
//* Send an OSC packet to the engine.
|
||||
METHCLA_EXPORT Methcla_Error methcla_engine_send(Methcla_Engine* engine, const void* packet, size_t size);
|
||||
|
||||
//* Open a sound file.
|
||||
METHCLA_EXPORT Methcla_Error methcla_engine_soundfile_open(const Methcla_Engine* engine, const char* path, Methcla_FileMode mode, Methcla_SoundFile** file, Methcla_SoundFileInfo* info);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* METHCLA_ENGINE_H_INCLUDED */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_FILE_H_INCLUDED
|
||||
#define METHCLA_FILE_H_INCLUDED
|
||||
|
||||
#include <methcla/common.h>
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kMethcla_FileModeRead,
|
||||
kMethcla_FileModeWrite
|
||||
} Methcla_FileMode;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kMethcla_SoundFileTypeUnknown,
|
||||
kMethcla_SoundFileTypeAIFF,
|
||||
kMethcla_SoundFileTypeWAV
|
||||
} Methcla_SoundFileType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kMethcla_SoundFileFormatUnknown,
|
||||
kMethcla_SoundFileFormatPCM16,
|
||||
kMethcla_SoundFileFormatPCM24,
|
||||
kMethcla_SoundFileFormatPCM32,
|
||||
kMethcla_SoundFileFormatFloat
|
||||
} Methcla_SoundFileFormat;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int64_t frames;
|
||||
unsigned int channels;
|
||||
unsigned int samplerate;
|
||||
Methcla_SoundFileType file_type;
|
||||
Methcla_SoundFileFormat file_format;
|
||||
} Methcla_SoundFileInfo;
|
||||
|
||||
typedef struct Methcla_SoundFile Methcla_SoundFile;
|
||||
|
||||
struct Methcla_SoundFile
|
||||
{
|
||||
void* handle;
|
||||
Methcla_Error (*close)(const Methcla_SoundFile* file);
|
||||
Methcla_Error (*seek)(const Methcla_SoundFile* file, int64_t numFrames);
|
||||
Methcla_Error (*tell)(const Methcla_SoundFile* file, int64_t* numFrames);
|
||||
Methcla_Error (*read_float)(const Methcla_SoundFile* file, float* buffer, size_t numFrames, size_t* outNumFrames);
|
||||
Methcla_Error (*write_float)(const Methcla_SoundFile* file, const float* buffer, size_t numFrames, size_t* outNumFrames);
|
||||
};
|
||||
|
||||
typedef struct Methcla_SoundFileAPI Methcla_SoundFileAPI;
|
||||
|
||||
struct Methcla_SoundFileAPI
|
||||
{
|
||||
void* handle;
|
||||
Methcla_Error (*open)(const Methcla_SoundFileAPI* api, const char* path, Methcla_FileMode mode, Methcla_SoundFile** file, Methcla_SoundFileInfo* info);
|
||||
};
|
||||
|
||||
static inline Methcla_Error methcla_soundfile_close(Methcla_SoundFile* file)
|
||||
{
|
||||
if ((file == NULL) || (file->close == NULL))
|
||||
return methcla_error_new(kMethcla_ArgumentError);
|
||||
return file->close(file);
|
||||
}
|
||||
|
||||
static inline Methcla_Error methcla_soundfile_seek(Methcla_SoundFile* file, int64_t numFrames)
|
||||
{
|
||||
if ((file == NULL) || (file->seek == NULL))
|
||||
return methcla_error_new(kMethcla_ArgumentError);
|
||||
return file->seek(file, numFrames);
|
||||
}
|
||||
|
||||
static inline Methcla_Error methcla_soundfile_tell(Methcla_SoundFile* file, int64_t* numFrames)
|
||||
{
|
||||
if ((file == NULL) || (file->tell == NULL) || (numFrames == NULL))
|
||||
return methcla_error_new(kMethcla_ArgumentError);
|
||||
return file->tell(file, numFrames);
|
||||
}
|
||||
|
||||
static inline Methcla_Error methcla_soundfile_read_float(Methcla_SoundFile* file, float* buffer, size_t numFrames, size_t* outNumFrames)
|
||||
{
|
||||
if ((file == NULL) || (file->read_float == NULL) ||
|
||||
(buffer == NULL) || (outNumFrames == NULL))
|
||||
return methcla_error_new(kMethcla_ArgumentError);
|
||||
return file->read_float(file, buffer, numFrames, outNumFrames);
|
||||
}
|
||||
|
||||
static inline Methcla_Error methcla_soundfile_write_float(Methcla_SoundFile* file, const float* buffer, size_t numFrames, size_t* outNumFrames)
|
||||
{
|
||||
if ((file == NULL) || (file->write_float == NULL) ||
|
||||
(buffer == NULL) || (outNumFrames == NULL))
|
||||
return methcla_error_new(kMethcla_ArgumentError);
|
||||
return file->write_float(file, buffer, numFrames, outNumFrames);
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* METHCLA_FILE_H_INCLUDED */
|
||||
@@ -0,0 +1,185 @@
|
||||
// Copyright 2012-2013 Samplecount S.L.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef METHCLA_FILE_HPP_INCLUDED
|
||||
#define METHCLA_FILE_HPP_INCLUDED
|
||||
|
||||
#include <methcla/detail.hpp>
|
||||
#include <methcla/engine.hpp>
|
||||
#include <methcla/file.h>
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Methcla
|
||||
{
|
||||
class SoundFileInfo : public Methcla_SoundFileInfo
|
||||
{
|
||||
public:
|
||||
SoundFileInfo()
|
||||
{
|
||||
frames = 0;
|
||||
channels = 0;
|
||||
samplerate = 0;
|
||||
file_type = kMethcla_SoundFileTypeUnknown;
|
||||
file_format = kMethcla_SoundFileFormatUnknown;
|
||||
}
|
||||
|
||||
SoundFileInfo(const Methcla_SoundFileInfo& info)
|
||||
{
|
||||
frames = info.frames;
|
||||
channels = info.channels;
|
||||
samplerate = info.samplerate;
|
||||
file_type = info.file_type;
|
||||
file_format = info.file_format;
|
||||
}
|
||||
|
||||
int64_t samples() const
|
||||
{
|
||||
return channels * frames;
|
||||
}
|
||||
|
||||
template <typename T> T duration() const
|
||||
{
|
||||
return (T)frames/(T)samplerate;
|
||||
}
|
||||
};
|
||||
|
||||
class SoundFile
|
||||
{
|
||||
Methcla_SoundFile* m_file;
|
||||
SoundFileInfo m_info;
|
||||
|
||||
inline void ensureInitialized() const
|
||||
{
|
||||
if (!m_file)
|
||||
throw std::logic_error("SoundFile has not been initialized");
|
||||
}
|
||||
|
||||
public:
|
||||
SoundFile()
|
||||
: m_file(nullptr)
|
||||
{}
|
||||
|
||||
SoundFile(Methcla_SoundFile* file, const Methcla_SoundFileInfo& info)
|
||||
: m_file(file)
|
||||
, m_info(info)
|
||||
{}
|
||||
|
||||
SoundFile(const Engine& engine, const std::string& path)
|
||||
{
|
||||
detail::checkReturnCode(
|
||||
methcla_engine_soundfile_open(engine, path.c_str(), kMethcla_FileModeRead, &m_file, &m_info)
|
||||
);
|
||||
}
|
||||
|
||||
SoundFile(const Engine& engine, const std::string& path, const SoundFileInfo& info)
|
||||
: m_info(info)
|
||||
{
|
||||
detail::checkReturnCode(
|
||||
methcla_engine_soundfile_open(engine, path.c_str(), kMethcla_FileModeWrite, &m_file, &m_info)
|
||||
);
|
||||
}
|
||||
|
||||
SoundFile(const Methcla_Host* host, const std::string& path)
|
||||
{
|
||||
detail::checkReturnCode(
|
||||
methcla_host_soundfile_open(host, path.c_str(), kMethcla_FileModeRead, &m_file, &m_info)
|
||||
);
|
||||
}
|
||||
|
||||
SoundFile(const Methcla_Host* host, const std::string& path, const SoundFileInfo& info)
|
||||
: m_info(info)
|
||||
{
|
||||
detail::checkReturnCode(
|
||||
methcla_host_soundfile_open(host, path.c_str(), kMethcla_FileModeWrite, &m_file, &m_info)
|
||||
);
|
||||
}
|
||||
|
||||
// SoundFile is moveable
|
||||
SoundFile(SoundFile&& other)
|
||||
: m_file(std::move(other.m_file))
|
||||
, m_info(std::move(other.m_info))
|
||||
{
|
||||
other.m_file = nullptr;
|
||||
}
|
||||
|
||||
SoundFile& operator=(SoundFile&& other)
|
||||
{
|
||||
m_file = std::move(other.m_file);
|
||||
m_info = std::move(other.m_info);
|
||||
other.m_file = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// SoundFile is not copyable
|
||||
SoundFile(const SoundFile&) = delete;
|
||||
SoundFile& operator=(const SoundFile&) = delete;
|
||||
|
||||
~SoundFile()
|
||||
{
|
||||
if (m_file != nullptr)
|
||||
methcla_soundfile_close(m_file);
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return m_file != nullptr;
|
||||
}
|
||||
|
||||
const SoundFileInfo& info() const
|
||||
{
|
||||
return m_info;
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
ensureInitialized();
|
||||
detail::checkReturnCode(methcla_soundfile_close(m_file));
|
||||
m_file = nullptr;
|
||||
}
|
||||
|
||||
void seek(int64_t numFrames)
|
||||
{
|
||||
ensureInitialized();
|
||||
detail::checkReturnCode(methcla_soundfile_seek(m_file, numFrames));
|
||||
}
|
||||
|
||||
int64_t tell()
|
||||
{
|
||||
ensureInitialized();
|
||||
int64_t numFrames;
|
||||
detail::checkReturnCode(methcla_soundfile_tell(m_file, &numFrames));
|
||||
return numFrames;
|
||||
}
|
||||
|
||||
size_t read(float* buffer, size_t numFrames)
|
||||
{
|
||||
ensureInitialized();
|
||||
size_t outNumFrames;
|
||||
detail::checkReturnCode(methcla_soundfile_read_float(m_file, buffer, numFrames, &outNumFrames));
|
||||
return outNumFrames;
|
||||
}
|
||||
|
||||
size_t write(const float* buffer, size_t numFrames)
|
||||
{
|
||||
ensureInitialized();
|
||||
size_t outNumFrames;
|
||||
detail::checkReturnCode(methcla_soundfile_write_float(m_file, buffer, numFrames, &outNumFrames));
|
||||
return outNumFrames;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // METHCLA_FILE_HPP_INCLUDED
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_LOG_H_INCLUDED
|
||||
#define METHCLA_LOG_H_INCLUDED
|
||||
|
||||
typedef enum Methcla_LogLevel
|
||||
{
|
||||
kMethcla_LogError,
|
||||
kMethcla_LogWarn,
|
||||
kMethcla_LogInfo,
|
||||
kMethcla_LogDebug
|
||||
} Methcla_LogLevel;
|
||||
|
||||
typedef struct Methcla_LogHandler
|
||||
{
|
||||
void* handle;
|
||||
void (*log_line)(void* handle, Methcla_LogLevel level, const char* message);
|
||||
} Methcla_LogHandler;
|
||||
|
||||
#endif /* METHCLA_LOG_H_INCLUDED */
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright 2014 Samplecount S.L.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef METHCLA_LOG_HPP_INCLUDED
|
||||
#define METHCLA_LOG_HPP_INCLUDED
|
||||
|
||||
#include <methcla/log.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
namespace Methcla {
|
||||
|
||||
class LogStream
|
||||
{
|
||||
Methcla_LogLevel m_level;
|
||||
std::function<void(Methcla_LogLevel,const char*)> m_callback;
|
||||
std::stringstream* m_stream;
|
||||
|
||||
public:
|
||||
LogStream(std::function<void(Methcla_LogLevel,const char*)> callback, Methcla_LogLevel messageLevel, Methcla_LogLevel currentLevel)
|
||||
: m_level(messageLevel)
|
||||
, m_callback(messageLevel <= currentLevel ? callback : nullptr)
|
||||
, m_stream(nullptr)
|
||||
{}
|
||||
|
||||
LogStream(std::function<void(Methcla_LogLevel,const char*)> callback, Methcla_LogLevel messageLevel)
|
||||
: LogStream(callback, messageLevel, messageLevel)
|
||||
{}
|
||||
|
||||
LogStream(const LogStream& other)
|
||||
: m_level(other.m_level)
|
||||
, m_callback(other.m_callback)
|
||||
, m_stream(other.m_stream ? new std::stringstream(other.m_stream->str()) : nullptr)
|
||||
{}
|
||||
|
||||
~LogStream()
|
||||
{
|
||||
if (m_stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (m_callback)
|
||||
m_callback(m_level, m_stream->str().c_str());
|
||||
delete m_stream;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete m_stream;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> LogStream& operator<<(const T& x)
|
||||
{
|
||||
if (m_callback)
|
||||
{
|
||||
if (!m_stream)
|
||||
m_stream = new std::stringstream();
|
||||
*m_stream << x;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Methcla
|
||||
|
||||
#endif // METHCLA_LOG_HPP_INCLUDED
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2013 Samplecount S.L.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef METHCLA_PLATFORM_PEPPER_HPP_INCLUDED
|
||||
#define METHCLA_PLATFORM_PEPPER_HPP_INCLUDED
|
||||
|
||||
#include <methcla/common.h>
|
||||
#include <methcla/engine.h>
|
||||
#include "ppapi/cpp/instance_handle.h"
|
||||
|
||||
METHCLA_EXPORT Methcla_AudioDriver* methcla_platform_pepper_audio_driver_new(
|
||||
const Methcla_AudioDriverOptions* options,
|
||||
const pp::InstanceHandle& instance
|
||||
);
|
||||
|
||||
#endif // METHCLA_PLATFORM_PEPPER_HPP_INCLUDED
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2014 Samplecount S.L.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef METHCLA_PLATFORM_RTAUDIO_HPP_INCLUDED
|
||||
#define METHCLA_PLATFORM_RTAUDIO_HPP_INCLUDED
|
||||
|
||||
#include <methcla/engine.h>
|
||||
|
||||
METHCLA_EXPORT Methcla_AudioDriver* methcla_rtaudio_driver_new(
|
||||
const Methcla_AudioDriverOptions* options
|
||||
);
|
||||
|
||||
#endif // METHCLA_PLATFORM_RTAUDIO_HPP_INCLUDED
|
||||
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGIN_H_INCLUDED
|
||||
#define METHCLA_PLUGIN_H_INCLUDED
|
||||
|
||||
#include <methcla/common.h>
|
||||
#include <methcla/file.h>
|
||||
#include <methcla/log.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define METHCLA_PLUGINS_URI "http://methc.la/plugins"
|
||||
|
||||
//* Realtime interface.
|
||||
typedef struct Methcla_World Methcla_World;
|
||||
|
||||
//* Non-realtime interface.
|
||||
typedef struct Methcla_Host Methcla_Host;
|
||||
|
||||
//* Synth handle managed by a plugin.
|
||||
typedef void Methcla_Synth;
|
||||
|
||||
//* Callback function type for performing commands in the non-realtime context.
|
||||
typedef void (*Methcla_HostPerformFunction)(const Methcla_Host* host, void* data);
|
||||
|
||||
//* Callback function type for performing commands in the realtime context.
|
||||
typedef void (*Methcla_WorldPerformFunction)(const Methcla_World* world, void* data);
|
||||
|
||||
//* Realtime interface
|
||||
struct Methcla_World
|
||||
{
|
||||
//* Handle for implementation specific data.
|
||||
void* handle;
|
||||
|
||||
//* Return engine sample rate.
|
||||
double (*samplerate)(const Methcla_World*);
|
||||
|
||||
//* Return maximum audio block size.
|
||||
size_t (*block_size)(const Methcla_World* world);
|
||||
|
||||
//* Return the time at the start of the current audio block in seconds.
|
||||
Methcla_Time (*current_time)(const struct Methcla_World* world);
|
||||
|
||||
// Realtime memory allocation
|
||||
void* (*alloc)(const struct Methcla_World* world, size_t size);
|
||||
void* (*alloc_aligned)(const struct Methcla_World* world, size_t alignment, size_t size);
|
||||
void (*free)(const struct Methcla_World* world, void* ptr);
|
||||
|
||||
//* Schedule a command for execution in the non-realtime context.
|
||||
void (*perform_command)(const Methcla_World* world, Methcla_HostPerformFunction perform, void* data);
|
||||
|
||||
//* Log a message and a newline character.
|
||||
void (*log_line)(const Methcla_World* world, Methcla_LogLevel level, const char* message);
|
||||
|
||||
//* Free synth.
|
||||
void (*synth_done)(const struct Methcla_World* world, Methcla_Synth* synth);
|
||||
};
|
||||
|
||||
static inline double methcla_world_samplerate(const Methcla_World* world)
|
||||
{
|
||||
assert(world && world->samplerate);
|
||||
return world->samplerate(world);
|
||||
}
|
||||
|
||||
static inline size_t methcla_world_block_size(const Methcla_World* world)
|
||||
{
|
||||
assert(world && world->block_size);
|
||||
return world->block_size(world);
|
||||
}
|
||||
|
||||
static inline Methcla_Time methcla_world_current_time(const Methcla_World* world)
|
||||
{
|
||||
assert(world);
|
||||
assert(world->current_time);
|
||||
return world->current_time(world);
|
||||
}
|
||||
|
||||
static inline void* methcla_world_alloc(const Methcla_World* world, size_t size)
|
||||
{
|
||||
assert(world && world->alloc);
|
||||
return world->alloc(world, size);
|
||||
}
|
||||
|
||||
static inline void* methcla_world_alloc_aligned(const Methcla_World* world, size_t alignment, size_t size)
|
||||
{
|
||||
assert(world && world->alloc_aligned);
|
||||
return world->alloc_aligned(world, alignment, size);
|
||||
}
|
||||
|
||||
static inline void methcla_world_free(const Methcla_World* world, void* ptr)
|
||||
{
|
||||
assert(world && world->free);
|
||||
world->free(world, ptr);
|
||||
}
|
||||
|
||||
static inline void methcla_world_perform_command(const Methcla_World* world, Methcla_HostPerformFunction perform, void* data)
|
||||
{
|
||||
assert(world && world->perform_command);
|
||||
assert(perform);
|
||||
world->perform_command(world, perform, data);
|
||||
}
|
||||
|
||||
static inline void methcla_world_log_line(const Methcla_World* world, Methcla_LogLevel level, const char* message)
|
||||
{
|
||||
assert(world);
|
||||
assert(world->log_line);
|
||||
assert(message);
|
||||
world->log_line(world, level, message);
|
||||
}
|
||||
|
||||
static inline void methcla_world_synth_done(const Methcla_World* world, Methcla_Synth* synth)
|
||||
{
|
||||
assert(world);
|
||||
assert(world->synth_done);
|
||||
assert(synth);
|
||||
world->synth_done(world, synth);
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kMethcla_Input,
|
||||
kMethcla_Output
|
||||
} Methcla_PortDirection;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kMethcla_ControlPort,
|
||||
kMethcla_AudioPort
|
||||
} Methcla_PortType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kMethcla_PortFlags = 0x0
|
||||
, kMethcla_Trigger = 0x1
|
||||
} Methcla_PortFlags;
|
||||
|
||||
typedef struct Methcla_PortDescriptor Methcla_PortDescriptor;
|
||||
|
||||
struct Methcla_PortDescriptor
|
||||
{
|
||||
Methcla_PortDirection direction;
|
||||
Methcla_PortType type;
|
||||
Methcla_PortFlags flags;
|
||||
};
|
||||
|
||||
typedef uint16_t Methcla_PortCount;
|
||||
|
||||
typedef void Methcla_SynthOptions;
|
||||
|
||||
typedef struct Methcla_SynthDef Methcla_SynthDef;
|
||||
|
||||
struct Methcla_SynthDef
|
||||
{
|
||||
//* Synth definition URI.
|
||||
const char* uri;
|
||||
|
||||
//* Size of an instance in bytes.
|
||||
size_t instance_size;
|
||||
|
||||
//* Size of options struct in bytes.
|
||||
size_t options_size;
|
||||
|
||||
//* Parse OSC options and fill options struct.
|
||||
void (*configure)(const void* tag_buffer, size_t tag_size, const void* arg_buffer, size_t arg_size, Methcla_SynthOptions* options);
|
||||
|
||||
//* Get port descriptor at index.
|
||||
bool (*port_descriptor)(const Methcla_SynthOptions* options, Methcla_PortCount index, Methcla_PortDescriptor* port);
|
||||
|
||||
//* Construct a synth instance at the location given.
|
||||
void (*construct)(const Methcla_World* world, const Methcla_SynthDef* def, const Methcla_SynthOptions* options, Methcla_Synth* synth);
|
||||
|
||||
//* Connect port at index to data.
|
||||
void (*connect)(Methcla_Synth* synth, Methcla_PortCount index, void* data);
|
||||
|
||||
//* Activate the synth instance just before starting to call `process`.
|
||||
void (*activate)(const Methcla_World* world, Methcla_Synth* synth);
|
||||
|
||||
//* Process numFrames of audio samples.
|
||||
void (*process)(const Methcla_World* world, Methcla_Synth* synth, size_t numFrames);
|
||||
|
||||
//* Destroy a synth instance.
|
||||
void (*destroy)(const Methcla_World* world, Methcla_Synth* synth);
|
||||
};
|
||||
|
||||
struct Methcla_Host
|
||||
{
|
||||
//* Handle for implementation specific data.
|
||||
void* handle;
|
||||
|
||||
//* Register a synth definition.
|
||||
void (*register_synthdef)(const struct Methcla_Host* host, const Methcla_SynthDef* synthDef);
|
||||
|
||||
//* Register sound file API.
|
||||
void (*register_soundfile_api)(const struct Methcla_Host* host, const Methcla_SoundFileAPI* api);
|
||||
|
||||
//* Allocate a block of memory
|
||||
void* (*alloc)(const struct Methcla_Host* context, size_t size);
|
||||
|
||||
//* Allocate a block of aligned memory.
|
||||
void* (*alloc_aligned)(const struct Methcla_Host* context, size_t alignment, size_t size);
|
||||
|
||||
//* Free a block of memory previously allocated by alloc or alloc_aligned.
|
||||
void (*free)(const struct Methcla_Host* context, void* ptr);
|
||||
|
||||
//* Open sound file.
|
||||
Methcla_Error (*soundfile_open)(const Methcla_Host* host, const char* path, Methcla_FileMode mode, Methcla_SoundFile** file, Methcla_SoundFileInfo* info);
|
||||
|
||||
//* Schedule a command for execution in the realtime context.
|
||||
void (*perform_command)(const Methcla_Host* host, const Methcla_WorldPerformFunction perform, void* data);
|
||||
|
||||
//* Send an OSC notification packet to the client.
|
||||
void (*notify)(const Methcla_Host* host, const void* packet, size_t size);
|
||||
|
||||
//* Log a message and a newline character.
|
||||
void (*log_line)(const Methcla_Host* host, Methcla_LogLevel level, const char* message);
|
||||
};
|
||||
|
||||
static inline void methcla_host_register_synthdef(const Methcla_Host* host, const Methcla_SynthDef* synthDef)
|
||||
{
|
||||
assert(host && host->register_synthdef);
|
||||
assert(synthDef);
|
||||
host->register_synthdef(host, synthDef);
|
||||
}
|
||||
|
||||
static inline void methcla_host_register_soundfile_api(const Methcla_Host* host, const Methcla_SoundFileAPI* api)
|
||||
{
|
||||
assert(host && host->register_soundfile_api && api);
|
||||
host->register_soundfile_api(host, api);
|
||||
}
|
||||
|
||||
static inline void* methcla_host_alloc(const Methcla_Host* context, size_t size)
|
||||
{
|
||||
assert(context);
|
||||
assert(context->alloc);
|
||||
return context->alloc(context, size);
|
||||
}
|
||||
|
||||
static inline void* methcla_host_alloc_aligned(const Methcla_Host* context, size_t alignment, size_t size)
|
||||
{
|
||||
assert(context);
|
||||
assert(context->alloc_aligned);
|
||||
return context->alloc_aligned(context, alignment, size);
|
||||
}
|
||||
|
||||
static inline void methcla_host_free(const Methcla_Host* context, void* ptr)
|
||||
{
|
||||
assert(context);
|
||||
assert(context->free);
|
||||
context->free(context, ptr);
|
||||
}
|
||||
|
||||
static inline Methcla_Error methcla_host_soundfile_open(const Methcla_Host* host, const char* path, Methcla_FileMode mode, Methcla_SoundFile** file, Methcla_SoundFileInfo* info)
|
||||
{
|
||||
assert(host && host->soundfile_open);
|
||||
assert(path);
|
||||
assert(file);
|
||||
assert(info);
|
||||
return host->soundfile_open(host, path, mode, file, info);
|
||||
}
|
||||
|
||||
static inline void methcla_host_perform_command(const Methcla_Host* host, Methcla_WorldPerformFunction perform, void* data)
|
||||
{
|
||||
assert(host && host->perform_command);
|
||||
host->perform_command(host, perform, data);
|
||||
}
|
||||
|
||||
static inline void methcla_host_log_line(const Methcla_Host* host, Methcla_LogLevel level, const char* message)
|
||||
{
|
||||
assert(host);
|
||||
assert(host->log_line);
|
||||
assert(message);
|
||||
host->log_line(host, level, message);
|
||||
}
|
||||
|
||||
typedef struct Methcla_Library Methcla_Library;
|
||||
|
||||
struct Methcla_Library
|
||||
{
|
||||
//* Handle for implementation specific data.
|
||||
void* handle;
|
||||
|
||||
//* Destroy the library and clean up associated resources.
|
||||
void (*destroy)(const Methcla_Library* library);
|
||||
};
|
||||
|
||||
typedef const Methcla_Library* (*Methcla_LibraryFunction)(const Methcla_Host* host, const char* bundlePath);
|
||||
|
||||
static inline void methcla_library_destroy(const Methcla_Library* library)
|
||||
{
|
||||
assert(library);
|
||||
if (library->destroy)
|
||||
library->destroy(library);
|
||||
}
|
||||
|
||||
// #define MESCALINE_MAKE_INIT_FUNC(name) MethclaInit_##name
|
||||
// #define MESCALINE_INIT_FUNC(name) MESCALINE_MAKE_INIT_FUNC(name)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* METHCLA_PLUGIN_H_INCLUDED */
|
||||
@@ -0,0 +1,305 @@
|
||||
// Copyright 2013 Samplecount S.L.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef METHCLA_PLUGIN_HPP_INCLUDED
|
||||
#define METHCLA_PLUGIN_HPP_INCLUDED
|
||||
|
||||
#include <methcla/log.hpp>
|
||||
#include <methcla/plugin.h>
|
||||
#include <oscpp/server.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <cstring>
|
||||
|
||||
// NOTE: This API is unstable and subject to change!
|
||||
|
||||
namespace Methcla { namespace Plugin {
|
||||
|
||||
template <class Synth> class World
|
||||
{
|
||||
const Methcla_World* m_context;
|
||||
|
||||
public:
|
||||
World(const Methcla_World* context)
|
||||
: m_context(context)
|
||||
{ }
|
||||
|
||||
double sampleRate() const
|
||||
{
|
||||
return methcla_world_samplerate(m_context);
|
||||
}
|
||||
|
||||
size_t blockSize() const
|
||||
{
|
||||
return methcla_world_block_size(m_context);
|
||||
}
|
||||
|
||||
Methcla_Time currentTime() const
|
||||
{
|
||||
return methcla_world_current_time(m_context);
|
||||
}
|
||||
|
||||
void* alloc(size_t size) const
|
||||
{
|
||||
return methcla_world_alloc(m_context, size);
|
||||
}
|
||||
|
||||
void* allocAligned(size_t alignment, size_t size) const
|
||||
{
|
||||
return methcla_world_alloc_aligned(m_context, alignment, size);
|
||||
}
|
||||
|
||||
void free(void* ptr)
|
||||
{
|
||||
methcla_world_free(m_context, ptr);
|
||||
}
|
||||
|
||||
void performCommand(Methcla_HostPerformFunction perform, void* data)
|
||||
{
|
||||
methcla_world_perform_command(m_context, perform, data);
|
||||
}
|
||||
|
||||
LogStream log(Methcla_LogLevel logLevel=kMethcla_LogInfo)
|
||||
{
|
||||
using namespace std::placeholders;
|
||||
return LogStream(std::bind(m_context->log_line, m_context, _1, _2), logLevel);
|
||||
}
|
||||
|
||||
void synthRetain(Synth* synth) const
|
||||
{
|
||||
methcla_world_synth_retain(m_context, synth);
|
||||
}
|
||||
|
||||
void synthRelease(Synth* synth) const
|
||||
{
|
||||
methcla_world_synth_release(m_context, synth);
|
||||
}
|
||||
|
||||
void synthDone(Synth* synth) const
|
||||
{
|
||||
methcla_world_synth_done(m_context, synth);
|
||||
}
|
||||
};
|
||||
|
||||
class HostContext
|
||||
{
|
||||
const Methcla_Host* m_context;
|
||||
|
||||
public:
|
||||
HostContext(const Methcla_Host* context)
|
||||
: m_context(context)
|
||||
{}
|
||||
|
||||
LogStream log(Methcla_LogLevel logLevel=kMethcla_LogInfo)
|
||||
{
|
||||
using namespace std::placeholders;
|
||||
return LogStream(std::bind(m_context->log_line, m_context, _1, _2), logLevel);
|
||||
}
|
||||
};
|
||||
|
||||
class NoPorts
|
||||
{
|
||||
public:
|
||||
enum Port { };
|
||||
|
||||
static size_t numPorts() { return 0; }
|
||||
|
||||
static Methcla_PortDescriptor descriptor(Port)
|
||||
{
|
||||
Methcla_PortDescriptor result;
|
||||
std::memset(&result, 0, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
class PortDescriptor
|
||||
{
|
||||
public:
|
||||
static Methcla_PortDescriptor make(Methcla_PortDirection direction, Methcla_PortType type, Methcla_PortFlags flags=kMethcla_PortFlags)
|
||||
{
|
||||
Methcla_PortDescriptor pd;
|
||||
pd.direction = direction;
|
||||
pd.type = type;
|
||||
pd.flags = flags;
|
||||
return pd;
|
||||
}
|
||||
|
||||
static Methcla_PortDescriptor audioInput(Methcla_PortFlags flags=kMethcla_PortFlags)
|
||||
{
|
||||
return make(kMethcla_Input, kMethcla_AudioPort, flags);
|
||||
}
|
||||
|
||||
static Methcla_PortDescriptor audioOutput(Methcla_PortFlags flags=kMethcla_PortFlags)
|
||||
{
|
||||
return make(kMethcla_Output, kMethcla_AudioPort, flags);
|
||||
}
|
||||
|
||||
static Methcla_PortDescriptor controlInput(Methcla_PortFlags flags=kMethcla_PortFlags)
|
||||
{
|
||||
return make(kMethcla_Input, kMethcla_ControlPort, flags);
|
||||
}
|
||||
|
||||
static Methcla_PortDescriptor controlOutput(Methcla_PortFlags flags=kMethcla_PortFlags)
|
||||
{
|
||||
return make(kMethcla_Output, kMethcla_ControlPort, flags);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Options, class PortDescriptor> class StaticSynthOptions
|
||||
{
|
||||
public:
|
||||
typedef Options Type;
|
||||
|
||||
static void
|
||||
configure( const void* tag_buffer
|
||||
, size_t tag_buffer_size
|
||||
, const void* arg_buffer
|
||||
, size_t arg_buffer_size
|
||||
, Methcla_SynthOptions* options )
|
||||
{
|
||||
OSCPP::Server::ArgStream args(
|
||||
OSCPP::ReadStream(tag_buffer, tag_buffer_size),
|
||||
OSCPP::ReadStream(arg_buffer, arg_buffer_size)
|
||||
);
|
||||
new (options) Type(args);
|
||||
}
|
||||
|
||||
static bool
|
||||
port_descriptor( const Methcla_SynthOptions*
|
||||
, Methcla_PortCount index
|
||||
, Methcla_PortDescriptor* port )
|
||||
{
|
||||
if (index < PortDescriptor::numPorts())
|
||||
{
|
||||
*port = PortDescriptor::descriptor(static_cast<typename PortDescriptor::Port>(index));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class Synth, bool Condition>
|
||||
class IfSynthDefHasActivate
|
||||
{
|
||||
public:
|
||||
static inline void exec(const Methcla_World*, Synth*) { }
|
||||
};
|
||||
|
||||
template <class Synth>
|
||||
class IfSynthDefHasActivate<Synth, true>
|
||||
{
|
||||
public:
|
||||
static inline void exec(const Methcla_World* context, Synth* synth)
|
||||
{ synth->activate(World<Synth>(context)); }
|
||||
};
|
||||
|
||||
template <class Synth, bool Condition>
|
||||
class IfSynthDefHasCleanup
|
||||
{
|
||||
public:
|
||||
static inline void exec(const Methcla_World*, Synth*) { }
|
||||
};
|
||||
|
||||
template <class Synth>
|
||||
class IfSynthDefHasCleanup<Synth, true>
|
||||
{
|
||||
public:
|
||||
static inline void exec(const Methcla_World* context, Synth* synth)
|
||||
{ synth->cleanup(World<Synth>(context)); }
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
enum SynthDefFlags
|
||||
{
|
||||
kSynthDefDefaultFlags = 0x00,
|
||||
kSynthDefHasActivate = 0x01,
|
||||
kSynthDefHasCleanup = 0x02
|
||||
};
|
||||
|
||||
template <class Synth, class Options, class PortDescriptor, SynthDefFlags Flags=kSynthDefDefaultFlags> class SynthDef
|
||||
{
|
||||
static void
|
||||
construct( const Methcla_World* context
|
||||
, const Methcla_SynthDef* synthDef
|
||||
, const Methcla_SynthOptions* options
|
||||
, Methcla_Synth* synth )
|
||||
{
|
||||
assert(context != nullptr);
|
||||
assert(options != nullptr);
|
||||
new (synth) Synth(World<Synth>(context), synthDef, *static_cast<const typename Options::Type*>(options));
|
||||
}
|
||||
|
||||
static void
|
||||
connect( Methcla_Synth* synth
|
||||
, Methcla_PortCount port
|
||||
, void* data)
|
||||
{
|
||||
static_cast<Synth*>(synth)->connect(static_cast<typename PortDescriptor::Port>(port), data);
|
||||
}
|
||||
|
||||
static void
|
||||
activate(const Methcla_World* context, Methcla_Synth* synth)
|
||||
{
|
||||
detail::IfSynthDefHasActivate<
|
||||
Synth,
|
||||
(Flags & kSynthDefHasActivate) == kSynthDefHasActivate
|
||||
>::exec(context, static_cast<Synth*>(synth));
|
||||
}
|
||||
|
||||
static void
|
||||
process(const Methcla_World* context, Methcla_Synth* synth, size_t numFrames)
|
||||
{
|
||||
static_cast<Synth*>(synth)->process(World<Synth>(context), numFrames);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy(const Methcla_World* context, Methcla_Synth* synth)
|
||||
{
|
||||
// Call cleanup method
|
||||
detail::IfSynthDefHasActivate<
|
||||
Synth,
|
||||
(Flags & kSynthDefHasCleanup) == kSynthDefHasCleanup
|
||||
>::exec(context, static_cast<Synth*>(synth));
|
||||
// Call destructor
|
||||
static_cast<Synth*>(synth)->~Synth();
|
||||
}
|
||||
|
||||
public:
|
||||
void operator()(const Methcla_Host* host, const char* uri)
|
||||
{
|
||||
static const Methcla_SynthDef kSynthDef =
|
||||
{
|
||||
uri,
|
||||
sizeof(Synth),
|
||||
sizeof(typename Options::Type),
|
||||
Options::configure,
|
||||
Options::port_descriptor,
|
||||
construct,
|
||||
connect,
|
||||
activate,
|
||||
process,
|
||||
destroy
|
||||
};
|
||||
methcla_host_register_synthdef(host, &kSynthDef);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Synth, class Options, class Ports, SynthDefFlags Flags=kSynthDefDefaultFlags>
|
||||
using StaticSynthDef
|
||||
= SynthDef<Synth, StaticSynthOptions<Options,Ports>, Ports, Flags>;
|
||||
} }
|
||||
|
||||
#endif // METHCLA_PLUGIN_HPP_INCLUDED
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_AMPLITUDE_FOLLOWER_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_AMPLITUDE_FOLLOWER_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_amplitude_follower(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_AMPLITUDE_FOLLOWER_URI METHCLA_PLUGINS_URI "/amplidute_follower"
|
||||
|
||||
#endif /* METHCLA_PLUGINS_AMPLITUDE_FOLLOWER_H_INCLUDED */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_DELAY_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_DELAY_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_delay(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_DELAY_URI METHCLA_PLUGINS_URI "/delay"
|
||||
|
||||
#endif /* METHCLA_PLUGINS_DELAY_H_INCLUDED */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_FFT_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_FFT_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_fft(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_FFT_URI METHCLA_PLUGINS_URI "/fft"
|
||||
|
||||
#endif /* METHCLA_PLUGINS_FFT_H_INCLUDED */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_HPF_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_HPF_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_hpf(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_HPF_URI METHCLA_PLUGINS_URI "/hpf"
|
||||
|
||||
#endif /* METHCLA_PLUGINS_HPF_H_INCLUDED */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_LPF_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_LPF_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_lpf(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_LPF_URI METHCLA_PLUGINS_URI "/lpf"
|
||||
|
||||
#endif /* METHCLA_PLUGINS_LPF_H_INCLUDED */
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright 2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_NODE_CONTROL_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_NODE_CONTROL_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_node_control(const Methcla_Host*, const char*);
|
||||
|
||||
#define METHCLA_PLUGINS_DONE_AFTER_URI METHCLA_PLUGINS_URI "/done-after"
|
||||
#define METHCLA_PLUGINS_ASR_ENVELOPE_URI METHCLA_PLUGINS_URI "/asr-envelope"
|
||||
|
||||
#endif // METHCLA_PLUGINS_NODE_CONTROL_H_INCLUDED
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_OSC_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_OSC_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_osc(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_OSC_URI METHCLA_PLUGINS_URI "/osc"
|
||||
|
||||
#endif /* METHCLA_PLUGINS_OSC_H_INCLUDED */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_PAN_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_PAN_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_pan(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_PAN_URI METHCLA_PLUGINS_URI "/pan"
|
||||
|
||||
#endif /* METHCLA_PLUGINS_PAN_H_INCLUDED */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_PAN2_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_PAN2_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_pan2(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_PAN2_URI METHCLA_PLUGINS_URI "/pan2"
|
||||
|
||||
#endif /* METHCLA_PLUGINS_PAN2_H_INCLUDED */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_PATCH_CABLE_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_PATCH_CABLE_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_patch_cable(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_PATCH_CABLE_URI METHCLA_PLUGINS_URI "/patch-cable"
|
||||
|
||||
#endif // METHCLA_PLUGINS_PATCH_CABLE_H_INCLUDED
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright 2012-2013 Samplecount S.L.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// See the file LICENSE-PRO for licensing details.
|
||||
|
||||
#ifndef METHCLA_PLUGINS_DISKSAMPLER_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_DISKSAMPLER_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
#define METHCLA_PLUGINS_DISKSAMPLER "methcla_plugins_disksampler"
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_disksampler(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_DISKSAMPLER_URI METHCLA_PLUGINS_URI "/disksampler"
|
||||
|
||||
#endif // METHCLA_PLUGINS_DISKSAMPLER_H_INCLUDED
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright 2012-2013 Samplecount S.L.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// See the file LICENSE-PRO for licensing details.
|
||||
|
||||
#ifndef METHCLA_SOUNDFILEAPI_EXTAUDIOFILE_H_INCLUDED
|
||||
#define METHCLA_SOUNDFILEAPI_EXTAUDIOFILE_H_INCLUDED
|
||||
|
||||
#include <methcla/file.h>
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_soundfile_api_extaudiofile(const Methcla_Host*, const char*);
|
||||
|
||||
#endif // METHCLA_SOUNDFILEAPI_EXTAUDIOFILE_H_INCLUDED
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_PULSE_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_PULSE_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_pulse(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_PULSE_URI METHCLA_PLUGINS_URI "/pulse"
|
||||
|
||||
#endif /* METHCLA_PLUGINS_PULSE_H_INCLUDED */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_SAMPLER_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_SAMPLER_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_sampler(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_SAMPLER_URI METHCLA_PLUGINS_URI "/sampler"
|
||||
|
||||
#endif /* METHCLA_PLUGINS_SAMPLER_H_INCLUDED */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_SAW_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_SAW_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_saw(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_SAW_URI METHCLA_PLUGINS_URI "/saw"
|
||||
|
||||
#endif /* METHCLA_PLUGINS_SAW_H_INCLUDED */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_SINE_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_SINE_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_sine(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_SINE_URI METHCLA_PLUGINS_URI "/sine"
|
||||
|
||||
#endif /* METHCLA_PLUGINS_SINE_H_INCLUDED */
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright 2013 Samplecount S.L.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef METHCLA_SOUNDFILEAPI_DUMMY_H_INCLUDED
|
||||
#define METHCLA_SOUNDFILEAPI_DUMMY_H_INCLUDED
|
||||
|
||||
#include <methcla/file.h>
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_soundfile_api_dummy(const Methcla_Host*, const char*);
|
||||
|
||||
#endif /* METHCLA_SOUNDFILEAPI_DUMMY_H_INCLUDED */
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright 2013 Samplecount S.L.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef METHCLA_SOUNDFILEAPI_LIBSNDFILE_H_INCLUDED
|
||||
#define METHCLA_SOUNDFILEAPI_LIBSNDFILE_H_INCLUDED
|
||||
|
||||
#include <methcla/file.h>
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_soundfile_api_libsndfile(const Methcla_Host*, const char*);
|
||||
|
||||
#endif /* METHCLA_SOUNDFILEAPI_LIBSNDFILE_H_INCLUDED */
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright 2013-2014 Samplecount S.L.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef METHCLA_SOUNDFILEAPI_MPG123_H_INCLUDED
|
||||
#define METHCLA_SOUNDFILEAPI_MPG123_H_INCLUDED
|
||||
|
||||
#include <methcla/file.h>
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_soundfile_api_mpg123(const Methcla_Host*, const char*);
|
||||
|
||||
#endif /* METHCLA_SOUNDFILEAPI_MPG123_H_INCLUDED */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_PLUGINS_TRI_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_TRI_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_tri(const Methcla_Host*, const char*);
|
||||
#define METHCLA_PLUGINS_TRI_URI METHCLA_PLUGINS_URI "/tri"
|
||||
|
||||
#endif /* METHCLA_PLUGINS_TRI_H_INCLUDED */
|
||||
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// whitenoise.h
|
||||
//
|
||||
//
|
||||
// Created by wirsing on 13.12.13.
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
#ifndef METHCLA_PLUGINS_WHITE_NOISE_H_INCLUDED
|
||||
#define METHCLA_PLUGINS_WHITE_NOISE_H_INCLUDED
|
||||
|
||||
#include <methcla/plugin.h>
|
||||
|
||||
METHCLA_EXPORT const Methcla_Library* methcla_plugins_white_noise(const Methcla_Host*, const char*);
|
||||
|
||||
#define METHCLA_PLUGINS_WHITE_NOISE_URI METHCLA_PLUGINS_URI "/white_noise"
|
||||
|
||||
#endif // METHCLA_PLUGINS_WHITE_NOISE_H_INCLUDED
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright 2012-2013 Samplecount S.L.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef METHCLA_TYPES_H_INCLUDED
|
||||
#define METHCLA_TYPES_H_INCLUDED
|
||||
|
||||
enum Methcla_NodePlacement
|
||||
{
|
||||
kMethcla_NodePlacementHeadOfGroup,
|
||||
kMethcla_NodePlacementTailOfGroup,
|
||||
kMethcla_NodePlacementBeforeNode,
|
||||
kMethcla_NodePlacementAfterNode
|
||||
};
|
||||
|
||||
enum Methcla_BusMappingFlags
|
||||
{
|
||||
kMethcla_BusMappingInternal = 0x00
|
||||
, kMethcla_BusMappingExternal = 0x01
|
||||
, kMethcla_BusMappingFeedback = 0x02
|
||||
, kMethcla_BusMappingReplace = 0x04
|
||||
};
|
||||
|
||||
enum Methcla_NodeDoneFlags
|
||||
{
|
||||
kMethcla_NodeDoneDoNothing = 0x00
|
||||
, kMethcla_NodeDoneFreeSelf = 0x01
|
||||
, kMethcla_NodeDoneFreePreceeding = 0x02
|
||||
, kMethcla_NodeDoneFreeFollowing = 0x04
|
||||
, kMethcla_NodeDoneFreeAllSiblings = 0x08
|
||||
, kMethcla_NodeDoneFreeParent = 0x10
|
||||
};
|
||||
|
||||
#endif /* METHCLA_TYPES_H_INCLUDED */
|
||||
@@ -0,0 +1,314 @@
|
||||
// oscpp library
|
||||
//
|
||||
// Copyright (c) 2004-2013 Stefan Kersten <sk@k-hornz.de>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef OSCPP_CLIENT_HPP_INCLUDED
|
||||
#define OSCPP_CLIENT_HPP_INCLUDED
|
||||
|
||||
#include <oscpp/detail/host.hpp>
|
||||
#include <oscpp/detail/stream.hpp>
|
||||
#include <oscpp/util.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
namespace OSCPP {
|
||||
namespace Client {
|
||||
|
||||
//! OSC packet construction.
|
||||
/*!
|
||||
* Construct a valid OSC packet for transmitting over a transport medium.
|
||||
*/
|
||||
class Packet
|
||||
{
|
||||
int32_t calcSize(const char* begin, const char* end)
|
||||
{
|
||||
// TODO: Make sure pointer difference fits into int32_t
|
||||
return end - begin - 4;
|
||||
}
|
||||
|
||||
public:
|
||||
//! Constructor.
|
||||
/*!
|
||||
*/
|
||||
Packet()
|
||||
{
|
||||
reset(0, 0);
|
||||
}
|
||||
|
||||
//! Constructor.
|
||||
/*!
|
||||
*/
|
||||
Packet(void* buffer, size_t size)
|
||||
{
|
||||
reset(buffer, size);
|
||||
}
|
||||
|
||||
//! Destructor.
|
||||
virtual ~Packet() { }
|
||||
|
||||
//! Get packet buffer address.
|
||||
/*!
|
||||
* Return the start address of the packet currently under construction.
|
||||
*/
|
||||
void* data() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
size_t capacity() const
|
||||
{
|
||||
return m_capacity;
|
||||
}
|
||||
|
||||
//! Get packet content size.
|
||||
/*!
|
||||
* Return the size of the packet currently under construction.
|
||||
*/
|
||||
size_t size() const
|
||||
{
|
||||
return m_args.consumed();
|
||||
}
|
||||
|
||||
//! Reset packet state.
|
||||
void reset(void* buffer, size_t size)
|
||||
{
|
||||
checkAlignment(&m_buffer, kAlignment);
|
||||
m_buffer = buffer;
|
||||
m_capacity = size;
|
||||
m_args = WriteStream(m_buffer, m_capacity);
|
||||
m_sizePosM = m_sizePosB = nullptr;
|
||||
m_inBundle = 0;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
reset(m_buffer, m_capacity);
|
||||
}
|
||||
|
||||
Packet& openBundle(uint64_t time)
|
||||
{
|
||||
if (m_inBundle > 0) {
|
||||
// Remember previous size pos offset
|
||||
// TODO: Make sure pointer difference fits into int32_t
|
||||
const int32_t offset = m_sizePosB - m_args.begin();
|
||||
char* curPos = m_args.pos();
|
||||
m_args.skip(4);
|
||||
// Record size pos
|
||||
std::memcpy(curPos, &offset, 4);
|
||||
m_sizePosB = curPos;
|
||||
} else if (m_args.pos() != m_args.begin()) {
|
||||
throw std::logic_error("Cannot open toplevel bundle in non-empty packet");
|
||||
}
|
||||
|
||||
m_inBundle++;
|
||||
m_args.putString("#bundle");
|
||||
m_args.putUInt64(time);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Packet& closeBundle()
|
||||
{
|
||||
if (m_inBundle > 0) {
|
||||
if (m_inBundle > 1) {
|
||||
// Get current stream pos
|
||||
char* curPos = m_args.pos();
|
||||
|
||||
// Get previous bundle size stream pos
|
||||
int32_t offset;
|
||||
memcpy(&offset, m_sizePosB, 4);
|
||||
// Get previous size pos
|
||||
char* prevPos = m_args.begin() + offset;
|
||||
|
||||
const int32_t bundleSize = calcSize(m_sizePosB, curPos);
|
||||
assert(bundleSize >= 0 && (size_t)bundleSize >= Size::bundle(0));
|
||||
// Write bundle size
|
||||
m_args.setPos(m_sizePosB);
|
||||
m_args.putInt32(bundleSize);
|
||||
m_args.setPos(curPos);
|
||||
|
||||
// record outer bundle size pos
|
||||
m_sizePosB = prevPos;
|
||||
}
|
||||
m_inBundle--;
|
||||
} else {
|
||||
throw std::logic_error("closeBundle() without matching openBundle()");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Packet& openMessage(const char* addr, size_t numTags)
|
||||
{
|
||||
if (m_inBundle > 0) {
|
||||
// record message size pos
|
||||
m_sizePosM = m_args.pos();
|
||||
// advance arg stream
|
||||
m_args.skip(4);
|
||||
}
|
||||
m_args.putString(addr);
|
||||
size_t sigLen = numTags + 2;
|
||||
m_tags = WriteStream(m_args, sigLen);
|
||||
m_args.zero(align(sigLen));
|
||||
m_tags.putChar(',');
|
||||
return *this;
|
||||
}
|
||||
|
||||
Packet& closeMessage()
|
||||
{
|
||||
if (m_inBundle > 0) {
|
||||
// Get current stream pos
|
||||
char* curPos = m_args.pos();
|
||||
// write message size
|
||||
m_args.setPos(m_sizePosM);
|
||||
m_args.putInt32(calcSize(m_sizePosM, curPos));
|
||||
// restore stream pos
|
||||
m_args.setPos(curPos);
|
||||
// reset tag stream
|
||||
m_tags = WriteStream();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Write integer message argument.
|
||||
/*!
|
||||
* Write a 32 bit integer message argument.
|
||||
*
|
||||
* \param arg 32 bit integer argument.
|
||||
*
|
||||
* \pre openMessage must have been called before with no intervening
|
||||
* closeMessage.
|
||||
*
|
||||
* \throw OSCPP::XRunError stream buffer xrun.
|
||||
*/
|
||||
Packet& int32(int32_t arg)
|
||||
{
|
||||
m_tags.putChar('i');
|
||||
m_args.putInt32(arg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Packet& float32(float arg)
|
||||
{
|
||||
m_tags.putChar('f');
|
||||
m_args.putFloat32(arg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Packet& string(const char* arg)
|
||||
{
|
||||
m_tags.putChar('s');
|
||||
m_args.putString(arg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// @throw std::invalid_argument if blob size is greater than std::numeric_limits<int32_t>::max()
|
||||
Packet& blob(const Blob& arg)
|
||||
{
|
||||
if (arg.size() > (size_t)std::numeric_limits<int32_t>::max())
|
||||
throw std::invalid_argument("Blob size greater than maximum value representable by int32_t");
|
||||
m_tags.putChar('b');
|
||||
m_args.putInt32(arg.size());
|
||||
m_args.putData(arg.data(), arg.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Packet& openArray()
|
||||
{
|
||||
m_tags.putChar('[');
|
||||
return *this;
|
||||
}
|
||||
|
||||
Packet& closeArray()
|
||||
{
|
||||
m_tags.putChar(']');
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T> Packet& put(T)
|
||||
{
|
||||
T::OSC_Client_Packet_put_unimplemented;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename InputIterator> Packet& put(InputIterator begin, InputIterator end)
|
||||
{
|
||||
for (auto it = begin; it != end; it++) {
|
||||
put(*it);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename InputIterator> Packet& putArray(InputIterator begin, InputIterator end)
|
||||
{
|
||||
openArray();
|
||||
put<InputIterator>(begin, end);
|
||||
closeArray();
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void* m_buffer;
|
||||
size_t m_capacity;
|
||||
WriteStream m_args; // packet stream
|
||||
WriteStream m_tags; // current tag stream
|
||||
char* m_sizePosM; // last message size position
|
||||
char* m_sizePosB; // last bundle size position
|
||||
size_t m_inBundle; // bundle nesting depth
|
||||
};
|
||||
|
||||
template <> inline Packet& Packet::put<int32_t>(int32_t x) { return int32(x); }
|
||||
template <> inline Packet& Packet::put<float>(float x) { return float32(x); }
|
||||
template <> inline Packet& Packet::put<const char*>(const char* x) { return string(x); }
|
||||
template <> inline Packet& Packet::put<Blob>(Blob x) { return blob(x); }
|
||||
|
||||
template <size_t buffer_size> class StaticPacket : public Packet
|
||||
{
|
||||
public:
|
||||
StaticPacket()
|
||||
: Packet(reinterpret_cast<char*>(&m_buffer), buffer_size)
|
||||
{ }
|
||||
|
||||
private:
|
||||
typedef typename std::aligned_storage<buffer_size,kAlignment>::type AlignedBuffer;
|
||||
AlignedBuffer m_buffer;
|
||||
};
|
||||
|
||||
class DynamicPacket : public Packet
|
||||
{
|
||||
public:
|
||||
DynamicPacket(size_t buffer_size)
|
||||
: Packet(static_cast<char*>(new char[buffer_size]), buffer_size)
|
||||
{ }
|
||||
|
||||
~DynamicPacket()
|
||||
{
|
||||
delete [] static_cast<char*>(data());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OSCPP_CLIENT_HPP_INCLUDED
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright 2005 Caleb Epstein
|
||||
// Copyright 2006 John Maddock
|
||||
// Copyright 2010 Rene Rivera
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompany-
|
||||
// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright notice reproduced from <boost/detail/limits.hpp>, from
|
||||
* which this code was originally taken.
|
||||
*
|
||||
* Modified by Caleb Epstein to use <endian.h> with GNU libc and to
|
||||
* defined the BOOST_ENDIAN macro.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modifications for oscpp by Stefan Kersten
|
||||
* - Change prefix from BOOST to OSCPP
|
||||
* - Remove PDP endianness
|
||||
* - Add OSCPP_BYTE_ORDER_* macros
|
||||
*/
|
||||
|
||||
#ifndef OSCPP_ENDIAN_HPP_INCLUDED
|
||||
#define OSCPP_ENDIAN_HPP_INCLUDED
|
||||
|
||||
#define OSCPP_BYTE_ORDER_BIG_ENDIAN 4321
|
||||
#define OSCPP_BYTE_ORDER_LITTLE_ENDIAN 1234
|
||||
|
||||
// GNU libc offers the helpful header <endian.h> which defines
|
||||
// __BYTE_ORDER
|
||||
|
||||
#if defined (__GLIBC__) || defined(__ANDROID__)
|
||||
# include <endian.h>
|
||||
# if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
# define OSCPP_LITTLE_ENDIAN
|
||||
# elif (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
# define OSCPP_BIG_ENDIAN
|
||||
# else
|
||||
# error Unknown machine endianness detected.
|
||||
# endif
|
||||
# define OSCPP_BYTE_ORDER __BYTE_ORDER
|
||||
#elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) || \
|
||||
defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) || \
|
||||
defined(_STLP_BIG_ENDIAN) && !defined(_STLP_LITTLE_ENDIAN)
|
||||
# define OSCPP_BIG_ENDIAN
|
||||
# define OSCPP_BYTE_ORDER OSCPP_BYTE_ORDER_BIG_ENDIAN
|
||||
#elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) || \
|
||||
defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) || \
|
||||
defined(_STLP_LITTLE_ENDIAN) && !defined(_STLP_BIG_ENDIAN)
|
||||
# define OSCPP_LITTLE_ENDIAN
|
||||
# define OSCPP_BYTE_ORDER OSCPP_BYTE_ORDER_LITTLE_ENDIAN
|
||||
#elif defined(__sparc) || defined(__sparc__) \
|
||||
|| defined(_POWER) || defined(__powerpc__) \
|
||||
|| defined(__ppc__) || defined(__hpux) || defined(__hppa) \
|
||||
|| defined(_MIPSEB) || defined(_POWER) \
|
||||
|| defined(__s390__)
|
||||
# define OSCPP_BIG_ENDIAN
|
||||
# define OSCPP_BYTE_ORDER OSCPP_BYTE_ORDER_BIG_ENDIAN
|
||||
#elif defined(__i386__) || defined(__alpha__) \
|
||||
|| defined(__ia64) || defined(__ia64__) \
|
||||
|| defined(_M_IX86) || defined(_M_IA64) \
|
||||
|| defined(_M_ALPHA) || defined(__amd64) \
|
||||
|| defined(__amd64__) || defined(_M_AMD64) \
|
||||
|| defined(__x86_64) || defined(__x86_64__) \
|
||||
|| defined(_M_X64) || defined(__bfin__)
|
||||
|
||||
# define OSCPP_LITTLE_ENDIAN
|
||||
# define OSCPP_BYTE_ORDER OSCPP_BYTE_ORDER_LITTLE_ENDIAN
|
||||
#else
|
||||
# error The file oscpp/endian.hpp needs to be set up for your CPU type.
|
||||
#endif
|
||||
|
||||
#endif // OSCPP_ENDIAN_HPP_INCLUDED
|
||||
@@ -0,0 +1,118 @@
|
||||
// oscpp library
|
||||
//
|
||||
// Copyright (c) 2004-2013 Stefan Kersten <sk@k-hornz.de>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef OSCPP_HOST_HPP_INCLUDED
|
||||
#define OSCPP_HOST_HPP_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
#include <oscpp/detail/endian.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace OSCPP
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
inline static uint32_t bswap32(uint32_t x)
|
||||
{
|
||||
return __builtin_bswap32(x);
|
||||
}
|
||||
inline static uint64_t bswap64(uint64_t x)
|
||||
{
|
||||
return __builtin_bswap64(x);
|
||||
}
|
||||
#elif defined(_WINDOWS_)
|
||||
# include <stdlib.h>
|
||||
inline static uint32_t bswap32(uint32_t x)
|
||||
{
|
||||
return _byteswap_ulong(x);
|
||||
}
|
||||
inline static uint64_t bswap64(uint64_t x)
|
||||
{
|
||||
return _byteswap_uint64(x);
|
||||
}
|
||||
#else
|
||||
// Fallback implementation
|
||||
# warning Using unoptimized byte swap functions
|
||||
|
||||
inline static uint32_t bswap32(uint32_t x)
|
||||
{
|
||||
const uint32_t b1 = x << 24;
|
||||
const uint32_t b2 = (x & 0x0000FF00) << 8;
|
||||
const uint32_t b3 = (x & 0x00FF0000) >> 8;
|
||||
const uint32_t b4 = x >> 24;
|
||||
return b1 | b2 | b3 | b4;
|
||||
}
|
||||
inline static uint64_t bswap64(int64_t x)
|
||||
{
|
||||
const uint64_t w1 = oscpp_bswap(uint32_t(x & 0x00000000FFFFFFFF)) << 32;
|
||||
const uint64_t w2 = oscpp_bswap(uint32_t(x >> 32));
|
||||
return w1 | w2;
|
||||
}
|
||||
#endif
|
||||
|
||||
enum ByteOrder
|
||||
{
|
||||
NetworkByteOrder,
|
||||
HostByteOrder
|
||||
};
|
||||
|
||||
template<ByteOrder B> inline uint32_t convert32(uint32_t)
|
||||
{
|
||||
throw std::logic_error("Invalid byte order");
|
||||
}
|
||||
|
||||
template<> inline uint32_t convert32<NetworkByteOrder>(uint32_t x)
|
||||
{
|
||||
#if defined(OSCPP_LITTLE_ENDIAN)
|
||||
return bswap32(x);
|
||||
#else
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> inline uint32_t convert32<HostByteOrder>(uint32_t x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
template<ByteOrder B> inline uint64_t convert64(uint64_t)
|
||||
{
|
||||
throw std::logic_error("Invalid byte order");
|
||||
}
|
||||
|
||||
template<> inline uint64_t convert64<NetworkByteOrder>(uint64_t x)
|
||||
{
|
||||
#if defined(OSCPP_LITTLE_ENDIAN)
|
||||
return bswap64(x);
|
||||
#else
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> inline uint64_t convert64<HostByteOrder>(uint64_t x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OSCPP_HOST_HPP_INCLUDED
|
||||
@@ -0,0 +1,346 @@
|
||||
// oscpp library
|
||||
//
|
||||
// Copyright (c) 2004-2013 Stefan Kersten <sk@k-hornz.de>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef OSCPP_STREAM_HPP_INCLUDED
|
||||
#define OSCPP_STREAM_HPP_INCLUDED
|
||||
|
||||
#include <oscpp/error.hpp>
|
||||
#include <oscpp/detail/host.hpp>
|
||||
#include <oscpp/types.hpp>
|
||||
#include <oscpp/util.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace OSCPP {
|
||||
|
||||
class Stream
|
||||
{
|
||||
public:
|
||||
Stream()
|
||||
{
|
||||
m_begin = m_end = m_pos = 0;
|
||||
}
|
||||
|
||||
Stream(void* data, size_t size)
|
||||
{
|
||||
m_begin = static_cast<char*>(data);
|
||||
m_end = m_begin + size;
|
||||
m_pos = m_begin;
|
||||
}
|
||||
|
||||
Stream(const Stream& stream)
|
||||
{
|
||||
m_begin = m_pos = stream.m_pos;
|
||||
m_end = stream.m_end;
|
||||
}
|
||||
|
||||
Stream(const Stream& stream, size_t size)
|
||||
{
|
||||
m_begin = m_pos = stream.m_pos;
|
||||
m_end = m_begin + size;
|
||||
if (m_end > stream.m_end) throw UnderrunError();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_pos = m_begin;
|
||||
}
|
||||
|
||||
const char* begin() const
|
||||
{
|
||||
return m_begin;
|
||||
}
|
||||
|
||||
char* begin()
|
||||
{
|
||||
return m_begin;
|
||||
}
|
||||
|
||||
const char* end() const
|
||||
{
|
||||
return m_end;
|
||||
}
|
||||
|
||||
size_t capacity() const
|
||||
{
|
||||
return end() - begin();
|
||||
}
|
||||
|
||||
const char* pos() const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
char* pos()
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
void setPos(char* pos)
|
||||
{
|
||||
assert((pos >= m_begin) && (pos <= m_end));
|
||||
m_pos = pos;
|
||||
}
|
||||
|
||||
void advance(size_t n)
|
||||
{
|
||||
m_pos += n;
|
||||
}
|
||||
|
||||
bool atEnd() const
|
||||
{
|
||||
return pos() == end();
|
||||
}
|
||||
|
||||
size_t consumed() const
|
||||
{
|
||||
return pos() - begin();
|
||||
}
|
||||
|
||||
size_t consumable() const
|
||||
{
|
||||
return end() - pos();
|
||||
}
|
||||
|
||||
inline void checkAlignment(size_t n) const
|
||||
{
|
||||
OSCPP::checkAlignment(pos(), n);
|
||||
}
|
||||
|
||||
protected:
|
||||
char* m_begin;
|
||||
char* m_end;
|
||||
char* m_pos;
|
||||
};
|
||||
|
||||
class WriteStream: public Stream
|
||||
{
|
||||
public:
|
||||
WriteStream()
|
||||
: Stream()
|
||||
{ }
|
||||
|
||||
WriteStream(void* data, size_t size)
|
||||
: Stream(data, size)
|
||||
{ }
|
||||
|
||||
WriteStream(const WriteStream& stream)
|
||||
: Stream(stream)
|
||||
{ }
|
||||
|
||||
WriteStream(const WriteStream& stream, size_t size)
|
||||
: Stream(stream, size)
|
||||
{ }
|
||||
|
||||
// throw (OverflowError)
|
||||
inline void checkWritable(size_t n) const
|
||||
{
|
||||
if (consumable() < n)
|
||||
throw OverflowError(n - consumable());
|
||||
}
|
||||
|
||||
void skip(size_t n)
|
||||
{
|
||||
checkWritable(n);
|
||||
advance(n);
|
||||
}
|
||||
|
||||
void zero(size_t n)
|
||||
{
|
||||
checkWritable(n);
|
||||
std::memset(m_pos, 0, n);
|
||||
advance(n);
|
||||
}
|
||||
|
||||
void putChar(char c)
|
||||
{
|
||||
checkWritable(1);
|
||||
*pos() = c;
|
||||
advance(1);
|
||||
}
|
||||
|
||||
void putInt32(int32_t x)
|
||||
{
|
||||
checkWritable(4);
|
||||
checkAlignment(4);
|
||||
uint32_t uh;
|
||||
memcpy(&uh, &x, 4);
|
||||
const uint32_t un = convert32<NetworkByteOrder>(uh);
|
||||
std::memcpy(pos(), &un, 4);
|
||||
advance(4);
|
||||
}
|
||||
|
||||
void putUInt64(uint64_t x)
|
||||
{
|
||||
checkWritable(8);
|
||||
const uint64_t un = convert64<NetworkByteOrder>(x);
|
||||
std::memcpy(pos(), &un, 8);
|
||||
advance(8);
|
||||
}
|
||||
|
||||
void putFloat32(float f)
|
||||
{
|
||||
checkWritable(4);
|
||||
checkAlignment(4);
|
||||
uint32_t uh;
|
||||
std::memcpy(&uh, &f, 4);
|
||||
const uint32_t un = convert32<NetworkByteOrder>(uh);
|
||||
std::memcpy(pos(), &un, 4);
|
||||
advance(4);
|
||||
}
|
||||
|
||||
void putData(const void* data, size_t size)
|
||||
{
|
||||
const size_t padding = OSCPP::padding(size);
|
||||
const size_t n = size + padding;
|
||||
checkWritable(n);
|
||||
std::memcpy(pos(), data, size);
|
||||
std::memset(pos()+size, 0, padding);
|
||||
advance(n);
|
||||
}
|
||||
|
||||
void putString(const char* s)
|
||||
{
|
||||
putData(s, strlen(s)+1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ReadStream : public Stream
|
||||
{
|
||||
public:
|
||||
ReadStream()
|
||||
{ }
|
||||
|
||||
ReadStream(const void* data, size_t size)
|
||||
: Stream(const_cast<void*>(data), size)
|
||||
{ }
|
||||
|
||||
ReadStream(const ReadStream& stream)
|
||||
: Stream(stream)
|
||||
{ }
|
||||
|
||||
ReadStream(const ReadStream& stream, size_t size)
|
||||
: Stream(stream, size)
|
||||
{ }
|
||||
|
||||
// throw (UnderrunError)
|
||||
void checkReadable(size_t n) const
|
||||
{
|
||||
if (consumable() < n) throw UnderrunError();
|
||||
}
|
||||
|
||||
// throw (UnderrunError)
|
||||
void skip(size_t n)
|
||||
{
|
||||
checkReadable(n);
|
||||
advance(n);
|
||||
}
|
||||
|
||||
// throw (UnderrunError)
|
||||
inline char peekChar() const
|
||||
{
|
||||
checkReadable(1);
|
||||
return *pos();
|
||||
}
|
||||
|
||||
// throw (UnderrunError)
|
||||
inline char getChar()
|
||||
{
|
||||
const char x = peekChar();
|
||||
advance(1);
|
||||
return x;
|
||||
}
|
||||
|
||||
// throw (UnderrunError)
|
||||
inline int32_t peekInt32() const
|
||||
{
|
||||
checkReadable(4);
|
||||
checkAlignment(4);
|
||||
uint32_t un;
|
||||
std::memcpy(&un, pos(), 4);
|
||||
const uint32_t uh = convert32<NetworkByteOrder>(un);
|
||||
int32_t x;
|
||||
std::memcpy(&x, &uh, 4);
|
||||
return x;
|
||||
}
|
||||
|
||||
// throw (UnderrunError)
|
||||
inline int32_t getInt32()
|
||||
{
|
||||
const int32_t x = peekInt32();
|
||||
advance(4);
|
||||
return x;
|
||||
}
|
||||
|
||||
// throw (UnderrunError)
|
||||
inline uint64_t getUInt64()
|
||||
{
|
||||
checkReadable(8);
|
||||
uint64_t un;
|
||||
std::memcpy(&un, pos(), 8);
|
||||
advance(8);
|
||||
return convert64<NetworkByteOrder>(un);
|
||||
}
|
||||
|
||||
// throw (UnderrunError)
|
||||
inline float getFloat32()
|
||||
{
|
||||
checkReadable(4);
|
||||
checkAlignment(4);
|
||||
uint32_t un;
|
||||
std::memcpy(&un, pos(), 4);
|
||||
advance(4);
|
||||
const uint32_t uh = convert32<NetworkByteOrder>(un);
|
||||
float f;
|
||||
std::memcpy(&f, &uh, 4);
|
||||
return f;
|
||||
}
|
||||
|
||||
// throw (UnderrunError, ParseError)
|
||||
const char* getString()
|
||||
{
|
||||
checkReadable(4); // min string length
|
||||
|
||||
const char* ptr = static_cast<const char*>(pos()) + 3;
|
||||
const char* end = static_cast<const char*>(this->end());
|
||||
|
||||
while (true) {
|
||||
if (ptr >= end) throw UnderrunError();
|
||||
if (*ptr == '\0') break;
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
const char* x = pos();
|
||||
advance(ptr - pos() + 1);
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // OSCPP_STREAM_HPP_INCLUDED
|
||||
@@ -0,0 +1,84 @@
|
||||
// oscpp library
|
||||
//
|
||||
// Copyright (c) 2004-2013 Stefan Kersten <sk@k-hornz.de>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef OSCPP_ERROR_HPP_INCLUDED
|
||||
#define OSCPP_ERROR_HPP_INCLUDED
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
namespace OSCPP {
|
||||
|
||||
class Error : public std::exception
|
||||
{
|
||||
public:
|
||||
Error(const std::string& what)
|
||||
: m_what(what)
|
||||
{ }
|
||||
|
||||
virtual ~Error() noexcept
|
||||
{ }
|
||||
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return m_what.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_what;
|
||||
};
|
||||
|
||||
class UnderrunError : public Error
|
||||
{
|
||||
public:
|
||||
UnderrunError()
|
||||
: Error(std::string("Buffer underrun"))
|
||||
{ }
|
||||
};
|
||||
|
||||
class OverflowError : public Error
|
||||
{
|
||||
public:
|
||||
OverflowError(size_t bytes)
|
||||
: Error(std::string("Buffer overflow")),
|
||||
m_bytes(bytes)
|
||||
{ }
|
||||
|
||||
size_t numBytes() const { return m_bytes; }
|
||||
|
||||
private:
|
||||
size_t m_bytes;
|
||||
};
|
||||
|
||||
class ParseError : public Error
|
||||
{
|
||||
public:
|
||||
ParseError(const std::string& what="Parse error")
|
||||
: Error(what)
|
||||
{ }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OSCPP_ERROR_HPP_INCLUDED
|
||||
@@ -0,0 +1,166 @@
|
||||
// OSCpp library
|
||||
//
|
||||
// Copyright (c) 2004-2011 Stefan Kersten <sk@k-hornz.de>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef OSCPP_PRINT_HPP_INCLUDED
|
||||
#define OSCPP_PRINT_HPP_INCLUDED
|
||||
|
||||
#include <oscpp/client.hpp>
|
||||
#include <oscpp/server.hpp>
|
||||
#include <ostream>
|
||||
|
||||
namespace OSCPP {
|
||||
namespace detail {
|
||||
|
||||
const size_t kDefaultIndentWidth = 4;
|
||||
|
||||
class Indent
|
||||
{
|
||||
public:
|
||||
Indent(size_t w)
|
||||
: m_width(w)
|
||||
, m_indent(0)
|
||||
{ }
|
||||
Indent(size_t w, size_t n)
|
||||
: m_width(w)
|
||||
, m_indent(n)
|
||||
{ }
|
||||
Indent(const Indent&) = default;
|
||||
|
||||
operator size_t () const { return m_indent; }
|
||||
Indent inc() const { return Indent(m_width, m_indent+m_width); }
|
||||
|
||||
private:
|
||||
size_t m_width;
|
||||
size_t m_indent;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const Indent& indent)
|
||||
{
|
||||
size_t n = indent;
|
||||
while (n-- > 0) out << ' ';
|
||||
return out;
|
||||
}
|
||||
|
||||
inline void printArgs(std::ostream& out, Server::ArgStream args)
|
||||
{
|
||||
while (!args.atEnd()) {
|
||||
const char t = args.tag();
|
||||
switch (t) {
|
||||
case 'i':
|
||||
out << "i:" << args.int32();
|
||||
break;
|
||||
case 'f':
|
||||
out << "f:" << args.float32();
|
||||
break;
|
||||
case 's':
|
||||
out << "s:" << args.string();
|
||||
break;
|
||||
case 'b':
|
||||
out << "b:" << args.blob().size();
|
||||
break;
|
||||
case '[':
|
||||
out << "[ ";
|
||||
printArgs(out, args.array());
|
||||
out << " ]";
|
||||
break;
|
||||
default:
|
||||
out << t << ":?";
|
||||
args.drop();
|
||||
break;
|
||||
}
|
||||
out << ' ';
|
||||
}
|
||||
}
|
||||
|
||||
inline void printMessage(std::ostream& out, const Server::Message& msg, const Indent& indent)
|
||||
{
|
||||
out << indent << msg.address() << ' ';
|
||||
printArgs(out, msg.args());
|
||||
}
|
||||
|
||||
inline void printBundle(std::ostream& out, const Server::Bundle& bundle, const Indent& indent)
|
||||
{
|
||||
out << indent << "# " << bundle.time() << " [" << std::endl;
|
||||
Indent nextIndent = indent.inc();
|
||||
auto packets = bundle.packets();
|
||||
while (!packets.atEnd()) {
|
||||
auto packet = packets.next();
|
||||
if (packet.isMessage()) {
|
||||
printMessage(out, packet, nextIndent);
|
||||
} else {
|
||||
printBundle(out, packet, nextIndent);
|
||||
}
|
||||
out << std::endl;
|
||||
}
|
||||
out << indent << "]";
|
||||
}
|
||||
|
||||
inline void printPacket(std::ostream& out, const Server::Packet& packet, const Indent& indent)
|
||||
{
|
||||
if (packet.isMessage()) {
|
||||
printMessage(out, packet, indent);
|
||||
} else {
|
||||
printBundle(out, packet, indent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace OSCPP {
|
||||
namespace Server {
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const Packet& packet)
|
||||
{
|
||||
detail::printPacket(out, packet, detail::Indent(detail::kDefaultIndentWidth));
|
||||
return out;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const Bundle& packet)
|
||||
{
|
||||
detail::printBundle(out, packet, detail::Indent(detail::kDefaultIndentWidth));
|
||||
return out;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const Message& packet)
|
||||
{
|
||||
detail::printMessage(out, packet, detail::Indent(detail::kDefaultIndentWidth));
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace OSCPP {
|
||||
namespace Client {
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const Packet& packet)
|
||||
{
|
||||
return out << Server::Packet(packet.data(), packet.size());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OSCPP_PRINT_HPP_INCLUDED
|
||||
@@ -0,0 +1,450 @@
|
||||
// oscpp library
|
||||
//
|
||||
// Copyright (c) 2004-2013 Stefan Kersten <sk@k-hornz.de>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef OSCPP_SERVER_HPP_INCLUDED
|
||||
#define OSCPP_SERVER_HPP_INCLUDED
|
||||
|
||||
#include <oscpp/detail/stream.hpp>
|
||||
#include <oscpp/util.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace OSCPP {
|
||||
namespace Server {
|
||||
|
||||
//! OSC Message Argument Iterator.
|
||||
/*!
|
||||
* Retrieve typed arguments from an incoming message.
|
||||
*
|
||||
* Supported tags and their correspondong types are:
|
||||
*
|
||||
* i -- 32 bit signed integer number<br>
|
||||
* f -- 32 bit floating point number<br>
|
||||
* s -- NULL-terminated string padded to 4-byte boundary<br>
|
||||
* b -- 32-bit integer size followed by 4-byte aligned data
|
||||
*
|
||||
* \sa getArgInt32
|
||||
* \sa getArgFloat32
|
||||
* \sa getArgString
|
||||
*/
|
||||
class ArgStream
|
||||
{
|
||||
public:
|
||||
//* Empty argument stream.
|
||||
ArgStream() = default;
|
||||
|
||||
//* Construct argument stream from tag and value streams.
|
||||
ArgStream(const ReadStream& tags, const ReadStream& args)
|
||||
: m_tags(tags)
|
||||
, m_args(args)
|
||||
{ }
|
||||
|
||||
//! Constructor.
|
||||
/*!
|
||||
* Read arguments from stream, which has to point to the start of a
|
||||
* message type signature.
|
||||
*
|
||||
* \throw OSCPP::UnderrunError stream buffer underrun.
|
||||
* \throw OSCPP::ParseError error while parsing input stream.
|
||||
*/
|
||||
ArgStream(const ReadStream& stream)
|
||||
{
|
||||
m_args = stream;
|
||||
const char* tags = m_args.getString();
|
||||
if (tags[0] != ',') throw ParseError("Tag string doesn't start with ','");
|
||||
m_tags = ReadStream(tags+1, strlen(tags)-1);
|
||||
}
|
||||
|
||||
//* Return the number of arguments that can be read from the stream.
|
||||
size_t size() const
|
||||
{
|
||||
return m_tags.capacity();
|
||||
}
|
||||
|
||||
//* Return true if no more arguments can be read from the stream.
|
||||
bool atEnd() const
|
||||
{
|
||||
return m_tags.atEnd();
|
||||
}
|
||||
|
||||
//* Return tag and argument streams.
|
||||
std::tuple<ReadStream,ReadStream> state() const
|
||||
{
|
||||
return std::make_tuple(m_tags, m_args);
|
||||
}
|
||||
|
||||
//* Return the type tag corresponding to the next message argument.
|
||||
char tag() const
|
||||
{
|
||||
return m_tags.peekChar();
|
||||
}
|
||||
|
||||
//* Drop next argument.
|
||||
void drop()
|
||||
{
|
||||
drop(m_tags.getChar());
|
||||
}
|
||||
|
||||
//! Get next integer argument.
|
||||
/*!
|
||||
* Read next numerical argument from the input stream and convert it to
|
||||
* an integer.
|
||||
*
|
||||
* \exception OSCPP::UnderrunError stream buffer underrun.
|
||||
* \exception OSCPP::ParseError argument could not be converted.
|
||||
*/
|
||||
int32_t int32()
|
||||
{
|
||||
const char t = m_tags.getChar();
|
||||
if (t == 'i') return m_args.getInt32();
|
||||
if (t == 'f') return (int32_t)m_args.getFloat32();
|
||||
throw ParseError("Cannot convert argument to int");
|
||||
}
|
||||
|
||||
//! Get next float argument.
|
||||
/*!
|
||||
* Read next numerical argument from the input stream and convert it to
|
||||
* a float.
|
||||
*
|
||||
* \exception OSCPP::UnderrunError stream buffer underrun.
|
||||
* \exception OSCPP::ParseError argument could not be converted.
|
||||
*/
|
||||
float float32()
|
||||
{
|
||||
const char t = m_tags.getChar();
|
||||
if (t == 'f') return m_args.getFloat32();
|
||||
if (t == 'i') return (float)m_args.getInt32();
|
||||
throw ParseError("Cannot convert argument to float");
|
||||
}
|
||||
|
||||
//! Get next string argument.
|
||||
/*!
|
||||
* Read next string argument and return it as a NULL-terminated string.
|
||||
*
|
||||
* \exception OSCPP::UnderrunError stream buffer underrun.
|
||||
* \exception OSCPP::ParseError argument could not be converted or is not
|
||||
* a valid string.
|
||||
*/
|
||||
const char* string()
|
||||
{
|
||||
if (m_tags.getChar() == 's') {
|
||||
return m_args.getString();
|
||||
}
|
||||
throw ParseError("Cannot convert argument to string");
|
||||
}
|
||||
|
||||
//* Get next blob argument.
|
||||
//
|
||||
// @throw OSCPP::UnderrunError stream buffer underrun.
|
||||
// @throw OSCPP::ParseError argument is not a valid blob
|
||||
Blob blob()
|
||||
{
|
||||
if (m_tags.getChar() == 'b') {
|
||||
return parseBlob();
|
||||
} else {
|
||||
throw ParseError("Cannot convert argument to blob");
|
||||
}
|
||||
}
|
||||
|
||||
//* Return a stream corresponding to an array argument.
|
||||
ArgStream array()
|
||||
{
|
||||
if (m_tags.getChar() == '[') {
|
||||
const char* tags = m_tags.pos();
|
||||
const char* args = m_args.pos();
|
||||
dropArray();
|
||||
// m_tags.pos() points right after the closing ']'.
|
||||
return ArgStream(ReadStream(tags, m_tags.pos() - tags - 1),
|
||||
ReadStream(args, m_args.pos() - args));
|
||||
} else {
|
||||
throw ParseError("Expected array");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> T next()
|
||||
{
|
||||
return T::OSC_Server_ArgStream_next_unimplemented;
|
||||
}
|
||||
|
||||
private:
|
||||
// Parse a blob (type tag already consumed).
|
||||
Blob parseBlob()
|
||||
{
|
||||
int32_t size = m_args.getInt32();
|
||||
if (size < 0) {
|
||||
throw ParseError("Invalid blob size is less than zero");
|
||||
} else {
|
||||
static_assert(sizeof(size_t) >= sizeof(int32_t),
|
||||
"Size of size_t must be greater than size of int32_t");
|
||||
const void* data = m_args.pos();
|
||||
m_args.skip(align(size));
|
||||
return Blob(data, static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
// Drop an atomic value of type t (type tag already consumed).
|
||||
void dropAtom(char t)
|
||||
{
|
||||
switch (t) {
|
||||
case 'i': m_args.skip(4); break;
|
||||
case 'f': m_args.skip(4); break;
|
||||
case 's': m_args.getString(); break;
|
||||
case 'b': parseBlob(); break;
|
||||
}
|
||||
}
|
||||
// Drop a possibly nested array.
|
||||
void dropArray()
|
||||
{
|
||||
unsigned int level = 0;
|
||||
for (;;) {
|
||||
char t = m_tags.getChar();
|
||||
if (t == ']') {
|
||||
if (level == 0) break;
|
||||
else level--;
|
||||
} else if (t == '[') {
|
||||
level++;
|
||||
} else {
|
||||
dropAtom(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Drop the next argument of type t (type tag already consumed).
|
||||
void drop(char t)
|
||||
{
|
||||
switch (t) {
|
||||
case '[': dropArray(); break;
|
||||
default: dropAtom(t);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ReadStream m_tags;
|
||||
ReadStream m_args;
|
||||
};
|
||||
|
||||
class Message
|
||||
{
|
||||
public:
|
||||
Message(const char* address, const ReadStream& stream)
|
||||
: m_address(address)
|
||||
, m_args(ArgStream(stream))
|
||||
{ }
|
||||
|
||||
const char* address() const
|
||||
{
|
||||
return m_address;
|
||||
}
|
||||
|
||||
ArgStream args() const
|
||||
{
|
||||
return m_args;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* m_address;
|
||||
ArgStream m_args;
|
||||
};
|
||||
|
||||
class PacketStream;
|
||||
|
||||
class Bundle
|
||||
{
|
||||
public:
|
||||
Bundle(uint64_t time, const ReadStream& stream)
|
||||
: m_time(time)
|
||||
, m_stream(stream)
|
||||
{ }
|
||||
|
||||
uint64_t time() const
|
||||
{
|
||||
return m_time;
|
||||
}
|
||||
|
||||
inline PacketStream packets() const;
|
||||
|
||||
private:
|
||||
uint64_t m_time;
|
||||
ReadStream m_stream;
|
||||
};
|
||||
|
||||
class Packet
|
||||
{
|
||||
public:
|
||||
Packet()
|
||||
: m_isBundle(false)
|
||||
{ }
|
||||
|
||||
Packet(const ReadStream& stream)
|
||||
: m_stream(stream)
|
||||
, m_isBundle(isBundle(stream))
|
||||
{
|
||||
// Skip over #bundle header
|
||||
if (m_isBundle) m_stream.skip(8);
|
||||
}
|
||||
|
||||
Packet(const void* data, size_t size)
|
||||
: Packet(ReadStream(data, size))
|
||||
{ }
|
||||
|
||||
const void* data() const
|
||||
{
|
||||
return m_stream.begin();
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return m_stream.capacity();
|
||||
}
|
||||
|
||||
bool isBundle() const
|
||||
{
|
||||
return m_isBundle;
|
||||
}
|
||||
|
||||
bool isMessage() const
|
||||
{
|
||||
return !isBundle();
|
||||
}
|
||||
|
||||
operator Bundle () const
|
||||
{
|
||||
if (!isBundle()) throw ParseError("Packet is not a bundle");
|
||||
ReadStream stream(m_stream);
|
||||
uint64_t time = stream.getUInt64();
|
||||
return Bundle(time, std::move(stream));
|
||||
}
|
||||
|
||||
operator Message () const
|
||||
{
|
||||
if (!isMessage()) throw ParseError("Packet is not a message");
|
||||
ReadStream stream(m_stream);
|
||||
const char* address = stream.getString();
|
||||
return Message(address, std::move(stream));
|
||||
}
|
||||
|
||||
static bool isMessage(const void* data, size_t size)
|
||||
{
|
||||
return (size > 3) && (static_cast<const char*>(data)[0] != '#');
|
||||
}
|
||||
|
||||
static bool isMessage(const ReadStream& stream)
|
||||
{
|
||||
return isMessage(stream.pos(), stream.consumable());
|
||||
}
|
||||
|
||||
static bool isBundle(const void* data, size_t size)
|
||||
{
|
||||
return (size > 15) && (std::memcmp(data, "#bundle", 8) == 0);
|
||||
}
|
||||
|
||||
static bool isBundle(const ReadStream& stream)
|
||||
{
|
||||
return isBundle(stream.pos(), stream.consumable());
|
||||
}
|
||||
|
||||
private:
|
||||
ReadStream m_stream;
|
||||
bool m_isBundle;
|
||||
};
|
||||
|
||||
|
||||
class PacketStream
|
||||
{
|
||||
public:
|
||||
PacketStream(const ReadStream& stream)
|
||||
: m_stream(stream)
|
||||
{ }
|
||||
|
||||
bool atEnd() const
|
||||
{
|
||||
return m_stream.atEnd();
|
||||
}
|
||||
|
||||
Packet next()
|
||||
{
|
||||
size_t size = m_stream.getInt32();
|
||||
ReadStream stream(m_stream, size);
|
||||
m_stream.skip(size);
|
||||
return Packet(stream);
|
||||
}
|
||||
|
||||
private:
|
||||
ReadStream m_stream;
|
||||
};
|
||||
|
||||
template <> inline int32_t ArgStream::next<int32_t>()
|
||||
{
|
||||
return int32();
|
||||
}
|
||||
|
||||
template <> inline float ArgStream::next<float>()
|
||||
{
|
||||
return float32();
|
||||
}
|
||||
|
||||
template <> inline const char* ArgStream::next<const char*>()
|
||||
{
|
||||
return string();
|
||||
}
|
||||
|
||||
template <> inline Blob ArgStream::next<Blob>()
|
||||
{
|
||||
return blob();
|
||||
}
|
||||
|
||||
template <> inline ArgStream ArgStream::next<ArgStream>()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
PacketStream Bundle::packets() const
|
||||
{
|
||||
return PacketStream(m_stream);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool operator==(const OSCPP::Server::Message& msg, const char* str)
|
||||
{
|
||||
return strcmp(msg.address(), str) == 0;
|
||||
}
|
||||
|
||||
static inline bool operator==(const char* str, const OSCPP::Server::Message& msg)
|
||||
{
|
||||
return msg == str;
|
||||
}
|
||||
|
||||
static inline bool operator!=(const OSCPP::Server::Message& msg, const char* str)
|
||||
{
|
||||
return !(msg == str);
|
||||
}
|
||||
|
||||
static inline bool operator!=(const char* str, const OSCPP::Server::Message& msg)
|
||||
{
|
||||
return msg != str;
|
||||
}
|
||||
|
||||
#endif // OSCPP_SERVER_HPP_INCLUDED
|
||||
@@ -0,0 +1,51 @@
|
||||
// oscpp library
|
||||
//
|
||||
// Copyright (c) 2004-2013 Stefan Kersten <sk@k-hornz.de>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef OSCPP_TYPES_HPP_INCLUDED
|
||||
#define OSCPP_TYPES_HPP_INCLUDED
|
||||
|
||||
namespace OSCPP {
|
||||
|
||||
class Blob
|
||||
{
|
||||
public:
|
||||
Blob()
|
||||
: m_size(0), m_data(nullptr)
|
||||
{ }
|
||||
Blob(const void* data, size_t size)
|
||||
: m_size(size), m_data(data)
|
||||
{ }
|
||||
Blob(const Blob& other) = default;
|
||||
|
||||
size_t size() const { return m_size; }
|
||||
const void* data() const { return m_data; }
|
||||
|
||||
private:
|
||||
size_t m_size;
|
||||
const void* m_data;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OSCPP_TYPES_HPP_INCLUDED
|
||||
@@ -0,0 +1,151 @@
|
||||
// oscpp library
|
||||
//
|
||||
// Copyright (c) 2004-2013 Stefan Kersten <sk@k-hornz.de>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef OSCPP_UTIL_HPP_INCLUDED
|
||||
#define OSCPP_UTIL_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
namespace OSCPP {
|
||||
|
||||
static const size_t kAlignment = 4;
|
||||
|
||||
inline bool isAligned(const void* ptr, size_t alignment)
|
||||
{
|
||||
return (reinterpret_cast<uintptr_t>(ptr) & (alignment-1)) == 0;
|
||||
}
|
||||
|
||||
constexpr bool isAligned(size_t n)
|
||||
{
|
||||
return (n & 3) == 0;
|
||||
}
|
||||
|
||||
constexpr size_t align(size_t n)
|
||||
{
|
||||
return (n + 3) & -4;
|
||||
}
|
||||
|
||||
constexpr size_t padding(size_t n)
|
||||
{
|
||||
return align(n) - n;
|
||||
}
|
||||
|
||||
inline void checkAlignment(const void* ptr, size_t n)
|
||||
{
|
||||
if (!isAligned(ptr, n)) {
|
||||
throw std::runtime_error("Unaligned pointer");
|
||||
}
|
||||
}
|
||||
|
||||
namespace Tags {
|
||||
|
||||
constexpr size_t int32()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
constexpr size_t float32()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
constexpr size_t string()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
constexpr size_t blob()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
constexpr size_t array(size_t numElems)
|
||||
{
|
||||
return numElems+2;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Size {
|
||||
|
||||
class String
|
||||
{
|
||||
public:
|
||||
String(const char* x)
|
||||
: m_value(x)
|
||||
{}
|
||||
|
||||
operator const char* () const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* m_value;
|
||||
};
|
||||
|
||||
inline size_t string(const String& x)
|
||||
{
|
||||
return align(std::strlen(x)+1);
|
||||
}
|
||||
|
||||
template <size_t N> constexpr size_t string(char const (&)[N])
|
||||
{
|
||||
return align(N);
|
||||
}
|
||||
|
||||
constexpr size_t bundle(size_t numPackets)
|
||||
{
|
||||
return 8 /* #bundle */ + 8 /* timestamp */ + 4 * numPackets /* size prefix */;
|
||||
}
|
||||
|
||||
inline size_t message(const String& address, size_t numArgs)
|
||||
{
|
||||
return string(address) + align(numArgs + 2);
|
||||
}
|
||||
|
||||
template <size_t N> constexpr size_t message(char const (&address)[N], size_t numArgs)
|
||||
{
|
||||
return string(address) + align(numArgs + 2);
|
||||
}
|
||||
|
||||
constexpr size_t int32(size_t n=1)
|
||||
{
|
||||
return n*4;
|
||||
}
|
||||
|
||||
constexpr size_t float32(size_t n=1)
|
||||
{
|
||||
return n*4;
|
||||
}
|
||||
|
||||
constexpr size_t string(size_t n)
|
||||
{
|
||||
return align(n + 1);
|
||||
}
|
||||
|
||||
constexpr size_t blob(size_t size)
|
||||
{
|
||||
return 4 + align(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OSCPP_UTIL_HPP_INCLUDED
|
||||
@@ -0,0 +1,277 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class processing_sound_MethClaInterface */
|
||||
|
||||
#ifndef _Included_processing_sound_MethClaInterface
|
||||
#define _Included_processing_sound_MethClaInterface
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: engineNew
|
||||
* Signature: (II)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_engineNew
|
||||
(JNIEnv *, jobject, jint, jint);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: engineStart
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_engineStart
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: engineStop
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_engineStop
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: synthStop
|
||||
* Signature: ([I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_synthStop
|
||||
(JNIEnv *, jobject, jintArray);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: oscSet
|
||||
* Signature: (FFFF[I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_oscSet
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat, jintArray);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: sinePlay
|
||||
* Signature: (FFFF)[I
|
||||
*/
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_sinePlay
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: sawPlay
|
||||
* Signature: (FFFF)[I
|
||||
*/
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_sawPlay
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: sqrPlay
|
||||
* Signature: (FFFF)[I
|
||||
*/
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_sqrPlay
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: sqrSet
|
||||
* Signature: (FFFF[I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_sqrSet
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat, jintArray);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: triPlay
|
||||
* Signature: (FFFF)[I
|
||||
*/
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_triPlay
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: pulsePlay
|
||||
* Signature: (FFFFF)[I
|
||||
*/
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_pulsePlay
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat, jfloat);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: pulseSet
|
||||
* Signature: (FFFFF[I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_pulseSet
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat, jfloat, jintArray);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: soundFileInfo
|
||||
* Signature: (Ljava/lang/String;)[I
|
||||
*/
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_soundFileInfo
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: soundFilePlayMono
|
||||
* Signature: (FFFFZLjava/lang/String;FI)[I
|
||||
*/
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_soundFilePlayMono
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat, jboolean, jstring, jfloat, jint);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: soundFilePlayMulti
|
||||
* Signature: (FFFZLjava/lang/String;FI)[I
|
||||
*/
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_soundFilePlayMulti
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat, jboolean, jstring, jfloat, jint);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: soundFileSetMono
|
||||
* Signature: (FFFF[I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_soundFileSetMono
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat, jintArray);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: soundFileSetStereo
|
||||
* Signature: (FFF[I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_soundFileSetStereo
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat, jintArray);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: whiteNoisePlay
|
||||
* Signature: (FFF)[I
|
||||
*/
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_whiteNoisePlay
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: whiteNoiseSet
|
||||
* Signature: (FFF[I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_whiteNoiseSet
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jfloat, jintArray);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: envelopePlay
|
||||
* Signature: ([IFFFF)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_envelopePlay
|
||||
(JNIEnv *, jobject, jintArray, jfloat, jfloat, jfloat, jfloat);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: doneAfter
|
||||
* Signature: (F)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_doneAfter
|
||||
(JNIEnv *, jobject, jfloat);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: highPassPlay
|
||||
* Signature: ([IFF)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_highPassPlay
|
||||
(JNIEnv *, jobject, jintArray, jfloat, jfloat);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: lowPassPlay
|
||||
* Signature: ([IFF)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_lowPassPlay
|
||||
(JNIEnv *, jobject, jintArray, jfloat, jfloat);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: bandPassPlay
|
||||
* Signature: ([IFF)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_bandPassPlay
|
||||
(JNIEnv *, jobject, jintArray, jfloat, jfloat);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: filterSet
|
||||
* Signature: (FFI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_filterSet
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jint);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: delayPlay
|
||||
* Signature: ([IFFF)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_delayPlay
|
||||
(JNIEnv *, jobject, jintArray, jfloat, jfloat, jfloat);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: delaySet
|
||||
* Signature: (FFI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_delaySet
|
||||
(JNIEnv *, jobject, jfloat, jfloat, jint);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: amplitude
|
||||
* Signature: ([I)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_processing_sound_MethClaInterface_amplitude
|
||||
(JNIEnv *, jobject, jintArray);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: poll_amplitude
|
||||
* Signature: (J)F
|
||||
*/
|
||||
JNIEXPORT jfloat JNICALL Java_processing_sound_MethClaInterface_poll_1amplitude
|
||||
(JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: destroy_amplitude
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_destroy_1amplitude
|
||||
(JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: fft
|
||||
* Signature: ([II)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_processing_sound_MethClaInterface_fft
|
||||
(JNIEnv *, jobject, jintArray, jint);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: poll_fft
|
||||
* Signature: (J)[F
|
||||
*/
|
||||
JNIEXPORT jfloatArray JNICALL Java_processing_sound_MethClaInterface_poll_1fft
|
||||
(JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: processing_sound_MethClaInterface
|
||||
* Method: destroy_fft
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_destroy_1fft
|
||||
(JNIEnv *, jobject, jlong);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,962 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cassert>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <typeinfo>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
|
||||
#include "processing_sound_MethClaInterface.h"
|
||||
#include "methcla/file.hpp"
|
||||
#include "methcla/engine.hpp"
|
||||
#include "methcla/plugins/sine.h"
|
||||
#include "methcla/plugins/saw.h"
|
||||
#include "methcla/plugins/tri.h"
|
||||
#include "methcla/plugins/pulse.h"
|
||||
#include "methcla/plugins/patch-cable.h"
|
||||
#include "methcla/plugins/soundfile_api_libsndfile.h"
|
||||
#include "methcla/plugins/sampler.h"
|
||||
#include "methcla/plugins/whitenoise.h"
|
||||
#include "methcla/plugins/node-control.h"
|
||||
#include "methcla/plugins/pan2.h"
|
||||
#include "methcla/plugins/soundfile_api_mpg123.h"
|
||||
#include "methcla/plugins/ampfol.h"
|
||||
#include "methcla/plugins/fft.h"
|
||||
#include "methcla/plugins/hpf.h"
|
||||
#include "methcla/plugins/lpf.h"
|
||||
#include "methcla/plugins/delay.h"
|
||||
|
||||
#define OUTPUT_BUFFER_SIZE 1024
|
||||
#define SNDF_BUFFER_LEN 1024
|
||||
|
||||
#define MAX_CHANNELS 2
|
||||
|
||||
Methcla::Engine* m_engine;
|
||||
Methcla::Engine& engine() { return *m_engine; }
|
||||
std::mutex mutex;
|
||||
|
||||
static Methcla_Time kLatency = 0.1;
|
||||
|
||||
typedef struct data_v{
|
||||
int id;
|
||||
std::atomic<float> amp;
|
||||
} ServerValue, *ServerValuePtr;
|
||||
|
||||
typedef struct data_a{
|
||||
int id;
|
||||
int fftSize=512;
|
||||
std::vector<float> fft;
|
||||
} ServerArray, *ServerArrayPtr;
|
||||
|
||||
|
||||
// Engine
|
||||
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_engineNew (JNIEnv *, jobject, jint sampleRate, jint bufferSize){
|
||||
|
||||
Methcla::EngineOptions options;
|
||||
options.audioDriver.bufferSize = bufferSize;
|
||||
options.realtimeMemorySize = 1024 * 1024 * 20;
|
||||
options.maxNumNodes = 1024 * 20;
|
||||
options.addLibrary(methcla_plugins_sine)
|
||||
.addLibrary(methcla_plugins_saw)
|
||||
.addLibrary(methcla_plugins_tri)
|
||||
.addLibrary(methcla_plugins_pulse)
|
||||
.addLibrary(methcla_soundfile_api_libsndfile)
|
||||
.addLibrary(methcla_plugins_patch_cable)
|
||||
.addLibrary(methcla_plugins_sampler)
|
||||
.addLibrary(methcla_plugins_white_noise)
|
||||
.addLibrary(methcla_plugins_node_control)
|
||||
.addLibrary(methcla_plugins_pan2)
|
||||
.addLibrary(methcla_plugins_amplitude_follower)
|
||||
.addLibrary(methcla_plugins_hpf)
|
||||
.addLibrary(methcla_plugins_lpf)
|
||||
.addLibrary(methcla_plugins_delay)
|
||||
.addLibrary(methcla_plugins_fft);
|
||||
|
||||
m_engine = new Methcla::Engine(options);
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_engineStart(JNIEnv *env, jobject object){
|
||||
engine().start();
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_engineStop(JNIEnv *env, jobject object){
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
request.freeAll(engine().root());
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
engine().stop();
|
||||
//delete m_engine;
|
||||
|
||||
};
|
||||
|
||||
// General Synth
|
||||
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_synthStop(JNIEnv *env, jobject object, jintArray nodeId){
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
request.free(m_nodeId[0]);
|
||||
request.free(m_nodeId[1]);
|
||||
|
||||
request.closeBundle();
|
||||
engine().addNotificationHandler(engine().freeNodeIdHandler(m_nodeId[0]));
|
||||
engine().addNotificationHandler(engine().freeNodeIdHandler(m_nodeId[1]));
|
||||
request.send();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
};
|
||||
|
||||
// General Oscillator set method
|
||||
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_oscSet (JNIEnv *env, jobject object, jfloat freq, jfloat amp, jfloat add, jfloat pos, jintArray nodeId){
|
||||
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
request.set(m_nodeId[0], 0 , freq);
|
||||
request.set(m_nodeId[0], 1 , amp);
|
||||
request.set(m_nodeId[0], 2 , add);
|
||||
request.set(m_nodeId[1], 0, pos);
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
};
|
||||
|
||||
// SineOsc
|
||||
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_sinePlay(JNIEnv *env, jobject object, jfloat freq, jfloat amp, jfloat add, jfloat pos){
|
||||
|
||||
jintArray nodeId = env->NewIntArray(2);
|
||||
jint *m_nodeId = env->GetIntArrayElements(nodeId, NULL);
|
||||
|
||||
Methcla::AudioBusId bus = m_engine->audioBusId().alloc();
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_SINE_URI,
|
||||
engine().root(),
|
||||
{freq, amp, add}
|
||||
);
|
||||
|
||||
auto pan = request.synth(
|
||||
METHCLA_PLUGINS_PAN2_URI,
|
||||
engine().root(),
|
||||
{pos, 1.f},
|
||||
{Methcla::Value(1.f)}
|
||||
);
|
||||
|
||||
request.mapOutput(synth.id(), 0, bus);
|
||||
request.mapInput(pan.id(), 0, bus);
|
||||
request.mapOutput(pan.id(), 0, Methcla::AudioBusId(0), Methcla::kBusMappingExternal);
|
||||
request.mapOutput(pan.id(), 1, Methcla::AudioBusId(1), Methcla::kBusMappingExternal);
|
||||
|
||||
request.activate(synth.id());
|
||||
request.activate(pan.id());
|
||||
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
m_nodeId[0]=synth.id();
|
||||
m_nodeId[1]=pan.id();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return nodeId;
|
||||
};
|
||||
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_sawPlay(JNIEnv *env, jobject object, jfloat freq, jfloat amp, jfloat add, jfloat pos){
|
||||
|
||||
jintArray nodeId = env->NewIntArray(2);
|
||||
jint *m_nodeId = env->GetIntArrayElements(nodeId, NULL);
|
||||
|
||||
Methcla::AudioBusId bus = m_engine->audioBusId().alloc();
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_SAW_URI,
|
||||
engine().root(),
|
||||
{freq, amp, add}
|
||||
);
|
||||
|
||||
auto pan = request.synth(
|
||||
METHCLA_PLUGINS_PAN2_URI,
|
||||
engine().root(),
|
||||
{pos, 1.f},
|
||||
{Methcla::Value(1.f)}
|
||||
);
|
||||
|
||||
request.mapOutput(synth.id(), 0, bus);
|
||||
request.mapInput(pan.id(), 0, bus);
|
||||
request.mapOutput(pan.id(), 0, Methcla::AudioBusId(0), Methcla::kBusMappingExternal);
|
||||
request.mapOutput(pan.id(), 1, Methcla::AudioBusId(1), Methcla::kBusMappingExternal);
|
||||
|
||||
request.activate(synth.id());
|
||||
request.activate(pan.id());
|
||||
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
m_nodeId[0]=synth.id();
|
||||
m_nodeId[1]=pan.id();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return nodeId;
|
||||
};
|
||||
|
||||
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_triPlay(JNIEnv *env, jobject object, jfloat freq, jfloat amp, jfloat add, jfloat pos){
|
||||
|
||||
jintArray nodeId = env->NewIntArray(2);
|
||||
jint *m_nodeId = env->GetIntArrayElements(nodeId, NULL);
|
||||
|
||||
Methcla::AudioBusId bus = m_engine->audioBusId().alloc();
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_TRI_URI,
|
||||
engine().root(),
|
||||
{freq, amp, add}
|
||||
);
|
||||
|
||||
auto pan = request.synth(
|
||||
METHCLA_PLUGINS_PAN2_URI,
|
||||
engine().root(),
|
||||
{pos, 1.f},
|
||||
{Methcla::Value(1.f)}
|
||||
);
|
||||
|
||||
request.mapOutput(synth.id(), 0, bus);
|
||||
request.mapInput(pan.id(), 0, bus);
|
||||
request.mapOutput(pan.id(), 0, Methcla::AudioBusId(0), Methcla::kBusMappingExternal);
|
||||
request.mapOutput(pan.id(), 1, Methcla::AudioBusId(1), Methcla::kBusMappingExternal);
|
||||
|
||||
request.activate(synth.id());
|
||||
request.activate(pan.id());
|
||||
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
m_nodeId[0]=synth.id();
|
||||
m_nodeId[1]=pan.id();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_sqrPlay(JNIEnv *env, jobject object, jfloat freq, jfloat amp, jfloat add, jfloat pos){
|
||||
jintArray nodeId = env->NewIntArray(2);
|
||||
jint *m_nodeId = env->GetIntArrayElements(nodeId, NULL);
|
||||
|
||||
Methcla::AudioBusId bus = m_engine->audioBusId().alloc();
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_PULSE_URI,
|
||||
engine().root(),
|
||||
{freq, 0.5, amp*2.f, add-1.f}
|
||||
);
|
||||
|
||||
auto pan = request.synth(
|
||||
METHCLA_PLUGINS_PAN2_URI,
|
||||
engine().root(),
|
||||
{pos, 1.f},
|
||||
{Methcla::Value(1.f)}
|
||||
);
|
||||
|
||||
request.mapOutput(synth.id(), 0, bus);
|
||||
request.mapInput(pan.id(), 0, bus);
|
||||
request.mapOutput(pan.id(), 0, Methcla::AudioBusId(0), Methcla::kBusMappingExternal);
|
||||
request.mapOutput(pan.id(), 1, Methcla::AudioBusId(1), Methcla::kBusMappingExternal);
|
||||
|
||||
request.activate(synth.id());
|
||||
request.activate(pan.id());
|
||||
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
m_nodeId[0]=synth.id();
|
||||
m_nodeId[1]=pan.id();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return nodeId;
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_sqrSet(JNIEnv *env, jobject object, jfloat freq, jfloat amp, jfloat add, jfloat pos, jintArray nodeId){
|
||||
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
request.set(m_nodeId[0], 0 , freq);
|
||||
request.set(m_nodeId[0], 2 , amp);
|
||||
request.set(m_nodeId[1], 0 , pos);
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
};
|
||||
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_pulsePlay(JNIEnv *env, jobject object, jfloat freq, jfloat width, jfloat amp, jfloat add, jfloat pos){
|
||||
|
||||
jintArray nodeId = env->NewIntArray(2);
|
||||
jint *m_nodeId = env->GetIntArrayElements(nodeId, NULL);
|
||||
|
||||
Methcla::AudioBusId bus = m_engine->audioBusId().alloc();
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_PULSE_URI,
|
||||
engine().root(),
|
||||
{freq, width, amp, add}
|
||||
);
|
||||
|
||||
auto pan = request.synth(
|
||||
METHCLA_PLUGINS_PAN2_URI,
|
||||
engine().root(),
|
||||
{pos, 1.f},
|
||||
{Methcla::Value(1.f)}
|
||||
);
|
||||
|
||||
request.mapOutput(synth.id(), 0, bus);
|
||||
request.mapInput(pan.id(), 0, bus);
|
||||
request.mapOutput(pan.id(), 0, Methcla::AudioBusId(0), Methcla::kBusMappingExternal);
|
||||
request.mapOutput(pan.id(), 1, Methcla::AudioBusId(1), Methcla::kBusMappingExternal);
|
||||
|
||||
request.activate(synth.id());
|
||||
request.activate(pan.id());
|
||||
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
m_nodeId[0]=synth.id();
|
||||
m_nodeId[1]=pan.id();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_pulseSet(JNIEnv *env, jobject object, jfloat freq, jfloat width, jfloat amp, jfloat add, jfloat pos, jintArray nodeId){
|
||||
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
request.set(m_nodeId[0], 0 , freq);
|
||||
request.set(m_nodeId[0], 1 , width);
|
||||
request.set(m_nodeId[0], 2 , amp);
|
||||
request.set(m_nodeId[1], 0 , pos);
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
};
|
||||
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_soundFileInfo(JNIEnv *env, jobject object, jstring path){
|
||||
const char *str = env->GetStringUTFChars(path, 0);
|
||||
|
||||
Methcla::SoundFile file(engine(), str);
|
||||
|
||||
jintArray info = env->NewIntArray(3);
|
||||
jint *temp = env->GetIntArrayElements(info, NULL);
|
||||
|
||||
temp[0] = file.info().frames;
|
||||
temp[1] = file.info().samplerate;
|
||||
temp[2] = file.info().channels;
|
||||
|
||||
env->ReleaseIntArrayElements(info, temp, 0);
|
||||
env->ReleaseStringUTFChars(path, str);
|
||||
|
||||
return info;
|
||||
};
|
||||
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_soundFilePlayMono (JNIEnv *env, jobject object, jfloat rate, jfloat pos, jfloat amp, jfloat add, jboolean loop, jstring path, jfloat dur, jint cue){
|
||||
|
||||
const char *str = env->GetStringUTFChars(path, 0);
|
||||
|
||||
jintArray nodeId = env->NewIntArray(2);
|
||||
jint *m_nodeId = env->GetIntArrayElements(nodeId, NULL);
|
||||
|
||||
Methcla::Request request(engine());
|
||||
Methcla::NodeTreeStatistics results;
|
||||
|
||||
Methcla::AudioBusId bus = m_engine->audioBusId().alloc();
|
||||
|
||||
request.openBundle(Methcla::immediately);
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_SAMPLER_URI,
|
||||
engine().root(),
|
||||
{ amp, rate },
|
||||
{ Methcla::Value(str),
|
||||
Methcla::Value(loop),
|
||||
Methcla::Value(cue) }
|
||||
);
|
||||
|
||||
auto pan = request.synth(
|
||||
METHCLA_PLUGINS_PAN2_URI,
|
||||
engine().root(),
|
||||
{pos, 1.f},
|
||||
{Methcla::Value(1.f)}
|
||||
);
|
||||
|
||||
auto after = request.synth(
|
||||
METHCLA_PLUGINS_DONE_AFTER_URI,
|
||||
engine().root(),
|
||||
{ },
|
||||
{ Methcla::Value(dur) }
|
||||
);
|
||||
|
||||
request.mapOutput(synth.id(), 0, bus);
|
||||
request.mapInput(pan.id(), 0, bus);
|
||||
request.mapOutput(pan.id(), 0, Methcla::AudioBusId(0), Methcla::kBusMappingExternal);
|
||||
request.mapOutput(pan.id(), 1, Methcla::AudioBusId(1), Methcla::kBusMappingExternal);
|
||||
|
||||
request.whenDone(after.id(), Methcla::kNodeDoneFreeSelf | Methcla::kNodeDoneFreePreceeding);
|
||||
request.activate(synth.id());
|
||||
request.activate(pan.id());
|
||||
if (loop == false)
|
||||
{
|
||||
request.activate(after.id());
|
||||
}
|
||||
request.closeBundle();
|
||||
|
||||
engine().addNotificationHandler(engine().freeNodeIdHandler(synth.id()));
|
||||
engine().addNotificationHandler(engine().freeNodeIdHandler(pan.id()));
|
||||
engine().addNotificationHandler(engine().freeNodeIdHandler(after.id()));
|
||||
|
||||
request.send();
|
||||
|
||||
m_nodeId[0]=synth.id();
|
||||
m_nodeId[1]=pan.id();
|
||||
|
||||
//results = engine().getNodeTreeStatistics();
|
||||
//std::cout << results.numSynths << std::endl;
|
||||
|
||||
env->ReleaseStringUTFChars(path, str);
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return nodeId;
|
||||
};
|
||||
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_soundFilePlayMulti(JNIEnv *env, jobject object, jfloat rate, jfloat amp, jfloat add, jboolean loop, jstring path, jfloat dur, jint cue){
|
||||
const char *str = env->GetStringUTFChars(path, 0);
|
||||
|
||||
jintArray nodeId = env->NewIntArray(2);
|
||||
jint *m_nodeId = env->GetIntArrayElements(nodeId, NULL);
|
||||
|
||||
Methcla::Request request(engine());
|
||||
Methcla::NodeTreeStatistics results;
|
||||
|
||||
request.openBundle(Methcla::immediately);
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_SAMPLER_URI,
|
||||
engine().root(),
|
||||
{ amp, rate },
|
||||
{ Methcla::Value(str),
|
||||
Methcla::Value(loop),
|
||||
Methcla::Value(cue) }
|
||||
);
|
||||
|
||||
auto after = request.synth(
|
||||
METHCLA_PLUGINS_DONE_AFTER_URI,
|
||||
engine().root(),
|
||||
{ },
|
||||
{ Methcla::Value(dur) }
|
||||
);
|
||||
|
||||
request.mapOutput(synth.id(), 0, Methcla::AudioBusId(0), Methcla::kBusMappingExternal);
|
||||
request.mapOutput(synth.id(), 1, Methcla::AudioBusId(1), Methcla::kBusMappingExternal);
|
||||
|
||||
request.whenDone(after.id(), Methcla::kNodeDoneFreeSelf | Methcla::kNodeDoneFreePreceeding);
|
||||
request.activate(synth.id());
|
||||
request.activate(after.id());
|
||||
request.closeBundle();
|
||||
|
||||
engine().addNotificationHandler(engine().freeNodeIdHandler(synth.id()));
|
||||
engine().addNotificationHandler(engine().freeNodeIdHandler(after.id()));
|
||||
|
||||
request.send();
|
||||
|
||||
m_nodeId[0]=synth.id();
|
||||
m_nodeId[1]=after.id();
|
||||
|
||||
//results = engine().getNodeTreeStatistics();
|
||||
//std::cout << results.numSynths << std::endl;
|
||||
|
||||
env->ReleaseStringUTFChars(path, str);
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_soundFileSetMono (JNIEnv *env, jobject object, jfloat rate, jfloat pos, jfloat amp, jfloat add, jintArray nodeId){
|
||||
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
request.set(m_nodeId[0], 0, amp);
|
||||
request.set(m_nodeId[0], 1, rate);
|
||||
request.set(m_nodeId[1], 0, pos);
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_soundFileSetStereo(JNIEnv *env, jobject object, jfloat rate, jfloat amp, jfloat add, jintArray nodeId){
|
||||
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
request.set(m_nodeId[0], 0, amp);
|
||||
request.set(m_nodeId[0], 1, rate);
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
};
|
||||
|
||||
JNIEXPORT jintArray JNICALL Java_processing_sound_MethClaInterface_whiteNoisePlay(JNIEnv *env, jobject object, jfloat amp, jfloat add, jfloat pos){
|
||||
|
||||
jintArray nodeId = env->NewIntArray(2);
|
||||
jint *m_nodeId = env->GetIntArrayElements(nodeId, NULL);
|
||||
|
||||
Methcla::AudioBusId bus = m_engine->audioBusId().alloc();
|
||||
Methcla::Request request(engine());
|
||||
|
||||
request.openBundle(Methcla::immediately);
|
||||
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_WHITE_NOISE_URI,
|
||||
engine().root(),
|
||||
{ amp, add },
|
||||
{Methcla::Value(0.0)}
|
||||
);
|
||||
|
||||
auto pan = request.synth(
|
||||
METHCLA_PLUGINS_PAN2_URI,
|
||||
engine().root(),
|
||||
{pos, 1.f},
|
||||
{Methcla::Value(1.f)}
|
||||
);
|
||||
|
||||
request.mapOutput(synth.id(), 0, bus);
|
||||
request.mapInput(pan.id(), 0, bus);
|
||||
request.mapOutput(pan.id(), 0, Methcla::AudioBusId(0), Methcla::kBusMappingExternal);
|
||||
request.mapOutput(pan.id(), 1, Methcla::AudioBusId(1), Methcla::kBusMappingExternal);
|
||||
|
||||
request.activate(synth.id());
|
||||
request.activate(pan.id());
|
||||
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
m_nodeId[0]=synth.id();
|
||||
m_nodeId[1]=pan.id();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return nodeId;
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_whiteNoiseSet(JNIEnv *env, jobject object, jfloat amp, jfloat add, jfloat pos, jintArray nodeId){
|
||||
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
request.set(m_nodeId[0], 0, amp);
|
||||
request.set(m_nodeId[1], 0, pos);
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
};
|
||||
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_envelopePlay(JNIEnv *env, jobject object, jintArray nodeId, jfloat attackTime, jfloat sustainTime, jfloat sustainLevel, jfloat releaseTime){
|
||||
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
|
||||
Methcla::AudioBusId in_bus = m_engine->audioBusId().alloc();
|
||||
Methcla::AudioBusId out_bus = m_engine->audioBusId().alloc();
|
||||
|
||||
|
||||
const std::list<Methcla::Value> envOptions =
|
||||
{ Methcla::Value(attackTime)
|
||||
, Methcla::Value(sustainTime)
|
||||
, Methcla::Value(sustainLevel)
|
||||
, Methcla::Value(releaseTime)
|
||||
};
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_ASR_ENVELOPE_URI,
|
||||
Methcla::NodePlacement::after(m_nodeId[0]),
|
||||
{},
|
||||
envOptions
|
||||
);
|
||||
|
||||
request.mapOutput(m_nodeId[0], 0, in_bus);
|
||||
request.mapInput(synth.id(), 0, in_bus);
|
||||
request.mapOutput(synth.id(), 0, out_bus);
|
||||
request.mapInput(m_nodeId[1], 0, out_bus);
|
||||
|
||||
request.activate(synth.id());
|
||||
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return synth.id();
|
||||
};
|
||||
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_highPassPlay(JNIEnv *env, jobject object, jintArray nodeId, jfloat freq, jfloat res){
|
||||
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
|
||||
Methcla::AudioBusId in_bus = m_engine->audioBusId().alloc();
|
||||
Methcla::AudioBusId out_bus = m_engine->audioBusId().alloc();
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_HPF_URI,
|
||||
Methcla::NodePlacement::after(m_nodeId[0]),
|
||||
{freq, res},
|
||||
{}
|
||||
);
|
||||
|
||||
request.mapOutput(m_nodeId[0], 0, in_bus);
|
||||
request.mapInput(synth.id(), 0, in_bus);
|
||||
request.mapOutput(synth.id(), 0, out_bus);
|
||||
request.mapInput(m_nodeId[1], 0, out_bus);
|
||||
|
||||
request.activate(synth.id());
|
||||
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return synth.id();
|
||||
};
|
||||
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_lowPassPlay(JNIEnv *env, jobject object, jintArray nodeId, jfloat freq, jfloat res){
|
||||
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
|
||||
Methcla::AudioBusId in_bus = m_engine->audioBusId().alloc();
|
||||
Methcla::AudioBusId out_bus = m_engine->audioBusId().alloc();
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_LPF_URI,
|
||||
Methcla::NodePlacement::after(m_nodeId[0]),
|
||||
{freq, res},
|
||||
{}
|
||||
);
|
||||
|
||||
request.mapOutput(m_nodeId[0], 0, in_bus);
|
||||
request.mapInput(synth.id(), 0, in_bus);
|
||||
request.mapOutput(synth.id(), 0, out_bus);
|
||||
request.mapInput(m_nodeId[1], 0, out_bus);
|
||||
|
||||
request.activate(synth.id());
|
||||
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return synth.id();
|
||||
};
|
||||
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_bandPassPlay(JNIEnv *env, jobject object, jintArray nodeId, jfloat freq, jfloat res){
|
||||
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
|
||||
Methcla::AudioBusId in_bus = m_engine->audioBusId().alloc();
|
||||
Methcla::AudioBusId out_bus = m_engine->audioBusId().alloc();
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_HPF_URI,
|
||||
Methcla::NodePlacement::after(m_nodeId[0]),
|
||||
{freq, res},
|
||||
{}
|
||||
);
|
||||
|
||||
request.mapOutput(m_nodeId[0], 0, in_bus);
|
||||
request.mapInput(synth.id(), 0, in_bus);
|
||||
request.mapOutput(synth.id(), 0, out_bus);
|
||||
request.mapInput(m_nodeId[1], 0, out_bus);
|
||||
|
||||
request.activate(synth.id());
|
||||
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return synth.id();
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_filterSet(JNIEnv *env, jobject object, jfloat freq, jfloat res, jint nodeId){
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
request.set(nodeId, 0, freq);
|
||||
request.set(nodeId, 1, res);
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
};
|
||||
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_delayPlay(JNIEnv *env, jobject object, jintArray nodeId, jfloat maxDelayTime, jfloat delayTime, jfloat feedBack){
|
||||
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
|
||||
Methcla::AudioBusId in_bus = m_engine->audioBusId().alloc();
|
||||
Methcla::AudioBusId out_bus = m_engine->audioBusId().alloc();
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_DELAY_URI,
|
||||
Methcla::NodePlacement::after(m_nodeId[0]),
|
||||
{delayTime, feedBack},
|
||||
{Methcla::Value(maxDelayTime)}
|
||||
);
|
||||
|
||||
request.mapOutput(m_nodeId[0], 0, in_bus);
|
||||
request.mapInput(synth.id(), 0, in_bus);
|
||||
request.mapOutput(synth.id(), 0, out_bus);
|
||||
request.mapInput(m_nodeId[1], 0, out_bus);
|
||||
|
||||
request.activate(synth.id());
|
||||
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return synth.id();
|
||||
};
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_delaySet(JNIEnv *env, jobject object, jfloat delayTime, jfloat feedBack, jint nodeId){
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
request.set(nodeId, 0, delayTime);
|
||||
request.set(nodeId, 1, feedBack);
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_processing_sound_MethClaInterface_amplitude(JNIEnv *env, jobject object, jintArray nodeId){
|
||||
|
||||
jlong ptr;
|
||||
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
|
||||
Methcla::AudioBusId in_bus = m_engine->audioBusId().alloc();
|
||||
Methcla::AudioBusId out_bus = m_engine->audioBusId().alloc();
|
||||
|
||||
Methcla::Request request(engine());
|
||||
|
||||
ServerValue *amp_ptr = (ServerValue *) malloc(sizeof(ServerValue));
|
||||
|
||||
ptr = (jlong)amp_ptr;
|
||||
|
||||
request.openBundle(Methcla::immediately);
|
||||
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_AMPLITUDE_FOLLOWER_URI,
|
||||
Methcla::NodePlacement::after(m_nodeId[0]),
|
||||
{},
|
||||
{}
|
||||
);
|
||||
|
||||
request.mapOutput(m_nodeId[0], 0, in_bus);
|
||||
request.mapInput(synth.id(), 0, in_bus);
|
||||
request.mapOutput(synth.id(), 0, out_bus);
|
||||
request.mapInput(m_nodeId[1], 0, out_bus);
|
||||
|
||||
request.activate(synth.id());
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
auto id = engine().addNotificationHandler([amp_ptr](const OSCPP::Server::Message& msg) {
|
||||
if (msg == "/amplitude") {
|
||||
OSCPP::Server::ArgStream args(msg.args());
|
||||
while (!args.atEnd()) {
|
||||
|
||||
amp_ptr->amp = args.float32();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
amp_ptr->id = id;
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return ptr;
|
||||
};
|
||||
|
||||
JNIEXPORT jfloat JNICALL Java_processing_sound_MethClaInterface_poll_1amplitude(JNIEnv * env, jobject object, jlong ptr){
|
||||
|
||||
ServerValue *amp_ptr = (ServerValue*)ptr;
|
||||
|
||||
return amp_ptr->amp;
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_destroy_1amplitude(JNIEnv *env, jobject object, jlong ptr){
|
||||
|
||||
ServerValue *amp_ptr = (ServerValue*)ptr;
|
||||
engine().removeNotificationHandler(amp_ptr->id);
|
||||
free(amp_ptr);
|
||||
|
||||
};
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_processing_sound_MethClaInterface_fft(JNIEnv *env, jobject object, jintArray nodeId, jint fftSize){
|
||||
|
||||
jlong ptr;
|
||||
jint* m_nodeId = env->GetIntArrayElements(nodeId, 0);
|
||||
ServerArray *fft_ptr = (ServerArray *) malloc(sizeof(ServerArray) + fftSize*(sizeof(std::vector<float>)));
|
||||
|
||||
std::cout << "1" << std::endl;
|
||||
|
||||
fft_ptr->fft.resize(fftSize);
|
||||
std::cout << "2" << std::endl;
|
||||
|
||||
fft_ptr->fftSize=fftSize;
|
||||
ptr = (jlong)fft_ptr;
|
||||
|
||||
Methcla::Engine::NotificationHandler msg;
|
||||
|
||||
Methcla::AudioBusId in_bus = m_engine->audioBusId().alloc();
|
||||
Methcla::AudioBusId out_bus = m_engine->audioBusId().alloc();
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_FFT_URI,
|
||||
Methcla::NodePlacement::after(m_nodeId[0]),
|
||||
{},
|
||||
{Methcla::Value(fftSize)}
|
||||
);
|
||||
|
||||
request.mapOutput(m_nodeId[0], 0, in_bus);
|
||||
request.mapInput(synth.id(), 0, in_bus);
|
||||
request.mapOutput(synth.id(), 0, out_bus);
|
||||
request.mapInput(m_nodeId[1], 0, out_bus);
|
||||
|
||||
request.activate(synth.id());
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
auto id = engine().addNotificationHandler([fft_ptr](const OSCPP::Server::Message& msg) {
|
||||
if (msg == "/fft") {
|
||||
OSCPP::Server::ArgStream args(msg.args());
|
||||
int i=0;
|
||||
while (!args.atEnd()) {
|
||||
fft_ptr->fft[i] = args.float32();
|
||||
std::lock_guard<std::mutex> guard(mutex);
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
fft_ptr->id = id;
|
||||
|
||||
env->ReleaseIntArrayElements(nodeId, m_nodeId, 0);
|
||||
|
||||
return ptr;
|
||||
};
|
||||
|
||||
JNIEXPORT jfloatArray JNICALL Java_processing_sound_MethClaInterface_poll_1fft(JNIEnv *env, jobject object, jlong ptr){
|
||||
|
||||
ServerArray *fft_ptr = (ServerArray*)ptr;
|
||||
|
||||
jfloatArray fft_mag = env->NewFloatArray(fft_ptr->fftSize);
|
||||
|
||||
|
||||
jfloat *m_fft_mag = env->GetFloatArrayElements(fft_mag, NULL);
|
||||
|
||||
for (int i = 0; i < fft_ptr->fftSize; ++i)
|
||||
{
|
||||
m_fft_mag[i]=fft_ptr->fft[i];
|
||||
}
|
||||
|
||||
env->ReleaseFloatArrayElements(fft_mag, m_fft_mag, 0);
|
||||
|
||||
return fft_mag;
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL Java_processing_sound_MethClaInterface_destroy_1fft(JNIEnv *env, jobject object, jlong ptr){
|
||||
ServerArray *fft_ptr = (ServerArray*)ptr;
|
||||
engine().removeNotificationHandler(fft_ptr->id);
|
||||
free(fft_ptr);
|
||||
};
|
||||
|
||||
|
||||
/* OLD VARIABLE IN OUT FUNCTION
|
||||
JNIEXPORT jint JNICALL Java_processing_sound_MethClaInterface_out(JNIEnv *env, jobject object, jint in, jint out, jfloatArray pos){
|
||||
|
||||
float* n_pos = (float *)env->GetFloatArrayElements(pos, 0);
|
||||
std::vector<float> control (in, 0.f);
|
||||
|
||||
for (int i = 0; i < in; ++i){control[i]=n_pos[i];}
|
||||
|
||||
Methcla::Request request(engine());
|
||||
request.openBundle(Methcla::immediately);
|
||||
auto synth = request.synth(
|
||||
METHCLA_PLUGINS_PAN2_URI,
|
||||
engine().root(),
|
||||
control,
|
||||
{Methcla::Value(in), Methcla::Value(out)}
|
||||
);
|
||||
//request.mapOutput(synth.id(), 0, Methcla::AudioBusId(0), Methcla::kBusMappingExternal);
|
||||
request.activate(synth.id());
|
||||
request.closeBundle();
|
||||
request.send();
|
||||
|
||||
env->ReleaseFloatArrayElements(pos, n_pos, 0);
|
||||
|
||||
return synth.id();
|
||||
};
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package processing.sound;
|
||||
import processing.core.*;
|
||||
|
||||
public class Amplitude {
|
||||
|
||||
PApplet parent;
|
||||
private MethClaInterface m_engine;
|
||||
private long ptr;
|
||||
|
||||
public Amplitude(PApplet theParent) {
|
||||
this.parent = theParent;
|
||||
parent.registerMethod("dispose", this);
|
||||
m_engine = new MethClaInterface();
|
||||
}
|
||||
|
||||
public void input(SoundObject input){
|
||||
ptr = m_engine.amplitude(input.returnId());
|
||||
}
|
||||
|
||||
public float process(){
|
||||
return m_engine.poll_amplitude(ptr);
|
||||
}
|
||||
/*
|
||||
public void stop(){
|
||||
m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
|
||||
public int returnId(){
|
||||
return m_nodeId;
|
||||
}
|
||||
*/
|
||||
public void dispose() {
|
||||
m_engine.destroy_amplitude(ptr);
|
||||
//m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package processing.sound;
|
||||
|
||||
import processing.core.PApplet;
|
||||
|
||||
public class AudioIn {
|
||||
|
||||
PApplet parent;
|
||||
private MethClaInterface m_engine;
|
||||
private int[] m_nodeId = {-1,-1};
|
||||
private float m_freq = 0;
|
||||
private float m_amp = 0;
|
||||
private float m_add = 0;
|
||||
private float m_pos = 0;
|
||||
|
||||
public AudioIn(PApplet theParent) {
|
||||
this.parent = theParent;
|
||||
parent.registerMethod("dispose", this);
|
||||
m_engine = new MethClaInterface();
|
||||
}
|
||||
|
||||
public void play(float freq, float amp, float add, float pos){
|
||||
m_freq=freq; m_amp=amp; m_add=add; m_pos=pos;
|
||||
m_nodeId = m_engine.sawPlay(m_freq, m_amp, m_add, m_pos);
|
||||
}
|
||||
|
||||
public void play(float freq, float amp, float add){
|
||||
m_freq=freq; m_amp=amp; m_add=add;
|
||||
m_nodeId = m_engine.sawPlay(m_freq, m_amp, m_add, m_pos);
|
||||
}
|
||||
|
||||
public void play(float freq, float amp){
|
||||
m_freq=freq; m_amp=amp;
|
||||
m_nodeId = m_engine.sawPlay(m_freq, m_amp, m_add, m_pos);
|
||||
}
|
||||
|
||||
public void play(){
|
||||
m_nodeId = m_engine.sawPlay(m_freq, m_amp, m_add, m_pos);
|
||||
}
|
||||
|
||||
private void set(){
|
||||
m_engine.oscSet(m_freq, m_amp, m_add, m_pos, m_nodeId);
|
||||
}
|
||||
|
||||
public void set(float freq, float amp, float add, float pos){
|
||||
m_freq=freq; m_amp=amp; m_add=add; m_pos=pos;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void freq(float freq){
|
||||
m_freq=freq;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void amp(float amp){
|
||||
m_amp=amp;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void add(float add){
|
||||
m_add=add;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void pan(float pos){
|
||||
m_pos=pos;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
|
||||
public int[] returnId(){
|
||||
return m_nodeId;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package processing.sound;
|
||||
|
||||
import processing.core.PApplet;
|
||||
|
||||
public class BPF implements SoundObject{
|
||||
|
||||
PApplet parent;
|
||||
private MethClaInterface m_engine;
|
||||
private int m_nodeId;
|
||||
private int[] m_m = {0,0};
|
||||
private float m_freq = 100;
|
||||
private float m_res = 1;
|
||||
|
||||
public BPF(PApplet theParent) {
|
||||
this.parent = theParent;
|
||||
parent.registerMethod("dispose", this);
|
||||
m_engine = new MethClaInterface();
|
||||
}
|
||||
|
||||
public void play(SoundObject input, float freq, float res){
|
||||
m_freq=freq; m_res=res;
|
||||
m_nodeId = m_engine.bandPassPlay(input.returnId(), m_freq, m_res);
|
||||
}
|
||||
|
||||
public void play(SoundObject input, float freq){
|
||||
m_freq=freq;
|
||||
m_nodeId = m_engine.bandPassPlay(input.returnId(), m_freq, m_res);
|
||||
}
|
||||
|
||||
private void set(){
|
||||
m_engine.filterSet(m_freq, m_res, m_nodeId);
|
||||
}
|
||||
|
||||
public void set(float freq, float res){
|
||||
m_freq=freq; m_res=res;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void freq(float freq){
|
||||
m_freq=freq;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void res(float res){
|
||||
m_res=res;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public int[] returnId(){
|
||||
return m_m;
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
//m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
//m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package processing.sound;
|
||||
|
||||
import processing.core.PApplet;
|
||||
|
||||
public class Delay implements SoundObject{
|
||||
|
||||
PApplet parent;
|
||||
private MethClaInterface m_engine;
|
||||
private int m_nodeId;
|
||||
private int[] m_m = {0,0};
|
||||
private float m_maxDelayTime = 2;
|
||||
private float m_delayTime = 0;
|
||||
private float m_feedBack = 0;
|
||||
|
||||
public Delay(PApplet theParent) {
|
||||
this.parent = theParent;
|
||||
parent.registerMethod("dispose", this);
|
||||
m_engine = new MethClaInterface();
|
||||
}
|
||||
|
||||
public void play(SoundObject input, float maxDelayTime, float delayTime, float feedBack){
|
||||
m_maxDelayTime=maxDelayTime; m_delayTime=delayTime; m_feedBack=feedBack;
|
||||
m_nodeId = m_engine.delayPlay(input.returnId(), m_maxDelayTime, m_delayTime, m_feedBack);
|
||||
}
|
||||
|
||||
public void play(SoundObject input, float maxDelayTime, float delayTime){
|
||||
m_maxDelayTime=maxDelayTime; m_delayTime=delayTime;
|
||||
m_nodeId = m_engine.delayPlay(input.returnId(), m_maxDelayTime, m_delayTime, m_feedBack);
|
||||
}
|
||||
|
||||
public void play(SoundObject input, float maxDelayTime){
|
||||
m_maxDelayTime=maxDelayTime;
|
||||
m_nodeId = m_engine.delayPlay(input.returnId(), m_maxDelayTime, m_delayTime, m_feedBack);
|
||||
}
|
||||
|
||||
private void set(){
|
||||
m_engine.delaySet(m_delayTime, m_feedBack, m_nodeId);
|
||||
}
|
||||
|
||||
public void set(float delayTime, float feedBack){
|
||||
m_delayTime=delayTime; m_feedBack=feedBack;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void time(float delayTime){
|
||||
m_delayTime=delayTime;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void feedback(float feedBack){
|
||||
m_feedBack=feedBack;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public int[] returnId(){
|
||||
return m_m;
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
//m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
//m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package processing.sound;
|
||||
import processing.core.*;
|
||||
|
||||
public class Env {
|
||||
|
||||
PApplet parent;
|
||||
MethClaInterface m_engine;
|
||||
int m_nodeId;
|
||||
|
||||
public Env (PApplet theParent) {
|
||||
this.parent = theParent;
|
||||
parent.registerMethod("dispose", this);
|
||||
m_engine = new MethClaInterface();
|
||||
}
|
||||
|
||||
public void play(SoundObject input, float attackTime, float sustainTime, float sustainLevel, float releaseTime){
|
||||
m_nodeId = m_engine.envelopePlay(input.returnId(), attackTime, sustainTime, sustainLevel, releaseTime);
|
||||
}
|
||||
|
||||
public void dispose(){
|
||||
//m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
package processing.sound;
|
||||
import processing.core.*;
|
||||
|
||||
public class FFT {
|
||||
|
||||
PApplet parent;
|
||||
private MethClaInterface m_engine;
|
||||
private long ptr;
|
||||
|
||||
public FFT(PApplet theParent) {
|
||||
this.parent = theParent;
|
||||
parent.registerMethod("dispose", this);
|
||||
m_engine = new MethClaInterface();
|
||||
}
|
||||
|
||||
public void input(SoundObject input, int fftSize){
|
||||
ptr = m_engine.fft(input.returnId(), fftSize);
|
||||
}
|
||||
|
||||
public void process(float[] value){
|
||||
float[] m_value = m_engine.poll_fft(ptr);
|
||||
int num_samples = Math.min(value.length, m_value.length);
|
||||
for(int i=0; i<num_samples; i++){
|
||||
value[i] = m_value[i];
|
||||
}
|
||||
}
|
||||
/*
|
||||
public void stop(){
|
||||
m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
|
||||
public int returnId(){
|
||||
return m_nodeId;
|
||||
}
|
||||
*/
|
||||
public void dispose() {
|
||||
m_engine.destroy_fft(ptr);
|
||||
//m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package processing.sound;
|
||||
|
||||
import processing.core.PApplet;
|
||||
|
||||
public class HPF implements SoundObject{
|
||||
|
||||
PApplet parent;
|
||||
private MethClaInterface m_engine;
|
||||
private int m_nodeId;
|
||||
private int[] m_m = {0,0};
|
||||
private float m_freq = 100;
|
||||
private float m_res = 1;
|
||||
|
||||
public HPF(PApplet theParent) {
|
||||
this.parent = theParent;
|
||||
parent.registerMethod("dispose", this);
|
||||
m_engine = new MethClaInterface();
|
||||
}
|
||||
|
||||
public void play(SoundObject input, float freq, float res){
|
||||
m_freq=freq; m_res=res;
|
||||
m_nodeId = m_engine.highPassPlay(input.returnId(), m_freq, m_res);
|
||||
}
|
||||
|
||||
public void play(SoundObject input, float freq){
|
||||
m_freq=freq;
|
||||
m_nodeId = m_engine.highPassPlay(input.returnId(), m_freq, m_res);
|
||||
}
|
||||
|
||||
private void set(){
|
||||
m_engine.filterSet(m_freq, m_res, m_nodeId);
|
||||
}
|
||||
|
||||
public void set(float freq, float res){
|
||||
m_freq=freq; m_res=res;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void freq(float freq){
|
||||
m_freq=freq;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void res(float res){
|
||||
m_res=res;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public int[] returnId(){
|
||||
return m_m;
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
//m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
//m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package processing.sound;
|
||||
|
||||
import processing.core.PApplet;
|
||||
|
||||
public class LPF implements SoundObject{
|
||||
|
||||
PApplet parent;
|
||||
private MethClaInterface m_engine;
|
||||
private int m_nodeId;
|
||||
private int[] m_m = {0,0};
|
||||
private float m_freq = 100;
|
||||
private float m_res = 1;
|
||||
|
||||
public LPF(PApplet theParent) {
|
||||
this.parent = theParent;
|
||||
parent.registerMethod("dispose", this);
|
||||
m_engine = new MethClaInterface();
|
||||
}
|
||||
|
||||
public void play(SoundObject input, float freq, float res){
|
||||
m_freq=freq; m_res=res;
|
||||
m_nodeId = m_engine.lowPassPlay(input.returnId(), m_freq, m_res);
|
||||
}
|
||||
|
||||
public void play(SoundObject input, float freq){
|
||||
m_freq=freq;
|
||||
m_nodeId = m_engine.lowPassPlay(input.returnId(), m_freq, m_res);
|
||||
}
|
||||
|
||||
private void set(){
|
||||
m_engine.filterSet(m_freq, m_res, m_nodeId);
|
||||
}
|
||||
|
||||
public void set(float freq, float res){
|
||||
m_freq=freq; m_res=res;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void freq(float freq){
|
||||
m_freq=freq;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void res(float res){
|
||||
m_res=res;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public int[] returnId(){
|
||||
return m_m;
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
//m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
//m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package processing.sound;
|
||||
|
||||
public class MethClaInterface
|
||||
{
|
||||
// load Library
|
||||
static {
|
||||
System.loadLibrary("MethClaInterface");
|
||||
}
|
||||
// Functions I want
|
||||
|
||||
// Engine
|
||||
|
||||
public native int engineNew(int sampleRate, int bufferSize );
|
||||
|
||||
public native void engineStart();
|
||||
|
||||
public native void engineStop();
|
||||
|
||||
// general Synth methods
|
||||
|
||||
public native void synthStop(int[] nodeId);
|
||||
|
||||
// general Oscillator methods
|
||||
|
||||
public native void oscSet(float freq, float amp, float add, float pos, int[] nodeId);
|
||||
|
||||
// Sine Wave Oscillator
|
||||
|
||||
public native int[] sinePlay(float freq, float amp, float add, float pos);
|
||||
|
||||
//Saw Wave Oscillator
|
||||
|
||||
public native int[] sawPlay(float freq, float amp, float add, float pos);
|
||||
|
||||
//Square Wave Oscillator
|
||||
|
||||
public native int[] sqrPlay(float freq, float amp, float add, float pos);
|
||||
|
||||
public native void sqrSet(float freq, float amp, float add, float pos, int[] nodeId);
|
||||
|
||||
// Triangle Wave Oscillator
|
||||
|
||||
public native int[] triPlay(float freq, float amp, float add, float pos);
|
||||
|
||||
// Pulse Wave Oscillator
|
||||
|
||||
public native int[] pulsePlay(float freq, float width, float amp, float add, float pos);
|
||||
|
||||
public native void pulseSet(float freq, float width, float amp, float add, float pos, int[] nodeId);
|
||||
|
||||
// SoundFile
|
||||
|
||||
public native int[] soundFileInfo(String path);
|
||||
|
||||
public native int[] soundFilePlayMono(float rate, float pos, float amp, float add, boolean loop, String path, float dur, int cue);
|
||||
|
||||
public native int[] soundFilePlayMulti(float rate, float amp, float add, boolean loop, String path, float dur, int cue);
|
||||
|
||||
public native void soundFileSetMono(float rate, float pos, float amp, float add, int[] nodeId);
|
||||
|
||||
public native void soundFileSetStereo(float rate, float amp, float add, int[] nodeId);
|
||||
|
||||
// Noise
|
||||
|
||||
public native int[] whiteNoisePlay(float amp, float add, float pos);
|
||||
|
||||
public native void whiteNoiseSet(float amp, float add, float pos, int[] nodeId);
|
||||
|
||||
// Envelope
|
||||
|
||||
public native int envelopePlay(int[] input, float attackTime, float sustainTime, float sustainLevel, float releaseTime);
|
||||
|
||||
public native int doneAfter(float seconds);
|
||||
|
||||
// Filters
|
||||
|
||||
public native int highPassPlay(int[] input, float freq, float res);
|
||||
|
||||
public native int lowPassPlay(int[] input, float freq, float res);
|
||||
|
||||
public native int bandPassPlay(int[] input, float freq, float res);
|
||||
|
||||
public native void filterSet(float freq, float res, int nodeId);
|
||||
|
||||
// Delay
|
||||
|
||||
public native int delayPlay(int[] input, float maxDelayTime, float delayTime, float feedBack);
|
||||
|
||||
public native void delaySet(float delayTime, float feedBack, int nodeId);
|
||||
|
||||
// Patch cable
|
||||
|
||||
//public native int out(int[] in, int[] out);
|
||||
|
||||
// Pan + Out
|
||||
|
||||
// public native int out(float pos, int nodeId);
|
||||
|
||||
// connect
|
||||
|
||||
// public native void connect(int nodeIdOut, int nodeIdIn);
|
||||
|
||||
// Descriptors
|
||||
|
||||
// Amplitude Follower
|
||||
|
||||
public native long amplitude(int[] nodeId);
|
||||
|
||||
public native float poll_amplitude(long ptr);
|
||||
|
||||
public native void destroy_amplitude(long ptr);
|
||||
|
||||
// FFT
|
||||
|
||||
public native long fft(int[] nodeId, int fftSize);
|
||||
|
||||
public native float[] poll_fft(long ptr);
|
||||
|
||||
public native void destroy_fft(long ptr);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package processing.sound;
|
||||
|
||||
public interface Oscillator extends SoundObject {
|
||||
|
||||
public void play(float freq, float amp, float add, float pos);
|
||||
public void play(float freq, float amp, float add);
|
||||
public void play(float freq, float amp);
|
||||
public void play();
|
||||
/* for modulation
|
||||
public void play(Oscillator freq, float amp, float add);
|
||||
public void play(Oscillator freq, float amp);
|
||||
public void play(float freq, Oscillator amp, float add);
|
||||
public void play(float freq, Oscillator amp);
|
||||
public void play(float freq, float amp, Oscillator add);
|
||||
public void play(Oscillator freq, Oscillator amp, float add);
|
||||
public void play(Oscillator freq, Oscillator amp);
|
||||
public void play(float freq, Oscillator amp, Oscillator add);
|
||||
public void play(Oscillator freq, float amp, Oscillator add);
|
||||
public void play(Oscillator freq, Oscillator amp, Oscillator add);
|
||||
*/
|
||||
public void freq(float freq);
|
||||
public void amp(float amp);
|
||||
public void add(float add);
|
||||
public void pan(float pos);
|
||||
public void set(float freq, float amp, float add, float pan);
|
||||
public void stop();
|
||||
public void dispose();
|
||||
|
||||
public int[] returnId();
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package processing.sound;
|
||||
|
||||
import processing.core.PApplet;
|
||||
|
||||
public class Pulse implements SoundObject {
|
||||
|
||||
PApplet parent;
|
||||
MethClaInterface m_engine;
|
||||
private int[] m_nodeId = {-1,-1};
|
||||
private float m_freq = 0;
|
||||
private float m_width = 0;
|
||||
private float m_amp = 0;
|
||||
private float m_add = 0;
|
||||
private float m_pos = 0;
|
||||
|
||||
public Pulse(PApplet theParent) {
|
||||
this.parent = theParent;
|
||||
parent.registerMethod("dispose", this);
|
||||
m_engine = new MethClaInterface();
|
||||
}
|
||||
|
||||
public void play(){
|
||||
m_nodeId = m_engine.pulsePlay(m_freq, m_width, m_amp, m_add, m_pos);
|
||||
};
|
||||
|
||||
public void play(float freq, float width, float amp, float add, float pos){
|
||||
m_freq=freq; m_width=width; m_amp=amp; m_add=add; m_pos=pos;
|
||||
this.play();
|
||||
};
|
||||
|
||||
public void play(float freq, float width, float amp, float add){
|
||||
m_freq=freq; m_width=width; m_amp=amp; m_add=add;
|
||||
this.play();
|
||||
};
|
||||
|
||||
public void play(float freq, float width, float amp){
|
||||
m_freq=freq; m_width=width; m_amp=amp;
|
||||
this.play();
|
||||
};
|
||||
|
||||
public void play(float freq, float width){
|
||||
m_freq=freq; m_width=width;
|
||||
this.play();
|
||||
};
|
||||
|
||||
public void play(float freq){
|
||||
m_freq=freq;
|
||||
this.play();
|
||||
};
|
||||
|
||||
private void set(){
|
||||
if(m_nodeId[0] != -1 ) {
|
||||
m_engine.pulseSet(m_freq, m_width, m_amp, m_add, m_pos, m_nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(float freq, float width, float amp, float add, float pos){
|
||||
m_freq=freq; m_width=width; m_amp=amp; m_add=add; m_pos=pos;
|
||||
this.set();
|
||||
};
|
||||
|
||||
public void freq(float freq){
|
||||
m_freq=freq;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void width(float width){
|
||||
m_width=width;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void amp(float amp){
|
||||
m_amp=amp;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void add(float add){
|
||||
m_add=add;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void pan(float pos){
|
||||
m_pos=pos;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
m_engine.synthStop(m_nodeId);
|
||||
};
|
||||
|
||||
public int[] returnId(){
|
||||
return m_nodeId;
|
||||
};
|
||||
|
||||
public void dispose(){
|
||||
m_engine.synthStop(m_nodeId);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package processing.sound;
|
||||
|
||||
import processing.core.PApplet;
|
||||
|
||||
public class SawOsc implements Oscillator{
|
||||
|
||||
PApplet parent;
|
||||
private MethClaInterface m_engine;
|
||||
private int[] m_nodeId = {-1,-1};
|
||||
private float m_freq = 0;
|
||||
private float m_amp = 0;
|
||||
private float m_add = 0;
|
||||
private float m_pos = 0;
|
||||
|
||||
public SawOsc(PApplet theParent) {
|
||||
this.parent = theParent;
|
||||
parent.registerMethod("dispose", this);
|
||||
m_engine = new MethClaInterface();
|
||||
}
|
||||
|
||||
public void play(float freq, float amp, float add, float pos){
|
||||
m_freq=freq; m_amp=amp; m_add=add; m_pos=pos;
|
||||
m_nodeId = m_engine.sawPlay(m_freq, m_amp, m_add, m_pos);
|
||||
}
|
||||
|
||||
public void play(float freq, float amp, float add){
|
||||
m_freq=freq; m_amp=amp; m_add=add;
|
||||
m_nodeId = m_engine.sawPlay(m_freq, m_amp, m_add, m_pos);
|
||||
}
|
||||
|
||||
public void play(float freq, float amp){
|
||||
m_freq=freq; m_amp=amp;
|
||||
m_nodeId = m_engine.sawPlay(m_freq, m_amp, m_add, m_pos);
|
||||
}
|
||||
|
||||
public void play(){
|
||||
m_nodeId = m_engine.sawPlay(m_freq, m_amp, m_add, m_pos);
|
||||
}
|
||||
|
||||
private void set(){
|
||||
if(m_nodeId[0] != -1 ) {
|
||||
m_engine.oscSet(m_freq, m_amp, m_add, m_pos, m_nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(float freq, float amp, float add, float pos){
|
||||
m_freq=freq; m_amp=amp; m_add=add; m_pos=pos;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void freq(float freq){
|
||||
m_freq=freq;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void amp(float amp){
|
||||
m_amp=amp;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void add(float add){
|
||||
m_add=add;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void pan(float pos){
|
||||
m_pos=pos;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
|
||||
public int[] returnId(){
|
||||
return m_nodeId;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package processing.sound;
|
||||
import processing.core.*;
|
||||
|
||||
public class SinOsc implements Oscillator {
|
||||
|
||||
PApplet parent;
|
||||
private MethClaInterface m_engine;
|
||||
private int[] m_nodeId = {-1,-1};
|
||||
private float m_freq = 0;
|
||||
private float m_amp = 0;
|
||||
private float m_add = 0;
|
||||
private float m_pos = 0;
|
||||
|
||||
public SinOsc(PApplet theParent) {
|
||||
this.parent = theParent;
|
||||
parent.registerMethod("dispose", this);
|
||||
m_engine = new MethClaInterface();
|
||||
}
|
||||
|
||||
public void play(float freq, float amp, float add, float pos){
|
||||
m_freq=freq; m_amp=amp; m_add=add; m_pos=pos;
|
||||
m_nodeId = m_engine.sinePlay(m_freq, m_amp, m_add, m_pos);
|
||||
}
|
||||
|
||||
public void play(float freq, float amp, float add){
|
||||
m_freq=freq; m_amp=amp; m_add=add;
|
||||
m_nodeId = m_engine.sinePlay(m_freq, m_amp, m_add, m_pos);
|
||||
}
|
||||
|
||||
public void play(float freq, float amp){
|
||||
m_freq=freq; m_amp=amp;
|
||||
m_nodeId = m_engine.sinePlay(m_freq, m_amp, m_add, m_pos);
|
||||
}
|
||||
|
||||
public void play(){
|
||||
m_nodeId = m_engine.sinePlay(m_freq, m_amp, m_add, m_pos);
|
||||
}
|
||||
|
||||
private void set(){
|
||||
if(m_nodeId[0] != -1 ) {
|
||||
m_engine.oscSet(m_freq, m_amp, m_add, m_pos, m_nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(float freq, float amp, float add, float pos){
|
||||
m_freq=freq; m_amp=amp; m_add=add; m_pos=pos;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void freq(float freq){
|
||||
m_freq=freq;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void amp(float amp){
|
||||
m_amp=amp;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void add(float add){
|
||||
m_add=add;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void pan(float pos){
|
||||
m_pos=pos;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
|
||||
public int[] returnId(){
|
||||
return m_nodeId;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
*
|
||||
* Copyright ##copyright## ##author##
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307 USA
|
||||
*
|
||||
* @author ##Wilm Thoben##
|
||||
* @modified ##10/23/2013##
|
||||
*/
|
||||
|
||||
package processing.sound;
|
||||
import processing.core.*;
|
||||
|
||||
public class Sound{
|
||||
|
||||
// myParent is a reference to the parent sketch
|
||||
PApplet parent;
|
||||
MethClaInterface methCla;
|
||||
|
||||
public final static String VERSION = "##library.prettyVersion##";
|
||||
|
||||
public Sound(PApplet parent, int sampleRate, int bufferSize) {
|
||||
this.parent = parent;
|
||||
parent.registerMethod("dispose", this);
|
||||
welcome();
|
||||
methCla = new MethClaInterface();
|
||||
methCla.engineNew(sampleRate, bufferSize);
|
||||
methCla.engineStart();
|
||||
}
|
||||
|
||||
public Sound(PApplet theParent) {
|
||||
this(theParent, 44100, 512);
|
||||
}
|
||||
|
||||
private void welcome() {
|
||||
System.out.println("##library.name## ##library.prettyVersion## by ##author##");
|
||||
}
|
||||
|
||||
public void engineStop() {
|
||||
methCla.engineStop();
|
||||
}
|
||||
|
||||
public static String version() {
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
methCla.engineStop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
package processing.sound;
|
||||
import processing.core.*;
|
||||
|
||||
public class SoundFile implements SoundObject {
|
||||
|
||||
PApplet parent;
|
||||
MethClaInterface m_engine;
|
||||
private int[] m_nodeId = {-1,-1};
|
||||
int[] m_info;
|
||||
String m_filePath;
|
||||
float m_rate=1;
|
||||
float m_amp=1;
|
||||
float m_add=0;
|
||||
int m_cue=0;
|
||||
float m_pos=0;
|
||||
|
||||
|
||||
public SoundFile(PApplet theParent, String path) {
|
||||
this.parent = theParent;
|
||||
parent.registerMethod("dispose", this);
|
||||
|
||||
m_engine = new MethClaInterface();
|
||||
m_filePath=theParent.dataPath(path);
|
||||
m_info = m_engine.soundFileInfo(m_filePath);
|
||||
}
|
||||
|
||||
public int frames(){
|
||||
return (int)m_info[0];
|
||||
}
|
||||
|
||||
public int sampleRate(){
|
||||
return (int)m_info[1];
|
||||
}
|
||||
|
||||
public int channels(){
|
||||
return (int)m_info[2];
|
||||
}
|
||||
|
||||
public float duration(){
|
||||
return (float) this.frames()/this.sampleRate();
|
||||
}
|
||||
|
||||
public void play(){
|
||||
if(this.channels() < 2){
|
||||
m_nodeId = m_engine.soundFilePlayMono(m_rate, m_pos, m_amp, m_add, false, m_filePath, this.duration()*(1/m_rate), m_cue);
|
||||
}
|
||||
else if(this.channels() == 2){
|
||||
m_nodeId = m_engine.soundFilePlayMulti(m_rate, m_amp, m_add, false, m_filePath, this.duration()*(1/m_rate), m_cue);
|
||||
}
|
||||
}
|
||||
|
||||
public void play(float rate, float pos, float amp, float add, int cue){
|
||||
m_rate=rate; m_pos=pos; m_amp=amp; m_add=add; m_cue=(int)cue * m_info[1];
|
||||
this.play();
|
||||
}
|
||||
|
||||
public void play(float rate, float pos, float amp, float add){
|
||||
m_rate=rate; m_pos=pos; m_amp=amp; m_add=add;
|
||||
this.play();
|
||||
}
|
||||
|
||||
public void play(float rate, float pos, float amp){
|
||||
m_rate=rate; m_pos=pos; m_amp=amp;
|
||||
this.play();
|
||||
}
|
||||
|
||||
public void play(float rate, float amp){
|
||||
m_rate=rate; m_amp=amp;
|
||||
this.play();
|
||||
}
|
||||
|
||||
public void play(float rate){
|
||||
m_rate=rate;
|
||||
this.play();
|
||||
}
|
||||
|
||||
public void loop(){
|
||||
if(this.channels() < 2){
|
||||
m_nodeId = m_engine.soundFilePlayMono(m_rate, m_pos, m_amp, m_add, true, m_filePath, this.duration()*(1/m_rate), m_cue);
|
||||
}
|
||||
else if(this.channels() == 2){
|
||||
m_nodeId = m_engine.soundFilePlayMulti(m_rate, m_amp, m_add, true, m_filePath, this.duration()*(1/m_rate), m_cue);
|
||||
}
|
||||
}
|
||||
|
||||
public void loop(float rate, float pos, float amp, float add, int cue){
|
||||
m_rate=rate; m_pos=pos; m_amp=amp; m_add=add; m_cue=cue;
|
||||
this.loop();
|
||||
}
|
||||
|
||||
public void loop(float rate, float pos, float amp, float add){
|
||||
m_rate=rate; m_pos=pos; m_amp=amp; m_add=add;
|
||||
this.loop();
|
||||
}
|
||||
|
||||
public void loop(float rate, float pos, float amp){
|
||||
m_rate=rate; m_pos=pos; m_amp=amp;
|
||||
this.loop();
|
||||
}
|
||||
|
||||
public void loop(float rate, float amp){
|
||||
m_rate=rate; m_amp=amp;
|
||||
this.loop();
|
||||
}
|
||||
|
||||
public void loop(float rate){
|
||||
m_rate=rate;
|
||||
this.loop();
|
||||
}
|
||||
|
||||
public void cue(int cue){
|
||||
m_cue = (int)cue * m_info[1];
|
||||
}
|
||||
|
||||
private void set(){
|
||||
if(m_nodeId[0] != -1 ) {
|
||||
if(this.channels() < 2){
|
||||
m_engine.soundFileSetMono(m_rate, m_pos, m_amp, m_add, m_nodeId);
|
||||
}
|
||||
else if(this.channels() == 2){
|
||||
m_engine.soundFileSetStereo(m_rate, m_amp, m_add, m_nodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void set(float rate, float pos, float amp, float add){
|
||||
m_rate=rate;m_pos=pos;m_amp=amp;m_add=add;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void pan(float pos){
|
||||
if(this.channels() > 1){
|
||||
throw new UnsupportedOperationException("Panning is not supported for stereo files");
|
||||
}
|
||||
|
||||
m_pos=pos;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void rate(float rate){
|
||||
m_rate=rate;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void amp(float amp){
|
||||
m_amp=amp;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void add(float add){
|
||||
m_add=add;
|
||||
this.set();
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
|
||||
public int[] returnId(){
|
||||
return m_nodeId;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
m_engine.synthStop(m_nodeId);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user