Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/markbattistella/audiomanager
AudioManager is a Swift package that provides a modular and easy-to-use interface for implementing audio feedback in your applications. It integrates seamlessly with SwiftUI, enabling you to enhance user experience through customisable audible feedback.
https://github.com/markbattistella/audiomanager
hacktoberfest ios macos swift tvos visionos
Last synced: 7 days ago
JSON representation
AudioManager is a Swift package that provides a modular and easy-to-use interface for implementing audio feedback in your applications. It integrates seamlessly with SwiftUI, enabling you to enhance user experience through customisable audible feedback.
- Host: GitHub
- URL: https://github.com/markbattistella/audiomanager
- Owner: markbattistella
- License: mit
- Created: 2024-05-11T06:14:11.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2024-12-11T02:31:08.000Z (12 days ago)
- Last Synced: 2024-12-11T03:25:12.567Z (12 days ago)
- Topics: hacktoberfest, ios, macos, swift, tvos, visionos
- Language: Swift
- Homepage: https://swiftpackageindex.com/markbattistella/AudioManager/documentation
- Size: 53.7 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# AudioManager
![Swift Versions](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fmarkbattistella%2FAudioManager%2Fbadge%3Ftype%3Dswift-versions)
![Platforms](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fmarkbattistella%2FAudioManager%2Fbadge%3Ftype%3Dplatforms)
![Licence](https://img.shields.io/badge/Licence-MIT-white?labelColor=blue&style=flat)
`AudioManager` is a Swift package that provides a modular and easy-to-use interface for implementing audio feedback in your applications. It integrates seamlessly with SwiftUI, enabling you to enhance user experience through customisable audible feedback.
## Features
- **Custom Audio:** Easily define and trigger audio feedback.
- **SwiftUI Extensions:** Add audio feedback to SwiftUI views in a declarative way.
- **User Preferences:** Enable or disable audio feedback based on user settings through simple configuration.
- **Custom Audio Patterns:** Extend and create your own audio feedback.## Installation
Add `AudioManager` to your Swift project using Swift Package Manager.
```swift
dependencies: [
.package(url: "https://github.com/markbattistella/AudioManager", from: "1.0.0")
]
```## Usage
There are three type of ways to use the `AudioManager`:
- **Static Action:** This is the simplest method, used when you want to trigger audio feedback for a particular state change. It's consistent and straightforward — ideal when the audio feedback needs to occur every time a specific condition (like a state variable changing) is met.
- **Static Action with Condition:** This approach adds more control compared to the standard static action. Here, you specify a set of conditions to determine when the audio feedback should be triggered. This allows you to handle more nuanced scenarios — such as only playing feedback when transitioning from one specific state to another, while ignoring others.
- **Dynamic Action:** The most flexible of the three, dynamic actions let you determine the type of audio feedback based on the old and new values during a state change. This means you can implement complex feedback behaviours that respond differently based on how the state transitions, allowing for a more dynamic and tailored user experience.> [!NOTE]
> Though there is the `.system()` `Playback` call, it is only available on iOS as that is where those in-build sounds live. All other uses can utilise the `.custom()` option.### Static Action
The static action format allows you to trigger audio feedback consistently and simply. In the example below, audio feedback is triggered whenever the `isSuccess` state changes.
```swift
@State private var isSuccess: Bool = falseButton("isSuccess: \(isSuccess)") {
isSuccess.toggle()
}
.audioFeedback(.system(.ui(.tock)), trigger: isSuccess)
```### Static Action with Condition
You can also use a condition to control when the audio feedback should be triggered, allowing for more focused control over when feedback occurs.
#### Old and New Values
```swift
enum Phase { case inactive, active, completed }@State private var phase: Phase = .inactive
Button("Update phase") {
switch phase {
case .inactive: phase = .active
case .active: phase = .completed
case .completed: phase = .inactive
}
}
.audioFeedback(.system(.ui(.tink)), trigger: phase) { oldValue, newValue in
oldValue != .completed && newValue == .completed
}
```#### New Value Only
```swift
enum Phase { case inactive, active, completed }@State private var phase: Phase = .inactive
Button("Update phase") {
switch phase {
case .inactive: phase = .active
case .active: phase = .completed
case .completed: phase = .inactive
}
}
.audioFeedback(.system(.ui(.tink)), trigger: phase) { newValue in
newValue == .completed
}
```#### No Parameters
```swift
@State private var phase: Bool = falseButton("Toggle Phase") {
phase.toggle()
}
.audioFeedback(.system(.ui(.tink)), trigger: phase) {
// Audio feedback triggered
}
```### Dynamic Action
The dynamic action approach gives you full control over both the type of feedback and the conditions under which it's triggered.
#### Old and New Values
```swift
enum LoadingState { case ready, success, failure }@State private var loadingState: LoadingState = .ready
Button("Update loading state") {
switch loadingState {
case .ready: loadingState = .success
case .success: loadingState = .failure
case .failure: loadingState = .ready
}
}
.audioFeedback(trigger: loadingState) { oldValue, newValue in
switch (oldValue, newValue) {
case (.failure, .ready):
return .system(.modern(.cameraShutterBurstBegin))
case (.ready, .success):
return .system(.nano(.screenCapture))
case (.success, .failure):
return .system(.new(.update))
default:
return nil
}
}
```#### New Values Only
```swift
enum LoadingState { case ready, success, failure }@State private var loadingState: LoadingState = .ready
Button("Update loading state") {
switch loadingState {
case .ready: loadingState = .success
case .success: loadingState = .failure
case .failure: loadingState = .ready
}
}
.audioFeedback(trigger: loadingState) { newValue in
switch newValue {
case .success: return .system(.modern(.cameraShutterBurstBegin))
case .failure: return .system(.nano(.screenCapture))
default: return nil
}
}
```#### No Parameters
```swift
enum LoadingState { case ready, success, failure }@State private var loadingState: LoadingState = .ready
Button("Update loading state") {
switch loadingState {
case .ready: loadingState = .success
case .success: loadingState = .failure
case .failure: loadingState = .ready
}
}
.audioFeedback(trigger: loadingState) {
// Audio feedback triggered
}
```### Configuring Audio Settings
`AudioManager` includes a `.audioEffectsEnabled` `UserDefaults` key, allowing you to dynamically enable or disable audio based on user settings.
This is helpful if you want to add a settings screen for toggling audio sound effects, or if you need an overall logic to control audio — for example, making it a premium feature.
#### Built-in UserDefaults Suite
The package uses an internal, publicly exposed `UserDefaults` suite for storing audio-related settings:
```swift
@main
struct MyAwesomeApp: App {init() {
UserDefaults.audio.register([
AudioUserDefaultsKey.audioEffectsEnabled : true
])
}var body: some Scene {
WindowGroup { ... }
}
}
```Or manually updating it:
```swift
Button("Turn audio off") {
UserDefaults.audio.set(false, for: AudioUserDefaultKeys.isAudioEnabled)
}Button("Turn audio on") {
UserDefaults.audio.set(true, for: AudioUserDefaultKeys.isAudioEnabled)
}
```> [!IMPORTANT]
> Although you can register `UserDefaults` to any suite (`.standard` or custom), the package will only respond to the internal `.audio` suite to prevent unintended clashes across different parts of the application.## Extending Audio Feedback Types
If the built-in feedback types are not sufficient, you can use your own custom audio files using the `.custom(CustomSoundRepresentable)` `Playback` case.
### Custom File Restrictions
There are a limited accepted audio file extensions allowed: `.aif`, `.aiff`, `.caf`, `.mp3`, and `.wav`.
Also your audio file is limited to `30` seconds. The playback will simply not occur if it is longer than 30 seconds.
### Creating a Custom Feedback
To add a custom audio feedback type:
1. Define a `CustomSoundRepresentable` conforming enum:
```swift
enum MyCustomSound: CustomSoundRepresentable {
case tupperwareFallingOutOfCrampedCupboardvar soundFile: SoundFile {
switch self {
case .tupperwareFallingOutOfCrampedCupboard:
Soundfile(name: "tupperwareFallingOutOfCrampedCupboard", extension: .aif)
}
}
}
```2. Ensure that the filename and extension are correct, and loaded into your app main bundle.
3. Use the custom feedback in your app:
```swift
@State private var isError: Bool = falseButton("Show error") {
isError.toggle()
}
.audioFeedback(.custom(MyCustomSound.tupperwareFallingOutOfCrampedCupboard), trigger: isError)
```## Contributing
Contributions are always welcome! Feel free to submit a pull request or open an issue for any suggestions or improvements you have.
## License
`AudioManager` is licensed under the MIT License. See the LICENCE file for more details.