Changed canonical format to fixed point for all platforms. Added metering view on ExampleAppMac
This commit is contained in:
parent
4df5a84569
commit
1c78dc5867
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 */,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue