Cropping buffer - Server.sync + best way

View: New views
14 Messages — Rating Filter:   Alert me  

Cropping buffer - Server.sync + best way

by thor-2 :: Rate this Message:

Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message


Hi all

I need to crop a buffer. That's not straight forward in SC because of memory
allocation on the buffer and such, so I'm wondering if the following is the best
way to do this? Has anyone got a better method?

But there are also some problems. See my comments.

PS. I need the cropped buffer to have the same bufnum as the original buffer.

cheers
thor


(
Routine.run {
var cond;
cond = Condition.new;


// original buffer
b = Buffer.read(s, "sounds/a11wlk01.wav");
"b.bufnum is: ".post; b.bufnum.postln;
s.sync(cond);

// temp buffer used in copying
c = Buffer.alloc(s, 88864, b.numChannels);
s.sync(cond);
b.copyData(c, 0, 100000, 88864); // my cropping
n = b.bufnum; // getting b's bufnum
s.sync(cond);
b.free;


// cropped buffer with b's bufnum
d = Buffer.alloc(s, c.numFrames, c.numChannels, bufnum:n);
s.sync(cond);
c.copyData(d);
s.sync(cond);
c.free;
\cropping_DONE.postln;
};
)


d.play // is the new buffer there? yes
d.bufnum // and it has the b.bufnum 

c.postln; 
c.play // c is freed. That's good.
c.bufnum

b.play // but I thought I'd freed b?
b.bufnum // and now b and d share same bufnum !!!

d.postln; 
b.postln;

// and now I could do d.write(b...path) and I've changed the file forever (I'll not do that to your file)




// I remember Julian telling me about s.bind once, but this doesn't work:
// Should it not?

(
s.bind({
b = Buffer.read(s, "sounds/a11wlk01.wav");
"b.bufnum is: ".post; b.bufnum.postln;
s.sync;

// temp buffer used in copying
c = Buffer.alloc(s, 88864, b.numChannels);
s.sync;
b.copyData(c, 0, 100000, 88864); // my cropping
n = b.bufnum; // getting b's bufnum
s.sync;
b.free;
s.sync;


// cropped buffer with b's bufnum
d = Buffer.alloc(s, c.numFrames, c.numChannels, bufnum:n);
s.sync;
c.copyData(d);
s.sync;
c.free;
})
)

d.play


Re: Cropping buffer - Server.sync + best way

by James Harkins-2 :: Rate this Message:

Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message

Take a look at Buffer:free --

free { arg completionMessage;
server.listSendMsg( this.freeMsg(completionMessage) );
}

It instructs the server to release the buffer, but does nothing else.

A Buffer (on the client) is really just a placeholder for the buffer number. Client-side Buffer objects don't know about changes in a server-side buffer's status. In your example, b was actually freed on the server, but "b" means (with respect to server communication), "Do stuff with whatever is being held at that buffer number right now." The other buffer object, d, puts new stuff at the same location that b is pointing to.

b and d are distinct objects on the client, but they point to the same buffer number on the server.

A sloppy C programmer can do something similar with a pointer variable that wasn't cleared properly -- i.e., try to access a memory location that is no longer allocated, or that is currently allocated for something else. There, the consequence is probably that the program crashes, rather than an unexpected response to .play.

We could argue about whether Buffer:free should clear the bufnum variable. I'm skeptical because it might break code.

If b's content is no longer meaningful in your code after freeing it, why not clear it? b = nil -- Cleaning up your garbage is a generally good programming practice anyway.

hjh

On Jul 20, 2008, at 9:14 AM, thor wrote:

b.play // but I thought I'd freed b?
b.bufnum // and now b and d share same bufnum !!!



: H. James Harkins

: jamshark70@...

: http://www.dewdrop-world.net

.::!:.:.......:.::........:..!.::.::...:..:...:.:.:.:..:


"Come said the Muse,

Sing me a song no poet has yet chanted,

Sing me the universal."  -- Whitman



Re: Cropping buffer - Server.sync + best way

by Dan Stowell :: Rate this Message:

Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message

Looks like JH has answered your main issue. Regarding s.bind, remember
what it does: it colllects together all the OSC messages that your
function creates, and bundles them all off once the function has
completed. So it's illogical to use s.sync inside an s.bind, because
the OSC message sent out by s.sync won't be sent until the function
has completed, yet s.sync won't let the function complete until it's
heard a reply back...

