/* |
File: SynthNoteList.h |
Abstract: Part of CoreAudio Utility Classes |
Version: 1.0.1 |
|
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple |
Inc. ("Apple") in consideration of your agreement to the following |
terms, and your use, installation, modification or redistribution of |
this Apple software constitutes acceptance of these terms. If you do |
not agree with these terms, please do not use, install, modify or |
redistribute this Apple software. |
|
In consideration of your agreement to abide by the following terms, and |
subject to these terms, Apple grants you a personal, non-exclusive |
license, under Apple's copyrights in this original Apple software (the |
"Apple Software"), to use, reproduce, modify and redistribute the Apple |
Software, with or without modifications, in source and/or binary forms; |
provided that if you redistribute the Apple Software in its entirety and |
without modifications, you must retain this notice and the following |
text and disclaimers in all such redistributions of the Apple Software. |
Neither the name, trademarks, service marks or logos of Apple Inc. may |
be used to endorse or promote products derived from the Apple Software |
without specific prior written permission from Apple. Except as |
expressly stated in this notice, no other rights or licenses, express or |
implied, are granted by Apple herein, including but not limited to any |
patent rights that may be infringed by your derivative works or by other |
works in which the Apple Software may be incorporated. |
|
The Apple Software is provided by Apple on an "AS IS" basis. APPLE |
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION |
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS |
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND |
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
|
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL |
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, |
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED |
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), |
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
|
Copyright (C) 2014 Apple Inc. All Rights Reserved. |
|
*/ |
#ifndef __SynthNoteList__ |
#define __SynthNoteList__ |
|
#include "SynthNote.h" |
|
#if DEBUG |
#ifndef DEBUG_PRINT |
#define DEBUG_PRINT 0 |
#endif |
#define USE_SANITY_CHECK 0 |
#endif |
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
struct SynthNoteList |
{ |
SynthNoteList() : mState(kNoteState_Unset), mHead(0), mTail(0) {} |
|
bool NotEmpty() const { return mHead != NULL; } |
bool IsEmpty() const { return mHead == NULL; } |
void Empty() { |
#if USE_SANITY_CHECK |
SanityCheck(); |
#endif |
mHead = mTail = NULL; |
} |
|
UInt32 Length() const { |
#if USE_SANITY_CHECK |
SanityCheck(); |
#endif |
UInt32 length = 0; |
for (SynthNote* note = mHead; note; note = note->mNext) |
length++; |
return length; |
}; |
|
void AddNote(SynthNote *inNote) |
{ |
#if DEBUG_PRINT |
printf("AddNote(inNote=%p) to state: %lu\n", inNote, mState); |
#endif |
#if USE_SANITY_CHECK |
SanityCheck(); |
#endif |
inNote->SetState(mState); |
inNote->mNext = mHead; |
inNote->mPrev = NULL; |
|
if (mHead) { mHead->mPrev = inNote; mHead = inNote; } |
else mHead = mTail = inNote; |
#if USE_SANITY_CHECK |
SanityCheck(); |
#endif |
} |
|
void RemoveNote(SynthNote *inNote) |
{ |
#if DEBUG_PRINT |
printf("RemoveNote(inNote=%p) from state: %lu\n", inNote, mState); |
#endif |
#if USE_SANITY_CHECK |
SanityCheck(); |
#endif |
if (inNote->mPrev) inNote->mPrev->mNext = inNote->mNext; |
else mHead = inNote->mNext; |
|
if (inNote->mNext) inNote->mNext->mPrev = inNote->mPrev; |
else mTail = inNote->mPrev; |
|
inNote->mPrev = 0; |
inNote->mNext = 0; |
#if USE_SANITY_CHECK |
SanityCheck(); |
#endif |
} |
|
void TransferAllFrom(SynthNoteList *inNoteList, UInt32 inFrame) |
{ |
#if DEBUG_PRINT |
printf("TransferAllFrom: from state %lu into state %lu\n", inNoteList->mState, mState); |
#endif |
#if USE_SANITY_CHECK |
SanityCheck(); |
inNoteList->SanityCheck(); |
#endif |
if (!inNoteList->mTail) return; |
|
if (mState == kNoteState_Released) |
{ |
for (SynthNote* note = inNoteList->mHead; note; note = note->mNext) |
{ |
#if DEBUG_PRINT |
printf("TransferAllFrom: releasing note %p\n", note); |
#endif |
note->Release(inFrame); |
note->SetState(mState); |
} |
} |
else |
{ |
for (SynthNote* note = inNoteList->mHead; note; note = note->mNext) |
{ |
note->SetState(mState); |
} |
} |
|
inNoteList->mTail->mNext = mHead; |
|
if (mHead) mHead->mPrev = inNoteList->mTail; |
else mTail = inNoteList->mTail; |
|
mHead = inNoteList->mHead; |
|
inNoteList->mHead = NULL; |
inNoteList->mTail = NULL; |
#if USE_SANITY_CHECK |
SanityCheck(); |
inNoteList->SanityCheck(); |
#endif |
} |
|
SynthNote* FindOldestNote() |
{ |
#if DEBUG_PRINT |
printf("FindOldestNote\n"); |
#endif |
#if USE_SANITY_CHECK |
SanityCheck(); |
#endif |
UInt64 minStartFrame = -1; |
SynthNote* oldestNote = NULL; |
for (SynthNote* note = mHead; note; note = note->mNext) |
{ |
if (note->mAbsoluteStartFrame < minStartFrame) |
{ |
oldestNote = note; |
minStartFrame = note->mAbsoluteStartFrame; |
} |
} |
return oldestNote; |
} |
|
SynthNote* FindMostQuietNote() |
{ |
#if DEBUG_PRINT |
printf("FindMostQuietNote\n"); |
#endif |
Float32 minAmplitude = 1e9f; |
UInt64 minStartFrame = -1; |
SynthNote* mostQuietNote = NULL; |
for (SynthNote* note = mHead; note; note = note->mNext) |
{ |
Float32 amp = note->Amplitude(); |
#if DEBUG_PRINT |
printf(" amp %g minAmplitude %g\n", amp, minAmplitude); |
#endif |
if (amp < minAmplitude) |
{ |
mostQuietNote = note; |
minAmplitude = amp; |
minStartFrame = note->mAbsoluteStartFrame; |
} |
else if (amp == minAmplitude && note->mAbsoluteStartFrame < minStartFrame) |
{ |
// use earliest start time as a tie breaker |
mostQuietNote = note; |
minStartFrame = note->mAbsoluteStartFrame; |
} |
} |
#if USE_SANITY_CHECK |
SanityCheck(); |
#endif |
return mostQuietNote; |
} |
|
void SanityCheck() const; |
|
SynthNoteState mState; |
SynthNote * mHead; |
SynthNote * mTail; |
}; |
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
#endif |