diff --git a/Audjustable/Classes/AudioPlayer/AudioPlayer.h b/Audjustable/Classes/AudioPlayer/AudioPlayer.h index 8f2f551..0878321 100644 --- a/Audjustable/Classes/AudioPlayer/AudioPlayer.h +++ b/Audjustable/Classes/AudioPlayer/AudioPlayer.h @@ -172,6 +172,10 @@ AudioQueueBufferRefLookupEntry; volatile BOOL audioQueueFlushing; volatile SInt64 audioPacketsReadCount; volatile SInt64 audioPacketsPlayedCount; + + BOOL meteringEnabled; + AudioQueueLevelMeterState *levelMeterState; + NSInteger numberOfChannels; } @property (readonly) double duration; @@ -179,6 +183,8 @@ AudioQueueBufferRefLookupEntry; @property (readwrite) AudioPlayerState state; @property (readonly) AudioPlayerStopReason stopReason; @property (readwrite, unsafe_unretained) id delegate; +//! Turns level metering on or off. Default is off +@property(getter=isMeteringEnabled) BOOL meteringEnabled; -(id) init; -(id) initWithNumberOfAudioQueueBuffers:(int)numberOfAudioQueueBuffers andReadBufferSize:(int)readBufferSizeIn; @@ -193,5 +199,11 @@ AudioQueueBufferRefLookupEntry; -(void) flushStop; -(void) dispose; -(NSObject*) currentlyPlayingQueueItemId; +//! Call to refresh meter values +- (void) updateMeters; +//! Returns peak power in decibels for a given channel +- (float) peakPowerForChannel:(NSUInteger)channelNumber; +//! Returns average power in decibels for a given channel +- (float) averagePowerForChannel:(NSUInteger)channelNumber; @end diff --git a/Audjustable/Classes/AudioPlayer/AudioPlayer.m b/Audjustable/Classes/AudioPlayer/AudioPlayer.m index cfb035e..170b881 100644 --- a/Audjustable/Classes/AudioPlayer/AudioPlayer.m +++ b/Audjustable/Classes/AudioPlayer/AudioPlayer.m @@ -451,6 +451,7 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ free(packetDescs); free(audioQueueBuffer); free(audioQueueBufferLookup); + free(levelMeterState); } -(void) startSystemBackgroundTask @@ -1215,6 +1216,9 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 1); + // Re set metering enabled in case the user set it before the queue was created + [self setMeteringEnabled:meteringEnabled]; + free(cookieData); } @@ -2169,4 +2173,55 @@ static void AudioQueueIsRunningCallbackProc(void* userData, AudioQueueRef audioQ return retval; } +#pragma mark Metering + +-(void) setMeteringEnabled:(BOOL)enabled +{ + // If the audioQueue isn't already created, set the property for later + if (!audioQueue) { + meteringEnabled = enabled; + return; + } + UInt32 on = enabled ? 1 : 0; + OSStatus error = AudioQueueSetProperty(audioQueue, kAudioQueueProperty_EnableLevelMetering, &on, sizeof(on)); + if (error) { + meteringEnabled = NO; + } else { + meteringEnabled = YES; + } +} + +-(BOOL) isMeteringEnabled +{ + return meteringEnabled; +} + +-(void) updateMeters +{ + if (!meteringEnabled) NSAssert(NO, @"Metering is not enabled. Make sure to set meteringEnabled = YES."); + + NSInteger channels = currentAudioStreamBasicDescription.mChannelsPerFrame; + if (numberOfChannels != channels) { + numberOfChannels = channels; + if (levelMeterState) free(levelMeterState); + levelMeterState = malloc(sizeof(AudioQueueLevelMeterState) * numberOfChannels); + } + + UInt32 sizeofMeters = sizeof(AudioQueueLevelMeterState) * numberOfChannels; + + AudioQueueGetProperty(audioQueue, kAudioQueueProperty_CurrentLevelMeterDB, levelMeterState, &sizeofMeters); +} + +-(float) peakPowerForChannel:(NSUInteger)channelNumber +{ + if (!meteringEnabled || !levelMeterState || (channelNumber > numberOfChannels)) return 0; + return levelMeterState[channelNumber].mPeakPower; +} + +-(float) averagePowerForChannel:(NSUInteger)channelNumber +{ + if (!meteringEnabled || !levelMeterState || (channelNumber > numberOfChannels)) return 0; + return levelMeterState[channelNumber].mAveragePower; +} + @end