How to know the number of the current sample in buffer~?

Mattia Zanzi's icon

Hello there. I'm using a buffer~ object to playback a sample. I'd love to get some help with a thing I'm implementing: basically, I need to know the number of the current sample which is played back. Not the actual value, but the sample number, compared to the total length (in sample) of the buffer~ content. The sampling rate is low, with only 100 samples per second. Any hint? Thanks a lot!

Source Audio's icon

use samplecount in that speed for playback and read current sample number.
100 hz sr means 10 ms per sample progress
metro 10 to counter to peek~ to sig~




Roman Thilenius's icon


one way to read from a buffer is to use the sample number by count~/index~, then you have it already.

Source Audio's icon

how does one set count~ to progres in 100 hz samplerate ?

Roman Thilenius's icon


it always progresses in samplerate? :)

i mean if he does not read at 1.0 speed, there is no samplecount (in int) anway.

Mattia Zanzi's icon

First of all, thanks for your replies. Let me better clarify my issue. My patch gravitates around the possibility to slow down the playback rate of the buffer~. To set the playback rate, I have the 'Slower' dial shown in the image below. Setting the dial on 2, the buffer will play at half the speed, 1/2. Now, I have tried to keep the sample count by using the 'count~' object, which seems to work as expected when the buffer plays at normal speed (i.e. when 'Slower' is set to 1); however, with other playback rates the counter keeps updating at the same rate as with normal speed, thus introducing artifacts to the current count. I don't know whether this is due to the properties of the groove~ object, which migth introduce some sort of interpolation (?) at low rates. Are you aware of any potential solution? Thanks a lot!

Source Audio's icon

what has the screenshot above with 100 Hz sampling rate that you mention in the original post?
Where do you set 100 Hz sampling rate ?
remove that count~ immediatelly, it has nothing to do there.

----
You have to understand a simple thing :
1- you use some mechanism that outputs count, either in signal or non signal form which tells some max object to output buffer contens.
In that case you would know which sample number you currently want to hear.

2- you use some autonome playback object and try to figure out which sampe it is currently playing.
it is your decision to go one or the other way.

In your screenshot you use groove~
it has sync output which outputs a signal 0. - 1. for set playback length.
You can translate that to length in samples , you just need to know how long loaded file is,
or how long slected playback chunk is.

Need help with that ?
post request ...

P.S. what for do you need to know which sample is currently playing for ?
You might want to do something with it which might work or not, depending on
how you retrieve current sample number.
To say it simple, post your question to the end, otherwise we all loose our time here.







Mattia Zanzi's icon

Sorry if my question was not clear. I'll try to better explain my purpose.

1) Currently, the first thing I do is loading an external .wav file to buffer~. In the patch, I want to start reading the buffer starting from a random sample value. To do this, I originally used the groove~ object in conjunction with the buffer~; I could therefore send the groove~ a message with a random integer X, and have the playback head now reading the buffer from number X.

2) After this, I have a looping mechanism. There is a button, and if I tap the button twice (1 and 2), the signal in the buffer~ is looped between tap 1 and tap 2. Thus, I thought to associate the knowledge of the 'current sample number' to the button taps: if tap 1 and 2 occur between sample nn. 1234 and 2234, I use a line object to generate a linear ramp between 1234 and 2234 (+ time between the two in msec), and send the ramp to the groove~ in order to play the buffer content between those two samples, in loop.

Combining 1) and 2): if I want to loop the signal between two samples in a buffer which starts at a random sample location, I need to know the current sample number relative to the buffer sample length, and encode it in the button taps. Problem: how do I keep track of this absolute sample number?

3) Finally, I noticed that the groove~ object was probably not the best option for my last purpose, that is: I want to be able to play the buffer~ content (i.e. the .wav file) at different speeds. However, the groove~ seems to output a fixed number of samples/second, regardless of the actual sampling frequency. This is why the counter~ object that you can find in my previous message is useless.

Conclusion: how to solve this issues, and combine 1), 2) and 3)? I thought to move to other objects, such as the peek~ associated with a counter (counting from 0 to buffer sample length), timed by a qmetro with scalable time (t). In this way, I can read the .wav file from the buffer at frequency t (e.g. 10ms for 100Hz sr), and use the current counter count to know the current sample number needed for the loop.

