Support

If you have a problem or need to report a bug please email : support@dsprobotics.com

There are 3 sections to this support area:

DOWNLOADS: access to product manuals, support files and drivers

HELP & INFORMATION: tutorials and example files for learning or finding pre-made modules for your projects

USER FORUMS: meet with other users and exchange ideas, you can also get help and assistance here

NEW REGISTRATIONS - please contact us if you wish to register on the forum

Users are reminded of the forum rules they sign up to which prohibits any activity that violates any laws including posting material covered by copyright

Limiting a signal

For general discussion related FlowStone

Limiting a signal

Postby tulamide » Sat Nov 07, 2015 8:57 pm

Sorry to bug you with this, but you should know by now that I am a figure of fun when it comes to dsp code.

I wanted to limit a signal, so that it is always between -1 and +1, no matter what input value there is (even if it is 2.3 or something). I tried this code, which is obviously wrong:

Code: Select all
streamin src;
streamout out;

out = src | ((src>1&1) + (src<-1&-1));


What would be the correct code?


EDIT:
Code: Select all
streamin src;
streamout out;
float n;

n = ((src>1&1) + (src<-1&-1));
out = n | (n==0&src);


This seems to somehow work (although it sounds odd). But is it correct code? And is there a more efficient way?

EDIT 2:
It does not work correctly. It goes beyond the limits. Oh why is dsp code so hard to understand?
"There lies the dog buried" (German saying translated literally)
tulamide
 
Posts: 2714
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany

Re: Limiting a signal

Postby MyCo » Sun Nov 08, 2015 1:19 am

Code: Select all
streamin in;
streamout out;

out = min(max(in,-1), 1);


No need to fiddle around with comparison bitmasks.
User avatar
MyCo
 
Posts: 718
Joined: Tue Jul 13, 2010 12:33 pm
Location: Germany

Re: Limiting a signal

Postby tulamide » Sun Nov 08, 2015 11:28 am

MyCo wrote:
Code: Select all
streamin in;
streamout out;

out = min(max(in,-1), 1);


No need to fiddle around with comparison bitmasks.

Thank you!
"There lies the dog buried" (German saying translated literally)
tulamide
 
Posts: 2714
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany

Re: Limiting a signal

Postby KG_is_back » Sun Nov 08, 2015 3:39 pm

I think I know what your problem with DSPcode is, Tulamide. You might be unfamiliar with the difference between Conditional and Bitwise operations. DSP code only supports bitwise, but I will briefly describe both (also for other users that may have similar problem).
Conditional operations
Conditional operations work with boolean values (true/false). Booleans are returned by comparisons. Also, in many C-like languages, zero value is considered "false" and nonzero value is considered "true". In case of Ruby, only "nil" and "false" itself are considered false.
Most languages implement conditional operations using "short-circuit". That means they evaluate the logical expression from left to right and stop once the definite result is clear. Then they return the value of the sub-expression that was responsible for the definite result. Once the definite value is set, rest of the expression is not even executed.
Conditional operations are usually denoted by double sign ( && ||) or by word (OR, AND, XOR, etc.) In ruby both work.
Ruby example:
Code: Select all
#OR needs at least one value to be true. Once it finds such value, rest of the expression is omitted:
x=5
(0>1) || nil || false || (x+5) || (x=x+1) #this expression returns 10, because (x+5) is the first "true" value in sequence of "OR"s.
x #x is still 5, because everything after "(x+5)" was omitted

#AND needs all values to be true. Once it finds "false" it returns "false" and rest of the expression is omitted.
#if all values are "true" it returns the value of the last one - because that one determined the definite result.
x=5
(x<10) && (x>0) && (x!=5) && (x+=1) #this returns false, because "(x!=5)" is false
x #x is still 5, because code after "(x!=5)" was not executed.
(x<10) && (x>0) && (x+=1) #this returns 6, because that's the value of the last sub-expression, and all sub-expressions are "true"

Conveniently you may use this to your advantage. You may determine which expressions should be executed without need of "IF" statements.
Code: Select all
x=0
(x!=0) && (x=1/x) #first expression is false, so the second one is not executed, thus error is not raised
x #x is still zero


Bitwise operators
Bitwise operations are completely different story. They do not use booleans. Instead, they produce results with specific binary patterns (called bitmasks). They have the same word-size as the operands (in case of DSP code 32bit packed float/int - which is technically a 128bit value). Because they work on bit-by-bit basis, all parts of the expression will be evaluated.
"Bitwise" comparisons return a bitmask that is all zeros for false (which is conveniently a value of zero in both int and float format) and all ones for true (which is -1 as integer and negative infinity as float). Bitwise logical operators (which are denoted by single sign & (and) | (or) ^ (xor - note this one isn't in DSP code)) are performed bit-by-bit.
Ruby does not support "bitwise" comparisons, but they may be emulated by adding ternary operator.
Code: Select all
((x>1) ? -1 : 0) #this returns binary mask: 0 for false and -1 for true (-1 integer is all bits true)

Because the operations are performed bit-by-bit, performing & and | if needer of the values is a binary mask may produce unexpected results. Basically the binary patters of the two values get "mixed" into completely new number.
Code: Select all
0b011 & 0b110 #returns 2 (0b010)
0b011 | 0b110 #returns 7 (0b111)

This property may be used to your advantage(especially with values in int format), but that is an advanced feature.

You might have noticed that DSP code does not raise errors. Instead, Floating point format has several "special" values:
NaN/IND - "not a number / is not defined". It is returned by undefined operations, like (0/0), square root of negative number, logarithm of negative number, etc. (strangely division by zero returns infinity for some reason). It has several special properties:
1. result of any arithmetic operation with NaN results NaN. (this may cause serious, hard to track bugs, especially if it happens in a feedback loop)
2. NaN is not equal to itself. (this may be used to detect and remove NaNs)
Code: Select all
x=x&(x==x); //converts any NaN to zero.

positive/negative infinity - these values are used when overflow happens (result is too big/small to be expressed in 32bit float format). Infinities also have several special properties (x is a non-zero finite value):
1. inf+x=inf
2. inf*x=inf
3. inf*-1= -inf
4. inf*0 = NaN
5. inf/inf= NaN
6. inf - inf=NaN
Infinities are big problem in recursive filters, because they tend to get stuck in feedback loops. You may use their properties to detect and remove them. Although it's better to prevent them happening.
Code: Select all
x=x&(x!=x+1); //converts infinities to zero


Now to your DSP code. Your first example does not work, because you're performing bitwise OR of "src" (nonzero value) with second expression which results -1,0 or 1. If both of them are non-zero, their binary patterns get "ORed" resulting in a completely new value.
Your second code works, because you are first calculating "n" which is -1,0 or 1. Then you do bitwise OR of "n" and second expression which returns "0" if n!=0 (in which case you are doing "n|0" which is "n") or returns "src" if n==0 (in which case you are doing "0|src" which is "src").

You might be asking "why do we need bitwise operators anyway?" Answer is simple and has multiple points:
1. Hardware-wise they are much easier to implement, because they use same memory/registers to store values and bitwise results (basically any bitwise operation takes only one CPU cycle). Conditionals need to keep track of their booleans separately in the background. If conditionals also implement "short-circuit" system, they also have to implement jumps.
2. With bitwise operators, the same code is executed in the same way and order, irrelevant of the actual values of arguments and results. This makes them SIMD compatible (SIMD= single instruction - multiple data), thus several copies of the code may run in parallel. Flowstone uses SIMD philosophy to implement poly and mono4 streams to save CPU power, so bitwise operators are much more convenient.
KG_is_back
 
Posts: 1196
Joined: Tue Oct 22, 2013 5:43 pm
Location: Slovakia

Re: Limiting a signal

Postby tulamide » Sun Nov 08, 2015 3:58 pm

Great! Yes I struggle a lot with bitmasks. Although I know the theory it becomes a pain when trying to test for several conditions, so to say. I'm glad you took the time to talk about it in-depth. It will be a reference for me, just as an example Myco posted some time ago.

If only my brain wouldn't be so bound to traditional programming :lol:
"There lies the dog buried" (German saying translated literally)
tulamide
 
Posts: 2714
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany

Re: Limiting a signal

Postby RJHollins » Sun Nov 08, 2015 7:20 pm

Thanks KG !

I think I need some type of FS 'Notebook' to put all these lessons into a place and form that can be referred to and studied.

8-)
RJHollins
 
Posts: 1571
Joined: Thu Mar 08, 2012 7:58 pm

Re: Limiting a signal

Postby martinvicanek » Sun Nov 08, 2015 7:28 pm

Hey KG, that tutorial would make a good article on FS Guru, don't you think?

@tulamide, if your programming skills are traditional then mine are completely outdated if anything. Remember FORTRAN? :mrgreen: That's where I come from. I will never be able to program in Ruby haha! :lol:
User avatar
martinvicanek
 
Posts: 1328
Joined: Sat Jun 22, 2013 8:28 pm

Re: Limiting a signal

Postby KG_is_back » Sun Nov 08, 2015 8:31 pm

martinvicanek wrote:Hey KG, that tutorial would make a good article on FS Guru, don't you think?

@tulamide, if your programming skills are traditional then mine are completely outdated if anything. Remember FORTRAN? :mrgreen: That's where I come from. I will never be able to program in Ruby haha! :lol:


I was actually considering that... I need to do some more research. I'm also waiting for DSPC3 to reach release version, because its capabilities are much superior to stock DSP code (which for example does not have XOR although assembler supports it). So Martin, If you find some free time, please give it a try (for example in your existing projects) and report any unexpected/buggy behaviour. It's hard for me to seriously test it, because currently I do not have any projects that would involve DSP.
KG_is_back
 
Posts: 1196
Joined: Tue Oct 22, 2013 5:43 pm
Location: Slovakia

Re: Limiting a signal

Postby tulamide » Sun Nov 08, 2015 8:51 pm

martinvicanek wrote:@tulamide, if your programming skills are traditional then mine are completely outdated if anything. Remember FORTRAN? :mrgreen: That's where I come from. I will never be able to program in Ruby haha! :lol:


At least completely outdated! My dsp skills are non-existent :lol:
But seriously: That's what makes us so strong when teaming up. Remember the 4-channel wavetable? You did the DSP-part, I did the Ruby-part - and together we created something that none of us would have been able to create alone. I hope we'll prove it again some time in the future ;)
"There lies the dog buried" (German saying translated literally)
tulamide
 
Posts: 2714
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany

Re: Limiting a signal

Postby RJHollins » Sun Nov 08, 2015 10:20 pm

I did some GFABasic programming on an ATARI STe back in the 80's.

Where does that put me :shock:

:oops:
:lol:
RJHollins
 
Posts: 1571
Joined: Thu Mar 08, 2012 7:58 pm

Next

Return to General

Who is online

Users browsing this forum: Majestic-12 [Bot] and 65 guests