Changed canonical format to fixed point for all platforms. Added metering view on ExampleAppMac

This commit is contained in:
Thong Nguyen 2014-02-02 14:19:12 +00:00
parent 4df5a84569
commit 1c78dc5867
6 changed files with 161 additions and 21 deletions

View File

@ -181,7 +181,7 @@
statusLabel.text = audioPlayer.state == STKAudioPlayerStateBuffering ? @"buffering" : @""; statusLabel.text = audioPlayer.state == STKAudioPlayerStateBuffering ? @"buffering" : @"";
CGFloat newWidth = 320 * (([audioPlayer peakPowerInDecibelsForChannel:1] + 60) / 60); CGFloat newWidth = 320 * (([audioPlayer averagePowerInDecibelsForChannel:1] + 60) / 60);
meter.frame = CGRectMake(0, 460, newWidth, 20); meter.frame = CGRectMake(0, 460, newWidth, 20);
} }

View File

@ -27,6 +27,7 @@
A1A499FA189E7A5600E2A2E2 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499F1189E799400E2A2E2 /* AudioToolbox.framework */; }; A1A499FA189E7A5600E2A2E2 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499F1189E799400E2A2E2 /* AudioToolbox.framework */; };
A1A499FC189E7A6D00E2A2E2 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499FB189E7A6D00E2A2E2 /* SystemConfiguration.framework */; }; A1A499FC189E7A6D00E2A2E2 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499FB189E7A6D00E2A2E2 /* SystemConfiguration.framework */; };
A1A499FD189E7BFC00E2A2E2 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499ED189E793700E2A2E2 /* AudioUnit.framework */; }; A1A499FD189E7BFC00E2A2E2 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A499ED189E793700E2A2E2 /* AudioUnit.framework */; };
A1A49A01189E82EC00E2A2E2 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A49A00189E82EC00E2A2E2 /* QuartzCore.framework */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@ -66,6 +67,8 @@
A1A499F4189E79CB00E2A2E2 /* CoreAudioKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudioKit.framework; path = System/Library/Frameworks/CoreAudioKit.framework; sourceTree = SDKROOT; }; A1A499F4189E79CB00E2A2E2 /* CoreAudioKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudioKit.framework; path = System/Library/Frameworks/CoreAudioKit.framework; sourceTree = SDKROOT; };
A1A499F8189E7A3500E2A2E2 /* libStreamingKitMac.a */ = {isa = PBXFileReference; lastKnownFileType = file; name = libStreamingKitMac.a; path = ../StreamingKit/build/Debug/libStreamingKitMac.a; sourceTree = "<group>"; }; A1A499F8189E7A3500E2A2E2 /* libStreamingKitMac.a */ = {isa = PBXFileReference; lastKnownFileType = file; name = libStreamingKitMac.a; path = ../StreamingKit/build/Debug/libStreamingKitMac.a; sourceTree = "<group>"; };
A1A499FB189E7A6D00E2A2E2 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; A1A499FB189E7A6D00E2A2E2 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
A1A499FE189E82DD00E2A2E2 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
A1A49A00189E82EC00E2A2E2 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -73,6 +76,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
A1A49A01189E82EC00E2A2E2 /* QuartzCore.framework in Frameworks */,
A1A499FD189E7BFC00E2A2E2 /* AudioUnit.framework in Frameworks */, A1A499FD189E7BFC00E2A2E2 /* AudioUnit.framework in Frameworks */,
A1A499FC189E7A6D00E2A2E2 /* SystemConfiguration.framework in Frameworks */, A1A499FC189E7A6D00E2A2E2 /* SystemConfiguration.framework in Frameworks */,
A1A499FA189E7A5600E2A2E2 /* AudioToolbox.framework in Frameworks */, A1A499FA189E7A5600E2A2E2 /* AudioToolbox.framework in Frameworks */,
@ -120,6 +124,8 @@
A1A499A3189E765800E2A2E2 /* Frameworks */ = { A1A499A3189E765800E2A2E2 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A1A49A00189E82EC00E2A2E2 /* QuartzCore.framework */,
A1A499FE189E82DD00E2A2E2 /* CoreGraphics.framework */,
A1A499FB189E7A6D00E2A2E2 /* SystemConfiguration.framework */, A1A499FB189E7A6D00E2A2E2 /* SystemConfiguration.framework */,
A1A499F8189E7A3500E2A2E2 /* libStreamingKitMac.a */, A1A499F8189E7A3500E2A2E2 /* libStreamingKitMac.a */,
A1A499F4189E79CB00E2A2E2 /* CoreAudioKit.framework */, A1A499F4189E79CB00E2A2E2 /* CoreAudioKit.framework */,

View File

@ -7,8 +7,9 @@
// //
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "STKAudioPlayer.h"
@interface AppDelegate : NSObject <NSApplicationDelegate> @interface AppDelegate : NSObject <NSApplicationDelegate, STKAudioPlayerDelegate>
@property (assign) IBOutlet NSWindow *window; @property (assign) IBOutlet NSWindow *window;

View File

@ -9,13 +9,112 @@
#import "AppDelegate.h" #import "AppDelegate.h"
#import "STKAudioPlayer.h" #import "STKAudioPlayer.h"
@interface AppDelegate()
{
NSView* meter;
NSSlider* slider;
STKAudioPlayer* audioPlayer;
}
@end
@implementation AppDelegate @implementation AppDelegate
-(void) applicationDidFinishLaunching:(NSNotification *)aNotification -(void) applicationDidFinishLaunching:(NSNotification *)aNotification
{ {
STKAudioPlayer* player = [[STKAudioPlayer alloc] init]; CGRect frame = [self.window.contentView frame];
[player play:@"http://fs.bloom.fm/oss/audiosamples/sample.mp3"]; NSButton* playFromHTTPButton = [[NSButton alloc] initWithFrame:CGRectMake(10, 10, frame.size.width - 20, 100)];
[playFromHTTPButton setTitle:@"Play from HTTP"];
[playFromHTTPButton setAction:@selector(playFromHTTP)];
slider = [[NSSlider alloc] initWithFrame:CGRectMake(10, 140, frame.size.width - 20, 20)];
[slider setAction:@selector(sliderChanged:)];
meter = [[NSView alloc] initWithFrame:CGRectMake(10, 200, 0, 20)];
[meter setLayer:[CALayer new]];
[meter setWantsLayer:YES];
meter.layer.backgroundColor = [NSColor greenColor].CGColor;
[[self.window contentView] addSubview:slider];
[[self.window contentView] addSubview:playFromHTTPButton];
[[self.window contentView] addSubview:meter];
audioPlayer = [[STKAudioPlayer alloc] init];
audioPlayer.delegate = self;
audioPlayer.meteringEnabled = YES;
[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(tick:) userInfo:nil repeats:YES];
}
-(void) playFromHTTP
{
[audioPlayer play:@"http://fs.bloom.fm/oss/audiosamples/sample.mp3"];
}
-(void) tick:(NSTimer*)timer
{
if (!audioPlayer)
{
slider.doubleValue = 0;
return;
}
CGFloat meterWidth = 0;
if (audioPlayer.duration != 0)
{
slider.minValue = 0;
slider.maxValue = audioPlayer.duration;
slider.doubleValue = audioPlayer.progress;
meterWidth = [self.window.contentView frame].size.width - 20;
meterWidth *= (([audioPlayer averagePowerInDecibelsForChannel:0] + 60) / 60);
}
else
{
slider.doubleValue = 0;
slider.minValue = 0;
slider.maxValue = 0;
meterWidth = 0;
}
CGRect frame = meter.frame;
frame.size.width = meterWidth;
meter.frame = frame;
}
-(void) sliderChanged:(NSSlider*)sliderIn
{
[audioPlayer seekToTime:sliderIn.doubleValue];
}
-(void) updateControls
{
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didStartPlayingQueueItemId:(NSObject*)queueItemId
{
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didFinishBufferingSourceWithQueueItemId:(NSObject*)queueItemId
{
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer stateChanged:(STKAudioPlayerState)state previousState:(STKAudioPlayerState)previousState
{
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didFinishPlayingQueueItemId:(NSObject*)queueItemId withReason:(STKAudioPlayerStopReason)stopReason andProgress:(double)progress andDuration:(double)duration
{
}
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer unexpectedError:(STKAudioPlayerErrorCode)errorCode
{
} }
@end @end

View File

@ -202,10 +202,12 @@ typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UIn
/// If the given name is nil, the filter will be inserted at the beginning of the filter change /// If the given name is nil, the filter will be inserted at the beginning of the filter change
-(void) addFrameFilterWithName:(NSString*)name afterFilterWithName:(NSString*)afterFilterWithName block:(STKFrameFilter)block; -(void) addFrameFilterWithName:(NSString*)name afterFilterWithName:(NSString*)afterFilterWithName block:(STKFrameFilter)block;
/// Reads the peak power in decibals for the given channel (0 or 1) /// Reads the peak power in decibals for the given channel (0 or 1).
/// Return values are between -60 (low) and 0 (high).
-(float) peakPowerInDecibelsForChannel:(NSUInteger)channelNumber; -(float) peakPowerInDecibelsForChannel:(NSUInteger)channelNumber;
/// Reads the average power in decibals for the given channel (0 or 1) /// Reads the average power in decibals for the given channel (0 or 1)
/// Return values are between -60 (low) and 0 (high).
-(float) averagePowerInDecibelsForChannel:(NSUInteger)channelNumber; -(float) averagePowerInDecibelsForChannel:(NSUInteger)channelNumber;
@end @end

View File

@ -292,14 +292,16 @@ static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UIn
if (self = [super init]) if (self = [super init])
{ {
options = optionsIn; options = optionsIn;
const int bytesPerSample = sizeof(AudioSampleType);
canonicalAudioStreamBasicDescription.mSampleRate = 44100.00; canonicalAudioStreamBasicDescription.mSampleRate = 44100.00;
canonicalAudioStreamBasicDescription.mFormatID = kAudioFormatLinearPCM; canonicalAudioStreamBasicDescription.mFormatID = kAudioFormatLinearPCM;
canonicalAudioStreamBasicDescription.mFormatFlags = kAudioFormatFlagsCanonical; canonicalAudioStreamBasicDescription.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
canonicalAudioStreamBasicDescription.mFramesPerPacket = 1; canonicalAudioStreamBasicDescription.mFramesPerPacket = 1;
canonicalAudioStreamBasicDescription.mChannelsPerFrame = 2; canonicalAudioStreamBasicDescription.mChannelsPerFrame = 2;
canonicalAudioStreamBasicDescription.mBytesPerFrame = sizeof(AudioSampleType) * canonicalAudioStreamBasicDescription.mChannelsPerFrame; canonicalAudioStreamBasicDescription.mBytesPerFrame = bytesPerSample * canonicalAudioStreamBasicDescription.mChannelsPerFrame;
canonicalAudioStreamBasicDescription.mBitsPerChannel = 8 * sizeof(AudioSampleType); canonicalAudioStreamBasicDescription.mBitsPerChannel = 8 * bytesPerSample;
canonicalAudioStreamBasicDescription.mBytesPerPacket = canonicalAudioStreamBasicDescription.mBytesPerFrame * canonicalAudioStreamBasicDescription.mFramesPerPacket; canonicalAudioStreamBasicDescription.mBytesPerPacket = canonicalAudioStreamBasicDescription.mBytesPerFrame * canonicalAudioStreamBasicDescription.mFramesPerPacket;
framesRequiredToStartPlaying = canonicalAudioStreamBasicDescription.mSampleRate * STK_DEFAULT_SECONDS_REQUIRED_TO_START_PLAYING; framesRequiredToStartPlaying = canonicalAudioStreamBasicDescription.mSampleRate * STK_DEFAULT_SECONDS_REQUIRED_TO_START_PLAYING;
@ -2393,10 +2395,11 @@ static OSStatus OutputRenderCallback(void* inRefCon, AudioUnitRenderActionFlags*
{ \ { \
if(sampleDB##channel > peakValue##channel) \ if(sampleDB##channel > peakValue##channel) \
{ \ { \
peakValue##channel = MIN(sampleDB##channel, 0); \ peakValue##channel = sampleDB##channel; \
} \ } \
if (sampleDB##channel > -DBL_MAX) \ if (sampleDB##channel > -DBL_MAX) \
{ \ { \
count##channel++; \
totalValue##channel += sampleDB##channel; \ totalValue##channel += sampleDB##channel; \
} \ } \
decibels##channel = peakValue##channel; \ decibels##channel = peakValue##channel; \
@ -2418,29 +2421,58 @@ static OSStatus OutputRenderCallback(void* inRefCon, AudioUnitRenderActionFlags*
{ {
[self appendFrameFilterWithName:@"STKMeteringFilter" block:^(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames) [self appendFrameFilterWithName:@"STKMeteringFilter" block:^(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames)
{ {
SInt16* samples = (SInt16*)frames; SInt16* samples16 = (SInt16*)frames;
SInt32* samples32 = (SInt32*)frames;
UInt32 countLeft = 0;
UInt32 countRight = 0;
Float32 decibelsLeft = STK_DBMIN; Float32 decibelsLeft = STK_DBMIN;
Float32 peakValueLeft = STK_DBMIN; Float32 peakValueLeft = STK_DBMIN;
Float64 totalValueLeft = STK_DBMIN; Float64 totalValueLeft = 0;
Float32 previousFilteredValueOfSampleAmplitudeLeft = 0; Float32 previousFilteredValueOfSampleAmplitudeLeft = 0;
Float32 decibelsRight = STK_DBMIN; Float32 decibelsRight = STK_DBMIN;
Float32 peakValueRight = STK_DBMIN; Float32 peakValueRight = STK_DBMIN;
Float64 totalValueRight = STK_DBMIN; Float64 totalValueRight = 0;
Float32 previousFilteredValueOfSampleAmplitudeRight = 0; Float32 previousFilteredValueOfSampleAmplitudeRight = 0;
for (int i = 0; i < frameCount * 2; i++) if (bytesPerFrame / channelsPerFrame == 2)
{ {
Float32 absoluteValueOfSampleAmplitudeLeft = abs(samples[i]); for (int i = 0; i < frameCount * channelsPerFrame; i += channelsPerFrame)
Float32 absoluteValueOfSampleAmplitudeRight = abs(samples[i]); {
Float32 absoluteValueOfSampleAmplitudeLeft = abs(samples16[i]);
CALCULATE_METER(Left); Float32 absoluteValueOfSampleAmplitudeRight = abs(samples16[i + 1]);
CALCULATE_METER(Right);
CALCULATE_METER(Left);
CALCULATE_METER(Right);
}
}
else if (bytesPerFrame / channelsPerFrame == 4)
{
for (int i = 0; i < frameCount * channelsPerFrame; i += channelsPerFrame)
{
Float32 absoluteValueOfSampleAmplitudeLeft = abs(samples32[i]) / 32768.0;
Float32 absoluteValueOfSampleAmplitudeRight = abs(samples32[i + 1]) / 32768.0;
CALCULATE_METER(Left);
CALCULATE_METER(Right);
}
}
else
{
return;
} }
peakPowerDb[0] = MIN(MAX(decibelsLeft, -60), 0); peakPowerDb[0] = MIN(MAX(decibelsLeft, -60), 0);
averagePowerDb[0] = MIN(MAX(totalValueLeft / frameCount, -60), 0);
peakPowerDb[1] = MIN(MAX(decibelsRight, -60), 0); peakPowerDb[1] = MIN(MAX(decibelsRight, -60), 0);
averagePowerDb[1] = MIN(MAX(totalValueRight / frameCount, -60), 0);
if (countLeft > 0)
{
averagePowerDb[0] = MIN(MAX(totalValueLeft / frameCount, -60), 0);
}
if (countRight != 0)
{
averagePowerDb[1] = MIN(MAX(totalValueRight / frameCount, -60), 0);
}
}]; }];
} }
} }