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

Shared Mem Wavetable Oscillator

Post any examples or modules that you want to share here

Shared Mem Wavetable Oscillator

Postby martinvicanek » Sat Apr 11, 2015 9:34 pm

Hi guys,

I have been trying to build a wavetable oscillator based on Trog's shared mem concept. One problem is how to create and populate the wavetable mem so it can be used in a poly section. Tulamide has provided a nice Ruby solution, where memory is not only allocated for 16 byte aligned access. The same module also actually writes data from a green array into the mem. Only after the writing is completed is a valid address passed to an ASM module for mem access. That way crashes are eliminated (well, less likely :mrgreen: ).

Below is a demo which uses linear interpolation and some SSE trickery for speed optimization. It turns out that there is actually room for two waveforms stored in one array. I am posting it eventhough it is half-baked, as there is similar activity in another thread.
Attachments
SharedMem_Ruby_Final_4_Arrays (base 2)_Modul_.fsm
(25.77 KiB) Downloaded 1181 times
User avatar
martinvicanek
 
Posts: 1322
Joined: Sat Jun 22, 2013 8:28 pm

Re: Shared Mem Wavetable Oscillator

Postby KG_is_back » Sat Apr 11, 2015 10:41 pm

Very, very nice! I do not understand the "lock" hack :oops:

Perhaps it is not necessary to put 4 wavetables in one array. with clever bitwise logic it is possible to shuffle the correct value to all channels even when mem is not 4channel. However, the code is rather lengthy and I've not written it down (a lot of shuffling and I don't have the nerves for it right now xD ).
KG_is_back
 
Posts: 1196
Joined: Tue Oct 22, 2013 5:43 pm
Location: Slovakia

Re: Shared Mem Wavetable Oscillator

Postby tulamide » Sat Apr 11, 2015 11:39 pm

KG_is_back wrote:I do not understand the "lock" hack :oops:

We are dealing with two parts that are independant from each other: Ruby and Assembler. Ruby doesn't know what Assembler does and vice-versa. Now, memory allocated by Ruby (whenever we use something, we allocate memory) will be controlled by Ruby. Therefore it is critical if we pass access to memory created with Ruby to Assembler.

Older languages used a pretty simple mechanism: The programmer allocates memory, uses it, and frees it after use. This can get pretty complicated for the programmer, should he/she forget to free memory. And in fact, it was often the reason for so called memory leaks.
Ruby goes another path. Pretty much every memory access is automated, so that the programmer doesn't have to care about it. For example, you just call "class.new" and Ruby takes care of allocating memory for the class structure. Since you don't have direct access to memory, another system is also needed to free memory. Ruby uses a system called "garbage collection".
Basically, whenever memory is allocated, information about it is put on a queue. Everything on the queue is checked regularly if still valid. If not, the memory is freed and the information removed from the queue. For example, if we did something like a = Array.new(100) and then somewhere later in the code do a = 2, then the array and its associated memory is no longer valid. Ruby then will free that memory. But memory that is freed will be used by the os or other applications, processes, and so on. But Assembler still works with that memory, so it would lead to issues and crashes.
By accessing the frame every once in a while from within Ruby the garbage collector will never get a chance to free the memory associated with the frame - which is what is needed to let Assembler work with that memory. Ruby acts as a memory protector for the asm module, so to say.
"There lies the dog buried" (German saying translated literally)
tulamide
 
Posts: 2696
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany

Re: Shared Mem Wavetable Oscillator

Postby KG_is_back » Sun Apr 12, 2015 12:01 am

Oh... so because the frame is regularly used by event method (in this case by the "watch" method inside it) it is protected from getting "expired" like a milk on a summer sun.

I thought objects in instance variables are protected from GC. Does this happen, because when rubyedit instance is not active for some time its instance variables may get scrapped as unnecessary?
KG_is_back
 
Posts: 1196
Joined: Tue Oct 22, 2013 5:43 pm
Location: Slovakia

Re: Shared Mem Wavetable Oscillator

Postby Tronic » Sun Apr 12, 2015 10:55 am

tulamide wrote:
KG_is_back wrote:I do not understand the "lock" hack :oops:

We are dealing with two parts that are independant from each other: Ruby and Assembler. Ruby doesn't know what Assembler does and vice-versa. Now, memory allocated by Ruby (whenever we use something, we allocate memory) will be controlled by Ruby. Therefore it is critical if we pass access to memory created with Ruby to Assembler.

