diff options
author | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2003-08-16 08:08:13 +0000 |
---|---|---|
committer | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2003-08-16 08:08:13 +0000 |
commit | 4f2dd2a9a7b197bd7646a0578bb754a78e75a642 (patch) | |
tree | ec6a917ef3f37a1c6630cc9196dc27b44c51777d | |
parent | e76b94b778c2350ce2945f8e876d96f4395b857e (diff) |
added files straight from Yves' sources
svn path=/trunk/externals/unauthorized/; revision=852
-rw-r--r-- | cooled~/CHANGES.LOG | 24 | ||||
-rw-r--r-- | cooled~/INSTALL | 15 | ||||
-rw-r--r-- | cooled~/README | 23 | ||||
-rw-r--r-- | cooled~/cooled~.c | 1382 | ||||
-rw-r--r-- | cooled~/cooled~.tk | 87 | ||||
-rw-r--r-- | cooled~/help-cooled~.pd | 144 |
6 files changed, 1675 insertions, 0 deletions
diff --git a/cooled~/CHANGES.LOG b/cooled~/CHANGES.LOG new file mode 100644 index 0000000..4e490a3 --- /dev/null +++ b/cooled~/CHANGES.LOG @@ -0,0 +1,24 @@ +0.11 + prevent crashes during reallocation +0.10 + recopy previous data when resizing +0.9 + selection made more precise + loop moving/resizing functions +0.8 + add an option to disable drawing in order to save CPU +0.7 + changed allocation policy +0.6 + output samples number when selecting [ start and stop ] + fix bugs in cut & paste & resize +0.5 + forbid data access while resizing ( source of crashes ) +0.4 + safer cut and paste code +0.3 + added "stereo" message to map mono to stereo +0.2 + pre-allocate all buffers : i think it can avoid some crashes +0.1 + first implementation diff --git a/cooled~/INSTALL b/cooled~/INSTALL new file mode 100644 index 0000000..411a1c3 --- /dev/null +++ b/cooled~/INSTALL @@ -0,0 +1,15 @@ +untar in /my/pd/dir/externs + +cd /my/pd/dir/externs/cooled~ + +make clean + +make + +make install + +open help-cooled~.pd + +Thanx for getting here. +Yves/ +comments and bugs @ ydegoyon@free.fr diff --git a/cooled~/README b/cooled~/README new file mode 100644 index 0000000..d35d1b9 --- /dev/null +++ b/cooled~/README @@ -0,0 +1,23 @@ +*****************************************************************************
+Version 0.1
+copyleft 2002 by Yves Degoyon
+tarballs and updates available @ http://ydegoyon.free.fr
+
+cooled : a micro sound editor
+
+This object displays a sound, lets you play a part of it
+and do some cut and paste operations.
+
+To install cooled~, follow the steps from INSTALL
+
+This software is published under GPL terms.
+
+This is software with ABSOLUTELY NO WARRANTY.
+Use it at your OWN RISK. It's possible to damage e.g. hardware or your hearing
+due to a bug or for other reasons.
+We do not warrant that the program is free of infringement of any third-party
+patents.
+
+*****************************************************************************
+
+
diff --git a/cooled~/cooled~.c b/cooled~/cooled~.c new file mode 100644 index 0000000..38c5a1a --- /dev/null +++ b/cooled~/cooled~.c @@ -0,0 +1,1382 @@ +/*------------------------ cooled~ -------------------------------------------- */ +/* */ +/* cooled~ : display sound, play parts and modify it with cut and paste */ +/* constructor : cooled~ | cooled~ <size> <width> <height> */ +/* */ +/* Copyleft Yves Degoyon ( ydegoyon@free.fr ) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* "I am the fly in the ointment" -- Wire + 154 */ +/* Komet -- Instrumentals */ +/* ---------------------------------------------------------------------------- */ + + + +#include <sys/types.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <malloc.h> +#include <ctype.h> +#include <pthread.h> +#ifdef UNIX +#include <unistd.h> +#endif +#ifdef NT +#define M_PI 3.14159265358979323846 +#endif +#include <math.h> + +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" +#include "t_tk.h" + +static int guidebug=0; +static int ignorevisible=1; // ignore visible test + // because this seems to lead to bad refresh + // wait for a fix + +#define SYS_VGUI2(a,b) if (guidebug) \ + post(a,b);\ + sys_vgui(a,b) + +#define SYS_VGUI3(a,b,c) if (guidebug) \ + post(a,b,c);\ + sys_vgui(a,b,c) + +#define SYS_VGUI4(a,b,c,d) if (guidebug) \ + post(a,b,c,d);\ + sys_vgui(a,b,c,d) + +#define SYS_VGUI5(a,b,c,d,e) if (guidebug) \ + post(a,b,c,d,e);\ + sys_vgui(a,b,c,d,e) + +#define SYS_VGUI6(a,b,c,d,e,f) if (guidebug) \ + post(a,b,c,d,e,f);\ + sys_vgui(a,b,c,d,e,f) + +#define SYS_VGUI7(a,b,c,d,e,f,g) if (guidebug) \ + post(a,b,c,d,e,f,g );\ + sys_vgui(a,b,c,d,e,f,g) + +#define SYS_VGUI8(a,b,c,d,e,f,g,h) if (guidebug) \ + post(a,b,c,d,e,f,g,h );\ + sys_vgui(a,b,c,d,e,f,g,h) + +#define SYS_VGUI9(a,b,c,d,e,f,g,h,i) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i );\ + sys_vgui(a,b,c,d,e,f,g,h,i) + +#define SYS_VGUI10(a,b,c,d,e,f,g,h,i,j) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j );\ + sys_vgui(a,b,c,d,e,f,g,h,i,j) + +#define SYS_VGUI11(a,b,c,d,e,f,g,h,i,j,k) if (guidebug) \ + post(a,b,c,d,e,f,g,h,i,j,k );\ + sys_vgui(a,b,c,d,e,f,g,h,i,j,k) + +#define THREAD_SLEEP_TIME 10000 // 10000 us = 10 ms +#define COOLED_BGCOLOR "#000000" +#define COOLED_FGCOLOR "#34E112" +#define COOLED_FRCOLOR "#FFFFFF" + +#define COOLED_DEFAULT_SIZE 1024 +#define COOLED_DEFAULT_WIDTH 400 +#define COOLED_DEFAULT_HEIGHT 200 + +static char *cooled_version = "cooled~: version 0.11, written by Yves Degoyon (ydegoyon@free.fr)"; + +static t_class *cooled_class; +t_widgetbehavior cooled_widgetbehavior; + +typedef struct _cooled +{ + t_object x_obj; + + t_int x_size; /* size of the stored sound */ + t_float x_readpos; /* data's playing position */ + t_int x_writepos; /* data's recording position */ + t_float x_readstart; /* data's starting position for reading */ + t_float x_readend; /* data's ending position for reading */ + t_int x_play; /* playing on/off flag */ + t_float x_readspeed; /* speed increment */ + t_float x_record; /* flag to start recording process */ + t_float x_allocate; /* flag to indicate pending allocation */ + t_float x_empty; /* flag to indicate it's a brand new sound */ + t_float *x_rdata; /* table containing right channel samples */ + t_float *x_ldata; /* table containing leftt channel samples */ + t_outlet *x_end; /* outlet for end of restitution */ + t_outlet *x_recend; /* outlet for end of recording */ + t_outlet *x_sampstart; /* outlet for sample number [ start ] when selecting */ + t_outlet *x_sampend; /* outlet for sample number [ end ] when selecting */ + t_float *x_rsemp; /* temporary sample buffer ( right ) */ + t_float *x_lsemp; /* temporary sample buffer ( left ) */ + char* x_gifdata; /* buffer to store graphic data */ + char* x_guicommand; /* buffer to store gui command */ + t_int x_draw; /* drawing option */ + + /* graphical data block */ + t_int x_width; /* graphical width */ + t_int x_height; /* graphical height */ + t_int x_selected; /* flag to remember if we are seleted or not */ + t_int x_erase; /* flag used when an erase is needed */ + t_int x_redraw; /* flag used when drawing is needed */ + t_glist *x_glist; /* keep graphic context for various operations */ + t_int x_zoom; /* zoom factor */ + pthread_t x_updatechild; /* thread id for the update child */ + t_int x_updatestart; /* starting position for update */ + t_int x_updateend; /* ending position for update */ + t_int x_xpos; /* stuck x position */ + t_int x_ypos; /* stuck y position */ + t_int x_shifted; /* remember shift state from last click */ + t_int x_alted; /* remember alt state from last click */ + t_int x_xdraw; /* x drawing position */ + t_int x_edraw; /* end of drawing */ + + t_float x_f; /* float needed for signal input */ + +} t_cooled; + +/* ------------------------ drawing functions ---------------------------- */ + +static void cooled_update_block(t_cooled *x, t_glist *glist, t_int bnumber) +{ + t_int hi, i=0; + t_float fspectrum=0.0; + t_int phase=0; + char color[8]; + + memset( x->x_gifdata, 0x0, x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + + // update cooled~ + for ( hi=x->x_height-1; hi>=0; hi-- ) + { + if ( ( hi == x->x_height/4) || ( hi == 3*x->x_height/4) ) + { + sprintf( color, "%s ", COOLED_FGCOLOR ); + } + else if ( hi == x->x_height/2) + { + sprintf( color, "%s ", COOLED_FRCOLOR ); + } + else + { + sprintf( color, "%s ", COOLED_BGCOLOR ); + } + for ( i=0; i<x->x_zoom; i++ ) + { + strncpy( x->x_gifdata+(hi*x->x_zoom+i)*8, color, 8 ); + } + } + + // set all points + { + t_int fsamp = ( bnumber * x->x_size ) / x->x_width; + t_int lsamp = ( ( bnumber+1) * x->x_size ) / x->x_width; + t_int si; + + // post ( "cooled~ : updating samples [%d,%d]", fsamp, lsamp ); + + for ( si=fsamp;si<lsamp; si++ ) + { + // calculate right channel index + { + t_int rind = 3*x->x_height/4 + ( *(x->x_rdata+si) * (x->x_height/4) ) - 1; + + if ( rind > x->x_height - 1 ) rind = x->x_height - 1; + if ( rind < x->x_height/2 ) rind = x->x_height/2; + + sprintf( color, "%s ", COOLED_FGCOLOR ); + for ( i=0; i<x->x_zoom; i++ ) + { + strncpy( x->x_gifdata+(rind*x->x_zoom+i)*8, color, 8 ); + } + } + + // calculate left channel index + { + t_int lind = x->x_height/4 + ( *(x->x_ldata+si) * (x->x_height/4) ) - 1; + + if ( lind > x->x_height/2 - 1 ) lind = x->x_height/2 - 1; + if ( lind < 0 ) lind = 0; + + sprintf( color, "%s ", COOLED_FGCOLOR ); + for ( i=0; i<x->x_zoom; i++ ) + { + strncpy( x->x_gifdata+(lind*x->x_zoom+i)*8, color, 8 ); + } + } + } + } + + for ( i=0; i<x->x_zoom; i++ ) + { + sprintf( x->x_guicommand, "COOLEDIMAGE%x put {%s} -to %d 0\n", x, x->x_gifdata, (bnumber*x->x_zoom)+i ); + if ( glist_isvisible( x->x_glist ) ) + sys_gui( x->x_guicommand ); + } + +} + +static void cooled_erase_block(t_cooled *x, t_glist *glist, t_int sample ) +{ + t_canvas *canvas=glist_getcanvas(glist); + t_int hi; + t_float fspectrum=0.0; + char fillColor[ 16 ]; + + for ( hi=0; hi<x->x_height; hi++) + { + { + int i; + + for ( i=0; i<x->x_zoom; i++ ) + { + strcpy( x->x_gifdata+i*sizeof("#FFFFFF "), strcat( COOLED_BGCOLOR, " ") ); + } + if ( glist_isvisible( x->x_glist ) ) + SYS_VGUI5("COOLEDIMAGE%x put {%s} -to %d %d\n", x, x->x_gifdata, + sample*x->x_zoom, (x->x_height-hi)*x->x_zoom ); + } + } +} + +static void *cooled_do_update_part(void *tdata) +{ + t_cooled *x = (t_cooled*) tdata; + t_int si; + t_int nbpoints = 0; + t_float percentage = 0, opercentage = 0; + + // loose synchro + usleep( THREAD_SLEEP_TIME ); + + // check bounds + if ( x->x_updateend > x->x_size-1 ) x->x_updateend = x->x_size-1; + if ( x->x_updatestart < 0 ) x->x_updatestart = 0; + + post("cooled~ : ok, let's go [updating %d, %d]", x->x_updatestart, x->x_updateend ); + + if ( x->x_erase ) + { + for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) + { + cooled_erase_block(x, x->x_glist, si); + nbpoints++; + percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); + if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) + { + // post( "cooled~ : erase part : %d %% completed", (int)percentage ); + opercentage = percentage; + } + } + } + + percentage = opercentage = nbpoints = 0; + + if ( x->x_redraw ) + { + for ( si=x->x_updatestart; si<=x->x_updateend; si++ ) + { + cooled_update_block(x, x->x_glist, si); + nbpoints++; + percentage = (nbpoints*100/(x->x_updateend-x->x_updatestart+1)); + if ( (percentage == (int) percentage) && ((int)percentage%5 == 0) && ( percentage != opercentage ) ) + { + // post( "cooled~ : update part : %d %% completed", (int)percentage ); + opercentage = percentage; + } + } + } + + if ( glist_isvisible( x->x_glist ) ) + { + SYS_VGUI3( ".x%x.c delete rectangle %xCLIPZONE\n", + glist_getcanvas( x->x_glist ), x); + if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) + { + SYS_VGUI7( ".x%x.c create rectangle %d %d %d %d -outline #FF0000 -tags %xCLIPZONE -width 2\n", + glist_getcanvas( x->x_glist ), x->x_xpos+(int)(x->x_readstart*(x->x_width)/100 ), + x->x_ypos, x->x_xpos+(int)(x->x_readend*(x->x_width)/100 ), + x->x_ypos+x->x_height*x->x_zoom, x ); + } + // set borders in black + SYS_VGUI3(".x%x.c itemconfigure %xCOOLED -outline #000000\n", glist_getcanvas(x->x_glist), x); + } + + post("cooled~ : child thread %d ended", (int)x->x_updatechild ); + x->x_updatechild = 0; + return NULL; +} + +static void cooled_update_part(t_cooled *x, t_glist *glist, t_int bstart, t_int bend, + t_int erase, t_int redraw, t_int keepframe) +{ + pthread_attr_t update_child_attr; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + if ( x->x_updatechild != 0 ) + { + // post( "cooled~ : error : no update is possible for now" ); + return; + } + x->x_updatestart = bstart; + x->x_updateend = bend; + if ( !keepframe ) + { + x->x_erase = 0; + } + else + { + x->x_erase = erase; + } + x->x_redraw = redraw; + // recreate the square if needed + if ( glist_isvisible( x->x_glist ) ) + { + if ( ( bstart == 0 ) && ( bend == x->x_width-1 ) && !keepframe ) + { + SYS_VGUI3(".x%x.c delete %xCOOLEDL\n", glist_getcanvas(glist), x ); + SYS_VGUI3(".x%x.c delete %xCOOLEDR\n", glist_getcanvas(glist), x ); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xCOOLEDR\n", + canvas, x->x_xpos, x->x_ypos, + x->x_xpos + x->x_width*x->x_zoom, + x->x_ypos + x->x_height/2*x->x_zoom, + x); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xCOOLEDL\n", + canvas, x->x_xpos, + x->x_ypos + x->x_height/2*x->x_zoom, + x->x_xpos + x->x_width*x->x_zoom, + x->x_ypos + x->x_height*x->x_zoom, + x); + SYS_VGUI2("image delete COOLEDIMAGE%x\n", x ); + SYS_VGUI3(".x%x.c delete ICOOLEDIMAGE%x\n", glist_getcanvas(glist), x ); + SYS_VGUI4("image create photo COOLEDIMAGE%x -format gif -width %d -height %d\n", + x, x->x_width*x->x_zoom, x->x_height*x->x_zoom ); + SYS_VGUI2("COOLEDIMAGE%x blank\n", x ); + SYS_VGUI6(".x%x.c create image %d %d -image COOLEDIMAGE%x -tags ICOOLEDIMAGE%x\n", + glist_getcanvas( x->x_glist ), + x->x_xpos+(x->x_width*x->x_zoom)/2, + x->x_ypos+(x->x_height*x->x_zoom)/2, x, x ); + canvas_fixlinesfor( glist_getcanvas(x->x_glist), (t_text*)x ); + } + // set borders in red + SYS_VGUI3(".x%x.c itemconfigure %xCOOLED -outline #FF0000\n", glist_getcanvas(glist), x); + } + + // launch update thread + if ( pthread_attr_init( &update_child_attr ) < 0 ) { + post( "cooled~ : could not launch update thread" ); + perror( "pthread_attr_init" ); + return; + } + if ( pthread_attr_setdetachstate( &update_child_attr, PTHREAD_CREATE_DETACHED ) < 0 ) { + post( "cooled~ : could not launch update thread" ); + perror( "pthread_attr_setdetachstate" ); + return; + } + if ( pthread_create( &x->x_updatechild, &update_child_attr, cooled_do_update_part, x ) < 0 ) { + post( "cooled~ : could not launch update thread" ); + perror( "pthread_create" ); + return; + } + else + { + // post( "cooled~ : drawing thread %d launched", (int)x->x_updatechild ); + } +} + +static void cooled_draw_new(t_cooled *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if ( x->x_xpos == -1 ) + { + x->x_xpos=x->x_obj.te_xpix; + x->x_ypos=x->x_obj.te_ypix; + x->x_xdraw=x->x_obj.te_xpix; + } + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xCOOLEDR\n", + canvas, x->x_xpos, x->x_ypos, + x->x_xpos + x->x_width*x->x_zoom, + x->x_ypos + x->x_height/2*x->x_zoom, + x); + SYS_VGUI7(".x%x.c create rectangle %d %d %d %d -fill #FFFFFF -tags %xCOOLEDL\n", + canvas, x->x_xpos, + x->x_ypos + x->x_height/2*x->x_zoom, + x->x_xpos + x->x_width*x->x_zoom, + x->x_ypos + x->x_height*x->x_zoom, + x); + SYS_VGUI4("image create photo COOLEDIMAGE%x -format gif -width %d -height %d\n", + x, x->x_width*x->x_zoom, x->x_height*x->x_zoom ); + SYS_VGUI2("COOLEDIMAGE%x blank\n", x ); + SYS_VGUI6(".x%x.c create image %d %d -image COOLEDIMAGE%x -tags ICOOLEDIMAGE%x\n", + glist_getcanvas( x->x_glist ), + x->x_xpos+(x->x_width*x->x_zoom)/2, + x->x_ypos+(x->x_height*x->x_zoom)/2, x, x ); + if ( x->x_draw) cooled_update_part(x, x->x_glist, 0, x->x_width-1, 0, 1, 0); + canvas_fixlinesfor( canvas, (t_text*)x ); +} + +static void cooled_draw_delete(t_cooled *x, t_glist *glist) +{ + if ( glist_isvisible( glist ) ) + { + SYS_VGUI3( ".x%x.c delete %xCAPTURE\n", glist_getcanvas( glist ), x ); + if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) + { + SYS_VGUI3( ".x%x.c delete rectangle %xCLIPZONE\n", glist_getcanvas( glist ), x); + } + SYS_VGUI3( ".x%x.c delete line %xINSERTHERE\n", glist_getcanvas( glist ), x); + SYS_VGUI3(".x%x.c delete %xCOOLEDR\n", glist_getcanvas( glist ), x ); + SYS_VGUI3(".x%x.c delete %xCOOLEDL\n", glist_getcanvas( glist ), x ); + SYS_VGUI3(".x%x.c delete ICOOLEDIMAGE%x\n", glist_getcanvas( glist ), x ); + SYS_VGUI2("image delete COOLEDIMAGE%x\n", x ); + } +} + +static void cooled_draw_move(t_cooled *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if ( glist_isvisible( x->x_glist ) ) + { + SYS_VGUI7(".x%x.c coords %xCOOLEDR %d %d %d %d\n", + canvas, x, + x->x_xpos, x->x_ypos, + x->x_xpos + x->x_width*x->x_zoom, + x->x_ypos + x->x_height/2*x->x_zoom); + SYS_VGUI7(".x%x.c coords %xCOOLEDL %d %d %d %d\n", + canvas, x, + x->x_xpos, + x->x_ypos + x->x_height/2*x->x_zoom, + x->x_xpos + x->x_width*x->x_zoom, + x->x_ypos + x->x_height*x->x_zoom ); + if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) + { + SYS_VGUI7(".x%x.c coords %xCLIPZONE %d %d %d %d\n", + canvas, x, + x->x_xpos+(int)(x->x_readstart*(x->x_width)/100*x->x_zoom ), + x->x_ypos, + x->x_xpos+(int)(x->x_readend*(x->x_width)/100*x->x_zoom ), + x->x_ypos+x->x_height*x->x_zoom ); + } + SYS_VGUI7(".x%x.c coords %xINSERTHERE %d %d %d %d\n", + canvas, x, + x->x_xdraw, + x->x_ypos, + x->x_xdraw, + x->x_ypos+x->x_height*x->x_zoom ); + SYS_VGUI5(".x%x.c coords ICOOLEDIMAGE%x %d %d\n", + canvas, x, + x->x_xpos+((x->x_width*x->x_zoom)/2), + (x->x_ypos+((x->x_height*x->x_zoom)/2)) ); + canvas_fixlinesfor( canvas, (t_text*)x ); + } +} + +static void cooled_draw_select(t_cooled* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if ( glist_isvisible( x->x_glist ) ) + { + if(x->x_selected) + { + /* sets the item in blue */ + SYS_VGUI3(".x%x.c itemconfigure %xCOOLEDR -outline #0000FF\n", canvas, x); + SYS_VGUI3(".x%x.c itemconfigure %xCOOLEDL -outline #0000FF\n", canvas, x); + } + else + { + SYS_VGUI3(".x%x.c itemconfigure %xCOOLEDR -outline #000000\n", canvas, x); + SYS_VGUI3(".x%x.c itemconfigure %xCOOLEDL -outline #000000\n", canvas, x); + } + } +} + +/* ------------------------ widget callbacks ----------------------------- */ + + + /* setting the starting point for reading ( in percent ) */ +static void cooled_readstart(t_cooled *x, t_floatarg fstart) +{ + t_float startpoint = fstart; + + if (startpoint < 0) startpoint = 0; + if (startpoint > 100) startpoint = 100; + x->x_readstart = startpoint; + // set readspeed sign + if ( ( x->x_readstart > x->x_readend ) && ( x->x_readspeed > 0 ) ) x->x_readspeed = -x->x_readspeed; + if ( ( x->x_readstart < x->x_readend ) && ( x->x_readspeed < 0 ) ) x->x_readspeed = -x->x_readspeed; + if ( glist_isvisible( x->x_glist ) ) + { + SYS_VGUI3( ".x%x.c delete rectangle %xCLIPZONE\n", + glist_getcanvas( x->x_glist ), x); + if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) + { + SYS_VGUI7( ".x%x.c create rectangle %d %d %d %d -outline #FF0000 -tags %xCLIPZONE -width 2\n", + glist_getcanvas( x->x_glist ), x->x_xpos+(int)(x->x_readstart*x->x_width*x->x_zoom/100 ), + x->x_ypos, x->x_xpos+(int)(x->x_readend*x->x_width*x->x_zoom/100 ), + x->x_ypos+x->x_height*x->x_zoom, x ); + } + } + outlet_float( x->x_sampstart, (x->x_readstart*x->x_size)/100 ); +} + + /* setting the ending point for reading ( in percent ) */ +static void cooled_readend(t_cooled *x, t_floatarg fend) +{ + t_float endpoint = fend; + + if (endpoint < 0) endpoint = 0; + if (endpoint > 100) endpoint = 100; + x->x_readend = endpoint; + // set readspeed sign + if ( ( x->x_readstart > x->x_readend ) && ( x->x_readspeed > 0 ) ) x->x_readspeed = -x->x_readspeed; + if ( ( x->x_readstart < x->x_readend ) && ( x->x_readspeed < 0 ) ) x->x_readspeed = -x->x_readspeed; + if ( glist_isvisible( x->x_glist ) ) + { + SYS_VGUI3( ".x%x.c delete rectangle %xCLIPZONE\n", + glist_getcanvas( x->x_glist ), x); + if ( ( x->x_readstart != 0 ) || ( x->x_readend != 100 ) ) + { + SYS_VGUI7( ".x%x.c create rectangle %d %d %d %d -outline #FF0000 -tags %xCLIPZONE -width 2\n", + glist_getcanvas( x->x_glist ), + x->x_xpos+(int)(x->x_readstart*x->x_width*x->x_zoom/100 ), + x->x_ypos, x->x_xpos+(int)(x->x_readend*x->x_width*x->x_zoom/100 ), + x->x_ypos+x->x_height*x->x_zoom, x ); + } + } + outlet_float( x->x_sampend, (x->x_readend*x->x_size)/100 ); +} + +static void cooled_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_cooled* x = (t_cooled*)z; + + *xp1 = x->x_xpos; + *yp1 = x->x_ypos; + *xp2 = x->x_xpos+x->x_width*x->x_zoom; + *yp2 = x->x_ypos+x->x_height*x->x_zoom+1; +} + +static void cooled_save(t_gobj *z, t_binbuf *b) +{ + t_cooled *x = (t_cooled *)z; + + binbuf_addv(b, "ssiisiiii", gensym("#X"),gensym("obj"), + (t_int)x->x_xpos, (t_int)x->x_ypos, + gensym("cooled~"), x->x_size, x->x_width, x->x_height, x->x_draw ); + binbuf_addv(b, ";"); +} + +static void cooled_select(t_gobj *z, t_glist *glist, int selected) +{ + t_cooled *x = (t_cooled *)z; + + x->x_selected = selected; + cooled_draw_select( x, glist ); +} + +static void cooled_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_cooled *x = (t_cooled *)z; + t_rtext *y; + + if (vis) + { + cooled_draw_new( x, glist ); + } + else + { + // erase all points + cooled_draw_delete( x, glist ); + } +} + +static void cooled_delete(t_gobj *z, t_glist *glist) +{ + canvas_deletelinesfor( glist_getcanvas(glist), (t_text *)z); +} + +static void cooled_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_cooled *x = (t_cooled *)z; + int xold = x->x_xpos; + int yold = x->x_ypos; + + x->x_xpos += dx; + x->x_ypos += dy; + + if ( ( x->x_xpos != xold ) || ( x->x_ypos != yold ) ) + { + cooled_draw_move( x, glist ); + } + +} + +static void cooled_motion(t_cooled *x, t_floatarg dx, t_floatarg dy) +{ + // post( "cooled_motion @ [%d,%d] dx=%f dy=%f alt=%d", x->x_xdraw, x->x_ydraw, dx, dy, x->x_alted ); + if ( dx != 0 ) + { + cooled_readstart( x, ((t_float)( x->x_xdraw - x->x_xpos ) * 100 )/ (t_float)( x->x_width * x->x_zoom ) ); + x->x_edraw += dx; + cooled_readend( x, ((t_float)( x->x_edraw - x->x_xpos ) * 100 )/ (t_float)( x->x_width * x->x_zoom ) ); + } +} + + /* erase data form readstart to readend */ +static void cooled_erase( t_cooled *x ) +{ + t_int startsamp, endsamp, si; + t_int lreadstart = x->x_readstart, lreadend = x->x_readend; + + if (x->x_allocate) { + post( "cooled~ : error : cannot erase while re-allocation" ); + return; + } + // post( "cooled~ : erase" ); + if ( lreadstart <= lreadend ) + { + startsamp = (lreadstart*x->x_size)/100; + endsamp = (lreadend*x->x_size)/100; + } + else + { + startsamp = (lreadend*x->x_size)/100; + endsamp = (lreadstart*x->x_size)/100; + } + + for ( si=startsamp; si<=endsamp; si++ ) + { + *(x->x_rdata+si) = 0.; + *(x->x_ldata+si) = 0.; + } + if ( x->x_draw ) cooled_update_part(x, x->x_glist, startsamp*x->x_width/x->x_size, endsamp*(x->x_width-1)/x->x_size, 0, 1, 1); +} + /* paste data form readstart to readend */ +static void cooled_paste( t_cooled *x ) +{ + t_int startsamp, endsamp, si, inssamp, hlimit, csize; + t_int lreadstart = x->x_readstart, lreadend = x->x_readend; + + if (x->x_allocate) { + post( "cooled~ : error : cannot paste while re-allocation" ); + return; + } + if ( lreadstart <= lreadend ) + { + startsamp = (lreadstart*x->x_size)/100; + endsamp = (lreadend*x->x_size)/100; + } + else + { + startsamp = (lreadend*x->x_size)/100; + endsamp = (lreadstart*x->x_size)/100; + } + + // insert data at insertion point + inssamp = ( x->x_xdraw - x->x_xpos) * x->x_size / ( x->x_width * x->x_zoom ); + // post( "cooled~ : replace [%d,%d] to %d", startsamp, endsamp, inssamp ); + csize=endsamp-startsamp; + for ( si=0; si<=csize; si++ ) + { + if ( ( si + inssamp >= x->x_size ) || ( startsamp + si >= x->x_size ) ) break; + *(x->x_rsemp+si) = *(x->x_rdata+startsamp+si); + *(x->x_lsemp+si) = *(x->x_ldata+startsamp+si); + } + hlimit = si; + for ( si=0 ; si<=hlimit; si++ ) + { + *(x->x_rdata+inssamp+si) += *(x->x_rsemp+si); + *(x->x_ldata+inssamp+si) += *(x->x_lsemp+si); + } + + // post( "cooled~ : updating [%d,%d]", inssamp*x->x_width/x->x_size, (inssamp+hlimit)*x->x_width/x->x_size ); + if ( x->x_draw ) cooled_update_part(x, x->x_glist, inssamp*x->x_width/x->x_size, (inssamp+hlimit)*(x->x_width-1)/x->x_size, 0, 1, 1); +} + /* replace data form readstart to readend */ +static void cooled_replace( t_cooled *x ) +{ + t_int startsamp, endsamp, si, inssamp, hlimit, csize; + t_int lreadstart = x->x_readstart, lreadend = x->x_readend; + + if (x->x_allocate) { + post( "cooled~ : error : cannot replace while re-allocation" ); + return; + } + if ( lreadstart <= lreadend ) + { + startsamp = (lreadstart*x->x_size)/100; + endsamp = (lreadend*x->x_size)/100; + } + else + { + startsamp = (lreadend*x->x_size)/100; + endsamp = (lreadstart*x->x_size)/100; + } + + // insert data at insertion point + inssamp = ( x->x_xdraw - x->x_xpos) * x->x_size / ( x->x_width * x->x_zoom ); + // post( "cooled~ : replace [%d,%d] to %d", startsamp, endsamp, inssamp ); + csize=endsamp-startsamp; + for ( si=0; si<=csize; si++ ) + { + if ( ( si + inssamp >= x->x_size ) || ( startsamp + si >= x->x_size ) ) break; + *(x->x_rsemp+si) = *(x->x_rdata+startsamp+si); + *(x->x_lsemp+si) = *(x->x_ldata+startsamp+si); + } + hlimit = si; + for ( si=0 ; si<=hlimit; si++ ) + { + *(x->x_rdata+inssamp+si) = *(x->x_rsemp+si); + *(x->x_ldata+inssamp+si) = *(x->x_lsemp+si); + } + + // post( "cooled~ : updating [%d,%d]", inssamp*x->x_width/x->x_size, (inssamp+hlimit)*x->x_width/x->x_size ); + if ( x->x_draw ) cooled_update_part(x, x->x_glist, inssamp*x->x_width/x->x_size, (inssamp+hlimit)*(x->x_width-1)/x->x_size, 0, 1, 1); + +} + + /* call editor's property dialog */ +static void cooled_properties(t_gobj *z, t_glist *owner) +{ + char buf[800]; + t_cooled *x=(t_cooled *)z; + + sprintf(buf, "pdtk_cooled_dialog %%s %d %d %d\n", + x->x_width, x->x_height, x->x_draw); + // post("cooled_properties : %s", buf ); + gfxstub_new(&x->x_obj.ob_pd, x, buf); +} + + /* handle properties change */ +static void cooled_dialog(t_cooled *x, t_symbol *s, int argc, t_atom *argv) +{ + if ( !x ) { + post( "cooled~ : error :tried to set properties on an unexisting object" ); + } + if ( argc != 3 ) + { + post( "cooled~ : error in the number of arguments ( %d instead of 3 )", argc ); + return; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || argv[2].a_type != A_FLOAT ) { + post( "cooled~ : wrong arguments" ); + return; + } + cooled_draw_delete(x, x->x_glist); + if ( x->x_gifdata != NULL ) { + freebytes(x->x_gifdata, x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_gifdata = NULL; + } + if ( x->x_guicommand != NULL ) { + freebytes(x->x_guicommand, 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_guicommand = NULL; + } + x->x_width = (int)argv[0].a_w.w_float; + if ( x->x_width < 0 ) x->x_width = 100; + x->x_height = (int)argv[1].a_w.w_float; + if ( x->x_height < 0 ) x->x_height = 100; + x->x_draw = (int)argv[2].a_w.w_float; + if ( !(x->x_gifdata = ( char* ) getbytes( x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return; + } else { + post( "cooled~ : allocated %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + } + if ( !(x->x_guicommand = ( char* ) getbytes( 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return; + } else { + post( "cooled~ : allocated %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + } + cooled_draw_new(x, x->x_glist); +} + + /* handle clicks */ +static int cooled_click(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_cooled* x = (t_cooled *)z; + t_int pipos; + + // post( "cooled_click : x=%d y=%d doit=%d alt=%d, shift=%d", xpix, ypix, doit, alt, shift ); + if ( doit ) + { + if ( shift && alt ) + { + cooled_paste(x); + } + else if ( shift ) + { + cooled_replace(x); + } + else if ( alt ) + { + cooled_erase(x); + } + else + { + x->x_xdraw = xpix; + x->x_edraw = xpix; + x->x_shifted = shift; + x->x_alted = alt; + // activate motion callback + glist_grab( glist, &x->x_obj.te_g, (t_glistmotionfn)cooled_motion, + 0, xpix, ypix ); + + // draw insertion line + if ( glist_isvisible( x->x_glist ) ) + { + SYS_VGUI3( ".x%x.c delete line %xINSERTHERE\n", + glist_getcanvas( x->x_glist ), x); + SYS_VGUI7( ".x%x.c create line %d %d %d %d -fill #00FFFF -tags %xINSERTHERE -width 2\n", + glist_getcanvas( x->x_glist ), x->x_xdraw, + x->x_ypos, x->x_xdraw, + x->x_ypos+x->x_height*x->x_zoom, x ); + } + + } + + } + else + { + // nothing + } + return (1); + +} + + /* clean up */ +static void cooled_free(t_cooled *x) +{ + if ( x->x_rdata != NULL ) { + freebytes(x->x_rdata, x->x_size*sizeof(float) ); + post( "Freed %d bytes", x->x_size*sizeof(float) ); + x->x_rdata = NULL; + } + if ( x->x_ldata != NULL ) { + freebytes(x->x_ldata, x->x_size*sizeof(float) ); + post( "Freed %d bytes", x->x_size*sizeof(float) ); + x->x_ldata = NULL; + } + if ( x->x_rsemp != NULL ) { + freebytes(x->x_rsemp, x->x_size*sizeof(float) ); + post( "Freed %d bytes", x->x_size*sizeof(float) ); + x->x_rsemp = NULL; + } + if ( x->x_lsemp != NULL ) { + freebytes(x->x_lsemp, x->x_size*sizeof(float) ); + post( "Freed %d bytes", x->x_size*sizeof(float) ); + x->x_lsemp = NULL; + } + if ( x->x_gifdata != NULL ) { + freebytes(x->x_gifdata, x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_gifdata = NULL; + } + if ( x->x_guicommand != NULL ) { + freebytes(x->x_guicommand, 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_guicommand = NULL; + } +} + + /* allocate tables for storing sound and temporary copy */ +static t_int cooled_allocate(t_cooled *x) +{ + t_int fi; + + if ( !(x->x_rdata = getbytes( x->x_size*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", x->x_size*sizeof(float) ); + } + if ( !(x->x_ldata = getbytes( x->x_size*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", x->x_size*sizeof(float) ); + } + if ( !(x->x_rsemp = getbytes( x->x_size*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", x->x_size*sizeof(float) ); + } + if ( !(x->x_lsemp = getbytes( x->x_size*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", x->x_size*sizeof(float) ); + } + if ( !(x->x_gifdata = ( char* ) getbytes( x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + } + if ( !(x->x_guicommand = ( char* ) getbytes( 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + } + + return 0; +} + + /* allocate tables for storing sound and temporary copy */ +static t_int cooled_reallocate(t_cooled *x, t_int ioldsize, t_int inewsize) +{ + t_int fi, csize; + t_float *prdata=x->x_rdata, *pldata=x->x_ldata, *prsemp=x->x_rsemp, *plsemp=x->x_lsemp; + + if ( !(x->x_rdata = getbytes( inewsize*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", inewsize*sizeof(float) ); + } + if ( !(x->x_ldata = getbytes( inewsize*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", inewsize*sizeof(float) ); + } + if ( !(x->x_rsemp = getbytes( inewsize*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", inewsize*sizeof(float) ); + } + if ( !(x->x_lsemp = getbytes( inewsize*sizeof(float) ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return -1; + } else { + post( "cooled~ : allocated %d bytes", inewsize*sizeof(float) ); + } + + if ( ioldsize <= inewsize ) + { + csize = ioldsize; + } + else + { + csize = inewsize; + } + memcpy( x->x_rdata, prdata, csize*sizeof(float) ); + memcpy( x->x_ldata, pldata, csize*sizeof(float) ); + memcpy( x->x_rsemp, prsemp, csize*sizeof(float) ); + memcpy( x->x_lsemp, plsemp, csize*sizeof(float) ); + + if ( prdata != NULL ) { + freebytes(prdata, ioldsize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*sizeof(float) ); + } + if ( pldata != NULL ) { + freebytes(pldata, ioldsize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*sizeof(float) ); + } + if ( prsemp != NULL ) { + freebytes(prsemp, ioldsize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*sizeof(float) ); + } + if ( plsemp != NULL ) { + freebytes(plsemp, ioldsize*sizeof(float) ); + post( "Freed %d bytes", ioldsize*sizeof(float) ); + } + + return 0; +} + + /* records and playback the sound */ +static t_int *cooled_perform(t_int *w) +{ + t_float *lin = (t_float *)(w[1]); + t_float *rin = (t_float *)(w[2]); + t_float *rout = (t_float *)(w[3]); + t_float *lout = (t_float *)(w[4]); + t_int is; + t_int n = (int)(w[5]); /* number of samples */ + t_int startsamp, endsamp; + t_cooled *x = (t_cooled *)(w[6]); + t_int lreadstart = x->x_readstart, lreadend = x->x_readend; + + if ( lreadstart <= lreadend ) + { + startsamp = (lreadstart*x->x_size)/100; + endsamp = (lreadend*x->x_size)/100; + } + else + { + startsamp = (lreadend*x->x_size)/100; + endsamp = (lreadstart*x->x_size)/100; + } + + while (n--) + { + // eventually records input + if ( x->x_record ) { + *(x->x_ldata+x->x_writepos)=*(lin); + *(x->x_rdata+x->x_writepos)=*(rin); + x->x_writepos++; + if ( x->x_writepos >= x->x_size ) { + x->x_record=0; + x->x_writepos=0; + if ( x->x_draw ) cooled_update_part(x, x->x_glist, 0, x->x_width-1, 0, 1, 0); + outlet_bang(x->x_recend); + if ( x->x_empty ) x->x_empty = 0; + // post( "cooled~ : stopped recording" ); + } + } + // set outputs + *rout = 0.0; + *lout = 0.0; + if ( x->x_play) { + is=0; + *lout = *(x->x_ldata+(int)x->x_readpos); + *rout = *(x->x_rdata+(int)x->x_readpos); + x->x_readpos+=x->x_readspeed; + // post( "xreadpos : %f (added %f) %d", x->x_readpos, x->x_readspeed, x->x_readend ); + if ( ( x->x_readspeed >= 0 ) && ( x->x_readpos >= endsamp ) ) { + x->x_play=0; + x->x_readpos=(float)(startsamp); + // post( "cooled~ : stopped playing (readpos=%d)", x->x_readpos ); + outlet_bang(x->x_end); + } + if ( ( x->x_readspeed < 0 ) && ( x->x_readpos <= startsamp ) ) { + x->x_play=0; + x->x_readpos = (float)(endsamp); + // post( "cooled~ : stopped playing (readpos=%d)", x->x_readpos ); + outlet_bang(x->x_end); + } + } + rout++;lout++; + rin++;lin++; + } + // post( "cooled~ : read : %f:%d : write: %d:%d", x->x_readpos, x->x_play, x->x_writepos, x->x_record ); + return (w+7); +} + +static void cooled_dsp(t_cooled *x, t_signal **sp) +{ + dsp_add(cooled_perform, 6, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n, x); +} + + /* record the cooled */ +static void cooled_record(t_cooled *x) +{ + if (x->x_allocate) { + post( "cooled~ : error : cannot record while re-allocation" ); + return; + } + x->x_record=1; + x->x_writepos=0; + post( "cooled~ : recording on" ); +} + + /* map to stereo */ +static void cooled_stereo(t_cooled *x) +{ + t_int si; + + if (x->x_allocate) { + post( "cooled~ : error : cannot map to stereo while re-allocation" ); + return; + } + for ( si=0; si<x->x_size; si++ ) + { + *(x->x_rdata+si) = *(x->x_ldata+si); + } + if ( x->x_draw ) cooled_update_part(x, x->x_glist, 0, x->x_width-1, !x->x_empty, !x->x_empty, 0); +} + + /* play the cooled */ +static void cooled_play(t_cooled *x) +{ + x->x_play=1; + // post( "cooled~ : playing on" ); +} + + /* sets the reading speed */ +static void cooled_readspeed(t_cooled *x, t_floatarg freadspeed) +{ + x->x_readspeed=freadspeed; +} + + /* resize cooled */ +static void cooled_resize(t_cooled *x, t_floatarg fnewsize ) +{ + if (fnewsize <= 0) { + post( "cooled~ : error : wrong size" ); + return; + } + if (x->x_allocate) { + post( "cooled~ : error : cannot resize while re-allocation" ); + return; + } + if (x->x_updatechild > 0) { + post( "cooled~ : can't resize now, an update is pending." ); + return; + } + post( "cooled~ : reallocating tables" ); + x->x_allocate = 1; + x->x_play = 0; + x->x_record = 0; + cooled_readstart( x, 0); + cooled_readend( x, 100); + cooled_reallocate(x, x->x_size, fnewsize); + x->x_size = fnewsize; + x->x_empty = 1; + if ( x->x_readstart <= x->x_readend ) + { + x->x_readpos = (x->x_readstart*x->x_size)/100; + } + else + { + x->x_readpos = (x->x_readend*x->x_size)/100; + } + // erase all points, as data is zero no drawing is needed + if ( x->x_draw) cooled_update_part(x, x->x_glist, 0, x->x_width-1, 0, !x->x_empty, 1); + x->x_allocate = 0; +} + + /* set zoom factor */ +static void cooled_zoom(t_cooled *x, t_floatarg fzoom ) +{ + if (fzoom < 1) { + post( "cooled~ : error : wrong zoom factor" ); + return; + } + if (x->x_allocate) { + post( "cooled~ : error : cannot zoom while re-allocation" ); + return; + } + if ( x->x_gifdata != NULL ) { + freebytes(x->x_gifdata, x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_gifdata = NULL; + } + if ( x->x_guicommand != NULL ) { + freebytes(x->x_guicommand, 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + post( "Freed %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + x->x_guicommand = NULL; + } + x->x_zoom = (int)fzoom; + if ( !(x->x_gifdata = ( char* ) getbytes( x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return; + } else { + post( "cooled~ : allocated %d bytes", x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + } + if ( !(x->x_guicommand = ( char* ) getbytes( 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ) ) ) { + post( "cooled~ : error : could not allocate buffers" ); + return; + } else { + post( "cooled~ : allocated %d bytes", 128+x->x_height*x->x_zoom*sizeof("#FFFFFF ") ); + } + if ( x->x_draw) cooled_update_part(x, x->x_glist, 0, x->x_width-1, !x->x_empty, !x->x_empty, 0); + canvas_fixlinesfor( glist_getcanvas( x->x_glist ), (t_text*)x ); +} + + /* modify the loop positions */ +static void cooled_loop(t_cooled *x, t_symbol *soperator ) +{ + char *operator = soperator->s_name; + t_int ci; + t_float fvalue, freadstart = x->x_readstart, freadend = x->x_readend; + + if ( (soperator->s_name[0] != '*') && + (soperator->s_name[0] != '/') && + (soperator->s_name[0] != '>') && + (soperator->s_name[0] != '<') ) { + post( "cooled~ : error : wrong operator argument : should be *|/|>|<" ); + return; + } + for ( ci=1; ci<(int)strlen( soperator->s_name ); ci++ ) + { + if ( !(isdigit(soperator->s_name[ci])||(soperator->s_name[ci]=='.')) ) { + post( "cooled~ : error : wrong operation value : %s : should be in a float format", soperator->s_name+1 ); + return; + } + } + if ( sscanf( soperator->s_name+1, "%f", &fvalue ) != 1 ) { + post( "cooled~ : error : can't get operation value" ); + return; + } + switch( soperator->s_name[0] ) + { + case '*' : + freadend = x->x_readstart + fvalue*(x->x_readend-x->x_readstart); + break; + + case '/' : + if ( fvalue != 0 ) { freadend = x->x_readstart + (x->x_readend-x->x_readstart)/fvalue; }; + break; + + case '>' : + freadstart = x->x_readstart + fvalue*(x->x_readend-x->x_readstart); + freadend = x->x_readend + fvalue*(x->x_readend-x->x_readstart); + break; + + case '<' : + freadstart = x->x_readstart - fvalue*(x->x_readend-x->x_readstart); + freadend = x->x_readend - fvalue*(x->x_readend-x->x_readstart); + break; + } + if ( freadstart < 0.0 ) freadstart = 0.0; + if ( freadend < 0.0 ) freadend = 0.0; + if ( freadstart > 100.0 ) freadstart = 100.0; + if ( freadend > 100.0 ) freadend = 100.0; + cooled_readstart( x, freadstart); + cooled_readend( x, freadend); +} + + /* refresh data */ +static void cooled_refresh(t_cooled *x) +{ + if (x->x_allocate) { + post( "cooled~ : error : cannot refresh while re-allocation" ); + return; + } + if ( x->x_draw ) cooled_update_part(x, x->x_glist, 0, x->x_width-1, 0, 1, 1); +} + +static void *cooled_new(t_symbol *s, int argc, t_atom *argv) +{ + t_cooled *x = (t_cooled *)pd_new(cooled_class); + outlet_new(&x->x_obj, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_recend = outlet_new(&x->x_obj, &s_bang ); + x->x_end = outlet_new(&x->x_obj, &s_bang ); + x->x_sampstart = outlet_new(&x->x_obj, &s_float ); + x->x_sampend = outlet_new(&x->x_obj, &s_float ); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readstart")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("readend")); + + if ( argc != 0 ) + { + if ( argc < 3 ) + { + post( "audience~ : error in the number of arguments ( %d )", argc ); + return NULL; + } + if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT || + argv[2].a_type != A_FLOAT ) { + post( "audience~ : wrong arguments" ); + return NULL; + } + x->x_size = (int)argv[0].a_w.w_float; + if ( x->x_size < 1 ) x->x_size = 1; + x->x_width = (int)argv[1].a_w.w_float; + if ( x->x_width < 10 ) x->x_width = 10; + x->x_height = (int)argv[2].a_w.w_float; + if ( x->x_height < 10 ) x->x_height = 10; + if ( argc == 3 ) + x->x_draw = 1; + else + x->x_draw = (int)argv[3].a_w.w_float; + } + else + { + x->x_size = COOLED_DEFAULT_SIZE; + x->x_width = COOLED_DEFAULT_WIDTH; + x->x_height = COOLED_DEFAULT_HEIGHT; + x->x_draw = 1; + } + + // activate graphical callbacks + class_setwidget(cooled_class, &cooled_widgetbehavior); + + x->x_play = 0; + x->x_readspeed = 1.; + x->x_record = 0; + x->x_allocate = 0; + x->x_readpos = 0.; + x->x_writepos = 0; + x->x_rdata = NULL; + x->x_ldata = NULL; + x->x_empty = 1; + x->x_xpos = -1; + x->x_ypos = -1; + /* graphic data */ + x->x_selected = 0; + x->x_zoom = 1; + x->x_updatechild = 0; + x->x_glist = (t_glist*)canvas_getcurrent(); + // post( "cooled~ : new : readend=%d", x->x_readend ); + cooled_readstart( x, 0); + cooled_readend( x, 100); + + if ( cooled_allocate(x) <0 ) { + return NULL; + } else { + return(x); + } + +} + +void cooled_tilde_setup(void) +{ +#include "cooled~.tk2c" + post(cooled_version); + cooled_class = class_new(gensym("cooled~"), (t_newmethod)cooled_new, (t_method)cooled_free, + sizeof(t_cooled), 0, A_GIMME, 0); + class_sethelpsymbol( cooled_class, gensym("help-cooled~.pd") ); + + // set callbacks + cooled_widgetbehavior.w_getrectfn = cooled_getrect; + cooled_widgetbehavior.w_displacefn = cooled_displace; + cooled_widgetbehavior.w_selectfn = cooled_select; + cooled_widgetbehavior.w_activatefn = NULL; + cooled_widgetbehavior.w_deletefn = cooled_delete; + cooled_widgetbehavior.w_visfn = cooled_vis; + cooled_widgetbehavior.w_clickfn = cooled_click; + cooled_widgetbehavior.w_propertiesfn = cooled_properties; + cooled_widgetbehavior.w_savefn = cooled_save; + + CLASS_MAINSIGNALIN( cooled_class, t_cooled, x_f ); + class_addmethod(cooled_class, (t_method)cooled_dsp, gensym("dsp"), A_NULL); + class_addmethod(cooled_class, (t_method)cooled_record, gensym("record"), A_NULL); + class_addmethod(cooled_class, (t_method)cooled_resize, gensym("resize"), A_FLOAT, A_NULL); + class_addmethod(cooled_class, (t_method)cooled_zoom, gensym("zoom"), A_FLOAT, A_NULL); + class_addmethod(cooled_class, (t_method)cooled_play, gensym("play"), A_NULL); + class_addmethod(cooled_class, (t_method)cooled_refresh, gensym("refresh"), A_NULL); + class_addmethod(cooled_class, (t_method)cooled_readstart, gensym("readstart"), A_FLOAT, A_NULL); + class_addmethod(cooled_class, (t_method)cooled_stereo, gensym("stereo"), A_NULL); + class_addmethod(cooled_class, (t_method)cooled_readend, gensym("readend"), A_FLOAT, A_NULL); + class_addmethod(cooled_class, (t_method)cooled_readspeed, gensym("readspeed"), A_FLOAT, A_NULL); + class_addmethod(cooled_class, (t_method)cooled_loop, gensym("loop"), A_SYMBOL, A_NULL); + class_addmethod(cooled_class, (t_method)cooled_dialog, gensym("dialog"), A_GIMME, 0); +} diff --git a/cooled~/cooled~.tk b/cooled~/cooled~.tk new file mode 100644 index 0000000..ebd7699 --- /dev/null +++ b/cooled~/cooled~.tk @@ -0,0 +1,87 @@ +############ cooled procedures -- ydegoyon@free.fr ######### + +proc cooled_apply {id} { +# strip "." from the TK id to make a variable name suffix + set vid [string trimleft $id .] +# for each variable, make a local variable to hold its name... + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_draw [concat graph_draw_$vid] + global $var_graph_draw + + set cmd [concat $id dialog \ + [eval concat $$var_graph_width] \ + [eval concat $$var_graph_height] \ + [eval concat $$var_graph_draw] \ + \;] + #puts stderr $cmd + pd $cmd +} + +proc cooled_cancel {id} { + set cmd [concat $id cancel \;] + #puts stderr $cmd + pd $cmd +} + +proc cooled_ok {id} { + cooled_apply $id + cooled_cancel $id +} + +proc pdtk_cooled_dialog {id width height draw} { + set vid [string trimleft $id .] + set var_graph_width [concat graph_width_$vid] + global $var_graph_width + set var_graph_height [concat graph_height_$vid] + global $var_graph_height + set var_graph_draw [concat graph_draw_$vid] + global $var_graph_draw + + set $var_graph_width $width + set $var_graph_height $height + set $var_graph_draw $draw + + toplevel $id + wm title $id {cooled} + wm protocol $id WM_DELETE_WINDOW [concat cooled_cancel $id] + + label $id.label -text {EDITOR PROPERTIES} + pack $id.label -side top + + frame $id.buttonframe + pack $id.buttonframe -side bottom -fill x -pady 2m + button $id.buttonframe.cancel -text {Cancel}\ + -command "cooled_cancel $id" + button $id.buttonframe.apply -text {Apply}\ + -command "cooled_apply $id" + button $id.buttonframe.ok -text {OK}\ + -command "cooled_ok $id" + pack $id.buttonframe.cancel -side left -expand 1 + pack $id.buttonframe.apply -side left -expand 1 + pack $id.buttonframe.ok -side left -expand 1 + + frame $id.1rangef + pack $id.1rangef -side top + label $id.1rangef.lwidth -text "Width :" + entry $id.1rangef.width -textvariable $var_graph_width -width 7 + pack $id.1rangef.lwidth $id.1rangef.width -side left + + frame $id.2rangef + pack $id.2rangef -side top + label $id.2rangef.lheight -text "Height :" + entry $id.2rangef.height -textvariable $var_graph_height -width 7 + pack $id.2rangef.lheight $id.2rangef.height -side left + + checkbutton $id.draw -text {Draw Sample} -variable $var_graph_draw \ + -anchor w + pack $id.draw -side top + + bind $id.1rangef.width <KeyPress-Return> [concat cooled_ok $id] + bind $id.2rangef.height <KeyPress-Return> [concat cooled_ok $id] + focus $id.1rangef.width +} + +############ cooled procedures END -- ydegoyon@free.fr ######### diff --git a/cooled~/help-cooled~.pd b/cooled~/help-cooled~.pd new file mode 100644 index 0000000..19a6d67 --- /dev/null +++ b/cooled~/help-cooled~.pd @@ -0,0 +1,144 @@ +#N canvas 29 25 986 675 10; +#X msg 30 628 \; pd dsp 1; +#X msg 104 629 \; pd dsp 0; +#X obj 122 567 dac~; +#X obj 29 599 loadbang; +#X obj 115 531 *~ 1; +#X obj 156 530 *~ 1; +#X floatatom 204 531 5 0 0; +#X text 557 36 Cooled~ : a micro sound editor; +#X text 555 48 it supports selection and cut/paste modifications; +#X text 686 645 Comments and bugs @ ydegoyon@noos.fr; +#X obj 277 506 print recend; +#X obj 362 540 print playend; +#X msg 28 31 bang; +#X obj 27 53 openpanel; +#X msg 62 226 resize \$1; +#X obj 27 73 t s b; +#X obj 76 73 float \$0; +#X text 27 6 Step 1 : Load a sound file; +#X obj 27 96 route float; +#X text 95 25 ( a small one ); +#X msg 208 218 record; +#X msg 315 10 bang; +#X text 355 9 Step 2 : Record the sound; +#X obj 63 163 pack s s s; +#X obj 19 117 makefilename %d-right-channel; +#X obj 23 140 makefilename %d-left-channel; +#X obj 180 611 table \$0-right-channel; +#X obj 181 636 table \$0-left-channel; +#X msg 62 184 read -resize \$1 \$2 \$3; +#X obj 289 41 tabplay~ \$0-right-channel; +#X obj 288 67 tabplay~ \$0-left-channel; +#X msg 18 298 refresh; +#X msg 23 467 play; +#X msg 22 445 bang; +#X text 11 494 Step 3 : Play it back; +#X obj 146 249 cooled~ 81839 400 200 1; +#X obj 397 157 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 0 1; +#X obj 397 179 hsl 128 15 0 100 0 0 empty empty empty 20 8 0 8 -262144 +-1 -1 12700 1; +#X text 400 131 Reading positions; +#X text 539 153 Start; +#X text 538 179 End; +#X msg 301 106 readspeed \$1; +#X floatatom 438 106 5 0 0; +#X obj 397 106 / 100; +#X msg 489 106 100; +#X text 521 105 Reading speed; +#X msg 18 328 zoom 2; +#X msg 19 357 zoom 1; +#X msg 361 179 100; +#X obj 297 179 loadbang; +#X obj 600 187 random 100; +#X msg 660 137 bang; +#X obj 681 186 random 100; +#X text 641 114 Random play; +#X obj 602 164 metro 1000; +#X text 601 507 Mouse modifications :; +#X text 601 522 <alt> <cli<k> : erase selection; +#X text 601 537 <shift> <cli<k> : replace by selection; +#X text 418 612 The red area is the selection; +#X text 419 596 point for paste and replace; +#X text 420 581 Note : the blue line is the insertion; +#X msg 361 155 0; +#X text 600 552 <shift> <alt> <cli<k> : add selection [ noize ]; +#X text 706 429 (invoke with <right mouse>Properties ); +#X text 709 419 You can set the following properties :; +#X text 733 460 * Width : graphical x size; +#X text 733 476 * Height : graphical y size; +#X msg 704 138 stop; +#X text 686 631 Part of unauthorized PD; +#X obj 683 163 metro 1000; +#X msg 23 391 stereo; +#X text 19 413 Map to stereo; +#X floatatom 448 481 8 0 0; +#X floatatom 521 481 8 0 0; +#X text 447 502 start; +#X text 510 503 end; +#X text 469 518 Selection; +#X msg 460 219 loop *2; +#X msg 401 218 loop /2; +#X msg 342 218 loop <1; +#X obj 62 206 soundfiler; +#X msg 282 218 loop >1; +#X text 520 220 loop operators ( accept any float value ); +#X connect 3 0 0 0; +#X connect 4 0 2 0; +#X connect 5 0 2 1; +#X connect 6 0 4 1; +#X connect 6 0 5 1; +#X connect 12 0 13 0; +#X connect 13 0 15 0; +#X connect 14 0 35 0; +#X connect 15 0 23 0; +#X connect 15 1 16 0; +#X connect 16 0 18 0; +#X connect 18 0 24 0; +#X connect 18 0 25 0; +#X connect 20 0 35 0; +#X connect 21 0 20 0; +#X connect 21 0 29 0; +#X connect 21 0 30 0; +#X connect 23 0 28 0; +#X connect 24 0 23 1; +#X connect 25 0 23 2; +#X connect 28 0 80 0; +#X connect 29 0 35 0; +#X connect 30 0 35 1; +#X connect 31 0 35 0; +#X connect 32 0 35 0; +#X connect 33 0 32 0; +#X connect 35 0 4 0; +#X connect 35 1 5 0; +#X connect 35 2 10 0; +#X connect 35 3 11 0; +#X connect 35 3 32 0; +#X connect 35 4 72 0; +#X connect 35 5 73 0; +#X connect 36 0 35 2; +#X connect 37 0 35 3; +#X connect 41 0 35 0; +#X connect 42 0 43 0; +#X connect 43 0 41 0; +#X connect 44 0 42 0; +#X connect 46 0 35 0; +#X connect 47 0 35 0; +#X connect 48 0 37 0; +#X connect 49 0 48 0; +#X connect 50 0 35 2; +#X connect 51 0 54 0; +#X connect 51 0 69 0; +#X connect 52 0 35 3; +#X connect 54 0 50 0; +#X connect 61 0 36 0; +#X connect 67 0 54 0; +#X connect 67 0 69 0; +#X connect 69 0 52 0; +#X connect 70 0 35 0; +#X connect 77 0 35 0; +#X connect 78 0 35 0; +#X connect 79 0 35 0; +#X connect 80 0 14 0; +#X connect 81 0 35 0; |