Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Showing
with 430 additions and 183 deletions
......@@ -44,20 +44,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<!-- Our javascript code -->
<script type="text/javascript">
// initialise audio
maximJs.maxiAudio.init();
var audio = new maximJs.maxiAudio();
audio.init();
//This shows how to use maximilian to do basic amplitude modulation
var mySine = new maximJs.maxiOsc();
var myOtherSine = new maximJs.maxiOsc();
maximJs.maxiAudio.play = function(){
audio.play = function(){
// these two sines will beat together. They're now a bit too loud though..
output = mySine.sinewave(440)*myOtherSine.sinewave(1);
this.output = mySine.sinewave(440)*myOtherSine.sinewave(1);
}
</script>
</head>
......@@ -70,20 +67,16 @@ maximJs.maxiAudio.play = function(){
Basic amplitude modulation
</p>
<pre class="prettyprint lang-js linenums:true" id="quine" style="border:4px solid #88c" >
// initialise audio
maximJs.maxiAudio.init();
var audio = new maximJs.maxiAudio();
audio.init();
//This shows how to use maximilian to do basic amplitude modulation
var mySine = new maximJs.maxiOsc();
var myOtherSine = new maximJs.maxiOsc();
maximJs.maxiAudio.play = function(){
audio.play = function(){
// these two sines will beat together. They're now a bit too loud though..
output = mySine.sinewave(440)*myOtherSine.sinewave(1);
}
this.output = mySine.sinewave(440)*myOtherSine.sinewave(1);
}
</pre>
</body></html>
......@@ -44,21 +44,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<!-- Our javascript code -->
<script type="text/javascript">
// initialise audio
maximJs.maxiAudio.init();
var audio = new maximJs.maxiAudio();
audio.init();
//This shows how to use maximilian to do basic amplitude modulation
var mySine = new maximJs.maxiOsc();
var myOtherSine = new maximJs.maxiOsc();
var myPhasor = new maximJs.maxiOsc();
maximJs.maxiAudio.play = function(){
audio.play = function(){
// these two sines will beat together. They're now a bit too loud though..
output = mySine.sinewave(440)*myOtherSine.sinewave(myPhasor.phasor(0.1,0,440));
this.output = mySine.sinewave(440)*myOtherSine.sinewave(myPhasor.phasor(0.1,0,440));
}
</script>
</head>
......@@ -72,17 +69,17 @@ maximJs.maxiAudio.play = function(){
</p>
<pre class="prettyprint lang-js linenums:true" id="quine" style="border:4px solid #88c" >
// initialise audio
maximJs.maxiAudio.init();
var audio = new maximJs.maxiAudio();
audio.init();
//This shows how to use maximilian to do basic amplitude modulation
var mySine = new maximJs.maxiOsc();
var myOtherSine = new maximJs.maxiOsc();
var myPhasor = new maximJs.maxiOsc();
maximJs.maxiAudio.play = function(){
audio.play = function(){
// these two sines will beat together. They're now a bit too loud though..
output = mySine.sinewave(440)*myOtherSine.sinewave(myPhasor.phasor(0.1,0,440));
this.output = mySine.sinewave(440)*myOtherSine.sinewave(myPhasor.phasor(0.1,0,440));
}
</pre>
</body></html>
......@@ -44,21 +44,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<!-- Our javascript code -->
<script type="text/javascript">
// initialise audio
maximJs.maxiAudio.init();
var audio = new maximJs.maxiAudio();
audio.init();
//This shows how to use maximilian to do basic amplitude modulation
var mySine = new maximJs.maxiOsc();
var myOtherSine = new maximJs.maxiOsc();
maximJs.maxiAudio.play = function(){
audio.play = function(){
// these two sines will beat together. They're now a bit too loud though.
output = mySine.sinewave(440+(myOtherSine.sinewave(1)*100));
this.output = mySine.sinewave(440+(myOtherSine.sinewave(1)*100));
}
</script>
</head>
......@@ -73,13 +70,16 @@ maximJs.maxiAudio.play = function(){
<pre class="prettyprint lang-js linenums:true" id="quine" style="border:4px solid #88c" >
var audio = new maximJs.maxiAudio();
audio.init();
//This shows how to use maximilian to do basic amplitude modulation
var mySine = new maximJs.maxiOsc();
var myOtherSine = new maximJs.maxiOsc();
function play(){
audio.play = function(){
// these two sines will beat together. They're now a bit too loud though.
output = mySine.sinewave(440+(myOtherSine.sinewave(1)*100));
this.output = mySine.sinewave(440+(myOtherSine.sinewave(1)*100));
}
</pre>
......
......@@ -44,7 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<!-- Our javascript code -->
<script type="text/javascript">
maximJs.maxiAudio.init();
var audio = new maximJs.maxiAudio();
audio.init();
//This shows how to use maximilian to do basic frequency modulation
var mySine = new maximJs.maxiOsc();
......@@ -52,8 +53,8 @@ var myOtherSine = new maximJs.maxiOsc();
var myLastSine = new maximJs.maxiOsc();
var myPhasor = new maximJs.maxiOsc();
maximJs.maxiAudio.play = function(){
output=mySine.sinewave(myOtherSine.sinewave(myLastSine.sinewave(0.1)*30)*440);//awesome bassline
audio.play = function(){
this.output=mySine.sinewave(myOtherSine.sinewave(myLastSine.sinewave(0.1)*30)*440);//awesome bassline
}
......@@ -70,14 +71,17 @@ maximJs.maxiAudio.play = function(){
</p>
<pre class="prettyprint lang-js linenums:true" id="quine" style="border:4px solid #88c" >
var audio = new maximJs.maxiAudio();
audio.init();
//This shows how to use maximilian to do basic frequency modulation
var mySine = new maximJs.maxiOsc();
var myOtherSine = new maximJs.maxiOsc();
var myLastSine = new maximJs.maxiOsc();
var myPhasor = new maximJs.maxiOsc();
maximJs.maxiAudio.play = function(){
output=mySine.sinewave(myOtherSine.sinewave(myLastSine.sinewave(0.1)*30)*440);//awesome bassline
audio.play = function(){
this.output=mySine.sinewave(myOtherSine.sinewave(myLastSine.sinewave(0.1)*30)*440);//awesome bassline
}
</pre>
</body></html>
......@@ -44,7 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<!-- Our javascript code -->
<script type="text/javascript">
maximJs.maxiAudio.init();
var audio = new maximJs.maxiAudio();
audio.init();
var mySine = new maximJs.maxiOsc(); // This is the oscillator we will use to generate the test tone
var myClock = new maximJs.maxiClock(); // This will allow us to generate a clock signal and do things at specific times
......@@ -56,7 +57,7 @@ myClock.setTempo(120);// This sets the tempo in Beats Per Minute
freq=20; // Here we initialise the variable
maximJs.maxiAudio.play = function(){
audio.play = function(){
myClock.ticker(); // This makes the clock object count at the current samplerate
//This is a 'conditional'. It does a test and then does something if the test is true
......@@ -66,7 +67,7 @@ maximJs.maxiAudio.play = function(){
} // The curly braces close the conditional
output=mySine.sinewave(freq);//simple as that!
this.output=mySine.sinewave(freq);//simple as that!
}
......@@ -83,7 +84,8 @@ maximJs.maxiAudio.play = function(){
</p>
<pre class="prettyprint lang-js linenums:true" id="quine" style="border:4px solid #88c" >
maximJs.maxiAudio.init();
var audio = new maximJs.maxiAudio();
audio.init();
var mySine = new maximJs.maxiOsc(); // This is the oscillator we will use to generate the test tone
var myClock = new maximJs.maxiClock(); // This will allow us to generate a clock signal and do things at specific times
......@@ -95,7 +97,7 @@ myClock.setTempo(120);// This sets the tempo in Beats Per Minute
freq=20; // Here we initialise the variable
maximJs.maxiAudio.play = function(){
audio.play = function(){
myClock.ticker(); // This makes the clock object count at the current samplerate
//This is a 'conditional'. It does a test and then does something if the test is true
......@@ -105,7 +107,8 @@ maximJs.maxiAudio.play = function(){
} // The curly braces close the conditional
output=mySine.sinewave(freq);//simple as that!
this.output=mySine.sinewave(freq);//simple as that!
}
</pre>
</body></html>
......@@ -43,7 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<!-- Our javascript code -->
<script type="text/javascript">
maximJs.maxiAudio.init();
var audio = new maximJs.maxiAudio();
audio.init();
var myCounter = new maximJs.maxiOsc(); //these oscillators will help us count and play sound
var mySquare = new maximJs.maxiOsc();
......@@ -51,12 +52,10 @@ var mySquare = new maximJs.maxiOsc();
//we're going to put the current count in this variable so that we can use it more easily.
var currentCount;
maximJs.maxiAudio.play = function(){
audio.play = function(){
CurrentCount = Math.floor(myCounter.phasor(1, 1, 9));//phasor can take three arguments; frequency, start value and end value
output=mySquare.square(CurrentCount*100);
}
</script>
</head>
......@@ -70,13 +69,16 @@ maximJs.maxiAudio.play = function(){
</p>
<pre class="prettyprint lang-js linenums:true" id="quine" style="border:4px solid #88c" >
var audio = new maximJs.maxiAudio();
audio.init();
var myCounter = new maximJs.maxiOsc(); //these oscillators will help us count and play sound
var mySquare = new maximJs.maxiOsc();
//we're going to put the current count in this variable so that we can use it more easily.
var currentCount;
maximJs.maxiAudio.play = function(){
audio.play = function(){
CurrentCount = Math.floor(myCounter.phasor(1, 1, 9));//phasor can take three arguments; frequency, start value and end value
output=mySquare.square(CurrentCount*100);
}
......
......@@ -44,14 +44,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<!-- Our javascript code -->
<script type="text/javascript">
maximJs.maxiAudio.init();
var audio = new maximJs.maxiAudio();
audio.init();
var myCounter = new maximJs.maxiOsc();
var mySwitchableOsc = new maximJs.maxiOsc();//these oscillators will help us count and make sound.
var CurrentCount;//we're going to put the current count in this variable so that we can use it more easily.
var myOscOutput;//we're going to stick the output here to make it easier to mess with stuff.
maximJs.maxiAudio.play = function(){
audio.play = function(){
CurrentCount=Math.floor(myCounter.phasor(1, 1, 9));//phasor can take three arguments; frequency, start value and end value.
if (CurrentCount<5){//simple if statement
......@@ -60,7 +61,7 @@ maximJs.maxiAudio.play = function(){
else if (CurrentCount>=5){//and the 'else' bit.
myOscOutput=mySwitchableOsc.sinewave(CurrentCount*50);//one osc object can produce whichever waveform you want.
}
output=myOscOutput;//point me at your speakers and fire.
this.output=myOscOutput;//point me at your speakers and fire.
}
......@@ -77,6 +78,24 @@ maximJs.maxiAudio.play = function(){
</p>
<pre class="prettyprint lang-js linenums:true" id="quine" style="border:4px solid #88c" >
var audio = new maximJs.maxiAudio();
audio.init();
var myCounter = new maximJs.maxiOsc();
var mySwitchableOsc = new maximJs.maxiOsc();//these oscillators will help us count and make sound.
var CurrentCount;//we're going to put the current count in this variable so that we can use it more easily.
var myOscOutput;//we're going to stick the output here to make it easier to mess with stuff.
audio.play = function(){
CurrentCount=Math.floor(myCounter.phasor(1, 1, 9));//phasor can take three arguments; frequency, start value and end value.
if (CurrentCount<5){//simple if statement
myOscOutput=mySwitchableOsc.square(CurrentCount*100);
}
else if (CurrentCount>=5){//and the 'else' bit.
myOscOutput=mySwitchableOsc.sinewave(CurrentCount*50);//one osc object can produce whichever waveform you want.
}
this.output=myOscOutput;//point me at your speakers and fire.
}
</pre>
</body></html>
......@@ -44,7 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<!-- Our javascript code -->
<script type="text/javascript">
maximJs.maxiAudio.init();
var audio = new maximJs.maxiAudio();
audio.init();
//these oscillators will help us count and make sound.
var myCounter = new maximJs.maxiOsc();
......@@ -55,7 +56,7 @@ var CurrentCount;//we're going to put the current count in this variable so that
var myOscOutput;//we're going to stick the output here to make it easier to mess with stuff.
var myArray=[100,200,300,400,300,200,100,240,640,360];
maximJs.maxiAudio.play = function(){
audio.play = function(){
CurrentCount=Math.round(myCounter.phasor(1*((another.sawn(0.1)+1)/2), 1, 9));//phasor can take three arguments; frequency, start value and end value.
if (CurrentCount<5) {//simple if statement
......@@ -66,11 +67,8 @@ maximJs.maxiAudio.play = function(){
myOscOutput=mySwitchableOsc.sawn(myArray[CurrentCount]);//one osc object can produce whichever waveform you want.
}
output=myOscOutput;//point me at your speakers and fire.
this.output=myOscOutput;//point me at your speakers and fire.
}
</script>
</head>
......@@ -84,21 +82,30 @@ maximJs.maxiAudio.play = function(){
</p>
<pre class="prettyprint lang-js linenums:true" id="quine" style="border:4px solid #88c" >
var audio = new maximJs.maxiAudio();
audio.init();
//these oscillators will help us count and make sound.
var myCounter = new maximJs.maxiOsc();
var mySwitchableOsc = new maximJs.maxiOsc();//these oscillators will help us count and make sound.
var mySwitchableOsc = new maximJs.maxiOsc();
var another = new maximJs.maxiOsc();
var CurrentCount;//we're going to put the current count in this variable so that we can use it more easily.
var myOscOutput;//we're going to stick the output here to make it easier to mess with stuff.
maximJs.maxiAudio.play = function(){
CurrentCount=Math.floor(myCounter.phasor(1, 1, 9));//phasor can take three arguments; frequency, start value and end value.
var myArray=[100,200,300,400,300,200,100,240,640,360];
audio.play = function(){
CurrentCount=Math.round(myCounter.phasor(1*((another.sawn(0.1)+1)/2), 1, 9));//phasor can take three arguments; frequency, start value and end value.
if (CurrentCount<5) {//simple if statement
myOscOutput=mySwitchableOsc.square(myArray[CurrentCount]);
}
else if (CurrentCount>=5) {//and the 'else' bit.
if (CurrentCount<5){//simple if statement
myOscOutput=mySwitchableOsc.square(CurrentCount*100);
myOscOutput=mySwitchableOsc.sawn(myArray[CurrentCount]);//one osc object can produce whichever waveform you want.
}
else if (CurrentCount>=5){//and the 'else' bit.
myOscOutput=mySwitchableOsc.sinewave(CurrentCount*50);//one osc object can produce whichever waveform you want.
}
output=myOscOutput;//point me at your speakers and fire.
this.output=myOscOutput;//point me at your speakers and fire.
}
</pre>
</body></html>
......@@ -43,7 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<!-- Our javascript code -->
<script type="text/javascript">
maximJs.maxiAudio.init();
var audio = new maximJs.maxiAudio();
audio.init();
var myCounter = new maximJs.maxiOsc(); //these oscillators will help us count and play sound
var mySwitchableOsc = new maximJs.maxiOsc();//
......@@ -61,7 +63,7 @@ myEnvelope.setSustain(1);
myEnvelope.setRelease(1000);
maximJs.maxiAudio.play = function(){
audio.play = function(){
//notice that we feed in a value of 1. to create an envelope shape we can apply later.
myCurrentVolume=myEnvelope.adsr(1.,myEnvelope.trigger);
......@@ -88,7 +90,7 @@ if (CurrentCount<5){
myOscOutput=mySwitchableOsc.sinewave(CurrentCount*50);//one osc object can produce whichever waveform you want.
}
output=myOscOutput*myCurrentVolume;//left speaker
this.output=myOscOutput*myCurrentVolume;//left speaker
}
......@@ -105,6 +107,10 @@ if (CurrentCount<5){
</p>
<pre class="prettyprint lang-js linenums:true" id="quine" style="border:4px solid #88c" >
var audio = new maximJs.maxiAudio();
audio.init();
var myCounter = new maximJs.maxiOsc(); //these oscillators will help us count and play sound
var mySwitchableOsc = new maximJs.maxiOsc();//
......@@ -113,15 +119,15 @@ var myOscOutput,myCurrentVolume;//
var myEnvelope = new maximJs.maxiEnv();
function setup(){
//Timing is in ms
myEnvelope.setAttack(0);
myEnvelope.setDecay(1); // Needs to be at least 1
myEnvelope.setSustain(1);
myEnvelope.setRelease(1000);
}
maximJs.maxiAudio.play = function(){
//Timing is in ms
myEnvelope.setAttack(0);
myEnvelope.setDecay(1); // Needs to be at least 1
myEnvelope.setSustain(1);
myEnvelope.setRelease(1000);
audio.play = function(){
//notice that we feed in a value of 1. to create an envelope shape we can apply later.
myCurrentVolume=myEnvelope.adsr(1.,myEnvelope.trigger);
......@@ -148,7 +154,7 @@ if (CurrentCount<5){
myOscOutput=mySwitchableOsc.sinewave(CurrentCount*50);//one osc object can produce whichever waveform you want.
}
output=myOscOutput*myCurrentVolume;//left speaker
this.output=myOscOutput*myCurrentVolume;//left speaker
}
</pre>
</body></html>
......@@ -50,14 +50,16 @@ void maxiFFT::setup(int _fftSize, int _windowSize, int _hopSize) {
bins = fftSize / 2;
hopSize = _hopSize;
buffer = (float *) malloc(fftSize * sizeof(float));
magnitudes = (float *) malloc(bins * sizeof(float));
// magnitudes = (float *) malloc(bins * sizeof(float));
magnitudes.resize(bins);
magnitudesDB = (float *) malloc(bins * sizeof(float));
phases = (float *) malloc(bins * sizeof(float));
// phases = (float *) malloc(bins * sizeof(float));
phases.resize(bins);
avgPower = new float;
memset(buffer, 0, fftSize * sizeof(float));
memset(magnitudes, 0, bins * sizeof(float));
// memset(magnitudes, 0, bins * sizeof(float));
memset(magnitudesDB, 0, bins * sizeof(float));
memset(phases, 0, bins * sizeof(float));
// memset(phases, 0, bins * sizeof(float));
*avgPower = 0;
pos =windowSize - hopSize;
newFFT = 0;
......@@ -73,9 +75,9 @@ bool maxiFFT::process(float value) {
newFFT = pos == windowSize;
if (newFFT) {
#if defined(__APPLE_CC__) && !defined(_NO_VDSP)
_fft->powerSpectrum_vdsp(0, buffer, window, magnitudes, phases);
_fft->powerSpectrum_vdsp(0, buffer, window, magnitudes.data(), phases.data());
#else
_fft->powerSpectrum(0, buffer, window, magnitudes, phases);
_fft->powerSpectrum(0, buffer, window, magnitudes.data(), phases.data());
#endif
//shift buffer back by one hop size
memcpy(buffer, buffer + hopSize, (windowSize - hopSize) * sizeof(float));
......@@ -89,9 +91,9 @@ bool maxiFFT::process(float value) {
float maxiFFT::magsToDB() {
#if defined(__APPLE_CC__) && !defined(_NO_VDSP)
_fft->convToDB_vdsp(magnitudes, magnitudesDB);
_fft->convToDB_vdsp(magnitudes.data(), magnitudesDB);
#else
_fft->convToDB(magnitudes, magnitudesDB);
_fft->convToDB(magnitudes.data(), magnitudesDB);
#endif
return *magnitudesDB;
}
......@@ -122,7 +124,7 @@ float maxiFFT::spectralCentroid() {
maxiFFT::~maxiFFT() {
delete _fft;
if (buffer)
delete[] buffer,magnitudes,phases,window, avgPower, magnitudesDB;
delete[] buffer,/*magnitudes,phases,*/window, avgPower, magnitudesDB;
}
......
......@@ -46,18 +46,26 @@ class maxiFFT {
public:
maxiFFT(){
_fft = NULL;
buffer = magnitudes = phases = window = avgPower = NULL;
buffer = /* magnitudes = phases = */window = avgPower = NULL;
};
~maxiFFT();
void setup(int fftSize, int windowSize, int hopSize);
bool process(float value);
float magsToDB();
float *magnitudes, *phases, *magnitudesDB;
float /* *magnitudes, *phases, */ *magnitudesDB;
vector<float> magnitudes, phases;
float *avgPower;
int windowSize;
int hopSize;
int bins;
vector<float> getMagnitudes() const{
return magnitudes;
}
vector<float> getPhases() const{
return phases;
}
// properties (emscr)
float getMagnitude(int n){
......@@ -97,6 +105,14 @@ public:
this->bins = n;
}
void setMagnitudes(vector<float> magnitudes_){
magnitudes = magnitudes_;
}
void setPhases(vector<float> phases_){
phases = phases_;
}
//features
float spectralFlatness();
float spectralCentroid();
......
......@@ -35,6 +35,9 @@ EMSCRIPTEN_BINDINGS(my_module_maxiFFT) {
.property("windowSize", &maxiFFT::getWindowSize, &maxiFFT::setWindowSize)
.property("hopSize", &maxiFFT::getHopSize, &maxiFFT::setHopSize)
.property("bins", &maxiFFT::getNumBins, &maxiFFT::setNumBins)
.property("magnitudes", &maxiFFT::getMagnitudes, &maxiFFT::setMagnitudes)
.property("phases", &maxiFFT::getPhases, &maxiFFT::setPhases)
;
// MAXI IFFT
......@@ -66,6 +69,7 @@ EMSCRIPTEN_BINDINGS(my_module_maxiFFT) {
.property("firstOctaveFrequency", &maxiFFTOctaveAnalyzer::getFirstOctFreq, &maxiFFTOctaveAnalyzer::setFirstOctFreq)
.property("averageFrequencyIncrement", &maxiFFTOctaveAnalyzer::getAvgFreqIncr, &maxiFFTOctaveAnalyzer::setAvgFreqIncr)
.function("getAverage", &maxiFFTOctaveAnalyzer::getAverage)
.function("getPeak", &maxiFFTOctaveAnalyzer::getPeak)
.function("getPeakHoldTime", &maxiFFTOctaveAnalyzer::getPeakHoldTime)
......
......@@ -72,7 +72,7 @@ public:
createDCTCoeffs();
}
// void mfcc(float* powerSpectrum, T *mfccs) {
void mfcc(vector<float> powerSpectrum, vector<T> mfccs) {
void mfcc(vector<float>& powerSpectrum, vector<T>& mfccs) {
melFilterAndLogSquare(powerSpectrum.data());
dct(mfccs.data());
}
......
......@@ -20,7 +20,7 @@ EMSCRIPTEN_BINDINGS(my_module_maxiMFCC) {
.smart_ptr_constructor("shared_ptr<maxiMFCC>",&std::make_shared<maxiMFCC>)
.function("setup", &maxiMFCC::setup)
.function("mfcc", &maxiMFCC::mfcc)
.function("mfcc", &maxiMFCC::mfcc, allow_raw_pointers())
;
};
#endif
......@@ -33,6 +33,15 @@ public:
static void clearVectorDbl(vector<double>& vecIn) {
vecIn.clear();
}
static void clearVectorFloat(vector<float>& vecIn) {
vecIn.clear();
}
// static void pr(){
// EM_ASM_({
// Module.print('I received: ' + $0);
// }, 100);
// }
};
using namespace emscripten;
......@@ -41,11 +50,14 @@ EMSCRIPTEN_BINDINGS(my_module) {
register_vector<int>("VectorInt");
register_vector<double>("VectorDouble");
register_vector<char>("VectorChar");
// register_vector<float>("VectorFloat");
register_vector<float>("VectorFloat");
class_<vectorTools>("vectorTools")
.constructor<>()
.class_function("clearVectorDbl", &vectorTools::clearVectorDbl)
.class_function("clearVectorFloat", &vectorTools::clearVectorFloat)
// .class_function("print", &vectorTools::pr)
;
// class_<testVectorHolder>("testVectorHolder")
......@@ -75,6 +87,9 @@ EMSCRIPTEN_BINDINGS(my_module) {
class_<maxiSettings>("maxiSettings")
.constructor<>()
.class_function("setup", &maxiSettings::setup)
.property("sampleRate", &maxiSettings::getSampleRate, &maxiSettings::setSampleRate)
.property("channels", &maxiSettings::getNumChannels, &maxiSettings::setNumChannels)
.property("bufferSize", &maxiSettings::getBufferSize, &maxiSettings::setBufferSize)
;
......@@ -158,11 +173,14 @@ EMSCRIPTEN_BINDINGS(my_module) {
// .constructor<>()
// .constructor<double, double>()
.smart_ptr_constructor("shared_ptr<maxiLagExp<double>>",&std::make_shared<maxiLagExp<double>>, allow_raw_pointers()) // not sure how to override constructors with smart_ptr
// .smart_ptr_constructor("shared_ptr<maxiLagExp<double>>",&std::make_shared<maxiLagExp<double>>)
// .smart_ptr_constructor("shared_ptr<maxiLagExp<double>>",&std::make_shared<maxiLagExp<double>>)
.function("init", &maxiLagExp<double>::init)
.function("addSample", &maxiLagExp<double>::addSample)
.function("value", &maxiLagExp<double>::value)
.property("alpha", &maxiLagExp<double>::getAlpha, &maxiLagExp<double>::setAlpha)
.property("alphaReciprocal", &maxiLagExp<double>::getAlphaReciprocal, &maxiLagExp<double>::setAlphaReciprocal)
.property("val", &maxiLagExp<double>::value, &maxiLagExp<double>::setVal)
;
......@@ -172,10 +190,10 @@ EMSCRIPTEN_BINDINGS(my_module) {
.smart_ptr_constructor("shared_ptr<maxiSample>",&std::make_shared<maxiSample>)
// .property("length", &maxiSample::getLength, &maxiSample::setLength) // no work???
.function("getLength", &maxiSample::getLength)
// .function("setSample", &maxiSample::setSample)
// .function("setSample", &maxiSample::setSample)
.function("setSample", select_overload<void(vector<double>&)>(&maxiSample::setSample))
.function("setSample", select_overload<void(vector<double>&, int)>(&maxiSample::setSample))
// .function("getSummary", &maxiSample::getSummary)
.function("isReady", &maxiSample::isReady)
......@@ -190,8 +208,8 @@ EMSCRIPTEN_BINDINGS(my_module) {
.function("trigger", &maxiSample::trigger)
.function("clear", &maxiSample::clear)
// .function("normalise", &maxiSample::normalise)
// .function("autoTrim", &maxiSample::autoTrim)
// .function("normalise", &maxiSample::normalise)
// .function("autoTrim", &maxiSample::autoTrim)
// .function("load", &maxiSample::load)
// .function("read", &maxiSample::read, allow_raw_pointers())
......@@ -334,10 +352,13 @@ EMSCRIPTEN_BINDINGS(my_module) {
.function("setTicksPerBeat", &maxiClock::setTicksPerBeat)
.function("isTick", &maxiClock::isTick)
.property("tick", &maxiClock::getTick, &maxiClock::setTick)
.property("playHead", &maxiClock::getPlayHead, &maxiClock::setPlayHead)
.property("currentCount", &maxiClock::getCurrentCount, &maxiClock::setCurrentCount)
.property("currentCount", &maxiClock::getLastCount, &maxiClock::setLastCount)
.property("playHead", &maxiClock::getPlayHead, &maxiClock::setPlayHead)
.property("bps", &maxiClock::getBps, &maxiClock::setBps)
.property("bpm", &maxiClock::getBpm, &maxiClock::setBpm)
.property("tick", &maxiClock::getTick, &maxiClock::setTick)
.property("ticks", &maxiClock::getTicks, &maxiClock::setTicks)
;
......
......@@ -63,6 +63,30 @@ public:
maxiSettings::channels = initChannels;
maxiSettings::bufferSize = initBufferSize;
}
void setSampleRate(int sampleRate_){
sampleRate = sampleRate_;
}
void setNumChannels(int channels_){
channels = channels_;
}
void setBufferSize(int bufferSize_){
bufferSize = bufferSize_;
}
int getSampleRate() const{
return sampleRate;
}
int getNumChannels() const{
return channels;
}
int getBufferSize() const{
return bufferSize;
}
};
......@@ -199,9 +223,9 @@ class maxiMix {
double four[4];
double eight[8];
public:
double x;
double y;
double z;
// double x;
// double y;
// double z;
// ------------------------------------------------
// getters/setters
......@@ -244,7 +268,29 @@ public:
val = (alpha * newVal) + (alphaReciprocal * val);
}
inline T value() {
// getters/setters
void setAlpha(T alpha_){
alpha = alpha_;
}
void setAlphaReciprocal(T alphaReciprocal_){
alphaReciprocal = alphaReciprocal_;
}
void setVal(T val_){
val = val_;
}
T getAlpha() const{
return alpha;
}
T getAlphaReciprocal() const{
return alphaReciprocal;
}
inline T value() const{
return val;
}
......@@ -896,31 +942,63 @@ public:
int ticks;
bool tick;
// SETTERS
void setCurrentCount(int n){
this->currentCount = n;
}
void setTick(int tick){
this->tick = tick;
void setLastCount(int n){
this->lastCount = n;
}
void setPlayHead(int n){
this->playHead = n;
}
void setCurrentCount(int n){
this->currentCount = n;
void setBps(int bps_){
this->bps = bps_;
}
void setBpm(int bpm_){
this->bpm = bpm_;
}
int getTick() const{
return tick;
void setTick(int tick_){
this->tick = tick_;
}
int getPlayHead() const{
return playHead;
void setTicks(int ticks_){
this->ticks = ticks_;
}
// GETTERS
int getCurrentCount() const{
return currentCount;
}
int getLastCount() const{
return lastCount;
}
int getPlayHead() const{
return playHead;
}
double getBps() const{
return bps;
}
double getBpm() const{
return bpm;
}
bool getTick() const{
return tick;
}
int getTicks() const{
return ticks;
}
};
......
/*
Copyright notice for the base64 to arraybuffer conversion algorithm.
Copyright (c) 2011, Daniel Guerrero
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL DANIEL GUERRERO BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// might adopt some strange functions from Module?
// var maximJs = Module;
......@@ -71,7 +95,7 @@ maximJs.maxiArray = function maxiArray(){
// // reset length var
// this.length = this.vec.size();
// }
// }
// };
};
......@@ -127,16 +151,17 @@ maximJs.maxiArray.prototype.clear = function(useSq){
// tools
maximJs.maxiTools = function(){};
maximJs.maxiTools.prototype.arrayOfObj = function(obj, num){
var array = [];
// not sure this is good
// maximJs.maxiTools.arrayOfObj = function(obj, num){
// var array = [];
for(var i = 0; i < num; i++){
array.push(new obj());
}
return array;
};
// for(var i = 0; i < num; i++){
// array.push(new obj());
// }
// return array;
// };
maximJs.maxiTools.prototype.getArrayAsVectorDbl = function(arrayIn){
maximJs.maxiTools.getArrayAsVectorDbl = function(arrayIn){
var vecOut = new Module.VectorDouble();
for(var i = 0; i < arrayIn.length; i++){
vecOut.push_back(arrayIn[i]);
......@@ -145,7 +170,28 @@ maximJs.maxiTools.prototype.getArrayAsVectorDbl = function(arrayIn){
return vecOut;
};
maximJs.maxiTools.getBase64 = function(str) {
//check if the string is a data URI
if (str.indexOf(';base64,') != -1 ) {
//see where the actual data begins
var dataStart = str.indexOf(';base64,') + 8;
//check if the data is base64-encoded, if yes, return it
// taken from
// http://stackoverflow.com/a/8571649
return str.slice(dataStart).match(/^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{4}|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)$/) ? str.slice(dataStart) : false;
}
else return false;
}
maximJs.maxiTools._keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
maximJs.maxiTools.removePaddingFromBase64 = function(input) {
var lkey = maximJs.maxiTools._keyStr.indexOf(input.charAt(input.length - 1));
if(lkey == 64){
return input.substring(0,input.length - 1);
}
return input;
}
// ------------------------------------------------
......@@ -157,14 +203,14 @@ maximJs.maxiAudio = function() {
this.source = null;
this.analyser = null;
this.jsProcessor = null;
this.bufferSize = 1024;
this.initDone = false;
};
maximJs.maxiAudio.play = function(){};
// don't really need setup??
maximJs.maxiAudio.prototype.setup = function(){
maximJs.maxiAudio.setup = function(){
console.log("non-overrided setup");
};
......@@ -183,6 +229,11 @@ maximJs.maxiAudio.prototype.setNumChannels = function(isArray, numChannels_){
this.resetAudio();
};
maximJs.maxiAudio.prototype.setBufferSize = function(newBufferSize) {
this.bufferSize = newBufferSize;
this.resetAudio();
};
// use this if you want to keep num of outputs but change
// method e.g. array or not
maximJs.maxiAudio.prototype.outputIsArray = function(isArray){
......@@ -197,60 +248,34 @@ maximJs.maxiAudio.prototype.outputIsArray = function(isArray){
}
};
// function handling audio processing
// called byjsProcessor
maximJs.maxiAudio.prototype.process = function(event) {
var numChannels = event.outputBuffer.numberOfChannels;
var outputLength = event.outputBuffer.getChannelData(0).length;
// console.log("n");
for (var i = 0; i < outputLength; ++i) {
this.play();
if(self.output instanceof Array){
for (var channel = 0; channel < numChannels; channel++) {
event.outputBuffer.getChannelData(channel)[i] = this.output[channel];
}
}
else
{
for (var channel = 0; channel < numChannels; channel++) {
event.outputBuffer.getChannelData(channel)[i] = this.output;
}
}
}
}
.bind(this)
;
maximJs.maxiAudio.prototype.init = function() {
// Temporary patch until all browsers support unprefixed context.
this.context = new (window.AudioContext || window.webkitAudioContext)();
this.source = this.context.createBufferSource();
this.jsProcessor = this.context.createScriptProcessor(4096, this.numChannels, this.numChannels);
this.jsProcessor = this.context.createScriptProcessor(this.bufferSize, this.numChannels, this.numChannels);
// var process = this.process;
this.jsProcessor.onaudioprocess = function(event) {
var numChannels = event.outputBuffer.numberOfChannels;
var outputLength = event.outputBuffer.getChannelData(0).length;
// console.log("n");
for (var i = 0; i < outputLength; ++i) {
this.play();
if(self.output instanceof Array){
for (var channel = 0; channel < numChannels; channel++) {
event.outputBuffer.getChannelData(channel)[i] = this.output[channel];
var numChannels = event.outputBuffer.numberOfChannels;
var outputLength = event.outputBuffer.getChannelData(0).length;
// console.log("n");
for (var i = 0; i < outputLength; ++i) {
this.play();
if(this.output instanceof Array){
for (var channel = 0; channel < numChannels; channel++) {
event.outputBuffer.getChannelData(channel)[i] = this.output[channel];
}
}
}
else
{
for (var channel = 0; channel < numChannels; channel++) {
event.outputBuffer.getChannelData(channel)[i] = this.output;
}
}
}
}
else
{
for (var channel = 0; channel < numChannels; channel++) {
event.outputBuffer.getChannelData(channel)[i] = this.output;
}
}
}
}
.bind(this)
;
......@@ -289,19 +314,47 @@ maximJs.maxiAudio.prototype.loadSample = function(url, samplePlayer, contextIn)
samplePlayer.clear();
// Load asynchronously
var request = new XMLHttpRequest();
request.addEventListener("load",
function (evt) {
console.log("The transfer is complete.");
});
request.open("GET", url, true);
//check if url is actually a base64-encoded string
var b64 = maximJs.maxiTools.getBase64(url);
if (b64) {
//convert to arraybuffer
//modified version of this:
// https://github.com/danguer/blog-examples/blob/master/js/base64-binary.js
var ab_bytes = (b64.length/4) * 3;
var arrayBuffer = new ArrayBuffer(ab_bytes);
b64 = maximJs.maxiTools.removePaddingFromBase64(maximJs.maxiTools.removePaddingFromBase64(b64));
var bytes = parseInt((b64.length / 4) * 3, 10);
var uarray;
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
var j = 0;
uarray = new Uint8Array(arrayBuffer);
b64 = b64.replace(/[^A-Za-z0-9\+\/\=]/g, "");
for (i=0; i<bytes; i+=3) {
//get the 3 octects in 4 ascii chars
enc1 = maximJs.maxiTools._keyStr.indexOf(b64.charAt(j++));
enc2 = maximJs.maxiTools._keyStr.indexOf(b64.charAt(j++));
enc3 = maximJs.maxiTools._keyStr.indexOf(b64.charAt(j++));
enc4 = maximJs.maxiTools._keyStr.indexOf(b64.charAt(j++));
request.responseType = "arraybuffer";
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
uarray[i] = chr1;
if (enc3 != 64) uarray[i+1] = chr2;
if (enc4 != 64) uarray[i+2] = chr3;
}
request.onload = function() {
context.decodeAudioData(
request.response,
arrayBuffer,
function(buffer) {
// source.buffer = buffer;
// source.loop = true;
......@@ -324,8 +377,50 @@ maximJs.maxiAudio.prototype.loadSample = function(url, samplePlayer, contextIn)
function(buffer) {
console.log("Error decoding source!");
}
);
}
else {
// Load asynchronously
var request = new XMLHttpRequest();
request.addEventListener("load",
function (evt) {
console.log("The transfer is complete.");
});
request.open("GET", url, true);
request.responseType = "arraybuffer";
request.onload = function() {
context.decodeAudioData(
request.response,
function(buffer) {
// source.buffer = buffer;
// source.loop = true;
// source.start(0);
data = buffer.getChannelData(0);
if(data){
var myBufferData = new Module.VectorDouble();
// Module.vectorTools.clearVectorDbl(myBufferData);
for(var n = 0; n < data.length; n++){
myBufferData.push_back(data[n]);
}
samplePlayer.setSample(myBufferData/*, context.sampleRate*/);
}
},
function(buffer) {
console.log("Error decoding source!");
}
);
};
};
request.send();
}
request.send();
};