Compare commits
34 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
6b6a5ad434 | |
|
|
7def768397 | |
|
|
532bac1e07 | |
|
|
15a9f6d395 | |
|
|
d13282d84e | |
|
|
dfe6c73621 | |
|
|
2d251d5150 | |
|
|
2043330287 | |
|
|
3cb6349c97 | |
|
|
b51035a267 | |
|
|
0d0280b631 | |
|
|
f9f8199015 | |
|
|
d9a6ba7248 | |
|
|
6264442f58 | |
|
|
830ed0f3db | |
|
|
6ef69bacf0 | |
|
|
d8b77ae214 | |
|
|
499e54731d | |
|
|
da71b04aaf | |
|
|
55a314b966 | |
|
|
8fa821a944 | |
|
|
0f69b7ea76 | |
|
|
4d0fccdd70 | |
|
|
5909657368 | |
|
|
50bec46acc | |
|
|
dec8b87498 | |
|
|
f872de223d | |
|
|
f84f1ef0bd | |
|
|
3bc3a85df3 | |
|
|
520f98a6b3 | |
|
|
4f72249c94 | |
|
|
726ec86d77 | |
|
|
15b0242305 | |
|
|
de99ec9d7a |
|
|
@ -230,7 +230,7 @@
|
||||||
A1115929188D686000641365 /* Project object */ = {
|
A1115929188D686000641365 /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0510;
|
LastUpgradeCheck = 0710;
|
||||||
ORGANIZATIONNAME = "Thong Nguyen";
|
ORGANIZATIONNAME = "Thong Nguyen";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
A111594B188D686000641365 = {
|
A111594B188D686000641365 = {
|
||||||
|
|
@ -346,6 +346,7 @@
|
||||||
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;
|
||||||
|
|
@ -422,6 +423,7 @@
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
@ -438,6 +440,7 @@
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
@ -459,6 +462,7 @@
|
||||||
"$(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;
|
||||||
|
|
@ -477,6 +481,7 @@
|
||||||
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;
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
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];
|
||||||
|
|
||||||
|
|
@ -39,7 +40,6 @@
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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((320 - size.width) / 2, frame.size.height * 0.10, size.width, size.height);
|
playFromHTTPButton.frame = CGRectMake((frame.size.width - 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((320 - size.width) / 2, frame.size.height * 0.10 + 35, size.width, size.height);
|
playFromIcecastButton.frame = CGRectMake((frame.size.width - 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((320 - size.width) / 2, frame.size.height * 0.10 + 70, size.width, size.height);
|
playFromLocalFileButton.frame = CGRectMake((frame.size.width - 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((320 - size.width) / 2, frame.size.height * 0.10 + 105, size.width, size.height);
|
queueShortFileButton.frame = CGRectMake((frame.size.width - 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((320 - size.width) / 2, frame.size.height * 0.10 + 140, size.width, size.height);
|
queuePcmWaveFileFromHTTPButton.frame = CGRectMake((frame.size.width - 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((320 - size.width) - 30, 400, size.width, size.height);
|
stopButton.frame = CGRectMake((frame.size.width - 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((320 - size.width) - 30, 430, size.width, size.height);
|
muteButton.frame = CGRectMake((frame.size.width - 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(320 - size.width - 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.on = audioPlayer.equalizerEnabled;
|
enableEqSwitch.on = audioPlayer.equalizerEnabled;
|
||||||
|
|
||||||
[enableEqSwitch addTarget:self action:@selector(onEnableEqSwitch) forControlEvents:UIControlEventAllTouchEvents];
|
[enableEqSwitch addTarget:self action:@selector(onEnableEqSwitch) forControlEvents:UIControlEventAllTouchEvents];
|
||||||
|
|
|
||||||
|
|
@ -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>abstractpath.com.${PRODUCT_NAME:rfc1034identifier}</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,31 @@
|
||||||
"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",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,31 @@
|
||||||
{
|
{
|
||||||
"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",
|
||||||
|
|
@ -8,11 +34,12 @@
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"orientation" : "portrait",
|
"extent" : "full-screen",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"subtype" : "retina4",
|
"subtype" : "retina4",
|
||||||
"extent" : "full-screen",
|
"filename" : "TX6sV-2.png",
|
||||||
"minimum-system-version" : "7.0",
|
"minimum-system-version" : "7.0",
|
||||||
|
"orientation" : "portrait",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -42,6 +69,26 @@
|
||||||
"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.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.3 KiB |
|
|
@ -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>abstractpath.com.${PRODUCT_NAME:rfc1034identifier}</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
|
|
|
||||||
6
LICENSE
6
LICENSE
|
|
@ -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) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved.
|
Copyright (c) 2015 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 the <organization>.
|
This product includes software developed by Thong Nguyen.
|
||||||
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 <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
THIS SOFTWARE IS PROVIDED BY THONG NGUYEN ''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
|
||||||
|
|
|
||||||
|
|
@ -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, AutoRecoveryingHTTP DataSources are provided).
|
* Easy to implement audio data sources (Local, HTTP, AutoRecoveringHTTP 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.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = "StreamingKit"
|
s.name = "StreamingKit"
|
||||||
s.version = "0.1.25"
|
s.version = "0.1.29"
|
||||||
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'
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
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 */; };
|
||||||
|
|
@ -91,6 +93,8 @@
|
||||||
/* 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; };
|
||||||
|
|
@ -270,6 +274,8 @@
|
||||||
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 */,
|
||||||
|
|
@ -331,6 +337,7 @@
|
||||||
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 */,
|
||||||
|
|
@ -425,7 +432,7 @@
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
CLASSPREFIX = STK;
|
CLASSPREFIX = STK;
|
||||||
LastUpgradeCheck = 0610;
|
LastUpgradeCheck = 0710;
|
||||||
ORGANIZATIONNAME = "Thong Nguyen";
|
ORGANIZATIONNAME = "Thong Nguyen";
|
||||||
};
|
};
|
||||||
buildConfigurationList = A1E7C4C3188D57F50010896F /* Build configuration list for PBXProject "StreamingKit" */;
|
buildConfigurationList = A1E7C4C3188D57F50010896F /* Build configuration list for PBXProject "StreamingKit" */;
|
||||||
|
|
@ -525,6 +532,7 @@
|
||||||
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 */,
|
||||||
|
|
@ -633,6 +641,7 @@
|
||||||
);
|
);
|
||||||
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;
|
||||||
|
|
@ -653,6 +662,7 @@
|
||||||
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;
|
||||||
|
|
@ -676,6 +686,7 @@
|
||||||
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;
|
||||||
|
|
@ -776,6 +787,7 @@
|
||||||
"$(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;
|
||||||
};
|
};
|
||||||
|
|
@ -792,6 +804,7 @@
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
7
StreamingKit/StreamingKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
StreamingKit/StreamingKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
|
|
@ -8,10 +8,14 @@
|
||||||
|
|
||||||
#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;
|
||||||
-(id) dequeue;
|
-(nullable id) dequeue;
|
||||||
-(id) peek;
|
-(nullable id) peek;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,9 @@
|
||||||
#include "UIKit/UIApplication.h"
|
#include "UIKit/UIApplication.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
typedef NS_OPTIONS(NSInteger, STKAudioPlayerState)
|
||||||
{
|
{
|
||||||
STKAudioPlayerStateReady,
|
STKAudioPlayerStateReady,
|
||||||
STKAudioPlayerStateRunning = 1,
|
STKAudioPlayerStateRunning = 1,
|
||||||
|
|
@ -54,10 +56,9 @@ typedef enum
|
||||||
STKAudioPlayerStateStopped = (1 << 4),
|
STKAudioPlayerStateStopped = (1 << 4),
|
||||||
STKAudioPlayerStateError = (1 << 5),
|
STKAudioPlayerStateError = (1 << 5),
|
||||||
STKAudioPlayerStateDisposed = (1 << 6)
|
STKAudioPlayerStateDisposed = (1 << 6)
|
||||||
}
|
};
|
||||||
STKAudioPlayerState;
|
|
||||||
|
|
||||||
typedef enum
|
typedef NS_ENUM(NSInteger, STKAudioPlayerStopReason)
|
||||||
{
|
{
|
||||||
STKAudioPlayerStopReasonNone = 0,
|
STKAudioPlayerStopReasonNone = 0,
|
||||||
STKAudioPlayerStopReasonEof,
|
STKAudioPlayerStopReasonEof,
|
||||||
|
|
@ -65,10 +66,9 @@ typedef enum
|
||||||
STKAudioPlayerStopReasonPendingNext,
|
STKAudioPlayerStopReasonPendingNext,
|
||||||
STKAudioPlayerStopReasonDisposed,
|
STKAudioPlayerStopReasonDisposed,
|
||||||
STKAudioPlayerStopReasonError = 0xffff
|
STKAudioPlayerStopReasonError = 0xffff
|
||||||
}
|
};
|
||||||
STKAudioPlayerStopReason;
|
|
||||||
|
|
||||||
typedef enum
|
typedef NS_ENUM(NSInteger, STKAudioPlayerErrorCode)
|
||||||
{
|
{
|
||||||
STKAudioPlayerErrorNone = 0,
|
STKAudioPlayerErrorNone = 0,
|
||||||
STKAudioPlayerErrorDataSource,
|
STKAudioPlayerErrorDataSource,
|
||||||
|
|
@ -77,9 +77,13 @@ typedef enum
|
||||||
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
|
||||||
|
|
@ -91,7 +95,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)
|
||||||
UInt32 bufferSizeInSeconds;
|
float 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)
|
||||||
|
|
@ -101,7 +105,9 @@ typedef struct
|
||||||
}
|
}
|
||||||
STKAudioPlayerOptions;
|
STKAudioPlayerOptions;
|
||||||
|
|
||||||
typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames);
|
#define STK_DISABLE_BUFFER (0xffffffff)
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
@ -129,6 +135,8 @@ 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>
|
||||||
|
|
@ -147,13 +155,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) NSArray* frameFilters;
|
@property (readonly, nullable) 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) NSObject* mostRecentlyQueuedStillPendingItem;
|
@property (readonly, nullable) 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
|
||||||
|
|
@ -170,10 +178,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
|
||||||
-(id) init;
|
-(instancetype) init;
|
||||||
|
|
||||||
/// Initializes a new STKAudioPlayer with the given options
|
/// Initializes a new STKAudioPlayer with the given options
|
||||||
-(id) initWithOptions:(STKAudioPlayerOptions)optionsIn;
|
-(instancetype) 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
|
||||||
|
|
@ -250,17 +258,19 @@ 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:(NSString*)afterFilterWithName block:(STKFrameFilter)block;
|
-(void) addFrameFilterWithName:(NSString*)name afterFilterWithName:(nullable 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
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@
|
||||||
#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
|
||||||
|
|
@ -51,20 +52,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 (2 * 60)
|
#define STK_DEFAULT_PCM_BUFFER_SIZE_IN_SECONDS (0.1)
|
||||||
#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 (64 * 1024)
|
#define STK_DEFAULT_READ_BUFFER_SIZE (128 * 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) ((status) >> 24) & 0xFF, ((status) >> 16) & 0xFF, ((status) >> 8) & 0xFF, (status) & 0xFF
|
#define OSSTATUS_PRINTF_VALUE(status) (char)(((status) >> 24) & 0xFF), (char)(((status) >> 16) & 0xFF), (char)(((status) >> 8) & 0xFF), (char)((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]];
|
||||||
|
|
||||||
|
|
@ -96,6 +97,34 @@ 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))) \
|
||||||
{ \
|
{ \
|
||||||
|
|
@ -145,7 +174,7 @@ STKAudioPlayerInternalState;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation STKFrameFilterEntry
|
@implementation STKFrameFilterEntry
|
||||||
-(id) initWithFilter:(STKFrameFilter)filterIn andName:(NSString*)nameIn
|
-(instancetype) initWithFilter:(STKFrameFilter)filterIn andName:(NSString*)nameIn
|
||||||
{
|
{
|
||||||
if (self = [super init])
|
if (self = [super init])
|
||||||
{
|
{
|
||||||
|
|
@ -271,6 +300,9 @@ 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;
|
||||||
|
|
@ -476,12 +508,12 @@ static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
-(id) init
|
-(instancetype) init
|
||||||
{
|
{
|
||||||
return [self initWithOptions:(STKAudioPlayerOptions){}];
|
return [self initWithOptions:(STKAudioPlayerOptions){}];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(id) initWithOptions:(STKAudioPlayerOptions)optionsIn
|
-(instancetype) initWithOptions:(STKAudioPlayerOptions)optionsIn
|
||||||
{
|
{
|
||||||
if (self = [super init])
|
if (self = [super init])
|
||||||
{
|
{
|
||||||
|
|
@ -491,6 +523,7 @@ 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;
|
||||||
|
|
@ -526,7 +559,21 @@ 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];
|
||||||
|
|
@ -878,7 +925,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;
|
||||||
}
|
}
|
||||||
|
|
@ -1716,10 +1763,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);
|
||||||
}
|
}
|
||||||
|
|
@ -1948,10 +1995,8 @@ static BOOL GetHardwareCodecClassDesc(UInt32 formatId, AudioClassDescription* cl
|
||||||
|
|
||||||
[self destroyAudioConverter];
|
[self destroyAudioConverter];
|
||||||
|
|
||||||
//This breaks mono files
|
|
||||||
//canonicalAudioStreamBasicDescription.mChannelsPerFrame = asbd->mChannelsPerFrame;
|
|
||||||
|
|
||||||
BOOL isRecording = currentlyReadingEntry.dataSource.recordToFileUrl != nil;
|
BOOL isRecording = currentlyReadingEntry.dataSource.recordToFileUrl != nil;
|
||||||
|
|
||||||
if (isRecording)
|
if (isRecording)
|
||||||
{
|
{
|
||||||
recordAudioStreamBasicDescription = (AudioStreamBasicDescription)
|
recordAudioStreamBasicDescription = (AudioStreamBasicDescription)
|
||||||
|
|
@ -2414,6 +2459,9 @@ static BOOL GetHardwareCodecClassDesc(UInt32 formatId, AudioClassDescription* cl
|
||||||
}
|
}
|
||||||
else if (!isRunning)
|
else if (!isRunning)
|
||||||
{
|
{
|
||||||
|
stopReason = stopReasonIn;
|
||||||
|
self.internalState = STKAudioPlayerInternalStateStopped;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3207,60 +3255,66 @@ static OSStatus OutputRenderCallback(void* inRefCon, AudioUnitRenderActionFlags*
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[self appendFrameFilterWithName:@"STKMeteringFilter" block:^(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames)
|
[self appendFrameFilterWithName:@"STKMeteringFilter" block:^(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, float* frames)
|
||||||
{
|
{
|
||||||
SInt16* samples16 = (SInt16*)frames;
|
STKFloatConverterToFloat(_floatConverter,&(pcmAudioBufferList),_floatBuffers,frameCount);
|
||||||
SInt32* samples32 = (SInt32*)frames;
|
|
||||||
UInt32 countLeft = 0;
|
if ([self.delegate respondsToSelector:@selector(plotGraphWithBuffer:andLength:)]) {
|
||||||
UInt32 countRight = 0;
|
[self.delegate plotGraphWithBuffer:*(_floatBuffers) andLength:frameCount];
|
||||||
Float32 decibelsLeft = STK_DBMIN;
|
}
|
||||||
Float32 peakValueLeft = STK_DBMIN;
|
|
||||||
Float64 totalValueLeft = 0;
|
// SInt16* samples16 = (SInt16*)frames;
|
||||||
Float32 previousFilteredValueOfSampleAmplitudeLeft = 0;
|
// SInt32* samples32 = (SInt32*)frames;
|
||||||
Float32 decibelsRight = STK_DBMIN;
|
// UInt32 countLeft = 0;
|
||||||
Float32 peakValueRight = STK_DBMIN;
|
// UInt32 countRight = 0;
|
||||||
Float64 totalValueRight = 0;
|
// Float32 decibelsLeft = STK_DBMIN;
|
||||||
Float32 previousFilteredValueOfSampleAmplitudeRight = 0;
|
// Float32 peakValueLeft = STK_DBMIN;
|
||||||
|
// Float64 totalValueLeft = 0;
|
||||||
if (bytesPerFrame / channelsPerFrame == 2)
|
// Float32 previousFilteredValueOfSampleAmplitudeLeft = 0;
|
||||||
{
|
// Float32 decibelsRight = STK_DBMIN;
|
||||||
for (int i = 0; i < frameCount * channelsPerFrame; i += channelsPerFrame)
|
// Float32 peakValueRight = STK_DBMIN;
|
||||||
{
|
// Float64 totalValueRight = 0;
|
||||||
Float32 absoluteValueOfSampleAmplitudeLeft = abs(samples16[i]);
|
// Float32 previousFilteredValueOfSampleAmplitudeRight = 0;
|
||||||
Float32 absoluteValueOfSampleAmplitudeRight = abs(samples16[i + 1]);
|
//
|
||||||
|
// if (bytesPerFrame / channelsPerFrame == 2)
|
||||||
CALCULATE_METER(Left);
|
// {
|
||||||
CALCULATE_METER(Right);
|
// for (int i = 0; i < frameCount * channelsPerFrame; i += channelsPerFrame)
|
||||||
}
|
// {
|
||||||
}
|
// Float32 absoluteValueOfSampleAmplitudeLeft = abs(samples16[i]);
|
||||||
else if (bytesPerFrame / channelsPerFrame == 4)
|
// Float32 absoluteValueOfSampleAmplitudeRight = abs(samples16[i + 1]);
|
||||||
{
|
//
|
||||||
for (int i = 0; i < frameCount * channelsPerFrame; i += channelsPerFrame)
|
// CALCULATE_METER(Left);
|
||||||
{
|
// 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);
|
// {
|
||||||
CALCULATE_METER(Right);
|
// for (int i = 0; i < frameCount * channelsPerFrame; i += channelsPerFrame)
|
||||||
}
|
// {
|
||||||
}
|
// Float32 absoluteValueOfSampleAmplitudeLeft = abs(samples32[i]) / 32768.0;
|
||||||
else
|
// Float32 absoluteValueOfSampleAmplitudeRight = abs(samples32[i + 1]) / 32768.0;
|
||||||
{
|
//
|
||||||
return;
|
// CALCULATE_METER(Left);
|
||||||
}
|
// CALCULATE_METER(Right);
|
||||||
|
// }
|
||||||
peakPowerDb[0] = MIN(MAX(decibelsLeft, -60), 0);
|
// }
|
||||||
peakPowerDb[1] = MIN(MAX(decibelsRight, -60), 0);
|
// else
|
||||||
|
// {
|
||||||
if (countLeft > 0)
|
// return;
|
||||||
{
|
// }
|
||||||
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);
|
||||||
|
// }
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@
|
||||||
#import "STKHTTPDataSource.h"
|
#import "STKHTTPDataSource.h"
|
||||||
#import "STKDataSourceWrapper.h"
|
#import "STKDataSourceWrapper.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int watchdogPeriodSeconds;
|
int watchdogPeriodSeconds;
|
||||||
|
|
@ -45,8 +47,10 @@ STKAutoRecoveringHTTPDataSourceOptions;
|
||||||
|
|
||||||
@interface STKAutoRecoveringHTTPDataSource : STKDataSourceWrapper
|
@interface STKAutoRecoveringHTTPDataSource : STKDataSourceWrapper
|
||||||
|
|
||||||
-(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource;
|
-(instancetype) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource;
|
||||||
|
|
||||||
@property (readonly) STKHTTPDataSource* innerDataSource;
|
@property (readonly) STKHTTPDataSource* innerDataSource;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
||||||
|
|
@ -101,22 +101,24 @@ static void PopulateOptionsWithDefault(STKAutoRecoveringHTTPDataSourceOptions* o
|
||||||
|
|
||||||
@implementation STKAutoRecoveringHTTPDataSource
|
@implementation STKAutoRecoveringHTTPDataSource
|
||||||
|
|
||||||
|
@dynamic innerDataSource;
|
||||||
|
|
||||||
-(STKHTTPDataSource*) innerHTTPDataSource
|
-(STKHTTPDataSource*) innerHTTPDataSource
|
||||||
{
|
{
|
||||||
return (STKHTTPDataSource*)self.innerDataSource;
|
return (STKHTTPDataSource*)self.innerDataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(id) initWithDataSource:(STKDataSource *)innerDataSource
|
-(instancetype) initWithDataSource:(STKDataSource *)innerDataSource
|
||||||
{
|
{
|
||||||
return [self initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource];
|
return [self initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn
|
-(instancetype) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn
|
||||||
{
|
{
|
||||||
return [self initWithHTTPDataSource:innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions){}];
|
return [self initWithHTTPDataSource:innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions){}];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions)optionsIn
|
-(instancetype) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions)optionsIn
|
||||||
{
|
{
|
||||||
if (self = [super initWithDataSource:innerDataSourceIn])
|
if (self = [super initWithDataSource:innerDataSourceIn])
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@
|
||||||
|
|
||||||
#import "STKDataSource.h"
|
#import "STKDataSource.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@class STKCoreFoundationDataSource;
|
@class STKCoreFoundationDataSource;
|
||||||
|
|
||||||
@interface CoreFoundationDataSourceClientInfo : NSObject
|
@interface CoreFoundationDataSourceClientInfo : NSObject
|
||||||
|
|
@ -62,3 +64,5 @@
|
||||||
-(CFStreamStatus) status;
|
-(CFStreamStatus) status;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@
|
||||||
#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>
|
||||||
|
|
@ -50,8 +52,8 @@
|
||||||
@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) id<STKDataSourceDelegate> delegate;
|
@property (readwrite, unsafe_unretained, nullable) id<STKDataSourceDelegate> delegate;
|
||||||
@property (nonatomic, strong) NSURL *recordToFileUrl;
|
@property (nonatomic, strong, nullable) NSURL *recordToFileUrl;
|
||||||
|
|
||||||
-(BOOL) registerForEvents:(NSRunLoop*)runLoop;
|
-(BOOL) registerForEvents:(NSRunLoop*)runLoop;
|
||||||
-(void) unregisterForEvents;
|
-(void) unregisterForEvents;
|
||||||
|
|
@ -62,3 +64,5 @@
|
||||||
-(AudioFileTypeID) audioFileTypeHint;
|
-(AudioFileTypeID) audioFileTypeHint;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,14 @@
|
||||||
|
|
||||||
#import "STKDataSource.h"
|
#import "STKDataSource.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@interface STKDataSourceWrapper : STKDataSource<STKDataSourceDelegate>
|
@interface STKDataSourceWrapper : STKDataSource<STKDataSourceDelegate>
|
||||||
|
|
||||||
-(id) initWithDataSource:(STKDataSource*)innerDataSource;
|
-(instancetype) initWithDataSource:(STKDataSource*)innerDataSource;
|
||||||
|
|
||||||
@property (readonly) STKDataSource* innerDataSource;
|
@property (readonly) STKDataSource* innerDataSource;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
|
|
||||||
@implementation STKDataSourceWrapper
|
@implementation STKDataSourceWrapper
|
||||||
|
|
||||||
-(id) initWithDataSource:(STKDataSource*)innerDataSourceIn
|
-(instancetype) initWithDataSource:(STKDataSource*)innerDataSourceIn
|
||||||
{
|
{
|
||||||
if (self = [super init])
|
if (self = [super init])
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
@ -0,0 +1,211 @@
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
@ -34,10 +34,12 @@
|
||||||
|
|
||||||
#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*(^STKURLProvider)();
|
typedef NSURL* _Nonnull (^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
|
||||||
|
|
@ -46,11 +48,13 @@ typedef void(^STKAsyncURLProvider)(STKHTTPDataSource* dataSource, BOOL forSeek,
|
||||||
@property (readonly) UInt32 httpStatusCode;
|
@property (readonly) UInt32 httpStatusCode;
|
||||||
|
|
||||||
+(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)fileExtension;
|
+(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)fileExtension;
|
||||||
-(id) initWithURL:(NSURL*)url;
|
-(instancetype) initWithURL:(NSURL*)url;
|
||||||
-(id) initWithURL:(NSURL *)url httpRequestHeaders:(NSDictionary *)httpRequestHeaders;
|
-(instancetype) initWithURL:(NSURL*)url httpRequestHeaders:(NSDictionary*)httpRequestHeaders;
|
||||||
-(id) initWithURLProvider:(STKURLProvider)urlProvider;
|
-(instancetype) initWithURLProvider:(STKURLProvider)urlProvider;
|
||||||
-(id) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProvider;
|
-(instancetype) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProvider;
|
||||||
-(NSRunLoop*) eventsRunLoop;
|
-(nullable NSRunLoop*) eventsRunLoop;
|
||||||
-(void) reconnect;
|
-(void) reconnect;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
||||||
|
|
@ -64,19 +64,19 @@
|
||||||
|
|
||||||
@implementation STKHTTPDataSource
|
@implementation STKHTTPDataSource
|
||||||
|
|
||||||
-(id) initWithURL:(NSURL*)urlIn
|
-(instancetype) initWithURL:(NSURL*)urlIn
|
||||||
{
|
{
|
||||||
return [self initWithURLProvider:^NSURL* { return urlIn; }];
|
return [self initWithURLProvider:^NSURL* { return urlIn; }];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(id) initWithURL:(NSURL *)urlIn httpRequestHeaders:(NSDictionary *)httpRequestHeaders
|
-(instancetype) 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(id) initWithURLProvider:(STKURLProvider)urlProviderIn
|
-(instancetype) initWithURLProvider:(STKURLProvider)urlProviderIn
|
||||||
{
|
{
|
||||||
urlProviderIn = [urlProviderIn copy];
|
urlProviderIn = [urlProviderIn copy];
|
||||||
|
|
||||||
|
|
@ -86,7 +86,7 @@
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(id) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProviderIn
|
-(instancetype) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProviderIn
|
||||||
{
|
{
|
||||||
if (self = [super init])
|
if (self = [super init])
|
||||||
{
|
{
|
||||||
|
|
@ -411,7 +411,7 @@
|
||||||
|
|
||||||
eventsRunLoop = savedEventsRunLoop;
|
eventsRunLoop = savedEventsRunLoop;
|
||||||
|
|
||||||
[self seekToOffset:self.position];
|
[self seekToOffset:self->supportsSeek ? self.position : 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) seekToOffset:(SInt64)offset
|
-(void) seekToOffset:(SInt64)offset
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,14 @@
|
||||||
|
|
||||||
#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;
|
||||||
-(id) initWithFilePath:(NSString*)filePath;
|
-(instancetype) initWithFilePath:(NSString*)filePath;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
@implementation STKLocalFileDataSource
|
@implementation STKLocalFileDataSource
|
||||||
@synthesize filePath;
|
@synthesize filePath;
|
||||||
|
|
||||||
-(id) initWithFilePath:(NSString*)filePathIn
|
-(instancetype) initWithFilePath:(NSString*)filePathIn
|
||||||
{
|
{
|
||||||
if (self = [super init])
|
if (self = [super init])
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
#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
|
||||||
|
|
@ -35,7 +37,7 @@
|
||||||
@property (readwrite, retain) NSObject* queueItemId;
|
@property (readwrite, retain) NSObject* queueItemId;
|
||||||
@property (readwrite, retain) STKDataSource* dataSource;
|
@property (readwrite, retain) STKDataSource* dataSource;
|
||||||
|
|
||||||
-(id) initWithDataSource:(STKDataSource*)dataSource andQueueItemId:(NSObject*)queueItemId;
|
-(instancetype) initWithDataSource:(STKDataSource*)dataSource andQueueItemId:(NSObject*)queueItemId;
|
||||||
|
|
||||||
-(void) reset;
|
-(void) reset;
|
||||||
-(double) duration;
|
-(double) duration;
|
||||||
|
|
@ -43,4 +45,6 @@
|
||||||
-(double) calculatedBitRate;
|
-(double) calculatedBitRate;
|
||||||
-(BOOL) isDefinitelyCompatible:(AudioStreamBasicDescription*)basicDescription;
|
-(BOOL) isDefinitelyCompatible:(AudioStreamBasicDescription*)basicDescription;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
@implementation STKQueueEntry
|
@implementation STKQueueEntry
|
||||||
|
|
||||||
-(id) initWithDataSource:(STKDataSource*)dataSourceIn andQueueItemId:(NSObject*)queueItemIdIn
|
-(instancetype) 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
|
||||||
|
|
|
||||||
|
|
@ -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>com.abstractpath.${PRODUCT_NAME:rfc1034identifier}</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
|
|
|
||||||
|
|
@ -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>abstractpath.com.${PRODUCT_NAME:rfc1034identifier}</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue