Compare commits

..

6 Commits

Author SHA1 Message Date
Pavel Lukandiy d02e624bc9 Revert "Playback speed"
This reverts commit 32d4330195.
2017-05-22 16:25:48 +03:00
Pavel Lukandiy bbf87829ec Revert "Refactor"
This reverts commit 4525951e5c.
2017-05-22 16:24:39 +03:00
Pavel 86a870d0d1 Merge pull request #2 from TouchInstinct/feature/seek
Feature/seek
2017-05-16 16:43:18 +03:00
Pavel Lukandiy 4525951e5c Refactor 2017-05-16 16:05:48 +03:00
Pavel Lukandiy 32d4330195 Playback speed 2017-05-16 16:05:37 +03:00
Anton a3d8b06975 STKAutoRecoveringHTTPDataSource http error handling fix 2016-09-22 16:10:04 +03:00
36 changed files with 138 additions and 664 deletions

View File

@ -230,7 +230,7 @@
A1115929188D686000641365 /* Project object */ = { A1115929188D686000641365 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 0710; LastUpgradeCheck = 0510;
ORGANIZATIONNAME = "Thong Nguyen"; ORGANIZATIONNAME = "Thong Nguyen";
TargetAttributes = { TargetAttributes = {
A111594B188D686000641365 = { A111594B188D686000641365 = {
@ -346,7 +346,6 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0; GCC_OPTIMIZATION_LEVEL = 0;
@ -423,7 +422,6 @@
IPHONEOS_DEPLOYMENT_TARGET = 6.0; IPHONEOS_DEPLOYMENT_TARGET = 6.0;
LLVM_LTO = YES; LLVM_LTO = YES;
OTHER_LDFLAGS = "-ObjC"; OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "abstractpath.com.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app; WRAPPER_EXTENSION = app;
}; };
@ -440,7 +438,6 @@
IPHONEOS_DEPLOYMENT_TARGET = 6.0; IPHONEOS_DEPLOYMENT_TARGET = 6.0;
LLVM_LTO = YES; LLVM_LTO = YES;
OTHER_LDFLAGS = "-ObjC"; OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "abstractpath.com.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app; WRAPPER_EXTENSION = app;
}; };
@ -462,7 +459,6 @@
"$(inherited)", "$(inherited)",
); );
INFOPLIST_FILE = "ExampleAppTests/ExampleAppTests-Info.plist"; INFOPLIST_FILE = "ExampleAppTests/ExampleAppTests-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "abstractpath.com.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)"; TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest; WRAPPER_EXTENSION = xctest;
@ -481,7 +477,6 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ExampleApp/ExampleApp-Prefix.pch"; GCC_PREFIX_HEADER = "ExampleApp/ExampleApp-Prefix.pch";
INFOPLIST_FILE = "ExampleAppTests/ExampleAppTests-Info.plist"; INFOPLIST_FILE = "ExampleAppTests/ExampleAppTests-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "abstractpath.com.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)"; TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest; WRAPPER_EXTENSION = xctest;

View File

@ -32,7 +32,6 @@
AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(bufferLength), &bufferLength); AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(bufferLength), &bufferLength);
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = [[UIViewController alloc] init];
self.window.backgroundColor = [UIColor whiteColor]; self.window.backgroundColor = [UIColor whiteColor];
@ -40,6 +39,7 @@
audioPlayer.meteringEnabled = YES; audioPlayer.meteringEnabled = YES;
audioPlayer.volume = 1; audioPlayer.volume = 1;
AudioPlayerView* audioPlayerView = [[AudioPlayerView alloc] initWithFrame:self.window.bounds andAudioPlayer:audioPlayer]; AudioPlayerView* audioPlayerView = [[AudioPlayerView alloc] initWithFrame:self.window.bounds andAudioPlayer:audioPlayer];
audioPlayerView.delegate = self; audioPlayerView.delegate = self;
@ -47,9 +47,9 @@
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder]; [self becomeFirstResponder];
[self.window addSubview:audioPlayerView];
[self.window makeKeyAndVisible]; [self.window makeKeyAndVisible];
[self.window.rootViewController.view addSubview:audioPlayerView];
return YES; return YES;
} }

View File

@ -58,27 +58,27 @@
CGSize size = CGSizeMake(220, 50); CGSize size = CGSizeMake(220, 50);
playFromHTTPButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; playFromHTTPButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
playFromHTTPButton.frame = CGRectMake((frame.size.width - size.width) / 2, frame.size.height * 0.10, size.width, size.height); playFromHTTPButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10, size.width, size.height);
[playFromHTTPButton addTarget:self action:@selector(playFromHTTPButtonTouched) forControlEvents:UIControlEventTouchUpInside]; [playFromHTTPButton addTarget:self action:@selector(playFromHTTPButtonTouched) forControlEvents:UIControlEventTouchUpInside];
[playFromHTTPButton setTitle:@"Play from HTTP" forState:UIControlStateNormal]; [playFromHTTPButton setTitle:@"Play from HTTP" forState:UIControlStateNormal];
playFromIcecastButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; playFromIcecastButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
playFromIcecastButton.frame = CGRectMake((frame.size.width - size.width) / 2, frame.size.height * 0.10 + 35, size.width, size.height); playFromIcecastButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10 + 35, size.width, size.height);
[playFromIcecastButton addTarget:self action:@selector(playFromIcecasButtonTouched) forControlEvents:UIControlEventTouchUpInside]; [playFromIcecastButton addTarget:self action:@selector(playFromIcecasButtonTouched) forControlEvents:UIControlEventTouchUpInside];
[playFromIcecastButton setTitle:@"Play from Icecast" forState:UIControlStateNormal]; [playFromIcecastButton setTitle:@"Play from Icecast" forState:UIControlStateNormal];
playFromLocalFileButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; playFromLocalFileButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
playFromLocalFileButton.frame = CGRectMake((frame.size.width - size.width) / 2, frame.size.height * 0.10 + 70, size.width, size.height); playFromLocalFileButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10 + 70, size.width, size.height);
[playFromLocalFileButton addTarget:self action:@selector(playFromLocalFileButtonTouched) forControlEvents:UIControlEventTouchUpInside]; [playFromLocalFileButton addTarget:self action:@selector(playFromLocalFileButtonTouched) forControlEvents:UIControlEventTouchUpInside];
[playFromLocalFileButton setTitle:@"Play from Local File" forState:UIControlStateNormal]; [playFromLocalFileButton setTitle:@"Play from Local File" forState:UIControlStateNormal];
queueShortFileButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; queueShortFileButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
queueShortFileButton.frame = CGRectMake((frame.size.width - size.width) / 2, frame.size.height * 0.10 + 105, size.width, size.height); queueShortFileButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10 + 105, size.width, size.height);
[queueShortFileButton addTarget:self action:@selector(queueShortFileButtonTouched) forControlEvents:UIControlEventTouchUpInside]; [queueShortFileButton addTarget:self action:@selector(queueShortFileButtonTouched) forControlEvents:UIControlEventTouchUpInside];
[queueShortFileButton setTitle:@"Queue short file" forState:UIControlStateNormal]; [queueShortFileButton setTitle:@"Queue short file" forState:UIControlStateNormal];
queuePcmWaveFileFromHTTPButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; queuePcmWaveFileFromHTTPButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
queuePcmWaveFileFromHTTPButton.frame = CGRectMake((frame.size.width - size.width) / 2, frame.size.height * 0.10 + 140, size.width, size.height); queuePcmWaveFileFromHTTPButton.frame = CGRectMake((320 - size.width) / 2, frame.size.height * 0.10 + 140, size.width, size.height);
[queuePcmWaveFileFromHTTPButton addTarget:self action:@selector(queuePcmWaveFileButtonTouched) forControlEvents:UIControlEventTouchUpInside]; [queuePcmWaveFileFromHTTPButton addTarget:self action:@selector(queuePcmWaveFileButtonTouched) forControlEvents:UIControlEventTouchUpInside];
[queuePcmWaveFileFromHTTPButton setTitle:@"Queue PCM/WAVE from HTTP" forState:UIControlStateNormal]; [queuePcmWaveFileFromHTTPButton setTitle:@"Queue PCM/WAVE from HTTP" forState:UIControlStateNormal];
@ -89,12 +89,12 @@
[playButton addTarget:self action:@selector(playButtonPressed) forControlEvents:UIControlEventTouchUpInside]; [playButton addTarget:self action:@selector(playButtonPressed) forControlEvents:UIControlEventTouchUpInside];
stopButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; stopButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
stopButton.frame = CGRectMake((frame.size.width - size.width) - 30, 400, size.width, size.height); stopButton.frame = CGRectMake((320 - size.width) - 30, 400, size.width, size.height);
[stopButton addTarget:self action:@selector(stopButtonPressed) forControlEvents:UIControlEventTouchUpInside]; [stopButton addTarget:self action:@selector(stopButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[stopButton setTitle:@"Stop" forState:UIControlStateNormal]; [stopButton setTitle:@"Stop" forState:UIControlStateNormal];
muteButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; muteButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
muteButton.frame = CGRectMake((frame.size.width - size.width) - 30, 430, size.width, size.height); muteButton.frame = CGRectMake((320 - size.width) - 30, 430, size.width, size.height);
[muteButton addTarget:self action:@selector(muteButtonPressed) forControlEvents:UIControlEventTouchUpInside]; [muteButton addTarget:self action:@selector(muteButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[muteButton setTitle:@"Mute" forState:UIControlStateNormal]; [muteButton setTitle:@"Mute" forState:UIControlStateNormal];
@ -106,7 +106,7 @@
repeatSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(30, frame.size.height * 0.15 + 180, size.width, size.height)]; repeatSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(30, frame.size.height * 0.15 + 180, size.width, size.height)];
enableEqSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(frame.size.width - size.width - 30, frame.size.height * 0.15 + 180, size.width, size.height)]; enableEqSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(320 - size.width - 30, frame.size.height * 0.15 + 180, size.width, size.height)];
enableEqSwitch.on = audioPlayer.equalizerEnabled; enableEqSwitch.on = audioPlayer.equalizerEnabled;
[enableEqSwitch addTarget:self action:@selector(onEnableEqSwitch) forControlEvents:UIControlEventAllTouchEvents]; [enableEqSwitch addTarget:self action:@selector(onEnableEqSwitch) forControlEvents:UIControlEventAllTouchEvents];

