Open danidev opened 4 years ago
I did some other tests on exporting with faust2teensy and I have some other info to share.
first of all, I did a fresh installation of faust on a Ubuntu 18.04.5 LTS. Cloned the repo and then:
make
sudo make install
then I compiled the .dsp script with:
faust2teensy -lib script.dsp
I've replaced the .cpp and .h previously exported with the online faust ide and then compiled with the teensyduino. It compiles (not tested yet on the board).
There are some differences on the .cpp files, here is a sample (but there are more):
This is the parseDouble function exported by faust2teensy:
/**
* @brief parseDouble : parse number [s]dddd[.dddd] or [s]d[.dddd][E|e][s][dddd] and store the result in x
* @param p the string to parse, then the remaining string
* @param x the float number found if any
* @return true if a float number was found at the begin of p
*/
static bool parseDouble(const char*& p, double& x)
{
double sign = 1.0; // sign of the number
double ipart = 0; // integral part of the number
double dpart = 0; // decimal part of the number before division
double dcoef = 1.0; // division factor for the decimal part
double expsign = 1.0; // sign of the E|e part
double expcoef = 0.0; // multiplication factor of E|e part
bool valid = false; // true if the number contains at least one digit
skipBlank(p);
const char* saved = p; // to restore position if we fail
// Sign
if (parseChar(p, '+')) {
sign = 1.0;
} else if (parseChar(p, '-')) {
sign = -1.0;
}
// Integral part
while (isdigit(*p)) {
valid = true;
ipart = ipart*10 + (*p - '0');
p++;
}
// Possible decimal part
if (parseChar(p, '.')) {
while (isdigit(*p)) {
valid = true;
dpart = dpart*10 + (*p - '0');
dcoef *= 10.0;
p++;
}
}
// Possible E|e part
if (parseChar(p, 'E') || parseChar(p, 'e')) {
if (parseChar(p, '+')) {
expsign = 1.0;
} else if (parseChar(p, '-')) {
expsign = -1.0;
}
while (isdigit(*p)) {
expcoef = expcoef*10 + (*p - '0');
p++;
}
}
if (valid) {
x = (sign*(ipart + dpart/dcoef)) * std::pow(10.0, expcoef*expsign);
} else {
p = saved;
}
return valid;
}
The same function generated by the web exporter:
/**
* @brief parseDouble : parse number [s]dddd[.dddd] and store the result in x
* @param p the string to parse, then the remaining string
* @param x the float number found if any
* @return true if a float number was found at the begin of p
*/
static bool parseDouble(const char*& p, double& x)
{
std::stringstream reader(p);
std::streambuf* pbuf = reader.rdbuf();
// Keep position before parsing
std::streamsize size1 = pbuf->in_avail();
// Parse the number
reader >> x;
// Keep position after parsing
std::streamsize size2 = pbuf->in_avail();
// Move from the actual size
p += (size1 - size2);
// True if the number contains at least one digit
return (size1 > size2);
}
Also, if I try to make the script polyphonic with:
faust2teensy -lib -nvoices 4 script.dsp
seems that the nvoices param is not recognised and if i use:
faust2teensy -lib script.dsp -nvoices 4
It exports 2 times on the .h file the dsp class, and I get a lot of errors by the teensyduino, here is the .h file:
#define NVOICES 4
/************************************************************************
FAUST Architecture File
Copyright (C) 2019-2020 GRAME, Centre National de Creation Musicale
---------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
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 this FAUST
architecture section is not modified.
************************************************************************/
#ifndef faust_MicrocosmosDsp_h_
#define faust_MicrocosmosDsp_h_
#include <string>
#include "Arduino.h"
#include "AudioStream.h"
#include "Audio.h"
class dsp;
class MapUI;
class MidiUI;
#if MIDICTRL
class teensy_midi;
#endif
class MicrocosmosDsp : public AudioStream
{
public:
MicrocosmosDsp();
~MicrocosmosDsp();
virtual void update(void);
void setParamValue(const std::string& path, float value);
float getParamValue(const std::string& path);
private:
template <int INPUTS, int OUTPUTS>
void updateImp(void);
float** fInChannel;
float** fOutChannel;
MapUI* fUI;
#if MIDICTRL
teensy_midi* fMIDIHandler;
MidiUI* fMIDIInterface;
#endif
dsp* fDSP;
};
#endif
#define NVOICES 4
/************************************************************************
FAUST Architecture File
Copyright (C) 2019-2020 GRAME, Centre National de Creation Musicale
---------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
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 this FAUST
architecture section is not modified.
************************************************************************/
#ifndef faust_MicrocosmosDsp_h_
#define faust_MicrocosmosDsp_h_
#include <string>
#include "Arduino.h"
#include "AudioStream.h"
#include "Audio.h"
class dsp;
class MapUI;
class MidiUI;
#if MIDICTRL
class teensy_midi;
#endif
class MicrocosmosDsp : public AudioStream
{
public:
MicrocosmosDsp();
~MicrocosmosDsp();
virtual void update(void);
void setParamValue(const std::string& path, float value);
float getParamValue(const std::string& path);
private:
template <int INPUTS, int OUTPUTS>
void updateImp(void);
float** fInChannel;
float** fOutChannel;
MapUI* fUI;
#if MIDICTRL
teensy_midi* fMIDIHandler;
MidiUI* fMIDIInterface;
#endif
dsp* fDSP;
};
#endif
-nvoices N
and -midi
are not really working for now, you'll have to stay on monophonic DSP for now (sorry...), or help us making the polyphonic code working !thanks @sletz for the clarification.
I've used as the main source of information this paper: https://ccrma.stanford.edu/~rmichon/publications/doc/SMC-19-teensy.pdf
(Right now I've found out that you are one of the authors! So I'm very glad to talk with you!)
In this paper you used:
faust2api -teensy -nvoices 4 -effect auto MyFaustSynthPoly.dsp
in order to achieve polyphony: that was my second attempt to develop a polyphonic synth with faust/teensy.
The first attempt was spawning several instances of the faust generated class and then feeding a mixer object but I got a lot of issues (probably memory leaks, but I didn't find out the main reason - something related to MIDI, I guess).
Having more than one voice is a crucial feature, not necessarily a polyphonic mode, but using more than one instance/class could be a workaround and then developing voices management outside faust (indeed I did it in my first attempt, so I have a raw working polyphonic mode for the teensy).
Do other exporters (like the one for osx or linux) work the same way or it is possible having more than one instance or include several different classes on one project? This could point me on the right direction to eventually join the dev team to port it for the teensy :-)
Hi Daniele,
Yes, the nvoices option was available for a while, but it was basically unusable because generated objects would use too much memory on the Teensy and almost never work. Hence, we decided to remove it. Even though the Teensy is quite powerful computationally speaking, it's small memory quickly becomes an issue for this type of applications.
Instantiating a Faust object multiple times (e.g., FaustSawtooth faustSawtooth[4];
) and handling polyphony by hand is definitely an option. Our problem is that the Faust infrastructure around polyphony was never really designed to run on such small system and its heaviness make it more or less impossible to use on the Teensy.
All Faust architectures work in a different way in that regard. It works in the case of the Teensy because we generate an object for the Teensy audio library so you still have to do the wiring with the audio engine "by hand". In come cases, like on the ESP32, the Faust architecture manages the whole audio chain so one Faust object is directly linked to audio resources. In that case, its' not possible to declare multiple Faust objects in parallel or at least they would have to be allocated/de-allocated every time.
Romain
@danidev You may have a look at OWL Faust architecture C++ file here: https://github.com/pingdynasty/OwlProgram/blob/feature/faust-buttons/FaustCode/owl.cpp, it seems to do polyphony in a simpler way !?
Hello,
I've compiled and installed faust to use the faust2teensy. I use the command:
faust2teensy -lib FaustVoice.dsp
The cpp and h file are different from the files generated by the faust IDE online. The teensy compiler then crashes with a lot of error (while it doesn't with the files generated by the online IDE)
Also the parameter -nvoices seems having no effect.
the reason why I'm using the compiled faust2teensy and not the exporter is that I need support for polyphony and the online exporter seems to not export polyphonic voices.
Any hint will be very useful. Thanks!!!