1 // interface for supercollider plugins
2 // Copyright (C) 2009, 2010 Tim Blechmann
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; see the file COPYING. If not, write to
16 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 // Boston, MA 02111-1307, USA.
23 #include "sc_plugin_interface.hpp"
24 #include "sc_ugen_factory.hpp"
25 #include "sc_synth.hpp"
27 #include "nova-simd/simd_memory.hpp"
29 #include "../server/server_args.hpp"
30 #include "../server/memory_pool.hpp"
31 #include "../server/server.hpp"
32 #include "../utilities/malloc_aligned.hpp"
33 #include "../utilities/sized_array.hpp"
36 #include "SC_Prototypes.h"
37 #include "SC_Errors.h"
40 #include "SC_fftlib.h"
41 #include "../../common/SC_SndFileHelpers.hpp"
43 // undefine the shadowed scfft functions
51 spin_lock log_guard
; // needs to be acquired for logging from the helper threads!
55 inline Node
* as_Node(server_node
* node
)
60 // hack!!! we only assume that the 32bit integer mID member can be accessed via Node
61 if (node
->is_synth()) {
62 sc_synth
* s
= static_cast<sc_synth
*>(node
);
65 void * nodePointer
= &node
->node_id
;
66 return (Node
*)nodePointer
;
70 void pause_node(Unit
* unit
)
72 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
73 sc_factory
->add_pause_node(node
);
76 void free_node(Unit
* unit
)
78 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
79 sc_factory
->add_done_node(node
);
82 void free_node_and_preceding(Unit
* unit
)
84 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
85 sc_factory
->add_done_node(node
);
87 if (node
->get_parent()->is_parallel()) {
88 spin_lock::scoped_lock
lock(log_guard
);
89 log("parallel groups have no notion of preceding nodes\n");
93 server_node
* preceding
= node
->previous_node();
95 sc_factory
->add_done_node(preceding
);
98 void free_node_and_pause_preceding(Unit
* unit
)
100 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
101 sc_factory
->add_done_node(node
);
103 if (node
->get_parent()->is_parallel()) {
104 spin_lock::scoped_lock
lock(log_guard
);
105 log("parallel groups have no notion of preceding nodes\n");
109 server_node
* preceding
= node
->previous_node();
111 sc_factory
->add_pause_node(preceding
);
114 void free_node_and_preceding_children(Unit
* unit
)
116 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
117 sc_factory
->add_done_node(node
);
119 if (node
->get_parent()->is_parallel()) {
120 spin_lock::scoped_lock
lock(log_guard
);
121 log("parallel groups have no notion of preceding nodes");
125 server_node
* preceding
= node
->previous_node();
128 if (preceding
->is_synth())
129 sc_factory
->add_done_node(preceding
);
131 abstract_group
* preceding_group
= static_cast<abstract_group
*>(preceding
);
132 sc_factory
->add_freeAll_node(preceding_group
);
137 void free_node_and_preceding_deep(Unit
* unit
)
139 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
140 sc_factory
->add_done_node(node
);
142 if (node
->get_parent()->is_parallel()) {
143 log("parallel groups have no notion of preceding nodes\n");
147 server_node
* preceding
= node
->previous_node();
150 if (preceding
->is_synth())
151 sc_factory
->add_done_node(preceding
);
153 abstract_group
* preceding_group
= static_cast<abstract_group
*>(preceding
);
154 sc_factory
->add_freeDeep_node(preceding_group
);
158 void free_node_and_all_preceding(Unit
* unit
)
160 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
161 sc_factory
->add_done_node(node
);
163 if (node
->get_parent()->is_parallel()) {
164 spin_lock::scoped_lock
lock(log_guard
);
165 log("parallel groups have no notion of preceding nodes\n");
170 node
= node
->previous_node();
172 sc_factory
->add_done_node(node
);
178 void free_node_and_following(Unit
* unit
)
180 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
181 sc_factory
->add_done_node(node
);
183 if (node
->get_parent()->is_parallel()) {
184 spin_lock::scoped_lock
lock(log_guard
);
185 log("parallel groups have no notion of following nodes\n");
189 server_node
* next
= node
->next_node();
191 sc_factory
->add_done_node(next
);
194 void free_node_and_pause_following(Unit
* unit
)
196 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
197 sc_factory
->add_done_node(node
);
199 if (node
->get_parent()->is_parallel()) {
200 spin_lock::scoped_lock
lock(log_guard
);
201 log("parallel groups have no notion of following nodes\n");
205 server_node
* next
= node
->next_node();
207 sc_factory
->add_pause_node(next
);
210 void free_node_and_following_children(Unit
* unit
)
212 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
213 sc_factory
->add_done_node(node
);
215 if (node
->get_parent()->is_parallel()) {
216 spin_lock::scoped_lock
lock(log_guard
);
217 log("parallel groups have no notion of following nodes\n");
221 server_node
* following
= node
->previous_node();
224 if (following
->is_synth())
225 sc_factory
->add_done_node(following
);
227 abstract_group
* following_group
= static_cast<abstract_group
*>(following
);
228 sc_factory
->add_freeAll_node(following_group
);
232 void free_node_and_following_deep(Unit
* unit
)
234 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
235 sc_factory
->add_done_node(node
);
237 if (node
->get_parent()->is_parallel()) {
238 spin_lock::scoped_lock
lock(log_guard
);
239 log("parallel groups have no notion of following nodes\n");
243 server_node
* following
= node
->previous_node();
246 if (following
->is_synth())
247 sc_factory
->add_done_node(following
);
249 abstract_group
* following_group
= static_cast<abstract_group
*>(following
);
250 sc_factory
->add_freeDeep_node(following_group
);
254 void free_node_and_all_following(Unit
* unit
)
256 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
257 sc_factory
->add_done_node(node
);
259 if (node
->get_parent()->is_parallel()) {
260 spin_lock::scoped_lock
lock(log_guard
);
261 log("parallel groups have no notion of following nodes\n");
266 node
= node
->previous_node();
268 sc_factory
->add_done_node(node
);
274 void free_group_members(Unit
* unit
)
276 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
277 abstract_group
* group
= const_cast<abstract_group
*>(node
->get_parent());
279 sc_factory
->add_freeAll_node(group
);
282 void free_parent_group(Unit
* unit
)
284 server_node
* node
= static_cast<sc_synth
*>(unit
->mParent
);
285 abstract_group
* group
= const_cast<abstract_group
*>(node
->get_parent());
286 sc_factory
->add_done_node(group
);
289 bool get_scope_buffer(World
*inWorld
, int index
, int channels
, int maxFrames
, ScopeBufferHnd
&hnd
)
291 scope_buffer_writer writer
= instance
->get_scope_buffer_writer( index
, channels
, maxFrames
);
293 if( writer
.valid() ) {
294 hnd
.internalData
= writer
.buffer
;
295 hnd
.data
= writer
.data();
296 hnd
.channels
= channels
;
297 hnd
.maxFrames
= maxFrames
;
301 hnd
.internalData
= 0;
306 void push_scope_buffer(World
*inWorld
, ScopeBufferHnd
&hnd
, int frames
)
308 scope_buffer_writer
writer(reinterpret_cast<scope_buffer
*>(hnd
.internalData
));
310 hnd
.data
= writer
.data();
313 void release_scope_buffer(World
*inWorld
, ScopeBufferHnd
&hnd
)
315 scope_buffer_writer
writer(reinterpret_cast<scope_buffer
*>(hnd
.internalData
));
316 instance
->release_scope_buffer_writer( writer
);
320 } /* namespace nova */
325 bool define_unit(const char *inUnitClassName
, size_t inAllocSize
,
326 UnitCtorFunc inCtor
, UnitDtorFunc inDtor
, uint32 inFlags
)
329 nova::sc_factory
->register_ugen(inUnitClassName
, inAllocSize
, inCtor
, inDtor
, inFlags
);
338 bool define_bufgen(const char * name
, BufGenFunc func
)
341 nova::sc_factory
->register_bufgen(name
, func
);
350 bool define_unitcmd(const char * unitClassName
, const char * cmdName
, UnitCmdFunc inFunc
)
352 return nova::sc_factory
->register_ugen_command_function(unitClassName
, cmdName
, inFunc
);
356 bool define_plugincmd(const char * name
, PlugInCmdFunc func
, void * user_data
)
358 return nova::sc_factory
->register_cmd_plugin(name
, func
, user_data
);
361 void * rt_alloc(World
* dummy
, size_t size
)
364 return nova::rt_pool
.malloc(size
);
369 void * rt_realloc(World
* dummy
, void * ptr
, size_t size
)
371 return nova::rt_pool
.realloc(ptr
, size
);
374 void rt_free(World
* dummy
, void * ptr
)
377 nova::rt_pool
.free(ptr
);
380 void * nrt_alloc(size_t size
)
385 void * nrt_realloc(void * ptr
, size_t size
)
387 return realloc(ptr
, size
);
390 void nrt_free(void * ptr
)
395 void clear_outputs(Unit
*unit
, int samples
)
397 size_t outputs
= unit
->mNumOutputs
;
399 if ((samples
& 15) == 0)
400 for (size_t i
=0; i
!=outputs
; ++i
)
401 nova::zerovec_simd(unit
->mOutBuf
[i
], samples
);
403 for (size_t i
=0; i
!=outputs
; ++i
)
404 nova::zerovec(unit
->mOutBuf
[i
], samples
);
407 void node_end(struct Node
* node
)
409 nova::server_node
* s
= nova::instance
->find_node(node
->mID
);
410 nova::sc_factory
->add_done_node(s
);
413 void node_set_run(struct Node
* node
, int run
)
415 using namespace nova
;
416 server_node
* s
= instance
->find_node(node
->mID
);
419 sc_factory
->add_pause_node(s
);
421 sc_factory
->add_resume_node(s
);
425 int print(const char *fmt
, ...)
428 va_start(vargs
, fmt
);
430 nova::log_guard
.lock();
431 bool status
= nova::instance
->log_printf(fmt
, vargs
);
432 nova::log_guard
.unlock();
435 return (status
== true) ? 0 : -1;
438 /* todo: we need to implement most of the done actions */
439 void done_action(int done_action
, struct Unit
*unit
)
441 using namespace nova
;
442 switch(done_action
) {
444 // do nothing when the UGen is finished
448 // pause the enclosing synth, but do not free it
449 nova::pause_node(unit
);
452 // free the enclosing synth
453 nova::free_node(unit
);
457 // free both this synth and the preceding node
458 nova::free_node_and_preceding(unit
);
462 // free both this synth and the following node
463 nova::free_node_and_following(unit
);
467 // free this synth; if the preceding node is a group then do g_freeAll on it, else free it
468 nova::free_node_and_preceding_children(unit
);
472 nova::free_node_and_following_children(unit
);
473 // free this synth; if the following node is a group then do g_freeAll on it, else free it
477 //free this synth and all preceding nodes in this group
478 nova::free_node_and_all_preceding(unit
);
482 //free this synth and all following nodes in this group
483 nova::free_node_and_all_following(unit
);
487 // free this synth and pause the preceding node
488 nova::free_node_and_pause_preceding(unit
);
492 // free this synth and pause the following node
493 nova::free_node_and_pause_following(unit
);
497 // free this synth and if the preceding node is a group then do g_deepFree on it, else free it
498 nova::free_node_and_preceding_deep(unit
);
502 // free this synth and if the following node is a group then do g_deepFree on it, else free it
503 nova::free_node_and_following_deep(unit
);
507 // free this synth and all other nodes in this group (before and after)
508 nova::free_group_members(unit
);
512 // free the enclosing group and all nodes within it (including this synth)
513 nova::free_parent_group(unit
);
521 int buf_alloc(SndBuf
* buf
, int channels
, int frames
, double samplerate
)
523 return nova::sc_factory
->allocate_buffer(buf
, channels
, frames
, samplerate
);
526 void send_trigger(Node
* unit
, int trigger_id
, float value
)
528 nova::instance
->send_trigger(unit
->mID
, trigger_id
, value
);
531 void world_lock(World
*world
)
533 world
->mNRTLock
->Lock();
536 void world_unlock(World
*world
)
538 world
->mNRTLock
->Unlock();
541 Node
* get_node(World
*world
, int id
)
543 nova::server_node
* node
= nova::instance
->find_node(id
);
544 return nova::as_Node(node
);
547 void send_node_reply(Node
* node
, int reply_id
, const char* command_name
, int argument_count
, const float* values
)
549 if (!nova::sc_factory
->world
.mRealTime
)
552 nova::instance
->send_node_reply(node
->mID
, reply_id
, command_name
, argument_count
, values
);
555 int do_asynchronous_command(World
*inWorld
, void* replyAddr
, const char* cmdName
, void *cmdData
,
556 AsyncStageFn stage2
, // stage2 is non real time
557 AsyncStageFn stage3
, // stage3 is real time - completion msg performed if stage3 returns true
558 AsyncStageFn stage4
, // stage4 is non real time - sends done if stage4 returns true
560 int completionMsgSize
, void* completionMsgData
)
562 nova::instance
->do_asynchronous_command(inWorld
, replyAddr
, cmdName
, cmdData
,
563 stage2
, stage3
, stage4
, cleanup
,
564 completionMsgSize
, completionMsgData
);
574 inline void initialize_rate(Rate
& rate
, double sample_rate
, int blocksize
)
576 rate
.mSampleRate
= sample_rate
;
577 rate
.mSampleDur
= 1. / sample_rate
;
578 rate
.mRadiansPerSample
= 2 * M_PI
/ sample_rate
;
580 rate
.mBufLength
= blocksize
;
581 rate
.mBufDuration
= blocksize
/ sample_rate
;
582 rate
.mBufRate
= sample_rate
/ blocksize
;
583 rate
.mSlopeFactor
= 1. / blocksize
;
585 div_t div_result
= std::div(blocksize
, 3);
586 rate
.mFilterLoops
= div_result
.quot
;
587 rate
.mFilterRemain
= div_result
.rem
;
588 if (rate
.mFilterLoops
== 0.)
589 rate
.mFilterSlope
= 0.;
591 rate
.mFilterSlope
= 1. / rate
.mFilterLoops
;
595 void sc_plugin_interface::initialize(server_arguments
const & args
, float * control_busses
)
597 done_nodes
.reserve(64);
598 pause_nodes
.reserve(16);
599 resume_nodes
.reserve(16);
600 freeAll_nodes
.reserve(16);
601 freeDeep_nodes
.reserve(16);
603 /* define functions */
604 sc_interface
.fDefineUnit
= &define_unit
;
605 sc_interface
.fDefineBufGen
= &define_bufgen
;
606 sc_interface
.fDefinePlugInCmd
= &define_plugincmd
;
607 sc_interface
.fDefineUnitCmd
= &define_unitcmd
;
609 /* interface functions */
610 sc_interface
.fNodeEnd
= &node_end
;
611 sc_interface
.fGetNode
= &get_node
;
612 sc_interface
.fNodeRun
= &node_set_run
;
613 sc_interface
.fPrint
= &print
;
614 sc_interface
.fDoneAction
= &done_action
;
616 /* sndfile functions */
618 sc_interface
.fSndFileFormatInfoFromStrings
= NULL
;
620 sc_interface
.fSndFileFormatInfoFromStrings
= &sndfileFormatInfoFromStrings
;
624 sc_interface
.mSine
= gSine
;
625 sc_interface
.mCosecant
= gInvSine
;
626 sc_interface
.mSineSize
= kSineSize
;
627 sc_interface
.mSineWavetable
= gSineWavetable
;
629 /* memory allocation */
630 sc_interface
.fRTAlloc
= &rt_alloc
;
631 sc_interface
.fRTRealloc
= &rt_realloc
;
632 sc_interface
.fRTFree
= &rt_free
;
634 sc_interface
.fNRTAlloc
= &nrt_alloc
;
635 sc_interface
.fNRTRealloc
= &nrt_realloc
;
636 sc_interface
.fNRTFree
= &nrt_free
;
639 sc_interface
.fClearUnitOutputs
= clear_outputs
;
641 /* buffer functions */
642 sc_interface
.fBufAlloc
= &buf_alloc
;
644 /* trigger functions */
645 sc_interface
.fSendTrigger
= &send_trigger
;
646 sc_interface
.fSendNodeReply
= &send_node_reply
;
649 sc_interface
.fNRTLock
= &world_lock
;
650 sc_interface
.fNRTUnlock
= &world_unlock
;
651 world
.mNRTLock
= new SC_Lock();
654 sc_interface
.fSCfftCreate
= &scfft_create
;
655 sc_interface
.fSCfftDestroy
= &scfft_destroy
;
656 sc_interface
.fSCfftDoFFT
= &scfft_dofft
;
657 sc_interface
.fSCfftDoIFFT
= &scfft_doifft
;
660 sc_interface
.fGetScopeBuffer
= &get_scope_buffer
;
661 sc_interface
.fPushScopeBuffer
= &push_scope_buffer
;
662 sc_interface
.fReleaseScopeBuffer
= &release_scope_buffer
;
665 sc_interface
.fDoAsynchronousCommand
= &do_asynchronous_command
;
667 /* initialize world */
669 world
.mControlBus
= control_busses
;
670 world
.mNumControlBusChannels
= args
.control_busses
;
671 world
.mControlBusTouched
= new int32
[args
.control_busses
];
672 std::fill(world
.mControlBusTouched
, world
.mControlBusTouched
+ args
.control_busses
, -1);
675 audio_busses
.initialize(args
.audio_busses
, args
.blocksize
);
677 world
.mAudioBus
= audio_busses
.buffers
;
678 world
.mNumAudioBusChannels
= args
.audio_busses
;
679 world
.mAudioBusTouched
= new int32
[args
.audio_busses
];
680 world
.mAudioBusLocks
= audio_busses
.locks
;
681 world
.mControlBusLock
= new spin_lock();
682 std::fill(world
.mAudioBusTouched
, world
.mAudioBusTouched
+ args
.audio_busses
, -1);
685 world
.mNumSndBufs
= args
.buffers
;
686 world
.mSndBufs
= new SndBuf
[world
.mNumSndBufs
];
687 world
.mSndBufsNonRealTimeMirror
= new SndBuf
[world
.mNumSndBufs
];
688 world
.mSndBufUpdates
= new SndBufUpdates
[world
.mNumSndBufs
];
689 memset(world
.mSndBufs
, 0, world
.mNumSndBufs
*sizeof(SndBuf
));
690 memset(world
.mSndBufsNonRealTimeMirror
, 0, world
.mNumSndBufs
*sizeof(SndBuf
));
691 memset(world
.mSndBufUpdates
, 0, world
.mNumSndBufs
*sizeof(SndBufUpdates
));
692 world
.mBufCounter
= 0;
694 async_buffer_guards
.reset(new boost::mutex
[world
.mNumSndBufs
]);
697 world
.mBufLength
= args
.blocksize
;
698 world
.mSampleRate
= args
.samplerate
;
700 initialize_rate(world
.mFullRate
, args
.samplerate
, args
.blocksize
);
701 initialize_rate(world
.mBufRate
, double(args
.samplerate
)/args
.blocksize
, 1);
703 world
.mNumInputs
= args
.input_channels
;
704 world
.mNumOutputs
= args
.output_channels
;
706 world
.mRealTime
= !args
.non_rt
;
709 void sc_plugin_interface::reset_sampling_rate(int sr
)
711 world
.mSampleRate
= sr
;
713 initialize_rate(world
.mFullRate
, sr
, world
.mBufLength
);
714 initialize_rate(world
.mBufRate
, double(sr
)/world
.mBufLength
, 1);
718 void sc_done_action_handler::update_nodegraph(void)
720 std::for_each(done_nodes
.begin(), done_nodes
.end(), boost::bind(&nova_server::free_node
, instance
, _1
));
723 std::for_each(resume_nodes
.begin(), resume_nodes
.end(), boost::bind(&nova_server::node_resume
, instance
, _1
));
724 resume_nodes
.clear();
726 std::for_each(pause_nodes
.begin(), pause_nodes
.end(), boost::bind(&nova_server::node_pause
, instance
, _1
));
729 std::for_each(freeDeep_nodes
.begin(), freeDeep_nodes
.end(), boost::bind(&nova_server::group_free_deep
, instance
, _1
));
730 freeDeep_nodes
.clear();
732 std::for_each(freeAll_nodes
.begin(), freeAll_nodes
.end(), boost::bind(&nova_server::group_free_all
, instance
, _1
));
733 freeAll_nodes
.clear();
736 sc_plugin_interface::~sc_plugin_interface(void)
738 delete[] world
.mAudioBusTouched
;
739 delete[] world
.mControlBus
;
740 delete[] world
.mControlBusTouched
;
741 delete[] world
.mSndBufs
;
742 delete[] world
.mSndBufsNonRealTimeMirror
;
743 delete[] world
.mSndBufUpdates
;
744 delete world
.mNRTLock
;
750 sample
* allocate_buffer(size_t samples
)
752 const size_t alloc_size
= samples
* sizeof(sample
);
753 sample
* ret
= (sample
*)calloc_aligned(alloc_size
);
755 mlock(ret
, alloc_size
);
759 void free_buffer(sample
* chunk
)
764 inline int32
bufmask(int32 x
)
766 return (1 << (31 - CLZ(x
))) - 1;
769 inline void sndbuf_init(SndBuf
* buf
)
781 buf
->isLocal
= false;
784 inline void sndbuf_copy(SndBuf
* dest
, const SndBuf
* src
)
786 dest
->samplerate
= src
->samplerate
;
787 dest
->sampledur
= src
->sampledur
;
788 dest
->data
= src
->data
;
789 dest
->channels
= src
->channels
;
790 dest
->samples
= src
->samples
;
791 dest
->frames
= src
->frames
;
792 dest
->mask
= src
->mask
;
793 dest
->mask1
= src
->mask1
;
794 dest
->coord
= src
->coord
;
795 dest
->sndfile
= src
->sndfile
;
796 dest
->isLocal
= src
->isLocal
;
799 static inline size_t compute_remaining_samples(size_t frames_per_read
, size_t already_read
, size_t total_frames
)
801 int remain
= frames_per_read
;
802 if (already_read
+ frames_per_read
> total_frames
)
803 remain
= total_frames
- already_read
;
807 void read_channel(SndfileHandle
& sf
, uint32_t channel_count
, const uint32_t * channel_data
, uint32 total_frames
, sample
* data
)
809 const unsigned int frames_per_read
= 1024;
810 sized_array
<sample
> read_frame(sf
.channels() * frames_per_read
);
812 if (channel_count
== 1) {
813 // fast-path for single-channel read
814 for (size_t i
= 0; i
< total_frames
; i
+= frames_per_read
) {
815 int remaining_samples
= compute_remaining_samples(frames_per_read
, i
, total_frames
);
816 size_t read
= sf
.readf(read_frame
.c_array(), remaining_samples
);
818 size_t channel_mapping
= channel_data
[0];
819 for (size_t frame
= 0; frame
!= read
; ++frame
) {
820 data
[0] = read_frame
[frame
* sf
.channels() + channel_mapping
];
821 data
+= channel_count
;
825 for (size_t i
= 0; i
< total_frames
; i
+= frames_per_read
) {
826 int remaining_samples
= compute_remaining_samples(frames_per_read
, i
, total_frames
);
827 size_t read
= sf
.readf(read_frame
.c_array(), remaining_samples
);
829 for (size_t frame
= 0; frame
!= read
; ++frame
) {
830 for (size_t c
= 0; c
!= channel_count
; ++c
) {
831 size_t channel_mapping
= channel_data
[c
];
832 data
[c
] = read_frame
[frame
* sf
.channels() + channel_mapping
];
834 data
+= channel_count
;
842 int sc_plugin_interface::allocate_buffer(SndBuf
* buf
, uint32_t frames
, uint32_t channels
, double samplerate
)
844 const uint32_t samples
= frames
* channels
;
846 return kSCErr_Failed
; /* invalid buffer size */
848 sample
* data
= nova::allocate_buffer(samples
);
850 return kSCErr_Failed
; /* could not allocate memory */
854 buf
->channels
= channels
;
855 buf
->frames
= frames
;
856 buf
->samples
= samples
;
857 buf
->mask
= bufmask(samples
); /* for delay lines */
858 buf
->mask1
= buf
->mask
- 1; /* for oscillators */
859 buf
->samplerate
= samplerate
;
860 buf
->sampledur
= 1.0 / samplerate
;
861 buf
->isLocal
= false;
865 SndBuf
* sc_plugin_interface::allocate_buffer(uint32_t index
, uint32_t frames
, uint32_t channels
)
867 SndBuf
* buf
= World_GetNRTBuf(&world
, index
);
868 allocate_buffer(buf
, frames
, channels
, world
.mFullRate
.mSampleRate
);
872 int sc_plugin_interface::buffer_read_alloc(uint32_t index
, const char * filename
, uint32_t start
, uint32_t frames
)
874 SndfileHandle
f(filename
);
876 return -1; /* file cannot be opened */
878 const size_t sf_frames
= f
.frames();
880 if (start
> sf_frames
)
883 if (frames
== 0 || frames
> sf_frames
- start
)
884 frames
= sf_frames
- start
;
886 SndBuf
* buf
= World_GetNRTBuf(&world
, index
);
887 allocate_buffer(buf
, frames
, f
.channels(), f
.samplerate());
889 f
.seek(start
, SEEK_SET
);
890 f
.readf(buf
->data
, frames
);
895 int sc_plugin_interface::buffer_alloc_read_channels(uint32_t index
, const char * filename
, uint32_t start
,
896 uint32_t frames
, uint32_t channel_count
,
897 const uint32_t * channel_data
)
899 SndfileHandle
f(filename
);
901 return -1; /* file cannot be opened */
903 uint32_t sf_channels
= uint32_t(f
.channels());
904 const uint32_t * max_chan
= std::max_element(channel_data
, channel_data
+ channel_count
);
905 if (*max_chan
>= sf_channels
)
908 const size_t sf_frames
= f
.frames();
910 if (start
> sf_frames
)
913 if (frames
== 0 || frames
> sf_frames
- start
)
914 frames
= sf_frames
- start
;
916 SndBuf
* buf
= World_GetNRTBuf(&world
, index
);
917 allocate_buffer(buf
, frames
, channel_count
, f
.samplerate());
919 f
.seek(start
, SEEK_SET
);
920 read_channel(f
, channel_count
, channel_data
, frames
, buf
->data
);
926 int sc_plugin_interface::buffer_write(uint32_t index
, const char * filename
, const char * header_format
, const char * sample_format
,
927 uint32_t start
, uint32_t frames
, bool leave_open
)
929 SndBuf
* buf
= World_GetNRTBuf(&world
, index
);
930 int format
= headerFormatFromString(header_format
) | sampleFormatFromString(sample_format
);
932 SndfileHandle
sf(filename
, SFM_WRITE
, format
, buf
->channels
, buf
->samplerate
);
937 if (frames
== 0xffffffff)
938 frames
= buf
->frames
;
940 const uint32_t remain
= uint32_t(buf
->frames
) > start
? buf
->frames
- start
: 0;
941 const uint32_t frames_to_write
= std::min(remain
, frames
);
944 sf
.writef(buf
->data
+ start
* buf
->channels
, frames_to_write
);
946 if (leave_open
&& !buf
->sndfile
)
947 buf
->sndfile
= sf
.takeOwnership();
952 static int buffer_read_verify(SndfileHandle
const & sf
, size_t min_length
, size_t samplerate
)
956 if (sf
.frames() < min_length
)
957 return -2; /* no more frames to read */
958 if (sf
.samplerate() != samplerate
)
959 return -3; /* sample rate mismatch */
963 int sc_plugin_interface::buffer_read(uint32_t index
, const char * filename
, uint32_t start_file
, uint32_t frames
,
964 uint32_t start_buffer
, bool leave_open
)
966 SndBuf
* buf
= World_GetNRTBuf(&world
, index
);
968 if (uint32_t(buf
->frames
) < start_buffer
)
969 return -2; /* buffer already full */
971 SndfileHandle
sf(filename
, SFM_READ
);
972 int error
= buffer_read_verify(sf
, start_file
, buf
->samplerate
);
976 if (sf
.channels() != buf
->channels
)
977 return -3; /* sample rate or channel count mismatch */
979 const uint32_t buffer_remain
= buf
->frames
- start_buffer
;
980 const uint32_t file_remain
= sf
.frames() - start_file
;
981 const uint32_t frames_to_read
= std::min(frames
, std::min(buffer_remain
, file_remain
));
983 sf
.seek(start_file
, SEEK_SET
);
984 sf
.readf(buf
->data
+ start_buffer
*buf
->channels
, frames_to_read
);
987 buf
->sndfile
= sf
.takeOwnership();
991 int sc_plugin_interface::buffer_read_channel(uint32_t index
, const char * filename
, uint32_t start_file
, uint32_t frames
,
992 uint32_t start_buffer
, bool leave_open
, uint32_t channel_count
,
993 const uint32_t * channel_data
)
995 SndBuf
* buf
= World_GetNRTBuf(&world
, index
);
997 if (channel_count
!= uint32_t(buf
->channels
))
998 return -2; /* channel count mismatch */
1000 if (uint32_t(buf
->frames
) >= start_buffer
)
1001 return -2; /* buffer already full */
1003 SndfileHandle
sf(filename
, SFM_READ
);
1004 int error
= buffer_read_verify(sf
, start_file
, buf
->samplerate
);
1008 uint32_t sf_channels
= uint32_t(sf
.channels());
1009 const uint32_t * max_chan
= std::max_element(channel_data
, channel_data
+ channel_count
);
1010 if (*max_chan
>= sf_channels
)
1012 const uint32_t buffer_remain
= buf
->frames
- start_buffer
;
1013 const uint32_t file_remain
= sf
.frames() - start_file
;
1015 const uint32_t frames_to_read
= std::min(frames
, std::min(buffer_remain
, file_remain
));
1017 sf
.seek(start_file
, SEEK_SET
);
1018 read_channel(sf
, channel_count
, channel_data
, frames
, buf
->data
);
1021 buf
->sndfile
= sf
.takeOwnership();
1025 void sc_plugin_interface::buffer_close(uint32_t index
)
1027 SndBuf
* buf
= World_GetNRTBuf(&world
, index
);
1029 if (buf
->sndfile
== NULL
)
1031 sf_close(buf
->sndfile
);
1032 buf
->sndfile
= NULL
;
1036 void sc_plugin_interface::buffer_zero(uint32_t index
)
1038 SndBuf
* buf
= World_GetNRTBuf(&world
, index
);
1040 uint32_t length
= buf
->frames
* buf
->channels
;
1042 uint32_t unrolled
= length
& ~63;
1043 uint32_t remain
= length
& 63;
1045 zerovec_simd(buf
->data
, unrolled
);
1046 zerovec(buf
->data
+ unrolled
, remain
);
1049 sample
* sc_plugin_interface::buffer_generate(uint32_t buffer_index
, const char* cmd_name
, struct sc_msg_iter
& msg
)
1051 return sc_factory
->run_bufgen(&world
, cmd_name
, buffer_index
, &msg
);
1054 void sc_plugin_interface::buffer_sync(uint32_t index
)
1056 sndbuf_copy(world
.mSndBufs
+ index
, world
.mSndBufsNonRealTimeMirror
+ index
);
1057 increment_write_updates(index
);
1060 void sc_plugin_interface::free_buffer(uint32_t index
)
1062 SndBuf
* buf
= world
.mSndBufsNonRealTimeMirror
+ index
;
1064 sf_close(buf
->sndfile
);
1068 void sc_plugin_interface::initialize_synths_perform(void)
1070 for (std::size_t i
= 0; i
!= uninitialized_synths
.size(); ++i
)
1072 sc_synth
* synth
= static_cast<sc_synth
*>(uninitialized_synths
[i
]);
1073 if (likely(synth
->get_parent())) // it is possible to remove a synth before it is initialized
1077 synths_to_initialize
= false;
1078 uninitialized_synths
.clear();
1081 } /* namespace nova */