BASICally: a new module for writing code within Rack

Indeed, the outputs are not clamped. It’s not uncommon to have to use external cables with these devices (to go from one AO-xxx to another, or to have feedback) so it doesn’t mess with what are essentially your intermediate numbers

2 Likes

That works for the time being. Actually, dividing by 1000 is enough for my current tests…

But, the maximum internal C constant value is 100.0, right?

1 Like

Whereas using sample counts for calculating time works well for samples, it does not work well for arbitrary timed events handling. That can probably not be done effectively without using some type of “system time”. Is it feasible to support system time query in BASICally?

Yes. For me that is the most significant shortcoming of the AO modules. To workaround the limitation you could dedicate two computations for each input, the first being one with no inputs to establish your multiplier that then gets passed down to the next where you multiply x*(y+c) with c=0. For example, exponential 10^(y+c) or 10^(x+c) with no input and C=3 will give you your 1000.

AO-106 would then allow 3 conversions.

I requested the ability to enter C values > 100, but David did not want to allow entry of values that could not be easily entered by the mouse.

The only other issue I have is that it is awkward and space inefficient to perform a computation and then reuse the result in multiple computations. For example, I would like to be able to compute 10^3 once, say in the top cell in AO-106, and then pass that value down as Y to all cells below where I multipley x*(y+c) and take the result from the x output. That would require the ability to specify whether a computation updates the x result, the y result, or both. Currently you can only pass through x and y, or you can perform a computation that updates both x and y. I have never put in that enhancement request - I think it would greatly increase the capability of the modules.

Good idea. I will try that. Thanks.

I agree that it is difficult to re-use values in the AO modules. Seems like I came up with some way of doing what you are describing, but that was a while back and cannot remember the specifics. Seems like I would push the intermediate value to the right so that it could be used in a later vertical calculation. I was easily confused though :wink:

I don’t know what the ramifications of calling a system time function per sample would be.

I think a time() function that returns the (floating point) number of seconds (milliseconds?) since, roughly speaking, that BASICally module instance started would do the trick.

I’d suspect that calling a steady_clock is probably more efficient than having BASICally compute ‘tick = tick + 1’, to be honest. And it only needs to compute the interval when time() is actually called.

That sound about right? Seconds or millis?

If I must choose, I would say milliseconds. Can we have both?

How aboout LOG10() and LOGe()?

Thanks for considering this.

And LOG2(), given how critical that is to audio applications.

I don’t know if exponentiation is supported. If not, then that should be added as well. Either x^y operator syntax, or else exp(x,y)

1 Like

pow(x,y) is there.

1 Like

@StochasticTelegraph

I am not making much headway with my event handling script. I keep getting hung up on how to think of arrays and how to interpret what happens per sample. I have your code downloaded and looking at it. I see things like array_ptr. Somewhere behind the scenes, you do create variable arrays and dynamically manage the array size, right. Looks like you also create line arrays, right?

I think you answered this before, but do all “array” elements persist until there is a reset start?

The other question is what happens per sample in the BASICally process() function? Does one expression line of the expression line array get processed per sample?

If I create an event array, should I be able to keep track of the array length using the semaphore method and thus effectively add and remove array elements, at least from the end of the array?

As BASICally is structured, do you think I could write an array element quicksort loop so that I can sort the event array in most imminent event order?

A variable in BASICally must be a simple numeric value, right? We cannot have anything like a compound object such as a struct or multidimensional arrays, right?

I know this is a lot and you may not have the time to answer all of these questions. If you could at least indicate whether you think something like I describe is feasible in BASICally, that would help.

Thanks for your consideration.

Just thinking… I think I can use multiple single dimension arrays to accomplish the same thing as an array of structs.

This approach seems viable, but I wonder if I have multiple ALSO blocks and each block is assigning and accessing the same “array” variables in their shared variable space, can any problems occur?

BTW, I re-read the manual more carefully and I think I understand what happens per sample now and in which order things occur.

1 Like

Arrays, array data, and variables persist until a CLEAR ALL.

RESET has no effect on variable values or arrays.

I had been considering the option of multidimensional arrays. Single dimensional arrays are more efficient (good for the audio buffer usage I’ve been playing with), but you’re making the case that I expected for the option (in the menu) of sparse multidimensional arrays.

mahlen

1 Like

After re-reading your Dec 22 post and looking at your code, I better understand what BASICally is doing under the hood with P-Code and std::vector dynamic arrays.

I noticed something on Basically. Say you want to program the ADSR+VCA. You have a trigger connected to IN1, so you do “when trigger(in1)” and all that, but after doing that you can’t use the sound source anymore, it seems. All the sound sources are now const voltages. So the only way to retrieve the sound (that I can think of) right now is to resample it with a cycle maybe. Too smart for me though. So it would be cool to have a way to use the live inputs ignoring the trigger behaviour. Maybe with some kind if syntax like @in1@ is a live input and just in1 is a constant when the trigger is on. wait a minute… I think that’s what I wanted with internal triggers. For sampling the input if something is happening. Like If in1 = 0 then do the trigger to sample the in2. So maybe we need to reverse the syntax. Like in1 is a live input and @in1@ is a sampled input.

Not sure if this would be super useful in other situations though… So that’s just a minor point though. It’s not necessary, of course,

As I am playing around with BASICally, I am finding it very difficult to do floating point calculations based on the per sample time. A single precision float is just marginally up to the task.

Am I thinking about this incorrectly? Do we need double floats in order to have more than a couple of digits of precision when calculating the sample time interval in seconds?

@StochasticTelegraph

What would be the implications of using doubles rather than floats internally in BASICally?

In my use case, I am trying to create an event scheduler and handler in BASICally, I want events to happen at a certain “time”. Right now, the only way to determine time in BASICally is to count samples and know the sample time (1/sampleRate). It is very easy to exceed the precision of a float when counting large integer and summing small floats.

I think if I had the system time as we have talked about, I could avoid the single precision float limitations, although I am not sure about this.

Of course I am open to suggestions on how to do this differently.

I haven’t used BASICally yet but have been following along the tread. I know it’s kind of ugly but since you already have a sample counter, what would happen if you just kept BBM counters also?

samps = samps + 1
if samps = SAMPS_IN_BEAT then 
    samps = 0
    beats = beats + 1
    if beats = BEATS_IN_BAR then
        beats = 0
        bars = bars + 1

… and so on

1 Like