Is this the best option? Are there more elegant ways to do this? Thanks a lot. Hope this is clear enough.

Source Audio's icon

You are mixing apples and oranges.
As first you talk to groove in ms - miliseconds and not samples.
Sampling rate means something else than playback speed.

you don't send any line ramps to groove for playback, maybe you mean some other object....

You don't need 2 groove~ objects to set loop start - end points
and to change the speed. All can be done with single one.
The only disadvatage with groove object is that it's sync output is NOT
related to buffer length but to selected playback range of the buffer.
For me the main queston here is not that, but how to tap and capture loop start - end points and use them ?

You can multiply groove sync output with buffer length and so get current playback time in ms.
You can tap to capture it as "markers" to use for loop start or end point.
But as soon as you tell groove to use that 2 points it will output sync signal 0. -1.
related to that new loop points.
You will not be able to tap new loop points outside of that range, only smaller,
and in addition if you manage to tap second value (loop end point) at later time than start point is, groove~ will stop playback.
only way is to reset groove to use entire buffer length again.
-------
here is patch showing how to make sync output play length in ms
and to capture the flow using 1, 2 or as many buttons as you want.
Then you can try to use that captured play positions

Max Patch
Copy patch and select New From Clipboard in Max.







Mattia Zanzi's icon

Ow man, problem solved by your 'you can multiply groove sync output with buffer length and so get current playback time in ms'! Thanks a lot!!

Mattia Zanzi's icon

Hey! Still here to ask for a little help. In the end, this is the patch I came out with:

This patch depicts a looping mechanism: I have a button (defined by the circled letter 'L'), which I tap twice to define the starting/ending points of the loop; these two points are picked by taking two separate snapshots of the current sample timing, as it comes out of the groove~'s right outlet (and converted to msec, as previously suggested); furthermore, combining the loop start/end with the plugphasor~ + onebang objects assure me to be clocked to Ableton Live's tempo (for quantization). In the picture, I have used a timer to keep track of the time passed from the loop start and the loop end (2500 msec, in the blue message).

To instantiate the loop repetition, the moment when the 'L' button is tapped for the second time (i.e. loop end), the value of the loop-start (in msec) - stored within the f object - is banged to the groove~ left inlet; this ensures the instantaneous playback of the .wav file stored in the buffer~ from that value, and the subsequent output of the corresponding sample timing from the groove~ right outlet. Finally, repetition of the loop is achieved when the sample timing (in msec) is >=~ then the loop-end value (in msec), carried by sig~. Every time this occurs, the loop begins from the starting point.

My problem is the following: it seems that some extra time is introduced, and 9.333333 msec are added somewhere to the original loop length (2500 msec). This is demonstrated by the blue message with the red text. I have tried debugging the code several times, with different strategies. It might seem that the extra time is added during the >=~/change~/==~ 1/edge~ chain, but I can't really figure out any solution. I'd love to have each loop repetition last precisely as the time detected from loop-start to loop-end button taps. Do you have any possible solution or a different strategy to achieve the same purpose? Thanks a lot!

Source Audio's icon

post the patch and not screeshot.
in general, measuring and comparing time with signal and non signal objects
introduces differences, being vector size based, or when it comes to Ableton Live
I have no idea what else...
Ayway, it is important that measured time fits with beat length of Live transport.
If you change tempo it will fail anyway, but that seems not to be issue here.
If I understand correctly, you quantize loop length to beat grid of Live transport.
In that case it will HAVE to be same length as number of beats in ms.
display 2 tapped values and subtract them if you need to be sure you got the right length.





Source Audio's icon

here are few tips

1 you can simplify current position timer by sending sapshot~ output to multiplier,
instead of multiplying all the time.

2- if you use plugsync~ with rate~ (to use other length than Live Beat for quantizing), then this would be proper way to do it:

If you allways use Live Beat, than plugsync~ would be easier to use,
here is Beat bang :


-------
If you want good timing, remove all not needed GUI objects, like that whatever it is under the groove~ object in your screenshot.