All Projects → tanhakabir → Swiftaudioplayer

tanhakabir / Swiftaudioplayer

Licence: other
Streaming and realtime audio manipulation with AVAudioEngine

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Swiftaudioplayer

Logstash
Logstash - transport and process your logs, events, or other data
Stars: ✭ 12,543 (+6501.58%)
Mutual labels:  streaming
Hstream
The streaming database built for IoT data storage and real-time processing in the 5G Era
Stars: ✭ 166 (-12.63%)
Mutual labels:  streaming
Iteratee
Iteratees for cats
Stars: ✭ 186 (-2.11%)
Mutual labels:  streaming
Tus Ruby Server
Ruby server for tus resumable upload protocol
Stars: ✭ 172 (-9.47%)
Mutual labels:  streaming
Haishinkit.swift
Camera and Microphone streaming library via RTMP, HLS for iOS, macOS, tvOS.
Stars: ✭ 2,237 (+1077.37%)
Mutual labels:  streaming
Scio
A Scala API for Apache Beam and Google Cloud Dataflow.
Stars: ✭ 2,247 (+1082.63%)
Mutual labels:  streaming
Smart open
Utils for streaming large files (S3, HDFS, gzip, bz2...)
Stars: ✭ 2,306 (+1113.68%)
Mutual labels:  streaming
Redis4cats
🔖 Redis client built on top of Cats Effect, Fs2 and Lettuce
Stars: ✭ 189 (-0.53%)
Mutual labels:  streaming
Node Csv Stringify
CSV stringifier implementing the Node.js `stream.Transform` API
Stars: ✭ 179 (-5.79%)
Mutual labels:  streaming
Xlsxtream
Streaming & Fast XLSX Spreadsheet Writer for Ruby
Stars: ✭ 184 (-3.16%)
Mutual labels:  streaming
Put.io Adder
OS X put.io client that acts as handler for magnet: links and .torrent files, and adds them to your put.io download queue
Stars: ✭ 172 (-9.47%)
Mutual labels:  streaming
Liftbridge
Lightweight, fault-tolerant message streams.
Stars: ✭ 2,175 (+1044.74%)
Mutual labels:  streaming
Fast
A framework for GPU based high-performance medical image processing and visualization
Stars: ✭ 179 (-5.79%)
Mutual labels:  streaming
Koel
🐦 A personal music streaming server that works.
Stars: ✭ 13,105 (+6797.37%)
Mutual labels:  streaming
Magiconion
Unified Realtime/API framework for .NET platform and Unity.
Stars: ✭ 2,505 (+1218.42%)
Mutual labels:  streaming
Onyx
Distributed, masterless, high performance, fault tolerant data processing
Stars: ✭ 2,019 (+962.63%)
Mutual labels:  streaming
Render Media
Intelligently render media files in the browser
Stars: ✭ 181 (-4.74%)
Mutual labels:  streaming
Flink Spector
Framework for Apache Flink unit tests
Stars: ✭ 190 (+0%)
Mutual labels:  streaming
Supysonic
Supysonic is a Python implementation of the Subsonic server API.
Stars: ✭ 187 (-1.58%)
Mutual labels:  streaming
Fs2 Kafka
Functional Kafka Streams for Scala
Stars: ✭ 183 (-3.68%)
Mutual labels:  streaming

SwiftAudioPlayer

Version License Platform

Swift-based audio player with AVAudioEngine as its base. Allows for: streaming online audio, playing local file, changing audio speed (3.5X, 4X, 32X), pitch, and real-time audio manipulation using custom audio enhancements.

This player was built for podcasting. We originally used AVPlayer for playing audio but we wanted to manipulate audio that was being streamed. We set up AVAudioEngine at first just to play a file saved on the phone and it worked great, but AVAudioEngine on its own doesn't support streaming audio as easily as AVPlayer.

Thus, using AudioToolbox, we are able to stream audio and convert the downloaded data into usable data for the AVAudioEngine to play. For an overview of our solution check out our blog post.

Basic Features

  1. Realtime audio manipulation that includes going up to 10x speed, using equalizers and other manipulations
  2. Stream online audio using AVAudioEngine
  3. Play locally saved audio with the same API
  4. Download audio
  5. Queue up downloaded and streamed audio for autoplay
  6. You're able to install taps and any other AVAudioEngine features to do cool things like skipping silences

Special Features

These are community supported audio manipulation features using this audio engine. You can implement your own version of these features and you can look at SAPlayerFeatures to learn how they were implemented using the library.

  1. Skip silences in audio
  2. Sleep timer to stop playing audio after a delay

