xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/CChannelMask.cpp (revision 51978af14a173e7fae0563b562be5603bc652aeb)
1 // ****************************************************************************
2 //
3 //		CChannelMask.cpp
4 //
5 //		Implementation file for the CChannelMask class.
6 //
7 // 	CChannelMask is a handy way to specify a group of pipes simultaneously.
8 //		It should really be called "CPipeMask", but the class name predates
9 //		the term "pipe".
10 //
11 // 	Since these masks are sometimes passed to the DSP, they must be kept in
12 //	 	little-endian format; the class does this for you.
13 //
14 //		Copyright Echo Digital Audio Corporation (c) 1998 - 2002
15 //		All rights reserved
16 //		www.echoaudio.com
17 //
18 //		Permission is hereby granted, free of charge, to any person obtaining a
19 //		copy of this software and associated documentation files (the
20 //		"Software"), to deal with the Software without restriction, including
21 //		without limitation the rights to use, copy, modify, merge, publish,
22 //		distribute, sublicense, and/or sell copies of the Software, and to
23 //		permit persons to whom the Software is furnished to do so, subject to
24 //		the following conditions:
25 //
26 //		- Redistributions of source code must retain the above copyright
27 //		notice, this list of conditions and the following disclaimers.
28 //
29 //		- Redistributions in binary form must reproduce the above copyright
30 //		notice, this list of conditions and the following disclaimers in the
31 //		documentation and/or other materials provided with the distribution.
32 //
33 //		- Neither the name of Echo Digital Audio, nor the names of its
34 //		contributors may be used to endorse or promote products derived from
35 //		this Software without specific prior written permission.
36 //
37 //		THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
38 //		EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
39 //		MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
40 //		IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
41 //		ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
42 //		TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
43 //		SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
44 //
45 // ****************************************************************************
46 
47 #include "CEchoGals.h"
48 
49 
50 /****************************************************************************
51 
52 	CChannelMask
53 
54  ****************************************************************************/
55 
56 //===========================================================================
57 //
58 // Constructor
59 //
60 //===========================================================================
61 
62 CChannelMask::CChannelMask()
63 {
64 
65 	Clear();
66 
67 }	// CChannelMask::CChannelMask()
68 
69 
70 //===========================================================================
71 //
72 //	SetMask, SetOutMask, and SetInMask all allow you to just set
73 // the masks directly.
74 //
75 //===========================================================================
76 
77 void CChannelMask::SetMask( CH_MASK OutMask, CH_MASK InMask, int nOutputs )
78 {
79 
80 	m_MaskRegs[ 0 ] = SWAP( OutMask );
81 	m_MaskRegs[ 0 ] |= SWAP( (CH_MASK) ( InMask << nOutputs ) );
82 	m_MaskRegs[ 1 ] = SWAP( (CH_MASK) ( InMask >> ( CH_MASK_BITS - nOutputs ) ) );
83 
84 }	// void CChannelMask::SetMask( ... )
85 
86 
87 void CChannelMask::SetOutMask( CH_MASK OutMask, int nOutputs )
88 {
89 
90 	m_MaskRegs[ 0 ] &= SWAP( (CH_MASK) ( (CH_MASK) -1 << nOutputs ) );
91 	m_MaskRegs[ 0 ] |= SWAP( OutMask );
92 
93 }	// void CChannelMask::SetOutMask( CH_MASK OutMask, int nOutputs )
94 
95 
96 void CChannelMask::SetInMask( CH_MASK InMask, int nOutputs )
97 {
98 	m_MaskRegs[ 0 ] &= SWAP( (CH_MASK) (~( (CH_MASK) -1 << nOutputs ) ) );
99 	m_MaskRegs[ 0 ] |= SWAP( (CH_MASK) ( InMask << nOutputs ) );
100 	m_MaskRegs[ 1 ] = SWAP( (CH_MASK) ( InMask >> ( CH_MASK_BITS - nOutputs ) ) );
101 }	// void CChannelMask::SetInMask( CH_MASK InMask, int nOutputs )
102 
103 
104 //===========================================================================
105 //
106 //	Retrieve an output bit mask and an input bitmask.
107 //
108 //===========================================================================
109 
110 void CChannelMask::GetMask( CH_MASK & OutMask, CH_MASK & InMask, int nOutputs )
111 {
112 	OutMask = GetOutMask( nOutputs );
113 	InMask = GetInMask( nOutputs );
114 }	// void CChannelMask::GetMask( ... )
115 
116 CH_MASK CChannelMask::GetOutMask( int nOutputs )
117 {
118 	return  SWAP( m_MaskRegs[ 0 ] ) & ~( (CH_MASK) -1 << nOutputs );
119 }	// CH_MASK CChannelMask::GetOutMask( int nOutputs )
120 
121 CH_MASK CChannelMask::GetInMask( int nOutputs )
122 {
123 	return ( SWAP( m_MaskRegs[ 0 ] ) >> nOutputs ) |
124 			  ( SWAP( m_MaskRegs[ 1 ] ) << ( CH_MASK_BITS - nOutputs ) );
125 }	// CH_MASK CChannelMask::GetIntMask( int nOutputs )
126 
127 
128 //===========================================================================
129 //
130 // IsEmpty returns TRUE if mask has no bits set
131 //
132 //===========================================================================
133 
134 BOOL CChannelMask::IsEmpty()
135 {
136 	int	i;
137 
138 	for ( i = 0; i < CH_MASK_SZ; i++ )
139 		if ( 0 != m_MaskRegs[ i ] )
140 			return FALSE;
141 
142 	return TRUE;
143 
144 }	// void CChannelMask::IsEmpty()
145 
146 
147 //===========================================================================
148 //
149 // Call SetIndexInMask and ClearIndexInMask to set or clear a single bit.
150 //
151 //===========================================================================
152 
153 // Set driver channel index into DSP mask format
154 void CChannelMask::SetIndexInMask( WORD wPipeIndex )
155 {
156 
157 	m_MaskRegs[ wPipeIndex / CH_MASK_BITS ] |=
158 		  SWAP( (CH_MASK) (( (CH_MASK) 1 ) << ( wPipeIndex % CH_MASK_BITS ) ) );
159 
160 }	// void CChannelMask::SetIndexInMask( WORD wPipeIndex )
161 
162 
163 // Clear driver channel index into DSP mask format
164 void CChannelMask::ClearIndexInMask( WORD wPipeIndex )
165 {
166 
167 	m_MaskRegs[ wPipeIndex / CH_MASK_BITS ] &=
168 			SWAP( (CH_MASK)(~( ( (CH_MASK) 1 ) << ( wPipeIndex % CH_MASK_BITS ) ) ) );
169 
170 }	// void CChannelMask::ClearIndexInMask( WORD wPipeIndex )
171 
172 
173 //===========================================================================
174 //
175 // Use GetIndexFromMask	to search the mask for bits that are set.
176 //
177 // The search starts at the bit specified by wStartPipeIndex and returns
178 // the pipe index for the first non-zero bit found.
179 //
180 //	Returns ECHO_INVALID_CHANNEL if none are found.
181 //
182 //===========================================================================
183 
184 WORD CChannelMask::GetIndexFromMask( WORD wStartPipeIndex )
185 {
186 	WORD		wIndex = wStartPipeIndex % CH_MASK_BITS;
187 	WORD		wCt	 = wStartPipeIndex / CH_MASK_BITS;
188 	CH_MASK	Mask;
189 
190 	for ( ; wCt < CH_MASK_SZ; wCt++ )
191 	{
192 		Mask = SWAP( m_MaskRegs[ wCt ] );
193 		if ( 0 != Mask )
194 		{
195 			while( !( Mask & (1<<wIndex) ) &&
196 					 wIndex < CH_MASK_BITS )
197 				wIndex++;
198 			if ( wIndex < CH_MASK_BITS )
199 				return( wIndex + ( wCt * CH_MASK_BITS ) );
200 		}
201 		wIndex = 0;
202 	}
203 	return( (WORD) ECHO_INVALID_CHANNEL );
204 
205 }		// WORD CChannelMask::GetIndexFromMask( WORD wStartIndex )
206 
207 
208 //===========================================================================
209 //
210 // Returns TRUE if the bit specified by the pipe index is set.
211 //
212 //===========================================================================
213 
214 BOOL CChannelMask::TestIndexInMask( WORD wPipeIndex )
215 {
216 	if ( SWAP( m_MaskRegs[ wPipeIndex / CH_MASK_BITS ] ) &
217 			  (CH_MASK)( ( (CH_MASK) 1 ) << ( wPipeIndex % CH_MASK_BITS ) )
218 		)
219 		return TRUE;
220 
221 	return FALSE;
222 }	// BOOL CChannelMask::TestIndexInMask( WORD wPipeIndex )
223 
224 
225 //===========================================================================
226 //
227 // Clear bits in this mask that are in SrcMask - this is just like
228 // operator -=, below.
229 //
230 //===========================================================================
231 
232 void CChannelMask::ClearMask( CChannelMask SrcMask )
233 {
234 	int	i;
235 
236 	for ( i = 0; i < CH_MASK_SZ; i++ )
237 	{
238 		m_MaskRegs[ i ] &= ~SrcMask.m_MaskRegs[ i ];
239 	}
240 
241 }	// void CChannelMask::ClearMask( CChannelMask SrcMask )
242 
243 
244 //===========================================================================
245 //
246 //	Clear all channels in this mask
247 //
248 //===========================================================================
249 
250 void CChannelMask::Clear()
251 {
252 	int	i;
253 
254 	for ( i = 0; i < CH_MASK_SZ; i++ )
255 		m_MaskRegs[ i ] = 0;
256 
257 }	// void CChannelMask::Clear()
258 
259 
260 //===========================================================================
261 //
262 //	operator +=    Add channels in source mask to this mask
263 //
264 //===========================================================================
265 
266 VOID CChannelMask::operator += (CONST CChannelMask & RVal)
267 {
268 	int	i;
269 
270 	for ( i = 0; i < CH_MASK_SZ; i++ )
271 		m_MaskRegs[ i ] |= RVal.m_MaskRegs[ i ];
272 }	// VOID operator += (CONST CChannelMask & RVal)
273 
274 
275 //===========================================================================
276 //
277 //	operator -=    Remove channels in source mask from this mask
278 //
279 //===========================================================================
280 
281 VOID CChannelMask::operator -= (CONST CChannelMask & RVal)
282 {
283 	int	i;
284 
285 	for ( i = 0; i < CH_MASK_SZ; i++ )
286 		m_MaskRegs[ i ] &= ~RVal.m_MaskRegs[ i ];
287 
288 }	// VOID operator -= (CONST CChannelMask & RVal)
289 
290 
291 //===========================================================================
292 //
293 // Test returns TRUE if any bits in source mask are set in this mask
294 //
295 //===========================================================================
296 
297 BOOL CChannelMask::Test( PCChannelMask pSrcMask )
298 {
299 	int	i;
300 
301 	for ( i = 0; i < CH_MASK_SZ; i++ )
302 		if ( m_MaskRegs[ i ] & pSrcMask->m_MaskRegs[ i ] )
303 			return TRUE;
304 	return FALSE;
305 
306 }	// BOOL CChannelMask::Test( PChannelMask pSrcMask )
307 
308 
309 //===========================================================================
310 //
311 //	IsSubsetOf returns TRUE if all of the channels in TstMask are set in
312 // m_MaskRegs.
313 //
314 //	Use to be sure all channels in this instance exist in
315 //	another instance.
316 //
317 //===========================================================================
318 
319 BOOL CChannelMask::IsSubsetOf
320 (
321 	CChannelMask& TstMask
322 )
323 {
324 	for ( int i = 0; i < CH_MASK_SZ; i++ )
325 	{
326 		CH_MASK ThisMask;
327 
328 		ThisMask = SWAP( m_MaskRegs[ i ]);
329 		if ( ( ThisMask & TstMask[ i ] ) != ThisMask )
330 			return FALSE;
331 	}
332 
333 	return TRUE;
334 
335 }	// BOOL CChannelMask::IsSubsetOf
336 
337 
338 //===========================================================================
339 //
340 //	IsIntersectionOf returns TRUE if TstMask contains at least one of the
341 // channels enabled in this instance.
342 //
343 //	Use this to find out if any channels in this instance exist in
344 //	another instance.
345 //
346 //===========================================================================
347 
348 BOOL CChannelMask::IsIntersectionOf
349 (
350 	CChannelMask& TstMask
351 )
352 {
353 	for ( int i = 0; i < CH_MASK_SZ; i++ )
354 		if ( 0 != ( m_MaskRegs[ i ] & TstMask[ i ] ) )
355 			return TRUE;
356 
357 	return FALSE;
358 
359 }	// BOOL CChannelMask::IsIntersectionOf
360 
361 
362 //===========================================================================
363 //
364 // Operator == is just what you'd expect - it tells you if one mask is
365 // the same as another
366 //
367 //===========================================================================
368 
369 BOOLEAN operator == ( CONST CChannelMask &LVal, CONST CChannelMask &RVal )
370 {
371 	for ( int i = 0; i < CH_MASK_SZ; i++ )
372 		if ( LVal.m_MaskRegs[ i ] != RVal.m_MaskRegs[ i ] )
373 			return FALSE;
374 
375 	return TRUE;
376 
377 }	// BOOLEAN operator == ( CONST CChannelMask &LVal, CONST CChannelMask &RVal )
378 
379 
380 //===========================================================================
381 //
382 // Operator = just copies from one mask to another.
383 //
384 //===========================================================================
385 
386 CChannelMask& CChannelMask::operator =(CONST CChannelMask & RVal)
387 {
388 	if ( &RVal == this )
389 		return *this;
390 
391 	for ( int i = 0; i < CH_MASK_SZ; i++ )
392 		m_MaskRegs[ i ] = RVal.m_MaskRegs[ i ];
393 
394 	return *this;
395 
396 }	// CChannelMask& CChannelMask::operator = (CONTS CChannelMask & RVal)
397 
398 
399 CChannelMask& CChannelMask::operator =(CONST CChMaskDsp & RVal)
400 {
401 	CH_MASK *	pMask = (CH_MASK *) &RVal.m_MaskRegs[ 0 ];
402 
403 	m_MaskRegs[ 0 ] = *pMask;
404 	m_MaskRegs[ 1 ] = 0;
405 
406 	return *this;
407 
408 }	// CChannelMask& CChannelMask::operator =(CONST CChMaskDsp & RVal)
409 
410 
411 //===========================================================================
412 //
413 // Operator & performs a bitwise logical AND
414 //
415 //===========================================================================
416 
417 VOID CChannelMask::operator &= (CONST CChannelMask & RVal)
418 {
419 	if ( &RVal == this )
420 		return;
421 
422 	for ( int i = 0; i < CH_MASK_SZ; i++ )
423 		m_MaskRegs[ i ] &= RVal.m_MaskRegs[ i ];
424 
425 }	// VOID CChannelMask::operator &= (CONST CChannelMask & RVal)
426 
427 
428 //===========================================================================
429 //
430 // Operator & performs a bitwise logical OR
431 //
432 //===========================================================================
433 
434 VOID CChannelMask::operator |= (CONST CChannelMask & RVal)
435 {
436 	if ( &RVal == this )
437 		return;
438 
439 	for ( int i = 0; i < CH_MASK_SZ; i++ )
440 		m_MaskRegs[ i ] |= RVal.m_MaskRegs[ i ];
441 
442 }	// VOID CChannelMask::operator |= (CONST CChannelMask & RVal)
443 
444 
445 //===========================================================================
446 //
447 // Overload new & delete so memory for this object is allocated
448 //	from non-paged memory.
449 //
450 //===========================================================================
451 
452 PVOID CChannelMask::operator new( size_t Size )
453 {
454 	PVOID 		pMemory;
455 	ECHOSTATUS 	Status;
456 
457 	Status = OsAllocateNonPaged(Size,&pMemory);
458 
459 	if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory ))
460 	{
461 		ECHO_DEBUGPRINTF(("CChannelMask::operator new - memory allocation failed\n"));
462 
463 		pMemory = NULL;
464 	}
465 	else
466 	{
467 		memset( pMemory, 0, Size );
468 	}
469 
470 	return pMemory;
471 
472 }	// PVOID CChannelMask::operator new( size_t Size )
473 
474 
475 VOID  CChannelMask::operator delete( PVOID pVoid )
476 {
477 	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
478 	{
479 		ECHO_DEBUGPRINTF(("CChannelMask::operator delete memory free failed\n"));
480 	}
481 }	// VOID  CChannelMask::operator delete( PVOID pVoid )
482 
483 
484 
485 
486 /****************************************************************************
487 
488 	CChMaskDsp
489 
490  ****************************************************************************/
491 
492 //===========================================================================
493 //
494 // Constructor
495 //
496 //===========================================================================
497 
498 CChMaskDsp::CChMaskDsp()
499 {
500 
501 	Clear();
502 
503 }	// CChMaskDsp::CChMaskDsp()
504 
505 
506 //===========================================================================
507 //
508 // IsEmpty returns TRUE if mask has no bits set
509 //
510 //===========================================================================
511 
512 BOOL CChMaskDsp::IsEmpty()
513 {
514 	int	i;
515 
516 	for ( i = 0; i < CH_MASK_SZ; i++ )
517 		if ( 0 != m_MaskRegs[ i ] )
518 			return FALSE;
519 
520 	return TRUE;
521 
522 }	// void CChMaskDsp::IsEmpty()
523 
524 
525 //===========================================================================
526 //
527 // Call SetIndexInMask and ClearIndexInMask to set or clear a single bit.
528 //
529 //===========================================================================
530 
531 // Set driver channel index into DSP mask format
532 void CChMaskDsp::SetIndexInMask( WORD wPipeIndex )
533 {
534 
535 	m_MaskRegs[ wPipeIndex / CH_MASK_DSP_BITS ] |=
536 		SWAP( (CH_MASK_DSP)(( (CH_MASK_DSP) 1 ) << ( wPipeIndex % CH_MASK_DSP_BITS ) ) );
537 }	// void CChMaskDsp::SetIndexInMask( WORD wPipeIndex )
538 
539 
540 // Clear driver channel index into DSP mask format
541 void CChMaskDsp::ClearIndexInMask( WORD wPipeIndex )
542 {
543 	m_MaskRegs[ wPipeIndex / CH_MASK_DSP_BITS ] &=
544 		SWAP( (CH_MASK_DSP)(~( ( (CH_MASK_DSP) 1 ) << ( wPipeIndex % CH_MASK_DSP_BITS ) ) ) );
545 
546 }	// void CChMaskDsp::SetIndexInMask( WORD wPipeIndex )
547 
548 
549 //===========================================================================
550 //
551 // Returns TRUE if the bit specified by the pipe index is set.
552 //
553 //===========================================================================
554 
555 BOOL CChMaskDsp::TestIndexInMask( WORD wPipeIndex )
556 {
557 	if ( m_MaskRegs[ wPipeIndex / CH_MASK_DSP_BITS ] &
558 		  SWAP( (CH_MASK_DSP)( ( (CH_MASK_DSP) 1 ) << ( wPipeIndex % CH_MASK_DSP_BITS ) ) ) )
559 		return TRUE;
560 
561 	return FALSE;
562 
563 }	// BOOL CChMaskDsp::TestIndexInMask( WORD wPipeIndex )
564 
565 
566 //===========================================================================
567 //
568 //	Clear all channels in this mask
569 //
570 //===========================================================================
571 
572 void CChMaskDsp::Clear()
573 {
574 	int	i;
575 
576 	for ( i = 0; i < CH_MASK_SZ; i++ )
577 		m_MaskRegs[ i ] = 0;
578 }	// void CChMaskDsp::Clear()
579 
580 
581 //===========================================================================
582 //
583 //	operator +=    Add channels in source mask to this mask
584 //
585 //===========================================================================
586 
587 VOID CChMaskDsp::operator += (CONST CChannelMask & RVal)
588 {
589 	CH_MASK *	pMask = (CH_MASK *) &m_MaskRegs[ 0 ];
590 
591 	*pMask |= RVal.m_MaskRegs[ 0 ];
592 }	// VOID operator += (CONST CChMaskDsp & RVal)
593 
594 
595 //===========================================================================
596 //
597 //	operator -=    Remove channels in source mask from this mask
598 //
599 //===========================================================================
600 
601 VOID CChMaskDsp::operator -= (CONST CChannelMask & RVal)
602 {
603 	CH_MASK *	pMask = (CH_MASK *) &m_MaskRegs[ 0 ];
604 
605 	*pMask &= ~RVal.m_MaskRegs[ 0 ];
606 }	// VOID operator += (CONST CChMaskDsp & RVal)
607 
608 
609 //===========================================================================
610 //
611 // Operator = just copies from one mask to another.
612 //
613 //===========================================================================
614 
615 CChMaskDsp& CChMaskDsp::operator =(CONST CChannelMask & RVal)
616 {
617 	CH_MASK *	pMask = (CH_MASK *) &m_MaskRegs[ 0 ];
618 
619 	*pMask = RVal.m_MaskRegs[ 0 ];
620 	return *this;
621 
622 }	// CChMaskDsp& CChMaskDsp::operator =(CONST CChannelMask & RVal)
623 
624 
625 //===========================================================================
626 //
627 // Overload new & delete so memory for this object is allocated
628 //	from non-paged memory.
629 //
630 //===========================================================================
631 
632 PVOID CChMaskDsp::operator new( size_t Size )
633 {
634 	PVOID 		pMemory;
635 	ECHOSTATUS 	Status;
636 
637 	Status = OsAllocateNonPaged(Size,&pMemory);
638 
639 	if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory ))
640 	{
641 		ECHO_DEBUGPRINTF(("CChMaskDsp::operator new memory allocation failed\n"));
642 
643 		pMemory = NULL;
644 	}
645 	else
646 	{
647 		memset( pMemory, 0, Size );
648 	}
649 
650 	return pMemory;
651 
652 }	// PVOID CChMaskDsp::operator new( size_t Size )
653 
654 
655 VOID  CChMaskDsp::operator delete( PVOID pVoid )
656 {
657 	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
658 	{
659 		ECHO_DEBUGPRINTF(("CChMaskDsp::operator delete memory free failed\n"));
660 	}
661 }	// VOID  CChMaskDsp::operator delete( PVOID pVoid )
662 
663 
664 // ChannelMask.cpp
665