summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/g_array.c
diff options
context:
space:
mode:
authorPeter D'Hoye <peter.dhoye@gmail.com>2009-05-24 21:28:16 +0000
committerPeter D'Hoye <peter.dhoye@gmail.com>2009-05-24 21:28:16 +0000
commit526b5580dabbfed7cfe5439dc3a90ec727f563c2 (patch)
tree22b1af92348785daad16714ee5e2b633017e0e48 /apps/plugins/pdbox/PDa/src/g_array.c
parent4f2dfcc01b260d946044ef2b6af5fe36cb772c8d (diff)
downloadrockbox-526b5580dabbfed7cfe5439dc3a90ec727f563c2.tar.gz
rockbox-526b5580dabbfed7cfe5439dc3a90ec727f563c2.zip
Cut the files in half and it might work better (note to self: check your tree is really clean before patching)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21070 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/g_array.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/g_array.c1368
1 files changed, 0 insertions, 1368 deletions
diff --git a/apps/plugins/pdbox/PDa/src/g_array.c b/apps/plugins/pdbox/PDa/src/g_array.c
index f259ac8dcb..3e2225637a 100644
--- a/apps/plugins/pdbox/PDa/src/g_array.c
+++ b/apps/plugins/pdbox/PDa/src/g_array.c
@@ -1364,1371 +1364,3 @@ void g_array_setup(void)
1364 class_setsavefn(garray_class, garray_save); 1364 class_setsavefn(garray_class, garray_save);
1365} 1365}
1366 1366
1367
1368/* Copyright (c) 1997-1999 Miller Puckette.
1369* For information on usage and redistribution, and for a DISCLAIMER OF ALL
1370* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
1371
1372#include <stdlib.h>
1373#include <string.h>
1374#include <stdio.h> /* for read/write to files */
1375#include "m_pd.h"
1376#include "g_canvas.h"
1377#include <math.h>
1378
1379/* see also the "plot" object in g_scalar.c which deals with graphing
1380arrays which are fields in scalars. Someday we should unify the
1381two, but how? */
1382
1383 /* aux routine to bash leading '#' to '$' for dialogs in u_main.tk
1384 which can't send symbols starting with '$' (because the Pd message
1385 interpreter would change them!) */
1386
1387static t_symbol *sharptodollar(t_symbol *s)
1388{
1389 if (*s->s_name == '#')
1390 {
1391 char buf[MAXPDSTRING];
1392 strncpy(buf, s->s_name, MAXPDSTRING);
1393 buf[MAXPDSTRING-1] = 0;
1394 buf[0] = '$';
1395 return (gensym(buf));
1396 }
1397 else return (s);
1398}
1399
1400/* --------- "pure" arrays with scalars for elements. --------------- */
1401
1402/* Pure arrays have no a priori graphical capabilities.
1403They are instantiated by "garrays" below or can be elements of other
1404scalars (g_scalar.c); their graphical behavior is defined accordingly. */
1405
1406t_array *array_new(t_symbol *templatesym, t_gpointer *parent)
1407{
1408 t_array *x = (t_array *)getbytes(sizeof (*x));
1409 t_template *template;
1410 t_gpointer *gp;
1411 template = template_findbyname(templatesym);
1412 x->a_templatesym = templatesym;
1413 x->a_n = 1;
1414 x->a_elemsize = sizeof(t_word) * template->t_n;
1415 x->a_vec = (char *)getbytes(x->a_elemsize);
1416 /* note here we blithely copy a gpointer instead of "setting" a
1417 new one; this gpointer isn't accounted for and needn't be since
1418 we'll be deleted before the thing pointed to gets deleted anyway;
1419 see array_free. */
1420 x->a_gp = *parent;
1421 x->a_stub = gstub_new(0, x);
1422 word_init((t_word *)(x->a_vec), template, parent);
1423 return (x);
1424}
1425
1426void array_resize(t_array *x, t_template *template, int n)
1427{
1428 int elemsize, oldn;
1429 t_gpointer *gp;
1430
1431 if (n < 1)
1432 n = 1;
1433 oldn = x->a_n;
1434 elemsize = sizeof(t_word) * template->t_n;
1435
1436 x->a_vec = (char *)resizebytes(x->a_vec, oldn * elemsize,
1437 n * elemsize);
1438 x->a_n = n;
1439 if (n > oldn)
1440 {
1441 char *cp = x->a_vec + elemsize * oldn;
1442 int i = n - oldn;
1443 for (; i--; cp += elemsize)
1444 {
1445 t_word *wp = (t_word *)cp;
1446 word_init(wp, template, &x->a_gp);
1447 }
1448 }
1449}
1450
1451void word_free(t_word *wp, t_template *template);
1452
1453void array_free(t_array *x)
1454{
1455 int i;
1456 t_template *scalartemplate = template_findbyname(x->a_templatesym);
1457 /* we don't unset our gpointer here since it was never "set." */
1458 /* gpointer_unset(&x->a_gp); */
1459 gstub_cutoff(x->a_stub);
1460 for (i = 0; i < x->a_n; i++)
1461 {
1462 t_word *wp = (t_word *)(x->a_vec + x->a_elemsize * i);
1463 word_free(wp, scalartemplate);
1464 }
1465 freebytes(x->a_vec, x->a_elemsize * x->a_n);
1466 freebytes(x, sizeof *x);
1467}
1468
1469/* --------------------- graphical arrays (garrays) ------------------- */
1470
1471t_class *garray_class;
1472static int gcount = 0;
1473
1474struct _garray
1475{
1476 t_gobj x_gobj;
1477 t_glist *x_glist;
1478 t_array x_array; /* actual array; note only 4 fields used as below */
1479 t_symbol *x_name;
1480 t_symbol *x_realname; /* name with "$" expanded */
1481 t_float x_firstx; /* X value of first item */
1482 t_float x_xinc; /* X increment */
1483 char x_usedindsp; /* true if some DSP routine is using this */
1484 char x_saveit; /* true if we should save this with parent */
1485};
1486
1487 /* macros to get into the "array" structure */
1488#define x_n x_array.a_n
1489#define x_elemsize x_array.a_elemsize
1490#define x_vec x_array.a_vec
1491#define x_templatesym x_array.a_templatesym
1492
1493t_garray *graph_array(t_glist *gl, t_symbol *s, t_symbol *templatesym,
1494 t_floatarg f, t_floatarg saveit)
1495{
1496 int n = f, i;
1497 int zz, nwords;
1498 t_garray *x;
1499 t_pd *x2;
1500 t_template *template;
1501 char *str;
1502 if (s == &s_)
1503 {
1504 char buf[40];
1505 sprintf(buf, "array%d", ++gcount);
1506 s = gensym(buf);
1507 templatesym = &s_float;
1508 n = 100;
1509 }
1510 else if (!strncmp((str = s->s_name), "array", 5)
1511 && (zz = atoi(str + 5)) > gcount) gcount = zz;
1512 template = template_findbyname(templatesym);
1513 if (!template)
1514 {
1515 error("array: couldn't find template %s", templatesym->s_name);
1516 return (0);
1517 }
1518 nwords = template->t_n;
1519 for (i = 0; i < nwords; i++)
1520 {
1521 /* we can't have array or list elements yet because what scalar
1522 can act as their "parent"??? */
1523 if (template->t_vec[i].ds_type == DT_ARRAY
1524 || template->t_vec[i].ds_type == DT_LIST)
1525 {
1526 error("array: template %s can't have sublists or arrays",
1527 templatesym->s_name);
1528 return (0);
1529 }
1530 }
1531 x = (t_garray *)pd_new(garray_class);
1532
1533 if (n <= 0) n = 100;
1534 x->x_n = n;
1535 x->x_elemsize = nwords * sizeof(t_word);
1536 x->x_vec = getbytes(x->x_n * x->x_elemsize);
1537 memset(x->x_vec, 0, x->x_n * x->x_elemsize);
1538 /* LATER should check that malloc */
1539 x->x_name = s;
1540 x->x_realname = canvas_realizedollar(gl, s);
1541 pd_bind(&x->x_gobj.g_pd, x->x_realname);
1542 x->x_templatesym = templatesym;
1543 x->x_firstx = 0;
1544 x->x_xinc = 1; /* LATER make methods to set this... */
1545 glist_add(gl, &x->x_gobj);
1546 x->x_glist = gl;
1547 x->x_usedindsp = 0;
1548 x->x_saveit = (saveit != 0);
1549 if (x2 = pd_findbyclass(gensym("#A"), garray_class))
1550 pd_unbind(x2, gensym("#A"));
1551
1552 pd_bind(&x->x_gobj.g_pd, gensym("#A"));
1553
1554 return (x);
1555}
1556
1557 /* called from array menu item to create a new one */
1558void canvas_menuarray(t_glist *canvas)
1559{
1560 t_glist *x = (t_glist *)canvas;
1561 char cmdbuf[200];
1562 sprintf(cmdbuf, "pdtk_array_dialog %%s array%d 100 1 1\n",
1563 ++gcount);
1564 gfxstub_new(&x->gl_pd, x, cmdbuf);
1565}
1566
1567 /* called from graph_dialog to set properties */
1568void garray_properties(t_garray *x)
1569{
1570 char cmdbuf[200];
1571 gfxstub_deleteforkey(x);
1572 /* create dialog window. LATER fix this to escape '$'
1573 properly; right now we just detect a leading '$' and escape
1574 it. There should be a systematic way of doing this. */
1575 if (x->x_name->s_name[0] == '$')
1576 sprintf(cmdbuf, "pdtk_array_dialog %%s \\%s %d %d 0\n",
1577 x->x_name->s_name, x->x_n, x->x_saveit);
1578 else sprintf(cmdbuf, "pdtk_array_dialog %%s %s %d %d 0\n",
1579 x->x_name->s_name, x->x_n, x->x_saveit);
1580 gfxstub_new(&x->x_gobj.g_pd, x, cmdbuf);
1581}
1582
1583 /* this is called back from the dialog window to create a garray.
1584 The otherflag requests that we find an existing graph to put it in. */
1585void glist_arraydialog(t_glist *parent, t_symbol *name, t_floatarg size,
1586 t_floatarg saveit, t_floatarg otherflag)
1587{
1588 t_glist *gl;
1589 t_garray *a;
1590 if (size < 1)
1591 size = 1;
1592 if (otherflag == 0 || (!(gl = glist_findgraph(parent))))
1593 gl = glist_addglist(parent, &s_, 0, 1,
1594 (size > 1 ? size-1 : size), -1, 0, 0, 0, 0);
1595 a = graph_array(gl, sharptodollar(name), &s_float, size, saveit);
1596}
1597
1598 /* this is called from the properties dialog window for an existing array */
1599void garray_arraydialog(t_garray *x, t_symbol *name, t_floatarg fsize,
1600 t_floatarg saveit, t_floatarg deleteit)
1601{
1602 if (deleteit != 0)
1603 {
1604 glist_delete(x->x_glist, &x->x_gobj);
1605 }
1606 else
1607 {
1608 int size;
1609 t_symbol *argname = sharptodollar(name);
1610 if (argname != x->x_name)
1611 {
1612 x->x_name = argname;
1613 pd_unbind(&x->x_gobj.g_pd, x->x_realname);
1614 x->x_realname = canvas_realizedollar(x->x_glist, argname);
1615 pd_bind(&x->x_gobj.g_pd, x->x_realname);
1616 }
1617 size = fsize;
1618 if (size < 1)
1619 size = 1;
1620 if (size != x->x_n)
1621 garray_resize(x, size);
1622 garray_setsaveit(x, (saveit != 0));
1623 garray_redraw(x);
1624 }
1625}
1626
1627static void garray_free(t_garray *x)
1628{
1629 t_pd *x2;
1630 gfxstub_deleteforkey(x);
1631 pd_unbind(&x->x_gobj.g_pd, x->x_realname);
1632 /* LATER find a way to get #A unbound earlier (at end of load?) */
1633 while (x2 = pd_findbyclass(gensym("#A"), garray_class))
1634 pd_unbind(x2, gensym("#A"));
1635 freebytes(x->x_vec, x->x_n * x->x_elemsize);
1636}
1637
1638/* ------------- code used by both array and plot widget functions ---- */
1639
1640 /* routine to get screen coordinates of a point in an array */
1641void array_getcoordinate(t_glist *glist,
1642 char *elem, int xonset, int yonset, int wonset, int indx,
1643 float basex, float basey, float xinc,
1644 float *xp, float *yp, float *wp)
1645{
1646 float xval, yval, ypix, wpix;
1647 if (xonset >= 0)
1648 xval = fixtof(*(t_sample *)(elem + xonset));
1649 else xval = indx * xinc;
1650 if (yonset >= 0)
1651 yval = fixtof(*(t_sample *)(elem + yonset));
1652 else yval = 0;
1653 ypix = glist_ytopixels(glist, basey + yval);
1654 if (wonset >= 0)
1655 {
1656 /* found "w" field which controls linewidth. */
1657 float wval = *(float *)(elem + wonset);
1658 wpix = glist_ytopixels(glist, basey + yval + wval) - ypix;
1659 if (wpix < 0)
1660 wpix = -wpix;
1661 }
1662 else wpix = 1;
1663 *xp = glist_xtopixels(glist, basex + xval);
1664 *yp = ypix;
1665 *wp = wpix;
1666}
1667
1668static float array_motion_xcumulative;
1669static float array_motion_ycumulative;
1670static t_symbol *array_motion_xfield;
1671static t_symbol *array_motion_yfield;
1672static t_glist *array_motion_glist;
1673static t_gobj *array_motion_gobj;
1674static t_word *array_motion_wp;
1675static t_template *array_motion_template;
1676static int array_motion_npoints;
1677static int array_motion_elemsize;
1678static int array_motion_altkey;
1679static float array_motion_initx;
1680static float array_motion_xperpix;
1681static float array_motion_yperpix;
1682static int array_motion_lastx;
1683static int array_motion_fatten;
1684
1685 /* LATER protect against the template changing or the scalar disappearing
1686 probably by attaching a gpointer here ... */
1687
1688static void array_motion(void *z, t_floatarg dx, t_floatarg dy)
1689{
1690 array_motion_xcumulative += dx * array_motion_xperpix;
1691 array_motion_ycumulative += dy * array_motion_yperpix;
1692 if (*array_motion_xfield->s_name)
1693 {
1694 /* it's an x, y plot; can drag many points at once */
1695 int i;
1696 char *charword = (char *)array_motion_wp;
1697 for (i = 0; i < array_motion_npoints; i++)
1698 {
1699 t_word *thisword = (t_word *)(charword + i * array_motion_elemsize);
1700 if (*array_motion_xfield->s_name)
1701 {
1702 float xwas = template_getfloat(array_motion_template,
1703 array_motion_xfield, thisword, 1);
1704 template_setfloat(array_motion_template,
1705 array_motion_xfield, thisword, xwas + dx, 1);
1706 }
1707 if (*array_motion_yfield->s_name)
1708 {
1709 float ywas = template_getfloat(array_motion_template,
1710 array_motion_yfield, thisword, 1);
1711 if (array_motion_fatten)
1712 {
1713 if (i == 0)
1714 {
1715 float newy = ywas + dy * array_motion_yperpix;
1716 if (newy < 0)
1717 newy = 0;
1718 template_setfloat(array_motion_template,
1719 array_motion_yfield, thisword, newy, 1);
1720 }
1721 }
1722 else
1723 {
1724 template_setfloat(array_motion_template,
1725 array_motion_yfield, thisword,
1726 ywas + dy * array_motion_yperpix, 1);
1727 }
1728 }
1729 }
1730 }
1731 else
1732 {
1733 /* a y-only plot. */
1734 int thisx = array_motion_initx +
1735 array_motion_xcumulative, x2;
1736 int increment, i, nchange;
1737 char *charword = (char *)array_motion_wp;
1738 float newy = array_motion_ycumulative,
1739 oldy = template_getfloat(
1740 array_motion_template, array_motion_yfield,
1741 (t_word *)(charword + array_motion_elemsize * array_motion_lastx), 1);
1742 float ydiff = newy - oldy;
1743 if (thisx < 0) thisx = 0;
1744 else if (thisx >= array_motion_npoints)
1745 thisx = array_motion_npoints - 1;
1746 increment = (thisx > array_motion_lastx ? -1 : 1);
1747 nchange = 1 + increment * (array_motion_lastx - thisx);
1748
1749 for (i = 0, x2 = thisx; i < nchange; i++, x2 += increment)
1750 {
1751 template_setfloat(array_motion_template,
1752 array_motion_yfield,
1753 (t_word *)(charword + array_motion_elemsize * x2),
1754 newy, 1);
1755 if (nchange > 1)
1756 newy -= ydiff * (1./(nchange - 1));
1757 }
1758 array_motion_lastx = thisx;
1759 }
1760 glist_redrawitem(array_motion_glist, array_motion_gobj);
1761}
1762
1763int array_doclick(t_array *array, t_glist *glist, t_gobj *gobj,
1764 t_symbol *elemtemplatesym,
1765 float linewidth, float xloc, float xinc, float yloc,
1766 int xpix, int ypix, int shift, int alt, int dbl, int doit)
1767{
1768 t_canvas *elemtemplatecanvas;
1769 t_template *elemtemplate;
1770 int elemsize, yonset, wonset, xonset, i;
1771
1772 if (!array_getfields(elemtemplatesym, &elemtemplatecanvas,
1773 &elemtemplate, &elemsize, &xonset, &yonset, &wonset))
1774 {
1775 float best = 100;
1776 int incr;
1777 /* if it has more than 2000 points, just check 300 of them. */
1778 if (array->a_n < 2000)
1779 incr = 1;
1780 else incr = array->a_n / 300;
1781 for (i = 0; i < array->a_n; i += incr)
1782 {
1783 float pxpix, pypix, pwpix, dx, dy;
1784 array_getcoordinate(glist, (char *)(array->a_vec) + i * elemsize,
1785 xonset, yonset, wonset, i, xloc, yloc, xinc,
1786 &pxpix, &pypix, &pwpix);
1787 if (pwpix < 4)
1788 pwpix = 4;
1789 dx = pxpix - xpix;
1790 if (dx < 0) dx = -dx;
1791 if (dx > 8)
1792 continue;
1793 dy = pypix - ypix;
1794 if (dy < 0) dy = -dy;
1795 if (dx + dy < best)
1796 best = dx + dy;
1797 if (wonset >= 0)
1798 {
1799 dy = (pypix + pwpix) - ypix;
1800 if (dy < 0) dy = -dy;
1801 if (dx + dy < best)
1802 best = dx + dy;
1803 dy = (pypix - pwpix) - ypix;
1804 if (dy < 0) dy = -dy;
1805 if (dx + dy < best)
1806 best = dx + dy;
1807 }
1808 }
1809 if (best > 8)
1810 return (0);
1811 best += 0.001; /* add truncation error margin */
1812 for (i = 0; i < array->a_n; i += incr)
1813 {
1814 float pxpix, pypix, pwpix, dx, dy, dy2, dy3;
1815 array_getcoordinate(glist, (char *)(array->a_vec) + i * elemsize,
1816 xonset, yonset, wonset, i, xloc, yloc, xinc,
1817 &pxpix, &pypix, &pwpix);
1818 if (pwpix < 4)
1819 pwpix = 4;
1820 dx = pxpix - xpix;
1821 if (dx < 0) dx = -dx;
1822 dy = pypix - ypix;
1823 if (dy < 0) dy = -dy;
1824 if (wonset >= 0)
1825 {
1826 dy2 = (pypix + pwpix) - ypix;
1827 if (dy2 < 0) dy2 = -dy2;
1828 dy3 = (pypix - pwpix) - ypix;
1829 if (dy3 < 0) dy3 = -dy3;
1830 if (yonset <= 0)
1831 dy = 100;
1832 }
1833 else dy2 = dy3 = 100;
1834 if (dx + dy <= best || dx + dy2 <= best || dx + dy3 <= best)
1835 {
1836 if (dy < dy2 && dy < dy3)
1837 array_motion_fatten = 0;
1838 else if (dy2 < dy3)
1839 array_motion_fatten = -1;
1840 else array_motion_fatten = 1;
1841 if (doit)
1842 {
1843 char *elem = (char *)array->a_vec;
1844 array_motion_elemsize = elemsize;
1845 array_motion_glist = glist;
1846 array_motion_gobj = gobj;
1847 array_motion_template = elemtemplate;
1848 array_motion_xperpix = glist_dpixtodx(glist, 1);
1849 array_motion_yperpix = glist_dpixtody(glist, 1);
1850 if (alt && xpix < pxpix) /* delete a point */
1851 {
1852 if (array->a_n <= 1)
1853 return (0);
1854 memmove((char *)(array->a_vec) + elemsize * i,
1855 (char *)(array->a_vec) + elemsize * (i+1),
1856 (array->a_n - 1 - i) * elemsize);
1857 array_resize(array, elemtemplate, array->a_n - 1);
1858 glist_redrawitem(array_motion_glist, array_motion_gobj);
1859 return (0);
1860 }
1861 else if (alt)
1862 {
1863 /* add a point (after the clicked-on one) */
1864 array_resize(array, elemtemplate, array->a_n + 1);
1865 elem = (char *)array->a_vec;
1866 memmove(elem + elemsize * (i+1),
1867 elem + elemsize * i,
1868 (array->a_n - i - 1) * elemsize);
1869 i++;
1870 }
1871 if (xonset >= 0)
1872 {
1873 array_motion_xfield = gensym("x");
1874 array_motion_xcumulative =
1875 *(float *)((elem + elemsize * i) + xonset);
1876 array_motion_wp = (t_word *)(elem + i * elemsize);
1877 array_motion_npoints = array->a_n - i;
1878 }
1879 else
1880 {
1881 array_motion_xfield = &s_;
1882 array_motion_xcumulative = 0;
1883 array_motion_wp = (t_word *)elem;
1884 array_motion_npoints = array->a_n;
1885
1886 array_motion_initx = i;
1887 array_motion_lastx = i;
1888 array_motion_xperpix *= (xinc == 0 ? 1 : 1./xinc);
1889 }
1890 if (array_motion_fatten)
1891 {
1892 array_motion_yfield = gensym("w");
1893 array_motion_ycumulative =
1894 *(float *)((elem + elemsize * i) + wonset);
1895 array_motion_yperpix *= array_motion_fatten;
1896 }
1897 else if (yonset >= 0)
1898 {
1899 array_motion_yfield = gensym("y");
1900 array_motion_ycumulative =
1901 *(float *)((elem + elemsize * i) + yonset);
1902 }
1903 else
1904 {
1905 array_motion_yfield = &s_;
1906 array_motion_ycumulative = 0;
1907 }
1908 glist_grab(glist, 0, array_motion, 0, xpix, ypix);
1909 }
1910 if (alt)
1911 {
1912 if (xpix < pxpix)
1913 return (CURSOR_EDITMODE_DISCONNECT);
1914 else return (CURSOR_RUNMODE_ADDPOINT);
1915 }
1916 else return (array_motion_fatten ?
1917 CURSOR_RUNMODE_THICKEN : CURSOR_RUNMODE_CLICKME);
1918 }
1919 }
1920 }
1921 return (0);
1922}
1923
1924/* -------------------- widget behavior for garray ------------ */
1925
1926static void garray_getrect(t_gobj *z, t_glist *glist,
1927 int *xp1, int *yp1, int *xp2, int *yp2)
1928{
1929 t_garray *x = (t_garray *)z;
1930 float x1 = 0x7fffffff, y1 = 0x7fffffff, x2 = -0x7fffffff, y2 = -0x7fffffff;
1931 t_canvas *elemtemplatecanvas;
1932 t_template *elemtemplate;
1933 int elemsize, yonset, wonset, xonset, i;
1934
1935 if (!array_getfields(x->x_templatesym, &elemtemplatecanvas,
1936 &elemtemplate, &elemsize, &xonset, &yonset, &wonset))
1937 {
1938 int incr;
1939 /* if it has more than 2000 points, just check 300 of them. */
1940 if (x->x_array.a_n < 2000)
1941 incr = 1;
1942 else incr = x->x_array.a_n / 300;
1943 for (i = 0; i < x->x_array.a_n; i += incr)
1944 {
1945 float pxpix, pypix, pwpix, dx, dy;
1946 array_getcoordinate(glist, (char *)(x->x_array.a_vec) +
1947 i * elemsize,
1948 xonset, yonset, wonset, i, 0, 0, 1,
1949 &pxpix, &pypix, &pwpix);
1950 if (pwpix < 2)
1951 pwpix = 2;
1952 if (pxpix < x1)
1953 x1 = pxpix;
1954 if (pxpix > x2)
1955 x2 = pxpix;
1956 if (pypix - pwpix < y1)
1957 y1 = pypix - pwpix;
1958 if (pypix + pwpix > y2)
1959 y2 = pypix + pwpix;
1960 }
1961 }
1962 *xp1 = x1;
1963 *yp1 = y1;
1964 *xp2 = x2;
1965 *yp2 = y2;
1966}
1967
1968static void garray_displace(t_gobj *z, t_glist *glist, int dx, int dy)
1969{
1970 /* refuse */
1971}
1972
1973static void garray_select(t_gobj *z, t_glist *glist, int state)
1974{
1975 t_garray *x = (t_garray *)z;
1976 /* fill in later */
1977}
1978
1979static void garray_activate(t_gobj *z, t_glist *glist, int state)
1980{
1981}
1982
1983static void garray_delete(t_gobj *z, t_glist *glist)
1984{
1985 /* nothing to do */
1986}
1987
1988static void garray_vis(t_gobj *z, t_glist *glist, int vis)
1989{
1990 t_garray *x = (t_garray *)z;
1991 if (vis)
1992 {
1993 int i, xonset, yonset, type;
1994 t_symbol *arraytype;
1995 t_template *template = template_findbyname(x->x_templatesym);
1996 if (!template)
1997 return;
1998 if (!template_find_field(template, gensym("y"), &yonset, &type,
1999 &arraytype) || type != DT_FLOAT)
2000 {
2001 error("%s: needs floating-point 'y' field",
2002 x->x_templatesym->s_name);
2003 sys_vgui(".x%x.c create text 50 50 -text foo\
2004 -tags .x%x.a%x\n",
2005 glist_getcanvas(glist), glist_getcanvas(glist), x);
2006 }
2007 else if (!template_find_field(template, gensym("x"), &xonset, &type,
2008 &arraytype) || type != DT_FLOAT)
2009 {
2010 float firsty, xcum = x->x_firstx;
2011 int lastpixel = -1, ndrawn = 0;
2012 float yval = 0, xpix;
2013 int ixpix = 0;
2014 sys_vgui(".x%x.c create line \\\n", glist_getcanvas(glist));
2015 for (i = 0; i < x->x_n; i++)
2016 {
2017 yval = fixtof(*(t_sample *)(x->x_vec +
2018 template->t_n * i * sizeof (t_word) + yonset));
2019 xpix = glist_xtopixels(glist, xcum);
2020 ixpix = xpix + 0.5;
2021 if (ixpix != lastpixel)
2022 {
2023 sys_vgui("%d %f \\\n", ixpix,
2024 glist_ytopixels(glist, yval));
2025 ndrawn++;
2026 }
2027 lastpixel = ixpix;
2028 if (ndrawn >= 1000) break;
2029 xcum += x->x_xinc;
2030 }
2031 /* TK will complain if there aren't at least 2 points... */
2032 if (ndrawn == 0) sys_vgui("0 0 0 0 \\\n");
2033 else if (ndrawn == 1) sys_vgui("%d %f \\\n", ixpix,
2034 glist_ytopixels(glist, yval));
2035 sys_vgui("-tags .x%x.a%x\n", glist_getcanvas(glist), x);
2036 firsty = fixtof(*(t_sample *)(x->x_vec + yonset));
2037 sys_vgui(".x%x.c create text %f %f -text {%s} -anchor e\
2038 -font -*-courier-bold--normal--%d-* -tags .x%x.a%x\n",
2039 glist_getcanvas(glist),
2040 glist_xtopixels(glist, x->x_firstx) - 5.,
2041 glist_ytopixels(glist, firsty),
2042 x->x_name->s_name, glist_getfont(glist),
2043 glist_getcanvas(glist), x);
2044 }
2045 else
2046 {
2047 post("x, y arrays not yet supported");
2048 }
2049 }
2050 else
2051 {
2052 sys_vgui(".x%x.c delete .x%x.a%x\n",
2053 glist_getcanvas(glist), glist_getcanvas(glist), x);
2054 }
2055}
2056
2057static int garray_click(t_gobj *z, struct _glist *glist,
2058 int xpix, int ypix, int shift, int alt, int dbl, int doit)
2059{
2060 t_garray *x = (t_garray *)z;
2061 return (array_doclick(&x->x_array, glist, z, x->x_templatesym, 1, 0, 1, 0,
2062 xpix, ypix, shift, alt, dbl, doit));
2063}
2064
2065#define ARRAYWRITECHUNKSIZE 1000
2066
2067static void garray_save(t_gobj *z, t_binbuf *b)
2068{
2069 t_garray *x = (t_garray *)z;
2070 binbuf_addv(b, "sssisi;", gensym("#X"), gensym("array"),
2071 x->x_name, x->x_n, x->x_templatesym, x->x_saveit);
2072 fprintf(stderr,"array save\n");
2073 if (x->x_saveit)
2074 {
2075 int n = x->x_n, n2 = 0;
2076 if (x->x_templatesym != &s_float)
2077 {
2078 pd_error(x, "sorry, you can only save 'float' arrays now");
2079 return;
2080 }
2081 if (n > 200000)
2082 post("warning: I'm saving an array with %d points!\n", n);
2083 while (n2 < n)
2084 {
2085 int chunk = n - n2, i;
2086 if (chunk > ARRAYWRITECHUNKSIZE)
2087 chunk = ARRAYWRITECHUNKSIZE;
2088 binbuf_addv(b, "si", gensym("#A"), n2);
2089 for (i = 0; i < chunk; i++)
2090 binbuf_addv(b, "f", fixtof(((t_sample *)(x->x_vec))[n2+i]));
2091 binbuf_addv(b, ";");
2092 n2 += chunk;
2093 }
2094 }
2095}
2096
2097t_widgetbehavior garray_widgetbehavior =
2098{
2099 garray_getrect,
2100 garray_displace,
2101 garray_select,
2102 garray_activate,
2103 garray_delete,
2104 garray_vis,
2105 garray_click
2106};
2107
2108/* ----------------------- public functions -------------------- */
2109
2110void garray_usedindsp(t_garray *x)
2111{
2112 x->x_usedindsp = 1;
2113}
2114
2115void garray_redraw(t_garray *x)
2116{
2117 if (glist_isvisible(x->x_glist))
2118 {
2119 garray_vis(&x->x_gobj, x->x_glist, 0);
2120 garray_vis(&x->x_gobj, x->x_glist, 1);
2121 }
2122}
2123
2124 /* This functiopn gets the template of an array; if we can't figure
2125 out what template an array's elements belong to we're in grave trouble
2126 when it's time to free or resize it. */
2127t_template *garray_template(t_garray *x)
2128{
2129 t_template *template = template_findbyname(x->x_templatesym);
2130 if (!template)
2131 bug("garray_template");
2132 return (template);
2133}
2134
2135int garray_npoints(t_garray *x) /* get the length */
2136{
2137 return (x->x_n);
2138}
2139
2140char *garray_vec(t_garray *x) /* get the contents */
2141{
2142 return ((char *)(x->x_vec));
2143}
2144
2145 /* routine that checks if we're just an array of floats and if
2146 so returns the goods */
2147
2148int garray_getfloatarray(t_garray *x, int *size, t_sample **vec)
2149{
2150 t_template *template = garray_template(x);
2151 int yonset, type;
2152 t_symbol *arraytype;
2153 if (!template_find_field(template, gensym("y"), &yonset,
2154 &type, &arraytype) || type != DT_FLOAT)
2155 error("%s: needs floating-point 'y' field",
2156 x->x_templatesym->s_name);
2157 else if (template->t_n != 1)
2158 error("%s: has more than one field", x->x_templatesym->s_name);
2159 else
2160 {
2161 *size = garray_npoints(x);
2162 *vec = (t_sample *)garray_vec(x);
2163 return (1);
2164 }
2165 return (0);
2166}
2167
2168 /* get any floating-point field of any element of an array */
2169float garray_get(t_garray *x, t_symbol *s, t_int indx)
2170{
2171 t_template *template = garray_template(x);
2172 int yonset, type;
2173 t_symbol *arraytype;
2174 if (!template_find_field(template, gensym("y"), &yonset,
2175 &type, &arraytype) || type != DT_FLOAT)
2176 {
2177 error("%s: needs floating-point '%s' field", x->x_templatesym->s_name,
2178 s->s_name);
2179 return (0);
2180 }
2181 if (indx < 0) indx = 0;
2182 else if (indx >= x->x_n) indx = x->x_n - 1;
2183 return (*(float *)((x->x_vec + sizeof(t_word) * indx) + yonset));
2184}
2185
2186 /* set the "saveit" flag */
2187void garray_setsaveit(t_garray *x, int saveit)
2188{
2189 if (x->x_saveit && !saveit)
2190 post("warning: array %s: clearing save-in-patch flag",
2191 x->x_name->s_name);
2192 x->x_saveit = saveit;
2193}
2194
2195/*------------------- Pd messages ------------------------ */
2196static void garray_const(t_garray *x, t_floatarg g)
2197{
2198 t_template *template = garray_template(x);
2199 int yonset, type, i;
2200 t_symbol *arraytype;
2201 if (!template_find_field(template, gensym("y"), &yonset,
2202 &type, &arraytype) || type != DT_FLOAT)
2203 error("%s: needs floating-point 'y' field",
2204 x->x_templatesym->s_name);
2205 else for (i = 0; i < x->x_n; i++)
2206 *(float *)(((char *)x->x_vec + sizeof(t_word) * i) + yonset) = g;
2207 garray_redraw(x);
2208}
2209
2210 /* sum of Fourier components; called from routines below */
2211static void garray_dofo(t_garray *x, int npoints, float dcval,
2212 int nsin, t_float *vsin, int sineflag)
2213{
2214 t_template *template = garray_template(x);
2215 int yonset, type, i, j;
2216 t_symbol *arraytype;
2217 double phase, phaseincr, fj;
2218 if (npoints == 0)
2219 npoints = 512; /* dunno what a good default would be... */
2220 if (npoints != (1 << ilog2(npoints)))
2221 post("%s: rounnding to %d points", x->x_templatesym->s_name,
2222 (npoints = (1<<ilog2(npoints))));
2223 garray_resize(x, npoints + 3);
2224 phaseincr = 2. * 3.14159 / npoints;
2225 if (!template_find_field(template, gensym("y"), &yonset,
2226 &type, &arraytype) || type != DT_FLOAT)
2227 {
2228 error("%s: needs floating-point 'y' field", x->x_templatesym->s_name);
2229 return;
2230 }
2231 for (i = 0, phase = -phaseincr; i < x->x_n; i++, phase += phaseincr )
2232 {
2233 double sum = dcval;
2234 if (sineflag)
2235 for (j = 0, fj = phase; j < nsin; j++, fj += phase)
2236 sum += vsin[j] * sin(fj);
2237 else
2238 for (j = 0, fj = 0; j < nsin; j++, fj += phase)
2239 sum += vsin[j] * cos(fj);
2240 *(float *)((x->x_vec + sizeof(t_word) * i) + yonset) = sum;
2241 }
2242 garray_redraw(x);
2243}
2244
2245static void garray_sinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv)
2246{
2247 t_template *template = garray_template(x);
2248
2249 t_float *svec = (t_float *)t_getbytes(sizeof(t_float) * argc);
2250 int npoints, i;
2251 if (argc < 2)
2252 {
2253 error("sinesum: %s: need number of points and partial strengths",
2254 x->x_templatesym->s_name);
2255 return;
2256 }
2257
2258 npoints = atom_getfloatarg(0, argc, argv);
2259 argv++, argc--;
2260
2261 svec = (t_float *)t_getbytes(sizeof(t_float) * argc);
2262 if (!svec) return;
2263
2264 for (i = 0; i < argc; i++)
2265 svec[i] = atom_getfloatarg(i, argc, argv);
2266 garray_dofo(x, npoints, 0, argc, svec, 1);
2267 t_freebytes(svec, sizeof(t_float) * argc);
2268}
2269
2270static void garray_cosinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv)
2271{
2272 t_template *template = garray_template(x);
2273
2274 t_float *svec = (t_float *)t_getbytes(sizeof(t_float) * argc);
2275 int npoints, i;
2276 if (argc < 2)
2277 {
2278 error("sinesum: %s: need number of points and partial strengths",
2279 x->x_templatesym->s_name);
2280 return;
2281 }
2282
2283 npoints = atom_getfloatarg(0, argc, argv);
2284 argv++, argc--;
2285
2286 svec = (t_float *)t_getbytes(sizeof(t_float) * argc);
2287 if (!svec) return;
2288
2289 for (i = 0; i < argc; i++)
2290 svec[i] = atom_getfloatarg(i, argc, argv);
2291 garray_dofo(x, npoints, 0, argc, svec, 0);
2292 t_freebytes(svec, sizeof(t_float) * argc);
2293}
2294
2295static void garray_normalize(t_garray *x, t_float f)
2296{
2297 t_template *template = garray_template(x);
2298 int yonset, type, npoints, i;
2299 double maxv, renormer;
2300 t_symbol *arraytype;
2301
2302 if (f <= 0)
2303 f = 1;
2304
2305 if (!template_find_field(template, gensym("y"), &yonset,
2306 &type, &arraytype) || type != DT_FLOAT)
2307 {
2308 error("%s: needs floating-point 'y' field", x->x_templatesym->s_name);
2309 return;
2310 }
2311 for (i = 0, maxv = 0; i < x->x_n; i++)
2312 {
2313 double v = *(float *)((x->x_vec + sizeof(t_word) * i) + yonset);
2314 if (v > maxv)
2315 maxv = v;
2316 if (-v > maxv)
2317 maxv = -v;
2318 }
2319 if (maxv >= 0)
2320 {
2321 renormer = f / maxv;
2322 for (i = 0; i < x->x_n; i++)
2323 {
2324 *(float *)((x->x_vec + sizeof(t_word) * i) + yonset)
2325 *= renormer;
2326 }
2327 }
2328 garray_redraw(x);
2329}
2330
2331 /* list -- the first value is an index; subsequent values are put in
2332 the "y" slot of the array. This generalizes Max's "table", sort of. */
2333static void garray_list(t_garray *x, t_symbol *s, int argc, t_atom *argv)
2334{
2335 t_template *template = garray_template(x);
2336 int yonset, type, i;
2337 t_symbol *arraytype;
2338 if (!template_find_field(template, gensym("y"), &yonset,
2339 &type, &arraytype) || type != DT_FLOAT)
2340 error("%s: needs floating-point 'y' field",
2341 x->x_templatesym->s_name);
2342 else if (argc < 2) return;
2343 else
2344 {
2345 int firstindex = atom_getfloat(argv);
2346 argc--;
2347 argv++;
2348 /* drop negative x values */
2349 if (firstindex < 0)
2350 {
2351 argc += firstindex;
2352 argv -= firstindex;
2353 firstindex = 0;
2354 if (argc <= 0) return;
2355 }
2356 if (argc + firstindex > x->x_n)
2357 {
2358 argc = x->x_n - firstindex;
2359 if (argc <= 0) return;
2360 }
2361 for (i = 0; i < argc; i++)
2362 *(t_sample *)((x->x_vec + sizeof(t_word) * (i + firstindex)) + yonset) =
2363 ftofix(atom_getfloat(argv + i));
2364 }
2365 garray_redraw(x);
2366}
2367
2368 /* forward a "bounds" message to the owning graph */
2369static void garray_bounds(t_garray *x, t_floatarg x1, t_floatarg y1,
2370 t_floatarg x2, t_floatarg y2)
2371{
2372 vmess(&x->x_glist->gl_pd, gensym("bounds"), "ffff", x1, y1, x2, y2);
2373}
2374
2375 /* same for "xticks", etc */
2376static void garray_xticks(t_garray *x,
2377 t_floatarg point, t_floatarg inc, t_floatarg f)
2378{
2379 vmess(&x->x_glist->gl_pd, gensym("xticks"), "fff", point, inc, f);
2380}
2381
2382static void garray_yticks(t_garray *x,
2383 t_floatarg point, t_floatarg inc, t_floatarg f)
2384{
2385 vmess(&x->x_glist->gl_pd, gensym("yticks"), "fff", point, inc, f);
2386}
2387
2388static void garray_xlabel(t_garray *x, t_symbol *s, int argc, t_atom *argv)
2389{
2390 typedmess(&x->x_glist->gl_pd, s, argc, argv);
2391}
2392
2393static void garray_ylabel(t_garray *x, t_symbol *s, int argc, t_atom *argv)
2394{
2395 typedmess(&x->x_glist->gl_pd, s, argc, argv);
2396}
2397 /* change the name of a garray. */
2398static void garray_rename(t_garray *x, t_symbol *s)
2399{
2400 pd_unbind(&x->x_gobj.g_pd, x->x_realname);
2401 pd_bind(&x->x_gobj.g_pd, x->x_realname = x->x_name = s);
2402 garray_redraw(x);
2403}
2404
2405static void garray_read(t_garray *x, t_symbol *filename)
2406{
2407 int nelem = x->x_n, filedesc;
2408 FILE *fd;
2409 char buf[MAXPDSTRING], *bufptr;
2410 t_template *template = garray_template(x);
2411 int yonset, type, i;
2412 t_symbol *arraytype;
2413 if (!template_find_field(template, gensym("y"), &yonset,
2414 &type, &arraytype) || type != DT_FLOAT)
2415 {
2416 error("%s: needs floating-point 'y' field", x->x_templatesym->s_name);
2417 return;
2418 }
2419 if ((filedesc = open_via_path(
2420 canvas_getdir(glist_getcanvas(x->x_glist))->s_name,
2421 filename->s_name, "", buf, &bufptr, MAXPDSTRING, 0)) < 0
2422 || !(fd = fdopen(filedesc, "r")))
2423 {
2424 error("%s: can't open", filename->s_name);
2425 return;
2426 }
2427 for (i = 0; i < nelem; i++)
2428 {
2429 if (!fscanf(fd, "%f", (float *)((x->x_vec + sizeof(t_word) * i) +
2430 yonset)))
2431 {
2432 post("%s: read %d elements into table of size %d",
2433 filename->s_name, i, nelem);
2434 break;
2435 }
2436 }
2437 while (i < nelem)
2438 *(float *)((x->x_vec + sizeof(t_word) * i) + yonset) = 0, i++;
2439 fclose(fd);
2440 garray_redraw(x);
2441}
2442
2443 /* this should be renamed and moved... */
2444int garray_ambigendian(void)
2445{
2446 unsigned short s = 1;
2447 unsigned char c = *(char *)(&s);
2448 return (c==0);
2449}
2450
2451#define BINREADMODE "rb"
2452#define BINWRITEMODE "wb"
2453
2454static void garray_read16(t_garray *x, t_symbol *filename,
2455 t_symbol *endian, t_floatarg fskip)
2456{
2457 int skip = fskip, filedesc;
2458 int i, nelem;
2459 t_sample *vec;
2460 FILE *fd;
2461 char buf[MAXPDSTRING], *bufptr;
2462 short s;
2463 int cpubig = garray_ambigendian(), swap = 0;
2464 char c = endian->s_name[0];
2465 if (c == 'b')
2466 {
2467 if (!cpubig) swap = 1;
2468 }
2469 else if (c == 'l')
2470 {
2471 if (cpubig) swap = 1;
2472 }
2473 else if (c)
2474 {
2475 error("array_read16: endianness is 'l' (low byte first ala INTEL)");
2476 post("... or 'b' (high byte first ala MIPS,DEC,PPC)");
2477 }
2478 if (!garray_getfloatarray(x, &nelem, &vec))
2479 {
2480 error("%s: not a float array", x->x_templatesym->s_name);
2481 return;
2482 }
2483 if ((filedesc = open_via_path(
2484 canvas_getdir(glist_getcanvas(x->x_glist))->s_name,
2485 filename->s_name, "", buf, &bufptr, MAXPDSTRING, 1)) < 0
2486 || !(fd = fdopen(filedesc, BINREADMODE)))
2487 {
2488 error("%s: can't open", filename->s_name);
2489 return;
2490 }
2491 if (skip)
2492 {
2493 long pos = fseek(fd, (long)skip, SEEK_SET);
2494 if (pos < 0)
2495 {
2496 error("%s: can't seek to byte %d", buf, skip);
2497 fclose(fd);
2498 return;
2499 }
2500 }
2501
2502 for (i = 0; i < nelem; i++)
2503 {
2504 if (fread(&s, sizeof(s), 1, fd) < 1)
2505 {
2506 post("%s: read %d elements into table of size %d",
2507 filename->s_name, i, nelem);
2508 break;
2509 }
2510 if (swap) s = ((s & 0xff) << 8) | ((s & 0xff00) >> 8);
2511 vec[i] = s * (1./32768.);
2512 }
2513 while (i < nelem) vec[i++] = 0;
2514 fclose(fd);
2515 garray_redraw(x);
2516}
2517
2518static void garray_write(t_garray *x, t_symbol *filename)
2519{
2520 FILE *fd;
2521 char buf[MAXPDSTRING];
2522 t_template *template = garray_template(x);
2523 int yonset, type, i;
2524 t_symbol *arraytype;
2525 if (!template_find_field(template, gensym("y"), &yonset,
2526 &type, &arraytype) || type != DT_FLOAT)
2527 {
2528 error("%s: needs floating-point 'y' field", x->x_templatesym->s_name);
2529 return;
2530 }
2531 canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name,
2532 buf, MAXPDSTRING);
2533 sys_bashfilename(buf, buf);
2534 if (!(fd = fopen(buf, "w")))
2535 {
2536 error("%s: can't create", buf);
2537 return;
2538 }
2539 for (i = 0; i < x->x_n; i++)
2540 {
2541 if (fprintf(fd, "%g\n",
2542 *(float *)((x->x_vec + sizeof(t_word) * i) + yonset)) < 1)
2543 {
2544 post("%s: write error", filename->s_name);
2545 break;
2546 }
2547 }
2548 fclose(fd);
2549}
2550
2551static unsigned char waveheader[] = {
25520x52, 0x49, 0x46, 0x46,
25530x00, 0x00, 0x00, 0x00,
25540x57, 0x41, 0x56, 0x45,
25550x66, 0x6d, 0x74, 0x20,
2556
25570x10, 0x00, 0x00, 0x00,
25580x01, 0x00, 0x01, 0x00,
25590x44, 0xac, 0x00, 0x00,
25600x88, 0x58, 0x01, 0x00,
2561
25620x02, 0x00, 0x10, 0x00,
25630x64, 0x61, 0x74, 0x61,
25640x00, 0x00, 0x00, 0x00,
2565};
2566
2567 /* wave format only so far */
2568static void garray_write16(t_garray *x, t_symbol *filename, t_symbol *format)
2569{
2570 t_template *template = garray_template(x);
2571 int yonset, type, i;
2572 t_symbol *arraytype;
2573 FILE *fd;
2574 int aiff = (format == gensym("aiff"));
2575 char filenamebuf[MAXPDSTRING], buf2[MAXPDSTRING];
2576 int swap = garray_ambigendian(); /* wave is only little endian */
2577 int intbuf;
2578 strncpy(filenamebuf, filename->s_name, MAXPDSTRING-10);
2579 filenamebuf[MAXPDSTRING-10] = 0;
2580 if (sizeof(int) != 4) post("write16: only works on 32-bit machines");
2581 if (aiff)
2582 {
2583 if (strcmp(filenamebuf + strlen(filenamebuf)-5, ".aiff"))
2584 strcat(filenamebuf, ".aiff");
2585 }
2586 else
2587 {
2588 if (strcmp(filenamebuf + strlen(filenamebuf)-4, ".wav"))
2589 strcat(filenamebuf, ".wav");
2590 }
2591 if (!template_find_field(template, gensym("y"), &yonset,
2592 &type, &arraytype) || type != DT_FLOAT)
2593 {
2594 error("%s: needs floating-point 'y' field", x->x_templatesym->s_name);
2595 return;
2596 }
2597 canvas_makefilename(glist_getcanvas(x->x_glist), filenamebuf,
2598 buf2, MAXPDSTRING);
2599 sys_bashfilename(buf2, buf2);
2600 if (!(fd = fopen(buf2, BINWRITEMODE)))
2601 {
2602 error("%s: can't create", buf2);
2603 return;
2604 }
2605 intbuf = 2 * x->x_n + 36;
2606 if (swap)
2607 {
2608 unsigned char *foo = (unsigned char *)&intbuf, xxx;
2609 xxx = foo[0]; foo[0] = foo[3]; foo[3] = xxx;
2610 xxx = foo[1]; foo[1] = foo[2]; foo[2] = xxx;
2611 }
2612 memcpy((void *)(waveheader + 4), (void *)(&intbuf), 4);
2613 intbuf = 2 * x->x_n;
2614 if (swap)
2615 {
2616 unsigned char *foo = (unsigned char *)&intbuf, xxx;
2617 xxx = foo[0]; foo[0] = foo[3]; foo[3] = xxx;
2618 xxx = foo[1]; foo[1] = foo[2]; foo[2] = xxx;
2619 }
2620 memcpy((void *)(waveheader + 40), (void *)(&intbuf), 4);
2621 if (fwrite(waveheader, sizeof(waveheader), 1, fd) < 1)
2622 {
2623 post("%s: write error", buf2);
2624 goto closeit;
2625 }
2626 for (i = 0; i < x->x_n; i++)
2627 {
2628 float f = 32767. * *(float *)((x->x_vec + sizeof(t_word) * i) + yonset);
2629 short sh;
2630 if (f < -32768) f = -32768;
2631 else if (f > 32767) f = 32767;
2632 sh = f;
2633 if (swap)
2634 {
2635 unsigned char *foo = (unsigned char *)&sh, xxx;
2636 xxx = foo[0]; foo[0] = foo[1]; foo[1] = xxx;
2637 }
2638 if (fwrite(&sh, sizeof(sh), 1, fd) < 1)
2639 {
2640 post("%s: write error", buf2);
2641 goto closeit;
2642 }
2643 }
2644closeit:
2645 fclose(fd);
2646}
2647
2648void garray_resize(t_garray *x, t_floatarg f)
2649{
2650 int was = x->x_n, elemsize;
2651 t_glist *gl;
2652 int dspwas;
2653 int n = f;
2654 char *nvec;
2655
2656 if (n < 1) n = 1;
2657 elemsize = template_findbyname(x->x_templatesym)->t_n * sizeof(t_word);
2658 nvec = t_resizebytes(x->x_vec, was * elemsize, n * elemsize);
2659 if (!nvec)
2660 {
2661 pd_error(x, "array resize failed: out of memory");
2662 return;
2663 }
2664 x->x_vec = nvec;
2665 /* LATER should check t_resizebytes result */
2666 if (n > was)
2667 memset(x->x_vec + was*elemsize,
2668 0, (n - was) * elemsize);
2669 x->x_n = n;
2670
2671 /* if this is the only array in the graph,
2672 reset the graph's coordinates */
2673 gl = x->x_glist;
2674 if (gl->gl_list == &x->x_gobj && !x->x_gobj.g_next)
2675 {
2676 vmess(&gl->gl_pd, gensym("bounds"), "ffff",
2677 0., gl->gl_y1, (double)(n > 1 ? n-1 : 1), gl->gl_y2);
2678 /* close any dialogs that might have the wrong info now... */
2679 gfxstub_deleteforkey(gl);
2680 }
2681 else garray_redraw(x);
2682 if (x->x_usedindsp) canvas_update_dsp();
2683}
2684
2685static void garray_print(t_garray *x)
2686{
2687 post("garray %s: template %s, length %d",
2688 x->x_name->s_name, x->x_templatesym->s_name, x->x_n);
2689}
2690
2691void g_array_setup(void)
2692{
2693 garray_class = class_new(gensym("array"), 0, (t_method)garray_free,
2694 sizeof(t_garray), CLASS_GOBJ, 0);
2695 class_setwidget(garray_class, &garray_widgetbehavior);
2696 class_addmethod(garray_class, (t_method)garray_const, gensym("const"),
2697 A_DEFFLOAT, A_NULL);
2698 class_addlist(garray_class, garray_list);
2699 class_addmethod(garray_class, (t_method)garray_bounds, gensym("bounds"),
2700 A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
2701 class_addmethod(garray_class, (t_method)garray_xticks, gensym("xticks"),
2702 A_FLOAT, A_FLOAT, A_FLOAT, 0);
2703 class_addmethod(garray_class, (t_method)garray_xlabel, gensym("xlabel"),
2704 A_GIMME, 0);
2705 class_addmethod(garray_class, (t_method)garray_yticks, gensym("yticks"),
2706 A_FLOAT, A_FLOAT, A_FLOAT, 0);
2707 class_addmethod(garray_class, (t_method)garray_ylabel, gensym("ylabel"),
2708 A_GIMME, 0);
2709 class_addmethod(garray_class, (t_method)garray_rename, gensym("rename"),
2710 A_SYMBOL, 0);
2711 class_addmethod(garray_class, (t_method)garray_read, gensym("read"),
2712 A_SYMBOL, A_NULL);
2713 class_addmethod(garray_class, (t_method)garray_read16, gensym("read16"),
2714 A_SYMBOL, A_DEFFLOAT, A_DEFSYM, A_NULL);
2715 class_addmethod(garray_class, (t_method)garray_write, gensym("write"),
2716 A_SYMBOL, A_NULL);
2717 class_addmethod(garray_class, (t_method)garray_write16, gensym("write16"),
2718 A_SYMBOL, A_DEFSYM, A_NULL);
2719 class_addmethod(garray_class, (t_method)garray_resize, gensym("resize"),
2720 A_FLOAT, A_NULL);
2721 class_addmethod(garray_class, (t_method)garray_print, gensym("print"),
2722 A_NULL);
2723 class_addmethod(garray_class, (t_method)garray_sinesum, gensym("sinesum"),
2724 A_GIMME, 0);
2725 class_addmethod(garray_class, (t_method)garray_cosinesum,
2726 gensym("cosinesum"), A_GIMME, 0);
2727 class_addmethod(garray_class, (t_method)garray_normalize,
2728 gensym("normalize"), A_DEFFLOAT, 0);
2729 class_addmethod(garray_class, (t_method)garray_arraydialog,
2730 gensym("arraydialog"), A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
2731 class_setsavefn(garray_class, garray_save);
2732}
2733
2734