aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/flext/source/flbuf.cpp
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2002-10-22 23:07:10 +0000
committerThomas Grill <xovo@users.sourceforge.net>2002-10-22 23:07:10 +0000
commitd62e56f4df9594f72ce501f5e19c974fd18e7295 (patch)
tree635d4af7a7c2425098e60ca277086ec436b617f7 /externals/grill/flext/source/flbuf.cpp
parentc6f373c281ecb5cd1f4aa7a070e15cc61ab8793c (diff)
This commit was generated by cvs2svn to compensate for changes in r186,
which included commits to RCS files with non-trunk default branches. svn path=/trunk/; revision=187
Diffstat (limited to 'externals/grill/flext/source/flbuf.cpp')
-rw-r--r--externals/grill/flext/source/flbuf.cpp255
1 files changed, 255 insertions, 0 deletions
diff --git a/externals/grill/flext/source/flbuf.cpp b/externals/grill/flext/source/flbuf.cpp
new file mode 100644
index 00000000..dc5704c0
--- /dev/null
+++ b/externals/grill/flext/source/flbuf.cpp
@@ -0,0 +1,255 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flbuf.cpp
+ \brief Implementation of the buffer abstraction class.
+*/
+
+#include "flext.h"
+
+#ifdef MAXMSP
+#include "flmspbuffer.h" // include inofficial buffer.h
+#endif
+
+#ifdef PD
+#define DIRTY_INTERVAL 0 // buffer dirty check in msec
+#endif
+
+
+
+flext::buffer::buffer(const t_symbol *bn,bool delayed):
+ sym(NULL),data(NULL),
+ chns(0),frames(0)
+{
+#ifdef PD
+ arr = NULL;
+ interval = DIRTY_INTERVAL;
+ isdirty = false;
+ ticking = false;
+ tick = clock_new(this,(t_method)cb_tick);
+#endif
+
+ if(bn) Set(bn,delayed);
+}
+
+flext::buffer::~buffer()
+{
+#ifdef PD
+ clock_free(tick);
+#endif
+}
+
+int flext::buffer::Set(const t_symbol *s,bool nameonly)
+{
+ int ret = 0;
+ bool valid = data != NULL; // valid now? (before change)
+
+ if(s && sym != s) {
+ ret = -1;
+ data = NULL;
+ frames = 0;
+ chns = 0;
+ }
+
+ if(s && *s->s_name) sym = s;
+
+ if(!sym) {
+ if(valid) ret = -1;
+ }
+ else if(!nameonly) {
+#ifdef PD
+ int frames1;
+ t_sample *data1;
+
+ arr = (t_garray *)pd_findbyclass(const_cast<t_symbol *>(sym), garray_class);
+ if(!arr)
+ {
+ if (*sym->s_name) error("buffer: no such array '%s'",sym->s_name);
+ sym = NULL;
+ if(valid) ret = -1;
+ }
+ else if(!garray_getfloatarray(arr, &frames1, &data1))
+ {
+ error("buffer: bad template '%s'", sym->s_name);
+ data = NULL;
+ frames = 0;
+ if(valid) ret = -1;
+ }
+ else {
+ garray_usedindsp(arr);
+ if(frames != frames1) { frames = frames1; if(!ret) ret = 1; }
+ if(data != data1) { data = data1; if(!ret) ret = 1; }
+ chns = 1;
+ }
+#elif defined(MAXMSP)
+ if(sym->s_thing) {
+ const _buffer *p = (const _buffer *)sym->s_thing;
+
+ if(NOGOOD(p)) {
+ post("buffer: buffer object '%s' no good",sym->s_name);
+ if(valid) ret = -1;
+ }
+ else {
+#ifdef DEBUG
+ post("%s: buffer object '%s' - valid:%i samples:%i channels:%i frames:%i",thisName(),bufname->s_name,p->b_valid,p->b_frames,p->b_nchans,p->b_frames);
+#endif
+ if(data != p->b_samples) { data = p->b_samples; if(!ret) ret = 1; }
+ if(chns != p->b_nchans) { chns = p->b_nchans; if(!ret) ret = 1; }
+ if(frames != p->b_frames) { frames = p->b_frames; if(!ret) ret = 1; }
+ }
+ }
+ else {
+ error("buffer: symbol '%s' not defined", sym->s_name);
+ if(valid) ret = -1;
+ }
+#endif
+ }
+
+ return ret;
+}
+
+bool flext::buffer::Update()
+{
+ if(!Ok()) return false;
+
+#ifdef PD
+ int frames1;
+ t_sample *data1;
+ if(!garray_getfloatarray(arr, &frames1, &data1)) {
+ frames = 0;
+ data = NULL;
+ chns = 0;
+ return true;
+ }
+ else if(data != data1 || frames != frames1) {
+ frames = frames1;
+ data = data1;
+ return true;
+ }
+ else
+ return false;
+#else // MAXMSP
+ if(!sym->s_thing)
+ return false;
+ else {
+ const _buffer *p = (const _buffer *)sym->s_thing;
+ if(data != p->b_samples || chns != p->b_nchans || frames != p->b_frames) {
+ data = p->b_samples;
+ chns = p->b_nchans;
+ frames = p->b_frames;
+ return true;
+ }
+ else
+ return false;
+ }
+#endif
+}
+
+void flext::buffer::Frames(int fr,bool keep)
+{
+#ifdef PD
+ ::garray_resize(arr,(float)fr);
+ Update();
+#else
+ t_sample *tmp = NULL;
+ int sz = frames;
+ if(fr < sz) sz = fr;
+
+ if(keep) {
+ // copy buffer data to tmp storage
+ tmp = new t_sample[sz];
+ if(tmp)
+ BlockMoveData(data,tmp,sizeof(t_sample)*sz);
+ else
+ error("flext::buffer - not enough memory for keeping buffer~ contents");
+ }
+
+ t_atom msg;
+ _buffer *buf = (_buffer *)sym->s_thing;
+ // b_msr reflects buffer sample rate... is this what we want?
+ // Max bug: adding small value 0.001 to get right sample count
+ float ms = fr/buf->b_msr+0.001;
+
+ SetFloat(msg,ms);
+ ::typedmess((object *)buf,gensym("size"),1,&msg);
+
+ Update();
+
+ if(tmp) {
+ // copy data back
+ BlockMoveData(tmp,data,sizeof(t_sample)*sz);
+ delete[] tmp;
+ }
+#endif
+}
+
+
+#ifdef PD
+void flext::buffer::SetRefrIntv(float intv)
+{
+ interval = intv;
+ if(interval == 0 && ticking) {
+ clock_unset(tick);
+ ticking = false;
+ }
+}
+#else
+void flext::buffer::SetRefrIntv(float) {}
+#endif
+
+
+void flext::buffer::Dirty(bool force)
+{
+ if(sym) {
+#ifdef PD
+ if((!ticking) && (interval || force)) {
+ ticking = true;
+ cb_tick(this); // immediately redraw
+ }
+ else {
+ if(force) clock_delay(tick,0);
+ isdirty = true;
+ }
+#elif defined(MAXMSP)
+ if(sym->s_thing) {
+ _buffer *p = (_buffer *)sym->s_thing;
+
+ if(NOGOOD(p)) {
+ post("buffer: buffer object '%s' no good",sym->s_name);
+ }
+ else {
+ p->b_modtime = gettime();
+ }
+ }
+ else {
+ error("buffer: symbol '%s' not defined",sym->s_name);
+ }
+#endif
+ }
+}
+
+#ifdef PD
+void flext::buffer::cb_tick(buffer *b)
+{
+ if(b->arr) garray_redraw(b->arr);
+#ifdef _DEBUG
+ else error("buffer: array is NULL");
+#endif
+
+ if(b->isdirty && b->interval) {
+ b->isdirty = false;
+ b->ticking = true;
+ clock_delay(b->tick,b->interval);
+ }
+ else
+ b->ticking = false;
+}
+#endif
+