Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scsynth: adding BelaScopeUGen #75

Closed
wants to merge 8 commits into from

Conversation

elgiano
Copy link

@elgiano elgiano commented Oct 13, 2020

Purpose and Motivation

Addressing issue #6, I'm proposing a bus-based implementation for accessing Bela's Scope from SuperCollider.

  1. BelaScopeUGen reads a bus and calls Scope.log() frame-by-frame
  2. sclang interfaces are provided for:
    • setup: creating a single synth which contains a BelaScopeUGen, and a bus for it
    • logging: UGen.belaScope (and Array.belaScope) are just helpers to write on that bus

Not sure if it's the best implementation, even less sure if the way I link Scope through CMake is optimal. It seems to work fine on my system though.

Known issue: there is a frame drop when BelaScopeUGen is created. Could it be because a new Scope() is created on the server, and that allocation is not real-time safe?

Types of changes

  • New feature (non-breaking change which adds functionality)

Checklist

  • All tests are passing
  • If necessary, new tests were created to address changes in PR, and tests are passing
  • Updated documentation, if necessary
  • This PR is ready for review

Remaining Work

  • Discussion: do you like it? can we improve it? shall we change something?
  • Testing
  • Documentation
  • bela-remote

@elgiano
Copy link
Author

elgiano commented Oct 13, 2020

I see now that my diff for BELAUGens.cpp is big.. it's actually full of trailing space correction that I haven't done, I guess they happened automatically. The only changes I made are about BelaScopeUGen, near the end of the file.

@giuliomoro
Copy link

thanks!

I know mostly nothing about Sc's ugens, I have only contributed to another one before. Is BelaScopeUGen_next() called when all the channels in the bus are ready to read?

@elgiano
Copy link
Author

elgiano commented Oct 13, 2020

Thank you!

BelaScopeUGen_next is called once per block, and bus channels are always ready to read. The fact that BelaScope puts a BelaScopeUGen after the node tree should guarantee in most situations that the bus is read after all other active ugens have completed processing (for every block).
Does this answer your question? :)

As far as I understand, Scope is supposed to plot at audio rate, i.e. to call log() for every frame of every block, am I right?

@giuliomoro
Copy link

yes and yes!
Is there any reason why frameData is allocated wit RTAlloc() ? There is no need for it to take up space in the RT memory pool, as it's allocated in the constructor. Last time I worked on a UGen, I got fed up with the fact that you cannot have objects in the struct, and initialisation values are ignored, so I thought this could be a nicer approach:

class BelaScopeObj 
{
    Scope belaScope;
    std::vector<float> frameData;
    unsigned int noScopeChannels = 0;
    Unit* unit; // this is so that the Sc macros keep working inside the class
public:
    BelaScopeObj(Unit* unit) : unit(unit) {...}
// add more methods here
//....
};
struct BelaScopeUGen : public Unit
{
    BelaScopeObj* ptr;
};

so that you can write a more C++-style constructor/destructor for class BelaScopeObj and then simply call new/delete once from the UGen's Ctor and Dtor, which I think is a nicer approach, especially considering possible future expansions.
What do you think?

If you are resubmitting a patch, please do not include the whitespace changes that your text editor added and also fix the indentation where appropriate. It seems that you are mixing tabs and spaces somewhere, e.g.:

    for(unsigned int ch = 0; ch < numChannels; ++ch)
	inputPointers[ch] = ZIN(ch+1);

@giuliomoro
Copy link

thanks, is there anything that could be added to prevent instantiating more than one instance of the class? There can be only one Scope object in use at a given time.

@elgiano
Copy link
Author

elgiano commented Oct 14, 2020

For a start, what do you think about giving a single Scope object to the server itself? I think we could add it to SC_World.h. Then BelaScopeUGen would just get a handle to it, and call log on it, while setup and cleanup could also be done by the server, like:

s.setupBelaScope(maxChannels: 4);
-> internally calls stop, cleanup, setup, and start on the scope object

I think safety concerns about calling setup() multiple times can be mitigated (actually eliminated IMO) by wrapping Scope.setup() in a function that always calls stop() and cleanup() first if scope is running.

What do you think?

@giuliomoro
Copy link

