buffer, frames and channels clarification

Nov 11, 2006 at 11:57am

buffer, frames and channels clarification

Hello,

i need a little clarification about the values we deal with when
peeking/poking buffers. Untill now, what i’ve done worked fine but with
a great dose of luck. But i need to understand what’s the matter with
buffer->b_chans & buffer->b_frames… In parts of my code, using
buffer->b_frames for position (in samples) is ok, sometimes i have to
multiply b_frames by b_chans… In the following code, crossfade
positions are wrong and i don’t know why.

typedef struct _tapedeck
{
t_pxobject m_ob; // my object
t_symbol *bufname; // buffer~ name
t_buffer *buf; // buffer~ object

long length_samps; // buffer~ length in samples
float length_ms; // buffer~ length in milliseconds
long chan; // current channel (?)

long xfsize_samps; // crossfade size in samples
long xfsize_ms; // crossfade size in milliseconds
long loop_start; // real loop start (according to
pre-roll)
long loop_end; // loop_length + pre-roll (beat_length)

long xfadein_start; // loop_start – xfsize_samps / 2
long xfadeout_start; // loop_end + xfsize_samps / 2

long tempo; // tempo in bpm
long beat; // beat division
long beat_length; // one beat length in samples
long loop_length; // loop length given by tempo & beat

float loop_points; // to update groove~ loop points

} t_tapedeck;

(…)

long index;
float *b_samples_in;
float *b_samples_out;
float *b_samples_final;

// default values
x->tempo = 120;
x->beat = 4;

// get buffer length

x->length_samps = x->buf->b_frames;
x->length_ms = x->length_samps / (x->buf->b_sr/1000);

// set fade size in samples

if (!x->xfsize_ms) x->xfsize_ms = 100;

x->xfsize_samps = x->xfsize_ms * (x->buf->b_sr/1000);

// set fade out points
//x->fadeout_start = (x->length_samps – x->xfsize_samps)*x->chan;
//if (debug) post(“fade_out start : %d”, x->fadeout_start);

// set variables

x->beat_length = 60000. / x->tempo; // in ms
x->loop_length = msToSamps(x, x->beat_length * x->beat); // in
samples
x->loop_start = msToSamps(x, x->beat_length); // in samples
x->loop_end = x->beat_length * (x->beat + 1); // in ms
x->xfadein_start = x->loop_start – (x->xfsize_samps / 2);
x->xfadeout_start = (x->loop_length + x->loop_start) –
(x->xfsize_samps / 2);

b_samples_in = malloc(sizeof(float)*x->xfsize_samps*x->chan);
b_samples_out = malloc(sizeof(float)*x->xfsize_samps*x->chan);
b_samples_final = malloc(sizeof(float)*x->xfsize_samps*x->chan);

for (index = 0; index < = x->xfsize_samps*x->chan; index++)
{
*(b_samples_in+index) =
*(x->buf->b_samples+(x->xfadein_start+index)) * ( (float) index /
(x->xfsize_samps*x->chan) );
*(b_samples_out+index) =
*(x->buf->b_samples+(x->xfadeout_start+index)) * (1 -((float)index /
(x->xfsize_samps*x->chan)));
*(b_samples_final+index)= *(b_samples_in+index) +
*(b_samples_out+index);
}

for (index = 0; index < = x->xfsize_samps*x->chan; index++)
{

*(x->buf->b_samples+(x->xfadein_start+index))=*(b_samples_final+index);

*(x->buf->b_samples+(x->xfadeout_start+index))=*(b_samples_final+index);
}

I hope there’s enough infos here…

best regards

f.e

#28645
Nov 12, 2006 at 1:17pm

f.e wrote:

> Hello,
>
> i need a little clarification about the values we deal with when
> peeking/poking buffers. Untill now, what i’ve done worked fine but with
> a great dose of luck. But i need to understand what’s the matter with
> buffer->b_chans & buffer->b_frames… In parts of my code, using
> buffer->b_frames for position (in samples) is ok, sometimes i have to
> multiply b_frames by b_chans… In the following code, crossfade
> positions are wrong and i don’t know why.

buffer->b_chans is the number of channels the buffer~ has.

buffer->b_frames is the number auf ‘audio frames’, which can be
calculated as:
buffer->b_frames = buffer->b_size / buffer->b_nchans;

buffer->b_size is the total size of buffer in SAMPLES. These sampes can
be short, int or float or whatever, you set their type in:

buffer->b_outputbytes = sizeof(float); // or whatever it is

However, I’m not sure whether anything apart from float is officially
supported. As long as you use buffer~s with your own objects only and
they know what to do it’s probably okay.

So the total size in bytes of buffer~’s audio part in memory is:

buffer->b_size * buffer->b_outputbytes;

or:

buffer->b_frames * buffer->b_nchans * buffer->b_outputbytes;

Hope this helps a bit.

Ah, and when you modify a buffer you have to do something like this:

buffer->b_modtime = gettime(); buffer->b_valid = true;