View File

@ -9,7 +9,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string> <string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>abstractpath.com.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>

View File

@ -5,31 +5,16 @@
"size" : "29x29", "size" : "29x29",
"scale" : "2x" "scale" : "2x"
}, },
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{ {
"idiom" : "iphone", "idiom" : "iphone",
"size" : "40x40", "size" : "40x40",
"scale" : "2x" "scale" : "2x"
}, },
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{ {
"idiom" : "iphone", "idiom" : "iphone",
"size" : "60x60", "size" : "60x60",
"scale" : "2x" "scale" : "2x"
}, },
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{ {
"idiom" : "ipad", "idiom" : "ipad",
"size" : "29x29", "size" : "29x29",

View File

@ -1,6 +0,0 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -1,31 +1,5 @@
{ {
"images" : [ "images" : [
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "736h",
"filename" : "TX6sV.png",
"minimum-system-version" : "8.0",
"orientation" : "portrait",
"scale" : "3x"
},
{
"orientation" : "landscape",
"idiom" : "iphone",
"extent" : "full-screen",
"minimum-system-version" : "8.0",
"subtype" : "736h",
"scale" : "3x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "667h",
"filename" : "dBEHd.png",
"minimum-system-version" : "8.0",
"orientation" : "portrait",
"scale" : "2x"
},
{ {
"orientation" : "portrait", "orientation" : "portrait",
"idiom" : "iphone", "idiom" : "iphone",
@ -34,12 +8,11 @@
"scale" : "2x" "scale" : "2x"
}, },
{ {
"extent" : "full-screen", "orientation" : "portrait",
"idiom" : "iphone", "idiom" : "iphone",
"subtype" : "retina4", "subtype" : "retina4",
"filename" : "TX6sV-2.png", "extent" : "full-screen",
"minimum-system-version" : "7.0", "minimum-system-version" : "7.0",
"orientation" : "portrait",
"scale" : "2x" "scale" : "2x"
}, },
{ {
@ -69,26 +42,6 @@
"extent" : "full-screen", "extent" : "full-screen",
"minimum-system-version" : "7.0", "minimum-system-version" : "7.0",
"scale" : "2x" "scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"extent" : "full-screen",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"extent" : "full-screen",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"filename" : "TX6sV-1.png",
"extent" : "full-screen",
"subtype" : "retina4",
"scale" : "2x"
} }
], ],
"info" : { "info" : {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string> <string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>abstractpath.com.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>

View File

@ -4,7 +4,7 @@
Inspired by Matt Gallagher's AudioStreamer: Inspired by Matt Gallagher's AudioStreamer:
https://github.com/mattgallagher/AudioStreamer https://github.com/mattgallagher/AudioStreamer
Copyright (c) 2015 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
@ -15,12 +15,12 @@
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software 3. All advertising materials mentioning features or use of this software
must display the following acknowledgement: must display the following acknowledgement:
This product includes software developed by Thong Nguyen. This product includes software developed by the <organization>.
4. Neither the name of the <organization> nor the 4. Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THONG NGUYEN ''AS IS'' AND ANY THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY

View File

@ -11,7 +11,7 @@ The primary motivation of this project was to decouple the input data sources fr
* Easy to read source. * Easy to read source.
* Carefully multi-threaded to provide a responsive API that won't block your UI thread nor starve the audio buffers. * Carefully multi-threaded to provide a responsive API that won't block your UI thread nor starve the audio buffers.
* Buffered and gapless playback between all format types. * Buffered and gapless playback between all format types.
* Easy to implement audio data sources (Local, HTTP, AutoRecoveringHTTP DataSources are provided). * Easy to implement audio data sources (Local, HTTP, AutoRecoveryingHTTP DataSources are provided).
* Easy to extend DataSource to support adaptive buffering, encryption, etc. * Easy to extend DataSource to support adaptive buffering, encryption, etc.
* Optimised for low CPU/battery usage (0% - 1% CPU usage when streaming). * Optimised for low CPU/battery usage (0% - 1% CPU usage when streaming).
* Optimised for linear data sources. Random access sources are required only for seeking. * Optimised for linear data sources. Random access sources are required only for seeking.

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = "StreamingKit" s.name = "StreamingKit"
s.version = "0.1.29" s.version = "0.1.25"
s.summary = "A fast and extensible audio streamer for iOS and OSX with support for gapless playback and custom (non-HTTP) sources." s.summary = "A fast and extensible audio streamer for iOS and OSX with support for gapless playback and custom (non-HTTP) sources."
s.homepage = "https://github.com/tumtumtum/StreamingKit/" s.homepage = "https://github.com/tumtumtum/StreamingKit/"
s.license = 'MIT' s.license = 'MIT'

View File

@ -15,8 +15,6 @@
5B949CD71A1140E4005675A0 /* STKHTTPDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A1E7C4FB188D5E550010896F /* STKHTTPDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5B949CD71A1140E4005675A0 /* STKHTTPDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A1E7C4FB188D5E550010896F /* STKHTTPDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
5B949CD81A1140E4005675A0 /* STKLocalFileDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A1E7C4FD188D5E550010896F /* STKLocalFileDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5B949CD81A1140E4005675A0 /* STKLocalFileDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A1E7C4FD188D5E550010896F /* STKLocalFileDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
5B949CD91A1140E4005675A0 /* STKQueueEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BF65D0189A6582004DD08C /* STKQueueEntry.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5B949CD91A1140E4005675A0 /* STKQueueEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BF65D0189A6582004DD08C /* STKQueueEntry.h */; settings = {ATTRIBUTES = (Public, ); }; };
95F80F4E1C68EE2300DB24B3 /* STKFloatConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 95F80F4C1C68EE2300DB24B3 /* STKFloatConverter.h */; };
95F80F4F1C68EE2300DB24B3 /* STKFloatConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 95F80F4D1C68EE2300DB24B3 /* STKFloatConverter.m */; };
A1A4996B189E744400E2A2E2 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A4996A189E744400E2A2E2 /* Cocoa.framework */; }; A1A4996B189E744400E2A2E2 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A4996A189E744400E2A2E2 /* Cocoa.framework */; };
A1A49975189E744500E2A2E2 /* StreamingKitMac.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A49974189E744500E2A2E2 /* StreamingKitMac.m */; }; A1A49975189E744500E2A2E2 /* StreamingKitMac.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A49974189E744500E2A2E2 /* StreamingKitMac.m */; };
A1A4997B189E744500E2A2E2 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1E7C4D9188D57F60010896F /* XCTest.framework */; }; A1A4997B189E744500E2A2E2 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1E7C4D9188D57F60010896F /* XCTest.framework */; };
@ -93,8 +91,6 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
95F80F4C1C68EE2300DB24B3 /* STKFloatConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKFloatConverter.h; sourceTree = "<group>"; };
95F80F4D1C68EE2300DB24B3 /* STKFloatConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKFloatConverter.m; sourceTree = "<group>"; };
A1A49969189E744400E2A2E2 /* libStreamingKitMac.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libStreamingKitMac.a; sourceTree = BUILT_PRODUCTS_DIR; }; A1A49969189E744400E2A2E2 /* libStreamingKitMac.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libStreamingKitMac.a; sourceTree = BUILT_PRODUCTS_DIR; };
A1A4996A189E744400E2A2E2 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; A1A4996A189E744400E2A2E2 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; };
A1A4996D189E744500E2A2E2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; A1A4996D189E744500E2A2E2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@ -274,8 +270,6 @@
A1E7C4CD188D57F50010896F /* StreamingKit */ = { A1E7C4CD188D57F50010896F /* StreamingKit */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
95F80F4C1C68EE2300DB24B3 /* STKFloatConverter.h */,
95F80F4D1C68EE2300DB24B3 /* STKFloatConverter.m */,
A1E7C4F1188D5E550010896F /* STKAudioPlayer.h */, A1E7C4F1188D5E550010896F /* STKAudioPlayer.h */,
A1E7C4F2188D5E550010896F /* STKAudioPlayer.m */, A1E7C4F2188D5E550010896F /* STKAudioPlayer.m */,
A1E7C4F3188D5E550010896F /* STKAutoRecoveringHTTPDataSource.h */, A1E7C4F3188D5E550010896F /* STKAutoRecoveringHTTPDataSource.h */,
@ -337,7 +331,6 @@
5B949CD41A1140E4005675A0 /* STKCoreFoundationDataSource.h in Headers */, 5B949CD41A1140E4005675A0 /* STKCoreFoundationDataSource.h in Headers */,
5B949CD51A1140E4005675A0 /* STKDataSource.h in Headers */, 5B949CD51A1140E4005675A0 /* STKDataSource.h in Headers */,
5B949CD61A1140E4005675A0 /* STKDataSourceWrapper.h in Headers */, 5B949CD61A1140E4005675A0 /* STKDataSourceWrapper.h in Headers */,
95F80F4E1C68EE2300DB24B3 /* STKFloatConverter.h in Headers */,
5B949CD71A1140E4005675A0 /* STKHTTPDataSource.h in Headers */, 5B949CD71A1140E4005675A0 /* STKHTTPDataSource.h in Headers */,
5B949CD81A1140E4005675A0 /* STKLocalFileDataSource.h in Headers */, 5B949CD81A1140E4005675A0 /* STKLocalFileDataSource.h in Headers */,
5B949CD91A1140E4005675A0 /* STKQueueEntry.h in Headers */, 5B949CD91A1140E4005675A0 /* STKQueueEntry.h in Headers */,
@ -432,7 +425,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
CLASSPREFIX = STK; CLASSPREFIX = STK;
LastUpgradeCheck = 0710; LastUpgradeCheck = 0610;
ORGANIZATIONNAME = "Thong Nguyen"; ORGANIZATIONNAME = "Thong Nguyen";
}; };
buildConfigurationList = A1E7C4C3188D57F50010896F /* Build configuration list for PBXProject "StreamingKit" */; buildConfigurationList = A1E7C4C3188D57F50010896F /* Build configuration list for PBXProject "StreamingKit" */;
@ -532,7 +525,6 @@
A1E7C505188D5E550010896F /* STKLocalFileDataSource.m in Sources */, A1E7C505188D5E550010896F /* STKLocalFileDataSource.m in Sources */,
A1BF65D2189A6582004DD08C /* STKQueueEntry.m in Sources */, A1BF65D2189A6582004DD08C /* STKQueueEntry.m in Sources */,
A1E7C504188D5E550010896F /* STKHTTPDataSource.m in Sources */, A1E7C504188D5E550010896F /* STKHTTPDataSource.m in Sources */,
95F80F4F1C68EE2300DB24B3 /* STKFloatConverter.m in Sources */,
A1E7C503188D5E550010896F /* STKDataSourceWrapper.m in Sources */, A1E7C503188D5E550010896F /* STKDataSourceWrapper.m in Sources */,
A1E7C502188D5E550010896F /* STKDataSource.m in Sources */, A1E7C502188D5E550010896F /* STKDataSource.m in Sources */,
A1BF65D5189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.m in Sources */, A1BF65D5189A65C6004DD08C /* NSMutableArray+STKAudioPlayer.m in Sources */,
@ -641,7 +633,6 @@
); );
INFOPLIST_FILE = "StreamingKitMacTests/StreamingKitMacTests-Info.plist"; INFOPLIST_FILE = "StreamingKitMacTests/StreamingKitMacTests-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.8; MACOSX_DEPLOYMENT_TARGET = 10.8;
PRODUCT_BUNDLE_IDENTIFIER = "com.abstractpath.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx; SDKROOT = macosx;
WRAPPER_EXTENSION = xctest; WRAPPER_EXTENSION = xctest;
@ -662,7 +653,6 @@
GCC_PREFIX_HEADER = "StreamingKitMac/StreamingKitMac-Prefix.pch"; GCC_PREFIX_HEADER = "StreamingKitMac/StreamingKitMac-Prefix.pch";
INFOPLIST_FILE = "StreamingKitMacTests/StreamingKitMacTests-Info.plist"; INFOPLIST_FILE = "StreamingKitMacTests/StreamingKitMacTests-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.8; MACOSX_DEPLOYMENT_TARGET = 10.8;
PRODUCT_BUNDLE_IDENTIFIER = "com.abstractpath.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx; SDKROOT = macosx;
WRAPPER_EXTENSION = xctest; WRAPPER_EXTENSION = xctest;
@ -686,7 +676,6 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0; GCC_OPTIMIZATION_LEVEL = 0;
@ -787,7 +776,6 @@
"$(inherited)", "$(inherited)",
); );
INFOPLIST_FILE = "StreamingKitTests/StreamingKitTests-Info.plist"; INFOPLIST_FILE = "StreamingKitTests/StreamingKitTests-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "abstractpath.com.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = xctest; WRAPPER_EXTENSION = xctest;
}; };
@ -804,7 +792,6 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "StreamingKit/StreamingKit-Prefix.pch"; GCC_PREFIX_HEADER = "StreamingKit/StreamingKit-Prefix.pch";
INFOPLIST_FILE = "StreamingKitTests/StreamingKitTests-Info.plist"; INFOPLIST_FILE = "StreamingKitTests/StreamingKitTests-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "abstractpath.com.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = xctest; WRAPPER_EXTENSION = xctest;
}; };

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@ -8,14 +8,10 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSMutableArray (STKAudioPlayer) @interface NSMutableArray (STKAudioPlayer)
-(void) enqueue:(id)obj; -(void) enqueue:(id)obj;
-(void) skipQueue:(id)obj; -(void) skipQueue:(id)obj;
-(void) skipQueueWithQueue:(NSMutableArray*)queue; -(void) skipQueueWithQueue:(NSMutableArray*)queue;
-(nullable id) dequeue; -(id) dequeue;
-(nullable id) peek; -(id) peek;
@end @end
NS_ASSUME_NONNULL_END

