Compare commits

...

6 Commits

Author SHA1 Message Date
tanhakabir e3e4e4dd46 Release 4.2.0 2021-04-16 10:05:57 -07:00
tanhakabir b60e567a83 fix recursive polling logic (#91) 2021-04-16 10:05:21 -07:00
tanhakabir 17e0ee5dd8 Update example app to include a radio stream link (#89)
* update links

* update example app to show podcast, soundbite, and radio
2021-04-06 21:16:13 -07:00
tanhakabir 97909bacce Release 4.1.0 2021-03-22 23:04:53 -07:00
tanhakabir 30b0189f61 Merge Fix PCM memory leak #87 2021-03-22 23:01:35 -07:00
tanhakabir a56d3314ad Update README.md 2021-03-22 11:50:53 -07:00
6 changed files with 27 additions and 14 deletions
@@ -72,8 +72,8 @@
<rect key="frame" x="16" y="60" width="343" height="32"/>
<segments>
<segment title="Soundbite"/>
<segment title="Acquired"/>
<segment title="Y Combinator"/>
<segment title="Podcast"/>
<segment title="Radio"/>
</segments>
<connections>
<action selector="audioSelected:" destination="vXZ-lx-hvc" eventType="valueChanged" id="oYE-yq-348"/>
+7 -7
View File
@@ -13,18 +13,18 @@ struct AudioInfo: Hashable {
var urls: [URL] = [URL(string: "https://www.fesliyanstudios.com/musicfiles/2019-04-23_-_Trusted_Advertising_-_www.fesliyanstudios.com/15SecVersion2019-04-23_-_Trusted_Advertising_-_www.fesliyanstudios.com.mp3")!,
URL(string: "https://chtbl.com/track/18338/traffic.libsyn.com/secure/acquired/acquired_-_armrev_2.mp3?dest-id=376122")!,
URL(string: "https://backtracks.fm/ycombinator/pr/0f685f72-29b1-11e9-9bcf-0ece7a7d2472/111---jake-klamka-and-kevin-hale---y-combinator.mp3?s=1&amp;sd=1&amp;u=1549423185")!]
URL(string: "https://ice6.somafm.com/groovesalad-256-mp3")!]
var url: URL {
switch index {
case 0:
return URL(string: "https://www.fesliyanstudios.com/musicfiles/2019-04-23_-_Trusted_Advertising_-_www.fesliyanstudios.com/15SecVersion2019-04-23_-_Trusted_Advertising_-_www.fesliyanstudios.com.mp3")!
return urls[0]
case 1:
return URL(string: "https://chtbl.com/track/18338/traffic.libsyn.com/secure/acquired/acquired_-_armrev_2.mp3?dest-id=376122")!
return urls[1]
case 2:
return URL(string: "https://backtracks.fm/ycombinator/pr/0f685f72-29b1-11e9-9bcf-0ece7a7d2472/111---jake-klamka-and-kevin-hale---y-combinator.mp3?s=1&amp;sd=1&amp;u=1549423185")!
return urls[2]
default:
return URL(string: "https://www.fesliyanstudios.com/musicfiles/2019-04-23_-_Trusted_Advertising_-_www.fesliyanstudios.com/15SecVersion2019-04-23_-_Trusted_Advertising_-_www.fesliyanstudios.com.mp3")!
return urls[0]
}
}
@@ -33,9 +33,9 @@ struct AudioInfo: Hashable {
case 0:
return "Soundbite"
case 1:
return "Acquired"
return "Podcast"
case 2:
return "Y Combinator"
return "Radio"
default:
return "Soundbite"
}
+2 -1
View File
@@ -17,6 +17,7 @@ Thus, using [AudioToolbox](https://developer.apple.com/documentation/audiotoolbo
1. Play locally saved audio with the same API
1. Download audio
1. Queue up downloaded and streamed audio for autoplay
1. Uses only 1-2% CPU for optimal performance for the rest of your app
1. You're able to install taps and any other AVAudioEngine features to do cool things like skipping silences
### Special Features
@@ -33,7 +34,7 @@ iOS 10.0 and higher.
### Running the Example Project
1. Clone repo
2. CD to directory
2. CD to the `Example` folder where the Example app lives
3. Run `pod install` in terminal
4. Build and run
+1
View File
@@ -173,6 +173,7 @@ class AudioEngine: AudioEngineProtocol {
Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: false) { [weak self] (timer: Timer) in
guard let self = self else { return }
guard self.playingStatus != .ended else {
// Log.test("END TIMER")
self.delegate = nil
return
}
+14 -3
View File
@@ -71,6 +71,7 @@ class AudioStreamEngine: AudioEngine {
private var numberOfBuffersScheduledInTotal = 0 {
didSet {
// Log.test(numberOfBuffersScheduledInTotal)
Log.debug("number of buffers scheduled in total: \(numberOfBuffersScheduledInTotal)")
if numberOfBuffersScheduledInTotal == 0 {
pause()
@@ -86,6 +87,7 @@ class AudioStreamEngine: AudioEngine {
private var numberOfBuffersScheduledFromPoll = 0 {
didSet {
if numberOfBuffersScheduledFromPoll > MAX_POLL_BUFFER_COUNT {
// Log.test("🛑 🛑 STOP POLLING")
shouldPollForNextBuffer = false
}
@@ -149,7 +151,7 @@ class AudioStreamEngine: AudioEngine {
guard let self = self else { return }
guard self.playingStatus != .ended else { return }
self.pollForNextBufferRecursive()
self.pollForNextBuffer()
self.updateNetworkBufferRange()
self.updateNeedle()
self.updateIsPlaying()
@@ -162,9 +164,16 @@ class AudioStreamEngine: AudioEngine {
//Called when
//1. First time audio is finally parsed
//2. When we run to the end of the network buffer and we're waiting again
private func pollForNextBufferRecursive() {
private func pollForNextBuffer() {
guard shouldPollForNextBuffer else { return }
// Log.test("POLL INIT")
pollForNextBufferRecursive()
}
private func pollForNextBufferRecursive() {
// Log.test("POLL")
do {
var nextScheduledBuffer: AVAudioPCMBuffer! = try converter.pullBuffer()
numberOfBuffersScheduledFromPoll += 1
@@ -174,15 +183,17 @@ class AudioStreamEngine: AudioEngine {
queue.async { [weak self] in
if #available(iOS 11.0, *) {
// to make sure the pcm buffers are properly free'd from memory we need to nil them after the player has used them
self?.playerNode.scheduleBuffer(nextScheduledBuffer, completionCallbackType: .dataRendered, completionHandler: { (_) in
self?.playerNode.scheduleBuffer(nextScheduledBuffer, completionCallbackType: .dataConsumed, completionHandler: { (_) in
nextScheduledBuffer = nil
self?.numberOfBuffersScheduledInTotal -= 1
// Log.test("POLL DATA RENDERED")
self?.pollForNextBufferRecursive()
})
} else {
self?.playerNode.scheduleBuffer(nextScheduledBuffer) {
nextScheduledBuffer = nil
self?.numberOfBuffersScheduledInTotal -= 1
// Log.test("POLL OLD")
self?.pollForNextBufferRecursive()
}
}
+1 -1
View File
@@ -8,7 +8,7 @@
Pod::Spec.new do |s|
s.name = 'SwiftAudioPlayer'
s.version = '4.0.0'
s.version = '4.2.0'
s.summary = 'SwiftAudioPlayer is a Swift based audio player that can handle streaming from a remote location and audio manipulation.'
# This description is used to generate tags and improve search results.