This tells Max that you messed with it, the time will tell Max when you
did so, so that it knows whether it should redraw the window.
The last thing is setting the valid tag back to true to allow others to
access buffer again.

In some code examples you see things like this:

while (1) // spin while buffer~ is in use
{
if (!buffer->b_inuse)
break;
}
buffer->b_valid = false;

But when you access a buffer from a second thread you should probably do
something like this:

while (1) // spin while buffer~ is in use
{
if (!x->x_buffer->b_inuse)
break;
else
#ifdef _WINDOWS
Sleep(1);
#else
usleep(1000);
#endif
}
buffer->b_valid = false;

…because the first example eats all the CPU power while spinning in
the while loop….

Olaf

#88239
Nov 12, 2006 at 5:45pm

Hi there,

thanks Olaf. It definetely helps…
There is another flag I have never been clear about:

float *b_memory;
// pointer to where memory starts (initial padding for
interp)

That’s what the buffer.h file says.

Many times you need to write routines that interpolate
the samples in a buffer. How would you use this
‘extra’ memory for that purpose?

Any sample code someone could share?

Thank you.

- Luigi

— Olaf Matthes

wrote:

> f.e wrote:
>
> > Hello,
> >
> > i need a little clarification about the values we
> deal with when
> > peeking/poking buffers. Untill now, what i’ve done
> worked fine but with
> > a great dose of luck. But i need to understand
> what’s the matter with
> > buffer->b_chans & buffer->b_frames… In parts of
> my code, using
> > buffer->b_frames for position (in samples) is ok,
> sometimes i have to
> > multiply b_frames by b_chans… In the following
> code, crossfade
> > positions are wrong and i don’t know why.
>
> buffer->b_chans is the number of channels the
> buffer~ has.
>
> buffer->b_frames is the number auf ‘audio frames’,
> which can be
> calculated as:
> buffer->b_frames = buffer->b_size /
> buffer->b_nchans;
>
> buffer->b_size is the total size of buffer in
> SAMPLES. These sampes can
> be short, int or float or whatever, you set their
> type in:
>
> buffer->b_outputbytes = sizeof(float); // or
> whatever it is
>
> However, I’m not sure whether anything apart from
> float is officially
> supported. As long as you use buffer~s with your own
> objects only and
> they know what to do it’s probably okay.
>
> So the total size in bytes of buffer~’s audio part
> in memory is:
>
> buffer->b_size * buffer->b_outputbytes;
>
> or:
>
> buffer->b_frames * buffer->b_nchans *
> buffer->b_outputbytes;
>
>
> Hope this helps a bit.
>
> Ah, and when you modify a buffer you have to do
> something like this:
>
> buffer->b_modtime = gettime(); buffer->b_valid
> = true;
>
> This tells Max that you messed with it, the time
> will tell Max when you
> did so, so that it knows whether it should redraw
> the window.
> The last thing is setting the valid tag back to true
> to allow others to
> access buffer again.
>
> In some code examples you see things like this:
>
> while (1) // spin while buffer~ is in use
> {
> if (!buffer->b_inuse)
> break;
> }
> buffer->b_valid = false;
>
>
> But when you access a buffer from a second thread
> you should probably do
> something like this:
>
> while (1) // spin while buffer~ is in use
> {
> if (!x->x_buffer->b_inuse)
> break;
> else
> #ifdef _WINDOWS
> Sleep(1);
> #else
> usleep(1000);
> #endif
> }
> buffer->b_valid = false;
>
> …because the first example eats all the CPU power
> while spinning in
> the while loop….
>
>
> Olaf
>

————————————————————
THIS E-MAIL MESSAGE IS FOR THE SOLE USE OF THE INTENDED RECIPIENT AND MAY CONTAIN CONFIDENTIAL AND/OR PRIVILEGED INFORMATION. ANY UNAUTHORIZED REVIEW, USE, DISCLOSURE OR DISTRIBUTION IS PROHIBITED. IF YOU ARE NOT THE INTENDED RECIPIENT, CONTACT THE SENDER BY E-MAIL AT SUPERBIGIO@YAHOO.COM AND DESTROY ALL COPIES OF THE ORIGINAL MESSAGE. WITHOUT PREJUDICE UCC1-207.
————————————————————

Do you Yahoo!?
Everyone is raving about the all-new Yahoo! Mail beta.

http://new.mail.yahoo.com

#88240
Nov 14, 2006 at 1:47pm

Am 12.11.2006 um 18:45 schrieb Luigi Castelli:

> Hi there,
>
> thanks Olaf. It definetely helps…
> There is another flag I have never been clear about:
>
> float *b_memory;
> // pointer to where memory starts (initial padding for
> interp)
>
> That’s what the buffer.h file says.
>
> Many times you need to write routines that interpolate
> the samples in a buffer. How would you use this
> ‘extra’ memory for that purpose?

And one more buffer~ question: which memory functions should one use
to resize a buffer~? I’m currently working on an external that
imports audio files into buffers, so I have to resize the buffer to
have the size of the file. Is t_resizebytes() okay for that or should
I use something else?

Olaf

#88241

You must be logged in to reply to this topic.