For a start, what do you think about giving a single Scope object to the server itself?

I'd rather avoid that. We are aiming to merge upstream, so the more we can keep our changes out of the way of regular Sc code, the better, so the approach of using UGens seems fine to me. What I was thinking is more having a static flag that can be used to check the number of instantiated objects. This is easy to do in C++, but I was wondering how to communicate the failure back to the language.

I think safety concerns about calling setup() multiple times can be mitigated (actually eliminated IMO) by wrapping Scope.setup() in a function that always calls stop() and cleanup() first if scope is running.

One could just delete the Scope object and recreate it. I assume that there is some guarantee in place that while the Dtor and Ctor are running no audio or control callback is being called, right?

Another interesting feature would be to have a trigger input to the scope for custom triggering.

@elgiano
Copy link
Author

elgiano commented Oct 14, 2020

Ok, I see your point, but wouldn't the addition of a Scope object inside the BELA ifdef in SC_World still be compatible with the idea of merging? Then maybe we skip creating new primitives and server methods, and handle everything else in the UGen.
My problem is that I don't really see a way to limit the creation of a UGen to a single instance. The best that comes to my mind is that BelaScopeUGen would check that static flag and turn into noop if there's more than one instance.

On the other hand it looks relatively easy to put the limit on sclang-side, but this would be unreliable if you have multiple clients (e.g. one on Bela and the other on host)

@giuliomoro
Copy link

giuliomoro commented Oct 14, 2020

My problem is that I don't really see a way to limit the creation of a UGen to a single instance.

Is there a way for the Ctor to fail? Given how it returns void, I suspect not but maybe there is a magic macro that communicates a failure?

but wouldn't the addition of a Scope object inside the BELA ifdef in SC_World still be compatible with the idea of merging?

You are right, I didn't realise we already have an #ifdef BELA in there *. And having one single Scope object as part of the server options is what makes the most sense anyhow.

Then maybe we skip creating new primitives and server methods, and handle everything else in the UGen.

Sounds good! Would you be able to do the above?

* I guess it's a sensible idea to have it there then. I am a bit concerned about having anything at all in SC_World, because it's a publicly visible structure, so in principle all plugins would have to be rebuilt for Bela (which is what we already do, but it'd be nice if we didn't have to). Anyhow, that's a consideration for another moment.

@elgiano
Copy link
Author

elgiano commented Oct 14, 2020

I'm on it... but I'm a bit confused about linking. If SC_World requires Scope, does it mean we have to link libbelaextra to scsynth, and add Bela "root folder" to include_directories?

@giuliomoro
Copy link

That seems right yes, and undo your earlier change to CMakeLists.

@elgiano
Copy link
Author

elgiano commented Oct 14, 2020

I added a commit where we create and store a Scope() object in SC_World, before the AudioDriver starts, and we call the scope's .setup() in belaSetup, on the AudioDriver. This way setup is not called in the audio thread, which used to give some initial frame drop.

Now we have a single Scope object per server, but I haven't yet figured out a way to call setup on it, other than at startup, without doing it on the audio thread, and without writing a primitive for it. One way I thought about is to init the max number of scope buffers only at startup, maybe through a server option?

