diff options
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/g_io.c')
-rw-r--r-- | apps/plugins/pdbox/PDa/src/g_io.c | 611 |
1 files changed, 0 insertions, 611 deletions
diff --git a/apps/plugins/pdbox/PDa/src/g_io.c b/apps/plugins/pdbox/PDa/src/g_io.c index 39788d2adb..db69543a87 100644 --- a/apps/plugins/pdbox/PDa/src/g_io.c +++ b/apps/plugins/pdbox/PDa/src/g_io.c | |||
@@ -610,615 +610,4 @@ void g_io_setup(void) | |||
610 | vinlet_setup(); | 610 | vinlet_setup(); |
611 | voutlet_setup(); | 611 | voutlet_setup(); |
612 | } | 612 | } |
613 | /* Copyright (c) 1997-1999 Miller Puckette. | ||
614 | * For information on usage and redistribution, and for a DISCLAIMER OF ALL | ||
615 | * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ | ||
616 | |||
617 | /* graphical inlets and outlets, both for control and signals. */ | ||
618 | |||
619 | /* This code is highly inefficient; messages actually have to be forwarded | ||
620 | by inlets and outlets. The outlet is in even worse shape than the inlet; | ||
621 | in order to avoid having a "signal" method in the class, the oulet actually | ||
622 | sprouts an inlet, which forwards the message to the "outlet" object, which | ||
623 | sends it on to the outlet proper. Another way to do it would be to have | ||
624 | separate classes for "signal" and "control" outlets, but this would complicate | ||
625 | life elsewhere. */ | ||
626 | |||
627 | |||
628 | /* hacked to run subpatches with different samplerates | ||
629 | * | ||
630 | * mfg.gfd.uil | ||
631 | * IOhannes | ||
632 | * | ||
633 | * edited lines are marked with "IOhannes" | ||
634 | * | ||
635 | */ | ||
636 | |||
637 | #include "m_pd.h" | ||
638 | #include "g_canvas.h" | ||
639 | #include <string.h> | ||
640 | void signal_setborrowed(t_signal *sig, t_signal *sig2); | ||
641 | void signal_makereusable(t_signal *sig); | ||
642 | |||
643 | /* ------------------------- vinlet -------------------------- */ | ||
644 | t_class *vinlet_class; | ||
645 | |||
646 | typedef struct _vinlet | ||
647 | { | ||
648 | t_object x_obj; | ||
649 | t_canvas *x_canvas; | ||
650 | t_inlet *x_inlet; | ||
651 | int x_bufsize; | ||
652 | t_float *x_buf; /* signal buffer; zero if not a signal */ | ||
653 | t_float *x_endbuf; | ||
654 | t_float *x_fill; | ||
655 | t_float *x_read; | ||
656 | int x_hop; | ||
657 | /* if not reblocking, the next slot communicates the parent's inlet | ||
658 | signal from the prolog to the DSP routine: */ | ||
659 | t_signal *x_directsignal; | ||
660 | |||
661 | t_resample x_updown; /* IOhannes */ | ||
662 | } t_vinlet; | ||
663 | |||
664 | static void *vinlet_new(t_symbol *s) | ||
665 | { | ||
666 | t_vinlet *x = (t_vinlet *)pd_new(vinlet_class); | ||
667 | x->x_canvas = canvas_getcurrent(); | ||
668 | x->x_inlet = canvas_addinlet(x->x_canvas, &x->x_obj.ob_pd, 0); | ||
669 | x->x_bufsize = 0; | ||
670 | x->x_buf = 0; | ||
671 | outlet_new(&x->x_obj, 0); | ||
672 | return (x); | ||
673 | } | ||
674 | |||
675 | static void vinlet_bang(t_vinlet *x) | ||
676 | { | ||
677 | outlet_bang(x->x_obj.ob_outlet); | ||
678 | } | ||
679 | |||
680 | static void vinlet_pointer(t_vinlet *x, t_gpointer *gp) | ||
681 | { | ||
682 | outlet_pointer(x->x_obj.ob_outlet, gp); | ||
683 | } | ||
684 | |||
685 | static void vinlet_float(t_vinlet *x, t_float f) | ||
686 | { | ||
687 | outlet_float(x->x_obj.ob_outlet, f); | ||
688 | } | ||
689 | |||
690 | static void vinlet_symbol(t_vinlet *x, t_symbol *s) | ||
691 | { | ||
692 | outlet_symbol(x->x_obj.ob_outlet, s); | ||
693 | } | ||
694 | |||
695 | static void vinlet_list(t_vinlet *x, t_symbol *s, int argc, t_atom *argv) | ||
696 | { | ||
697 | outlet_list(x->x_obj.ob_outlet, s, argc, argv); | ||
698 | } | ||
699 | |||
700 | static void vinlet_anything(t_vinlet *x, t_symbol *s, int argc, t_atom *argv) | ||
701 | { | ||
702 | outlet_anything(x->x_obj.ob_outlet, s, argc, argv); | ||
703 | } | ||
704 | |||
705 | static void vinlet_free(t_vinlet *x) | ||
706 | { | ||
707 | canvas_rminlet(x->x_canvas, x->x_inlet); | ||
708 | resample_free(&x->x_updown); | ||
709 | } | ||
710 | |||
711 | t_inlet *vinlet_getit(t_pd *x) | ||
712 | { | ||
713 | if (pd_class(x) != vinlet_class) bug("vinlet_getit"); | ||
714 | return (((t_vinlet *)x)->x_inlet); | ||
715 | } | ||
716 | |||
717 | /* ------------------------- signal inlet -------------------------- */ | ||
718 | int vinlet_issignal(t_vinlet *x) | ||
719 | { | ||
720 | return (x->x_buf != 0); | ||
721 | } | ||
722 | |||
723 | static int tot; | ||
724 | |||
725 | t_int *vinlet_perform(t_int *w) | ||
726 | { | ||
727 | t_vinlet *x = (t_vinlet *)(w[1]); | ||
728 | t_float *out = (t_float *)(w[2]); | ||
729 | int n = (int)(w[3]); | ||
730 | t_float *in = x->x_read; | ||
731 | #if 0 | ||
732 | if (tot < 5) post("-in %x out %x n %d", in, out, n); | ||
733 | if (tot < 5) post("-buf %x endbuf %x", x->x_buf, x->x_endbuf); | ||
734 | if (tot < 5) post("in[0] %f in[1] %f in[2] %f", in[0], in[1], in[2]); | ||
735 | #endif | ||
736 | while (n--) *out++ = *in++; | ||
737 | if (in == x->x_endbuf) in = x->x_buf; | ||
738 | x->x_read = in; | ||
739 | return (w+4); | ||
740 | } | ||
741 | |||
742 | static void vinlet_dsp(t_vinlet *x, t_signal **sp) | ||
743 | { | ||
744 | t_signal *outsig; | ||
745 | /* no buffer means we're not a signal inlet */ | ||
746 | if (!x->x_buf) | ||
747 | return; | ||
748 | outsig = sp[0]; | ||
749 | if (x->x_directsignal) | ||
750 | { | ||
751 | signal_setborrowed(sp[0], x->x_directsignal); | ||
752 | } | ||
753 | else | ||
754 | { | ||
755 | dsp_add(vinlet_perform, 3, x, outsig->s_vec, outsig->s_n); | ||
756 | x->x_read = x->x_buf; | ||
757 | } | ||
758 | } | ||
759 | |||
760 | /* prolog code: loads buffer from parent patch */ | ||
761 | t_int *vinlet_doprolog(t_int *w) | ||
762 | { | ||
763 | t_vinlet *x = (t_vinlet *)(w[1]); | ||
764 | t_float *in = (t_float *)(w[2]); | ||
765 | int n = (int)(w[3]); | ||
766 | t_float *out = x->x_fill; | ||
767 | if (out == x->x_endbuf) | ||
768 | { | ||
769 | t_float *f1 = x->x_buf, *f2 = x->x_buf + x->x_hop; | ||
770 | int nshift = x->x_bufsize - x->x_hop; | ||
771 | out -= x->x_hop; | ||
772 | while (nshift--) *f1++ = *f2++; | ||
773 | } | ||
774 | #if 0 | ||
775 | if (tot < 5) post("in %x out %x n %x", in, out, n), tot++; | ||
776 | if (tot < 5) post("in[0] %f in[1] %f in[2] %f", in[0], in[1], in[2]); | ||
777 | #endif | ||
778 | |||
779 | while (n--) *out++ = *in++; | ||
780 | x->x_fill = out; | ||
781 | return (w+4); | ||
782 | } | ||
783 | 613 | ||
784 | int inlet_getsignalindex(t_inlet *x); | ||
785 | |||
786 | /* set up prolog DSP code */ | ||
787 | void vinlet_dspprolog(t_vinlet *x, t_signal **parentsigs, | ||
788 | int myvecsize, int phase, int period, int frequency, int downsample, int upsample/* IOhannes */, int reblock, | ||
789 | int switched) | ||
790 | { | ||
791 | t_signal *insig, *outsig; | ||
792 | x->x_updown.downsample = downsample; | ||
793 | x->x_updown.upsample = upsample; | ||
794 | |||
795 | /* if the "reblock" flag is set, arrange to copy data in from the | ||
796 | parent. */ | ||
797 | if (reblock) | ||
798 | { | ||
799 | int parentvecsize, bufsize, oldbufsize, prologphase; | ||
800 | int re_parentvecsize; /* resampled parentvectorsize: IOhannes */ | ||
801 | /* this should never happen: */ | ||
802 | if (!x->x_buf) return; | ||
803 | |||
804 | /* the prolog code counts from 0 to period-1; the | ||
805 | phase is backed up by one so that AFTER the prolog code | ||
806 | runs, the "x_fill" phase is in sync with the "x_read" phase. */ | ||
807 | prologphase = (phase - 1) & (period - 1); | ||
808 | if (parentsigs) | ||
809 | { | ||
810 | insig = parentsigs[inlet_getsignalindex(x->x_inlet)]; | ||
811 | parentvecsize = insig->s_n; | ||
812 | re_parentvecsize = parentvecsize * upsample / downsample; | ||
813 | } | ||
814 | else | ||
815 | { | ||
816 | insig = 0; | ||
817 | parentvecsize = 1; | ||
818 | re_parentvecsize = 1; | ||
819 | } | ||
820 | |||
821 | bufsize = re_parentvecsize; | ||
822 | if (bufsize < myvecsize) bufsize = myvecsize; | ||
823 | if (bufsize != (oldbufsize = x->x_bufsize)) | ||
824 | { | ||
825 | t_float *buf = x->x_buf; | ||
826 | t_freebytes(buf, oldbufsize * sizeof(*buf)); | ||
827 | buf = (t_float *)t_getbytes(bufsize * sizeof(*buf)); | ||
828 | memset((char *)buf, 0, bufsize * sizeof(*buf)); | ||
829 | x->x_bufsize = bufsize; | ||
830 | x->x_endbuf = buf + bufsize; | ||
831 | x->x_buf = buf; | ||
832 | } | ||
833 | if (parentsigs) | ||
834 | { | ||
835 | /* IOhannes { */ | ||
836 | x->x_hop = period * re_parentvecsize; | ||
837 | |||
838 | x->x_fill = x->x_endbuf - | ||
839 | (x->x_hop - prologphase * re_parentvecsize); | ||
840 | |||
841 | if (upsample * downsample == 1) | ||
842 | dsp_add(vinlet_doprolog, 3, x, insig->s_vec, re_parentvecsize); | ||
843 | else { | ||
844 | resamplefrom_dsp(&x->x_updown, insig->s_vec, parentvecsize, re_parentvecsize, x->x_updown.method); | ||
845 | dsp_add(vinlet_doprolog, 3, x, x->x_updown.s_vec, re_parentvecsize); | ||
846 | } | ||
847 | |||
848 | /* } IOhannes */ | ||
849 | /* if the input signal's reference count is zero, we have | ||
850 | to free it here because we didn't in ugen_doit(). */ | ||
851 | if (!insig->s_refcount) | ||
852 | signal_makereusable(insig); | ||
853 | } | ||
854 | else memset((char *)(x->x_buf), 0, bufsize * sizeof(*x->x_buf)); | ||
855 | x->x_directsignal = 0; | ||
856 | } | ||
857 | else | ||
858 | { | ||
859 | /* no reblocking; in this case our output signal is "borrowed" | ||
860 | and merely needs to be pointed to the real one. */ | ||
861 | x->x_directsignal = parentsigs[inlet_getsignalindex(x->x_inlet)]; | ||
862 | } | ||
863 | } | ||
864 | |||
865 | //static void *vinlet_newsig(void) | ||
866 | static void *vinlet_newsig(t_symbol *s) | ||
867 | { | ||
868 | t_vinlet *x = (t_vinlet *)pd_new(vinlet_class); | ||
869 | x->x_canvas = canvas_getcurrent(); | ||
870 | x->x_inlet = canvas_addinlet(x->x_canvas, &x->x_obj.ob_pd, &s_signal); | ||
871 | x->x_endbuf = x->x_buf = (t_float *)getbytes(0); | ||
872 | x->x_bufsize = 0; | ||
873 | x->x_directsignal = 0; | ||
874 | outlet_new(&x->x_obj, &s_signal); | ||
875 | |||
876 | resample_init(&x->x_updown); | ||
877 | |||
878 | /* this should be though over: | ||
879 | * it might prove hard to provide consistency between labeled up- & downsampling methods | ||
880 | * maybe indeces would be better... | ||
881 | * | ||
882 | * up till now we provide several upsampling methods and 1 single downsampling method (no filtering !) | ||
883 | */ | ||
884 | if (s == gensym("hold"))x->x_updown.method=1; /* up: sample and hold */ | ||
885 | else if (s == gensym("lin"))x->x_updown.method=2; /* up: linear interpolation */ | ||
886 | else x->x_updown.method=0; /* up: zero-padding */ | ||
887 | |||
888 | return (x); | ||
889 | } | ||
890 | |||
891 | static void vinlet_setup(void) | ||
892 | { | ||
893 | vinlet_class = class_new(gensym("inlet"), (t_newmethod)vinlet_new, | ||
894 | (t_method)vinlet_free, sizeof(t_vinlet), CLASS_NOINLET, A_DEFSYM, 0); | ||
895 | class_addcreator((t_newmethod)vinlet_newsig, gensym("inlet~"), A_DEFSYM, 0); | ||
896 | class_addbang(vinlet_class, vinlet_bang); | ||
897 | class_addpointer(vinlet_class, vinlet_pointer); | ||
898 | class_addfloat(vinlet_class, vinlet_float); | ||
899 | class_addsymbol(vinlet_class, vinlet_symbol); | ||
900 | class_addlist(vinlet_class, vinlet_list); | ||
901 | class_addanything(vinlet_class, vinlet_anything); | ||
902 | class_addmethod(vinlet_class, (t_method)vinlet_dsp, gensym("dsp"), 0); | ||
903 | class_sethelpsymbol(vinlet_class, gensym("pd")); | ||
904 | } | ||
905 | |||
906 | /* ------------------------- voutlet -------------------------- */ | ||
907 | |||
908 | t_class *voutlet_class; | ||
909 | |||
910 | typedef struct _voutlet | ||
911 | { | ||
912 | t_object x_obj; | ||
913 | t_canvas *x_canvas; | ||
914 | t_outlet *x_parentoutlet; | ||
915 | int x_bufsize; | ||
916 | t_sample *x_buf; /* signal buffer; zero if not a signal */ | ||
917 | t_sample *x_endbuf; | ||
918 | t_sample *x_empty; /* next to read out of buffer in epilog code */ | ||
919 | t_sample *x_write; /* next to write in to buffer */ | ||
920 | int x_hop; /* hopsize */ | ||
921 | /* vice versa from the inlet, if we don't block, this holds the | ||
922 | parent's outlet signal, valid between the prolog and the dsp setup | ||
923 | routines. */ | ||
924 | t_signal *x_directsignal; | ||
925 | /* and here's a flag indicating that we aren't blocked but have to | ||
926 | do a copy (because we're switched). */ | ||
927 | char x_justcopyout; | ||
928 | t_resample x_updown; /* IOhannes */ | ||
929 | } t_voutlet; | ||
930 | |||
931 | static void *voutlet_new(t_symbol *s) | ||
932 | { | ||
933 | t_voutlet *x = (t_voutlet *)pd_new(voutlet_class); | ||
934 | x->x_canvas = canvas_getcurrent(); | ||
935 | x->x_parentoutlet = canvas_addoutlet(x->x_canvas, &x->x_obj.ob_pd, 0); | ||
936 | inlet_new(&x->x_obj, &x->x_obj.ob_pd, 0, 0); | ||
937 | x->x_bufsize = 0; | ||
938 | x->x_buf = 0; | ||
939 | return (x); | ||
940 | } | ||
941 | |||
942 | static void voutlet_bang(t_voutlet *x) | ||
943 | { | ||
944 | outlet_bang(x->x_parentoutlet); | ||
945 | } | ||
946 | |||
947 | static void voutlet_pointer(t_voutlet *x, t_gpointer *gp) | ||
948 | { | ||
949 | outlet_pointer(x->x_parentoutlet, gp); | ||
950 | } | ||
951 | |||
952 | static void voutlet_float(t_voutlet *x, t_float f) | ||
953 | { | ||
954 | outlet_float(x->x_parentoutlet, f); | ||
955 | } | ||
956 | |||
957 | static void voutlet_symbol(t_voutlet *x, t_symbol *s) | ||
958 | { | ||
959 | outlet_symbol(x->x_parentoutlet, s); | ||
960 | } | ||
961 | |||
962 | static void voutlet_list(t_voutlet *x, t_symbol *s, int argc, t_atom *argv) | ||
963 | { | ||
964 | outlet_list(x->x_parentoutlet, s, argc, argv); | ||
965 | } | ||
966 | |||
967 | static void voutlet_anything(t_voutlet *x, t_symbol *s, int argc, t_atom *argv) | ||
968 | { | ||
969 | outlet_anything(x->x_parentoutlet, s, argc, argv); | ||
970 | } | ||
971 | |||
972 | static void voutlet_free(t_voutlet *x) | ||
973 | { | ||
974 | canvas_rmoutlet(x->x_canvas, x->x_parentoutlet); | ||
975 | resample_free(&x->x_updown); | ||
976 | } | ||
977 | |||
978 | t_outlet *voutlet_getit(t_pd *x) | ||
979 | { | ||
980 | if (pd_class(x) != voutlet_class) bug("voutlet_getit"); | ||
981 | return (((t_voutlet *)x)->x_parentoutlet); | ||
982 | } | ||
983 | |||
984 | /* ------------------------- signal outlet -------------------------- */ | ||
985 | |||
986 | int voutlet_issignal(t_voutlet *x) | ||
987 | { | ||
988 | return (x->x_buf != 0); | ||
989 | } | ||
990 | |||
991 | /* LATER optimize for non-overlapped case where the "+=" isn't needed */ | ||
992 | t_int *voutlet_perform(t_int *w) | ||
993 | { | ||
994 | t_voutlet *x = (t_voutlet *)(w[1]); | ||
995 | t_sample *in = (t_sample *)(w[2]); | ||
996 | int n = (int)(w[3]); | ||
997 | t_sample *out = x->x_write, *outwas = out; | ||
998 | #if 0 | ||
999 | if (tot < 5) post("-in %x out %x n %d", in, out, n); | ||
1000 | if (tot < 5) post("-buf %x endbuf %x", x->x_buf, x->x_endbuf); | ||
1001 | #endif | ||
1002 | while (n--) | ||
1003 | { | ||
1004 | *out++ += *in++; | ||
1005 | if (out == x->x_endbuf) out = x->x_buf; | ||
1006 | } | ||
1007 | outwas += x->x_hop; | ||
1008 | if (outwas >= x->x_endbuf) outwas = x->x_buf; | ||
1009 | x->x_write = outwas; | ||
1010 | return (w+4); | ||
1011 | } | ||
1012 | |||
1013 | /* epilog code for blocking: write buffer to parent patch */ | ||
1014 | static t_int *voutlet_doepilog(t_int *w) | ||
1015 | { | ||
1016 | t_voutlet *x = (t_voutlet *)(w[1]); | ||
1017 | t_sample *out = (t_sample *)(w[2]); /* IOhannes */ | ||
1018 | |||
1019 | int n = (int)(w[3]); | ||
1020 | t_sample *in = x->x_empty; | ||
1021 | if (x->x_updown.downsample != x->x_updown.upsample) out = x->x_updown.s_vec; /* IOhannes */ | ||
1022 | |||
1023 | #if 0 | ||
1024 | if (tot < 5) post("outlet in %x out %x n %x", in, out, n), tot++; | ||
1025 | #endif | ||
1026 | for (; n--; in++) *out++ = *in, *in = 0; | ||
1027 | if (in == x->x_endbuf) in = x->x_buf; | ||
1028 | x->x_empty = in; | ||
1029 | return (w+4); | ||
1030 | } | ||
1031 | |||
1032 | /* IOhannes { */ | ||
1033 | static t_int *voutlet_doepilog_resampling(t_int *w) | ||
1034 | { | ||
1035 | t_voutlet *x = (t_voutlet *)(w[1]); | ||
1036 | // t_float *dummy = (t_float *)(w[2]); | ||
1037 | int n = (int)(w[2]); | ||
1038 | t_sample *in = x->x_empty; | ||
1039 | t_sample *out = x->x_updown.s_vec; /* IOhannes */ | ||
1040 | |||
1041 | #if 0 | ||
1042 | if (tot < 5) post("outlet in %x out %x n %x", in, out, n), tot++; | ||
1043 | #endif | ||
1044 | for (; n--; in++) *out++ = *in, *in = 0; | ||
1045 | if (in == x->x_endbuf) in = x->x_buf; | ||
1046 | x->x_empty = in; | ||
1047 | return (w+3); | ||
1048 | } | ||
1049 | /* } IOhannes */ | ||
1050 | int outlet_getsignalindex(t_outlet *x); | ||
1051 | |||
1052 | /* prolog for outlets -- store pointer to the outlet on the | ||
1053 | parent, which, if "reblock" is false, will want to refer | ||
1054 | back to whatever we see on our input during the "dsp" method | ||
1055 | called later. */ | ||
1056 | void voutlet_dspprolog(t_voutlet *x, t_signal **parentsigs, | ||
1057 | int myvecsize, int phase, int period, int frequency, int downsample, int upsample /* IOhannes */, int reblock, | ||
1058 | int switched) | ||
1059 | { | ||
1060 | x->x_updown.downsample=downsample; x->x_updown.upsample=upsample; /* IOhannes */ | ||
1061 | x->x_justcopyout = (switched && !reblock); | ||
1062 | if (reblock) | ||
1063 | { | ||
1064 | x->x_directsignal = 0; | ||
1065 | } | ||
1066 | else | ||
1067 | { | ||
1068 | if (!parentsigs) bug("voutlet_dspprolog"); | ||
1069 | x->x_directsignal = | ||
1070 | parentsigs[outlet_getsignalindex(x->x_parentoutlet)]; | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | static void voutlet_dsp(t_voutlet *x, t_signal **sp) | ||
1075 | { | ||
1076 | t_signal *insig; | ||
1077 | if (!x->x_buf) return; | ||
1078 | insig = sp[0]; | ||
1079 | if (x->x_justcopyout) | ||
1080 | dsp_add_copy(insig->s_vec, x->x_directsignal->s_vec, insig->s_n); | ||
1081 | else if (x->x_directsignal) | ||
1082 | { | ||
1083 | /* if we're just going to make the signal available on the | ||
1084 | parent patch, hand it off to the parent signal. */ | ||
1085 | /* this is done elsewhere--> sp[0]->s_refcount++; */ | ||
1086 | signal_setborrowed(x->x_directsignal, sp[0]); | ||
1087 | } | ||
1088 | else | ||
1089 | dsp_add(voutlet_perform, 3, x, insig->s_vec, insig->s_n); | ||
1090 | } | ||
1091 | |||
1092 | /* set up epilog DSP code. If we're reblocking, this is the | ||
1093 | time to copy the samples out to the containing object's outlets. | ||
1094 | If we aren't reblocking, there's nothing to do here. */ | ||
1095 | void voutlet_dspepilog(t_voutlet *x, t_signal **parentsigs, | ||
1096 | int myvecsize, int phase, int period, int frequency, int downsample, int upsample /* IOhannes */, int reblock, | ||
1097 | int switched) | ||
1098 | { | ||
1099 | if (!x->x_buf) return; /* this shouldn't be necesssary... */ | ||
1100 | x->x_updown.downsample=downsample; x->x_updown.upsample=upsample; /* IOhannes */ | ||
1101 | if (reblock) | ||
1102 | { | ||
1103 | t_signal *insig, *outsig; | ||
1104 | int parentvecsize, bufsize, oldbufsize; | ||
1105 | int re_parentvecsize; /* IOhannes */ | ||
1106 | int bigperiod, epilogphase, blockphase; | ||
1107 | if (parentsigs) | ||
1108 | { | ||
1109 | outsig = parentsigs[outlet_getsignalindex(x->x_parentoutlet)]; | ||
1110 | parentvecsize = outsig->s_n; | ||
1111 | re_parentvecsize = parentvecsize * upsample / downsample; | ||
1112 | } | ||
1113 | else | ||
1114 | { | ||
1115 | outsig = 0; | ||
1116 | parentvecsize = 1; | ||
1117 | re_parentvecsize = 1; | ||
1118 | } | ||
1119 | // bigperiod = (downsample * myvecsize)/(upsample * parentvecsize); /* IOhannes */ | ||
1120 | bigperiod = myvecsize/re_parentvecsize; /* IOhannes */ | ||
1121 | if (!bigperiod) bigperiod = 1; | ||
1122 | epilogphase = phase & (bigperiod - 1); | ||
1123 | blockphase = (phase + period - 1) & (bigperiod - 1) & (- period); | ||
1124 | // bufsize = parentvecsize * upsample; /* IOhannes */ | ||
1125 | bufsize = re_parentvecsize; /* IOhannes */ | ||
1126 | if (bufsize < myvecsize) bufsize = myvecsize; | ||
1127 | if (bufsize != (oldbufsize = x->x_bufsize)) | ||
1128 | { | ||
1129 | t_sample *buf = x->x_buf; | ||
1130 | t_freebytes(buf, oldbufsize * sizeof(*buf)); | ||
1131 | buf = (t_sample *)t_getbytes(bufsize * sizeof(*buf)); | ||
1132 | memset((char *)buf, 0, bufsize * sizeof(*buf)); | ||
1133 | x->x_bufsize = bufsize; | ||
1134 | x->x_endbuf = buf + bufsize; | ||
1135 | x->x_buf = buf; | ||
1136 | } | ||
1137 | /* IOhannes: { */ | ||
1138 | if (re_parentvecsize * period > bufsize) bug("voutlet_dspepilog"); | ||
1139 | x->x_write = x->x_buf + re_parentvecsize * blockphase; | ||
1140 | if (x->x_write == x->x_endbuf) x->x_write = x->x_buf; | ||
1141 | if (period == 1 && frequency > 1) | ||
1142 | x->x_hop = re_parentvecsize / frequency; | ||
1143 | else x->x_hop = period * re_parentvecsize; | ||
1144 | /* } IOhannes */ | ||
1145 | /* post("phase %d, block %d, parent %d", phase & 63, | ||
1146 | parentvecsize * blockphase, parentvecsize * epilogphase); */ | ||
1147 | if (parentsigs) | ||
1148 | { | ||
1149 | /* set epilog pointer and schedule it */ | ||
1150 | /* IOhannes { */ | ||
1151 | x->x_empty = x->x_buf + re_parentvecsize * epilogphase; | ||
1152 | if (upsample * downsample == 1) | ||
1153 | dsp_add(voutlet_doepilog, 3, x, outsig->s_vec, re_parentvecsize); | ||
1154 | else { | ||
1155 | dsp_add(voutlet_doepilog_resampling, 2, x, re_parentvecsize); | ||
1156 | resampleto_dsp(&x->x_updown, outsig->s_vec, re_parentvecsize, parentvecsize, x->x_updown.method); | ||
1157 | } | ||
1158 | /* } IOhannes */ | ||
1159 | } | ||
1160 | } | ||
1161 | /* if we aren't blocked but we are switched, the epilog code just | ||
1162 | copies zeros to the output. In this case the blocking code actually | ||
1163 | jumps over the epilog if the block is running. */ | ||
1164 | else if (switched) | ||
1165 | { | ||
1166 | if (parentsigs) | ||
1167 | { | ||
1168 | t_signal *outsig = | ||
1169 | parentsigs[outlet_getsignalindex(x->x_parentoutlet)]; | ||
1170 | dsp_add_zero(outsig->s_vec, outsig->s_n); | ||
1171 | } | ||
1172 | } | ||
1173 | } | ||
1174 | |||
1175 | static void *voutlet_newsig(t_symbol *s) | ||
1176 | { | ||
1177 | t_voutlet *x = (t_voutlet *)pd_new(voutlet_class); | ||
1178 | x->x_canvas = canvas_getcurrent(); | ||
1179 | x->x_parentoutlet = canvas_addoutlet(x->x_canvas, | ||
1180 | &x->x_obj.ob_pd, &s_signal); | ||
1181 | inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); | ||
1182 | x->x_endbuf = x->x_buf = (t_sample *)getbytes(0); | ||
1183 | x->x_bufsize = 0; | ||
1184 | |||
1185 | resample_init(&x->x_updown); | ||
1186 | |||
1187 | /* this should be though over: | ||
1188 | * it might prove hard to provide consistency between labeled up- & downsampling methods | ||
1189 | * maybe indeces would be better... | ||
1190 | * | ||
1191 | * up till now we provide several upsampling methods and 1 single downsampling method (no filtering !) | ||
1192 | */ | ||
1193 | if (s == gensym("hold"))x->x_updown.method=1; /* up: sample and hold */ | ||
1194 | else if (s == gensym("lin"))x->x_updown.method=2; /* up: linear interpolation */ | ||
1195 | else if (s == gensym("linear"))x->x_updown.method=2; /* up: linear interpolation */ | ||
1196 | else x->x_updown.method=0; /* up: zero-padding; down: ignore samples inbetween */ | ||
1197 | |||
1198 | return (x); | ||
1199 | } | ||
1200 | |||
1201 | |||
1202 | static void voutlet_setup(void) | ||
1203 | { | ||
1204 | voutlet_class = class_new(gensym("outlet"), (t_newmethod)voutlet_new, | ||
1205 | (t_method)voutlet_free, sizeof(t_voutlet), CLASS_NOINLET, A_DEFSYM, 0); | ||
1206 | class_addcreator((t_newmethod)voutlet_newsig, gensym("outlet~"), A_DEFSYM, 0); | ||
1207 | class_addbang(voutlet_class, voutlet_bang); | ||
1208 | class_addpointer(voutlet_class, voutlet_pointer); | ||
1209 | class_addfloat(voutlet_class, (t_method)voutlet_float); | ||
1210 | class_addsymbol(voutlet_class, voutlet_symbol); | ||
1211 | class_addlist(voutlet_class, voutlet_list); | ||
1212 | class_addanything(voutlet_class, voutlet_anything); | ||
1213 | class_addmethod(voutlet_class, (t_method)voutlet_dsp, gensym("dsp"), 0); | ||
1214 | class_sethelpsymbol(voutlet_class, gensym("pd")); | ||
1215 | } | ||
1216 | |||
1217 | |||
1218 | /* ---------------------------- overall setup ----------------------------- */ | ||
1219 | |||
1220 | void g_io_setup(void) | ||
1221 | { | ||
1222 | vinlet_setup(); | ||
1223 | voutlet_setup(); | ||
1224 | } | ||