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// ----------------------------------------------------------------------------
15//
16// This file is part of Echo Digital Audio's generic driver library.
17// Copyright Echo Digital Audio Corporation (c) 1998 - 2005
18// All rights reserved
19// www.echoaudio.com
20//
21// This library is free software; you can redistribute it and/or
22// modify it under the terms of the GNU Lesser General Public
23// License as published by the Free Software Foundation; either
24// version 2.1 of the License, or (at your option) any later version.
25//
26// This library is distributed in the hope that it will be useful,
27// but WITHOUT ANY WARRANTY; without even the implied warranty of
28// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29// Lesser General Public License for more details.
30//
31// You should have received a copy of the GNU Lesser General Public
32// License along with this library; if not, write to the Free Software
33// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
34//
35// ****************************************************************************
36
37#include "CEchoGals.h"
38
39
40/****************************************************************************
41
42	CChannelMask
43
44 ****************************************************************************/
45
46//===========================================================================
47//
48// Constructor
49//
50//===========================================================================
51
52CChannelMask::CChannelMask()
53{
54
55	Clear();
56
57}	// CChannelMask::CChannelMask()
58
59
60//===========================================================================
61//
62//	SetMask, SetOutMask, and SetInMask all allow you to just set
63// the masks directly.
64//
65//===========================================================================
66
67void CChannelMask::SetMask( CH_MASK OutMask, CH_MASK InMask, int nOutputs )
68{
69
70	m_Mask = OutMask;
71	m_Mask |= InMask << nOutputs;
72
73}	// void CChannelMask::SetMask( ... )
74
75
76void CChannelMask::SetOutMask( CH_MASK OutMask, int nOutputs )
77{
78
79	m_Mask &= ((CH_MASK) -1) << nOutputs;
80	m_Mask |= OutMask;
81
82}	// void CChannelMask::SetOutMask( CH_MASK OutMask, int nOutputs )
83
84
85void CChannelMask::SetInMask( CH_MASK InMask, int nOutputs )
86{
87	m_Mask &= ~( (CH_MASK) -1 << nOutputs );
88	m_Mask |= InMask << nOutputs;
89}	// void CChannelMask::SetInMask( CH_MASK InMask, int nOutputs )
90
91
92//===========================================================================
93//
94//	Retrieve an output bit mask and an input bitmask.
95//
96//===========================================================================
97
98void CChannelMask::GetMask( CH_MASK & OutMask, CH_MASK & InMask, int nOutputs )
99{
100	OutMask = GetOutMask( nOutputs );
101	InMask = GetInMask( nOutputs );
102}	// void CChannelMask::GetMask( ... )
103
104CH_MASK CChannelMask::GetOutMask( int nOutputs )
105{
106	return  m_Mask & ~( (CH_MASK) -1 << nOutputs );
107}	// CH_MASK CChannelMask::GetOutMask( int nOutputs )
108
109CH_MASK CChannelMask::GetInMask( int nOutputs )
110{
111	return  m_Mask >> nOutputs;
112}	// CH_MASK CChannelMask::GetIntMask( int nOutputs )
113
114
115//===========================================================================
116//
117// IsEmpty returns TRUE if mask has no bits set
118//
119//===========================================================================
120
121BOOL CChannelMask::IsEmpty()
122{
123	if (0 != m_Mask)
124		return FALSE;
125
126	return TRUE;
127
128}	// void CChannelMask::IsEmpty()
129
130
131//===========================================================================
132//
133// Call SetIndexInMask and ClearIndexInMask to set or clear a single bit.
134//
135//===========================================================================
136
137// Set driver channel index into DSP mask format
138void CChannelMask::SetIndexInMask( WORD wPipeIndex )
139{
140	m_Mask |= 1 << wPipeIndex;
141
142}	// void CChannelMask::SetIndexInMask( WORD wPipeIndex )
143
144
145// Clear driver channel index into DSP mask format
146void CChannelMask::ClearIndexInMask( WORD wPipeIndex )
147{
148
149	m_Mask &= ~((CH_MASK) 1 << wPipeIndex);
150
151}	// void CChannelMask::ClearIndexInMask( WORD wPipeIndex )
152
153
154//===========================================================================
155//
156// Use GetIndexFromMask	to search the mask for bits that are set.
157//
158// The search starts at the bit specified by wStartPipeIndex and returns
159// the pipe index for the first non-zero bit found.
160//
161//	Returns ECHO_INVALID_CHANNEL if none are found.
162//
163//===========================================================================
164
165WORD CChannelMask::GetIndexFromMask( WORD wStartPipeIndex )
166{
167	CH_MASK bit;
168	WORD index;
169
170	bit = 1 << wStartPipeIndex;
171	index = wStartPipeIndex;
172	while (bit != 0)
173	{
174		if (0 != (m_Mask & bit))
175			return index;
176
177		bit <<= 1;
178		index++;
179	}
180
181	return( (WORD) ECHO_INVALID_CHANNEL );
182
183}		// WORD CChannelMask::GetIndexFromMask( WORD wStartIndex )
184
185
186//===========================================================================
187//
188// Returns TRUE if the bit specified by the pipe index is set.
189//
190//===========================================================================
191
192BOOL CChannelMask::TestIndexInMask( WORD wPipeIndex )
193{
194	if (0 != (m_Mask & ((CH_MASK) 1 << wPipeIndex)))
195		return TRUE;
196
197	return FALSE;
198}	// BOOL CChannelMask::TestIndexInMask( WORD wPipeIndex )
199
200
201//===========================================================================
202//
203// Clear bits in this mask that are in SrcMask - this is just like
204// operator -=, below.
205//
206//===========================================================================
207
208void CChannelMask::ClearMask( CChannelMask SrcMask )
209{
210	m_Mask &= ~SrcMask.m_Mask;
211
212}	// void CChannelMask::ClearMask( CChannelMask SrcMask )
213
214
215//===========================================================================
216//
217//	Clear all channels in this mask
218//
219//===========================================================================
220
221void CChannelMask::Clear()
222{
223	m_Mask = 0;
224}	// void CChannelMask::Clear()
225
226
227//===========================================================================
228//
229//	operator +=    Add channels in source mask to this mask
230//
231//===========================================================================
232
233VOID CChannelMask::operator += (CONST CChannelMask & RVal)
234{
235	m_Mask |= RVal.m_Mask;
236
237}	// VOID operator += (CONST CChannelMask & RVal)
238
239
240//===========================================================================
241//
242//	operator -=    Remove channels in source mask from this mask
243//
244//===========================================================================
245
246VOID CChannelMask::operator -= (CONST CChannelMask & RVal)
247{
248	ClearMask(RVal);
249}	// VOID operator -= (CONST CChannelMask & RVal)
250
251
252//===========================================================================
253//
254// Test returns TRUE if any bits in source mask are set in this mask
255//
256//===========================================================================
257
258BOOL CChannelMask::Test( PCChannelMask pSrcMask )
259{
260	if (0 != (m_Mask & pSrcMask->m_Mask))
261		return TRUE;
262
263	return FALSE;
264
265}	// BOOL CChannelMask::Test( PChannelMask pSrcMask )
266
267
268//===========================================================================
269//
270//	IsSubsetOf returns TRUE if all of the channels in TstMask are set in
271// m_Mask.
272//
273//	Use to be sure all channels in this instance exist in
274//	another instance.
275//
276//===========================================================================
277
278BOOL CChannelMask::IsSubsetOf
279(
280	CChannelMask& TstMask
281)
282{
283	if ((m_Mask & TstMask.m_Mask) != TstMask.m_Mask)
284		return FALSE;
285
286	return TRUE;
287
288}	// BOOL CChannelMask::IsSubsetOf
289
290
291//===========================================================================
292//
293//	IsIntersectionOf returns TRUE if TstMask contains at least one of the
294// channels enabled in this instance.
295//
296//	Use this to find out if any channels in this instance exist in
297//	another instance.
298//
299//===========================================================================
300
301BOOL CChannelMask::IsIntersectionOf
302(
303	CChannelMask& TstMask
304)
305{
306	if (0 != (m_Mask & TstMask.m_Mask))
307		return TRUE;
308
309	return FALSE;
310
311}	// BOOL CChannelMask::IsIntersectionOf
312
313
314//===========================================================================
315//
316// Operator == is just what you'd expect - it tells you if one mask is
317// the same as another
318//
319//===========================================================================
320
321BOOLEAN operator == ( CONST CChannelMask &LVal, CONST CChannelMask &RVal )
322{
323	if (LVal.m_Mask != RVal.m_Mask)
324		return FALSE;
325
326	return TRUE;
327
328}	// BOOLEAN operator == ( CONST CChannelMask &LVal, CONST CChannelMask &RVal )
329
330
331//===========================================================================
332//
333// Operator = just copies from one mask to another.
334//
335//===========================================================================
336
337CChannelMask& CChannelMask::operator =(CONST CChannelMask & RVal)
338{
339	if ( &RVal == this )
340		return *this;
341
342	m_Mask = RVal.m_Mask;
343
344	return *this;
345
346}	// CChannelMask& CChannelMask::operator = (CONTS CChannelMask & RVal)
347
348
349//===========================================================================
350//
351// Operator & performs a bitwise logical AND
352//
353//===========================================================================
354
355VOID CChannelMask::operator &= (CONST CChannelMask & RVal)
356{
357	if ( &RVal == this )
358		return;
359
360	m_Mask &= RVal.m_Mask;
361
362}	// VOID CChannelMask::operator &= (CONST CChannelMask & RVal)
363
364
365//===========================================================================
366//
367// Operator & performs a bitwise logical OR
368//
369//===========================================================================
370
371VOID CChannelMask::operator |= (CONST CChannelMask & RVal)
372{
373	if ( &RVal == this )
374		return;
375
376	m_Mask |= RVal.m_Mask;
377
378}	// VOID CChannelMask::operator |= (CONST CChannelMask & RVal)
379
380
381//===========================================================================
382//
383// Overload new & delete so memory for this object is allocated
384//	from non-paged memory.
385//
386//===========================================================================
387
388PVOID CChannelMask::operator new( size_t Size )
389{
390	PVOID 		pMemory;
391	ECHOSTATUS 	Status;
392
393	Status = OsAllocateNonPaged(Size,&pMemory);
394
395	if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory ))
396	{
397		ECHO_DEBUGPRINTF(("CChannelMask::operator new - memory allocation failed\n"));
398
399		pMemory = NULL;
400	}
401	else
402	{
403		memset( pMemory, 0, Size );
404	}
405
406	return pMemory;
407
408}	// PVOID CChannelMask::operator new( size_t Size )
409
410
411VOID  CChannelMask::operator delete( PVOID pVoid )
412{
413	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
414	{
415		ECHO_DEBUGPRINTF(("CChannelMask::operator delete memory free failed\n"));
416	}
417}	// VOID  CChannelMask::operator delete( PVOID pVoid )
418
419
420
421
422/****************************************************************************
423
424	CChMaskDsp
425
426 ****************************************************************************/
427
428//===========================================================================
429//
430// Constructor
431//
432//===========================================================================
433
434CChMaskDsp::CChMaskDsp()
435{
436
437	Clear();
438
439}	// CChMaskDsp::CChMaskDsp()
440
441
442//===========================================================================
443//
444// IsEmpty returns TRUE if mask has no bits set
445//
446//===========================================================================
447
448BOOL CChMaskDsp::IsEmpty()
449{
450	if (0 != m_Mask)
451			return FALSE;
452
453	return TRUE;
454
455}	// void CChMaskDsp::IsEmpty()
456
457
458//===========================================================================
459//
460// Call SetIndexInMask and ClearIndexInMask to set or clear a single bit.
461//
462//===========================================================================
463
464// Set driver channel index into DSP mask format
465void CChMaskDsp::SetIndexInMask( WORD wPipeIndex )
466{
467	CH_MASK_DSP bit,temp;
468
469	temp = SWAP( m_Mask );
470	bit = 1 << wPipeIndex;
471	temp |= bit;
472	m_Mask = SWAP( temp );
473
474}	// void CChMaskDsp::SetIndexInMask( WORD wPipeIndex )
475
476
477// Clear driver channel index into DSP mask format
478void CChMaskDsp::ClearIndexInMask( WORD wPipeIndex )
479{
480	CH_MASK_DSP bit,temp;
481
482	temp = SWAP( m_Mask );
483	bit = 1 << wPipeIndex;
484	temp &= ~bit;
485	m_Mask = SWAP( temp );
486
487}	// void CChMaskDsp::SetIndexInMask( WORD wPipeIndex )
488
489
490//===========================================================================
491//
492// Returns TRUE if the bit specified by the pipe index is set.
493//
494//===========================================================================
495
496BOOL CChMaskDsp::TestIndexInMask( WORD wPipeIndex )
497{
498	CH_MASK_DSP temp,bit;
499
500	temp = SWAP(m_Mask);
501	bit = 1 << wPipeIndex;
502	if (0 != (temp & bit))
503		return TRUE;
504
505	return FALSE;
506
507}	// BOOL CChMaskDsp::TestIndexInMask( WORD wPipeIndex )
508
509
510//===========================================================================
511//
512//	Clear all channels in this mask
513//
514//===========================================================================
515
516void CChMaskDsp::Clear()
517{
518	m_Mask = 0;
519}	// void CChMaskDsp::Clear()
520
521
522//===========================================================================
523//
524// Operator = just copies from one mask to another.
525//
526//===========================================================================
527
528CChMaskDsp& CChMaskDsp::operator =(CONST CChannelMask & RVal)
529{
530	m_Mask = SWAP(RVal.m_Mask);
531
532	return *this;
533
534}	// CChMaskDsp& CChMaskDsp::operator =(CONST CChannelMask & RVal)
535
536
537//===========================================================================
538//
539// Overload new & delete so memory for this object is allocated
540//	from non-paged memory.
541//
542//===========================================================================
543
544PVOID CChMaskDsp::operator new( size_t Size )
545{
546	PVOID 		pMemory;
547	ECHOSTATUS 	Status;
548
549	Status = OsAllocateNonPaged(Size,&pMemory);
550
551	if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory ))
552	{
553		ECHO_DEBUGPRINTF(("CChMaskDsp::operator new memory allocation failed\n"));
554
555		pMemory = NULL;
556	}
557	else
558	{
559		memset( pMemory, 0, Size );
560	}
561
562	return pMemory;
563
564}	// PVOID CChMaskDsp::operator new( size_t Size )
565
566
567VOID  CChMaskDsp::operator delete( PVOID pVoid )
568{
569	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
570	{
571		ECHO_DEBUGPRINTF(("CChMaskDsp::operator delete memory free failed\n"));
572	}
573}	// VOID  CChMaskDsp::operator delete( PVOID pVoid )
574
575
576// ChannelMask.cpp
577