It seems to me that everything a UGen does is done on the audio thread (that's why RTAlloc for frameData in the constructor), so it's ok to call scope->log(), but apparently not setup(), maybe because of WSServer or AuxTask allocations?

@giuliomoro
Copy link

Thanks for your new commit. I seem to understand that now we have a fixed number of channels, but it would be a better option to have them set up in the server options as you previously suggested (or better s.options.belaScope(maxChannels: 4); (the rationale behind this is that scope channels are expensive (CPU-wise), and one wouldn't want to have 8 when they need 2).

One way I thought about is to init the max number of scope buffers only at startup, maybe through a server option?

yes!

If I understand correctly, one can still instantiate multiple copies of the ugen, which is going to cause trouble (because calling scope.log() more than once per frame is going to send multiple frames to the scope per each audio frames). Maybe yet another approach would be to have the scope associated with some of the Out.ar() channels (how many would be decided by the s.options. field)? Then one can send audio to those channels, and we can call scope.log() from within the BelaAudioCallback().

One other alternative is to hook into Sc's own .scope. That seems more complicate by the looks of it.

@elgiano
Copy link
Author

elgiano commented Oct 15, 2020

  • Sc .scope is quite complex, and as far as I can see it is so because it needs to access shared memory in order for the gui on sclang's side to work (I might very well be wrong, I only skimmed through the implementation)
  • I would avoid duplicating the whole Out.ar/audio bus mechanism. I started going into it by allocating a bus just for scope, outside the normal audio busses range, but then we would have to duplicate the whole IO/locks mechanism, which I think it would be better to avoid.

An alternative is to use the bus system as it is, reserve a bus language-side, and put in some guards for not doing that twice. The bus is read by a BelaScopeUGen, which calls .log, and we could also figure out a way for not having more than one such UGen running. Otherwise, if we want to call .log from BelaAudioCallback it looks like we either need to allocate our own bus out of the audio bus range (see above), or to have some kind of osc message to tell the server which bus we are using for scope.

@elgiano
Copy link
Author

elgiano commented Oct 15, 2020

Extra question: sometimes I get this warning in the IDE (now it happened after I left the tab in the background, with a test project running for a long time, like more than one hour). And of course scoping doesn't work anymore afterwards.

Error while sending to pipe from WSClient_scope_data: (12) Cannot allocate memory (size: 36864)

I got it sporadically since the first version of this PR... can you give me any clue about what is it?

@elgiano
Copy link
Author

elgiano commented Oct 15, 2020

Update: I implemented a ServerOption ( -O belaMaxScopeChannels ), and single-instance-guards for sclang and BelaScopeUGen. Apart from that sporadic WSClient memory error I reported above, I feel good about this implementation :)

  • the server creates and initializes a Scope object (and destroys it on quit)
  • a BelaScopeUGen calls log() on it
  • Client interface only requires to call .belaScope(channel) on some UGen or Array.

Let me know what you think, when you have time of course.

@giuliomoro
Copy link

giuliomoro commented Oct 18, 2020

Error while sending to pipe from WSClient_scope_data: (12) Cannot allocate memory (size: 36864)

this essentially means that you are sending too much data to the audio-to-websocket pipe, that is not sent via the websocket to the in-browser Scope fast enough. In practice, it often boils down to using too many Scope channels with a too high refresh rate for the CPU available. A common solution is increase the holdoff in the Scope GUI.

Could you please provide a .scd file that I can run on Bela to test the scope? I am really a noob with Sc, so something that I could just drop in the IDE and launch would be great, thanks.

Is there a way to add another "trigger" input channel to the scope? The server should be notified at setup time that a trigger channel is active, so that it can switch the Scope object to custom triggering mode (calling setTrigger() [this is improved with an enum in the Bela dev branch, which I shall soon merge into master]. It would then call scope->trigger() every time a 0 to 1 transition is encountered in the trigger input

A couple more issues:

  • I would set the default number of scope channels in both sclang and scsynth to 0, and on the server I would not instantiate the Scope object if the number of channels is 0.
  • Currently, mBelaMaxScopeChannels is ignored, because in sc_belaSetup() there is an 8 hardcoded.

Here's a patch that should fix these two issues:

diff --git a/SCClassLibrary/Common/Control/Server.sc b/SCClassLibrary/Common/Control/Server.sc
index 396c944a7..87f432f78 100644
--- a/SCClassLibrary/Common/Control/Server.sc
+++ b/SCClassLibrary/Common/Control/Server.sc
@@ -60,7 +60,7 @@ ServerOptions {
 	var <>adcLevel;
 	var <>numMultiplexChannels;
 	var <>belaPRU;
-	var <>belaMaxScopeChannels = 2;
+	var <>belaMaxScopeChannels = 0;

 	var <>recHeaderFormat="aiff";
 	var <>recSampleFormat="float";
diff --git a/server/plugins/BELAUGens.cpp b/server/plugins/BELAUGens.cpp
index b9e72384d..8fd7b4f62 100644
--- a/server/plugins/BELAUGens.cpp
+++ b/server/plugins/BELAUGens.cpp
@@ -1379,11 +1379,11 @@ void BelaScopeUGen_Ctor(BelaScopeUGen *unit)
     uint32 numInputs = unit->mNumInputs;
     uint32 maxScopeChannels = unit->mWorld->mBelaMaxScopeChannels;
     if(numInputs > maxScopeChannels) {
-       rt_printf("BelaScopeUGen warning: can't scope %i channels, maxBelaScopeChannels is set to %i\n", numInputs, maxScopeChannels);
+       rt_fprintf(stderr, "BelaScopeUGen warning: can't initialise scope %i channels, maxBelaScopeChannels is set to %i\n", numInputs, maxScopeChannels);
     }
     BelaScopeUGen::instanceCount++;
     if(BelaScopeUGen::instanceCount > 1) {
-        rt_printf("BelaScopeUGen warning: creating a new instance when one is already active. This one will do nothing.\n");
+        rt_fprintf(stderr, "BelaScopeUGen warning: creating a new instance when one is already active. This one will do nothing.\n");
         SETCALC(BelaScopeUGen_noop);
         return;
     };
diff --git a/server/scsynth/SC_Bela.cpp b/server/scsynth/SC_Bela.cpp
index 4730530fd..9355f75bd 100644
--- a/server/scsynth/SC_Bela.cpp
+++ b/server/scsynth/SC_Bela.cpp
@@ -148,7 +148,7 @@ bool sc_belaSetup(BelaContext* belaContext, void* userData)
     // cast void pointer
 	SC_BelaDriver *belaDriver = (SC_BelaDriver*) userData;
 	gBelaSampleRate = belaContext->audioSampleRate;
-	belaDriver->mBelaScope->setup(8, gBelaSampleRate);
+	belaDriver->mBelaScope->setup(mBelaMaxScopeChannels, belaContext->audioSampleRate);
 	return true;
 }

diff --git a/server/scsynth/scsynth_main.cpp b/server/scsynth/scsynth_main.cpp
index 451933847..600d7eefe 100644
--- a/server/scsynth/scsynth_main.cpp
+++ b/server/scsynth/scsynth_main.cpp
@@ -184,7 +184,7 @@ int main(int argc, char* argv[])
 	options.mBelaDACLevel = 0;
 	options.mBelaNumMuxChannels = 0;
 	options.mBelaPRU = 1;
-    options.mBelaMaxScopeChannels = 2;
+	options.mBelaMaxScopeChannels = 0;
 #endif

 	for (int i=1; i<argc;) {

There are still a few whitespace errors (which you can see with git diff, but those I can fix myself as there are already too many of those around).

@giuliomoro
Copy link

also, I'd be interested in hearing if @sensestage has any suggestion on this

@elgiano
Copy link
Author

elgiano commented Oct 19, 2020

Thanks for looking at it!

  • Error in WSClient: got it, so there's nothing we should do on this PR's side, or is it?
  • corrected the hardcoded 8, and set default maxChannels to 0
    EDIT: I also added an error when trying to instantiate BelaScope on sclang and options.belaMaxScopeChannels = 0
  • about triggering, I have to use a bit of time to think about it :) I'm thinking we can give one more channel to the scope bus, and reserve it for triggering. I would say the last one. Would it be possible then to switch to customTrigger mode lazily, only when the first trigger is received? I guess this question boils down to: is it possible (safe) to change triggering mode on the audio thread?
  • spacing: looks like I can never be on top of that, I'll take another look

Here is a simple sketch that scopes stereo inputs + 6 random sine waves:

s = Server.default;

s.options.numAnalogInChannels = 8;
s.options.numAnalogOutChannels = 8;
s.options.numDigitalChannels = 16;

s.options.blockSize = 64;
s.options.numInputBusChannels = 2;
s.options.numOutputBusChannels = 2;
s.options.maxLogins = 4;

s.options.postln;

s.options.belaMaxScopeChannels = 8;

s.waitForBoot({
  SynthDef("help-scope",{ arg out=0;
		var in = SoundIn.ar([0,1]).belaScope(0);
      	var sin = SinOsc.ar(TExpRand.kr(50,1000,Dust.kr(1!5)).lag2(1)) * LFNoise2.ar(1!5).exprange(0.01,1);
      	sin.belaScope(2);
		Out.ar(out, Pan2.ar(sin,[-1,1])+in);
      
  }).play;
});

@giuliomoro
Copy link

Error in WSClient: got it, so there's nothing we should do on this PR's side, or is it?

correct

about triggering, I have to use a bit of time to think about it :) I'm thinking we can give one more channel to the scope bus, and reserve it for triggering. I would say the last one. Would it be possible then to switch to customTrigger mode lazily, only when the first trigger is received? I guess this question boils down to: is it possible (safe) to change triggering mode on the audio thread?

I am actually thinking: if one wants to use "custom" triggering, they shall just send a trigger audio-rate signal into one scope channel, and select that as the triggering channel from the Scope frontend. No need to add any extra support for it. I think we are good to go (or as good as we can get with the current design). I will wait for a couple of days to see if @sensestage has any comments. In the meantime I will merge this on top of my mainlining attempt and build a beta release.

@giuliomoro
Copy link

In the meanwhile I'll write an Help file for BelaScope, and should I finally squash all my commits into one?

great, yes please

Please let me know if I can help in any way!

Test after I build the release. I will continue the conversation in #74

giuliomoro pushed a commit that referenced this pull request Oct 19, 2020
This is a squash and reformatting of several commits that originally made up #75

BelaScope: create in SC_World, setup in SC_Bela

ServerOptions: -O belaMaxScopeChannels

BelaScope: single instance and valid inputs checks

BelaScopeUGen: single instance guard

BelaScope: add .belaScope to Server, Bus and Function

BelaScope: maxScopeChannels defaults to 0
@giuliomoro
Copy link

giuliomoro commented Oct 19, 2020

Great I squashed and reformatted this here.

Here's a build, please test it (I enjoyed the scope example, thanks!):

https://github.com/BelaPlatform/supercollider/releases/tag/v3.11-bela2

Note: if you want to build this yourself, you need the very latest Bela master, as I changed a couple of things in bela-config

EDIT: updated link to bela2

giuliomoro pushed a commit that referenced this pull request Oct 19, 2020
This is a squash and reformatting of several commits that originally made up #75

BelaScope: create in SC_World, setup in SC_Bela

ServerOptions: -O belaMaxScopeChannels

BelaScope: single instance and valid inputs checks

BelaScopeUGen: single instance guard

BelaScope: add .belaScope to Server, Bus and Function

BelaScope: maxScopeChannels defaults to 0
@giuliomoro giuliomoro mentioned this pull request Oct 20, 2020
4 tasks
@giuliomoro
Copy link

giuliomoro commented Oct 20, 2020

Updated the release to include Ableton Link support and Xenomai IPC:

https://github.com/BelaPlatform/supercollider/releases/tag/v3.11-bela3

@elgiano
Copy link
Author

elgiano commented Oct 22, 2020

Just FYI: I will be unable to test this properly until at least next thursday. Sorry, I'm drowning in other works

giuliomoro pushed a commit that referenced this pull request Oct 23, 2020
This is a squash and reformatting of several commits that originally made up #75

BelaScope: create in SC_World, setup in SC_Bela

ServerOptions: -O belaMaxScopeChannels

BelaScope: single instance and valid inputs checks

BelaScopeUGen: single instance guard

BelaScope: add .belaScope to Server, Bus and Function

BelaScope: maxScopeChannels defaults to 0
@sensestage
Copy link

Hi there!

Yes, I do have suggestions. (Admittedly, I haven't read through the whole thread, so just sharing my initial thoughts)

My initial go at this ugen was to have one ugen BelaScopeChannel, to scope just one channel, and one UGen that can just be instantiated once that refers to the BelaScope, and that sets the amount of channels to use. So it does not have to be a startup parameter.

Back in the day I did not get around to making it all work out, but this was my initial start. It avoids having to add things to the World struct.

/*
int noScopeChannels = 0;
Scope * belaScope;


void BelaScopeChannel_next( BelaScope *unit )
{
    int scopeChannel = unit->mScopeChannel;
    float *in = IN(1);

    for(unsigned int n = 0; n < inNumSamples; n++) {
        belaScope->logChannel( scopeChannel, in[n] );
    }
}
    

void BelaScopeChannel_Ctor(BelaScope *unit)
{
    BelaContext *context = unit->mWorld->mBelaContext;
    
//     belaScope = Scope();
    // which channel is an input variable
//     belaScope->setup(3, context->audioSampleRate);
    float fChan = ZIN0(0); // number of channels
    mScopeChannel = (int ) fChan;
    // check whether channel is within number of channels of scope
    if ( mScopeChannel > noScopeChannels ){
            // error
    }
    // initiate first sample
    
    BelaScopeChannel_next( unit, 1);  
    // set calculation method
    SETCALC(BelaScopeChannel_next);
}



void BelaScope_next(BelaScope *unit)
{
}

void BelaScope_Ctor(BelaScope *unit)
{
    BelaContext *context = unit->mWorld->mBelaContext;
    
    float fChan = ZIN0(0); // number of channels
    noScopeChannels = (int) fChan;

    belaScope = Scope();
    // number of channels is a variable
    belaScope->setup(noScopeChannels, context->audioSampleRate);

    // initiate first sample
    BelaScope_next( unit, 1);  
    // set calculation method
    SETCALC(BelaScope_next);
}

void BelaScope_Dtor(BelaScope *unit)
{
    belaScope->stop();
    delete belaScope;
    noScopeChannels = 0;
}
*/

@giuliomoro
Copy link

@sensestage
I see a couple of issues with your implementation :

  • it relies on Scope::logChannel() which is not implemented on the Bela side (and it's not straightforward to do)
  • if BelaScope_Dtor is allowed to destroy the belaScope object that is used by instances of the BelaScopeChannel UGen, some synchronisation mechanism would be needed to ensure this only gets destroyed after the BelaScopeChannel ugens have been deactivated. This adds significant extra complexity. What thread calls Dtor?
    I'd assume a different one from the one that runs BelaScopeChannel_next , so there should be some locking mechanism in place, e.g.: BelaScopeChannel_next always calls a try_lock() and BelaScope_Dtor should wait on getting hold of that lock before deleting the object and notifying the BelaScopeChannel ugens that it should stop logging. Getting a lock at every iteration of BelaScopeChannel_next() seems like a lot of overhead. Maybe a flag could be used instead, but then you'd need to set a flag from BelaScope_Dtor and sleep until it gets ack'ed from BelaScopeChannel_next() by each active instance of BelaScopeChannel. Is it allowed to sleep or block in a Dtor?
  • if the user destroys and recreates a BelaScope ugen to change the number of channels, and by doing so they are decreasing the number of channels, we'd need to notify the user that some of the previously valid BelaScopeChannel are no longer valid, so there would have to be a global register of which BelaScopeChannel ugens are currently active.

Overall, I am not sure the added complexity is worth the trouble, if the only gain you get from this is to have a variable number of scope channels, but I'd be happy to hear your thoughts on this. Remember that I know very little about the inner workings of scsynth and even less about how to use sclang.

Admittedly, I haven't read through the whole thread, so just sharing my initial thoughts)

A good summary of the discussion is in the current implementation, which is all contained in 2fc8ce6 and can be tested with the code in #75 (comment) .

@giuliomoro
Copy link

@elgiano Just FYI: I will be unable to test this properly until at least next thursday. Sorry, I'm drowning in other works

No worries. Make sure you always test the latest release.

@giuliomoro
Copy link

@sensestage another thing about your implementation: would there be need for a s.sync between instantiating the BelaScope ugen and instantiating one of the BelaScopeChannel ugens?

@elgiano
Copy link
Author

elgiano commented Oct 25, 2020

@sensestage
I've seen your implementation, it is actually still there, commented out in BELAUGens.cpp :)
The two problems I found:

  • as giuliomoro said, logChannel would need to be implemented in the main Bela library
  • constructing and destructing Scope objects in a UGen Ctor/Dtor causes dropouts

So we ended up giving a Scope to the Server object, which initializes it and destructs it outside the audio thread. The max number of scope channels is fixed as a startup option, but it is still possible to scope less channels by writing to less Bus channels. Of course, Scope is still logging all the other (zero) channels anyway, and this can't be changed without re-initing the Scope object with a different number of channels, which would introduce a lot of complexity if it has to be done outside the audio thread (or better, I couldn't figure out a simple way to do this). Overall, the Bus implementation feels to me light and easy to use enough, with no significant overhead (or code duplication) other than reserving that Bus.

What do you think?

@giuliomoro
Copy link

@elgiano any luck in testing this?

@elgiano
Copy link
Author

elgiano commented Nov 7, 2020

@giuliomoro I'm giving it a go now! Tried the oscilloscope test script above and it all works, I did some back and forth between the latest release and my version from git, and I can't see any noticeable difference.
Except some more warnings when starting supercollider from the web ide:

  • after "Speakers are not muted":
--  cold init from program
--  cobalt->init()
--  connected to Cobalt
--  memory locked
--  memory heaps mapped
--  boilerplate->init()
--  program bootstrap done
--  warm init from �
--  � bootstrap done

after "SuperCollider 3 server ready."

   1"200.735| WARNING: [main] duplicate call from main program to xenomai_init() ignored
   1"200.933| WARNING: [main] (xeno-config --no-auto-init disables implicit call)

Hope that can be useful for you, and other than this, I don't really have projects on which I can test this release, so I'm open for any suggestion about testing it :)

@giuliomoro
Copy link

thanks, the first few lines are expected. The others not so much. Have you updated your Bela to the latest master and run make -C ~/Bela lib to update libbela which is used by Sc ?

@elgiano
Copy link
Author

elgiano commented Nov 8, 2020 via email

@giuliomoro
Copy link

Great, I think I will submit for upstream merge soon

@giuliomoro giuliomoro closed this Nov 8, 2020
@giuliomoro
Copy link

@elgiano
Copy link
Author

elgiano commented Nov 8, 2020

Great, although I still have to submit documentation for this! I'm almost done with it, shall I make another PR or shall we reopen this?

Also, if you have time, please consider this (BelaPlatform/Bela#645) contribution to the main Bela repo, where I added syntax highlighting for SC code :)

I'll look into the other issues as well!

@giuliomoro
Copy link

Great, although I still have to submit documentation for this! I'm almost done with it, shall I make another PR or shall we reopen this?

Open a new one against the bela-merge-formatted-rebase branch

Also, if you have time, please consider this (BelaPlatform/Bela#645) contribution to the main Bela repo, where I added syntax highlighting for SC code :)

Thanks very much, I shall do that soon. I will also need an example for the scope to add to the main repo, so you can submit a separate PR there for that if you want. On that note, I wanted to add the ServerQuit.add({ 0.exit }) line to all Sc examples so that when the server is stopped (e.g.: by pressing the button on the Bela cape) (see here), so maybe you can start by adding it to your example (or even the existing ones if you want :) )

giuliomoro added a commit that referenced this pull request Dec 1, 2020
This is a squash and reformatting of several commits that originally made up #75

BelaScope: create in SC_World, setup in SC_Bela

ServerOptions: -O belaMaxScopeChannels

BelaScope: single instance and valid inputs checks

BelaScopeUGen: single instance guard

BelaScope: add .belaScope to Server, Bus and Function

BelaScope: maxScopeChannels defaults to 0
giuliomoro added a commit that referenced this pull request Dec 1, 2020
This is a squash, reformatting and rebase of several commits that originally made up #75 and #83
giuliomoro added a commit that referenced this pull request Dec 1, 2020
This is a squash, reformatting and rebase of several commits that originally made up #75 and #83

Co-authored-by: Giulio Moro <[email protected]>
giuliomoro pushed a commit that referenced this pull request Dec 1, 2020
This is a squash and reformatting of several commits that originally made up #75

BelaScope: create in SC_World, setup in SC_Bela

ServerOptions: -O belaMaxScopeChannels

BelaScope: single instance and valid inputs checks

BelaScopeUGen: single instance guard

BelaScope: add .belaScope to Server, Bus and Function

BelaScope: maxScopeChannels defaults to 0
giuliomoro added a commit that referenced this pull request Dec 18, 2020
This is a squash, reformatting and rebase of several commits that originally made up #75 and #83 and #84

Co-authored-by: Giulio Moro <[email protected]>
giuliomoro added a commit that referenced this pull request Dec 18, 2020
This is a squash, reformatting and rebase of several commits that originally made up #75 and #83 and #84

Co-authored-by: Giulio Moro <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants