- Abort if using a nim version != 1.6.0.
-
Remove the use of
nm
to check the presence ofperform
/sample
blocks. -
Data[SomeNumber]
can now be accessed and replaced in theperform
/sample
blocks. -
struct
's default initialization of fields now support basic maths operations:struct Something: a = (PI * 2) + 25 init: something = Something()
-
def
now supports generics instantiation:def something[T](a T): return a * 2 init: a = something(1) #like structs: no generics == float a int = something[int](1) #explicit int
-
struct
now supports default initialization for fields. Also, it automagically figures out the default constructor in case the user does not specify itstruct Something[T]: a T def newData[T](size): return Data[T](size) struct SomethingElse[T]: a = 0.5 b int = 3 something Something[T] something2 = Something[T](samplerate) #using a constructor: type is inferred data Data[T] = newData[T](100) #not calling a constructor: must be explicit on the type!
struct Something: data Data delay Delay init: something = Something() #automatically calls Data() and Delay() if user does not pass his own
-
Data[T]
will compile even with uninitialized fields: they will be initialized with the default constructor ofT
.struct Something: data Data delay Delay init: c = new Data[Data[Data[Data[Data[Something]]]]](3) sample: out1 = c[0][0][0][0][0].data[0]
-
Accessing an uninitialized
Data[T]
field in theinit
block will initialize it to the defaultT
constructor.struct Something: data Data init: a = Data[Something](10) #Will initialize a[1] to Something() print a[1].data[0] #Will initialize a[9] to Something() and .data[1000] will return 0 print a[1000].data[1000] #a[1] is already initialized, will not re-initialize it and print warning a[1] = Something() sample: discard
-
Complete memory safety. If any allocation fail,
Omni_UGenInit
will return false and print out a nice error message.
-
Deprecate
nim < 1.4
. -
New
ins
andouts
mechanism: dynamic counting of IO:ins 2 ins 2: freq amp ins: freq amp outs 2 outs 2: out1 out2 outs: out1 out2
-
New
ins
andouts
mechanism: dynamic counting of IO insideperform
andsample
. This allows to not having to declareins
andouts
explicitly, but they will be extracted by parsing theperform
orsample
blocks. Dynamic access still works as expected:sample: out1 = in15 out26 = in2 outs[27] = 2 #Will be ignored, outs are 26 outs[20] = ins[16] #outs[20] will be set to 0, as ins[16] is out of bounds
-
Introducing
params
. These arefloats
like inputs, but they imply a separation between what's audio rate and what's control rate:ins
will always be audio rate, whileparams
will always be control rate.params: freq {440, 1, 22000} amp {1, 0, 1} init: phase = 0 sample: freq_incr = freq / samplerate out1 = sin(phase * twopi) * amp phase = (phase + freq_incr) % 1
When names are not declared,
params
will be namedparam1, param2, etc...
:params 3 sample: out1 = param1 + param2 + param3
-
Introducing
buffers
. This is the new way of declaring aBuffer
. An Omni wrapper, then, would use this interface to provide its own implementation of aBuffer
. Refer toWriting an Omni wrapper
on the manual.buffers: myBuf1 "defaultValue" myBuf2 myBuf3 "anotherDefaultValue" sample: out1 = myBuf1[0] + myBuf2[0] + myBuf3[0]
When names are not declared,
buffers
will be namedbuf1, buf2, etc...
:buffers 3 sample: out1 = buf1[0] + buf2[0] + buf3[0]
-
Dynamic access to
ins
,outs
,params
andbuffers
:params 2 buffers 3 ins 4 outs 5 sample: loop(i, params): outs[i] = ins[i] * buffers[i][params[i]]
-
Define
default
/min
/max
with keywords:ins: freq {min: 0, max: 1000} params: freq {default: 440, min: 0, max: 20000} amp {min: 0}
-
Introducing
:=
for aliases:struct Something: data Data init: something = Something(Data()) myData := something.data sample: out1 = myData[0] myData[0] = in1
-
def
can now be used without arguments, if needed:def something: return 0.5 def something2 float: return 0.5 def something3 float: return 0.5
-
loop
: reversed the arguments and support for range.loop(i, 4) loop(i, 0..3) loop(i, 0..<4) loop i 4 loop i 0..3 loop i 0..<4 loop i, 4 loop i, 0..3 loop i, 0..<4
Anonymous index through the
_
identifier:loop 4: print _
Support for
Data
access and initialization:struct Something: a float init: data = Data[Something](10) loop(something, data): something = Something() data2 = Data[Something](10) loop data2: _ = Something() #Together with the standard for loop syntax data3 = Data[Something](10) for entry in data3: entry = Something() data4 = Data[Something](10) for i, entry in data4: print i entry = Something()
Infinite loops:
loop: print "hanging forever"
-
New CLI flag:
--exportIO
. This will export anomni_io.txt
file with infos aboutins
/params
/buffers
/outs
. -
CLI's
--importModule
flag is now shortened with-m
. -
New
--define
options:- omni_locks_disable: disable all locks relative to
params
andbuffers
access, turning them into no-ops. This option also defines both omni_locks_disable_param_lock and omni_locks_disable_buffer_lock. - omni_locks_disable_param_lock: disable all locks (even individual ones when
omni_locks_multi_param_lock
is defined) relative toparams
. - omni_locks_disable_buffer_lock: disable the global
buffer
lock. - omni_locks_multi_param_lock: use an individual lock for each
param
. If not defined, a global lock, like the one forbuffers
, will be used - omni_buffers_disable_multithreading: don't run the
unlock()
call onbuffers
(no multithread access to them).
NOTE: These locks are internal
Omni
locks, and they do not refer to the ones that anOmni
wrapper might implement for safe access tobuffers
. TheOmni
locks only make sure that anyOmni_UGenSetParam
/Omni_UGenSetBuffer
operation is thread safe. - omni_locks_disable: disable all locks relative to
- Fix for
-d:lto
on MacOS - Added
-v
flag and copyright - Added Error printing on Warning[GcMem]
- Support for Nim 1.4.0
- Added
-d:lto
flag - Added
--panics:on
flag Delay
length defaults to 1
-
Introducing the
loop
construct:loop 4 i: print i
-
Better error printing for invalid
def
andstruct
builds.
-
Support for command-like calls. Just like
nim
, it works for one arguments only:a = Data 10 a = Data(10) #equivalent
-
Support for
new
statement, both asdotExpr
and command:a = new Data a = new Data 10 a = new Data(10) a = Data.new() a = Data.new(10)
-
Explicit casting at variables declaration will keep the type:
a = int(1) #Will be int, not float!
-
Variables and
Buffers
can now be declared from theins
statement:ins 2: buffer Buffer speed {1, 0, 10} outs 1 init: phase = 0.0 sample: scaled_rate = buffer.samplerate / samplerate out1 = buffer[phase] phase += (speed * scaled_rate) phase = phase % buffer.len
-
Added
tuples
support:def giveMeATuple(): a (int, int) = (1, 2) #OR a = (int(1), int(2)) b = (1, 2, a) #(float, float, (int, int)) return b init: a = giveMeATuple() print a[0]; print a[1] print a[2][0]; print a[2][1]
-
Introducing
modules
via theuse
/require
statements (they are equivalent, still deciding which name I like better):One.omni:
struct Something: a def someFunc(): return 0.7
Two.omni
struct Something: a def someFunc(): return 0.3
Three.omni:
use One: Something as Something1 someFunc as someFunc1 use Two: Something as Something2 someFunc as someFunc2 init: one = Something1() two = Something2() sample: out1 = someFunc1() + someFunc2()
For more complex examples, check the
NewModules
folder inomni_lang
's tests. -
Better handling of variables' scope.
if / elif / else / for / while
have their own scope, but won't overwrite variables of encapsulating scopes.init: a = 0 if in1 > 0: a = 2 #Gonna change declared a b = 0 #b belongs to this if statement else: a = 3 #Gonna change declared a b = 1 #b belongs to this else statement