View File

@ -44,9 +44,7 @@
#include "UIKit/UIApplication.h" #include "UIKit/UIApplication.h"
#endif #endif
NS_ASSUME_NONNULL_BEGIN typedef enum
typedef NS_OPTIONS(NSInteger, STKAudioPlayerState)
{ {
STKAudioPlayerStateReady, STKAudioPlayerStateReady,
STKAudioPlayerStateRunning = 1, STKAudioPlayerStateRunning = 1,
@ -56,9 +54,10 @@ typedef NS_OPTIONS(NSInteger, STKAudioPlayerState)
STKAudioPlayerStateStopped = (1 << 4), STKAudioPlayerStateStopped = (1 << 4),
STKAudioPlayerStateError = (1 << 5), STKAudioPlayerStateError = (1 << 5),
STKAudioPlayerStateDisposed = (1 << 6) STKAudioPlayerStateDisposed = (1 << 6)
}; }
STKAudioPlayerState;
typedef NS_ENUM(NSInteger, STKAudioPlayerStopReason) typedef enum
{ {
STKAudioPlayerStopReasonNone = 0, STKAudioPlayerStopReasonNone = 0,
STKAudioPlayerStopReasonEof, STKAudioPlayerStopReasonEof,
@ -66,9 +65,10 @@ typedef NS_ENUM(NSInteger, STKAudioPlayerStopReason)
STKAudioPlayerStopReasonPendingNext, STKAudioPlayerStopReasonPendingNext,
STKAudioPlayerStopReasonDisposed, STKAudioPlayerStopReasonDisposed,
STKAudioPlayerStopReasonError = 0xffff STKAudioPlayerStopReasonError = 0xffff
}; }
STKAudioPlayerStopReason;
typedef NS_ENUM(NSInteger, STKAudioPlayerErrorCode) typedef enum
{ {
STKAudioPlayerErrorNone = 0, STKAudioPlayerErrorNone = 0,
STKAudioPlayerErrorDataSource, STKAudioPlayerErrorDataSource,
@ -77,13 +77,9 @@ typedef NS_ENUM(NSInteger, STKAudioPlayerErrorCode)
STKAudioPlayerErrorCodecError, STKAudioPlayerErrorCodecError,
STKAudioPlayerErrorDataNotFound, STKAudioPlayerErrorDataNotFound,
STKAudioPlayerErrorOther = 0xffff STKAudioPlayerErrorOther = 0xffff
}; }
STKAudioPlayerErrorCode;
///
/// Options to initiailise the Audioplayer with.
/// By default if you set buffer size or seconds to 0, the non-zero default will be used
/// If you would like to disable the buffer option completely set to STK_DISABLE_BUFFER
///
typedef struct typedef struct
{ {
/// If YES then seeking a track will cause all pending items to be flushed from the queue /// If YES then seeking a track will cause all pending items to be flushed from the queue
@ -95,7 +91,7 @@ typedef struct
/// The size of the internal I/O read buffer. This data in this buffer is transient and does not need to be larger. /// The size of the internal I/O read buffer. This data in this buffer is transient and does not need to be larger.
UInt32 readBufferSize; UInt32 readBufferSize;
/// The size of the decompressed buffer (Default is 10 seconds which uses about 1.7MB of RAM) /// The size of the decompressed buffer (Default is 10 seconds which uses about 1.7MB of RAM)
float bufferSizeInSeconds; UInt32 bufferSizeInSeconds;
/// Number of seconds of decompressed audio is required before playback first starts for each item (Default is 0.5 seconds. Must be larger than bufferSizeInSeconds) /// Number of seconds of decompressed audio is required before playback first starts for each item (Default is 0.5 seconds. Must be larger than bufferSizeInSeconds)
Float32 secondsRequiredToStartPlaying; Float32 secondsRequiredToStartPlaying;
/// Seconds after a seek is performed before data needs to come in (after which the state will change to playing/buffering) /// Seconds after a seek is performed before data needs to come in (after which the state will change to playing/buffering)
@ -105,9 +101,7 @@ typedef struct
} }
STKAudioPlayerOptions; STKAudioPlayerOptions;
#define STK_DISABLE_BUFFER (0xffffffff) typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames);
typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, float* frames);
@interface STKFrameFilterEntry : NSObject @interface STKFrameFilterEntry : NSObject
@property (readonly) NSString* name; @property (readonly) NSString* name;
@ -135,8 +129,6 @@ typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UIn
/// Raised when items queued items are cleared (usually because of a call to play, setDataSource or stop) /// Raised when items queued items are cleared (usually because of a call to play, setDataSource or stop)
-(void) audioPlayer:(STKAudioPlayer*)audioPlayer didCancelQueuedItems:(NSArray*)queuedItems; -(void) audioPlayer:(STKAudioPlayer*)audioPlayer didCancelQueuedItems:(NSArray*)queuedItems;
-(void) plotGraphWithBuffer:(float*)buffer andLength:(UInt32)count;
@end @end
@interface STKAudioPlayer : NSObject<STKDataSourceDelegate> @interface STKAudioPlayer : NSObject<STKDataSourceDelegate>
@ -155,13 +147,13 @@ typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UIn
/// Enables or disables the EQ /// Enables or disables the EQ
@property (readwrite) BOOL equalizerEnabled; @property (readwrite) BOOL equalizerEnabled;
/// Returns an array of STKFrameFilterEntry objects representing the filters currently in use /// Returns an array of STKFrameFilterEntry objects representing the filters currently in use
@property (readonly, nullable) NSArray* frameFilters; @property (readonly) NSArray* frameFilters;
/// Returns the items pending to be played (includes buffering and upcoming items but does not include the current item) /// Returns the items pending to be played (includes buffering and upcoming items but does not include the current item)
@property (readonly) NSArray* pendingQueue; @property (readonly) NSArray* pendingQueue;
/// The number of items pending to be played (includes buffering and upcoming items but does not include the current item) /// The number of items pending to be played (includes buffering and upcoming items but does not include the current item)
@property (readonly) NSUInteger pendingQueueCount; @property (readonly) NSUInteger pendingQueueCount;
/// Gets the most recently queued item that is still pending to play /// Gets the most recently queued item that is still pending to play
@property (readonly, nullable) NSObject* mostRecentlyQueuedStillPendingItem; @property (readonly) NSObject* mostRecentlyQueuedStillPendingItem;
/// Gets the current state of the player /// Gets the current state of the player
@property (readwrite) STKAudioPlayerState state; @property (readwrite) STKAudioPlayerState state;
/// Gets the options provided to the player on startup /// Gets the options provided to the player on startup
@ -178,10 +170,10 @@ typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UIn
+(STKDataSource*) dataSourceFromURL:(NSURL*)url; +(STKDataSource*) dataSourceFromURL:(NSURL*)url;
/// Initializes a new STKAudioPlayer with the default options /// Initializes a new STKAudioPlayer with the default options
-(instancetype) init; -(id) init;
/// Initializes a new STKAudioPlayer with the given options /// Initializes a new STKAudioPlayer with the given options
-(instancetype) initWithOptions:(STKAudioPlayerOptions)optionsIn; -(id) initWithOptions:(STKAudioPlayerOptions)optionsIn;
/// Plays an item from the given URL string (all pending queued items are removed). /// Plays an item from the given URL string (all pending queued items are removed).
/// The NSString is used as the queue item ID /// The NSString is used as the queue item ID
@ -258,19 +250,17 @@ typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UIn
/// Appends a frame filter with the given name and filter block just after the filter with the given name. /// Appends a frame filter with the given name and filter block just after the filter with the given name.
/// 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:(nullable 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). /// 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). /// Return values are between -60 (low) and 0 (high).
//-(float) averagePowerInDecibelsForChannel:(NSUInteger)channelNumber; -(float) averagePowerInDecibelsForChannel:(NSUInteger)channelNumber;
/// Sets the gain value (from -96 low to +24 high) for an equalizer band (0 based index) /// Sets the gain value (from -96 low to +24 high) for an equalizer band (0 based index)
-(void) setGain:(float)gain forEqualizerBand:(int)bandIndex; -(void) setGain:(float)gain forEqualizerBand:(int)bandIndex;
@end @end
NS_ASSUME_NONNULL_END

