-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
reaper_plugin.h
1495 lines (1173 loc) · 66.8 KB
/
reaper_plugin.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/***************************************
*** REAPER Plug-in API
**
** Copyright (C) 2006-2015, Cockos Incorporated
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
** Notes: the C++ interfaces used require MSVC on win32, or at least the MSVC-compatible C++ ABI. Sorry, mingw users :(
**
*/
#ifndef _REAPER_PLUGIN_H_
#define _REAPER_PLUGIN_H_
#ifndef REASAMPLE_SIZE
#define REASAMPLE_SIZE 8 // if we change this it will break everything!
#endif
#if REASAMPLE_SIZE == 4
typedef float ReaSample;
#else
typedef double ReaSample;
#endif
#ifdef _WIN32
#include <windows.h>
#define REAPER_PLUGIN_DLL_EXPORT __declspec(dllexport)
#define REAPER_PLUGIN_HINSTANCE HINSTANCE
#else
#include "../WDL/WDL/swell/swell.h"
#include <pthread.h>
#define REAPER_PLUGIN_DLL_EXPORT __attribute__((visibility("default")))
#define REAPER_PLUGIN_HINSTANCE void *
#endif
#define REAPER_PLUGIN_ENTRYPOINT ReaperPluginEntry
#define REAPER_PLUGIN_ENTRYPOINT_NAME "ReaperPluginEntry"
#ifdef _MSC_VER
#define INT64 __int64
#define INT64_CONSTANT(x) (x##i64)
#else
#define INT64 long long
#define INT64_CONSTANT(x) (x##LL)
#endif
#ifdef __GNUC__
#define REAPER_STATICFUNC __attribute__((unused)) static
#else
#define REAPER_STATICFUNC static
#endif
/*
** Endian-tools and defines (currently only __ppc__ and BIG_ENDIAN is recognized, for OS X -- all other platforms are assumed to be LE)
*/
REAPER_STATICFUNC int REAPER_BSWAPINT(int x) {
return ((((x)) & 0xff) << 24) | ((((x)) & 0xff00) << 8) | ((((x)) & 0xff0000) >> 8)
| (((x) >> 24) & 0xff);
}
REAPER_STATICFUNC void REAPER_BSWAPINTMEM(void* buf) {
char p[4], tmp;
memcpy(p, buf, 4);
tmp = p[0];
p[0] = p[3];
p[3] = tmp;
tmp = p[1];
p[1] = p[2];
p[2] = tmp;
memcpy(buf, p, 4);
}
REAPER_STATICFUNC void REAPER_BSWAPINTMEM8(void* buf) {
char p[8], tmp;
memcpy(p, buf, 8);
tmp = p[0];
p[0] = p[7];
p[7] = tmp;
tmp = p[1];
p[1] = p[6];
p[6] = tmp;
tmp = p[2];
p[2] = p[5];
p[5] = tmp;
tmp = p[3];
p[3] = p[4];
p[4] = tmp;
memcpy(buf, p, 8);
}
#if defined(__ppc__)
#define REAPER_BIG_ENDIAN
#define REAPER_FOURCC(d,c,b,a) (((unsigned int)(d)&0xff)|(((unsigned int)(c)&0xff)<<8)|(((unsigned int)(b)&0xff)<<16)|(((unsigned int)(a)&0xff)<<24))
#define REAPER_MAKEBEINT(x) (x)
#define REAPER_MAKEBEINTMEM(x)
#define REAPER_MAKEBEINTMEM8(x)
#define REAPER_MAKELEINT(x) REAPER_BSWAPINT(x)
#define REAPER_MAKELEINTMEM(x) REAPER_BSWAPINTMEM(x)
#define REAPER_MAKELEINTMEM8(x) REAPER_BSWAPINTMEM8(x)
#else
#define REAPER_FOURCC(a, b, c, d) (((unsigned int)(d)&0xff)|(((unsigned int)(c)&0xff)<<8)|(((unsigned int)(b)&0xff)<<16)|(((unsigned int)(a)&0xff)<<24))
#define REAPER_MAKELEINT(x) (x)
#define REAPER_MAKELEINTMEM(x)
#define REAPER_MAKELEINTMEM8(x)
#define REAPER_MAKEBEINT(x) REAPER_BSWAPINT(x)
#define REAPER_MAKEBEINTMEM(x) REAPER_BSWAPINTMEM(x)
#define REAPER_MAKEBEINTMEM8(x) REAPER_BSWAPINTMEM8(x)
#endif
#if 1
#define ADVANCE_TIME_BY_SAMPLES(t, spls, srate) ((t) += (spls)/(double)(srate)) // not completely accurate but still quite accurate.
#else
#define ADVANCE_TIME_BY_SAMPLES(t, spls, srate) ((t) = floor((t) * (srate) + spls + 0.5)/(double)(srate)) // good forever? may have other issues though if srate changes. disabled for now
#endif
// REAPER extensions must support this entry function:
// int ReaperPluginEntry(HINSTANCE hInstance, reaper_plugin_info_t *rec);
// return 1 if you are compatible (anything else will result in plugin being unloaded)
// if rec == NULL, then time to unload
//
// CLAP plugins can access the REAPER API via:
// const void *clap_host.get_extension(const clap_host *host, "cockos.reaper_extension");
// which returns a pointer to a reaper_plugin_info_t struct
//
// CLAP plugins can also (v6.80+) get their context information by getFunc("clap_get_reaper_context")
// void *(*clap_get_reaper_context)(const clap_host *host, int sel);
// sel=1 for parent track if track FX
// sel=2 for parent take if item FX
// sel=3 for project
// sel=4 for FxDsp
// sel=5 for track channel count (INT_PTR)
// sel=6 for index in chain
#define REAPER_PLUGIN_VERSION 0x20E
typedef struct reaper_plugin_info_t {
int caller_version; // REAPER_PLUGIN_VERSION
HWND hwnd_main;
/*
Register() is the API that plug-ins register most things, be it keyboard shortcuts, project importers, etc.
Register() is also available by using GetFunc("plugin_register")
extensions typically register things on load of the DLL, for example:
static pcmsink_register_t myreg={ ... };
rec->Register("pcmsink",&myreg);
on plug-in unload (or if the extension wishes to remove it for some reason):
rec->Register("-pcmsink",&myreg);
the "-" prefix is supported for most registration types.
some types support the < prefix to register at the start of the list
Registration types:
API_*:
if you have a function called myfunction(..) that you want to expose to other extensions, use:
rec->Register("API_myfunction",funcaddress);
other extensions then use GetFunc("myfunction") to get the function pointer.
APIdef_*:
To make a function registered with API_* available via ReaScript, follow the API_ registration with:
double myfunction(char* str, int flag);
const char *defstring = "double\0char*,int\0str,flag\0help text for myfunction"
rec->Register("APIdef_myfunction",(void*)defstring);
defstring is four null-separated fields: return type, argument types, argument names, and help.
APIvararg_*:
Used to set the reascript vararg function pointer for an API_:
(void *) (void * (*faddr_vararg)(void **arglist, int numparms))
numparms will typically be the full requested parameter count (including NULL pointers for any
unspecified optional parameters)
arguments and return values:
integer as (void *)(INT_PTR) intval
double as (void *)&some_double_in_memory
pointers directly as pointers (can be NULL, especially if Optional)
hookcommand:
Registers a hook which runs prior to every action in the main section:
bool runCommand(int command, int flag);
rec->Register("hookcommand",runCommand);
runCommand() should return true if it processed the command (prevent further hooks or the action from running)
It is OK to call Main_OnCommand() from runCommand(), but it must check for and handle any recursion.
hookpostcommand:
Registers a hook which runs after each action in the main section:
void postCommand(int command, int flag);
rec->Register("hookpostcommand",postCommand);
hookcommand2:
Registers a hook which runs prior to every action triggered by a key/MIDI event:
bool onAction(KbdSectionInfo *sec, int command, int val, int val2, int relmode, HWND hwnd);
rec->Register("hookcommand2",hook); \
onAction returns true if it processed the command (preventing further hooks or actions from running)
val/val2 are used for actions triggered by MIDI/OSC/mousewheel
- val = [0..127] and val2 = -1 for MIDI CC,
- val2 >=0 for MIDI pitch or OSC with value = (val2|(val<<7))/16383.0
- relmode absolute(0) or 1/2/3 for relative adjust modes
hookpostcommand2:
void (*hook)(KbdSectionInfo *section, int actionCommandID, int val, int valhw, int relmode, HWND hwnd, ReaProject *proj);
rec->Register("hookpostcommand2",hook);
command_id:
Registers/looks up a command ID for an action. Parameter is a unique string with only A-Z, a-z, 0-9.
int command = Register("command_id","MyCommandName");
returns 0 if unsupported/out of actions
command_id_lookup:
Like command_id but only looks up, does not create a new command ID.
pcmsink_ext:
Registers an extended audio sink type:
(pcmsink_register_ext_t *)
pcmsink:
Registers an audio sink type:
(pcmsink_register_t *)
pcmsrc:
Registers an audio source:
(pcmsrc_register_t *)
timer:
Runs a timer periodically:
void (*timer_function)();
hwnd_info: (6.29+)
query information about a hwnd
int (*callback)(HWND hwnd, INT_PTR info_type);
return 0 if hwnd is not a known window, or if info_type is unknown
info_type:
0 = query if hwnd should be treated as a text-field for purposes of global hotkeys
return: 1 if text field
return: -1 if not text field
1 = query if global hotkeys should be processed for this context (6.60+)
return 1 if global hotkey should be skipped (and default accelerator processing used instead)
return -1 if global hotkey should be forced
file_in_project_ex:
void *p[2] = {(void *)fn, projptr };
plugin_register("file_in_project_ex",p);
plugin_register("-file_in_project_ex",p);
fn does not need to persist past the call of the function (it is copied)
projptr must be a valid ReaProject (the default NULL=g_project semantics do not apply).
file references are reference counted so you can add twice/remove twice etc.
file_in_project_ex2:
Extended syntax to receive rename notifications, or to have your plug-in request that the file go in a subdirectory:
INT_PTR fileInProjectCallback(void *_userdata, int msg, void *parm) {
if (msg == 0 && parm)
{
// rename notification, parm is (const char *)new filename
}
if (msg == 0x100) return (INT_PTR)"samples"; // subdirectory name, if desired (return 0 if not desired)
return 0;
}
void *p[4] = {(void *)fn, projptr, userdatacontext, fileInProjectCallback };
plugin_register("file_in_project_ex2",p);
plugin_register("-file_in_project_ex2",p);
toolbar_icon_map:
Allows a plugin to override default toolbar images for its registered commands.
const char *GetToolbarIconName(const char *toolbar_name, int cmd, int state)
{
if (!strcmp(toolbarid,"Main toolbar") || !strncmp(toolbarid,"Floating toolbar",16))
if (cmd == g_registered_command_id) return "toolbar_whatever";
return NULL;
}
plugin_register("toolbar_icon_map", (void *)GetToolbarIconName);
accel_section:
action_help:
custom_action:
gaccel:
hookcustommenu:
prefpage:
projectimport:
projectconfig:
editor:
accelerator:
csurf:
csurf_inst:
toggleaction:
on_update_hooks:
open_file_reduce:
*/
int (* Register)(const char* name, void* infostruct); // returns 1 if registered successfully
// get a generic API function, there many of these defined. see reaper_plugin_functions.h
void* (* GetFunc)(const char* name); // returns 0 if function not found
} reaper_plugin_info_t;
/****************************************************************************************
**** interface for plugin objects to save/load state. they should use ../WDL/LineParser.h too...
***************************************************************************************/
// ProjectStateContext tempflags meaning for &0xFFFF
enum {
PROJSTATECTX_UNDO_REDO = 1,
PROJSTATECTX_SAVE_LOAD = 2, // project, track template, etc
PROJSTATECTX_CUTCOPY_PASTE = 3,
};
// &0xFFFF0000 is for receiver use
#ifdef __cplusplus
#ifndef _WDL_PROJECTSTATECONTEXT_DEFINED_
#define _REAPER_PLUGIN_PROJECTSTATECONTEXT_DEFINED_
class ProjectStateContext // this is also defined in WDL, need to keep these interfaces identical
{
public:
virtual ~ProjectStateContext(){};
#ifdef __GNUC__
virtual void __attribute__ ((format (printf,2,3))) AddLine(const char *fmt, ...) = 0;
#else
virtual void AddLine(const char *fmt, ...)=0;
#endif
virtual int GetLine(char *buf, int buflen)=0; // returns -1 on eof
virtual INT64 GetOutputSize()=0; // output size written so far, only usable on REAPER 3.14+
virtual int GetTempFlag()=0;
virtual void SetTempFlag(int flag)=0;
};
#endif
/***************************************************************************************
**** MIDI event definition and abstract list
***************************************************************************************/
struct MIDI_event_t
{
int frame_offset;
int size; // bytes used by midi_message, can be >3, but should never be <3, even if a short 1 or 2 byte msg
unsigned char midi_message[4]; // size is number of bytes valid -- can be more than 4!
// new helpers
bool is_note() const { return (midi_message[0]&0xe0)==0x80; }
bool is_note_on() const {
return (midi_message[0]&0xf0)==0x90 && midi_message[2];
}
bool is_note_off() const {
switch (midi_message[0]&0xf0)
{
case 0x80: return true;
case 0x90: return midi_message[2]==0;
}
return false;
}
enum {
CC_ALL_SOUND_OFF=120,
CC_ALL_NOTES_OFF=123,
CC_EOF_INDICATOR = CC_ALL_NOTES_OFF
};
};
class MIDI_eventlist
{
public:
virtual void AddItem(MIDI_event_t *evt)=0;
virtual MIDI_event_t *EnumItems(int *bpos)=0;
virtual void DeleteItem(int bpos)=0;
virtual int GetSize()=0; // size of block in bytes
virtual void Empty()=0;
protected:
// this is only defined in REAPER 4.60+, for 4.591 and earlier you should delete only via the implementation pointer
virtual ~MIDI_eventlist() { }
};
#endif // __cplusplus
typedef struct _MIDI_eventprops {
double ppqpos;
double ppqpos_end_or_bezier_tension; // only for note events or CC events
char flag; // &1=selected, &2=muted, >>4&0xF=cc shape
unsigned char msg[3]; // msg is not valid if varmsglen > 0
char* varmsg;
int varmsglen;
int
setflag; // &1:selected, &2:muted, &4:ppqpos, &8:endppqpos or bez tension, &16:msg1 high bits, &32:msg1 low bits, &64:msg2, &128:msg3, &256:varmsg, &1024:shape/tension fields used, &16384:no sort after set
} MIDI_eventprops;
/***************************************************************************************
**** PCM source API
***************************************************************************************/
typedef struct _PCM_source_transfer_t {
double time_s; // start time of block
double samplerate; // desired output samplerate and channels
int nch;
int length; // desired length in sample(pair)s of output
ReaSample* samples; // samples filled in (the caller allocates this)
int samples_out; // updated with number of sample(pair)s actually rendered
MIDI_eventlist* midi_events;
double approximate_playback_latency; // 0.0 if not supported
double absolute_time_s;
double force_bpm;
} PCM_source_transfer_t;
#ifdef __cplusplus
class REAPER_PeakGet_Interface;
typedef struct _PCM_source_peaktransfer_t
{
double start_time; // start time of block
double peakrate; // peaks per second (see samplerate below)
int numpeak_points; // desired number of points for data
int nchpeaks; // number of channels of peaks data requested
ReaSample *peaks; // peaks output (caller allocated)
int peaks_out; // number of points actually output (less than desired means at end)
enum
{
PEAKTRANSFER_PEAKS_MODE=0,
PEAKTRANSFER_WAVEFORM_MODE=1,
PEAKTRANSFER_MIDI_NOTE_MODE=2,
PEAKTRANSFER_MIDI_DRUM_MODE=3,
PEAKTRANSFER_MIDI_DRUM_TRIANGLE_MODE=4,
};
int output_mode; // see enum above
double absolute_time_s;
ReaSample *peaks_minvals; // can be NULL, otherwise receives minimum values
int peaks_minvals_used;
double samplerate; // peakrate is peaks per second, samplerate is used only as a hint for what style of peaks to draw, OK to pass in zero
#define PEAKINFO_EXTRADATA_SPECTRAL1 ((int)'s')
#define PEAKINFO_EXTRADATA_SPECTROGRAM1 ((int)'g')
#define PEAKINFO_EXTRADATA_MIDITEXT ((int)'m')
#define PEAKINFO_EXTRADATA_LOUDNESS_DEPRECATED ((int)'l') // use PEAKINFO_EXTRADATA_LOUDNESS_RAW instead
#define PEAKINFO_EXTRADATA_LOUDNESS_RAW ((int)'r')
int extra_requested_data_type; // PEAKINFO_EXTRADATA_* for spectral information
int extra_requested_data_out; // output: number of samples returned (== peaks_out if successful)
void *extra_requested_data;
REAPER_PeakGet_Interface *__peakgetter;
#ifdef __LP64__
int *exp[27];
#else
int *exp[26];
#endif
static inline int extra_blocksize(int extra_requested_data_type)
{
switch (extra_requested_data_type)
{
case PEAKINFO_EXTRADATA_SPECTRAL1: return SPECTRAL1_BYTES;
case PEAKINFO_EXTRADATA_SPECTROGRAM1: return SPECTROGRAM1_BLOCKSIZE_BYTES;
case PEAKINFO_EXTRADATA_MIDITEXT: return MIDITEXT_BYTES;
case PEAKINFO_EXTRADATA_LOUDNESS_DEPRECATED: return LOUDNESS_DEPRECATED_BYTES;
case PEAKINFO_EXTRADATA_LOUDNESS_RAW: return LOUDNESS_RAW_BYTES;
}
return 0;
}
enum {
SPECTROGRAM1_BLOCKSIZE_BYTES=128 * 3 / 2, // 128 bins, 12 bits each (MSB1, (LSN1<<4)|LSN2, MSB2)
SPECTRAL1_BYTES=4, // one LE int per channel per sample spectral info: low 15 bits frequency, next 14 bits density (16383=tonal, 0=noise, 12288 = a bit noisy)
MIDITEXT_BYTES=1, // at most one character per pixel
LOUDNESS_DEPRECATED_BYTES=4, // 4 byte LE integer: LUFS-M low 12 bits, LUFS-S next 12 bits, 0-3000 valid: ex: 0 means -150.0 LU (consider this -inf), 1500 means +0 LU - loudness values returned for each channel even if the calculation is for all channels combined
LOUDNESS_RAW_BYTES=8, // 4 byte LE float LUFS-M low 32 bits, 4 byte LE float LUFS-S high 32 bits, values are a windowed average of squared filtered samples
// intermediate loudness calculation values are returned for each channel and must be combined before display
};
} PCM_source_peaktransfer_t;
// used to update MIDI sources with new events during recording
typedef struct _REAPER_midi_realtime_write_struct_t
{
double global_time;
double global_item_time;
double srate;
int length; // length in samples
int overwritemode; // 0=overdub, 1=replace,
// -1 = literal (do nothing just add)
// 65536+(16 bit mask) = replace notes on just these channels (touch-replace)
MIDI_eventlist *events;
double item_playrate;
double latency;
unsigned int *overwrite_actives; // [16(note)+16(CC)+16(poly AT)][4]; only used when overwritemode is >0
// CC: 127=pitch, 126=program, 125=channel pressure
double do_not_quantize_past_sec; // amount in future that quantizing should never move things past (or 0 for not used)
} midi_realtime_write_struct_t;
// abstract base class
class PCM_source
{
public:
virtual ~PCM_source() { }
virtual PCM_source *Duplicate()=0;
virtual bool IsAvailable()=0;
virtual void SetAvailable(bool avail) { } // optional, if called with avail=false, close files/etc, and so on
virtual const char *GetType()=0;
virtual const char *GetFileName() { return NULL; } // return NULL if no filename (not purely a file)
virtual bool SetFileName(const char *newfn)=0; // return TRUE if supported, this will only be called when offline
virtual PCM_source *GetSource() { return NULL; }
virtual void SetSource(PCM_source *src) { }
virtual int GetNumChannels()=0; // return number of channels
virtual double GetSampleRate()=0; // returns preferred sample rate. if < 1.0 then it is assumed to be silent (or MIDI)
virtual double GetLength()=0; // length in seconds
virtual double GetLengthBeats() { return -1.0; } // length in beats if supported
virtual int GetBitsPerSample() { return 0; } // returns bits/sample, if available. only used for metadata purposes, since everything returns as doubles anyway
virtual double GetPreferredPosition() { return -1.0; } // not supported returns -1
virtual int PropertiesWindow(HWND hwndParent)=0;
virtual void GetSamples(PCM_source_transfer_t *block)=0;
virtual void GetPeakInfo(PCM_source_peaktransfer_t *block)=0;
virtual void SaveState(ProjectStateContext *ctx)=0;
virtual int LoadState(const char *firstline, ProjectStateContext *ctx)=0; // -1 on error
// these are called by the peaks building UI to build peaks for files.
virtual void Peaks_Clear(bool deleteFile)=0;
virtual int PeaksBuild_Begin()=0; // returns nonzero if building is opened, otherwise it may mean building isn't necessary
virtual int PeaksBuild_Run()=0; // returns nonzero if building should continue
virtual void PeaksBuild_Finish()=0; // called when done
virtual int Extended(int call, void *parm1, void *parm2, void *parm3) { return 0; } // return 0 if unsupported
};
typedef struct _REAPER_cue
{
int m_id; // ignored for PCM_SINK_EXT_ADDCUE, populated for PCM_SOURCE_EXT_ENUMCUES
double m_time;
double m_endtime;
bool m_isregion;
char *m_name; // can be NULL if unnamed
int m_flags; // &1:DEPRECATED caller must call Extended(PCM_SOURCE_EXT_ENUMCUES, -1, &cue, 0) when finished, &2:time is QN, &0x10000:write cue regardless of sink settings, &4:is chapter, &(8|16)=8:has low confidence cue name, &(8|16)=16:has medium confidence cue name, &(8|16)=24:has high confidence cue name
char resvd[124]; // future expansion -- should be 0
} REAPER_cue;
typedef struct _REAPER_slice
{
PCM_source* m_sliceSrc;
double m_beatSnapOffset;
int flag; // &1=only return beatsnapoffset, not slicesrc
char resvd[124]; // future expansion -- should be 0
} REAPER_slice;
typedef struct _REAPER_inline_positioninfo
{
double draw_start_time; // project time at pixel start of draw
int draw_start_y; // if y-scroll is partway into the item, positive pixel value
double pixels_per_second;
int width, height; // width and height of view of the item. if doing a partial update this may be larger than the bitmap passed in
int mouse_x, mouse_y; // valid only on mouse/key/setcursor/etc messages
void *extraParms[8];
// WM_KEYDOWN handlers can use MSG *msg = (MSG *)extraParms[0]
// WM_SETCURSOR handlers should set *extraParms[0] = hcursor
} REAPER_inline_positioninfo;
typedef struct _REAPER_tempochg
{
double timepos, qnpos, bpm;
int tsnum, tsdenom;
int flag; // &1=linear tempo change, &2=internal use
} REAPER_tempochg;
#define PCM_SOURCE_EXT_INLINEEDITOR 0x100 /* parm1 = (void *)(INT_PTR)message, parm2/parm3 = parms
note: for the WM_* constants, you can use windows.h if on Windows, and SWELL's definitions if on other platforms
note: for LICE_IBitmap interface, you can use LICE's definition
for SWELL and LICE, see Cockos WDL -- https://www.cockos.com/wdl
NOTE: fx-embed documentation is now in reaper_plugin_fx_embed.h
messages:
0 = query if editor is available/supported. returns <0 if supported but unavailable, >0 if available, 0=if not supported
WM_CREATE to create the editor instance
WM_DESTROY to destroy the editor instance (nonzero if success)
WM_LBUTTON*, WM_RBUTTON*, WM_MOUSEMOVE, WM_MOUSEWHEEL -- parm2=rsvd, parm3= REAPER_inline_positioninfo)
these can return any combination of:
REAPER_INLINE_RETNOTIFY_INVALIDATE
REAPER_INLINE_RETNOTIFY_SETCAPTURE
REAPER_INLINE_RETNOTIFY_SETFOCUS
WM_KEYDOWN -- parm3=REAPER_inline_positioninfo*, MSG *kbmsg = (MSG *)rec->extraParms[0]
return nonzero to eat the key. can return REAPER_INLINE_RETNOTIFY_INVALIDATE.
WM_SETCURSOR -- parm3=REAPER_inline_positioninfo*
-- *rec->extraParms[0] = hcursor
paint messages: parm2 = LICE_IBitmap *, parm3 = (REAPER_inline_positioninfo*).
WM_ERASEBKGND -- draw first pass -- should return 1 if supported
WM_PAINT -- draw second pass -- should return 1 if paint supported
WM_NCPAINT -- draw third pass
Notes on Retina/HiDPI:
on macOS retina, (int)LICE_IBitmap::Extended(LICE_EXT_GET_SCALING,NULL) may return 512. in this case LICE will internally render things double-sized
on other platforms HiDPI, if (int)LICE_IBitmap::Extended(LICE_EXT_GET_ADVISORY_SCALING,NULL) returns nonzero, then it is a 24.8 scale factor which things
should be scaled by.
*/
#define REAPER_INLINE_RETNOTIFY_INVALIDATE 0x1000000 // want refresh of display
#define REAPER_INLINE_RETNOTIFY_SETCAPTURE 0x2000000 // setcapture
#define REAPER_INLINE_RETNOTIFY_SETFOCUS 0x4000000 // set focus to item
#define REAPER_INLINE_RETNOTIFY_NOAUTOSCROLL 0x8000000 // modifier only valid when setcapture set
#define REAPER_INLINEFLAG_SHOWALLTAKES 0x1000 // only valid as a return value flag for message=0, display in inactive take lanes
#define REAPER_INLINEFLAG_WANTOVERLAYEDCONTROLS 0x4000 // only valid as a return value flag for message=0, to have fades/etc still drawn over like normal
#define PCM_SOURCE_EXT_PROJCHANGENOTIFY 0x2000 // parm1 = nonzero if activated project, zero if deactivated project
#define PCM_SOURCE_EXT_OPENEDITOR 0x10001 // parm1=hwnd, implementation dependent parm2/parm3
#define PCM_SOURCE_EXT_GETEDITORSTRING 0x10002 // parm1=index (0 or 1), parm2=(const char**)desc, optional parm3=(int*)has_had_editor
#define PCM_SOURCE_EXT_DEPRECATED_1 0x10003 // was PCM_SOURCE_EXT_CLOSESECONDARYSRC
#define PCM_SOURCE_EXT_SETITEMCONTEXT 0x10004 // parm1=MediaItem*, parm2=MediaItem_Take*
#define PCM_SOURCE_EXT_ADDMIDIEVENTS 0x10005 // parm1=pointer to midi_realtime_write_struct_t, nch=1 for replace, =0 for overdub, parm2=midi_quantize_mode_t* (optional)
#define PCM_SOURCE_EXT_GETASSOCIATED_RPP 0x10006 // parm1=pointer to char* that will receive a pointer to the string
#define PCM_SOURCE_EXT_GETMETADATA 0x10007 // parm1=pointer to name string, parm2=pointer to buffer, parm3=(int)buffersizemax. returns length used. defined strings are "TITLE", "ARTIST", "ALBUM", "TRACKNUMBER", "YEAR", "GENRE", "COMMENT", "DESC", "BPM", "KEY", "DB_CUSTOM"
#define PCM_SOURCE_EXT_SETASSECONDARYSOURCE 0x10008 // parm1=optional pointer to src (same subtype as receiver), if supplied, set the receiver as secondary src for parm1's editor, if not supplied, receiver has to figure out if there is an appropriate editor open to attach to, parm2/3 impl defined
#define PCM_SOURCE_EXT_SHOWMIDIPREVIEW 0x10009 // parm1=(MIDI_eventlist*), can be NULL for all-notes-off (also to check if this source supports showing preview at this moment)
#define PCM_SOURCE_EXT_SEND_EDITOR_MSG 0x1000A // impl defined parameters
#define PCM_SOURCE_EXT_SETSECONDARYSOURCELIST 0x1000B // parm1=(PCM_source**)sourcelist, parm2=list size, parm3=close any existing src not in the list
#define PCM_SOURCE_EXT_ISOPENEDITOR 0x1000C // returns 1 if this source is currently open in an editor, 2 if open in a secondary editor. parm1=1 to close. parm2=(int*)&flags to get extra flags (&1=editor is currently hidden)
#define PCM_SOURCE_EXT_SETEDITORGRID 0x1000D // parm1=(double*)griddiv: 0.25=quarter note, 1.0/3.0=half note triplet, etc. parm2=int* swingmode(1=swing), parm3=double*swingamt
#define PCM_SOURCE_EXT_GETITEMCONTEXT 0x10010 // parm1=MediaItem**, parm2=MediaItem_Take**, parm3=MediaTrack**
#define PCM_SOURCE_EXT_GETALLMETADATA_DEPRECATED 0x10011 // no longer supported
#define PCM_SOURCE_EXT_GETBITRATE 0x10012 // parm1=(double*)bitrate, if different from samplerate*channels*bitdepth/length
#define PCM_SOURCE_EXT_ENUMMETADATA 0x10013 // parm1=(int)index, parm2=(const char**)key, parm3=(const char**)value. enumerates all metadata, returns 0 when no more metadata exists
#define PCM_SOURCE_EXT_GETINFOSTRING 0x10014 // parm1=(char*)buffer, parm2=(int)buffer length, return the data that would be displayed in the properties window
#define PCM_SOURCE_EXT_CONFIGISFILENAME 0x20000
#define PCM_SOURCE_EXT_WRITEMETADATA_DEPRECATED 0x20007 // no longer supported
#define PCM_SOURCE_EXT_WRITE_METADATA 0x20008 // parm1=char* new file name, parm2=(char**)NULL-terminated array of key,value,key2,value2,... pointers, parm3=flags (&1=merge, &2=do not allow update in-place). returns 1 if successfully generated a new file, 2 if original file was updated
#define PCM_SOURCE_EXT_GETBPMANDINFO 0x40000 // parm1=pointer to double for bpm. parm2=pointer to double for snap/downbeat offset (seconds).
#define PCM_SOURCE_EXT_GETNTRACKS 0x80000 // for midi data, returns number of tracks that would have been available. optional parm1=(int*)mask of channels available, mask&(1<<16)=metadata
#define PCM_SOURCE_EXT_GETTITLE 0x80001 // parm1=(char**)title (string persists in plugin)
#define PCM_SOURCE_EXT_ENUMTEMPOMAP 0x80002 // parm1=index, parm2=pointer to REAPER_tempochg, returns 0 if no tempo map or enumeration complete
#define PCM_SOURCE_EXT_WANTOLDBEATSTYLE 0x80003
#define PCM_SOURCE_EXT_GETNOTATIONSETTINGS 0x80004 // parm1=(int)what, (what==0) => parm2=(double*)keysigmap, parm3=(int*)keysigmapsize; (what==1) => parm2=(int*)display transpose semitones, (what==2) => parm2=(char*)clef1, parm3=(char*)clef2
#define PCM_SOURCE_EXT_RELOADTRACKDATA 0x80005 // internal use
#define PCM_SOURCE_EXT_WANT_TRIM 0x90001 // parm1=(int64*)total number of decoded samples after trimming, parm2=(int*)number of samples to trim from start, parm3=(int*)number of samples to trim from end
#define PCM_SOURCE_EXT_WANTTRIM_DEPRECATED 0x90002 // no longer supported
#define PCM_SOURCE_EXT_TRIMITEM 0x90003 // parm1=lrflag, parm2=double *{position,length,startoffs,rate}
#define PCM_SOURCE_EXT_EXPORTTOFILE 0x90004 // parm1=output filename, only currently supported by MIDI but in theory any source could support this
#define PCM_SOURCE_EXT_ENUMCUES 0x90005 // DEPRECATED, use PCM_SOURCE_EXT_ENUMCUES_EX instead. parm1=(int) index of cue to get (-1 to free cue), parm2=(optional)REAPER_cue **. Returns 0 and sets parm2 to NULL when out of cues. return value otherwise is how much to advance parm2 (1, or 2 usually)
#define PCM_SOURCE_EXT_ENUMCUES_EX 0x90016 // parm1=(int) index of cue (source must provide persistent backing store for cue->m_name), parm2=(REAPER_cue*) optional. Returns 0 when out of cues, otherwise returns how much to advance index (1 or 2 usually).
// a PCM_source may be the parent of a number of beat-based slices, if so the parent should report length and nchannels only, handle ENUMSLICES, and be deleted after the slices are retrieved
#define PCM_SOURCE_EXT_ENUMSLICES 0x90006 // parm1=(int*) index of slice to get, parm2=REAPER_slice* (pointing to caller's existing slice struct), parm3=(double*)bpm. if parm2 passed in zero, returns the number of slices. returns 0 if no slices or out of slices.
#define PCM_SOURCE_EXT_ENDPLAYNOTIFY 0x90007 // notify a source that it can release any pooled resources
#define PCM_SOURCE_EXT_SETPREVIEWTEMPO 0x90008 // parm1=(double*)bpm, only meaningful for MIDI or slice-based source media; bpm==0 to follow project tempo changes
enum { RAWMIDI_NOTESONLY=1, RAWMIDI_UNFILTERED=2, RAWMIDI_CHANNELFILTER=3 }; // if RAWMIDI_CHANNELFILTER, flags>>4 is a mask of which channels to play
#define PCM_SOURCE_EXT_GETRAWMIDIEVENTS 0x90009 // parm1 = (PCM_source_transfer_t *), parm2 = RAWMIDI flags
#define PCM_SOURCE_EXT_SETRESAMPLEMODE 0x9000A // parm1= mode to pass to resampler->Extended(RESAMPLE_EXT_SETRSMODE,mode,0,0)
#define PCM_SOURCE_EXT_NOTIFYPREVIEWPLAYPOS 0x9000B // parm1 = ptr to double of play position, or NULL if stopped
#define PCM_SOURCE_EXT_SETSIZE 0x9000C // parm1=(double*)startpos, parm2=(double*)endpos, parm3=flags. Start can be negative. Receiver may adjust start/end to avoid erasing content, in which case the adjusted values are returned in parm1 and parm2. parm3/flags: 1 if start/end in QN (always the case now). 2=resize even pooled items
#define PCM_SOURCE_EXT_GETSOURCETEMPO 0x9000D // parm1=(double*)bpm, parm2=(int*)timesig_numerator<<8|timesig_denominator, parm3=(double*)current preview tempo if applicable. this is for reporting purposes only, does not necessarily mean the media should be adjusted (as PCM_SOURCE_EXT_GETBPMANDINFO means)
#define PCM_SOURCE_EXT_ISABNORMALAUDIO 0x9000E // return 1 if rex, video, etc (meaning file export will just copy file directly rather than trim/converting)
#define PCM_SOURCE_EXT_GETPOOLEDMIDIID 0x9000F // parm1=(char*)id, parm2=(int*)pool user count, parm3=(MediaItem_Take**)firstuser
#define PCM_SOURCE_EXT_REMOVEFROMMIDIPOOL 0x90010
#define PCM_SOURCE_EXT_GETHASH 0x90011 // parm1=(WDL_UINT64*)hash (64-bit hash of the source data)
#define PCM_SOURCE_EXT_GETIMAGE 0x90012 // parm1=(LICE_IBitmap**)image. parm2 = NULL or pointer to int, which is (w<<16)|h desired approx
#define PCM_SOURCE_EXT_NOAUDIO 0x90013
#define PCM_SOURCE_EXT_HASMIDI 0x90014 // returns 1 if contains any MIDI data, parm1=(double*)time offset of first event
#define PCM_SOURCE_EXT_DELETEMIDINOTES 0x90015 // parm1=(double*)minlen (0.125 for 1/8 notes, etc), parm2=1 if only trailing small notes should be deleted, parm3=(bool*)true if any notes were deleted (return)
#define PCM_SOURCE_EXT_GETGUID 0x90017 // parm1=(GUID*)guid
#define PCM_SOURCE_EXT_DOPASTEINITEM 0x90100 // no parms used, acts as a paste from clipboard
#define PCM_SOURCE_EXT_GETNOTERANGE 0x90018 // parm1=(int*)low note, parm2=(int*)high note
#define PCM_SOURCE_EXT_PPQCONVERT 0x90020 // parm1=(double*)pos, parm2=(int)flag 0=ppq to proj time, 1=proj time to ppq
#define PCM_SOURCE_EXT_COUNTMIDIEVTS 0x90021 // parm1=(int*)notecnt, parm2=(int*)ccevtcnt, parm3=(int*)metaevtcnt
#define PCM_SOURCE_EXT_GETSETMIDIEVT 0x90022 // parm1=(MIDI_eventprops*)event properties (NULL to delete); parm2=(int)event index (<0 to insert); parm2=(int)flag: 1=index counts notes only, 2=index counts CC only, 3=index counts meta-events only
#define PCM_SOURCE_EXT_GETSUGGESTEDTEXT 0x90023 // parm1=char ** which will receive pointer to suggested label text, if any
#define PCM_SOURCE_EXT_GETSCALE 0x90024 // parm1=unsigned int: &0xF=pitch (0=C), &0x10=root, &0x20=min2, &0x40=maj2, &0x80=min3, &0xF0=maj3, &0x100=4, etc) ; parm2=(char*)name (optional), parm3=int size of name buffer
#define PCM_SOURCE_EXT_SELECTCONTENT 0x90025 // parm1=1 to select, 0 to deselect
#define PCM_SOURCE_EXT_GETGRIDINFO 0x90026 // parm1=(double*)snap grid size, parm2=(double*)swing strength, parm3=(double*)note insert length, -1 if follows grid size
#define PCM_SOURCE_EXT_SORTMIDIEVTS 0x9027
#define PCM_SOURCE_EXT_MIDI_COMPACTPHRASES 0x90028 // compact the notation phrase ID space
#define PCM_SOURCE_EXT_GETSETALLMIDI 0x90029 // parm1=(unsigned char*)data buffer, parm2=(int*)buffer length in bytes, parm2=(1:set, 0:get). Buffer is a list of { int offset, char flag, int msglen, unsigned char msg[] }. offset: MIDI ticks from previous event, flag: &1=selected &2=muted, msglen: byte length of msg (usually 3), msg: the MIDI message.
#define PCM_SOURCE_EXT_DISABLESORTMIDIEVTS 0x90030 // disable sorting for PCM_SOURCE_EXT_GETSETMIDIEVT until PCM_SOURCE_EXT_SORTMIDIEVTS is called
#define PCM_SOURCE_EXT_GETPOOLEDMIDIID2 0x90031 // parm1=(GUID*)id, parm2=(int*)pool user count, parm3=(MediaItem_Take**)firstuser
#define PCM_SOURCE_EXT_GETSETMIDICHANFILTER 0x90032 // parm1=(int*)filter: filter&(1<<n) to play channel n, parm2=(int)set: 0 to get, 1 to set
#define PCM_SOURCE_EXT_REFRESH_EDITORS 0x90033 // synchronously refresh any open editors
#define PCM_SOURCE_EXT_GETLAPPING 0xC0100 // parm1 = ReaSample buffer, parm2=(INT_PTR)maxlap, returns size of lapping returned. usually not supported. special purpose.
#define PCM_SOURCE_EXT_SET_PREVIEW_POS_OVERRIDE 0xC0101 // parm1 = (double *)&tickpos, tickpos<0 for no override
// register with Register("pcmsrc",&struct ... and unregister with "-pcmsrc"
typedef struct _REAPER_pcmsrc_register_t {
PCM_source *(*CreateFromType)(const char *type, int priority); // priority is 0-7, 0 is highest
PCM_source *(*CreateFromFile)(const char *filename, int priority); // if priority is 5-7, and the file isn't found, open it in an offline state anyway, thanks
// this is used for UI only, not so muc
const char *(*EnumFileExtensions)(int i, const char **descptr); // call increasing i until returns a string, if descptr's output is NULL, use last description
} pcmsrc_register_t;
/*
** OK so the pcm source class has a lot of responsibility, and people may not wish to
** have to implement them. So, for basic audio decoders, you can use this class instead:
**
** And you can use the PCM_Source_CreateFromSimple API to create a PCM_source from your ISimpleMediaDecoder derived class
*/
class ISimpleMediaDecoder
{
public:
virtual ~ISimpleMediaDecoder() { }
virtual ISimpleMediaDecoder *Duplicate()=0;
// filename can be NULL to use "last filename"
// diskread* are suggested values to pass to WDL_FileRead if you use it, otherwise can ignore
virtual void Open(const char *filename, int diskreadmode, int diskreadbs, int diskreadnb)=0;
// if fullClose=0, close disk resources, but can leave decoders etc initialized (and subsequently check the file date on re-open)
virtual void Close(bool fullClose)=0;
virtual const char *GetFileName()=0;
virtual const char *GetType()=0;
// an info string suitable for a dialog, and a title for that dialog
virtual void GetInfoString(char *buf, int buflen, char *title, int titlelen)=0;
virtual bool IsOpen()=0;
virtual int GetNumChannels()=0;
virtual int GetBitsPerSample()=0;
virtual double GetSampleRate()=0;
// positions in sample frames
virtual INT64 GetLength()=0;
virtual INT64 GetPosition()=0;
virtual void SetPosition(INT64 pos)=0;
// returns sample-frames read. buf will be at least length*GetNumChannels() ReaSamples long.
virtual int ReadSamples(ReaSample *buf, int length)=0;
// these extended messages may include PCM_source messages
virtual int Extended(int call, void *parm1, void *parm2, void *parm3) { return 0; } // return 0 if unsupported
};
/***************************************************************************************
**** PCM sink API
***************************************************************************************/
typedef struct _REAPER_midi_quantize_mode_t
{
bool doquant;
char movemode; // 0=default(l/r), -1=left only, 1=right only
char sizemode; // 0=preserve length, 1=quantize end
char quantstrength; // 1-100
double quantamt; // quantize to (in qn)
char swingamt; // 1-100
char range_min; // 0-100
char range_max;
} midi_quantize_mode_t;
class PCM_sink
{
public:
PCM_sink() { m_st=0.0; }
virtual ~PCM_sink() { }
virtual void GetOutputInfoString(char *buf, int buflen)=0;
virtual double GetStartTime() { return m_st; }
virtual void SetStartTime(double st) { m_st=st; }
virtual const char *GetFileName()=0; // get filename, if applicable (otherwise "")
virtual int GetNumChannels()=0; // return number of channels
virtual double GetLength()=0; // length in seconds, so far
virtual INT64 GetFileSize()=0;
virtual void WriteMIDI(MIDI_eventlist *events, int len, double samplerate)=0;
virtual void WriteDoubles(ReaSample **samples, int len, int nch, int offset, int spacing)=0;
virtual bool WantMIDI() { return 0; }
virtual int GetLastSecondPeaks(int sz, ReaSample *buf) { return 0; }
virtual void GetPeakInfo(PCM_source_peaktransfer_t *block) { } // allow getting of peaks thus far
virtual int Extended(int call, void *parm1, void *parm2, void *parm3) { return 0; } // return 0 if unsupported
private:
double m_st;
};
#define PCM_SINK_EXT_CREATESOURCE 0x80000 // parm1 = PCM_source ** (will be created if supported)
#define PCM_SINK_EXT_DONE 0x80001 // parm1 = optional HWND of the render dialog in case the sink needs more user interaction, parm2 = optional (char**)NULL-terminated array of key,value,key2,value2,... pointers if the sink supports updating metadata after write (may require the caller to have set padded metadata via SetCurrentSinkMetadata before creating the sink)
#define PCM_SINK_EXT_VERIFYFMT 0x80002 // parm1=int *srate, parm2= int *nch. plugin can override (and return 1!!)
#define PCM_SINK_EXT_SETQUANT 0x80003 // parm1 = (midi_quantize_mode_t*), or NULL to disable
#define PCM_SINK_EXT_SETRATE 0x80004 // parm1 = (double *) rateadj
#define PCM_SINK_EXT_GETBITDEPTH 0x80005 // parm1 = (int*) bitdepth (return 1 if supported)
#define PCM_SINK_EXT_ADDCUE 0x80006 // parm1=(PCM_cue*)cue OR parm2=(double*)transient position
#define PCM_SINK_EXT_SETCURBLOCKTIME 0x80007 // parm1 = (double *) project position -- called before each WriteDoubles etc
#define PCM_SINK_EXT_IS_VIDEO 0x80008 // deprecated/unused
typedef struct _REAPER_pcmsink_register_t // register using "pcmsink"
{
unsigned int (*GetFmt)(const char **desc);
const char *(*GetExtension)(const void *cfg, int cfg_l);
HWND (*ShowConfig)(const void *cfg, int cfg_l, HWND parent);
PCM_sink *(*CreateSink)(const char *filename, void *cfg, int cfg_l, int nch, int srate, bool buildpeaks);
} pcmsink_register_t;
typedef struct _REAPER_pcmsink_register_ext_t // register using "pcmsink_ext"
{
pcmsink_register_t sink;
// for extended calls that refer to the generic type of sink, rather than a specific instance of a sink
int (*Extended)(int call, void* parm1, void* parm2, void* parm3);
char expand[256];
} pcmsink_register_ext_t;
// supported via pcmsink_register_ext_t::Extended:
#define PCMSINKEXT_GETFORMATDESC 0x80000 // parm1=(void*)cfg, parm2=(int)cfglen, parm3=(const char*)retstring
#define PCMSINKEXT_GETFORMATDATARATE 0x80001 // parm1=(void*)cfg, parm2=(int)cfglen, parm3 = int[] {channels, samplerate}
#define PCMSINKEXT_GETFORMATBITDEPTH 0x80002 // parm1=(void*)cfg, parm2=(int)cfglen, returns bit depth if supported (negative with effective size if FP)
#define PCMSINKEXT_GETFORMATSTREAMDESC 0x80003 // parm1=(void*)cfg, parm2=(int)cfglen, parm3=(int*)streams (&1=has video, &2=has audio), returns 1 if supported
/***************************************************************************************
**** Resampler API (plug-ins can use this for SRC)
**
**
** See API functions Resampler_Create() and Resample_EnumModes()
***************************************************************************************/
class REAPER_Resample_Interface
{
public:
virtual ~REAPER_Resample_Interface(){}
virtual void SetRates(double rate_in, double rate_out)=0;
virtual void Reset()=0;
virtual double GetCurrentLatency()=0; // latency in seconds buffered -- do not call between resampleprepare and resampleout, undefined if you do...
virtual int ResamplePrepare(int out_samples, int nch, ReaSample **inbuffer)=0; // sample ratio
virtual int ResampleOut(ReaSample *out, int nsamples_in, int nsamples_out, int nch)=0; // returns output samples
virtual int Extended(int call, void *parm1, void *parm2, void *parm3) { return 0; } // return 0 if unsupported
};
#define RESAMPLE_EXT_SETRSMODE 0x1000 // parm1 == (int)resamplemode, or -1 for project default
#define RESAMPLE_EXT_SETFEEDMODE 0x1001 // parm1 = nonzero to set ResamplePrepare's out_samples to refer to request a specific number of input samples
#define RESAMPLE_EXT_RESETWITHFRACPOS 0x6000 // parm1 = (double*)&fracpos
/***************************************************************************************
**** Pitch shift API (plug-ins can use this for pitch shift/time stretch)
**
** See API calls ReaperGetPitchShiftAPI(), EnumPitchShiftModes(), EnumPitchShiftSubModes()
**
***************************************************************************************/
#define REAPER_PITCHSHIFT_API_VER 0x14
class IReaperPitchShift
{
public:
virtual ~IReaperPitchShift() { };
virtual void set_srate(double srate)=0;
virtual void set_nch(int nch)=0;
virtual void set_shift(double shift)=0;
virtual void set_formant_shift(double shift)=0; // shift can be <0 for "only shift when in formant preserve mode", so that you can use it for effective rate changes etc in that mode
virtual void set_tempo(double tempo)=0;
virtual void Reset()=0; // reset all buffers/latency
virtual ReaSample *GetBuffer(int size)=0;
virtual void BufferDone(int input_filled)=0;
virtual void FlushSamples()=0; // make sure all output is available
virtual bool IsReset()=0;
virtual int GetSamples(int requested_output, ReaSample *buffer)=0; // returns number of samplepairs returned
virtual void SetQualityParameter(int parm)=0; // set to: (mode<<16)+(submode), or -1 for "project default" (default)
virtual int Extended(int call, void *parm1, void *parm2, void *parm3) { return 0; } // return 0 if unsupported
};
#define REAPER_PITCHSHIFT_EXT_GETMINMAXPRODUCTS 0x1
#define REAPER_PITCHSHIFT_EXT_GET_CHAN_LIMIT 0x100 // return channel limit if any
#define REAPER_PITCHSHIFT_EXT_SET_OUTPUT_BPM 0x200 // parm1 = *(double *)bpm
#define REAPER_PITCHSHIFT_EXT_WANT_OUTPUT_BPM 0x201 // returns 1 if desired
/***************************************************************************************
**** Peak getting/building API
**
** These are really only needed if you implement a PCM_source or PCM_sink.
**
** See functions PeakGet_Create(), PeakBuild_Create(), GetPeakFileName(), ClearPeakCache()
**
***************************************************************************************/
class REAPER_PeakGet_Interface
{
public:
virtual ~REAPER_PeakGet_Interface() { }
virtual double GetMaxPeakRes()=0;
virtual void GetPeakInfo(PCM_source_peaktransfer_t *block)=0;
virtual int Extended(int call, void *parm1, void *parm2, void *parm3) { return 0; } // return 0 if unsupported
};
class REAPER_PeakBuild_Interface
{
public:
virtual ~REAPER_PeakBuild_Interface() { }
virtual void ProcessSamples(ReaSample **samples, int len, int nch, int offs, int spread)=0; // in case a sink wants to build its own peaks (make sure it was created with src=NULL)
virtual int Run()=0; // or let it do it automatically (created with source!=NULL)
virtual int GetLastSecondPeaks(int sz, ReaSample *buf)=0; // returns number of peaks in the last second, sz is maxsize
virtual void GetPeakInfo(PCM_source_peaktransfer_t *block)=0; // allow getting of peaks thus far (won't hit the highest resolution mipmap, just the 10/sec one or so)
virtual int Extended(int call, void *parm1, void *parm2, void *parm3) { return 0; } // return 0 if unsupported
};
// recommended settings for sources switching to peak caches
#define REAPER_PEAKRES_MAX_NOPKS 200.0
#define REAPER_PEAKRES_MUL_MIN 0.00001 // recommended for plug-ins, when 1000peaks/pix, toss hires source
#define REAPER_PEAKRES_MUL_MAX 1.0 // recommended for plug-ins, when 1.5pix/peak, switch to hi res source. this may be configurable someday via some sneakiness