1 /* 2 Copyright (C) 2016 Apple Inc. All Rights Reserved. 3 See LICENSE.txt for this sample’s licensing information 4 5 Abstract: 6 Part of Core Audio AUInstrument Base Classes 7 */ 8 9 #ifndef __SynthNoteList__ 10 #define __SynthNoteList__ 11 12 #include "SynthNote.h" 13 14 #if DEBUG 15 #ifndef DEBUG_PRINT 16 #define DEBUG_PRINT 0 17 #endif 18 #define USE_SANITY_CHECK 0 19 #endif 20 21 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 22 23 struct SynthNoteList 24 { SynthNoteListSynthNoteList25 SynthNoteList() : mState(kNoteState_Unset), mHead(0), mTail(0) {} 26 NotEmptySynthNoteList27 bool NotEmpty() const { return mHead != NULL; } IsEmptySynthNoteList28 bool IsEmpty() const { return mHead == NULL; } EmptySynthNoteList29 void Empty() { 30 #if USE_SANITY_CHECK 31 SanityCheck(); 32 #endif 33 mHead = mTail = NULL; 34 } 35 LengthSynthNoteList36 UInt32 Length() const { 37 #if USE_SANITY_CHECK 38 SanityCheck(); 39 #endif 40 UInt32 length = 0; 41 for (SynthNote* note = mHead; note; note = note->mNext) 42 length++; 43 return length; 44 }; 45 AddNoteSynthNoteList46 void AddNote(SynthNote *inNote) 47 { 48 #if DEBUG_PRINT 49 printf("AddNote(inNote=%p) to state: %lu\n", inNote, mState); 50 #endif 51 #if USE_SANITY_CHECK 52 SanityCheck(); 53 #endif 54 inNote->SetState(mState); 55 inNote->mNext = mHead; 56 inNote->mPrev = NULL; 57 58 if (mHead) { mHead->mPrev = inNote; mHead = inNote; } 59 else mHead = mTail = inNote; 60 #if USE_SANITY_CHECK 61 SanityCheck(); 62 #endif 63 } 64 RemoveNoteSynthNoteList65 void RemoveNote(SynthNote *inNote) 66 { 67 #if DEBUG_PRINT 68 printf("RemoveNote(inNote=%p) from state: %lu\n", inNote, mState); 69 #endif 70 #if USE_SANITY_CHECK 71 SanityCheck(); 72 #endif 73 if (inNote->mPrev) inNote->mPrev->mNext = inNote->mNext; 74 else mHead = inNote->mNext; 75 76 if (inNote->mNext) inNote->mNext->mPrev = inNote->mPrev; 77 else mTail = inNote->mPrev; 78 79 inNote->mPrev = 0; 80 inNote->mNext = 0; 81 #if USE_SANITY_CHECK 82 SanityCheck(); 83 #endif 84 } 85 TransferAllFromSynthNoteList86 void TransferAllFrom(SynthNoteList *inNoteList, UInt32 inFrame) 87 { 88 #if DEBUG_PRINT 89 printf("TransferAllFrom: from state %lu into state %lu\n", inNoteList->mState, mState); 90 #endif 91 #if USE_SANITY_CHECK 92 SanityCheck(); 93 inNoteList->SanityCheck(); 94 #endif 95 if (!inNoteList->mTail) return; 96 97 if (mState == kNoteState_Released) 98 { 99 for (SynthNote* note = inNoteList->mHead; note; note = note->mNext) 100 { 101 #if DEBUG_PRINT 102 printf("TransferAllFrom: releasing note %p\n", note); 103 #endif 104 note->Release(inFrame); 105 note->SetState(mState); 106 } 107 } 108 else 109 { 110 for (SynthNote* note = inNoteList->mHead; note; note = note->mNext) 111 { 112 note->SetState(mState); 113 } 114 } 115 116 inNoteList->mTail->mNext = mHead; 117 118 if (mHead) mHead->mPrev = inNoteList->mTail; 119 else mTail = inNoteList->mTail; 120 121 mHead = inNoteList->mHead; 122 123 inNoteList->mHead = NULL; 124 inNoteList->mTail = NULL; 125 #if USE_SANITY_CHECK 126 SanityCheck(); 127 inNoteList->SanityCheck(); 128 #endif 129 } 130 FindOldestNoteSynthNoteList131 SynthNote* FindOldestNote() 132 { 133 #if DEBUG_PRINT 134 printf("FindOldestNote\n"); 135 #endif 136 #if USE_SANITY_CHECK 137 SanityCheck(); 138 #endif 139 UInt64 minStartFrame = -1; 140 SynthNote* oldestNote = NULL; 141 for (SynthNote* note = mHead; note; note = note->mNext) 142 { 143 if (note->mAbsoluteStartFrame < minStartFrame) 144 { 145 oldestNote = note; 146 minStartFrame = note->mAbsoluteStartFrame; 147 } 148 } 149 return oldestNote; 150 } 151 FindMostQuietNoteSynthNoteList152 SynthNote* FindMostQuietNote() 153 { 154 #if DEBUG_PRINT 155 printf("FindMostQuietNote\n"); 156 #endif 157 Float32 minAmplitude = 1e9f; 158 UInt64 minStartFrame = -1; 159 SynthNote* mostQuietNote = NULL; 160 for (SynthNote* note = mHead; note; note = note->mNext) 161 { 162 Float32 amp = note->Amplitude(); 163 #if DEBUG_PRINT 164 printf(" amp %g minAmplitude %g\n", amp, minAmplitude); 165 #endif 166 if (amp < minAmplitude) 167 { 168 mostQuietNote = note; 169 minAmplitude = amp; 170 minStartFrame = note->mAbsoluteStartFrame; 171 } 172 else if (amp == minAmplitude && note->mAbsoluteStartFrame < minStartFrame) 173 { 174 // use earliest start time as a tie breaker 175 mostQuietNote = note; 176 minStartFrame = note->mAbsoluteStartFrame; 177 } 178 } 179 #if USE_SANITY_CHECK 180 SanityCheck(); 181 #endif 182 return mostQuietNote; 183 } 184 185 void SanityCheck() const; 186 187 SynthNoteState mState; 188 SynthNote * mHead; 189 SynthNote * mTail; 190 }; 191 192 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 193 194 #endif 195