3rdparty/licenseReport: Add seperate LGPL checks
[haiku.git] / src / add-ons / media / media-add-ons / vst_host / VSTNode.cpp
blob13ae66d1ac131276ea19843e5be76eb6cc4e0bde
1 /*
2 * Copyright 2012, Gerasim Troeglazov (3dEyes**), 3dEyes@gmail.com.
3 * All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
7 #include <ByteOrder.h>
8 #include <Buffer.h>
9 #include <BufferGroup.h>
10 #include <TimeSource.h>
11 #include <ParameterWeb.h>
12 #include <String.h>
14 #include <stdio.h>
15 #include <string.h>
17 #include "VSTNode.h"
19 //VSTNode
20 VSTNode::~VSTNode()
22 Quit();
25 VSTNode::VSTNode(BMediaAddOn* addon, const char* name, const char* path)
27 BMediaNode(name),
28 BBufferConsumer(B_MEDIA_RAW_AUDIO),
29 BBufferProducer(B_MEDIA_RAW_AUDIO),
30 BControllable(),
31 BMediaEventLooper(),
32 fAddOn(addon),
33 fOutputMediaEnabled(true),
34 fDownstreamLatency(0),
35 fProcessLatency(0)
37 fPlugin = new VSTPlugin();
38 fPlugin->LoadModule(path);
41 //BMediaNode
42 BMediaAddOn*
43 VSTNode::AddOn(int32* id) const
45 if(fAddOn)
46 *id = 0;
47 return fAddOn;
50 status_t
51 VSTNode::HandleMessage(int32 message, const void* data, size_t size)
53 if((BControllable::HandleMessage(message, data, size) != B_OK) &&
54 (BBufferConsumer::HandleMessage(message, data, size) != B_OK) &&
55 (BBufferProducer::HandleMessage(message, data, size) != B_OK) &&
56 (BControllable::HandleMessage(message, data, size) != B_OK) ) {
57 BMediaNode::HandleMessage(message, data, size);
58 return B_OK;
60 BMediaNode::HandleBadMessage(message, data, size);
61 return B_ERROR;
64 void
65 VSTNode::NodeRegistered()
67 fPreferredFormat.type = B_MEDIA_RAW_AUDIO;
68 fPreferredFormat.u.raw_audio.buffer_size = BUFF_SIZE;
69 fPreferredFormat.u.raw_audio = media_raw_audio_format::wildcard;
70 fPreferredFormat.u.raw_audio.channel_count =
71 media_raw_audio_format::wildcard.channel_count;
72 fPreferredFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
74 fFormat.type = B_MEDIA_RAW_AUDIO;
75 fFormat.u.raw_audio = media_raw_audio_format::wildcard;
77 fInputMedia.destination.port = ControlPort();
78 fInputMedia.destination.id = ID_AUDIO_INPUT;
79 fInputMedia.node = Node();
80 fInputMedia.source = media_source::null;
81 fInputMedia.format = fFormat;
82 strncpy(fInputMedia.name, "Audio Input", B_MEDIA_NAME_LENGTH);
84 fOutputMedia.source.port = ControlPort();
85 fOutputMedia.source.id = ID_AUDIO_OUTPUT;
86 fOutputMedia.node = Node();
87 fOutputMedia.destination = media_destination::null;
88 fOutputMedia.format = fFormat;
89 strncpy(fOutputMedia.name, "Audio Output", B_MEDIA_NAME_LENGTH);
91 InitParameterValues();
92 InitParameterWeb();
94 SetPriority(B_REAL_TIME_PRIORITY);
95 Run();
98 //BControllable
99 status_t
100 VSTNode::GetParameterValue(int32 id, bigtime_t* lastChangeTime, void* value,
101 size_t *size)
103 if (*size < sizeof(float) || *size < sizeof(int32))
104 return B_NO_MEMORY;
106 type_code v_type = B_FLOAT_TYPE;
108 BParameter *param;
109 for(int i = 0; i < fWeb->CountParameters(); i++) {
110 param = fWeb->ParameterAt(i);
111 if(param->ID() == id) {
112 v_type = param->ValueType();
113 break;
117 *size = sizeof(float);
119 if (id == P_MUTE) {
120 *(int32*)value = fMute;
121 *lastChangeTime = fMuteLastChanged;
122 return B_OK;
123 } else if (id == P_BYPASS) {
124 *(int32*)value = fByPass;
125 *lastChangeTime = fByPassLastChanged;
126 return B_OK;
127 } else {
128 int32 idx = id - P_PARAM;
129 if (idx >= 0 && idx < fPlugin->ParametersCount()) {
130 VSTParameter *param = fPlugin->Parameter(idx);
132 if (v_type == B_FLOAT_TYPE)
133 *(float*)value = param->Value();
135 if (v_type == B_INT32_TYPE)
136 *(int32*)value = (int32)ceil(param->Value());
138 *lastChangeTime = param->LastChangeTime();
139 return B_OK;
142 return B_ERROR;
145 void
146 VSTNode::SetParameterValue(int32 id, bigtime_t time, const void* value,
147 size_t size)
149 int32 idx = id - P_PARAM;
150 if ((idx >= 0 && idx < fPlugin->ParametersCount()) || id == P_MUTE ||
151 id == P_BYPASS) {
152 media_timed_event ev(time, BTimedEventQueue::B_PARAMETER, (void*)value,
153 BTimedEventQueue::B_NO_CLEANUP, size, id, "VSTParam");
154 //dirty hack for parameter processing (mediakit bug????)
155 ParameterEventProcessing(&ev);
156 EventQueue()->AddEvent(ev);
160 //BBufferConsumer
161 void
162 VSTNode::BufferReceived(BBuffer* buffer)
164 if (buffer->Header()->destination != fInputMedia.destination.id) {
165 buffer->Recycle();
166 return;
169 if (fOutputMedia.destination == media_destination::null ||
170 !fOutputMediaEnabled) {
171 buffer->Recycle();
172 return;
175 FilterBuffer(buffer);
177 status_t err = SendBuffer(buffer, fOutputMedia.source,
178 fOutputMedia.destination);
180 if (err < B_OK)
181 buffer->Recycle();
184 status_t
185 VSTNode::AcceptFormat(const media_destination &dst, media_format* format)
187 if (dst != fInputMedia.destination)
188 return B_MEDIA_BAD_DESTINATION;
190 if (format->type != B_MEDIA_RAW_AUDIO)
191 return B_MEDIA_BAD_FORMAT;
193 ValidateFormat(
194 (fFormat.u.raw_audio.format != media_raw_audio_format::wildcard.format) ?
195 fFormat : fPreferredFormat, *format);
197 return B_OK;
200 status_t
201 VSTNode::GetNextInput(int32* cookie, media_input* input)
203 if (*cookie)
204 return B_BAD_INDEX;
206 ++*cookie;
207 *input = fInputMedia;
208 return B_OK;
211 void
212 VSTNode::DisposeInputCookie(int32 cookie)
216 status_t
217 VSTNode::FormatChanged(const media_source &src, const media_destination &dst,
218 int32 changeTag, const media_format &format)
220 return B_MEDIA_BAD_FORMAT;
223 void
224 VSTNode::ProducerDataStatus(const media_destination &dst, int32 status,
225 bigtime_t when)
227 if (fOutputMedia.destination != media_destination::null)
228 SendDataStatus(status, fOutputMedia.destination, when);
231 status_t
232 VSTNode::GetLatencyFor( const media_destination &dst, bigtime_t* latency,
233 media_node_id* outTimeSource)
235 if (dst != fInputMedia.destination)
236 return B_MEDIA_BAD_DESTINATION;
238 *latency = fDownstreamLatency + fProcessLatency;
239 *outTimeSource = TimeSource()->ID();
240 return B_OK;
243 status_t
244 VSTNode::Connected(const media_source& source,
245 const media_destination& destination, const media_format& format,
246 media_input* input)
248 if (destination != fInputMedia.destination)
249 return B_MEDIA_BAD_DESTINATION;
251 if (fInputMedia.source != media_source::null)
252 return B_MEDIA_ALREADY_CONNECTED;
254 fInputMedia.source = source;
255 fInputMedia.format = format;
256 *input = fInputMedia;
257 fFormat = format;
259 return B_OK;
262 void
263 VSTNode::Disconnected(const media_source &src, const media_destination &dst)
265 if(fInputMedia.source!=src || dst!=fInputMedia.destination)
266 return;
268 fInputMedia.source = media_source::null;
270 if(fOutputMedia.destination == media_destination::null)
271 fFormat.u.raw_audio = media_raw_audio_format::wildcard;
273 fInputMedia.format = fFormat;
276 //BBufferProducer
277 status_t
278 VSTNode::FormatSuggestionRequested(media_type type, int32 quality,
279 media_format* format)
281 if (type != B_MEDIA_RAW_AUDIO)
282 return B_MEDIA_BAD_FORMAT;
284 if (fFormat.u.raw_audio.format != media_raw_audio_format::wildcard.format)
285 *format = fFormat;
286 else
287 *format = fPreferredFormat;
289 return B_OK;
292 status_t
293 VSTNode::FormatProposal(const media_source &src, media_format* format)
295 if (src != fOutputMedia.source)
296 return B_MEDIA_BAD_SOURCE;
298 if (format->type != B_MEDIA_RAW_AUDIO)
299 return B_MEDIA_BAD_FORMAT;
301 ValidateFormat(
302 (fFormat.u.raw_audio.format != media_raw_audio_format::wildcard.format) ?
303 fFormat : fPreferredFormat, *format);
305 return B_OK;
308 status_t
309 VSTNode::FormatChangeRequested(const media_source &src,
310 const media_destination &dst, media_format* format, int32* _deprecated_)
312 return B_MEDIA_BAD_FORMAT;
315 void
316 VSTNode::LateNoticeReceived(const media_source &src,
317 bigtime_t late, bigtime_t when)
319 if (src != fOutputMedia.source || fInputMedia.source == media_source::null)
320 return;
322 NotifyLateProducer(fInputMedia.source, late, when);
325 status_t
326 VSTNode::GetNextOutput(int32 *cookie, media_output* output)
328 if (*cookie)
329 return B_BAD_INDEX;
331 ++*cookie;
332 *output = fOutputMedia;
333 return B_OK;
336 status_t
337 VSTNode::DisposeOutputCookie(int32 cookie)
339 return B_OK;
342 status_t
343 VSTNode::SetBufferGroup(const media_source &src, BBufferGroup* group)
345 status_t ret;
346 int32 changeTag;
348 if (src != fOutputMedia.source)
349 return B_MEDIA_BAD_SOURCE;
351 if (fInputMedia.source == media_source::null)
352 return B_ERROR;
354 ret = SetOutputBuffersFor(fInputMedia.source, fInputMedia.destination,
355 group, 0, &changeTag);
357 return ret;
360 status_t
361 VSTNode::PrepareToConnect( const media_source &src, const media_destination &dst,
362 media_format* format, media_source* out_source, char* name)
364 status_t ret = B_OK;
366 if (src != fOutputMedia.source)
367 return B_MEDIA_BAD_SOURCE;
369 if (format->type != B_MEDIA_RAW_AUDIO)
370 return B_MEDIA_BAD_FORMAT;
372 if (fOutputMedia.destination != media_destination::null)
373 return B_MEDIA_ALREADY_CONNECTED;
375 ret = ValidateFormat(
376 (fFormat.u.raw_audio.format != media_raw_audio_format::wildcard.format) ?
377 fFormat : fPreferredFormat, *format);
379 if (ret < B_OK)
380 return ret;
382 SetOutputFormat(*format);
384 fOutputMedia.destination = dst;
385 fOutputMedia.format = *format;
387 *out_source = fOutputMedia.source;
388 strncpy(name, fOutputMedia.name, B_MEDIA_NAME_LENGTH);
390 return B_OK;
393 void
394 VSTNode::Connect(status_t status, const media_source &src,
395 const media_destination &dst, const media_format &format, char* name)
397 if (status < B_OK) {
398 fOutputMedia.destination = media_destination::null;
399 return;
402 strncpy(name, fOutputMedia.name, B_MEDIA_NAME_LENGTH);
403 fOutputMedia.destination = dst;
404 fFormat = format;
406 media_node_id timeSource;
407 FindLatencyFor(fOutputMedia.destination, &fDownstreamLatency, &timeSource);
409 InitFilter();
411 fProcessLatency = GetFilterLatency();
412 SetEventLatency(fDownstreamLatency + fProcessLatency);
414 if (fInputMedia.source != media_source::null) {
415 SendLatencyChange(fInputMedia.source, fInputMedia.destination,
416 EventLatency()+SchedulingLatency());
419 bigtime_t duration = 0;
421 int sample_size = (fFormat.u.raw_audio.format & 0xf)*
422 fFormat.u.raw_audio.channel_count;
423 if (fFormat.u.raw_audio.buffer_size > 0 &&
424 fFormat.u.raw_audio.frame_rate > 0 &&
425 sample_size > 0) {
426 duration = (bigtime_t)(((fFormat.u.raw_audio.buffer_size / sample_size) /
427 fFormat.u.raw_audio.frame_rate) * 1000000.0);
430 SetBufferDuration(duration);
433 void
434 VSTNode::Disconnect(const media_source &src, const media_destination &dst)
436 if (src != fOutputMedia.source)
437 return;
439 if (dst != fOutputMedia.destination)
440 return;
442 fOutputMedia.destination = media_destination::null;
444 if (fInputMedia.source == media_source::null)
445 fFormat.u.raw_audio = media_raw_audio_format::wildcard;
447 fOutputMedia.format = fFormat;
450 void
451 VSTNode::EnableOutput(const media_source &src, bool enabled, int32* _deprecated_)
453 if (src != fOutputMedia.source)
454 return;
456 fOutputMediaEnabled = enabled;
459 status_t
460 VSTNode::GetLatency(bigtime_t* latency)
462 *latency = EventLatency() + SchedulingLatency();
463 return B_OK;
466 void
467 VSTNode::LatencyChanged(const media_source &src, const media_destination &dst,
468 bigtime_t latency, uint32 flags)
470 if (src != fOutputMedia.source || dst != fOutputMedia.destination)
471 return;
473 fDownstreamLatency = latency;
474 SetEventLatency(fDownstreamLatency + fProcessLatency);
476 if (fInputMedia.source != media_source::null) {
477 SendLatencyChange(fInputMedia.source,
478 fInputMedia.destination,EventLatency() + SchedulingLatency());
482 //BMediaEventLooper
483 bigtime_t
484 VSTNode::OfflineTime()
486 return 0LL;
489 //VSTNode
490 void
491 VSTNode::HandleEvent(const media_timed_event *event, bigtime_t late,
492 bool realTime)
494 if(event->type == BTimedEventQueue::B_PARAMETER)
495 ParameterEventProcessing(event);
498 void
499 VSTNode::ParameterEventProcessing(const media_timed_event* event)
501 float value = 0.0;
502 int32 value32 = 0;
504 int32 id = event->bigdata;
505 size_t size = event->data;
506 bigtime_t now = TimeSource()->Now();
508 type_code v_type = B_FLOAT_TYPE;
510 BParameter* web_param;
511 for(int i = 0; i < fWeb->CountParameters(); i++) {
512 web_param = fWeb->ParameterAt(i);
513 if(web_param->ID() == id) {
514 v_type = web_param->ValueType();
515 break;
519 if (v_type == B_FLOAT_TYPE)
520 value = *((float*)event->pointer);
521 if (v_type == B_INT32_TYPE) {
522 value32 = *((int32*)event->pointer);
523 value = (float)value32;
526 if (id == P_MUTE) {
527 fMute = value32;
528 fMuteLastChanged = now;
529 BroadcastNewParameterValue(now, id, event->pointer, size);
530 } else if (id == P_BYPASS) {
531 fByPass = value32;
532 fByPassLastChanged = now;
533 BroadcastNewParameterValue(now, id, event->pointer, size);
534 } else {
535 int32 idx = id - P_PARAM;
536 if (idx >= 0 && idx < fPlugin->ParametersCount()) {
537 VSTParameter *param = fPlugin->Parameter(idx);
538 param->SetValue(value);
539 BroadcastNewParameterValue(now, id, &value, size);
544 status_t
545 VSTNode::ValidateFormat(const media_format &preferredFormat,
546 media_format &proposedFormat)
548 status_t ret = B_OK;
550 if (proposedFormat.type != B_MEDIA_RAW_AUDIO) {
551 proposedFormat = preferredFormat;
552 return B_MEDIA_BAD_FORMAT;
555 media_raw_audio_format &wild = media_raw_audio_format::wildcard;
556 media_raw_audio_format &f = proposedFormat.u.raw_audio;
557 const media_raw_audio_format &pref = preferredFormat.u.raw_audio;
559 if(pref.frame_rate != wild.frame_rate && f.frame_rate != pref.frame_rate) {
560 if(f.frame_rate != wild.frame_rate)
561 ret = B_MEDIA_BAD_FORMAT;
562 f.frame_rate = pref.frame_rate;
565 if(pref.channel_count != wild.channel_count &&
566 f.channel_count != pref.channel_count) {
567 if(f.channel_count != wild.channel_count)
568 ret = B_MEDIA_BAD_FORMAT;
569 f.channel_count = pref.channel_count;
572 if(pref.format != wild.format && f.format != pref.format) {
573 if(f.format != wild.format)
574 ret = B_MEDIA_BAD_FORMAT;
575 f.format = pref.format;
578 if(pref.byte_order != wild.byte_order &&
579 f.byte_order != pref.byte_order) {
580 if(f.byte_order != wild.byte_order)
581 ret = B_MEDIA_BAD_FORMAT;
582 f.byte_order = pref.byte_order;
585 if(pref.buffer_size != wild.buffer_size &&
586 f.buffer_size != pref.buffer_size) {
587 if(f.buffer_size != wild.buffer_size)
588 ret = B_MEDIA_BAD_FORMAT;
589 f.buffer_size = pref.buffer_size;
592 return ret;
596 void
597 VSTNode::SetOutputFormat(media_format &format)
599 media_raw_audio_format &f = format.u.raw_audio;
600 media_raw_audio_format &w = media_raw_audio_format::wildcard;
602 if (f.frame_rate == w.frame_rate)
603 f.frame_rate = 44100.0;
605 if (f.channel_count == w.channel_count) {
606 if(fInputMedia.source != media_source::null)
607 f.channel_count = fInputMedia.format.u.raw_audio.channel_count;
608 else
609 f.channel_count = fPlugin->Channels(VST_OUTPUT_CHANNELS);
612 if (f.format == w.format)
613 f.format = media_raw_audio_format::B_AUDIO_FLOAT;
615 if (f.byte_order == w.format) {
616 f.byte_order = (B_HOST_IS_BENDIAN) ?
617 B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
620 if (f.buffer_size == w.buffer_size)
621 f.buffer_size = BUFF_SIZE;
624 void
625 VSTNode::InitParameterValues()
627 fMute = 0;
628 fByPass = 0;
629 fMuteLastChanged = 0LL;
630 fByPassLastChanged = 0LL;
633 void
634 VSTNode::InitParameterWeb()
636 fWeb = new BParameterWeb();
638 bool switch_group_needed = false;
639 for(int i = 0; i < fPlugin->ParametersCount(); i++) {
640 VSTParameter* param = fPlugin->Parameter(i);
641 if (param->Type() == VST_PARAM_CHECKBOX ||
642 param->Type() == VST_PARAM_DROPLIST) {
643 switch_group_needed = true;
644 break;
648 BParameterGroup* fParamGroup = fWeb->MakeGroup("Parameters");
649 BParameterGroup* fSwitchesGroup = switch_group_needed ?
650 fWeb->MakeGroup("Switches") : NULL;
651 BParameterGroup* fAboutGroup = fWeb->MakeGroup("About");
653 BParameter* value;
654 BNullParameter* label;
655 BParameterGroup* group;
657 BParameterGroup* fFControlGroup = fParamGroup->MakeGroup("FilterControl");
658 BParameterGroup* fCheckBoxGroup = switch_group_needed ?
659 fSwitchesGroup->MakeGroup("CheckBoxes") : NULL;
660 BParameterGroup* fSelectorsGroup = switch_group_needed ?
661 fSwitchesGroup->MakeGroup("Selectors") : NULL;
663 fFControlGroup->MakeDiscreteParameter(P_MUTE,
664 B_MEDIA_NO_TYPE,"Mute", B_ENABLE);
665 fFControlGroup->MakeDiscreteParameter(P_BYPASS,
666 B_MEDIA_NO_TYPE,"ByPass", B_ENABLE);
668 for(int i = 0; i < fPlugin->ParametersCount(); i++) {
669 VSTParameter *param = fPlugin->Parameter(i);
670 switch(param->Type()) {
671 case VST_PARAM_CHECKBOX:
673 BString str;
674 str << param->Name() << " (" << param->MinimumValue()
675 << "/" << param->MaximumValue() << ")";
676 value = fCheckBoxGroup->MakeDiscreteParameter(
677 P_PARAM + param->Index(), B_MEDIA_NO_TYPE,
678 str.String(), B_ENABLE);
679 break;
681 case VST_PARAM_DROPLIST:
683 BDiscreteParameter *dvalue =
684 fSelectorsGroup->MakeDiscreteParameter(P_PARAM + param->Index(),
685 B_MEDIA_NO_TYPE, param->Name(), B_OUTPUT_MUX);
686 for(int j = 0; j < param->ListCount(); j++) {
687 dvalue->AddItem( param->ListItemAt(j)->Index,
688 param->ListItemAt(j)->Name.String());
690 break;
692 //sliders
693 default:
695 BString str;
696 group = fParamGroup->MakeGroup(param->Name());
697 label = group->MakeNullParameter(P_LABEL + param->Index(),
698 B_MEDIA_NO_TYPE, param->Name(), B_GENERIC);
700 str.SetTo(param->MaximumValue());
701 str << " " << param->Unit();
703 group->MakeNullParameter(P_LABEL2 + param->Index(),
704 B_MEDIA_NO_TYPE, str.String(), B_GENERIC);
705 value = group->MakeContinuousParameter(P_PARAM + param->Index(),
706 B_MEDIA_NO_TYPE, "", B_GAIN, "", 0.0, 1.0, 0.01);
707 label->AddOutput(value);
708 value->AddInput(label);
710 str.SetTo(param->MinimumValue());
711 str << " " << param->Unit();
713 group->MakeNullParameter(P_LABEL3 + param->Index(),
714 B_MEDIA_NO_TYPE, str.String(), B_GENERIC);
715 break;
720 BString str("About plugin");
721 label = fAboutGroup->MakeNullParameter(P_ABOUT + 0,
722 B_MEDIA_NO_TYPE, str.String(), B_GENERIC);
724 str.SetTo("Effect name: ");
725 if (strlen(fPlugin->EffectName()) != 0)
726 str.Append(fPlugin->EffectName());
727 else
728 str.Append("not specified");
730 label = fAboutGroup->MakeNullParameter(P_ABOUT + 1,
731 B_MEDIA_NO_TYPE, str.String(), B_GENERIC);
733 str.SetTo("Vendor: ");
734 if (strlen(fPlugin->Vendor()) != 0)
735 str.Append(fPlugin->Vendor());
736 else
737 str.Append("not specified");
739 label = fAboutGroup->MakeNullParameter(P_ABOUT + 2,
740 B_MEDIA_NO_TYPE, str.String(), B_GENERIC);
742 str.SetTo("Product: ");
743 if (strlen(fPlugin->Product()) != 0)
744 str.Append(fPlugin->Product());
745 else
746 str.Append("not specified");
748 label = fAboutGroup->MakeNullParameter(P_ABOUT + 3,
749 B_MEDIA_NO_TYPE, str.String(), B_GENERIC);
751 str.SetTo("Input Channels: ");
752 str<<fPlugin->Channels(VST_INPUT_CHANNELS);
753 label = fAboutGroup->MakeNullParameter(P_ABOUT + 4,
754 B_MEDIA_NO_TYPE, str.String(), B_GENERIC);
756 str.SetTo("Output Channels: ");
757 str<<fPlugin->Channels(VST_OUTPUT_CHANNELS);
758 label = fAboutGroup->MakeNullParameter(P_ABOUT + 5,
759 B_MEDIA_NO_TYPE, str.String(), B_GENERIC);
761 SetParameterWeb(fWeb);
764 void
765 VSTNode::InitFilter()
767 fBlockSize = fFormat.u.raw_audio.buffer_size /
768 (fFormat.u.raw_audio.channel_count * sizeof(float));
770 fPlugin->SetBlockSize(fBlockSize);
771 fPlugin->SetSampleRate(fFormat.u.raw_audio.frame_rate);
774 bigtime_t
775 VSTNode::GetFilterLatency()
777 if (fOutputMedia.destination == media_destination::null)
778 return 0LL;
780 BBufferGroup* temp_group =
781 new BBufferGroup(fOutputMedia.format.u.raw_audio.buffer_size, 1);
783 BBuffer *buffer =
784 temp_group->RequestBuffer(fOutputMedia.format.u.raw_audio.buffer_size);
785 buffer->Header()->type = B_MEDIA_RAW_AUDIO;
786 buffer->Header()->size_used = fOutputMedia.format.u.raw_audio.buffer_size;
788 bigtime_t begin = system_time();
789 FilterBuffer(buffer);
790 bigtime_t latency = system_time()-begin;
792 InitFilter();
794 buffer->Recycle();
795 delete temp_group;
797 return latency;
800 void
801 VSTNode::FilterBuffer(BBuffer* buffer)
803 uint32 m_frameSize = (fFormat.u.raw_audio.format & 0x0f)*
804 fFormat.u.raw_audio.channel_count;
805 uint32 samples = buffer->Header()->size_used / m_frameSize;
806 uint32 channels = fFormat.u.raw_audio.channel_count;
808 if (fMute != 0) {
809 memset(buffer->Data(), 0, buffer->Header()->size_used);
810 } else {
811 if (fByPass == 0) {
812 fPlugin->Process((float*)buffer->Data(), samples, channels);