11 //#include <sys/soundcard.h>
13 #include <sys/types.h>
22 #include "wx/statbox.h"
23 #include "wx/notebook.h"
24 #include "wx/spinctrl.h"
28 #include <jack/jack.h>
30 // linux : g++ -O3 -lm -ljack `wx-config --cflags --libs` ex2.cpp
31 // macosx: g++ karplus-strong.cpp -D__WXMAC__ -DWXMAKINGDLL -lwx_mac-2.4 -ljack -o karplus
38 //-------------------------------------------------------------------
39 // Generic min and max using gcc extensions
40 //-------------------------------------------------------------------
42 #define max(x,y) ((x)>?(y))
43 #define min(x,y) ((x)<?(y))
45 //abs(x) should be already predefined
49 //-------------------------------------------------------------------
50 // Generic min and max using c++ inline
51 //-------------------------------------------------------------------
53 inline int max (unsigned int a
, unsigned int b
) { return (a
>b
) ? a
: b
; }
54 inline int max (int a
, int b
) { return (a
>b
) ? a
: b
; }
56 inline long max (long a
, long b
) { return (a
>b
) ? a
: b
; }
57 inline long max (int a
, long b
) { return (a
>b
) ? a
: b
; }
58 inline long max (long a
, int b
) { return (a
>b
) ? a
: b
; }
60 inline float max (float a
, float b
) { return (a
>b
) ? a
: b
; }
61 inline float max (int a
, float b
) { return (a
>b
) ? a
: b
; }
62 inline float max (float a
, int b
) { return (a
>b
) ? a
: b
; }
63 inline float max (long a
, float b
) { return (a
>b
) ? a
: b
; }
64 inline float max (float a
, long b
) { return (a
>b
) ? a
: b
; }
66 inline double max (double a
, double b
) { return (a
>b
) ? a
: b
; }
67 inline double max (int a
, double b
) { return (a
>b
) ? a
: b
; }
68 inline double max (double a
, int b
) { return (a
>b
) ? a
: b
; }
69 inline double max (long a
, double b
) { return (a
>b
) ? a
: b
; }
70 inline double max (double a
, long b
) { return (a
>b
) ? a
: b
; }
71 inline double max (float a
, double b
) { return (a
>b
) ? a
: b
; }
72 inline double max (double a
, float b
) { return (a
>b
) ? a
: b
; }
75 inline int min (int a
, int b
) { return (a
<b
) ? a
: b
; }
77 inline long min (long a
, long b
) { return (a
<b
) ? a
: b
; }
78 inline long min (int a
, long b
) { return (a
<b
) ? a
: b
; }
79 inline long min (long a
, int b
) { return (a
<b
) ? a
: b
; }
81 inline float min (float a
, float b
) { return (a
<b
) ? a
: b
; }
82 inline float min (int a
, float b
) { return (a
<b
) ? a
: b
; }
83 inline float min (float a
, int b
) { return (a
<b
) ? a
: b
; }
84 inline float min (long a
, float b
) { return (a
<b
) ? a
: b
; }
85 inline float min (float a
, long b
) { return (a
<b
) ? a
: b
; }
87 inline double min (double a
, double b
) { return (a
<b
) ? a
: b
; }
88 inline double min (int a
, double b
) { return (a
<b
) ? a
: b
; }
89 inline double min (double a
, int b
) { return (a
<b
) ? a
: b
; }
90 inline double min (long a
, double b
) { return (a
<b
) ? a
: b
; }
91 inline double min (double a
, long b
) { return (a
<b
) ? a
: b
; }
92 inline double min (float a
, double b
) { return (a
<b
) ? a
: b
; }
93 inline double min (double a
, float b
) { return (a
<b
) ? a
: b
; }
97 // abs is now predefined
98 //template<typename T> T abs (T a) { return (a<T(0)) ? -a : a; }
101 inline int lsr (int x
, int n
) { return int(((unsigned int)x
) >> n
); }
103 inline int int2pow2 (int x
) { int r
=0; while ((1<<r
)<x
) r
++; return r
; }
106 /******************************************************************************
107 *******************************************************************************
111 *******************************************************************************
112 *******************************************************************************/
114 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); }
115 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((size_t)(calloc((nmemb*size)+15,sizeof(char)))+15 & ~15); }
120 /******************************************************************************
121 *******************************************************************************
125 *******************************************************************************
126 *******************************************************************************/
133 UI() : fStopped(false) {}
136 virtual void addButton(char* label
, float* zone
) = 0;
137 virtual void addToggleButton(char* label
, float* zone
) = 0;
138 virtual void addCheckButton(char* label
, float* zone
) = 0;
139 virtual void addVerticalSlider(char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
140 virtual void addHorizontalSlider(char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
141 virtual void addNumEntry(char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
143 virtual void openFrameBox(char* label
) = 0;
144 virtual void openTabBox(char* label
) = 0;
145 virtual void openHorizontalBox(char* label
) = 0;
146 virtual void openVerticalBox(char* label
) = 0;
147 virtual void closeBox() = 0;
149 virtual void run() {};
151 void stop() { fStopped
= true; }
152 bool stopped() { return fStopped
; }
157 /******************************************************************************
158 *******************************************************************************
162 *******************************************************************************
163 *******************************************************************************/
167 //----------------------------------------------------------------
168 // définition du processeur de signal
169 //----------------------------------------------------------------
176 virtual int getNumInputs() = 0;
177 virtual int getNumOutputs() = 0;
178 virtual void buildUserInterface(UI
* interface
) = 0;
179 virtual void init(int samplingRate
) = 0;
180 virtual void compute(int len
, float** inputs
, float** outputs
) = 0;
191 /******************************************************************************
192 *******************************************************************************
196 *******************************************************************************
197 *******************************************************************************/
201 //----------------------------------------------------------------------------
202 // number of input and output channels
203 //----------------------------------------------------------------------------
209 //----------------------------------------------------------------------------
211 //----------------------------------------------------------------------------
213 jack_port_t
*input_ports
[256];
214 jack_port_t
*output_ports
[256];
216 //----------------------------------------------------------------------------
217 // tables of noninterleaved input and output channels for FAUST
218 //----------------------------------------------------------------------------
220 float* gInChannel
[256];
221 float* gOutChannel
[256];
224 //----------------------------------------------------------------------------
226 //----------------------------------------------------------------------------
228 int srate(jack_nframes_t nframes
, void *arg
)
230 printf("the sample rate is now %lu/sec\n", nframes
);
234 void jack_shutdown(void *arg
)
239 int process (jack_nframes_t nframes
, void *arg
)
241 // ATTENTION: en vectoriel il faut s'assurer que gInChannel et gOutChannel soit align�s sur une fronti�re de 128 bits
243 for (int i
= 0; i
< gNumInChans
; i
++) {
244 gInChannel
[i
] = (float *)jack_port_get_buffer(input_ports
[i
], nframes
);
246 for (int i
= 0; i
< gNumOutChans
; i
++) {
247 gOutChannel
[i
] = (float *)jack_port_get_buffer(output_ports
[i
], nframes
);
249 DSP
.compute(nframes
, gInChannel
, gOutChannel
);
254 /******************************************************************************
255 *******************************************************************************
257 WXWINDOWS USER INTERFACE
259 *******************************************************************************
260 *******************************************************************************/
263 // les modes d'insertion
265 #define kNormalState 0
266 #define kNotebookState 1
267 #define kAutoPageState 2
271 #define kFlag wxALL|wxGROW
274 // faustButton : a wxButton for FAUST.
275 class faustButton
: public wxButton
279 faustButton(wxWindow
* parent
, const wxString
& label
, float* zone
)
280 : wxButton(parent
, -1, label
, wxPoint(-1, -1)), fZone(zone
)
286 void clickdown (wxCommandEvent
& ev
) { *fZone
= 1.0; /*printf("click down : zone (at %p) = %f\n", fZone, *fZone); ev.Skip();*/}
287 void clickup (wxCommandEvent
& ev
) { *fZone
= 0.0; /*printf("click up : zone (at %p) = %f\n", fZone, *fZone);ev.Skip();*/ }
289 void clickdown (wxCommandEvent
& ev
) { *fZone
= 1.0; /*printf("click down : zone (at %p) = %f\n", fZone, *fZone);*/ ev
.Skip();}
290 void clickup (wxCommandEvent
& ev
) { *fZone
= 0.0; /*printf("click up : zone (at %p) = %f\n", fZone, *fZone);*/ ev
.Skip(); }
293 DECLARE_EVENT_TABLE()
296 BEGIN_EVENT_TABLE(faustButton
, wxButton
)
297 EVT_LEFT_DOWN(faustButton::clickdown
)
298 EVT_LEFT_UP(faustButton::clickup
)
302 class faustCheckBox
: public wxCheckBox
306 faustCheckBox(wxWindow
* parent
, const wxString
& label
, float* zone
)
307 : wxCheckBox(parent
, -1, label
, wxPoint(-1, -1)), fZone(zone
)
312 void toggle (wxCommandEvent
& ev
) {
313 *fZone
= (ev
.IsChecked()) ? 1.0 : 0.0;
314 //printf("toogle : zone (at %p) = %f\n", fZone, *fZone);
318 DECLARE_EVENT_TABLE()
321 BEGIN_EVENT_TABLE(faustCheckBox
, wxCheckBox
)
322 EVT_CHECKBOX(-1, faustCheckBox::toggle
)
326 class faustHorizontalSlider
: public wxSlider
331 faustHorizontalSlider(wxWindow
* parent
, float* zone
, float init
, float min
, float max
, float step
)
332 : wxSlider(parent
, -1, int(init
/step
), int(min
/step
), int(max
/step
), wxDefaultPosition
, wxSize(120,30), wxSL_HORIZONTAL
), fStep(step
), fZone(zone
)
337 void update (wxCommandEvent
& ev
) {
338 *fZone
= GetValue()*fStep
;
339 //printf("horizontal slider update : zone (at %p) = %f\n", fZone, *fZone);
343 DECLARE_EVENT_TABLE()
346 BEGIN_EVENT_TABLE(faustHorizontalSlider
, wxSlider
)
347 EVT_SLIDER (-1, faustHorizontalSlider::update
)
351 class faustVerticalSlider
: public wxSlider
356 faustVerticalSlider(wxWindow
* parent
, float* zone
, float init
, float min
, float max
, float step
)
357 : wxSlider(parent
, -1, int((max
+min
-init
)/step
), int(min
/step
), int(max
/step
), wxDefaultPosition
, wxSize(30,120), wxSL_VERTICAL
), fStep(step
), fZone(zone
)
362 void update (wxCommandEvent
& ev
) {
363 *fZone
= (GetMin()+GetMax()-GetValue())*fStep
;
364 //printf("vertical slider update : zone (at %p) = %f\n", fZone, *fZone);
368 DECLARE_EVENT_TABLE()
371 BEGIN_EVENT_TABLE(faustVerticalSlider
, wxSlider
)
372 EVT_SLIDER (-1, faustVerticalSlider::update
)
376 //--------------------------------
377 // faustSpinCtrl* b = new faustSpinCtrl(topPanel(), zone, init, min, max, step);
378 // wxSpinCtrl* b = new wxSpinCtrl( topPanel(), -1, "", wxPoint(200, 160), wxSize(80, -1) );
379 // b->SetRange(int(min),int(max));
380 // b->SetValue(int(init));
383 class faustSpinCtrl
: public wxSpinCtrl
388 faustSpinCtrl(wxWindow
* parent
, float* zone
, float init
, float min
, float max
, float step
)
389 : wxSpinCtrl(parent
), fStep(step
), fZone(zone
)
391 SetRange(int(min
),int(max
));
396 void update (wxCommandEvent
& ev
) { *fZone
= GetValue(); printf("spin ctrl update : zone (at %p) = %f\n", fZone
, *fZone
); }
399 DECLARE_EVENT_TABLE()
402 BEGIN_EVENT_TABLE(faustSpinCtrl
, wxSpinCtrl
)
403 EVT_SPINCTRL (-1, faustSpinCtrl::update
)
408 class WXUI
: public UI
// user interface
414 wxWindow
* const fPanel
;
415 wxSizer
* const fSizer
;
418 State (int t
, wxWindow
* p
, wxSizer
* z
) : fType(t
), fPanel(p
), fSizer(z
) {}
419 int type() const { return fType
; }
420 wxWindow
* panel() const { return fPanel
; }
421 wxSizer
* sizer() const { return fSizer
; }
428 // gestion de l'etat courant du constructeur
430 void push (int t
, wxWindow
* p
, wxSizer
* z
)
432 printf("push %d of %d, %p, %p\n", lState
.size(), t
, p
, z
);
433 lState
.push(State(t
,p
,z
));
436 int topType() { return lState
.top().type(); }
437 wxWindow
* topPanel() { return lState
.top().panel(); }
438 wxSizer
* topSizer() { return lState
.top().sizer(); }
442 printf("pop %d", lState
.size()-1);
447 void openAutoPage(char* label
)
449 if (topType() == kNotebookState
) {
451 if (!label
) label
= "";
453 wxNotebook
* nb
= (wxNotebook
*) topPanel();
454 wxPanel
* p
= new wxPanel( nb
, -1 );
455 wxBoxSizer
* z
= new wxBoxSizer( wxVERTICAL
);
457 nb
->AddPage(p
, label
);
458 p
->SetAutoLayout(TRUE
);
461 push(kAutoPageState
, p
, z
);
467 if (topType() == kAutoPageState
) pop();
470 void openOrientedBox(char* label
, int orientation
)
474 wxSizer
* z
= (label
== 0) ? new wxBoxSizer(orientation
)
475 : new wxStaticBoxSizer(new wxStaticBox(topPanel(), -1, label
), orientation
);
477 topSizer()->Add(z
, 1, kFlag
, kBorder
);
478 push(kNormalState
, topPanel(), z
);
488 void openFrame(wxFrame
* f
)
491 fSizer
= new wxBoxSizer(wxVERTICAL
);
492 frame
->SetSizer(fSizer
);
493 push(kNormalState
, frame
, fSizer
);
496 wxFrame
* closeFrame()
499 fSizer
->SetSizeHints(frame
);
503 virtual void openHorizontalBox(char* label
) { openOrientedBox(label
, wxHORIZONTAL
); }
504 virtual void openVerticalBox(char* label
) { openOrientedBox(label
, wxVERTICAL
); }
506 virtual void openTabBox(char* label
)
510 wxNotebook
* nb
= new wxNotebook( topPanel(), -1 );
511 wxNotebookSizer
* z
= new wxNotebookSizer( nb
);
513 topSizer()->Add(z
, 1, kFlag
, kBorder
);
514 push(kNotebookState
, nb
, z
);
517 virtual void closeBox()
523 //--------------------------------- les elements ------------------------------------------
525 virtual void addButton(char* label
, float* zone
)
528 faustButton
* b
= new faustButton(topPanel(), label
, zone
);
529 topSizer()->Add(b
, kProp
, kFlag
, kBorder
);
533 virtual void addCheckButton(char* label
, float* zone
)
536 faustCheckBox
* b
= new faustCheckBox(topPanel(), label
, zone
);
537 topSizer()->Add(b
, kProp
, kFlag
, kBorder
);
541 virtual void addVerticalSlider(char* label
, float* zone
, float init
, float min
, float max
, float step
)
545 wxSizer
* z
= new wxStaticBoxSizer(new wxStaticBox(topPanel(), -1, label
), wxHORIZONTAL
);
546 topSizer()->Add(z
, 1, kFlag
, kBorder
);
547 faustVerticalSlider
* b
= new faustVerticalSlider(topPanel(), zone
, init
, min
, max
, step
);
548 b
->SetToolTip(label
);
549 z
->Add(b
, 1, kFlag
|wxALIGN_CENTER_VERTICAL
, kBorder
);
551 faustVerticalSlider
* b
= new faustVerticalSlider(topPanel(), zone
, init
, min
, max
, step
);
552 topSizer()->Add(b
, kProp
, kFlag
, kBorder
);
557 virtual void addHorizontalSlider(char* label
, float* zone
, float init
, float min
, float max
, float step
)
561 wxSizer
* z
= new wxStaticBoxSizer(new wxStaticBox(topPanel(), -1, label
), wxVERTICAL
);
562 topSizer()->Add(z
, 1, kFlag
, kBorder
);
563 faustHorizontalSlider
* b
= new faustHorizontalSlider(topPanel(), zone
, init
, min
, max
, step
);
564 b
->SetToolTip(label
);
565 z
->Add(b
, 1, kFlag
|wxALIGN_CENTER_HORIZONTAL
, kBorder
);
567 faustHorizontalSlider
* b
= new faustHorizontalSlider(topPanel(), zone
, init
, min
, max
, step
);
568 topSizer()->Add(b
, kProp
, kFlag
, kBorder
);
573 virtual void addToggleButton(char* label
, float* zone
) {}
574 virtual void addNumEntry(char* label
, float* zone
, float init
, float min
, float max
, float step
)
578 wxSizer
* z
= new wxStaticBoxSizer(new wxStaticBox(topPanel(), -1, label
), wxVERTICAL
);
579 topSizer()->Add(z
, 0, kFlag
, kBorder
);
580 faustSpinCtrl
* b
= new faustSpinCtrl(topPanel(), zone
, init
, min
, max
, step
);
581 // wxSpinCtrl* b = new wxSpinCtrl( topPanel(), -1, "", wxPoint(200, 160), wxSize(80, -1) );
582 // b->SetRange(int(min),int(max));
583 // b->SetValue(int(init));
584 b
->SetToolTip(label
);
585 z
->Add(b
, 0, kFlag
, kBorder
);
587 faustSpinCtrl
* b
= new faustSpinCtrl(topPanel(), zone
, init
, min
, max
, step
);
588 // wxSpinCtrl* b = new wxSpinCtrl( topPanel(), -1, "", wxPoint(200, 160), wxSize(80, -1) );
589 // b->SetRange(int(min),int(max));
590 // b->SetValue(int(init));
591 topSizer()->Add(b
, kProp
, kFlag
, kBorder
);
595 virtual void openFrameBox(char* label
) {}
600 /******************************************************************************
601 *******************************************************************************
605 *******************************************************************************
606 *******************************************************************************/
609 enum { ID_QUIT
=1, ID_ABOUT
};
612 class MyFrame
: public wxFrame
615 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
616 : wxFrame(0, -1, title
, pos
, size
)
618 wxMenu
* m
= new wxMenu
;
619 m
->Append(ID_ABOUT
, "&About...");
620 m
->AppendSeparator();
621 m
->Append(ID_QUIT
, "E&xit");
623 wxMenuBar
* b
= new wxMenuBar
;
624 b
->Append(m
, "&File");
627 SetStatusText("hello...");
630 void OnQuit(wxCommandEvent
& event
)
635 void OnAbout(wxCommandEvent
& event
)
637 wxMessageBox("message 1", "message 2", wxOK
|wxICON_INFORMATION
);
641 DECLARE_EVENT_TABLE()
645 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
646 EVT_MENU(ID_QUIT
, MyFrame::OnQuit
)
647 EVT_MENU(ID_ABOUT
, MyFrame::OnAbout
)
652 /******************************************************************************
653 *******************************************************************************
655 WXWINDOWS MAIN APPLICATION
657 *******************************************************************************
658 *******************************************************************************/
660 // Scan Command Line Arguments
662 class MyApp
: public wxApp
664 jack_client_t
* client
;
666 char** physicalInPorts
;
667 char** physicalOutPorts
;
669 virtual bool OnInit()
671 MyFrame
* frame
= new MyFrame(argv
[0], wxPoint(50,50), wxSize(-1, -1));
673 wxMenu* m = new wxMenu;
674 m->Append(ID_ABOUT, "&About...");
675 m->AppendSeparator();
676 m->Append(ID_QUIT, "E&xit");
678 wxMenuBar* b = new wxMenuBar;
679 b->Append(m, "&File");
681 frame->SetMenuBar(b);
682 frame->CreateStatusBar();
683 frame->SetStatusText("Faust dsp...");
685 WXUI
* ui
= new WXUI();
686 ui
->openFrame(frame
);
687 DSP
.buildUserInterface((UI
*)ui
);
693 snprintf(jackname
, 256, "faust_%s", basename(argv
[0]));
695 if ((client
= jack_client_open(jackname
, JackNullOption
, NULL
)) == 0) {
696 fprintf(stderr
, "jack server not running?\n");
700 jack_set_process_callback(client
, process
, 0);
701 jack_set_sample_rate_callback(client
, srate
, 0);
702 jack_on_shutdown(client
, jack_shutdown
, 0);
704 gNumInChans
= DSP
.getNumInputs();
705 gNumOutChans
= DSP
.getNumOutputs();
707 for (int i
= 0; i
< gNumInChans
; i
++) {
709 snprintf(buf
, 256, "in_%d", i
);
710 input_ports
[i
] = jack_port_register(client
, buf
, JACK_DEFAULT_AUDIO_TYPE
, JackPortIsInput
, 0);
712 for (int i
= 0; i
< gNumOutChans
; i
++) {
714 snprintf(buf
, 256, "out_%d", i
);
715 output_ports
[i
] = jack_port_register(client
, buf
, JACK_DEFAULT_AUDIO_TYPE
, JackPortIsOutput
, 0);
718 DSP
.init(jack_get_sample_rate(client
));
720 physicalInPorts
= (char **)jack_get_ports(client
, NULL
, NULL
, JackPortIsPhysical
|JackPortIsInput
);
721 physicalOutPorts
= (char **)jack_get_ports(client
, NULL
, NULL
, JackPortIsPhysical
|JackPortIsOutput
);
723 if (jack_activate(client
)) {
724 fprintf(stderr
, "cannot activate client");
728 if (physicalOutPorts
!= NULL
) {
729 for (int i
= 0; i
< gNumInChans
&& physicalOutPorts
[i
]; i
++) {
730 jack_connect(client
, physicalOutPorts
[i
], jack_port_name(input_ports
[i
]));
732 free(physicalOutPorts
);
735 if (physicalInPorts
!= NULL
) {
736 for (int i
= 0; i
< gNumOutChans
&& physicalInPorts
[i
]; i
++) {
737 jack_connect(client
, jack_port_name(output_ports
[i
]), physicalInPorts
[i
]);
739 free(physicalInPorts
);
747 jack_deactivate(client
);
749 for (int i
= 0; i
< gNumInChans
; i
++) {
750 jack_port_unregister(client
, input_ports
[i
]);
752 for (int i
= 0; i
< gNumOutChans
; i
++) {
753 jack_port_unregister(client
, output_ports
[i
]);
756 jack_client_close(client
);