X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/blobdiff_plain/c7f552fd8888da2f0d8cfb228fe0f28d3df3a12c..b4b6f2ea75b9f0f3ca918f5b84016610bf7a4d4f:/interpretor/faust-0.9.47mr3/architecture/alchemy-as.cpp diff --git a/interpretor/faust-0.9.47mr3/architecture/alchemy-as.cpp b/interpretor/faust-0.9.47mr3/architecture/alchemy-as.cpp deleted file mode 100644 index 339cb0e..0000000 --- a/interpretor/faust-0.9.47mr3/architecture/alchemy-as.cpp +++ /dev/null @@ -1,463 +0,0 @@ -/************************************************************************ - - IMPORTANT NOTE : this file contains two clearly delimited sections : - the ARCHITECTURE section (in two parts) and the USER section. Each section - is governed by its own copyright and license. Please check individually - each section for license and copyright information. -*************************************************************************/ - -/*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/ - -/************************************************************************ - FAUST Architecture File - Copyright (C) 2010-2011 Travis Skare - --------------------------------------------------------------------- - This Architecture section is free software; you can redistribute it - and/or modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 3 of - the License, or (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; If not, see . - - EXCEPTION : As a special exception, you may create a larger work that - contains this FAUST architecture section and distribute - that work under terms of your choice, so long as that this FAUST - architecture section is not modified. - - - ************************************************************************ - ************************************************************************/ - -// Faust -> Alchemy -> ActionScript C++ Architecture File - -#include "AS3.h" -// math.h is needed for many faust examples, so include it. -// otherwise we have to hand-edit c++. -#include "math.h" - - -#ifdef __GNUC__ - -#define max(x,y) (((x)>(y)) ? (x) : (y)) -#define min(x,y) (((x)<(y)) ? (x) : (y)) - -// abs is now predefined -//template T abs (T a) { return (a> n); } -#else -#endif -/****************************************************************************** -******************************************************************************* - - VECTOR INTRINSICS - -******************************************************************************* -*******************************************************************************/ - -//inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); } -inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((size_t)(calloc((nmemb*size)+15,sizeof(char)))+15 & ~15); } - -<> - -/****************************************************************************** -******************************************************************************* - - ABSTRACT USER INTERFACE - -******************************************************************************* -*******************************************************************************/ - -class UI -{ - -public: - bool fStopped; - UI() : fStopped(false) {} - virtual ~UI() {} - - virtual void addButton(char* label, float* zone) = 0; - virtual void addToggleButton(char* label, float* zone) = 0; - virtual void addCheckButton(char* label, float* zone) = 0; - virtual void addVerticalSlider(char* label, float* zone, float init, float min, float max, float step) = 0; - virtual void addHorizontalSlider(char* label, float* zone, float init, float min, float max, float step) = 0; - virtual void addNumEntry(char* label, float* zone, float init, float min, float max, float step) = 0; - - virtual void openFrameBox(char* label) = 0; - virtual void openTabBox(char* label) = 0; - virtual void openHorizontalBox(char* label) = 0; - virtual void openVerticalBox(char* label) = 0; - virtual void closeBox() = 0; - - virtual void run() = 0; - - void stop() { fStopped = true; } - bool stopped() { return fStopped; } -}; - - -////// Implementation of UI - -// Faust UI hookup is straightforward -// We subclass from UI and then these methods will get called by compiled -// Faust which assembles controls. We handle all UI as needed, and when -// things changed we need to set *zone=(some value). -// This is a little more complicated when jumping between alchemy/script. -// So rather than deal with marshalling pointers, just cheat and use an int:pointer map. -// NOTE: I should have used an STL map but that wasn't working back when I used gcc. -// I'll investigate since that would clean up the code quite a bit. - -// upper bound on number of controls -#define MAX_CONTROLS 25 -// map of unique ui control id to a float* where faust reads the corresponding value. -static float* uidToZone[MAX_CONTROLS]; -// Counter that assigns control IDs. -static int uiMap_id = 0; - -// I wasn't able to properly thunk the UI actionscrpit methods to C. -// Since we know the complete UI at the time of creation, a collection of -// ui creation info is passed back from faust_init, and actionscript -// can read it and create the UI. -// This is a little messy and was done last-minute. -const int TYPE_BUTTON = 0; -const int TYPE_TOGGLE = 1; -const int TYPE_SLIDER = 2; -// max length for a label - more than 50 chars will get cut. -#define LABEL_LEN 50 -struct uiElemInfo { - int type; - int id; - char label[LABEL_LEN+1]; - float min; - float max; - float init; - float step; -}; -uiElemInfo uielems[MAX_CONTROLS]; -static int uielems_size = 0; - -// todo: stdio.h has strncpy, I just got paranoid about extra includes making the code bigger :) -void strcopy(char *src, char *dst) { - dst[LABEL_LEN] = '\0'; - for (int i = 0; i < LABEL_LEN; ++i) { - if (0 == (dst[i] = src[i])) return; - } -} - -void BuildUIArray(AS3_Val &array) { - for (int i = 0; i < uielems_size; ++i) { - AS3_Val result = AS3_Object( "type:AS3ValType,id:AS3ValType,label:AS3ValType,min:AS3ValType,max:AS3ValType,init:AS3ValType,step:AS3ValType", - AS3_Int(uielems[i].type), - AS3_Int(uielems[i].id), - AS3_String(uielems[i].label), - AS3_Number(uielems[i].min), - AS3_Number(uielems[i].max), - AS3_Number(uielems[i].init), - AS3_Number(uielems[i].step) - ); - AS3_Set(array, AS3_Int(i), result); - // decrease refcount? todo: this may leak memory... - //AS3_Release(result); - } -} - -class ActionScriptUI : public UI { - public: - ActionScriptUI() { - fStopped = false; - } - - virtual ~ActionScriptUI() { - } - - // Pass in a zone, get back a unique ID. - int registerControl(float *zone) { - if (!zone) return 0; - uiMap_id++; - uidToZone[uiMap_id] = zone; - return uiMap_id; - } - - // Called from Flash when any control is updated. - // Results will take effect on the next dsp callback - // since everything runs in the same thread. - void updateControl(int id, float value) { - *(uidToZone[id]) = value; - } - - - virtual void addButton(char* label, float* zone) { - int id = registerControl(zone); - uielems[uielems_size].type = TYPE_BUTTON; - uielems[uielems_size].id = id; - strcopy(label, uielems[uielems_size].label); - uielems[uielems_size].min = 0; - uielems[uielems_size].max = 0; - uielems[uielems_size].init = 0; - uielems[uielems_size].step = 0; - uielems_size++; - } - virtual void addToggleButton(char* label, float* zone) { - int id = registerControl(zone); - uielems[uielems_size].type = TYPE_TOGGLE; - uielems[uielems_size].id = id; - strcopy(label, uielems[uielems_size].label); - uielems[uielems_size].min = 0; - uielems[uielems_size].max = 0; - uielems[uielems_size].init = 0; - uielems[uielems_size].step = 0; - uielems_size++; - } - virtual void addCheckButton(char* label, float* zone) { - return addToggleButton(label, zone); - } - virtual void addVerticalSlider(char* label, float* zone, float init, float min, float max, float step) { - return addHorizontalSlider(label, zone, init, min, max, step); - } - virtual void addHorizontalSlider(char* label, float* zone, float init, float min, float max, float step) { - int id = registerControl(zone); - uielems[uielems_size].type = TYPE_SLIDER; - uielems[uielems_size].id = id; - strcopy(label, uielems[uielems_size].label); - uielems[uielems_size].min = min; - uielems[uielems_size].max = max; - uielems[uielems_size].init = init; - uielems[uielems_size].step = step; - uielems_size++; - } - virtual void addNumEntry(char* label, float* zone, float init, float min, float max, float step) { - return addHorizontalSlider(label, zone, init, min, max, step); - } - - // Not implemented yet - these only affect UI layout and aren't critical. - // See actionscript comments for details. - virtual void openFrameBox(char* label) {} - virtual void openTabBox(char* label) {} - virtual void openHorizontalBox(char* label) {} - virtual void openVerticalBox(char* label) {} - virtual void closeBox() {} - virtual void run() { } -}; - -/****************************************************************************** -******************************************************************************* - - FAUST DSP - -******************************************************************************* -*******************************************************************************/ - - - -//---------------------------------------------------------------- -// abstract definition of a signal processor -//---------------------------------------------------------------- - -class dsp { - protected: - int fSamplingFreq; - public: - dsp() {} - virtual ~dsp() {} - - virtual int getNumInputs() = 0; - virtual int getNumOutputs() = 0; - virtual void buildUserInterface(UI* interface) = 0; - virtual void init(int samplingRate) = 0; - virtual void compute(int len, float** inputs, float** outputs) = 0; -}; - - -//---------------------------------------------------------------------------- -// FAUST generated signal processor -//---------------------------------------------------------------------------- - - - -/********************END ARCHITECTURE SECTION (part 1/2)****************/ - -/**************************BEGIN USER SECTION **************************/ - -<> - -/***************************END USER SECTION ***************************/ - -/*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/ - - - - -/// Alchemy DSP -class Faust { -public: - Faust() { - // mydsp will be defined by faust in 'includeclass' - dsp_ = new mydsp(); - ui_ = new ActionScriptUI(); - dsp_->buildUserInterface(ui_); - dsp_->init(44100); // 44.1k, 2 channels, @ 32-bit is hardcoded into flash player 10. - } - - ~Faust() { - if (dsp_) delete dsp_; - if (ui_) delete ui_; - } - -//private: -public: // we're all friends here - mydsp *dsp_; - ActionScriptUI *ui_; -}; - - -Faust *faust = NULL; - -// Alchemy wrapper interface code -static AS3_Val api_init(void *thisPtr, AS3_Val args) { - faust = new Faust(); - AS3_Val array = AS3_Array(""); - BuildUIArray(array); - return array; -} - -static AS3_Val api_shutdown(void *thisPtr, AS3_Val args) { - if (faust) - delete faust; - return AS3_Int(0); -} - -// args = int id, float value -static AS3_Val api_onControlChange(void *thisPtr, AS3_Val args) { - if (!faust) return AS3_Int(0); - - // Marshall the arguments in. - int id = 0; - AS3_Val controlVal; - AS3_ArrayValue(args, "IntType, AS3ValType", &id, &controlVal); - double control_double = AS3_NumberValue(controlVal); - - // loss of precision is ok. - float value = (float)control_double; - - // Call the actual update function - faust->ui_->updateControl(id, value); - return AS3_Int(0); -} - -#define MAX_FLASH_BUFFER 8192 -// output buffers - L/R channels separate -static float bufferL[MAX_FLASH_BUFFER]; -static float bufferR[MAX_FLASH_BUFFER]; -// output buffer - construct interleaved output -static float bufferSum[2*MAX_FLASH_BUFFER]; - -// input buffers - L/R separate -static float inputL[MAX_FLASH_BUFFER]; -static float inputR[MAX_FLASH_BUFFER]; -// input buffer scratch space - interleaved -static float bufferInSum[2*MAX_FLASH_BUFFER]; - -// This is the most 'interesting' function of the file - it takes in flash sound buffers -// and sends them through Faust DSP code. -// args = int nsamples, float* buffer (byte[] in flash) -static AS3_Val api_tick(void *thisPtr, AS3_Val args) { - if (!faust) return AS3_Int(0); - - // Marshall arguments in. - int nsamples = 0; - int use_input = 0; - AS3_Val buffer; - AS3_Val input; - AS3_ArrayValue(args, "IntType, IntType, AS3ValType, AS3ValType", &nsamples, &use_input, &input, &buffer); - - float* outputs[2] = {bufferL, bufferR}; - float* inputs[2] = {inputL, inputR}; - if (use_input) { - //AS3_ByteArray_seek(input, 0, 0); - // we need (#samples * sizeof(float) * 2 channels) bytes. - AS3_ByteArray_readBytes((char*)bufferInSum, input, nsamples * 4 * 2); - char *src = (char*)bufferInSum; - char *dl = (char*)inputL, *dr = (char*)inputR; - for (int i = 0; i < nsamples; ++i) { - // fix endianness - dl[3] = src[0]; - dl[2] = src[1]; - dl[1] = src[2]; - dl[0] = src[3]; - dr[3] = src[4]; - dr[2] = src[5]; - dr[1] = src[6]; - dr[0] = src[7]; - dl += 4; - dr += 4; - src += 8; - } - } - - // magic! - faust->dsp_->compute(nsamples, inputs, outputs); - - - // Post-process: interleave arrays. - // Faust outputs to two separate arrays (which are probably contiguous in memory - see above) - // Flash's sound callback needs this as LRLRLRLR... - // For added fun, LLVM internal float seems to be the opposite endianness - // as what Flash uses, so we have to do this byte-by-byte. - char *copyL = (char*)bufferL; - char *copyR = (char*)bufferR; - char *tape_head = (char*)bufferSum; - for (int i = 0; i < nsamples; ++i) { - *tape_head++ = copyL[3]; - *tape_head++ = copyL[2]; - *tape_head++ = copyL[1]; - *tape_head++ = copyL[0]; - *tape_head++ = copyR[3]; - *tape_head++ = copyR[2]; - *tape_head++ = copyR[1]; - *tape_head++ = copyR[0]; - copyL+=4; - copyR+=4; - } - AS3_ByteArray_writeBytes(buffer, bufferSum, 4 * nsamples * 2); - - return AS3_Int(0); -} - - -//Alchemy entry point -// Here we are responsible for contructing an API object to pass back to Flash. -// This must contain pointers to all functions which may be called. -int main() -{ - //define the methods exposed to ActionScript - //typed as an ActionScript Function instance - AS3_Val methodInit = AS3_Function( NULL, api_init ); - AS3_Val methodShutdown = AS3_Function( NULL, api_shutdown ); - AS3_Val methodOnControlChange = AS3_Function( NULL, api_onControlChange ); - AS3_Val methodTick = AS3_Function( NULL, api_tick ); - - // construct an API lookup table with references to all functions - // In flash we'll instantiate one of these and call methods on it - // e.g. faust.api_tick(). - AS3_Val result = AS3_Object( - "api_init:AS3ValType, api_shutdown:AS3ValType, api_onControlChange:AS3ValType, api_tick:AS3ValType", - methodInit, methodShutdown, methodOnControlChange, methodTick); - - AS3_Release(methodInit); - AS3_Release(methodShutdown); - AS3_Release(methodOnControlChange); - AS3_Release(methodTick); - - // notify Flash of our functions and run -- this function never returns. - AS3_LibInit(result); - - return 0; -} -/********************END ARCHITECTURE SECTION (part 2/2)****************/ -