Hi folks, I'm trying to implement a ring buffer with a table for a sampler patch based on an array.
But I'm having the hardest time cause it always "clicks" when I start writing back on the beginning of the array.
I made this simple test attached below using metro. But I'm figuring the flaw is because is not trivial at all to keep control data in sync with audio blocks
any hints or ideas?
thanks
============================
#N canvas 727 343 619 425 10; #N canvas 0 0 450 300 (subpatch) 0; #X array sample 88200 float 2; #X coords 0 1 88199 -1 200 140 1; #X restore 261 172 graph; #X obj 82 188 tabwrite~ sample; #X obj 109 270 tabplay~ sample; #X obj 104 307 dac~; #X obj 99 240 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 168 131 metro 2000; #X obj 53 124 adc~ 1; #X obj 189 172 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 101 119 sel 0; #X msg 101 143 stop; #X obj 137 232 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 168 57 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 168 78 t f f; #X connect 2 0 3 0; #X connect 2 0 3 1; #X connect 2 1 4 0; #X connect 4 0 2 0; #X connect 5 0 1 0; #X connect 5 0 7 0; #X connect 6 0 1 0; #X connect 8 0 9 0; #X connect 9 0 1 0; #X connect 10 0 2 0; #X connect 11 0 12 0; #X connect 12 0 5 0; #X connect 12 1 8 0;
2012/1/8 Alexandre Torres Porres porres@gmail.com
Hi folks, I'm trying to implement a ring buffer with a table for a sampler patch based on an array.
But I'm having the hardest time cause it always "clicks" when I start writing back on the beginning of the array.
I made this simple test attached below using metro. But I'm figuring the flaw is because is not trivial at all to keep control data in sync with audio blocks
any hints or ideas?
[bang~] ?
thanks
============================
#N canvas 727 343 619 425 10; #N canvas 0 0 450 300 (subpatch) 0; #X array sample 88200 float 2; #X coords 0 1 88199 -1 200 140 1; #X restore 261 172 graph; #X obj 82 188 tabwrite~ sample; #X obj 109 270 tabplay~ sample; #X obj 104 307 dac~; #X obj 99 240 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 168 131 metro 2000; #X obj 53 124 adc~ 1; #X obj 189 172 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 101 119 sel 0; #X msg 101 143 stop; #X obj 137 232 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 168 57 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 168 78 t f f; #X connect 2 0 3 0; #X connect 2 0 3 1; #X connect 2 1 4 0; #X connect 4 0 2 0; #X connect 5 0 1 0; #X connect 5 0 7 0; #X connect 6 0 1 0; #X connect 8 0 9 0; #X connect 9 0 1 0; #X connect 10 0 2 0; #X connect 11 0 12 0; #X connect 12 0 5 0; #X connect 12 1 8 0;
Pd-list@iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
I know, I thought of that, but then, I need to make the table always as big as a multiple of an audio block, right?
I was hoping to have a way without this restrain. But maybe it isn't that much of a big deal.
2012/1/8 tim vets timvets@gmail.com
2012/1/8 Alexandre Torres Porres porres@gmail.com
Hi folks, I'm trying to implement a ring buffer with a table for a sampler patch based on an array.
But I'm having the hardest time cause it always "clicks" when I start writing back on the beginning of the array.
I made this simple test attached below using metro. But I'm figuring the flaw is because is not trivial at all to keep control data in sync with audio blocks
any hints or ideas?
[bang~] ?
thanks
============================
#N canvas 727 343 619 425 10; #N canvas 0 0 450 300 (subpatch) 0; #X array sample 88200 float 2; #X coords 0 1 88199 -1 200 140 1; #X restore 261 172 graph; #X obj 82 188 tabwrite~ sample; #X obj 109 270 tabplay~ sample; #X obj 104 307 dac~; #X obj 99 240 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 168 131 metro 2000; #X obj 53 124 adc~ 1; #X obj 189 172 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 101 119 sel 0; #X msg 101 143 stop; #X obj 137 232 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 168 57 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 168 78 t f f; #X connect 2 0 3 0; #X connect 2 0 3 1; #X connect 2 1 4 0; #X connect 4 0 2 0; #X connect 5 0 1 0; #X connect 5 0 7 0; #X connect 6 0 1 0; #X connect 8 0 9 0; #X connect 9 0 1 0; #X connect 10 0 2 0; #X connect 11 0 12 0; #X connect 12 0 5 0; #X connect 12 1 8 0;
Pd-list@iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
On 1/8/12, Alexandre Torres Porres porres@gmail.com wrote:
Hi folks, I'm trying to implement a ring buffer with a table for a sampler patch based on an array.
But I'm having the hardest time cause it always "clicks" when I start writing back on the beginning of the array.
I made this simple test attached below using metro. But I'm figuring the flaw is because is not trivial at all to keep control data in sync with audio blocks
any hints or ideas?
I think you might be better able to keep the data in sync with a vline~/metro/tabread4~ construction, because it preserves the timing information in the messages. Instead of vline~/metro, you could also use phasor~ which makes the looping implicit.
To work around clicks, crossfading is what I hear about the most on list. I'm not sure how it's implemented.
When I think about coding in C, I always want to have N contiguous samples to avoid having to check against the end of the array. To do that, you make the buffer 2*N-1 in length. Then, on each write, you write to two locations (0,N), (1,N+1), (2,N+2)... That ensures there is always N samples in a row to read from, and you just move the read pointer by 1 each time you get a vector of N samples long. (my personal method...nothing more).
Well, this is for the phase vocoder patch, which is based on miller's I07 example.
There's a counter that reads over the table, and I expanded the thing allowing it to loop and other convenient sampling controls.
I never needed a perfect loop, cause I never loaded real perfectly looped files in it, so I just check when the counter grows bigger than the table size and restart it. As for recording on the tables, I do fade-in and fade-out, because it would click anyway.
Now, for the ring buffer, it needs to be in perfect sync, so I can have tables that are multiples of the block size and use [bang~], it's not that much of a big restrain at all. You won't be able to specify an exact table size, but the resolution is 64 samples, and that is like 1.45 miliseconds (about nothing). So I got over it, did it, and it works!!!
I can adapt the thing for loaded samples, and have it the table size rounded up to multiples of the block + 1. This is not a perfect loop, but they weren't perfect before anyhow...
But why stop there? How to make it loop perfectly? This is the issue now. *Checking Miller's Phase Vocoder example. If you load a sample, how to make it loop perfectly?*
I know one could use phasor~ and other stuff to read the table. But for the Phase Vocoder patch, we need that structure with the counter and everything.
Well, I'll keep thinking.
Thanks
2012/1/8 Charles Henry czhenry@gmail.com
On 1/8/12, Alexandre Torres Porres porres@gmail.com wrote:
Hi folks, I'm trying to implement a ring buffer with a table for a
sampler
patch based on an array.
But I'm having the hardest time cause it always "clicks" when I start writing back on the beginning of the array.
I made this simple test attached below using metro. But I'm figuring the flaw is because is not trivial at all to keep control data in sync with audio blocks
any hints or ideas?
I think you might be better able to keep the data in sync with a vline~/metro/tabread4~ construction, because it preserves the timing information in the messages. Instead of vline~/metro, you could also use phasor~ which makes the looping implicit.
To work around clicks, crossfading is what I hear about the most on list. I'm not sure how it's implemented.
When I think about coding in C, I always want to have N contiguous samples to avoid having to check against the end of the array. To do that, you make the buffer 2*N-1 in length. Then, on each write, you write to two locations (0,N), (1,N+1), (2,N+2)... That ensures there is always N samples in a row to read from, and you just move the read pointer by 1 each time you get a vector of N samples long. (my personal method...nothing more).
Hi Alex
On Sun, 2012-01-08 at 16:33 -0200, Alexandre Torres Porres wrote:
Hi folks, I'm trying to implement a ring buffer with a table for a sampler patch based on an array.
But I'm having the hardest time cause it always "clicks" when I start writing back on the beginning of the array.
I made this simple test attached below using metro. But I'm figuring the flaw is because is not trivial at all to keep control data in sync with audio blocks
I see two flaws with the same cause in your patch.
Both objects, [tabwrite~ ] and [tabplay~ ], execute the incoming messages at block boundaries. Thus, your patch suffers from the limitation that you intended to avoid by not using [bang~ ]. It does not matter whether you use [bang~ ] or not, either way you cannot start the [tabwrite~ ] recording between blocks. It's not possible with the current implementation to make it record exactly every 2000ms (unless 2000ms is an exact multiple of the block size).
The same applies to [tabplay~]. It does not take into account the scheduling information of the incoming bang message and simply starts playing at the next block start.
Because of above mentioned reasons I suggest to stick with [delwrite~ ] and [delread~ ]. [delwrite~ ] is exactly what you are asking for: a ring buffer. Is there a particular reason why you don't use those?
Roman