xref: /haiku/src/add-ons/media/media-add-ons/equalizer/EqualizerNode.cpp (revision 830f67ef991407f287dbc1238aa5f5906d90c991)
1 /*
2  * Copyright 2012, Gerasim Troeglazov (3dEyes**), 3dEyes@gmail.com.
3  * All rights reserved.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 #include <ByteOrder.h>
8 #include <Buffer.h>
9 #include <BufferGroup.h>
10 #include <TimeSource.h>
11 #include <ParameterWeb.h>
12 #include <String.h>
13 
14 #include <stdio.h>
15 #include <string.h>
16 
17 #include "EqualizerNode.h"
18 
19 //EqualizerNode
20 EqualizerNode::~EqualizerNode()
21 {
22 	Quit();
23 }
24 
25 
26 EqualizerNode::EqualizerNode(BMediaAddOn* addon)
27 	:
28 	BMediaNode("10 Band Equalizer"),
29 	BBufferConsumer(B_MEDIA_RAW_AUDIO),
30 	BBufferProducer(B_MEDIA_RAW_AUDIO),
31 	BControllable(),
32 	BMediaEventLooper(),
33 	fAddOn(addon),
34 	fProcessLatency(0),
35 	fDownstreamLatency(0),
36 	fOutputMediaEnabled(true)
37 {
38 }
39 
40 
41 //BMediaNode
42 BMediaAddOn*
43 EqualizerNode::AddOn(int32* id) const
44 {
45 	if (fAddOn)
46 		*id = 0;
47 	return fAddOn;
48 }
49 
50 
51 status_t
52 EqualizerNode::HandleMessage(int32 message, const void *data, size_t size)
53 {
54 	if ((BControllable::HandleMessage(message, data, size) != B_OK) &&
55 		(BBufferConsumer::HandleMessage(message, data, size) != B_OK) &&
56 		(BBufferProducer::HandleMessage(message, data, size) != B_OK) &&
57 		(BControllable::HandleMessage(message, data, size) != B_OK)) {
58 		BMediaNode::HandleMessage(message, data, size);
59 		return B_OK;
60 	}
61 	BMediaNode::HandleBadMessage(message, data, size);
62 	return B_ERROR;
63 }
64 
65 
66 void
67 EqualizerNode::NodeRegistered()
68 {
69 	fPreferredFormat.type = B_MEDIA_RAW_AUDIO;
70 	fPreferredFormat.u.raw_audio.buffer_size = BUFF_SIZE;
71 	fPreferredFormat.u.raw_audio = media_raw_audio_format::wildcard;
72 	fPreferredFormat.u.raw_audio.channel_count =
73 		media_raw_audio_format::wildcard.channel_count;
74 	fPreferredFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
75 
76 	fFormat.type = B_MEDIA_RAW_AUDIO;
77 	fFormat.u.raw_audio = media_raw_audio_format::wildcard;
78 
79 	fInputMedia.destination.port = ControlPort();
80 	fInputMedia.destination.id = ID_AUDIO_INPUT;
81 	fInputMedia.node = Node();
82 	fInputMedia.source = media_source::null;
83 	fInputMedia.format = fFormat;
84 	strncpy(fInputMedia.name, "Audio Input", B_MEDIA_NAME_LENGTH);
85 
86 	fOutputMedia.source.port = ControlPort();
87 	fOutputMedia.source.id = ID_AUDIO_OUTPUT;
88 	fOutputMedia.node = Node();
89 	fOutputMedia.destination = media_destination::null;
90 	fOutputMedia.format = fFormat;
91 	strncpy(fOutputMedia.name, "Audio Output", B_MEDIA_NAME_LENGTH);
92 
93 	InitParameterValues();
94 	InitParameterWeb();
95 
96 	SetPriority(B_REAL_TIME_PRIORITY);
97 	Run();
98 }
99 
100 
101 //BControllable
102 status_t
103 EqualizerNode::GetParameterValue(int32 id, bigtime_t* lastChangeTime,
104 	void* value, size_t* size)
105 {
106 	if (*size < sizeof(float))
107 		return B_NO_MEMORY;
108 
109 	if (id == P_MUTE) {
110 		*(int32*)value = fMute;
111 		*lastChangeTime = fMuteLastChanged;
112 		*size = sizeof(int32);
113 	} else if (id == P_BYPASS) {
114 		*(int32*)value = fByPass;
115 		*lastChangeTime = fByPassLastChanged;
116 		*size = sizeof(int32);
117 	} else if (id == P_PREAMP) {
118 		*(float*)value = (float)fEqualizer.PreAmp();
119 		*lastChangeTime = fPreAmpLastChanged;
120 		*size = sizeof(float);
121 	} else if (id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount()) {
122 		int band = id - P_BANDS;
123 		*(float*)value = (float)fEqualizer.Band(band);
124 		*lastChangeTime = fBandsLastChanged[band];
125 		*size = sizeof(float);
126 	} else
127 		return B_ERROR;
128 	return B_OK;
129 }
130 
131 
132 void
133 EqualizerNode::SetParameterValue(int32 id, bigtime_t time, const void* value,
134 	size_t size)
135 {
136 	if (id == P_PREAMP || id == P_BYPASS || id == P_MUTE
137 		|| (id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount())) {
138 		media_timed_event ev(time, BTimedEventQueue::B_PARAMETER, (void*)value,
139 			BTimedEventQueue::B_NO_CLEANUP, size, id, (char*)"EQ");
140 		//dirty hack for parameter processing (mediakit bug????)
141 		ParameterEventProcessing(&ev);
142 		EventQueue()->AddEvent(ev);
143 	}
144 }
145 
146 
147 //BBufferConsumer
148 void
149 EqualizerNode::BufferReceived(BBuffer* buffer)
150 {
151 	if (buffer->Header()->destination != fInputMedia.destination.id) {
152 		buffer->Recycle();
153 		return;
154 	}
155 
156 	if (fOutputMedia.destination == media_destination::null
157 		|| !fOutputMediaEnabled) {
158 		buffer->Recycle();
159 		return;
160 	}
161 
162 	FilterBuffer(buffer);
163 
164 	status_t err = SendBuffer(buffer, fOutputMedia.source,
165 		fOutputMedia.destination);
166 	if (err < B_OK)
167 		buffer->Recycle();
168 }
169 
170 
171 status_t
172 EqualizerNode::AcceptFormat(const media_destination &dst, media_format* format)
173 {
174 	if (dst != fInputMedia.destination)
175 		return B_MEDIA_BAD_DESTINATION;
176 
177 	if (format->type != B_MEDIA_RAW_AUDIO)
178 		return B_MEDIA_BAD_FORMAT;
179 
180 	ValidateFormat((fFormat.u.raw_audio.format
181 			!= media_raw_audio_format::wildcard.format) ?
182 		fFormat : fPreferredFormat, *format);
183 
184 	return B_OK;
185 }
186 
187 
188 status_t
189 EqualizerNode::GetNextInput(int32* cookie, media_input* input)
190 {
191 	if (*cookie)
192 		return B_BAD_INDEX;
193 
194 	++*cookie;
195 	*input = fInputMedia;
196 	return B_OK;
197 }
198 
199 
200 void
201 EqualizerNode::DisposeInputCookie(int32 cookie)
202 {
203 }
204 
205 
206 status_t
207 EqualizerNode::FormatChanged(const media_source &src,
208 	const media_destination &dst, int32 changeTag, const media_format &format)
209 {
210 	return B_MEDIA_BAD_FORMAT;
211 }
212 
213 
214 void
215 EqualizerNode::ProducerDataStatus(const media_destination &dst, int32 status,
216 	bigtime_t when)
217 {
218 	if (fOutputMedia.destination != media_destination::null)
219 		SendDataStatus(status, fOutputMedia.destination, when);
220 }
221 
222 
223 status_t
224 EqualizerNode::GetLatencyFor(const media_destination &dst, bigtime_t* latency,
225 	media_node_id* outTimeSource)
226 {
227 
228 	if (dst != fInputMedia.destination)
229 		return B_MEDIA_BAD_DESTINATION;
230 
231 	*latency = fDownstreamLatency + fProcessLatency;
232 	*outTimeSource = TimeSource()->ID();
233 	return B_OK;
234 }
235 
236 
237 status_t
238 EqualizerNode::Connected(const media_source& source,
239 	const media_destination& destination, const media_format& format,
240 	media_input* poInput)
241 {
242 	if (destination != fInputMedia.destination)
243 		return B_MEDIA_BAD_DESTINATION;
244 
245 	if (fInputMedia.source != media_source::null)
246 		return B_MEDIA_ALREADY_CONNECTED;
247 
248 	fInputMedia.source = source;
249 	fInputMedia.format = format;
250 	*poInput = fInputMedia;
251 	fFormat = format;
252 
253 	return B_OK;
254 }
255 
256 
257 void
258 EqualizerNode::Disconnected(const media_source &src,
259 	const media_destination &dst)
260 {
261 	if (fInputMedia.source != src || dst != fInputMedia.destination)
262 		return;
263 
264 	fInputMedia.source = media_source::null;
265 
266 	if (fOutputMedia.destination == media_destination::null)
267 		fFormat.u.raw_audio = media_raw_audio_format::wildcard;
268 
269 	fInputMedia.format = fFormat;
270 }
271 
272 
273 //BBufferProducer
274 status_t
275 EqualizerNode::FormatSuggestionRequested(media_type type, int32 quality,
276 	media_format* format)
277 {
278 	if (type != B_MEDIA_RAW_AUDIO)
279 		return B_MEDIA_BAD_FORMAT;
280 
281 	if (fFormat.u.raw_audio.format != media_raw_audio_format::wildcard.format)
282 		*format = fFormat;
283 	else
284 		*format = fPreferredFormat;
285 	return B_OK;
286 }
287 
288 
289 status_t
290 EqualizerNode::FormatProposal(const media_source &src, media_format* format)
291 {
292 	if (src != fOutputMedia.source)
293 		return B_MEDIA_BAD_SOURCE;
294 
295 	if (format->type != B_MEDIA_RAW_AUDIO)
296 		return B_MEDIA_BAD_FORMAT;
297 
298 	ValidateFormat((fFormat.u.raw_audio.format
299 			!= media_raw_audio_format::wildcard.format) ?
300 		fFormat:fPreferredFormat, *format);
301 
302 	return B_OK;
303 }
304 
305 
306 status_t
307 EqualizerNode::FormatChangeRequested(const media_source &src,
308 	const media_destination &dst, media_format* format, int32* _deprecated_)
309 {
310 	return B_MEDIA_BAD_FORMAT;
311 }
312 
313 
314 void
315 EqualizerNode::LateNoticeReceived(const media_source &src, bigtime_t late,
316 	bigtime_t when)
317 {
318 	if (src != fOutputMedia.source || fInputMedia.source == media_source::null)
319 		return;
320 
321 	NotifyLateProducer(fInputMedia.source, late, when);
322 }
323 
324 
325 status_t
326 EqualizerNode::GetNextOutput(int32* cookie, media_output* output)
327 {
328 	if (*cookie)
329 		return B_BAD_INDEX;
330 
331 	++*cookie;
332 	*output = fOutputMedia;
333 	return B_OK;
334 }
335 
336 
337 status_t
338 EqualizerNode::DisposeOutputCookie(int32 cookie)
339 {
340 	return B_OK;
341 }
342 
343 
344 status_t
345 EqualizerNode::SetBufferGroup(const media_source &src, BBufferGroup* group)
346 {
347 	int32 changeTag;
348 	status_t ret = B_OK;
349 
350 	if (src != fOutputMedia.source)
351 		return B_MEDIA_BAD_SOURCE;
352 
353 	if (fInputMedia.source == media_source::null)
354 		return B_ERROR;
355 
356 	ret = SetOutputBuffersFor(fInputMedia.source, fInputMedia.destination,
357 		group, 0, &changeTag);
358 	return ret;
359 }
360 
361 
362 status_t
363 EqualizerNode::PrepareToConnect(const media_source &src,
364 	const media_destination &dst, media_format* format, media_source* outSource,
365 	char* outName)
366 {
367 	if (src != fOutputMedia.source)
368 		return B_MEDIA_BAD_SOURCE;
369 
370 	if (format->type != B_MEDIA_RAW_AUDIO)
371 		return B_MEDIA_BAD_FORMAT;
372 
373 	if (fOutputMedia.destination != media_destination::null)
374 		return B_MEDIA_ALREADY_CONNECTED;
375 
376 	status_t err = ValidateFormat((fFormat.u.raw_audio.format
377 			!= media_raw_audio_format::wildcard.format) ? fFormat
378 		: fPreferredFormat, *format);
379 
380 	if (err < B_OK)
381 		return err;
382 
383 	SetOutputFormat(*format);
384 
385 	fOutputMedia.destination = dst;
386 	fOutputMedia.format = *format;
387 
388 	*outSource = fOutputMedia.source;
389 	strncpy(outName, fOutputMedia.name, B_MEDIA_NAME_LENGTH);
390 
391 	return B_OK;
392 }
393 
394 
395 void
396 EqualizerNode::Connect(status_t status, const media_source &src,
397 	const media_destination &dst, const media_format &format, char* name)
398 {
399 	if (status < B_OK) {
400 		fOutputMedia.destination = media_destination::null;
401 		return;
402 	}
403 
404 	strncpy(name, fOutputMedia.name, B_MEDIA_NAME_LENGTH);
405 	fOutputMedia.destination = dst;
406 	fFormat = format;
407 
408 	media_node_id timeSource;
409 	FindLatencyFor(fOutputMedia.destination, &fDownstreamLatency, &timeSource);
410 
411 	InitFilter();
412 
413 	fProcessLatency = GetFilterLatency();
414 	SetEventLatency(fDownstreamLatency + fProcessLatency);
415 
416 	if (fInputMedia.source != media_source::null) {
417 		SendLatencyChange(fInputMedia.source, fInputMedia.destination,
418 			EventLatency() + SchedulingLatency());
419 	}
420 
421 	bigtime_t duration = 0;
422 
423 	int sample_size = (fFormat.u.raw_audio.format & 0xf)
424 		* fFormat.u.raw_audio.channel_count;
425 
426 	if (fFormat.u.raw_audio.buffer_size > 0
427 		&& fFormat.u.raw_audio.frame_rate > 0 && sample_size > 0) {
428 		duration = (bigtime_t)(((fFormat.u.raw_audio.buffer_size / sample_size)
429 			/ fFormat.u.raw_audio.frame_rate) * 1000000.0);
430 	}
431 
432 	SetBufferDuration(duration);
433 }
434 
435 
436 void
437 EqualizerNode::Disconnect(const media_source &src, const media_destination &dst)
438 {
439 	if (src != fOutputMedia.source)
440 		return;
441 
442 	if (dst != fOutputMedia.destination)
443 		return;
444 
445 	fOutputMedia.destination = media_destination::null;
446 
447 	if (fInputMedia.source == media_source::null)
448 		fFormat.u.raw_audio = media_raw_audio_format::wildcard;
449 
450 	fOutputMedia.format = fFormat;
451 }
452 
453 
454 void
455 EqualizerNode::EnableOutput(const media_source &src, bool enabled,
456 	int32* _deprecated_)
457 {
458 	if (src != fOutputMedia.source)
459 		return;
460 	fOutputMediaEnabled = enabled;
461 }
462 
463 
464 status_t
465 EqualizerNode::GetLatency(bigtime_t* latency)
466 {
467 	*latency = EventLatency() + SchedulingLatency();
468 	return B_OK;
469 }
470 
471 
472 void
473 EqualizerNode::LatencyChanged(const media_source &src,
474 	const media_destination &dst, bigtime_t latency, uint32 flags)
475 {
476 	if (src != fOutputMedia.source || dst != fOutputMedia.destination)
477 		return;
478 
479 	fDownstreamLatency = latency;
480 	SetEventLatency(fDownstreamLatency + fProcessLatency);
481 
482 	if (fInputMedia.source != media_source::null) {
483 		SendLatencyChange(fInputMedia.source,
484 			fInputMedia.destination,EventLatency() + SchedulingLatency());
485 	}
486 }
487 
488 
489 //BMediaEventLooper
490 bigtime_t
491 EqualizerNode::OfflineTime()
492 {
493 	return 0LL;
494 }
495 
496 
497 //EqualizerNode
498 void
499 EqualizerNode::HandleEvent(const media_timed_event* event, bigtime_t late,
500 	bool realTime)
501 {
502 	if (event->type == BTimedEventQueue::B_PARAMETER)
503 		ParameterEventProcessing(event);
504 }
505 
506 
507 void
508 EqualizerNode::ParameterEventProcessing(const media_timed_event* event)
509 {
510 	float value = 0.0;
511 	int32 value32 = 0;
512 
513 	int32 id = event->bigdata;
514 	size_t size = event->data;
515 	bigtime_t now = TimeSource()->Now();
516 
517 	type_code v_type = B_FLOAT_TYPE;
518 
519 	BParameter* web_param;
520 
521 	for (int i = 0; i < fWeb->CountParameters(); i++) {
522 		web_param = fWeb->ParameterAt(i);
523 		if (web_param->ID() == id) {
524 			v_type=web_param->ValueType();
525 			break;
526 		}
527 	}
528 
529 	if (v_type == B_FLOAT_TYPE)
530 		value = *((float*)event->pointer);
531 	else if (v_type == B_INT32_TYPE) {
532 		value32 = *((int32*)event->pointer);
533 		value = (float)value32;
534 	}
535 
536 	if (id == P_MUTE) {
537 		fMute = value32;
538 		fMuteLastChanged = now;
539 		BroadcastNewParameterValue(now,	id,	event->pointer, size);
540 	} else if (id == P_BYPASS) {
541 		fByPass = value32;
542 		fByPassLastChanged = now;
543 		BroadcastNewParameterValue(now,	id,	event->pointer, size);
544 	} else if (id == P_PREAMP) {
545 		if (value != fEqualizer.PreAmp()) {
546 			fEqualizer.SetPreAmp(value);
547 			fPreAmpLastChanged = now;
548 			BroadcastNewParameterValue(now,	id,	&value,	size);
549 		}
550 	} else if (id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount()) {
551 		int band = id - P_BANDS;
552 		if (value != fEqualizer.Band(band)) {
553 			fEqualizer.SetBand(band, value);
554 			fBandsLastChanged[band] = now;
555 			BroadcastNewParameterValue(now,	id,	&value,	size);
556 		}
557 	}
558 }
559 
560 
561 status_t
562 EqualizerNode::ValidateFormat(const media_format &preferred_format,
563 							media_format &proposed_format)
564 {
565 	status_t ret = B_OK;
566 
567 	if (proposed_format.type != B_MEDIA_RAW_AUDIO) {
568 		proposed_format = preferred_format;
569 		return B_MEDIA_BAD_FORMAT;
570 	}
571 
572 	const media_raw_audio_format &wild = media_raw_audio_format::wildcard;
573 	media_raw_audio_format &f = proposed_format.u.raw_audio;
574 	const media_raw_audio_format &pref = preferred_format.u.raw_audio;
575 
576 	if(pref.frame_rate != wild.frame_rate && f.frame_rate != pref.frame_rate) {
577 		if(f.frame_rate != wild.frame_rate)
578 			ret = B_MEDIA_BAD_FORMAT;
579 		f.frame_rate = pref.frame_rate;
580 	}
581 
582 	if(pref.channel_count != wild.channel_count &&
583 		f.channel_count != pref.channel_count) {
584 		if(f.channel_count != wild.channel_count)
585 			ret = B_MEDIA_BAD_FORMAT;
586 		f.channel_count = pref.channel_count;
587 	}
588 
589 	if(pref.format != wild.format && f.format != pref.format) {
590 		if(f.format != wild.format)
591 			ret = B_MEDIA_BAD_FORMAT;
592 		f.format = pref.format;
593 	}
594 
595 	if(pref.byte_order != wild.byte_order &&
596 		f.byte_order != pref.byte_order) {
597 		if(f.byte_order != wild.byte_order)
598 			ret = B_MEDIA_BAD_FORMAT;
599 		f.byte_order = pref.byte_order;
600 	}
601 
602 	if(pref.buffer_size != wild.buffer_size &&
603 		f.buffer_size != pref.buffer_size) {
604 		if(f.buffer_size != wild.buffer_size)
605 			ret = B_MEDIA_BAD_FORMAT;
606 		f.buffer_size = pref.buffer_size;
607 	}
608 
609 	return ret;
610 }
611 
612 
613 void
614 EqualizerNode::SetOutputFormat(media_format &format)
615 {
616 	media_raw_audio_format &f = format.u.raw_audio;
617 	const media_raw_audio_format &w = media_raw_audio_format::wildcard;
618 
619 	if (f.frame_rate == w.frame_rate) {
620 		f.frame_rate = 44100.0;
621 	}
622 	if (f.channel_count == w.channel_count) {
623 		if(fInputMedia.source != media_source::null)
624 			f.channel_count = fInputMedia.format.u.raw_audio.channel_count;
625 		else
626 			f.channel_count = 2;
627 	}
628 
629 	if (f.format == w.format)
630 		f.format = media_raw_audio_format::B_AUDIO_FLOAT;
631 
632 	if (f.byte_order == w.format) {
633 		f.byte_order = (B_HOST_IS_BENDIAN) ?
634 			B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
635 	}
636 
637 	if (f.buffer_size == w.buffer_size)
638 		f.buffer_size = BUFF_SIZE;
639 }
640 
641 
642 void
643 EqualizerNode::InitParameterValues()
644 {
645 	fMute = 0;
646 	fByPass = 0;
647 	fMuteLastChanged = 0LL;
648 	fByPassLastChanged = 0LL;
649 	fPreAmpLastChanged = 0LL;
650 
651 	for (int i = 0; i < EQ_BANDS; i++)
652 		fBandsLastChanged[i] = 0LL;
653 
654 	fEqualizer.CleanUp();
655 }
656 
657 
658 void
659 EqualizerNode::InitParameterWeb(void)
660 {
661 	fWeb = new BParameterWeb();
662 
663 	BParameterGroup* fParamGroup = fWeb->MakeGroup("EqualizerNode Parameters");
664 	BParameterGroup* fFControlGroup = fParamGroup->MakeGroup("FilterControl");
665 
666 	fFControlGroup->MakeDiscreteParameter(P_MUTE,B_MEDIA_NO_TYPE,"Mute",
667 		B_ENABLE);
668 	fFControlGroup->MakeDiscreteParameter(P_BYPASS,B_MEDIA_NO_TYPE,"ByPass",
669 		B_ENABLE);
670 
671 	BNullParameter* label;
672 	BParameterGroup* group;
673 	BContinuousParameter* value;
674 
675 	group = fParamGroup->MakeGroup("Pre Amp");
676 	label = group->MakeNullParameter(P_PREAMP_LABEL, B_MEDIA_NO_TYPE, "Pre Amp",
677 		B_GENERIC);
678 	value = group->MakeContinuousParameter(P_PREAMP, B_MEDIA_NO_TYPE, "",
679 		B_GAIN, "dB", -8.0, 8.0, 0.1);
680 	label->AddOutput(value);
681 	value->AddInput(label);
682 
683 	for (int i = 0; i < fEqualizer.BandCount(); i++) {
684 		char freq[32];
685 		sprintf(freq,"%gHz",fEqualizer.BandFrequency(i));
686 		group = fParamGroup->MakeGroup(freq);
687 		label = group->MakeNullParameter(P_BAND_LABELS + i, B_MEDIA_NO_TYPE,
688 			freq, B_GENERIC);
689 		value = group->MakeContinuousParameter(P_BANDS + i, B_MEDIA_NO_TYPE,
690 			"", B_GAIN, "dB", -16.0, 16.0, 0.1);
691 		label->AddOutput(value);
692 		value->AddInput(label);
693 	}
694 
695 	SetParameterWeb(fWeb);
696 }
697 
698 
699 void
700 EqualizerNode::InitFilter(void)
701 {
702 	fEqualizer.SetFormat(fFormat.u.raw_audio.channel_count,
703 		fFormat.u.raw_audio.frame_rate);
704 }
705 
706 
707 bigtime_t
708 EqualizerNode::GetFilterLatency(void)
709 {
710 	if (fOutputMedia.destination == media_destination::null)
711 		return 0LL;
712 
713 	BBufferGroup* test_group =
714 		new BBufferGroup(fOutputMedia.format.u.raw_audio.buffer_size, 1);
715 
716 	BBuffer* buffer =
717 		test_group->RequestBuffer(fOutputMedia.format.u.raw_audio.buffer_size);
718 	buffer->Header()->type = B_MEDIA_RAW_AUDIO;
719 	buffer->Header()->size_used = fOutputMedia.format.u.raw_audio.buffer_size;
720 
721 	bigtime_t begin = system_time();
722 	FilterBuffer(buffer);
723 	bigtime_t latency = system_time() - begin;
724 
725 	buffer->Recycle();
726 	delete test_group;
727 
728 	InitFilter();
729 
730 	return latency;
731 }
732 
733 
734 void
735 EqualizerNode::FilterBuffer(BBuffer* buffer)
736 {
737 	uint32 m_frameSize = (fFormat.u.raw_audio.format & 0x0f)
738 		* fFormat.u.raw_audio.channel_count;
739 	uint32 samples = buffer->Header()->size_used / m_frameSize;
740 	uint32 channels = fFormat.u.raw_audio.channel_count;
741 	if (fMute != 0)
742 		memset(buffer->Data(), 0, buffer->Header()->size_used);
743 	else if (fByPass == 0)
744 		fEqualizer.ProcessBuffer((float*)buffer->Data(), samples * channels);
745 }
746