Older languages used a pretty simple mechanism: The programmer allocates memory, uses it, and frees it after use. This can get pretty complicated for the programmer, should he/she forget to free memory. And in fact, it was often the reason for so called memory leaks.
Ruby goes another path. Pretty much every memory access is automated, so that the programmer doesn't have to care about it. For example, you just call "class.new" and Ruby takes care of allocating memory for the class structure. Since you don't have direct access to memory, another system is also needed to free memory. Ruby uses a system called "garbage collection".
Basically, whenever memory is allocated, information about it is put on a queue. Everything on the queue is checked regularly if still valid. If not, the memory is freed and the information removed from the queue. For example, if we did something like a = Array.new(100) and then somewhere later in the code do a = 2, then the array and its associated memory is no longer valid. Ruby then will free that memory. But memory that is freed will be used by the os or other applications, processes, and so on. But Assembler still works with that memory, so it would lead to issues and crashes.
By accessing the frame every once in a while from within Ruby the garbage collector will never get a chance to free the memory associated with the frame - which is what is needed to let Assembler work with that memory. Ruby acts as a memory protector for the asm module, so to say.


not all true,
the problem of the crash is mainly due to how Flowstone manages memory and especially the case, here less discussed and considered, which is the relocation after the memory is freed.
to test it just to copy and paste some ruby modules that create frame, and you'll see that the memory is not managed by ruby, but by FlowStone, ruby only uses it.
Tronic
 
Posts: 539
Joined: Wed Dec 21, 2011 12:59 pm

Re: Shared Mem Wavetable Oscillator

Postby tulamide » Sun Apr 12, 2015 11:20 am

Tronic wrote:not all true,
the problem of the crash is mainly due to how Flowstone manages memory and especially the case, here less discussed and considered, which is the relocation after the memory is freed.
to test it just to copy and paste some ruby modules that create frame, and you'll see that the memory is not managed by ruby, but by FlowStone, ruby only uses it.

I know what you mean, because the behaviour you describe is exactly what I prevent with this hack :)
"There lies the dog buried" (German saying translated literally)
tulamide
 
Posts: 2696
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany

Re: Shared Mem Wavetable Oscillator

Postby Exo » Sun Apr 12, 2015 7:00 pm

Very nice, thanks Martin and tulamide.

This is a solution when using frames.

I prefer to use the mem create with the mem to address, this is more stable. Check out my free running poly oscs this doesn't have any problem with garbage collection because we can create and delete the memory ourselves.

I do have one crashing issue regarding using the "mem to address" directly with a wavetable create and a wave file. I have a crash on load sometimes but I don't think it is related to this issue because I am not using Ruby. But I think I may have an invalid address while the wavetable or wavefile is loaded.

I like the fact that you are outputting zero while the frame is created, I think I will try that because it could solve my stability problem.

But I think the stability problem is also there when using the float array to mem, because the float array is copied to a mem so every time the float array updates the address changes.
Flowstone Guru. Blog and download site for Flowstone.
Best VST Plugins. Initial Audio.
Exo
 
Posts: 426
Joined: Wed Aug 04, 2010 8:58 pm
Location: UK

Re: Shared Mem Wavetable Oscillator

Postby Exo » Sun Apr 12, 2015 7:40 pm

This is a good solution for most cases though.

Anywhere I would use a "float array to mem" > "mem address" I could replace with this.

But this solution wouldn't be suitable in the case of the wavetable create primitive, because passing it to the Ruby component as a float array would be way to heavy.

The case I am using is a bandlimited wavetable (4096 sample points) that is 32MB in size, Ruby cannot handle that.

So very large arrays are not suitable. But smaller arrays this is perfect :)
Flowstone Guru. Blog and download site for Flowstone.
Best VST Plugins. Initial Audio.
Exo
 
Posts: 426
Joined: Wed Aug 04, 2010 8:58 pm
Location: UK

Re: Shared Mem Wavetable Oscillator

Postby tulamide » Mon Apr 13, 2015 11:04 am

Exo wrote:The case I am using is a bandlimited wavetable (4096 sample points) that is 32MB in size, Ruby cannot handle that.

Well, actually it can. But the time needed is just inacceptable (and the reason for Flowstone to interfear). You encounter the downside of the garbage collector. Before writing a wall of text, have a look at this blog for an explanation: http://www.platanus.cz/blog/working-wit ... es-in-ruby
"There lies the dog buried" (German saying translated literally)
tulamide
 
Posts: 2696
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany


Return to User Examples

Who is online

Users browsing this forum: No registered users and 21 guests