LCOV - code coverage report
Current view: top level - Core - OOSoundSourcePool.m (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 0 10 0.0 %
Date: 2025-05-28 07:50:54 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : 
       3             : OOSoundSourcePool.m
       4             :  
       5             :  
       6             : Copyright (C) 2008-2013 Jens Ayton
       7             : 
       8             : Permission is hereby granted, free of charge, to any person obtaining a copy
       9             : of this software and associated documentation files (the "Software"), to deal
      10             : in the Software without restriction, including without limitation the rights
      11             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12             : copies of the Software, and to permit persons to whom the Software is
      13             : furnished to do so, subject to the following conditions:
      14             : 
      15             : The above copyright notice and this permission notice shall be included in all
      16             : copies or substantial portions of the Software.
      17             : 
      18             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      19             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      20             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      21             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      22             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      24             : SOFTWARE.
      25             : 
      26             : */
      27             : 
      28             : #import "OOSoundSourcePool.h"
      29             : #import "OOSound.h"
      30             : #import "Universe.h"
      31             : 
      32             : 
      33           0 : enum
      34             : {
      35             :         kNoSlot = UINT8_MAX
      36             : };
      37             : 
      38             : 
      39           0 : typedef struct OOSoundSourcePoolElement
      40             : {
      41           0 :         OOSoundSource                   *source;
      42           0 :         OOTimeAbsolute                  expiryTime;
      43           0 :         float                                   priority;
      44           0 : } PoolElement;
      45             : 
      46             : 
      47             : @interface OOSoundSourcePool (Private)
      48             : 
      49           0 : - (uint8_t) selectSlotForPriority:(float)priority;
      50             : 
      51             : @end
      52             : 
      53             : 
      54             : @implementation OOSoundSourcePool
      55             : 
      56             : + (instancetype) poolWithCount:(uint8_t)count minRepeatTime:(OOTimeDelta)minRepeat
      57             : {
      58             :         return [[[self alloc] initWithCount:count minRepeatTime:minRepeat] autorelease];
      59             : }
      60             : 
      61             : 
      62             : - (id) initWithCount:(uint8_t)count minRepeatTime:(OOTimeDelta)minRepeat
      63             : {
      64             :         if ((self = [super init]))
      65             :         {
      66             :                 // Sanity-check count
      67             :                 if (count == 0)  count = 1;
      68             :                 if (count == kNoSlot)  --count;
      69             :                 _count = count;
      70             :                 _reserved = kNoSlot;
      71             :                 
      72             :                 if (minRepeat < 0.0)  minRepeat = 0.0;
      73             :                 _minRepeat = minRepeat;
      74             :                 
      75             :                 // Create source pool
      76             :                 _sources = calloc(sizeof(PoolElement), count);
      77             :                 if (_sources == NULL)
      78             :                 {
      79             :                         [self release];
      80             :                         self = nil;
      81             :                 }
      82             :         }
      83             :         return self;
      84             : }
      85             : 
      86             : 
      87           0 : - (void) dealloc
      88             : {
      89             :         uint8_t                                 i;
      90             :         
      91             :         for (i = 0; i != _count; i++)
      92             :         {
      93             :                 [_sources[i].source release];
      94             :         }
      95             :         free(_sources);
      96             : 
      97             :         [_lastKey release];
      98             :         
      99             :         [super dealloc];
     100             : }
     101             : 
     102             : 
     103             : - (void) playSoundWithKey:(NSString *)key
     104             :                                  priority:(float)priority
     105             :                            expiryTime:(OOTimeDelta)expiryTime
     106             :                                  overlap:(BOOL)overlap
     107             :                                  position:(Vector)position
     108             : {
     109             :         uint8_t                                 slot;
     110             :         OOTimeAbsolute                  now, absExpiryTime;
     111             :         PoolElement                             *element = NULL;
     112             :         OOSound                                 *sound = NULL;
     113             :         
     114             :         // Convert expiry time to absolute
     115             :         now = [UNIVERSE getTime];
     116             :         absExpiryTime = expiryTime + now;
     117             :         
     118             :         // Avoid repeats if required
     119             :         if (now < _nextRepeat && [key isEqualToString:_lastKey])  return;
     120             :         if (!overlap && _reserved != kNoSlot && [_sources[_reserved].source isPlaying]) return;
     121             :         
     122             :         // Look for a slot in the source list to use
     123             :         slot = [self selectSlotForPriority:priority];
     124             :         if (slot == kNoSlot)  return;
     125             :         element = &_sources[slot];
     126             :         
     127             :         // Load sound
     128             :         sound = [OOSound soundWithCustomSoundKey:key];
     129             :         if (sound == nil)  return;
     130             :         
     131             :         // Stop playing sound or set up sound source as appropriate
     132             :         if (element->source != nil)  [element->source stop];
     133             :         else
     134             :         {
     135             :                 element->source = [[OOSoundSource alloc] init];
     136             :                 if (element->source == nil)  return;
     137             :         }
     138             :         if (slot == _reserved) _reserved = kNoSlot;     // _reserved has finished playing!
     139             :         if (!overlap) _reserved = slot;
     140             :         
     141             :         // Play and store metadata
     142             :         [element->source setPosition:position];
     143             :         [element->source playSound:sound];
     144             :         element->expiryTime = absExpiryTime;
     145             :         element->priority = priority;
     146             :         if (_minRepeat > 0.0)
     147             :         {
     148             :                 _nextRepeat = now + _minRepeat;
     149             :                 [_lastKey release];
     150             :                 _lastKey = [key copy];
     151             :         }
     152             :         
     153             :         // Set staring search location for next slot lookup
     154             :         _latest = slot;
     155             : }
     156             : 
     157             : 
     158             : - (void) playSoundWithKey:(NSString *)key
     159             :                                  priority:(float)priority
     160             :                            expiryTime:(OOTimeDelta)expiryTime
     161             : {
     162             :         [self playSoundWithKey:key
     163             :                                   priority:priority
     164             :                                 expiryTime:expiryTime
     165             :                                    overlap:YES
     166             :                                   position:kZeroVector];
     167             : }
     168             : 
     169             : 
     170             : - (void) playSoundWithKey:(NSString *)key
     171             :                                  priority:(float)priority
     172             :                                  position:(Vector)position
     173             : {
     174             :         [self playSoundWithKey:key
     175             :                                   priority:priority
     176             :                                 expiryTime:0.5 + randf() * 0.1
     177             :                                    overlap:YES
     178             :                                   position:position];
     179             : }
     180             : 
     181             : 
     182             : - (void) playSoundWithKey:(NSString *)key
     183             :                                  priority:(float)priority
     184             : {
     185             :         [self playSoundWithKey:key
     186             :                                   priority:priority
     187             :                                 expiryTime:0.5 + randf() * 0.1];
     188             : }
     189             : 
     190             : 
     191             : - (void) playSoundWithKey:(NSString *)key
     192             : {
     193             :         [self playSoundWithKey:key priority:1.0];
     194             : }
     195             : 
     196             : 
     197             : - (void) playSoundWithKey:(NSString *)key position:(Vector)position
     198             : {
     199             :         [self playSoundWithKey:key priority:1.0 position:position];
     200             : }
     201             : 
     202             : 
     203             : - (void) playSoundWithKey:(NSString *)key overlap:(BOOL)overlap
     204             : {
     205             :         [self playSoundWithKey:key
     206             :                                   priority:1.0
     207             :                                 expiryTime:0.5
     208             :                                    overlap:overlap
     209             :                                   position:kZeroVector];
     210             : }
     211             : 
     212             : 
     213             : - (void) playSoundWithKey:(NSString *)key overlap:(BOOL)overlap position:(Vector)position
     214             : {
     215             :         [self playSoundWithKey:key
     216             :                                   priority:1.0
     217             :                                 expiryTime:0.5
     218             :                                    overlap:overlap
     219             :                                   position:position];
     220             : }
     221             : 
     222             : 
     223             : @end
     224             : 
     225             : 
     226             : @implementation OOSoundSourcePool (Private)
     227             : 
     228             : - (uint8_t) selectSlotForPriority:(float)priority
     229             : {
     230             :         uint8_t                                 curr, count, expiredLower = kNoSlot, unexpiredLower = kNoSlot, expiredEqual = kNoSlot;
     231             :         PoolElement                             *element = NULL;
     232             :         OOTimeAbsolute                  now = [UNIVERSE getTime];
     233             :         
     234           0 : #define NEXT(x) (((x) + 1) % _count)
     235             :         
     236             :         curr = _latest;
     237             :         count = _count;
     238             :         do
     239             :         {
     240             :                 curr = NEXT(curr);
     241             :                 element = &_sources[curr];
     242             :                 
     243             :                 if (element->source == nil || ![element->source isPlaying])  return curr; // Best type of slot: empty
     244             :                 else if (element->priority < priority)
     245             :                 {
     246             :                         if (element->expiryTime <= now)  expiredLower = curr;     // Second-best type: expired lower-priority
     247             :                         else if (curr != _reserved) unexpiredLower = curr;              // Third-best type: unexpired lower-priority
     248             :                 }
     249             :                 else if (element->priority == priority && element->expiryTime <= now)
     250             :                 {
     251             :                         expiredEqual = curr;                                                                    // Fourth-best type: expired equal-priority.
     252             :                 }
     253             :         } while (--count);
     254             :         
     255             :         if (expiredLower != kNoSlot)  return expiredLower;
     256             :         if (unexpiredLower != kNoSlot)  return unexpiredLower;
     257             :         return expiredEqual;    // Will be kNoSlot if none found
     258             : }
     259             : 
     260             : @end

Generated by: LCOV version 1.14