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
custom WaveFile class for ruby
9 posts
• Page 1 of 1
custom WaveFile class for ruby
The multisampler project (gsamp) is progressing and there has been a discussion about mems, waves and wave files again. I've decided to experiment with wave files again and created a very-basic WaveFile class.
It allows you to open wave files in ruby (converting it to float format in the process), obtain informations about the wave file as well as send pointer to the raw data in RAM, which can be used in assembler to access the wave.
Naturally it also allows you to access individual samples from the wave (read-only).
It should be possible to build custom wave-array module with this stuff...
One problem I have is the loading. If a file is very long ruby stops working due to extensive processing. I tried to add optional "background" loading, but it doesn't work at the moment.
Detailed list of methods is in the schematic, as well as an example.
It allows you to open wave files in ruby (converting it to float format in the process), obtain informations about the wave file as well as send pointer to the raw data in RAM, which can be used in assembler to access the wave.
Naturally it also allows you to access individual samples from the wave (read-only).
It should be possible to build custom wave-array module with this stuff...
One problem I have is the loading. If a file is very long ruby stops working due to extensive processing. I tried to add optional "background" loading, but it doesn't work at the moment.
Detailed list of methods is in the schematic, as well as an example.
- Attachments
-
- newWave.fsm
- (6.25 KiB) Downloaded 1306 times
- KG_is_back
- Posts: 1196
- Joined: Tue Oct 22, 2013 5:43 pm
- Location: Slovakia
Re: custom WaveFile class for ruby
I just had a look at it. It is solid, good job.
Just forget about threads/processes. They won't help you with the extensive processing issue. The only way to prevent that issue is to give control back to Ruby from time to time, not calling a thread from a method of a class.
What you need is a method in a RubyEdit that loads x bytes, then gives control back and waits to be called again. One way would be to use the event on time trick, as shown in many examples.
You just need to start by calling my_reader once, and it will run as long as needed, while giving control back to Ruby in between the calls to the method.
Just forget about threads/processes. They won't help you with the extensive processing issue. The only way to prevent that issue is to give control back to Ruby from time to time, not calling a thread from a method of a class.
What you need is a method in a RubyEdit that loads x bytes, then gives control back and waits to be called again. One way would be to use the event on time trick, as shown in many examples.
- Code: Select all
def event i, v, t
if i == 99
my_reader(with appropritate attributes)
end
end
def my_reader(file, offset, length)
...fills a buffer with the data over time
if still_data_left
input 99, nil, time + 0.02 #Ruby runs at 100 Hz, so better not call 0.01
end
end
You just need to start by calling my_reader once, and it will run as long as needed, while giving control back to Ruby in between the calls to the method.
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
Re: custom WaveFile class for ruby
I think I've found an ultimate solution. When WaveFile object is initialized it sends itself to a buffer of loading files.
A Class method is being called periodically somewere in the schematic, that triggers "keep_loading" method, which triggers the WaveFile objects in the buffer to load next datachunk. While loading the file outputs a progress bar (0-1 float) and when finishes it outputs nil. The nil is a sign for the "keep_loading" method to remove this file from the buffer and proceed to the next.
Only downside of this approach is, that the loading speed is effectively fixed, so it will need to be set low enough for slower machines to keep up. This unnecessarily penalizes people with fast computers.
Perhaps there is a way to test processing speed of a computer by taking advantage of the ruby locking in flowstone. And it's not like we can test the loading speed either... because the speed may be different, depending on the files location (SSD, HDD, internet, etc.).
I still kept the "background loading" optional. You can load the file in one go if you're certain it will be a small single file or put them into loading buffer for safe loading.
A Class method is being called periodically somewere in the schematic, that triggers "keep_loading" method, which triggers the WaveFile objects in the buffer to load next datachunk. While loading the file outputs a progress bar (0-1 float) and when finishes it outputs nil. The nil is a sign for the "keep_loading" method to remove this file from the buffer and proceed to the next.
Only downside of this approach is, that the loading speed is effectively fixed, so it will need to be set low enough for slower machines to keep up. This unnecessarily penalizes people with fast computers.
Perhaps there is a way to test processing speed of a computer by taking advantage of the ruby locking in flowstone. And it's not like we can test the loading speed either... because the speed may be different, depending on the files location (SSD, HDD, internet, etc.).
I still kept the "background loading" optional. You can load the file in one go if you're certain it will be a small single file or put them into loading buffer for safe loading.
- Attachments
-
- newWavev0.2.fsm
- (4.22 KiB) Downloaded 1102 times
- KG_is_back
- Posts: 1196
- Joined: Tue Oct 22, 2013 5:43 pm
- Location: Slovakia
Re: custom WaveFile class for ruby
It's too late now to go into details. Just one thing: The class constant may bring you into trouble. That is if you have several instances of the plugin running in the daw, they will share the constant.
I like your approach. As long as Ruby gets back control from time to time, everything's fine. Regarding loading speed, you could load a block and measure time, only then start the real process of loading, adapted to the measuring.
I like your approach. As long as Ruby gets back control from time to time, everything's fine. Regarding loading speed, you could load a block and measure time, only then start the real process of loading, adapted to the measuring.
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
Re: custom WaveFile class for ruby
tulamide wrote:It's too late now to go into details. Just one thing: The class constant may bring you into trouble. That is if you have several instances of the plugin running in the daw, they will share the constant.
It is OK if they do. preferably you want to load only one file at a time anyway.
tulamide wrote:Regarding loading speed, you could load a block and measure time, only then start the real process of loading, adapted to the measuring.
Oh... I didn't realize it is possible to measure time in ruby via Time class. That is cool! It solves SO many problems... I wish I figured that one out sooner
- KG_is_back
- Posts: 1196
- Joined: Tue Oct 22, 2013 5:43 pm
- Location: Slovakia
Re: custom WaveFile class for ruby
OK, I've implemented the loading as smoothly as possible. Only problem seems to be relatively high memory-usage. I had to force garbage collection after every loaded file, because I had occasional "out of memory" errors when trying to allocate memory for new file, if both old an new file were very big.
I still feel this might not be the ideal way to work with wave files...
I still feel this might not be the ideal way to work with wave files...
- Attachments
-
- newWavev0.2.fsm
- (6.57 KiB) Downloaded 1092 times
- KG_is_back
- Posts: 1196
- Joined: Tue Oct 22, 2013 5:43 pm
- Location: Slovakia
Re: custom WaveFile class for ruby
KG_is_back wrote:OK, I've implemented the loading as smoothly as possible. Only problem seems to be relatively high memory-usage. I had to force garbage collection after every loaded file, because I had occasional "out of memory" errors when trying to allocate memory for new file, if both old an new file were very big.
I still feel this might not be the ideal way to work with wave files...
The gc is lazy and if you are giving Ruby so little idle time this is the result. Nothing to worry about, I'd say.
Your last sentence makes me smile. Let me ask you: What would be the ideal way to work with wave files then, from your point of view?
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
Re: custom WaveFile class for ruby
tulamide wrote:Your last sentence makes me smile. Let me ask you: What would be the ideal way to work with wave files then, from your point of view?
Well... for a start, using compiled code vs. interpreted one could improve performance. Ruby seems to do waste a lot of resources allocating memory. I tried to write the code in a way, that most of the the buffers and variables are reused. I might be overreacting here.
Question: does ruby actually create (and allocate memory for) an intermediate array in scenario like this?
- Code: Select all
def convert16bitIntToFloat(buffer) #buffer is a string of packed 16bit integers
buffer.unpack("s*").map!{|a| a=a*(2.0**-16)}.pack("f*")
end
in theory the code could be implemented by reading values from the string, converting it and then packing it to new string as float. However, the way I understand ruby, it first creates array, fills it with the integers from the string (by converting them one by one). Then iterating through the array (via map! method) and finally packing the array to new string. It allocates memory for one full array completely purposelessly.
I might be wrong and it might be the case, that ruby does some self-optimization under the hood, but somehow I doubt it. Using winAPI dll could possibly solve this problem, but it will not work for VSTs :-/
- KG_is_back
- Posts: 1196
- Joined: Tue Oct 22, 2013 5:43 pm
- Location: Slovakia
Re: custom WaveFile class for ruby
Hehe, and that's why I smiled. You probably guess that I expected your answer. You look for more efficient ways. But, Ruby is not part of Flowstone for efficiency, but for comfort. It is such a convenient language that it allows most complex things in just a few lines of code. Your example is a good one in this regard. Just one line of code, but look what it does!
Flowstone created plugins are also kind of interpreted. Which means, just as Ruby has, there are precompiled building blocks and a script that calls them. If you think Ruby's not good enough because it is interpreted, you have to say the same about Flowstone.
In fact, I've seen quite a few guys here on the forums from which I asked myself, why they don't do the jump to C/C++. And guess what, they did. The last one was MyCo. I see you in the same situation. You are far too good in your skills to waste it on Flowstone. Really! You should jump to C++ as well. I have no doubt you will have fast success in learning.
But back to the current situation. Yes, you are right. Ruby acts exactly as you describe it. But that's when using pre-built convenience functions. Nobody forces you to use them. Build your own conversion method, Ruby offers quite some tools for byte and bit access.
Your assumption, an external library wouldn't work for VSTs is wrong. That only refers to Ruby Gems. You can safely use dlls, as long as you export your VST with the appropriate ruby\libraries\win32 folder (More about it at the end of chapter 8). Here's a very, very, very good library. The best about it is, that no matter what format the original file was in, you just call for a format (in our case 32bit float) and it will be auto-converted on the fly. This library is all about loading and writing audio files - and nothing else. But, it allows you to access dozens of soundfile-formats, incl. flac and ogg.
For the documentation and a windows installer visit
http://www.mega-nerd.com/libsndfile/
For just the dll visit
https://github.com/bastibe/libsndfile-binaries
Flowstone created plugins are also kind of interpreted. Which means, just as Ruby has, there are precompiled building blocks and a script that calls them. If you think Ruby's not good enough because it is interpreted, you have to say the same about Flowstone.
In fact, I've seen quite a few guys here on the forums from which I asked myself, why they don't do the jump to C/C++. And guess what, they did. The last one was MyCo. I see you in the same situation. You are far too good in your skills to waste it on Flowstone. Really! You should jump to C++ as well. I have no doubt you will have fast success in learning.
But back to the current situation. Yes, you are right. Ruby acts exactly as you describe it. But that's when using pre-built convenience functions. Nobody forces you to use them. Build your own conversion method, Ruby offers quite some tools for byte and bit access.
Your assumption, an external library wouldn't work for VSTs is wrong. That only refers to Ruby Gems. You can safely use dlls, as long as you export your VST with the appropriate ruby\libraries\win32 folder (More about it at the end of chapter 8). Here's a very, very, very good library. The best about it is, that no matter what format the original file was in, you just call for a format (in our case 32bit float) and it will be auto-converted on the fly. This library is all about loading and writing audio files - and nothing else. But, it allows you to access dozens of soundfile-formats, incl. flac and ogg.
For the documentation and a windows installer visit
http://www.mega-nerd.com/libsndfile/
For just the dll visit
https://github.com/bastibe/libsndfile-binaries
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
9 posts
• Page 1 of 1
Who is online
Users browsing this forum: Google [Bot] and 17 guests