2 * Copyright (c) 1999-2000, Eric Moon.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions, and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 // AudioAdapterNode.cpp
34 #include "AudioAdapterNode.h"
35 #include "AudioAdapterParams.h"
37 #include "SoundUtils.h"
42 // -------------------------------------------------------- //
44 // -------------------------------------------------------- //
46 _AudioAdapterNode::~_AudioAdapterNode() {}
48 _AudioAdapterNode::_AudioAdapterNode(
50 IAudioOpFactory
* opFactory
,
54 AudioFilterNode(name
, opFactory
, addOn
) {
58 // "--*-- _AudioAdapterNode() [%s] --*--\n\n",
62 // -------------------------------------------------------- //
64 // -------------------------------------------------------- //
66 status_t
_AudioAdapterNode::getRequiredInputFormat(
67 media_format
& ioFormat
) {
69 status_t err
= getPreferredInputFormat(ioFormat
);
73 // 16sep99: input byte-swapping now supported
74 ioFormat
.u
.raw_audio
.byte_order
= media_raw_audio_format::wildcard
.byte_order
;
76 // ioFormat.u.raw_audio.format = media_raw_audio_format::wildcard.format;
77 // ioFormat.u.raw_audio.channel_count = media_raw_audio_format::wildcard.channel_count;
78 _AudioAdapterParams
* p
= dynamic_cast<_AudioAdapterParams
*>(parameterSet());
81 // media_raw_audio_format& w = media_raw_audio_format::wildcard;
83 // copy user preferences
84 ioFormat
.u
.raw_audio
.format
= p
->inputFormat
.format
;
85 ioFormat
.u
.raw_audio
.channel_count
= p
->inputFormat
.channel_count
;
88 // don't require a buffer size until format & channel_count are known [16sep99]
89 ioFormat
.u
.raw_audio
.buffer_size
= media_raw_audio_format::wildcard
.buffer_size
;
91 if(output().destination
== media_destination::null
) {
92 // frame rate isn't constrained yet
93 ioFormat
.u
.raw_audio
.frame_rate
= media_raw_audio_format::wildcard
.frame_rate
;
99 // +++++ 17sep99: use parameter data!
101 status_t
_AudioAdapterNode::getPreferredInputFormat(
102 media_format
& ioFormat
) {
104 status_t err
= _inherited::getPreferredInputFormat(ioFormat
);
108 _AudioAdapterParams
* p
= dynamic_cast<_AudioAdapterParams
*>(parameterSet());
111 media_raw_audio_format
& f
= ioFormat
.u
.raw_audio
;
112 media_raw_audio_format
& w
= media_raw_audio_format::wildcard
;
114 // copy user preferences
115 if(p
->inputFormat
.format
!= w
.format
)
116 f
.format
= p
->inputFormat
.format
;
117 if(p
->inputFormat
.channel_count
!= w
.channel_count
)
118 f
.channel_count
= p
->inputFormat
.channel_count
;
120 // // if one end is connected, prefer not to do channel conversions [15sep99]
121 // if(output().destination != media_destination::null)
122 // ioFormat.u.raw_audio.channel_count = output().format.u.raw_audio.channel_count;
124 // if output connected, constrain:
127 if(output().destination
!= media_destination::null
) {
128 // if the user doesn't care, default to the output's frame format
129 if(f
.format
== w
.format
)
130 f
.format
= output().format
.u
.raw_audio
.format
;
131 if(f
.channel_count
== w
.channel_count
)
132 f
.channel_count
= output().format
.u
.raw_audio
.channel_count
;
136 frames_per_buffer(output().format
.u
.raw_audio
);
137 f
.frame_rate
= output().format
.u
.raw_audio
.frame_rate
;
143 status_t
_AudioAdapterNode::getRequiredOutputFormat(
144 media_format
& ioFormat
) {
146 status_t err
= getPreferredOutputFormat(ioFormat
);
150 ioFormat
.u
.raw_audio
.format
= media_raw_audio_format::wildcard
.format
;
151 ioFormat
.u
.raw_audio
.channel_count
= media_raw_audio_format::wildcard
.channel_count
;
153 _AudioAdapterParams
* p
= dynamic_cast<_AudioAdapterParams
*>(parameterSet());
156 // media_raw_audio_format& w = media_raw_audio_format::wildcard;
158 // copy user preferences
159 ioFormat
.u
.raw_audio
.format
= p
->outputFormat
.format
;
160 ioFormat
.u
.raw_audio
.channel_count
= p
->outputFormat
.channel_count
;
162 // don't require a buffer size until format & channel_count are known [16sep99]
163 ioFormat
.u
.raw_audio
.buffer_size
= media_raw_audio_format::wildcard
.buffer_size
;
165 if(input().source
== media_source::null
) {
166 // frame rate isn't constrained yet
167 ioFormat
.u
.raw_audio
.frame_rate
= media_raw_audio_format::wildcard
.frame_rate
;
173 // +++++ 17sep99: use parameter data!
175 status_t
_AudioAdapterNode::getPreferredOutputFormat(
176 media_format
& ioFormat
) {
178 status_t err
= _inherited::getPreferredOutputFormat(ioFormat
);
182 _AudioAdapterParams
* p
= dynamic_cast<_AudioAdapterParams
*>(parameterSet());
185 media_raw_audio_format
& w
= media_raw_audio_format::wildcard
;
187 // copy user preferences
188 if(p
->outputFormat
.format
!= w
.format
)
189 ioFormat
.u
.raw_audio
.format
= p
->outputFormat
.format
;
190 if(p
->outputFormat
.channel_count
!= w
.channel_count
)
191 ioFormat
.u
.raw_audio
.channel_count
= p
->outputFormat
.channel_count
;
193 //// // if one end is connected, prefer not to do channel conversions [15sep99]
194 //// if(input().source != media_source::null)
195 //// ioFormat.u.raw_audio.channel_count = input().format.u.raw_audio.channel_count;
197 // if input connected, constrain:
200 if(input().source
!= media_source::null
) {
201 // if the user doesn't care, default to the input's frame format
202 if(ioFormat
.u
.raw_audio
.format
== w
.format
)
203 ioFormat
.u
.raw_audio
.format
= input().format
.u
.raw_audio
.format
;
204 if(ioFormat
.u
.raw_audio
.channel_count
== w
.channel_count
)
205 ioFormat
.u
.raw_audio
.channel_count
= input().format
.u
.raw_audio
.channel_count
;
207 ioFormat
.u
.raw_audio
.buffer_size
=
208 bytes_per_frame(ioFormat
.u
.raw_audio
) *
209 frames_per_buffer(input().format
.u
.raw_audio
);
210 PRINT(("##### preferred output buffer_size: %ld (%" B_PRIxSIZE
")\n", ioFormat
.u
.raw_audio
.buffer_size
, ioFormat
.u
.raw_audio
.buffer_size
));
211 ioFormat
.u
.raw_audio
.frame_rate
= input().format
.u
.raw_audio
.frame_rate
;
219 status_t
_AudioAdapterNode::validateProposedInputFormat(
220 const media_format
& preferredFormat
,
221 media_format
& ioProposedFormat
) {
223 status_t err
= _inherited::validateProposedInputFormat(
224 preferredFormat
, ioProposedFormat
);
226 media_raw_audio_format
& w
= media_raw_audio_format::wildcard
;
228 if(output().destination
!= media_destination::null
) {
230 // an output connection exists; constrain the input format
232 // is there enough information to suggest a buffer size?
234 ioProposedFormat
.u
.raw_audio
.format
!= w
.format
&&
235 ioProposedFormat
.u
.raw_audio
.channel_count
!= w
.channel_count
) {
237 size_t target_buffer_size
=
238 bytes_per_frame(ioProposedFormat
.u
.raw_audio
) *
239 frames_per_buffer(output().format
.u
.raw_audio
);
241 if(ioProposedFormat
.u
.raw_audio
.buffer_size
!= target_buffer_size
) {
242 if(ioProposedFormat
.u
.raw_audio
.buffer_size
!= w
.buffer_size
)
243 err
= B_MEDIA_BAD_FORMAT
;
245 ioProposedFormat
.u
.raw_audio
.buffer_size
= target_buffer_size
;
249 // require output frame rate
250 if(ioProposedFormat
.u
.raw_audio
.frame_rate
!= output().format
.u
.raw_audio
.frame_rate
) {
251 if(ioProposedFormat
.u
.raw_audio
.frame_rate
!= w
.frame_rate
)
252 err
= B_MEDIA_BAD_FORMAT
;
254 ioProposedFormat
.u
.raw_audio
.frame_rate
= output().format
.u
.raw_audio
.frame_rate
;
258 char fmt_string
[256];
259 string_for_format(ioProposedFormat
, fmt_string
, 255);
261 "### _AudioAdapterNode::validateProposedInputFormat():\n"
262 " %s\n", fmt_string
));
266 status_t
_AudioAdapterNode::validateProposedOutputFormat(
267 const media_format
& preferredFormat
,
268 media_format
& ioProposedFormat
) {
270 status_t err
= _inherited::validateProposedOutputFormat(
271 preferredFormat
, ioProposedFormat
);
273 media_raw_audio_format
& w
= media_raw_audio_format::wildcard
;
275 if(input().source
!= media_source::null
) {
277 // an input connection exists; constrain the output format
279 // is there enough information to suggest a buffer size?
281 ioProposedFormat
.u
.raw_audio
.format
!= w
.format
&&
282 ioProposedFormat
.u
.raw_audio
.channel_count
!= w
.channel_count
) {
284 size_t target_buffer_size
=
285 bytes_per_frame(ioProposedFormat
.u
.raw_audio
) *
286 frames_per_buffer(input().format
.u
.raw_audio
);
288 if(ioProposedFormat
.u
.raw_audio
.buffer_size
!= target_buffer_size
) {
289 if(ioProposedFormat
.u
.raw_audio
.buffer_size
!= w
.buffer_size
)
290 err
= B_MEDIA_BAD_FORMAT
;
292 ioProposedFormat
.u
.raw_audio
.buffer_size
= target_buffer_size
;
296 // require same frame rate as input
297 if(ioProposedFormat
.u
.raw_audio
.frame_rate
!= input().format
.u
.raw_audio
.frame_rate
) {
298 if(ioProposedFormat
.u
.raw_audio
.frame_rate
!= w
.frame_rate
)
299 err
= B_MEDIA_BAD_FORMAT
;
301 ioProposedFormat
.u
.raw_audio
.frame_rate
= input().format
.u
.raw_audio
.frame_rate
;
305 char fmt_string
[256];
306 string_for_format(ioProposedFormat
, fmt_string
, 255);
308 "### _AudioAdapterNode::validateProposedOutputFormat():\n"
309 " %s\n", fmt_string
));
314 _AudioAdapterNode::SetParameterValue(int32 id
, bigtime_t changeTime
, const void *value
, size_t size
)
317 case _AudioAdapterParams::P_INPUT_FORMAT
:
318 if(input().source
!= media_source::null
) {
319 media_multi_audio_format f
= input().format
.u
.raw_audio
;
322 f
.format
= *(uint32
*)value
;
323 _attemptInputFormatChange(f
);
327 case _AudioAdapterParams::P_INPUT_CHANNEL_COUNT
:
328 if(input().source
!= media_source::null
) {
329 media_multi_audio_format f
= input().format
.u
.raw_audio
;
332 f
.channel_count
= *(uint32
*)value
;
333 _attemptInputFormatChange(f
);
337 case _AudioAdapterParams::P_OUTPUT_FORMAT
:
338 if(output().source
!= media_source::null
) {
339 media_multi_audio_format f
= output().format
.u
.raw_audio
;
342 f
.format
= *(uint32
*)value
;
343 _attemptOutputFormatChange(f
);
347 case _AudioAdapterParams::P_OUTPUT_CHANNEL_COUNT
:
348 if(output().source
!= media_source::null
) {
349 media_multi_audio_format f
= output().format
.u
.raw_audio
;
352 f
.channel_count
= *(uint32
*)value
;
353 _attemptOutputFormatChange(f
);
359 return _inherited::SetParameterValue(id
, changeTime
, value
, size
);
363 // -------------------------------------------------------- //
364 // BBufferProducer/Consumer
365 // -------------------------------------------------------- //
367 status_t
_AudioAdapterNode::Connected(
368 const media_source
& source
,
369 const media_destination
& destination
,
370 const media_format
& format
,
371 media_input
* outInput
) {
373 status_t err
= _inherited::Connected(
374 source
, destination
, format
, outInput
);
377 _AudioAdapterParams
* p
= dynamic_cast<_AudioAdapterParams
*>(parameterSet());
379 p
->inputFormat
= format
.u
.raw_audio
;
381 _broadcastInputFormatParams();
387 void _AudioAdapterNode::Connect(
389 const media_source
& source
,
390 const media_destination
& destination
,
391 const media_format
& format
,
395 _AudioAdapterParams
* p
= dynamic_cast<_AudioAdapterParams
*>(parameterSet());
397 p
->outputFormat
= format
.u
.raw_audio
;
399 _broadcastOutputFormatParams();
403 status
, source
, destination
, format
, ioName
);
407 void _AudioAdapterNode::_attemptInputFormatChange(
408 const media_multi_audio_format
& format
) {
413 f
.type
= B_MEDIA_RAW_AUDIO
;
414 f
.u
.raw_audio
= format
;
415 string_for_format(f
, fmtString
, 256);
417 "_AudioAdapterNode::attemptInputFormatChange():\n '%s'\n",
422 // +++++ reject attempt: broadcast params for current format
423 _broadcastInputFormatParams();
426 void _AudioAdapterNode::_attemptOutputFormatChange(
427 const media_multi_audio_format
& format
) {
432 f
.type
= B_MEDIA_RAW_AUDIO
;
433 f
.u
.raw_audio
= format
;
434 string_for_format(f
, fmtString
, 256);
436 "_AudioAdapterNode::attemptOutputFormatChange():\n '%s'\n",
439 media_destination dest
= output().destination
;
440 if(dest
== media_destination::null
) {
442 "! output not connected!\n"));
446 _AudioAdapterParams
* p
= dynamic_cast<_AudioAdapterParams
*>(parameterSet());
450 // disallow wildcards
451 if(format
.format
== media_raw_audio_format::wildcard
.format
||
452 format
.channel_count
== media_raw_audio_format::wildcard
.channel_count
) {
454 "! wildcards not allowed\n"));
458 err
= prepareFormatChange(f
);
462 "! format not supported\n"));
466 err
= ProposeFormatChange(&f
, dest
);
470 "! format rejected\n"));
480 PRINT(("! ChangeFormat(): %s\n", strerror(err
)));
485 p
->outputFormat
= format
;
487 // inform AudioFilterNode of format change
491 _broadcastOutputFormatParams();
496 _AudioAdapterNode::_broadcastInputFormatParams()
498 PRINT(("_AudioAdapterNode::_broadcastInputFormatParams()\n"));
499 BroadcastNewParameterValue(
501 _AudioAdapterParams::P_INPUT_FORMAT
,
502 (void*)&input().format
.u
.raw_audio
.format
,
504 BroadcastNewParameterValue(
506 _AudioAdapterParams::P_INPUT_CHANNEL_COUNT
,
507 (void*)&input().format
.u
.raw_audio
.channel_count
,
509 // BroadcastChangedParameter(_AudioAdapterParams::P_INPUT_FORMAT);
510 // BroadcastChangedParameter(_AudioAdapterParams::P_INPUT_CHANNEL_COUNT);
514 _AudioAdapterNode::_broadcastOutputFormatParams()
516 PRINT(("_AudioAdapterNode::_broadcastOutputFormatParams()\n"));
518 BroadcastNewParameterValue(
520 _AudioAdapterParams::P_OUTPUT_FORMAT
,
521 (void*)&output().format
.u
.raw_audio
.format
,
523 BroadcastNewParameterValue(
525 _AudioAdapterParams::P_OUTPUT_CHANNEL_COUNT
,
526 (void*)&output().format
.u
.raw_audio
.channel_count
,
528 // BroadcastChangedParameter(_AudioAdapterParams::P_OUTPUT_FORMAT);
529 // BroadcastChangedParameter(_AudioAdapterParams::P_OUTPUT_CHANNEL_COUNT);
534 // END -- AudioAdapterNode.cpp --