1 /*
2  * Copyright (C) 2002 2003 2004 2005, Magnus Hjorth
3  *
4  * This file is part of mhWaveEdit.
5  *
6  * mhWaveEdit is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * mhWaveEdit is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with mhWaveEdit; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 
22 #include <config.h>
23 
24 #include "mainwindow.h"
25 #include "combinechannelsdialog.h"
26 #include "effectbrowser.h"
27 #include "main.h"
28 
29 static GtkObjectClass *parent_class;
30 static sample_t *combination_matrix;
31 static sample_t *samples = NULL;
32 
combine_channels_dialog_apply_proc(void * in,guint sample_size,chunk_writeout_func out_func,WriteoutID id,Dataformat * format)33 static gboolean combine_channels_dialog_apply_proc(void *in, guint sample_size,
34 						   chunk_writeout_func out_func,
35 						   WriteoutID id,
36 						   Dataformat *format)
37 {
38      sample_t *s = (sample_t *)in, d;
39      guint i,j,chn=format->channels;
40      if (!samples)
41 	  samples = g_malloc(sample_size);
42      for (i=0; i<chn; i++) {
43 	  d = 0.0;
44 	  for (j=0; j<chn; j++)
45 	       d += s[j] * combination_matrix[i*chn+j];
46 	  samples[i] = d;
47      }
48      return out_func(id,samples,sample_size);
49 }
50 
combine_channels_dialog_apply(EffectDialog * ed)51 static gboolean combine_channels_dialog_apply(EffectDialog *ed)
52 {
53      guint i;
54      gboolean b;
55      Document *d = EFFECT_BROWSER(ed->eb)->dl->selected;
56      CombineChannelsDialog *ccd = COMBINE_CHANNELS_DIALOG(ed);
57      g_assert(ccd->channels == d->chunk->format.channels);
58      for (i=0; i<ccd->channels*ccd->channels; i++)
59 	  if (floatbox_check(ccd->combination_matrix[i])) return TRUE;
60      combination_matrix =g_malloc(ccd->channels*ccd->channels*sizeof(sample_t));
61      for (i=0; i<ccd->channels*ccd->channels; i++)
62 	  combination_matrix[i] = ccd->combination_matrix[i]->val / 100.0;
63      b = document_apply(d,combine_channels_dialog_apply_proc,NULL,
64 			CHUNK_FILTER_FULL,TRUE,NULL);
65      g_free(samples);
66      samples = NULL;
67      g_free(combination_matrix);
68      return b;
69 }
70 
combine_channels_dialog_target_changed(EffectDialog * ed)71 static void combine_channels_dialog_target_changed(EffectDialog *ed)
72 {
73      CombineChannelsDialog *ccd = COMBINE_CHANNELS_DIALOG(ed);
74      if (ccd->channels != EFFECT_BROWSER(ed->eb)->dl->format.channels)
75 	  effect_browser_invalidate_effect(EFFECT_BROWSER(ed->eb),"combine",
76 					   'B');
77 }
78 
combine_channels_setup(EffectDialog * ed)79 static void combine_channels_setup(EffectDialog *ed)
80 {
81     int i,j;
82     GtkWidget *a,*b,*c;
83     guint channels = EFFECT_BROWSER(ed->eb)->dl->format.channels;
84     CombineChannelsDialog *ccd = COMBINE_CHANNELS_DIALOG(ed);
85     ccd->channels = channels;
86     ccd->combination_matrix = g_malloc(channels*channels*sizeof(Floatbox *));
87     for (i=0; i<channels*channels; i++)
88         ccd->combination_matrix[i] =
89         FLOATBOX(floatbox_new( (i%(channels+1)==0) ? 100.0 : 0.0 ));
90     for (i=0; i<ccd->channels; i++) {
91         a=gtk_frame_new(channel_name(i,channels));
92 	gtk_container_set_border_width(GTK_CONTAINER(a),3);
93         gtk_box_pack_start(GTK_BOX(ed->input_area),a,FALSE,FALSE,0);
94         gtk_widget_show(a);
95         b = gtk_table_new(channels,3,FALSE);
96         gtk_container_add(GTK_CONTAINER(a),b);
97         gtk_widget_show(b);
98         for (j=0; j<channels; j++) {
99             c=gtk_label_new(channel_name(j,channels));
100             gtk_table_attach(GTK_TABLE(b),c,0,1,j,j+1,GTK_FILL,0,3,3);
101             gtk_widget_show(c);
102             c = GTK_WIDGET(ccd->combination_matrix[i*channels+j]);
103             gtk_table_attach(GTK_TABLE(b),c,1,2,j,j+1,GTK_FILL,0,3,3);
104             gtk_widget_show(c);
105             c = gtk_label_new("%");
106             gtk_table_attach(GTK_TABLE(b),c,2,3,j,j+1,GTK_FILL,0,0,3);
107             gtk_widget_show(c);
108         }
109     }
110 }
111 
combine_channels_destroy(GtkObject * obj)112 static void combine_channels_destroy(GtkObject *obj)
113 {
114     CombineChannelsDialog *ccd = COMBINE_CHANNELS_DIALOG(obj);
115     g_free(ccd->combination_matrix);
116     ccd->combination_matrix = NULL;
117     parent_class->destroy(obj);
118 }
119 
combine_channels_dialog_class_init(EffectDialogClass * klass)120 static void combine_channels_dialog_class_init(EffectDialogClass *klass)
121 {
122     parent_class = gtk_type_class(effect_dialog_get_type());
123     klass->apply = combine_channels_dialog_apply;
124     klass->setup = combine_channels_setup;
125     klass->target_changed = combine_channels_dialog_target_changed;
126     GTK_OBJECT_CLASS(klass)->destroy = combine_channels_destroy;
127 }
128 
combine_channels_dialog_init(CombineChannelsDialog * obj)129 static void combine_channels_dialog_init(CombineChannelsDialog *obj)
130 {
131 }
132 
combine_channels_dialog_get_type(void)133 GtkType combine_channels_dialog_get_type(void)
134 {
135     static GtkType id = 0;
136     if (!id) {
137         GtkTypeInfo info = {
138             "CombineChannelsDialog",
139             sizeof(CombineChannelsDialog),
140             sizeof(CombineChannelsDialogClass),
141             (GtkClassInitFunc)combine_channels_dialog_class_init,
142             (GtkObjectInitFunc)combine_channels_dialog_init
143         };
144         id = gtk_type_unique(effect_dialog_get_type(),&info);
145     }
146     return id;
147 }
148