View File

@ -41,7 +41,6 @@
#import "NSMutableArray+STKAudioPlayer.h" #import "NSMutableArray+STKAudioPlayer.h"
#import "libkern/OSAtomic.h" #import "libkern/OSAtomic.h"
#import <float.h> #import <float.h>
#import "STKFloatConverter.h"
#ifndef DBL_MAX #ifndef DBL_MAX
#define DBL_MAX 1.7976931348623157e+308 #define DBL_MAX 1.7976931348623157e+308
@ -52,20 +51,20 @@
#define kOutputBus 0 #define kOutputBus 0
#define kInputBus 1 #define kInputBus 1
//#define STK_DBMIN (-60) #define STK_DBMIN (-60)
//#define STK_DBOFFSET (-74.0) #define STK_DBOFFSET (-74.0)
#define STK_LOWPASSFILTERTIMESLICE (0.0005) #define STK_LOWPASSFILTERTIMESLICE (0.0005)
#define STK_DEFAULT_PCM_BUFFER_SIZE_IN_SECONDS (0.1) #define STK_DEFAULT_PCM_BUFFER_SIZE_IN_SECONDS (2 * 60)
#define STK_DEFAULT_SECONDS_REQUIRED_TO_START_PLAYING (1) #define STK_DEFAULT_SECONDS_REQUIRED_TO_START_PLAYING (1)
#define STK_DEFAULT_SECONDS_REQUIRED_TO_START_PLAYING_AFTER_BUFFER_UNDERRUN (7.5) #define STK_DEFAULT_SECONDS_REQUIRED_TO_START_PLAYING_AFTER_BUFFER_UNDERRUN (7.5)
#define STK_MAX_COMPRESSED_PACKETS_FOR_BITRATE_CALCULATION (4096) #define STK_MAX_COMPRESSED_PACKETS_FOR_BITRATE_CALCULATION (4096)
#define STK_DEFAULT_READ_BUFFER_SIZE (128 * 1024) #define STK_DEFAULT_READ_BUFFER_SIZE (64 * 1024)
#define STK_DEFAULT_PACKET_BUFFER_SIZE (2048) #define STK_DEFAULT_PACKET_BUFFER_SIZE (2048)
#define STK_DEFAULT_GRACE_PERIOD_AFTER_SEEK_SECONDS (0.5) #define STK_DEFAULT_GRACE_PERIOD_AFTER_SEEK_SECONDS (0.5)
#define OSSTATUS_PRINTF_PLACEHOLDER @"%c%c%c%c" #define OSSTATUS_PRINTF_PLACEHOLDER @"%c%c%c%c"
#define OSSTATUS_PRINTF_VALUE(status) (char)(((status) >> 24) & 0xFF), (char)(((status) >> 16) & 0xFF), (char)(((status) >> 8) & 0xFF), (char)((status) & 0xFF) #define OSSTATUS_PRINTF_VALUE(status) ((status) >> 24) & 0xFF, ((status) >> 16) & 0xFF, ((status) >> 8) & 0xFF, (status) & 0xFF
#define LOGINFO(x) [self logInfo:[NSString stringWithFormat:@"%s %@", sel_getName(_cmd), x]]; #define LOGINFO(x) [self logInfo:[NSString stringWithFormat:@"%s %@", sel_getName(_cmd), x]];
@ -97,34 +96,6 @@ static void PopulateOptionsWithDefault(STKAudioPlayerOptions* options)
} }
} }
static void NormalizeDisabledBuffers(STKAudioPlayerOptions* options)
{
if (options->bufferSizeInSeconds == STK_DISABLE_BUFFER)
{
options->bufferSizeInSeconds = 0;
}
if (options->readBufferSize == STK_DISABLE_BUFFER)
{
options->readBufferSize = 0;
}
if (options->secondsRequiredToStartPlaying == STK_DISABLE_BUFFER)
{
options->secondsRequiredToStartPlaying = 0;
}
if (options->secondsRequiredToStartPlayingAfterBufferUnderun == STK_DISABLE_BUFFER)
{
options->secondsRequiredToStartPlayingAfterBufferUnderun = 0;
}
if (options->gracePeriodAfterSeekInSeconds == STK_DISABLE_BUFFER)
{
options->gracePeriodAfterSeekInSeconds = 0;
}
}
#define CHECK_STATUS_AND_REPORT(call) \ #define CHECK_STATUS_AND_REPORT(call) \
if ((status = (call))) \ if ((status = (call))) \
{ \ { \
@ -174,7 +145,7 @@ STKAudioPlayerInternalState;
@end @end
@implementation STKFrameFilterEntry @implementation STKFrameFilterEntry
-(instancetype) initWithFilter:(STKFrameFilter)filterIn andName:(NSString*)nameIn -(id) initWithFilter:(STKFrameFilter)filterIn andName:(NSString*)nameIn
{ {
if (self = [super init]) if (self = [super init])
{ {
@ -300,9 +271,6 @@ static AudioStreamBasicDescription recordAudioStreamBasicDescription;
volatile BOOL disposeWasRequested; volatile BOOL disposeWasRequested;
volatile BOOL seekToTimeWasRequested; volatile BOOL seekToTimeWasRequested;
volatile STKAudioPlayerStopReason stopReason; volatile STKAudioPlayerStopReason stopReason;
float **_floatBuffers;
STKFloatConverter *_floatConverter;
} }
@property (readwrite) STKAudioPlayerInternalState internalState; @property (readwrite) STKAudioPlayerInternalState internalState;
@ -508,12 +476,12 @@ static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UIn
} }
} }
-(instancetype) init -(id) init
{ {
return [self initWithOptions:(STKAudioPlayerOptions){}]; return [self initWithOptions:(STKAudioPlayerOptions){}];
} }
-(instancetype) initWithOptions:(STKAudioPlayerOptions)optionsIn -(id) initWithOptions:(STKAudioPlayerOptions)optionsIn
{ {
if (self = [super init]) if (self = [super init])
{ {
@ -523,7 +491,6 @@ static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UIn
self->equalizerEnabled = optionsIn.equalizerBandFrequencies[0] != 0; self->equalizerEnabled = optionsIn.equalizerBandFrequencies[0] != 0;
PopulateOptionsWithDefault(&options); PopulateOptionsWithDefault(&options);
NormalizeDisabledBuffers(&options);
framesRequiredToStartPlaying = canonicalAudioStreamBasicDescription.mSampleRate * options.secondsRequiredToStartPlaying; framesRequiredToStartPlaying = canonicalAudioStreamBasicDescription.mSampleRate * options.secondsRequiredToStartPlaying;
framesRequiredToPlayAfterRebuffering = canonicalAudioStreamBasicDescription.mSampleRate * options.secondsRequiredToStartPlayingAfterBufferUnderun; framesRequiredToPlayAfterRebuffering = canonicalAudioStreamBasicDescription.mSampleRate * options.secondsRequiredToStartPlayingAfterBufferUnderun;
@ -559,21 +526,7 @@ static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UIn
upcomingQueue = [[NSMutableArray alloc] init]; upcomingQueue = [[NSMutableArray alloc] init];
bufferingQueue = [[NSMutableArray alloc] init]; bufferingQueue = [[NSMutableArray alloc] init];
//initialie the float converter
// Allocate the float buffers
_floatConverter = [[STKFloatConverter alloc] initWithSourceFormat:canonicalAudioStreamBasicDescription];
size_t sizeToAllocate = sizeof(float*) * canonicalAudioStreamBasicDescription.mChannelsPerFrame;
sizeToAllocate = MAX(8, sizeToAllocate);
_floatBuffers = (float**)malloc( sizeToAllocate );
UInt32 outputBufferSize = 32 * 1024; // 32 KB
for ( int i=0; i< canonicalAudioStreamBasicDescription.mChannelsPerFrame; i++ ) {
_floatBuffers[i] = (float*)malloc(outputBufferSize);
}
[self resetPcmBuffers]; [self resetPcmBuffers];
[self createAudioGraph]; [self createAudioGraph];
[self createPlaybackThread]; [self createPlaybackThread];
@ -925,7 +878,7 @@ static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UIn
} }
case kAudioFileStreamProperty_ReadyToProducePackets: case kAudioFileStreamProperty_ReadyToProducePackets:
{ {
if (audioConverterAudioStreamBasicDescription.mFormatID != kAudioFormatLinearPCM) if (!audioConverterAudioStreamBasicDescription.mFormatID == kAudioFormatLinearPCM)
{ {
discontinuous = YES; discontinuous = YES;
} }
@ -1763,10 +1716,10 @@ static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UIn
self->pcmBufferFrameStartIndex = 0; self->pcmBufferFrameStartIndex = 0;
self->pcmBufferUsedFrameCount = 0; self->pcmBufferUsedFrameCount = 0;
// self->peakPowerDb[0] = STK_DBMIN; self->peakPowerDb[0] = STK_DBMIN;
// self->peakPowerDb[1] = STK_DBMIN; self->peakPowerDb[1] = STK_DBMIN;
// self->averagePowerDb[0] = STK_DBMIN; self->averagePowerDb[0] = STK_DBMIN;
// self->averagePowerDb[1] = STK_DBMIN; self->averagePowerDb[1] = STK_DBMIN;
OSSpinLockUnlock(&pcmBufferSpinLock); OSSpinLockUnlock(&pcmBufferSpinLock);
} }
@ -1995,8 +1948,10 @@ static BOOL GetHardwareCodecClassDesc(UInt32 formatId, AudioClassDescription* cl
[self destroyAudioConverter]; [self destroyAudioConverter];
BOOL isRecording = currentlyReadingEntry.dataSource.recordToFileUrl != nil; //This breaks mono files
//canonicalAudioStreamBasicDescription.mChannelsPerFrame = asbd->mChannelsPerFrame;
BOOL isRecording = currentlyReadingEntry.dataSource.recordToFileUrl != nil;
if (isRecording) if (isRecording)
{ {
recordAudioStreamBasicDescription = (AudioStreamBasicDescription) recordAudioStreamBasicDescription = (AudioStreamBasicDescription)
@ -2459,9 +2414,6 @@ static BOOL GetHardwareCodecClassDesc(UInt32 formatId, AudioClassDescription* cl
} }
else if (!isRunning) else if (!isRunning)
{ {
stopReason = stopReasonIn;
self.internalState = STKAudioPlayerInternalStateStopped;
return; return;
} }
@ -3255,66 +3207,60 @@ static OSStatus OutputRenderCallback(void* inRefCon, AudioUnitRenderActionFlags*
} }
else else
{ {
[self appendFrameFilterWithName:@"STKMeteringFilter" block:^(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, float* frames) [self appendFrameFilterWithName:@"STKMeteringFilter" block:^(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames)
{ {
STKFloatConverterToFloat(_floatConverter,&(pcmAudioBufferList),_floatBuffers,frameCount); SInt16* samples16 = (SInt16*)frames;
SInt32* samples32 = (SInt32*)frames;
if ([self.delegate respondsToSelector:@selector(plotGraphWithBuffer:andLength:)]) { UInt32 countLeft = 0;
[self.delegate plotGraphWithBuffer:*(_floatBuffers) andLength:frameCount]; UInt32 countRight = 0;
} Float32 decibelsLeft = STK_DBMIN;
Float32 peakValueLeft = STK_DBMIN;
// SInt16* samples16 = (SInt16*)frames; Float64 totalValueLeft = 0;
// SInt32* samples32 = (SInt32*)frames; Float32 previousFilteredValueOfSampleAmplitudeLeft = 0;
// UInt32 countLeft = 0; Float32 decibelsRight = STK_DBMIN;
// UInt32 countRight = 0; Float32 peakValueRight = STK_DBMIN;
// Float32 decibelsLeft = STK_DBMIN; Float64 totalValueRight = 0;
// Float32 peakValueLeft = STK_DBMIN; Float32 previousFilteredValueOfSampleAmplitudeRight = 0;
// Float64 totalValueLeft = 0;
// Float32 previousFilteredValueOfSampleAmplitudeLeft = 0; if (bytesPerFrame / channelsPerFrame == 2)
// Float32 decibelsRight = STK_DBMIN; {
// Float32 peakValueRight = STK_DBMIN; for (int i = 0; i < frameCount * channelsPerFrame; i += channelsPerFrame)
// Float64 totalValueRight = 0; {
// Float32 previousFilteredValueOfSampleAmplitudeRight = 0; Float32 absoluteValueOfSampleAmplitudeLeft = abs(samples16[i]);
// Float32 absoluteValueOfSampleAmplitudeRight = abs(samples16[i + 1]);
// if (bytesPerFrame / channelsPerFrame == 2)
// { CALCULATE_METER(Left);
// for (int i = 0; i < frameCount * channelsPerFrame; i += channelsPerFrame) CALCULATE_METER(Right);
// { }
// Float32 absoluteValueOfSampleAmplitudeLeft = abs(samples16[i]); }
// Float32 absoluteValueOfSampleAmplitudeRight = abs(samples16[i + 1]); else if (bytesPerFrame / channelsPerFrame == 4)
// {
// CALCULATE_METER(Left); for (int i = 0; i < frameCount * channelsPerFrame; i += channelsPerFrame)
// CALCULATE_METER(Right); {
// } Float32 absoluteValueOfSampleAmplitudeLeft = abs(samples32[i]) / 32768.0;
// } Float32 absoluteValueOfSampleAmplitudeRight = abs(samples32[i + 1]) / 32768.0;
// else if (bytesPerFrame / channelsPerFrame == 4)
// { CALCULATE_METER(Left);
// for (int i = 0; i < frameCount * channelsPerFrame; i += channelsPerFrame) CALCULATE_METER(Right);
// { }
// Float32 absoluteValueOfSampleAmplitudeLeft = abs(samples32[i]) / 32768.0; }
// Float32 absoluteValueOfSampleAmplitudeRight = abs(samples32[i + 1]) / 32768.0; else
// {
// CALCULATE_METER(Left); return;
// CALCULATE_METER(Right); }
// }
// } peakPowerDb[0] = MIN(MAX(decibelsLeft, -60), 0);
// else peakPowerDb[1] = MIN(MAX(decibelsRight, -60), 0);
// {
// return; if (countLeft > 0)
// } {
// averagePowerDb[0] = MIN(MAX(totalValueLeft / frameCount, -60), 0);
// peakPowerDb[0] = MIN(MAX(decibelsLeft, -60), 0); }
// peakPowerDb[1] = MIN(MAX(decibelsRight, -60), 0);
// if (countRight != 0)
// if (countLeft > 0) {
// { averagePowerDb[1] = MIN(MAX(totalValueRight / frameCount, -60), 0);
// averagePowerDb[0] = MIN(MAX(totalValueLeft / frameCount, -60), 0); }
// }
//
// if (countRight != 0)
// {
// averagePowerDb[1] = MIN(MAX(totalValueRight / frameCount, -60), 0);
// }
}]; }];
} }
} }

View File

@ -36,8 +36,6 @@
#import "STKHTTPDataSource.h" #import "STKHTTPDataSource.h"
#import "STKDataSourceWrapper.h" #import "STKDataSourceWrapper.h"
NS_ASSUME_NONNULL_BEGIN
typedef struct typedef struct
{ {
int watchdogPeriodSeconds; int watchdogPeriodSeconds;
@ -47,10 +45,8 @@ STKAutoRecoveringHTTPDataSourceOptions;
@interface STKAutoRecoveringHTTPDataSource : STKDataSourceWrapper @interface STKAutoRecoveringHTTPDataSource : STKDataSourceWrapper
-(instancetype) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource; -(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource;
@property (readonly) STKHTTPDataSource* innerDataSource; @property (readonly) STKHTTPDataSource* innerDataSource;
@end @end
NS_ASSUME_NONNULL_END

View File

@ -101,24 +101,22 @@ static void PopulateOptionsWithDefault(STKAutoRecoveringHTTPDataSourceOptions* o
@implementation STKAutoRecoveringHTTPDataSource @implementation STKAutoRecoveringHTTPDataSource
@dynamic innerDataSource;
-(STKHTTPDataSource*) innerHTTPDataSource -(STKHTTPDataSource*) innerHTTPDataSource
{ {
return (STKHTTPDataSource*)self.innerDataSource; return (STKHTTPDataSource*)self.innerDataSource;
} }
-(instancetype) initWithDataSource:(STKDataSource *)innerDataSource -(id) initWithDataSource:(STKDataSource *)innerDataSource
{ {
return [self initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource]; return [self initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource];
} }
-(instancetype) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn -(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn
{ {
return [self initWithHTTPDataSource:innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions){}]; return [self initWithHTTPDataSource:innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions){}];
} }
-(instancetype) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions)optionsIn -(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions)optionsIn
{ {
if (self = [super initWithDataSource:innerDataSourceIn]) if (self = [super initWithDataSource:innerDataSourceIn])
{ {

View File

@ -34,8 +34,6 @@
#import "STKDataSource.h" #import "STKDataSource.h"
NS_ASSUME_NONNULL_BEGIN
@class STKCoreFoundationDataSource; @class STKCoreFoundationDataSource;
@interface CoreFoundationDataSourceClientInfo : NSObject @interface CoreFoundationDataSourceClientInfo : NSObject
@ -64,5 +62,3 @@ NS_ASSUME_NONNULL_BEGIN
-(CFStreamStatus) status; -(CFStreamStatus) status;
@end @end
NS_ASSUME_NONNULL_END

View File

@ -35,8 +35,6 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#include <AudioToolbox/AudioToolbox.h> #include <AudioToolbox/AudioToolbox.h>
NS_ASSUME_NONNULL_BEGIN
@class STKDataSource; @class STKDataSource;
@protocol STKDataSourceDelegate<NSObject> @protocol STKDataSourceDelegate<NSObject>
@ -52,8 +50,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (readonly) SInt64 length; @property (readonly) SInt64 length;
@property (readonly) BOOL hasBytesAvailable; @property (readonly) BOOL hasBytesAvailable;
@property (nonatomic, readwrite, assign) double durationHint; @property (nonatomic, readwrite, assign) double durationHint;
@property (readwrite, unsafe_unretained, nullable) id<STKDataSourceDelegate> delegate; @property (readwrite, unsafe_unretained) id<STKDataSourceDelegate> delegate;
@property (nonatomic, strong, nullable) NSURL *recordToFileUrl; @property (nonatomic, strong) NSURL *recordToFileUrl;
-(BOOL) registerForEvents:(NSRunLoop*)runLoop; -(BOOL) registerForEvents:(NSRunLoop*)runLoop;
-(void) unregisterForEvents; -(void) unregisterForEvents;
@ -64,5 +62,3 @@ NS_ASSUME_NONNULL_BEGIN
-(AudioFileTypeID) audioFileTypeHint; -(AudioFileTypeID) audioFileTypeHint;
@end @end
NS_ASSUME_NONNULL_END

View File

@ -34,14 +34,10 @@
#import "STKDataSource.h" #import "STKDataSource.h"
NS_ASSUME_NONNULL_BEGIN
@interface STKDataSourceWrapper : STKDataSource<STKDataSourceDelegate> @interface STKDataSourceWrapper : STKDataSource<STKDataSourceDelegate>
-(instancetype) initWithDataSource:(STKDataSource*)innerDataSource; -(id) initWithDataSource:(STKDataSource*)innerDataSource;
@property (readonly) STKDataSource* innerDataSource; @property (readonly) STKDataSource* innerDataSource;
@end @end
NS_ASSUME_NONNULL_END

View File

@ -40,7 +40,7 @@
@implementation STKDataSourceWrapper @implementation STKDataSourceWrapper
-(instancetype) initWithDataSource:(STKDataSource*)innerDataSourceIn -(id) initWithDataSource:(STKDataSource*)innerDataSourceIn
{ {
if (self = [super init]) if (self = [super init])
{ {

View File

@ -1,124 +0,0 @@
//
// AEFloatConverter.h
// The Amazing Audio Engine
//
// Created by Michael Tyson on 25/10/2012.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
#ifdef __cplusplus
extern "C" {
#endif
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
/*!
* Universal converter to float format
*
* Use this class to easily convert arbitrary audio formats to floating point
* for use with utilities like the Accelerate framework.
*/
@interface STKFloatConverter : NSObject
/*!
* Initialize
*
* @param sourceFormat The audio format to use
*/
- (id)initWithSourceFormat:(AudioStreamBasicDescription)sourceFormat;
/*!
* Convert audio to floating-point
*
* This C function, safe to use in a Core Audio realtime thread context, will take
* an audio buffer list of audio in the format you provided at initialisation, and
* convert it into a noninterleaved float array.
*
* @param converter Pointer to the converter object.
* @param sourceBuffer An audio buffer list containing the source audio.
* @param targetBuffers An array of floating-point arrays to store the converted float audio into.
* Note that you must provide the correct number of arrays, to match the number of channels.
* @param frames The number of frames to convert.
* @return YES on success; NO on failure
*/
BOOL STKFloatConverterToFloat(STKFloatConverter* converter, AudioBufferList *sourceBuffer, float * const * targetBuffers, UInt32 frames);
/*!
* Convert audio to floating-point, in a buffer list
*
* This C function, safe to use in a Core Audio realtime thread context, will take
* an audio buffer list of audio in the format you provided at initialisation, and
* convert it into a noninterleaved float format.
*
* @param converter Pointer to the converter object.
* @param sourceBuffer An audio buffer list containing the source audio.
* @param targetBuffer An audio buffer list to store the converted floating-point audio.
* @param frames The number of frames to convert.
* @return YES on success; NO on failure
*/
BOOL STKFloatConverterToFloatBufferList(STKFloatConverter* converter, AudioBufferList *sourceBuffer, AudioBufferList *targetBuffer, UInt32 frames);
/*!
* Convert audio from floating-point
*
* This C function, safe to use in a Core Audio realtime thread context, will take
* an audio buffer list of audio in the format you provided at initialisation, and
* convert it into a float array.
*
* @param converter Pointer to the converter object.
* @param sourceBuffers An array of floating-point arrays containing the floating-point audio to convert.
* Note that you must provide the correct number of arrays, to match the number of channels.
* @param targetBuffer An audio buffer list to store the converted audio into.
* @param frames The number of frames to convert.
* @return YES on success; NO on failure
*/
BOOL STKFloatConverterFromFloat(STKFloatConverter* converter, float * const * sourceBuffers, AudioBufferList *targetBuffer, UInt32 frames);
/*!
* Convert audio from floating-point, in a buffer list
*
* This C function, safe to use in a Core Audio realtime thread context, will take
* an audio buffer list of audio in the format you provided at initialisation, and
* convert it into a float array.
*
* @param converter Pointer to the converter object.
* @param sourceBuffer An audio buffer list containing the source audio.
* @param targetBuffer An audio buffer list to store the converted audio into.
* @param frames The number of frames to convert.
* @return YES on success; NO on failure
*/
BOOL STKFloatConverterFromFloatBufferList(STKFloatConverter* converter, AudioBufferList *sourceBuffer, AudioBufferList *targetBuffer, UInt32 frames);
/*!
* The AudioStreamBasicDescription representing the converted floating-point format
*/
@property (nonatomic, readonly) AudioStreamBasicDescription floatingPointAudioDescription;
/*!
* The source audio format set at initialization
*/
@property (nonatomic, readonly) AudioStreamBasicDescription sourceFormat;
@end
#ifdef __cplusplus
}
#endif

View File

@ -1,211 +0,0 @@
//
// AEFloatConverter.m
// The Amazing Audio Engine
//
// Created by Michael Tyson on 25/10/2012.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
#import "STKFloatConverter.h"
#define checkResult(result,operation) (_checkResult((result),(operation),strrchr(__FILE__, '/')+1,__LINE__))
static inline BOOL _checkResult(OSStatus result, const char *operation, const char* file, int line) {
if ( result != noErr ) {
NSLog(@"%s:%d: %s result %d %08X %4.4s", file, line, operation, (int)result, (int)result, (char*)&result);
return NO;
}
return YES;
}
#define kNoMoreDataErr -2222
struct complexInputDataProc_t {
AudioBufferList *sourceBuffer;
};
@interface STKFloatConverter () {
AudioStreamBasicDescription _sourceAudioDescription;
AudioStreamBasicDescription _floatAudioDescription;
AudioConverterRef _toFloatConverter;
AudioConverterRef _fromFloatConverter;
AudioBufferList *_scratchFloatBufferList;
}
static OSStatus complexInputDataProc(AudioConverterRef inAudioConverter,
UInt32 *ioNumberDataPackets,
AudioBufferList *ioData,
AudioStreamPacketDescription **outDataPacketDescription,
void *inUserData);
@end
@implementation STKFloatConverter
@synthesize sourceFormat = _sourceAudioDescription;
-(id)initWithSourceFormat:(AudioStreamBasicDescription)sourceFormat {
if ( !(self = [super init]) ) return nil;
_floatAudioDescription.mFormatID = kAudioFormatLinearPCM;
_floatAudioDescription.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved;
_floatAudioDescription.mChannelsPerFrame = sourceFormat.mChannelsPerFrame;
_floatAudioDescription.mBytesPerPacket = sizeof(float);
_floatAudioDescription.mFramesPerPacket = 1;
_floatAudioDescription.mBytesPerFrame = sizeof(float);
_floatAudioDescription.mBitsPerChannel = 8 * sizeof(float);
_floatAudioDescription.mSampleRate = sourceFormat.mSampleRate;
_sourceAudioDescription = sourceFormat;
if ( memcmp(&sourceFormat, &_floatAudioDescription, sizeof(AudioStreamBasicDescription)) != 0 ) {
checkResult(AudioConverterNew(&sourceFormat, &_floatAudioDescription, &_toFloatConverter), "AudioConverterNew");
checkResult(AudioConverterNew(&_floatAudioDescription, &sourceFormat, &_fromFloatConverter), "AudioConverterNew");
_scratchFloatBufferList = (AudioBufferList*)malloc(sizeof(AudioBufferList) + (_floatAudioDescription.mChannelsPerFrame-1)*sizeof(AudioBuffer));
_scratchFloatBufferList->mNumberBuffers = _floatAudioDescription.mChannelsPerFrame;
for ( int i=0; i<_scratchFloatBufferList->mNumberBuffers; i++ ) {
_scratchFloatBufferList->mBuffers[i].mNumberChannels = 1;
}
}
return self;
}
-(void)dealloc {
if ( _toFloatConverter ) AudioConverterDispose(_toFloatConverter);
if ( _fromFloatConverter ) AudioConverterDispose(_fromFloatConverter);
if ( _scratchFloatBufferList ) free(_scratchFloatBufferList);
// [super dealloc];
}
BOOL STKFloatConverterToFloat(STKFloatConverter* THIS, AudioBufferList *sourceBuffer, float * const * targetBuffers, UInt32 frames) {
if ( frames == 0 ) return YES;
if ( THIS->_toFloatConverter ) {
UInt32 priorDataByteSize = sourceBuffer->mBuffers[0].mDataByteSize;
for ( int i=0; i<sourceBuffer->mNumberBuffers; i++ ) {
sourceBuffer->mBuffers[i].mDataByteSize = frames * THIS->_sourceAudioDescription.mBytesPerFrame;
}
for ( int i=0; i<THIS->_scratchFloatBufferList->mNumberBuffers; i++ ) {
THIS->_scratchFloatBufferList->mBuffers[i].mData = targetBuffers[i];
THIS->_scratchFloatBufferList->mBuffers[i].mDataByteSize = frames * sizeof(float);
}
OSStatus result = AudioConverterFillComplexBuffer(THIS->_toFloatConverter,
complexInputDataProc,
&(struct complexInputDataProc_t) { .sourceBuffer = sourceBuffer },
&frames,
THIS->_scratchFloatBufferList,
NULL);
for ( int i=0; i<sourceBuffer->mNumberBuffers; i++ ) {
sourceBuffer->mBuffers[i].mDataByteSize = priorDataByteSize;
}
if ( !checkResult(result, "AudioConverterConvertComplexBuffer") ) {
return NO;
}
} else {
for ( int i=0; i<sourceBuffer->mNumberBuffers; i++ ) {
memcpy(targetBuffers[i], sourceBuffer->mBuffers[i].mData, frames * sizeof(float));
}
}
return YES;
}
BOOL STKFloatConverterToFloatBufferList(STKFloatConverter* converter, AudioBufferList *sourceBuffer, AudioBufferList *targetBuffer, UInt32 frames) {
assert(targetBuffer->mNumberBuffers == converter->_floatAudioDescription.mChannelsPerFrame);
float *targetBuffers[targetBuffer->mNumberBuffers];
for ( int i=0; i<targetBuffer->mNumberBuffers; i++ ) {
targetBuffers[i] = (float*)targetBuffer->mBuffers[i].mData;
}
return STKFloatConverterToFloat(converter, sourceBuffer, targetBuffers, frames);
}
BOOL STKFloatConverterFromFloat(STKFloatConverter* THIS, float * const * sourceBuffers, AudioBufferList *targetBuffer, UInt32 frames) {
if ( frames == 0 ) return YES;
if ( THIS->_fromFloatConverter ) {
for ( int i=0; i<THIS->_scratchFloatBufferList->mNumberBuffers; i++ ) {
THIS->_scratchFloatBufferList->mBuffers[i].mData = sourceBuffers[i];
THIS->_scratchFloatBufferList->mBuffers[i].mDataByteSize = frames * sizeof(float);
}
UInt32 priorDataByteSize = targetBuffer->mBuffers[0].mDataByteSize;
for ( int i=0; i<targetBuffer->mNumberBuffers; i++ ) {
targetBuffer->mBuffers[i].mDataByteSize = frames * THIS->_sourceAudioDescription.mBytesPerFrame;
}
OSStatus result = AudioConverterFillComplexBuffer(THIS->_fromFloatConverter,
complexInputDataProc,
&(struct complexInputDataProc_t) { .sourceBuffer = THIS->_scratchFloatBufferList },
&frames,
targetBuffer,
NULL);
for ( int i=0; i<targetBuffer->mNumberBuffers; i++ ) {
targetBuffer->mBuffers[i].mDataByteSize = priorDataByteSize;
}
if ( !checkResult(result, "AudioConverterConvertComplexBuffer") ) {
return NO;
}
} else {
for ( int i=0; i<targetBuffer->mNumberBuffers; i++ ) {
memcpy(targetBuffer->mBuffers[i].mData, sourceBuffers[i], frames * sizeof(float));
}
}
return YES;
}
BOOL STKFloatConverterFromFloatBufferList(STKFloatConverter* converter, AudioBufferList *sourceBuffer, AudioBufferList *targetBuffer, UInt32 frames) {
assert(sourceBuffer->mNumberBuffers == converter->_floatAudioDescription.mChannelsPerFrame);
float *sourceBuffers[sourceBuffer->mNumberBuffers];
for ( int i=0; i<sourceBuffer->mNumberBuffers; i++ ) {
sourceBuffers[i] = (float*)sourceBuffer->mBuffers[i].mData;
}
return STKFloatConverterFromFloat(converter, sourceBuffers, targetBuffer, frames);
}
static OSStatus complexInputDataProc(AudioConverterRef inAudioConverter,
UInt32 *ioNumberDataPackets,
AudioBufferList *ioData,
AudioStreamPacketDescription **outDataPacketDescription,
void *inUserData) {
struct complexInputDataProc_t *arg = (struct complexInputDataProc_t*)inUserData;
if ( !arg->sourceBuffer ) {
return kNoMoreDataErr;
}
memcpy(ioData, arg->sourceBuffer, sizeof(AudioBufferList) + (arg->sourceBuffer->mNumberBuffers-1)*sizeof(AudioBuffer));
arg->sourceBuffer = NULL;
return noErr;
}
-(AudioStreamBasicDescription)floatingPointAudioDescription {
return _floatAudioDescription;
}
@end

View File

@ -34,12 +34,10 @@
#import "STKCoreFoundationDataSource.h" #import "STKCoreFoundationDataSource.h"
NS_ASSUME_NONNULL_BEGIN
@class STKHTTPDataSource; @class STKHTTPDataSource;
typedef void(^STKURLBlock)(NSURL* url); typedef void(^STKURLBlock)(NSURL* url);
typedef NSURL* _Nonnull (^STKURLProvider)(); typedef NSURL*(^STKURLProvider)();
typedef void(^STKAsyncURLProvider)(STKHTTPDataSource* dataSource, BOOL forSeek, STKURLBlock callback); typedef void(^STKAsyncURLProvider)(STKHTTPDataSource* dataSource, BOOL forSeek, STKURLBlock callback);
@interface STKHTTPDataSource : STKCoreFoundationDataSource @interface STKHTTPDataSource : STKCoreFoundationDataSource
@ -48,13 +46,11 @@ typedef void(^STKAsyncURLProvider)(STKHTTPDataSource* dataSource, BOOL forSeek,
@property (readonly) UInt32 httpStatusCode; @property (readonly) UInt32 httpStatusCode;
+(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)fileExtension; +(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)fileExtension;
-(instancetype) initWithURL:(NSURL*)url; -(id) initWithURL:(NSURL*)url;
-(instancetype) initWithURL:(NSURL*)url httpRequestHeaders:(NSDictionary*)httpRequestHeaders; -(id) initWithURL:(NSURL *)url httpRequestHeaders:(NSDictionary *)httpRequestHeaders;
-(instancetype) initWithURLProvider:(STKURLProvider)urlProvider; -(id) initWithURLProvider:(STKURLProvider)urlProvider;
-(instancetype) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProvider; -(id) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProvider;
-(nullable NSRunLoop*) eventsRunLoop; -(NSRunLoop*) eventsRunLoop;
-(void) reconnect; -(void) reconnect;
@end @end
NS_ASSUME_NONNULL_END

View File

@ -64,19 +64,19 @@
@implementation STKHTTPDataSource @implementation STKHTTPDataSource
-(instancetype) initWithURL:(NSURL*)urlIn -(id) initWithURL:(NSURL*)urlIn
{ {
return [self initWithURLProvider:^NSURL* { return urlIn; }]; return [self initWithURLProvider:^NSURL* { return urlIn; }];
} }
-(instancetype) initWithURL:(NSURL *)urlIn httpRequestHeaders:(NSDictionary *)httpRequestHeaders -(id) initWithURL:(NSURL *)urlIn httpRequestHeaders:(NSDictionary *)httpRequestHeaders
{ {
self = [self initWithURLProvider:^NSURL* { return urlIn; }]; self = [self initWithURLProvider:^NSURL* { return urlIn; }];
self->requestHeaders = httpRequestHeaders; self->requestHeaders = httpRequestHeaders;
return self; return self;
} }
-(instancetype) initWithURLProvider:(STKURLProvider)urlProviderIn -(id) initWithURLProvider:(STKURLProvider)urlProviderIn
{ {
urlProviderIn = [urlProviderIn copy]; urlProviderIn = [urlProviderIn copy];
@ -86,7 +86,7 @@
}]; }];
} }
-(instancetype) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProviderIn -(id) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProviderIn
{ {
if (self = [super init]) if (self = [super init])
{ {
@ -411,7 +411,7 @@
eventsRunLoop = savedEventsRunLoop; eventsRunLoop = savedEventsRunLoop;
[self seekToOffset:self->supportsSeek ? self.position : 0]; [self seekToOffset:self.position];
} }
-(void) seekToOffset:(SInt64)offset -(void) seekToOffset:(SInt64)offset

View File

@ -34,14 +34,10 @@
#import "STKCoreFoundationDataSource.h" #import "STKCoreFoundationDataSource.h"
NS_ASSUME_NONNULL_BEGIN
@interface STKLocalFileDataSource : STKCoreFoundationDataSource @interface STKLocalFileDataSource : STKCoreFoundationDataSource
+(AudioFileTypeID) audioFileTypeHintFromFileExtension:(NSString*)fileExtension; +(AudioFileTypeID) audioFileTypeHintFromFileExtension:(NSString*)fileExtension;
@property (readonly, copy) NSString* filePath; @property (readonly, copy) NSString* filePath;
-(instancetype) initWithFilePath:(NSString*)filePath; -(id) initWithFilePath:(NSString*)filePath;
@end @end
NS_ASSUME_NONNULL_END

View File

@ -47,7 +47,7 @@
@implementation STKLocalFileDataSource @implementation STKLocalFileDataSource
@synthesize filePath; @synthesize filePath;
-(instancetype) initWithFilePath:(NSString*)filePathIn -(id) initWithFilePath:(NSString*)filePathIn
{ {
if (self = [super init]) if (self = [super init])
{ {

View File

@ -10,8 +10,6 @@
#import "libkern/OSAtomic.h" #import "libkern/OSAtomic.h"
#import "AudioToolbox/AudioToolbox.h" #import "AudioToolbox/AudioToolbox.h"
NS_ASSUME_NONNULL_BEGIN
@interface STKQueueEntry : NSObject @interface STKQueueEntry : NSObject
{ {
@public @public
@ -37,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (readwrite, retain) NSObject* queueItemId; @property (readwrite, retain) NSObject* queueItemId;
@property (readwrite, retain) STKDataSource* dataSource; @property (readwrite, retain) STKDataSource* dataSource;
-(instancetype) initWithDataSource:(STKDataSource*)dataSource andQueueItemId:(NSObject*)queueItemId; -(id) initWithDataSource:(STKDataSource*)dataSource andQueueItemId:(NSObject*)queueItemId;
-(void) reset; -(void) reset;
-(double) duration; -(double) duration;
@ -45,6 +43,4 @@ NS_ASSUME_NONNULL_BEGIN
-(double) calculatedBitRate; -(double) calculatedBitRate;
-(BOOL) isDefinitelyCompatible:(AudioStreamBasicDescription*)basicDescription; -(BOOL) isDefinitelyCompatible:(AudioStreamBasicDescription*)basicDescription;
@end @end
NS_ASSUME_NONNULL_END

View File

@ -14,7 +14,7 @@
@implementation STKQueueEntry @implementation STKQueueEntry
-(instancetype) initWithDataSource:(STKDataSource*)dataSourceIn andQueueItemId:(NSObject*)queueItemIdIn -(id) initWithDataSource:(STKDataSource*)dataSourceIn andQueueItemId:(NSObject*)queueItemIdIn
{ {
if (self = [super init]) if (self = [super init])
{ {
@ -121,4 +121,4 @@
return [[self queueItemId] description]; return [[self queueItemId] description];
} }
@end @end

View File

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string> <string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>com.abstractpath.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>

View File

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string> <string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>abstractpath.com.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>