Dan


2008/7/20 thor <th.list@...>:

>
> Hi all
> I need to crop a buffer. That's not straight forward in SC because of memory
> allocation on the buffer and such, so I'm wondering if the following is the
> best
> way to do this? Has anyone got a better method?
> But there are also some problems. See my comments.
> PS. I need the cropped buffer to have the same bufnum as the original
> buffer.
> cheers
> thor
>
> (
> Routine.run {
> var cond;
> cond = Condition.new;
>
> // original buffer
> b = Buffer.read(s, "sounds/a11wlk01.wav");
> "b.bufnum is: ".post; b.bufnum.postln;
> s.sync(cond);
> // temp buffer used in copying
> c = Buffer.alloc(s, 88864, b.numChannels);
> s.sync(cond);
> b.copyData(c, 0, 100000, 88864); // my cropping
> n = b.bufnum; // getting b's bufnum
> s.sync(cond);
> b.free;
>
> // cropped buffer with b's bufnum
> d = Buffer.alloc(s, c.numFrames, c.numChannels, bufnum:n);
> s.sync(cond);
> c.copyData(d);
> s.sync(cond);
> c.free;
> \cropping_DONE.postln;
> };
> )
>
> d.play // is the new buffer there? yes
> d.bufnum // and it has the b.bufnum
> c.postln;
> c.play // c is freed. That's good.
> c.bufnum
> b.play // but I thought I'd freed b?
> b.bufnum // and now b and d share same bufnum !!!
> d.postln;
> b.postln;
> // and now I could do d.write(b...path) and I've changed the file forever
> (I'll not do that to your file)
>
>
>
> // I remember Julian telling me about s.bind once, but this doesn't work:
> // Should it not?
> (
> s.bind({
> b = Buffer.read(s, "sounds/a11wlk01.wav");
> "b.bufnum is: ".post; b.bufnum.postln;
> s.sync;
> // temp buffer used in copying
> c = Buffer.alloc(s, 88864, b.numChannels);
> s.sync;
> b.copyData(c, 0, 100000, 88864); // my cropping
> n = b.bufnum; // getting b's bufnum
> s.sync;
> b.free;
> s.sync;
>
> // cropped buffer with b's bufnum
> d = Buffer.alloc(s, c.numFrames, c.numChannels, bufnum:n);
> s.sync;
> c.copyData(d);
> s.sync;
> c.free;
> })
> )
> d.play
>



--
http://www.mcld.co.uk

_______________________________________________
sc-users mailing list

info (subscribe and unsubscribe): http://swiki.hfbk-hamburg.de:8888/MusicTechnology/880
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/

Re: Cropping buffer - Server.sync + best way

by thor-2 :: Rate this Message:

Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message


Thanks James. I get why the client still has the reference.

Would you say that this is a good way of cropping a buffer though?
Is there a better way?

Also, I'm interested to know why the s.bind example is not working but
perhaps Julian can explain that if he'll read this thread.

cheers
thor


On 20 Jul 2008, at 15:10, James Harkins wrote:

Take a look at Buffer:free --

free { arg completionMessage;
server.listSendMsg( this.freeMsg(completionMessage) );
}

It instructs the server to release the buffer, but does nothing else.

A Buffer (on the client) is really just a placeholder for the buffer number. Client-side Buffer objects don't know about changes in a server-side buffer's status. In your example, b was actually freed on the server, but "b" means (with respect to server communication), "Do stuff with whatever is being held at that buffer number right now." The other buffer object, d, puts new stuff at the same location that b is pointing to.

b and d are distinct objects on the client, but they point to the same buffer number on the server.

A sloppy C programmer can do something similar with a pointer variable that wasn't cleared properly -- i.e., try to access a memory location that is no longer allocated, or that is currently allocated for something else. There, the consequence is probably that the program crashes, rather than an unexpected response to .play.

We could argue about whether Buffer:free should clear the bufnum variable. I'm skeptical because it might break code.

If b's content is no longer meaningful in your code after freeing it, why not clear it? b = nil -- Cleaning up your garbage is a generally good programming practice anyway.

hjh

On Jul 20, 2008, at 9:14 AM, thor wrote:

b.play // but I thought I'd freed b?
b.bufnum // and now b and d share same bufnum !!!



: H. James Harkins
.::!:.:.......:.::........:..!.::.::...:..:...:.:.:.:..:

"Come said the Muse,
Sing me a song no poet has yet chanted,
Sing me the universal."  -- Whitman



Re: Cropping buffer - Server.sync + best way

by Julian Rohrhuber :: Rate this Message:

Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message

>Looks like JH has answered your main issue. Regarding s.bind, remember
>what it does: it colllects together all the OSC messages that your
>function creates, and bundles them all off once the function has
>completed. So it's illogical to use s.sync inside an s.bind, because
>the OSC message sent out by s.sync won't be sent until the function
>has completed, yet s.sync won't let the function complete until it's
>heard a reply back...


no, this is not correct. A sync inside a bind will separate the
bundles and automatically send the second part when the first is
received.

So it should work, I don't know why it wouldn't.
Take a look into the BundleNetAddr, maybe there is aome way to query
your intermediate state.


>Dan
>
>
>2008/7/20 thor <th.list@...>:
>>
>>  Hi all
>>  I need to crop a buffer. That's not straight forward in SC because of memory
>>  allocation on the buffer and such, so I'm wondering if the following is the
>>  best
>>  way to do this? Has anyone got a better method?
>>  But there are also some problems. See my comments.
>>  PS. I need the cropped buffer to have the same bufnum as the original
>>  buffer.
>>  cheers
>>  thor
>>
>>  (
>>  Routine.run {
>>  var cond;
>>  cond = Condition.new;
>>
>>  // original buffer
>>  b = Buffer.read(s, "sounds/a11wlk01.wav");
>>  "b.bufnum is: ".post; b.bufnum.postln;
>>  s.sync(cond);
>>  // temp buffer used in copying
>>  c = Buffer.alloc(s, 88864, b.numChannels);
>>  s.sync(cond);
>>  b.copyData(c, 0, 100000, 88864); // my cropping
>>  n = b.bufnum; // getting b's bufnum
>>  s.sync(cond);
>>  b.free;
>>
>>  // cropped buffer with b's bufnum
>>  d = Buffer.alloc(s, c.numFrames, c.numChannels, bufnum:n);
>>  s.sync(cond);
>>  c.copyData(d);
>>  s.sync(cond);
>>  c.free;
>>  \cropping_DONE.postln;
>>  };
>>  )
>>
>>  d.play // is the new buffer there? yes
>>  d.bufnum // and it has the b.bufnum
>>  c.postln;
>>  c.play // c is freed. That's good.
>>  c.bufnum
>>  b.play // but I thought I'd freed b?
>>  b.bufnum // and now b and d share same bufnum !!!
>>  d.postln;
>>  b.postln;
>>  // and now I could do d.write(b...path) and I've changed the file forever
>>  (I'll not do that to your file)
>>
>>
>>
>>  // I remember Julian telling me about s.bind once, but this doesn't work:
>>  // Should it not?
>>  (
>>  s.bind({
>>  b = Buffer.read(s, "sounds/a11wlk01.wav");
>>  "b.bufnum is: ".post; b.bufnum.postln;
>>  s.sync;
>>  // temp buffer used in copying
>>  c = Buffer.alloc(s, 88864, b.numChannels);
>>  s.sync;
>>  b.copyData(c, 0, 100000, 88864); // my cropping
>>  n = b.bufnum; // getting b's bufnum
>>  s.sync;
>>  b.free;
>>  s.sync;
>>
>>  // cropped buffer with b's bufnum
>>  d = Buffer.alloc(s, c.numFrames, c.numChannels, bufnum:n);
>>  s.sync;
>>  c.copyData(d);
>>  s.sync;
>>  c.free;
>>  })
>>  )
>>  d.play
>>
>
>
>
>--
>http://www.mcld.co.uk
>
>_______________________________________________
>sc-users mailing list
>
>info (subscribe and unsubscribe):
>http://swiki.hfbk-hamburg.de:8888/MusicTechnology/880
>archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
>search: http://www.listarc.bham.ac.uk/lists/sc-users/search/


--





.

_______________________________________________
sc-users mailing list

info (subscribe and unsubscribe): http://swiki.hfbk-hamburg.de:8888/MusicTechnology/880
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/

Re: Cropping buffer - Server.sync + best way

by thor-2 :: Rate this Message:

Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message


Thanks for all the replies. Right now I don't have time to investigate the bind issue
but I've implemented the crop method like this:

(still interested in improvements : )


b = Buffer.read(s, "sounds/a11wlk01.wav");
b.play
b.crop(100000, 66666, false)
b.play
b


+ Buffer {
crop {arg startFrame, numFrames, overwrite=false;
var s, cond, tempbuf, tempbufnum, newbuf, chNum;
cond = Condition.new;
s = Server.default;


Routine.run {
chNum = this.numChannels;
s.sync(cond);
tempbuf = Buffer.alloc(s, numFrames, chNum);
s.sync(cond);
this.copyData(tempbuf, 0, startFrame, numFrames);
tempbufnum = this.bufnum;
s.sync(cond);
this.free;
s.sync(cond);

newbuf = Buffer.alloc(s, tempbuf.numFrames, tempbuf.numChannels, bufnum:tempbufnum);
s.sync(cond);
tempbuf.copyData(newbuf);
s.sync(cond);
tempbuf.free;
tempbuf = nil;


if(overwrite, { newbuf.write(this.path, "aiff", "int16") });


s.sync(cond);
this.updateInfo; // update so the buffer object has the new buffer info
};
}
}



On 20 Jul 2008, at 16:54, Julian Rohrhuber wrote:

Looks like JH has answered your main issue. Regarding s.bind, remember
what it does: it colllects together all the OSC messages that your
function creates, and bundles them all off once the function has
completed. So it's illogical to use s.sync inside an s.bind, because
the OSC message sent out by s.sync won't be sent until the function
has completed, yet s.sync won't let the function complete until it's
heard a reply back...


no, this is not correct. A sync inside a bind will separate the bundles and automatically send the second part when the first is received.

So it should work, I don't know why it wouldn't.
Take a look into the BundleNetAddr, maybe there is aome way to query your intermediate state.


Dan


2008/7/20 thor <th.list@...>:

 Hi all
 I need to crop a buffer. That's not straight forward in SC because of memory
 allocation on the buffer and such, so I'm wondering if the following is the
 best
 way to do this? Has anyone got a better method?
 But there are also some problems. See my comments.
 PS. I need the cropped buffer to have the same bufnum as the original
 buffer.
 cheers
 thor

 (
 Routine.run {
 var cond;
 cond = Condition.new;

 // original buffer
 b = Buffer.read(s, "sounds/a11wlk01.wav");
 "b.bufnum is: ".post; b.bufnum.postln;
 s.sync(cond);
 // temp buffer used in copying
 c = Buffer.alloc(s, 88864, b.numChannels);
 s.sync(cond);
 b.copyData(c, 0, 100000, 88864); // my cropping
 n = b.bufnum; // getting b's bufnum
 s.sync(cond);
 b.free;

 // cropped buffer with b's bufnum
 d = Buffer.alloc(s, c.numFrames, c.numChannels, bufnum:n);
 s.sync(cond);
 c.copyData(d);
 s.sync(cond);
 c.free;
 \cropping_DONE.postln;
 };
 )

 d.play // is the new buffer there? yes
 d.bufnum // and it has the b.bufnum
 c.postln;
 c.play // c is freed. That's good.
 c.bufnum
 b.play // but I thought I'd freed b?
 b.bufnum // and now b and d share same bufnum !!!
 d.postln;
 b.postln;
 // and now I could do d.write(b...path) and I've changed the file forever
 (I'll not do that to your file)



 // I remember Julian telling me about s.bind once, but this doesn't work:
 // Should it not?
 (
 s.bind({
 b = Buffer.read(s, "sounds/a11wlk01.wav");
 "b.bufnum is: ".post; b.bufnum.postln;
 s.sync;
 // temp buffer used in copying
 c = Buffer.alloc(s, 88864, b.numChannels);
 s.sync;
 b.copyData(c, 0, 100000, 88864); // my cropping
 n = b.bufnum; // getting b's bufnum
 s.sync;
 b.free;
 s.sync;

 // cropped buffer with b's bufnum
 d = Buffer.alloc(s, c.numFrames, c.numChannels, bufnum:n);
 s.sync;
 c.copyData(d);
 s.sync;
 c.free;
 })
 )
 d.play




--

_______________________________________________
sc-users mailing list



-- 





.

_______________________________________________
sc-users mailing list



Re: Cropping buffer - Server.sync + best way

by Fredrik Olofsson :: Rate this Message:

Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message

some minor suggestions...
i would avoid Server.default inside a method.  specially here since  
the Buffer object already knows which server it belongs to.
and this.numChannels and this.bufnum could be just numChannels and  
bufnum.
your argument numFrames you might want to rename just to make it  
different from Buffer.numFrames.
the first .sync should not be needed.
and perhaps add an action function?
_f


/*
b = Buffer.read(s, "sounds/a11wlk01.wav");
b.play
b.crop(100000, 66666, false)
b.play
b
*/

+ Buffer {
        crop {arg startFrame, frames, overwrite=false, action;
                var cond, tempbuf, newbuf;
                cond = Condition.new;
               
                Routine.run {
                        tempbuf = Buffer.alloc(server, frames, numChannels);
                        server.sync(cond);
                        this.copyData(tempbuf, 0, startFrame, frames);
                        server.sync(cond);
                        this.free;
                        server.sync(cond);

                        newbuf = Buffer.alloc(server, tempbuf.numFrames,  
tempbuf.numChannels, bufnum:bufnum);
                        server.sync(cond);
                        tempbuf.copyData(newbuf);
                        server.sync(cond);
                        tempbuf.free;
                        tempbuf = nil;
                       
                        if(overwrite, { newbuf.write(this.path, "aiff", "int16") });
                       
                        server.sync(cond);
                        this.updateInfo(action); // update so the buffer object has the  
new buffer info
                };
        }
}



21 jul 2008 kl. 01.04 skrev thor:

>
> Thanks for all the replies. Right now I don't have time to  
> investigate the bind issue
> but I've implemented the crop method like this:
>
> (still interested in improvements : )
>
>
> b = Buffer.read(s, "sounds/a11wlk01.wav");
> b.play
> b.crop(100000, 66666, false)
> b.play
> b
>
>
> + Buffer {
> crop {arg startFrame, numFrames, overwrite=false;
> var s, cond, tempbuf, tempbufnum, newbuf, chNum;
> cond = Condition.new;
> s = Server.default;
>
> Routine.run {
> chNum = this.numChannels;
> s.sync(cond);
> tempbuf = Buffer.alloc(s, numFrames, chNum);
> s.sync(cond);
> this.copyData(tempbuf, 0, startFrame, numFrames);
> tempbufnum = this.bufnum;
> s.sync(cond);
> this.free;
> s.sync(cond);
>
> newbuf = Buffer.alloc(s, tempbuf.numFrames, tempbuf.numChannels,  
> bufnum:tempbufnum);
> s.sync(cond);
> tempbuf.copyData(newbuf);
> s.sync(cond);
> tempbuf.free;
> tempbuf = nil;
>
> if(overwrite, { newbuf.write(this.path, "aiff", "int16") });
>
> s.sync(cond);
> this.updateInfo; // update so the buffer object has the new  
> buffer info
> };
> }
> }



   #|
      fredrikolofsson.com     klippav.org     musicalfieldsforever.com
   |#


_______________________________________________
sc-users mailing list

info (subscribe and unsubscribe): http://swiki.hfbk-hamburg.de:8888/MusicTechnology/880
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/

Re: Cropping buffer - Server.sync + best way

by thor-2 :: Rate this Message:

Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message


Great comments Fredrik.

It turns out that the method is not working so well: I can only crop it once, 
the second time I try to crop the same buffer, the frames disappear for some
reason and it seems to happen when the this.updateInfo is called.

Check out the method here with the postlns. But I've implemented all your
suggestions in this class.

Test code:

b = Buffer.read(s, "sounds/a11wlk01.wav");
b.numFrames
b.play


b.crop(100000, 66666, false, {|buf| buf.numFrames.postln;})
b.numFrames
b.play


b.crop(10000, 6666, false, {|buf| buf.numFrames.postln;})
b.numFrames
b.play


+ Buffer {
crop {arg