12 #include <sys/types.h>
21 #include "wx/statbox.h"
22 #include "wx/notebook.h"
23 #include "wx/spinctrl.h"
25 #include <portaudio.h>
27 // linux : g++ -O3 -lm -lportaudio `wx-config --cflags --libs` ex2.cpp
28 // macosx: g++ karplus-strong.cpp -D__WXMAC__ -DWXMAKINGDLL -lwx_mac-2.4 -ljack -o karplus
35 //-------------------------------------------------------------------
36 // Generic min and max using gcc extensions
37 //-------------------------------------------------------------------
39 #define max(x,y) ((x)>?(y))
40 #define min(x,y) ((x)<?(y))
42 //abs(x) should be already predefined
46 //-------------------------------------------------------------------
47 // Generic min and max using c++ inline
48 //-------------------------------------------------------------------
50 inline int max (unsigned int a
, unsigned int b
) { return (a
>b
) ? a
: b
; }
51 inline int max (int a
, int b
) { return (a
>b
) ? a
: b
; }
53 inline long max (long a
, long b
) { return (a
>b
) ? a
: b
; }
54 inline long max (int a
, long b
) { return (a
>b
) ? a
: b
; }
55 inline long max (long a
, int b
) { return (a
>b
) ? a
: b
; }
57 inline float max (float a
, float b
) { return (a
>b
) ? a
: b
; }
58 inline float max (int a
, float b
) { return (a
>b
) ? a
: b
; }
59 inline float max (float a
, int b
) { return (a
>b
) ? a
: b
; }
60 inline float max (long a
, float b
) { return (a
>b
) ? a
: b
; }
61 inline float max (float a
, long b
) { return (a
>b
) ? a
: b
; }
63 inline double max (double a
, double b
) { return (a
>b
) ? a
: b
; }
64 inline double max (int a
, double b
) { return (a
>b
) ? a
: b
; }
65 inline double max (double a
, int b
) { return (a
>b
) ? a
: b
; }
66 inline double max (long a
, double b
) { return (a
>b
) ? a
: b
; }
67 inline double max (double a
, long b
) { return (a
>b
) ? a
: b
; }
68 inline double max (float a
, double b
) { return (a
>b
) ? a
: b
; }
69 inline double max (double a
, float b
) { return (a
>b
) ? a
: b
; }
72 inline int min (int a
, int b
) { return (a
<b
) ? a
: b
; }
74 inline long min (long a
, long b
) { return (a
<b
) ? a
: b
; }
75 inline long min (int a
, long b
) { return (a
<b
) ? a
: b
; }
76 inline long min (long a
, int b
) { return (a
<b
) ? a
: b
; }
78 inline float min (float a
, float b
) { return (a
<b
) ? a
: b
; }
79 inline float min (int a
, float b
) { return (a
<b
) ? a
: b
; }
80 inline float min (float a
, int b
) { return (a
<b
) ? a
: b
; }
81 inline float min (long a
, float b
) { return (a
<b
) ? a
: b
; }
82 inline float min (float a
, long b
) { return (a
<b
) ? a
: b
; }
84 inline double min (double a
, double b
) { return (a
<b
) ? a
: b
; }
85 inline double min (int a
, double b
) { return (a
<b
) ? a
: b
; }
86 inline double min (double a
, int b
) { return (a
<b
) ? a
: b
; }
87 inline double min (long a
, double b
) { return (a
<b
) ? a
: b
; }
88 inline double min (double a
, long b
) { return (a
<b
) ? a
: b
; }
89 inline double min (float a
, double b
) { return (a
<b
) ? a
: b
; }
90 inline double min (double a
, float b
) { return (a
<b
) ? a
: b
; }
94 // abs is now predefined
95 //template<typename T> T abs (T a) { return (a<T(0)) ? -a : a; }
98 inline int lsr (int x
, int n
) { return int(((unsigned int)x
) >> n
); }
100 inline int int2pow2 (int x
) { int r
=0; while ((1<<r
)<x
) r
++; return r
; }
104 /******************************************************************************
105 *******************************************************************************
109 *******************************************************************************
110 *******************************************************************************/
117 /******************************************************************************
118 *******************************************************************************
122 *******************************************************************************
123 *******************************************************************************/
130 UI() : fStopped(false) {}
133 virtual void addButton(char* label
, float* zone
) = 0;
134 virtual void addToggleButton(char* label
, float* zone
) = 0;
135 virtual void addCheckButton(char* label
, float* zone
) = 0;
136 virtual void addVerticalSlider(char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
137 virtual void addHorizontalSlider(char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
138 virtual void addNumEntry(char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
140 virtual void openFrameBox(char* label
) = 0;
141 virtual void openTabBox(char* label
) = 0;
142 virtual void openHorizontalBox(char* label
) = 0;
143 virtual void openVerticalBox(char* label
) = 0;
144 virtual void closeBox() = 0;
146 virtual void run() {};
148 void stop() { fStopped
= true; }
149 bool stopped() { return fStopped
; }
154 /******************************************************************************
155 *******************************************************************************
159 *******************************************************************************
160 *******************************************************************************/
164 //----------------------------------------------------------------
165 // d�finition du processeur de signal
166 //----------------------------------------------------------------
173 virtual int getNumInputs() = 0;
174 virtual int getNumOutputs() = 0;
175 virtual void buildUserInterface(UI
* interface
) = 0;
176 virtual void init(int samplingRate
) = 0;
177 virtual void compute(int len
, float** inputs
, float** outputs
) = 0;
189 /******************************************************************************
190 *******************************************************************************
194 *******************************************************************************
195 *******************************************************************************/
199 //----------------------------------------------------------------------------
200 // number of physical input and output channels of the PA device
201 //----------------------------------------------------------------------------
207 //----------------------------------------------------------------------------
208 // tables of noninterleaved input and output channels for FAUST
209 //----------------------------------------------------------------------------
211 float* gInChannel
[256];
212 float* gOutChannel
[256];
215 //----------------------------------------------------------------------------
216 // allocated the noninterleaved input and output channels for FAUST
217 //----------------------------------------------------------------------------
219 void allocChannels (int size
, int numInChan
, int numOutChan
)
222 assert (numInChan
< 256);
223 assert (numOutChan
< 256);
226 for (int i
= 0; i
< numInChan
; i
++) {
227 gInChannel
[i
] = (float*) calloc (size
, sizeof(float));
228 for (int j
= 0; j
< size
; j
++) {
229 gInChannel
[i
][j
] = 0.0;
233 for (int i
= 0; i
< numOutChan
; i
++) {
234 gOutChannel
[i
] = (float*) calloc (size
, sizeof(float));
235 for (int j
= 0; j
< size
; j
++) {
236 gOutChannel
[i
][j
] = 0.0;
241 //----------------------------------------------------------------------------
242 // Port Audio Callback
243 //----------------------------------------------------------------------------
245 static int audioCallback(const void *ibuf
, void *obuf
, unsigned long frames
, const PaStreamCallbackTimeInfo
*, PaStreamCallbackFlags
, void *)
247 float* fInputBuffer
= (float*) ibuf
;
248 float* fOutputBuffer
= (float*) obuf
;
250 // split input samples
251 for (unsigned long s
= 0; s
< frames
; s
++) {
252 for (int c
= 0; c
< gDevNumInChans
; c
++) {
253 gInChannel
[c
][s
] = fInputBuffer
[c
+ s
*gDevNumInChans
];
258 DSP
.compute(frames
, gInChannel
, gOutChannel
);
260 // merge output samples
261 for (unsigned long s
= 0; s
< frames
; s
++) {
262 for (int c
= 0; c
< gDevNumOutChans
; c
++) {
263 fOutputBuffer
[c
+ s
*gDevNumOutChans
] = gOutChannel
[c
][s
];
273 /******************************************************************************
274 *******************************************************************************
276 WXWINDOWS USER INTERFACE
278 *******************************************************************************
279 *******************************************************************************/
282 // les modes d'insertion
284 #define kNormalState 0
285 #define kNotebookState 1
286 #define kAutoPageState 2
290 #define kFlag wxALL|wxGROW
293 // faustButton : a wxButton for FAUST.
294 class faustButton
: public wxButton
298 faustButton(wxWindow
* parent
, const wxString
& label
, float* zone
)
299 : wxButton(parent
, -1, label
, wxPoint(-1, -1)), fZone(zone
)
305 void clickdown (wxCommandEvent
& ev
) { *fZone
= 1.0; /*printf("click down : zone (at %p) = %f\n", fZone, *fZone); ev.Skip();*/}
306 void clickup (wxCommandEvent
& ev
) { *fZone
= 0.0; /*printf("click up : zone (at %p) = %f\n", fZone, *fZone);ev.Skip();*/ }
308 void clickdown (wxCommandEvent
& ev
) { *fZone
= 1.0; /*printf("click down : zone (at %p) = %f\n", fZone, *fZone);*/ ev
.Skip();}
309 void clickup (wxCommandEvent
& ev
) { *fZone
= 0.0; /*printf("click up : zone (at %p) = %f\n", fZone, *fZone);*/ ev
.Skip(); }
312 DECLARE_EVENT_TABLE()
315 BEGIN_EVENT_TABLE(faustButton
, wxButton
)
316 EVT_LEFT_DOWN(faustButton::clickdown
)
317 EVT_LEFT_UP(faustButton::clickup
)
321 class faustCheckBox
: public wxCheckBox
325 faustCheckBox(wxWindow
* parent
, const wxString
& label
, float* zone
)
326 : wxCheckBox(parent
, -1, label
, wxPoint(-1, -1)), fZone(zone
)
331 void toggle (wxCommandEvent
& ev
) {
332 *fZone
= (ev
.IsChecked()) ? 1.0 : 0.0;
333 //printf("toogle : zone (at %p) = %f\n", fZone, *fZone);
337 DECLARE_EVENT_TABLE()
340 BEGIN_EVENT_TABLE(faustCheckBox
, wxCheckBox
)
341 EVT_CHECKBOX(-1, faustCheckBox::toggle
)
345 class faustHorizontalSlider
: public wxSlider
350 faustHorizontalSlider(wxWindow
* parent
, float* zone
, float init
, float min
, float max
, float step
)
351 : wxSlider(parent
, -1, int(init
/step
), int(min
/step
), int(max
/step
), wxDefaultPosition
, wxSize(120,30), wxSL_HORIZONTAL
), fStep(step
), fZone(zone
)
356 void update (wxCommandEvent
& ev
) {
357 *fZone
= GetValue()*fStep
;
358 //printf("horizontal slider update : zone (at %p) = %f\n", fZone, *fZone);
362 DECLARE_EVENT_TABLE()
365 BEGIN_EVENT_TABLE(faustHorizontalSlider
, wxSlider
)
366 EVT_SLIDER (-1, faustHorizontalSlider::update
)
370 class faustVerticalSlider
: public wxSlider
375 faustVerticalSlider(wxWindow
* parent
, float* zone
, float init
, float min
, float max
, float step
)
376 : wxSlider(parent
, -1, int((max
+min
-init
)/step
), int(min
/step
), int(max
/step
), wxDefaultPosition
, wxSize(30,120), wxSL_VERTICAL
), fStep(step
), fZone(zone
)
381 void update (wxCommandEvent
& ev
) {
382 *fZone
= (GetMin()+GetMax()-GetValue())*fStep
;
383 //printf("vertical slider update : zone (at %p) = %f\n", fZone, *fZone);
387 DECLARE_EVENT_TABLE()
390 BEGIN_EVENT_TABLE(faustVerticalSlider
, wxSlider
)
391 EVT_SLIDER (-1, faustVerticalSlider::update
)
395 //--------------------------------
396 // faustSpinCtrl* b = new faustSpinCtrl(topPanel(), zone, init, min, max, step);
397 // wxSpinCtrl* b = new wxSpinCtrl( topPanel(), -1, "", wxPoint(200, 160), wxSize(80, -1) );
398 // b->SetRange(int(min),int(max));
399 // b->SetValue(int(init));
402 class faustSpinCtrl
: public wxSpinCtrl
407 faustSpinCtrl(wxWindow
* parent
, float* zone
, float init
, float min
, float max
, float step
)
408 : wxSpinCtrl(parent
), fStep(step
), fZone(zone
)
410 SetRange(int(min
),int(max
));
415 void update (wxCommandEvent
& ev
) { *fZone
= GetValue(); printf("spin ctrl update : zone (at %p) = %f\n", fZone
, *fZone
); }
418 DECLARE_EVENT_TABLE()
421 BEGIN_EVENT_TABLE(faustSpinCtrl
, wxSpinCtrl
)
422 EVT_SPINCTRL (-1, faustSpinCtrl::update
)
427 class WXUI
: public UI
// user interface
433 wxWindow
* const fPanel
;
434 wxSizer
* const fSizer
;
437 State (int t
, wxWindow
* p
, wxSizer
* z
) : fType(t
), fPanel(p
), fSizer(z
) {}
438 int type() const { return fType
; }
439 wxWindow
* panel() const { return fPanel
; }
440 wxSizer
* sizer() const { return fSizer
; }
447 // gestion de l'etat courant du constructeur
449 void push (int t
, wxWindow
* p
, wxSizer
* z
)
451 printf("push %d of %d, %p, %p\n", lState
.size(), t
, p
, z
);
452 lState
.push(State(t
,p
,z
));
455 int topType() { return lState
.top().type(); }
456 wxWindow
* topPanel() { return lState
.top().panel(); }
457 wxSizer
* topSizer() { return lState
.top().sizer(); }
461 printf("pop %d", lState
.size()-1);
466 void openAutoPage(char* label
)
468 if (topType() == kNotebookState
) {
470 if (!label
) label
= "";
472 wxNotebook
* nb
= (wxNotebook
*) topPanel();
473 wxPanel
* p
= new wxPanel( nb
, -1 );
474 wxBoxSizer
* z
= new wxBoxSizer( wxVERTICAL
);
476 nb
->AddPage(p
, label
);
477 p
->SetAutoLayout(TRUE
);
480 push(kAutoPageState
, p
, z
);
486 if (topType() == kAutoPageState
) pop();
489 void openOrientedBox(char* label
, int orientation
)
493 wxSizer
* z
= (label
== 0) ? new wxBoxSizer(orientation
)
494 : new wxStaticBoxSizer(new wxStaticBox(topPanel(), -1, label
), orientation
);
496 topSizer()->Add(z
, 1, kFlag
, kBorder
);
497 push(kNormalState
, topPanel(), z
);
507 void openFrame(wxFrame
* f
)
510 fSizer
= new wxBoxSizer(wxVERTICAL
);
511 frame
->SetSizer(fSizer
);
512 push(kNormalState
, frame
, fSizer
);
515 wxFrame
* closeFrame()
518 fSizer
->SetSizeHints(frame
);
522 virtual void openHorizontalBox(char* label
) { openOrientedBox(label
, wxHORIZONTAL
); }
523 virtual void openVerticalBox(char* label
) { openOrientedBox(label
, wxVERTICAL
); }
525 virtual void openTabBox(char* label
)
529 wxNotebook
* nb
= new wxNotebook( topPanel(), -1 );
530 wxNotebookSizer
* z
= new wxNotebookSizer( nb
);
532 topSizer()->Add(z
, 1, kFlag
, kBorder
);
533 push(kNotebookState
, nb
, z
);
536 virtual void closeBox()
542 //--------------------------------- les elements ------------------------------------------
544 virtual void addButton(char* label
, float* zone
)
547 faustButton
* b
= new faustButton(topPanel(), label
, zone
);
548 topSizer()->Add(b
, kProp
, kFlag
, kBorder
);
552 virtual void addCheckButton(char* label
, float* zone
)
555 faustCheckBox
* b
= new faustCheckBox(topPanel(), label
, zone
);
556 topSizer()->Add(b
, kProp
, kFlag
, kBorder
);
560 virtual void addVerticalSlider(char* label
, float* zone
, float init
, float min
, float max
, float step
)
564 wxSizer
* z
= new wxStaticBoxSizer(new wxStaticBox(topPanel(), -1, label
), wxHORIZONTAL
);
565 topSizer()->Add(z
, 1, kFlag
, kBorder
);
566 faustVerticalSlider
* b
= new faustVerticalSlider(topPanel(), zone
, init
, min
, max
, step
);
567 b
->SetToolTip(label
);
568 z
->Add(b
, 1, kFlag
|wxALIGN_CENTER_VERTICAL
, kBorder
);
570 faustVerticalSlider
* b
= new faustVerticalSlider(topPanel(), zone
, init
, min
, max
, step
);
571 topSizer()->Add(b
, kProp
, kFlag
, kBorder
);
576 virtual void addHorizontalSlider(char* label
, float* zone
, float init
, float min
, float max
, float step
)
580 wxSizer
* z
= new wxStaticBoxSizer(new wxStaticBox(topPanel(), -1, label
), wxVERTICAL
);
581 topSizer()->Add(z
, 1, kFlag
, kBorder
);
582 faustHorizontalSlider
* b
= new faustHorizontalSlider(topPanel(), zone
, init
, min
, max
, step
);
583 b
->SetToolTip(label
);
584 z
->Add(b
, 1, kFlag
|wxALIGN_CENTER_HORIZONTAL
, kBorder
);
586 faustHorizontalSlider
* b
= new faustHorizontalSlider(topPanel(), zone
, init
, min
, max
, step
);
587 topSizer()->Add(b
, kProp
, kFlag
, kBorder
);
592 virtual void addToggleButton(char* label
, float* zone
) {}
593 virtual void addNumEntry(char* label
, float* zone
, float init
, float min
, float max
, float step
)
597 wxSizer
* z
= new wxStaticBoxSizer(new wxStaticBox(topPanel(), -1, label
), wxVERTICAL
);
598 topSizer()->Add(z
, 0, kFlag
, kBorder
);
599 faustSpinCtrl
* b
= new faustSpinCtrl(topPanel(), zone
, init
, min
, max
, step
);
600 // wxSpinCtrl* b = new wxSpinCtrl( topPanel(), -1, "", wxPoint(200, 160), wxSize(80, -1) );
601 // b->SetRange(int(min),int(max));
602 // b->SetValue(int(init));
603 b
->SetToolTip(label
);
604 z
->Add(b
, 0, kFlag
, kBorder
);
606 faustSpinCtrl
* b
= new faustSpinCtrl(topPanel(), zone
, init
, min
, max
, step
);
607 // wxSpinCtrl* b = new wxSpinCtrl( topPanel(), -1, "", wxPoint(200, 160), wxSize(80, -1) );
608 // b->SetRange(int(min),int(max));
609 // b->SetValue(int(init));
610 topSizer()->Add(b
, kProp
, kFlag
, kBorder
);
614 virtual void openFrameBox(char* label
) {}
619 /******************************************************************************
620 *******************************************************************************
624 *******************************************************************************
625 *******************************************************************************/
628 enum { ID_QUIT
=1, ID_ABOUT
};
631 class MyFrame
: public wxFrame
634 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
635 : wxFrame(0, -1, title
, pos
, size
)
637 wxMenu
* m
= new wxMenu
;
638 m
->Append(ID_ABOUT
, "&About...");
639 m
->AppendSeparator();
640 m
->Append(ID_QUIT
, "E&xit");
642 wxMenuBar
* b
= new wxMenuBar
;
643 b
->Append(m
, "&File");
646 SetStatusText("hello...");
649 void OnQuit(wxCommandEvent
& event
)
654 void OnAbout(wxCommandEvent
& event
)
656 wxMessageBox("message 1", "message 2", wxOK
|wxICON_INFORMATION
);
660 DECLARE_EVENT_TABLE()
664 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
665 EVT_MENU(ID_QUIT
, MyFrame::OnQuit
)
666 EVT_MENU(ID_ABOUT
, MyFrame::OnAbout
)
671 /******************************************************************************
672 *******************************************************************************
674 WXWINDOWS MAIN APPLICATION
676 *******************************************************************************
677 *******************************************************************************/
679 // Scan Command Line Arguments
681 class MyApp
: public wxApp
685 long lopt (char *name
, long def
)
688 for (i
=0; argv
[i
]; i
++) if (!strcmp(argv
[i
], name
)) return atoi(argv
[i
+1]);
692 void pa_error(int err
)
694 if (err
!= paNoError
) {
695 printf( "PortAudio error: %s\n", Pa_GetErrorText( err
) );
700 virtual bool OnInit()
702 MyFrame
* frame
= new MyFrame(argv
[0], wxPoint(50,50), wxSize(-1, -1));
704 wxMenu* m = new wxMenu;
705 m->Append(ID_ABOUT, "&About...");
706 m->AppendSeparator();
707 m->Append(ID_QUIT, "E&xit");
709 wxMenuBar* b = new wxMenuBar;
710 b->Append(m, "&File");
712 frame->SetMenuBar(b);
713 frame->CreateStatusBar();
714 frame->SetStatusText("Faust dsp...");
716 WXUI
* ui
= new WXUI();
717 ui
->openFrame(frame
);
718 DSP
.buildUserInterface((UI
*)ui
);
724 // initialize portaudio
725 pa_error(Pa_Initialize());
727 const PaDeviceInfo
* idev
= Pa_GetDeviceInfo(Pa_GetDefaultInputDevice());
728 const PaDeviceInfo
* odev
= Pa_GetDeviceInfo(Pa_GetDefaultOutputDevice());
730 long srate
= (long)lopt(argv
, "--frequency", 44100);
731 int fpb
= lopt("--buffer", 128);
733 gDevNumInChans
= (DSP
.getNumInputs() > 0) ? idev
->maxInputChannels
: 0 ;
734 gDevNumOutChans
= (DSP
.getNumOutputs() > 0) ? odev
->maxOutputChannels
: 0;
736 PaStreamParameters inputParameters
;
737 PaStreamParameters outputParameters
;
739 inputParameters
.device
= Pa_GetDefaultInputDevice();
740 inputParameters
.sampleFormat
= paFloat32
;
741 inputParameters
.channelCount
= gDevNumInChans
;
742 inputParameters
.hostApiSpecificStreamInfo
= 0;
744 outputParameters
.device
= Pa_GetDefaultOutputDevice();
745 outputParameters
.sampleFormat
= paFloat32
;
746 outputParameters
.channelCount
= gDevNumOutChans
;
747 outputParameters
.hostApiSpecificStreamInfo
= 0;
750 if ((err
= Pa_IsFormatSupported(
751 ((gDevNumInChans
> 0) ? &inputParameters
: 0),
752 ((gDevNumOutChans
> 0) ? &outputParameters
: 0), srate
)) != 0) {
753 printf("stream format is not supported err = %d\n", err
);
757 printf("inchan = %d, outchan = %d, freq = %f\n", gDevNumInChans
, gDevNumOutChans
, srate
);
758 allocChannels(fpb
, max(gDevNumInChans
, DSP
.getNumInputs()), max(gDevNumOutChans
, DSP
.getNumOutputs()));
759 DSP
.init(long(srate
));
760 pa_error(Pa_OpenDefaultStream(&as
, gDevNumInChans
, gDevNumOutChans
, paFloat32
, srate
, fpb
, audioCallback
, 0));