Requirements

iOS 10.0 and higher.

Getting Started

Running the Example Project

  1. Clone repo
  2. CD to directory
  3. Run pod install in terminal
  4. Build and run

Installation

SwiftAudioPlayer is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'SwiftAudioPlayer'

Usage

Import the player at the top:

import SwiftAudioPlayer

Important: For app in background downloading please refer to note.

To play remote audio:

let url = URL(string: "https://randomwebsite.com/audio.mp3")!
SAPlayer.shared.startRemoteAudio(withRemoteUrl: url)
SAPlayer.shared.play()

To set the display information for the lockscreen:

let info = SALockScreenInfo(title: "Random audio", artist: "Foo", artwork: UIImage(), releaseDate: 123456789)
SAPlayer.shared.mediaInfo = info

To receive streaming progress (for buffer progress %):

@IBOutlet weak var bufferProgress: UIProgressView!

override func viewDidLoad() {
    super.viewDidLoad()
    
    _ = SAPlayer.Updates.StreamingBuffer.subscribe{ [weak self] (url, buffer) in
        guard let self = self else { return }
        guard url == self.selectedAudioUrl else { return }

        let progress = Float((buffer.totalDurationBuffered + buffer.startingBufferTimePositon) / self.duration)

        self.bufferProgress.progress = progress

        self.isPlayable = buffer.isReadyForPlaying
    }
}

Look at the Updates section to see usage details and other updates to follow.

For realtime audio manipulations, AVAudioUnit nodes are used. For example to adjust the reverb through a slider in the UI:

@IBOutlet weak var reverbSlider: UISlider!

override func viewDidLoad() {
    super.viewDidLoad()

    let node = AVAudioUnitReverb()
    SAPlayer.shared.audioModifiers.append(node)
    node.wetDryMix = 300
}

@IBAction func reverbSliderChanged(_ sender: Any) {
    if let node = SAPlayer.shared.audioModifiers[1] as? AVAudioUnitReverb {
            node.wetDryMix = reverbSlider.value
        }
}

For a more detailed explanation on usage, look at the Realtime Audio Manipulations section.

For more details and specifics look at the API documentation below.

Contact

Issues

Submit any issues or requests on the Github repo.

Any questions?

Feel free to reach out to either of us:

tanhakabir, [email protected] JonMercer, [email protected]

License

SwiftAudioPlayer is available under the MIT license. See the LICENSE file for more info.


API in detail

SAPlayer

Access the player and all of its fields and functions through SAPlayer.shared.

Supported file types

Known supported file types are .mp3 and .wav.

Playing Audio (Basic Commands)

To set up player with audio to play, use either:

  • startSavedAudio(withSavedUrl url: URL, mediaInfo: SALockScreenInfo?) to play audio that is saved on the device.
  • startRemoteAudio(withRemoteUrl url: URL, mediaInfo: SALockScreenInfo?) to play audio streamed from a remote location.

Both of these expect a URL of the location of the audio and an optional media information to display on the lockscreen.

For streaming remote audio, subscribe to SAPlayer.Updates.StreamingBuffer for updates on streaming progress.

Basic controls available:

play()
pause()
togglePlayAndPause()
seekTo(seconds: Double)
skipForward()
skipBackwards()

Queuing Audio for Autoplay

You can queue either remote or locally saved audio to be played automatically next.

To queue:

SAPlayer.shared.queueSavedAudio(withSavedUrl: C://random_folder/audio.mp3) // or
SAPlayer.shared.queueRemoteAudio(withRemoteUrl: https://randomwebsite.com/audio.mp3)

Important

The engine can handle audio manipulations like speed, pitch, effects, etc. To do this, nodes for effects must be finalized before initialize is called. Look at audio manipulation documentation for more information.

Lockscreen Media Player

Update and set what displays on the lockscreen's media player when the player is active.

skipForwardSeconds and skipBackwardSeconds for the intervals to skip forward and back with.

mediaInfo for the audio's information to display on the lockscreen. Is of type SALockScreenInfo which contains:

title: String
artist: String
artwork: UIImage?
releaseDate: UTC // Int

playbackRateOfAudioChanged(rate: Float) is used to update the lockscreen media player that the playback rate has changed.

SAPlayer.Downloader

Use functionaity from Downloader to save audio files from remote locations for future offline playback.

Audio files are saved under custom naming scheme on device and are recoverable with original remote URL for file.

Important step for background downloads

To ensure that your app will keep downloading audio in the background be sure to add the following to AppDelegate.swift:

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
    SAPlayer.Downloader.setBackgroundCompletionHandler(completionHandler)
}

Downloading

All downloads will be paused when audio is streamed from a URL. They will automatically resume when streaming is done.

Use the following to start downloading audio in the background:

func downloadAudio(withRemoteUrl url: URL, completion: @escaping (_ savedUrl: URL) -> ())

It will call the completion handler you pass after successful download with the location of the downloaded file on the device.

Subscribe to SAPlayer.Updates.AudioDownloading for downloading progress updates.

And use the following to stop any active or prevent future downloads of the corresponding remote URL:

func cancelDownload(withRemoteUrl url: URL)

By default downloading will be allowed on cellular data. If you would like to turn this off set:

SAPlayer.Downloader.allowUsingCellularData = false

You can also retrieve what preference you have set for cellular downloads through allowUsingCellularData.

Manage Downloaded

Use the following to manage downloaded audio files.

Checks if downloaded already:

func isDownloaded(withRemoteUrl url: URL) -> Bool

Get URL of audio file saved on device corresponding to remote location:

func getSavedUrl(forRemoteUrl url: URL) -> URL?

Delete downloaded audio if it exists:

func deleteDownloaded(withSavedUrl url: URL)

NOTE: You're in charge or clearing downloads when your don't need them anymore

SAPlayer.Updates

Receive updates for changing values from the player, such as the duration, elapsed time of playing audio, download progress, and etc.

All subscription functions for updates take the form of:

func subscribe(_ closure: @escaping (_ url: URL, _ payload:  <Payload>) -> ()) -> UInt
  • closure: The closure that will receive the updates. It's recommended to have a weak reference to a class that uses these functions.
  • url: The corresponding remote URL for the update. In the case there might be multiple files observed, such as downloading many files at once or switching over from playing one audio to another and the updates corresponding to the previous aren't silenced on switch-over.
  • payload: The updated value.
  • Returns: the id for the subscription in the case you would like to unsubscribe to updates for the closure.

Similarily unsubscribe takes the form of:

func unsubscribe(_ id: UInt)
  • id: The closure with this id will stop receiving updates.

ElapsedTime

Payload = Double

Changes in the timestamp/elapsed time of the current initialized audio. Aka, where the scrubber's pointer of the audio should be at.

Subscribe to this to update views on changes in position of which part of audio is being played.

Duration

Payload = Double

Changes in the duration of the current initialized audio. Especially helpful for audio that is being streamed and can change with more data. The engine makes a best effort guess as to the duration of the audio. The guess gets better with more bytes streamed from the web.

PlayingStatus

Payload = SAPlayingStatus

Changes in the playing status of the player. Can be one of the following 4: playing, paused, buffering, ended (audio ended).

StreamingBuffer

Payload = SAAudioAvailabilityRange

Changes in the progress of downloading audio for streaming. Information about range of audio available and if the audio is playable. Look at SAAudioAvailabilityRange for more information.

For progress of downloading audio that saves to the phone for playback later, look at AudioDownloading instead.

AudioDownloading

Payload = Double

Changes in the progress of downloading audio in the background. This does not correspond to progress in streaming downloads, look at StreamingBuffer for streaming progress.

Audio Effects

Realtime Audio Manipulation

All audio effects on the player is done through AVAudioUnit nodes. These include adding reverb, changing pitch and playback rate, and adding distortion. Full list of effects available here.

The effects intended to use are stored in audioModifiers as a list of nodes. These nodes are in the order that the engine will attach them to one another.

Note: By default SAPlayer starts off with one node, an AVAudioUnitTimePitch node, that is set to change the rate of audio without changing the pitch of the audio (intended for changing the rate of spoken word).

Important

All the nodes intended to be used on the playing audio must be finalized before calling initializeSavedAudio(...) or initializeRemoteAudio(...). Any changes to list of nodes after initialize is called for a given audio file will not be reflected in playback.

Once all nodes are added to audioModifiers and the player has been initialized, any manipulations done with the nodes are performed in realtime. The example app shows manipulating the playback rate in realtime:

let speed = rateSlider.value
if let node = SAPlayer.shared.audioModifiers[0] as? AVAudioUnitTimePitch {
    node.rate = speed
    SAPlayer.shared.playbackRateOfAudioChanged(rate: speed)
}

Note: if the rate of the audio is changed, playbackRateOfAudioChanged should also be called to update the lockscreen's media player.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].