Regenerate project screenshots
mainIf you need to regenerate the README images, use the WaveformScreenshots SPM executable target:
swift run WaveformScreenshotsrepository·main·Indexed 23 days ago
https://github.com/dmrschmidt/dswaveformimageA native audio waveform rendering library for Apple platforms (iOS, iPadOS, macOS, visionOS, and Mac Catalyst). It provides high-level SwiftUI and UIKit views, a raw drawing API for generating images via WaveformImageDrawer, and an analyzer for raw audio samples. Features include linear and circular renderers, spectral tinting, amplitude scaling, and support for real-time live audio waveform rendering.
If you need to regenerate the README images, use the WaveformScreenshots SPM executable target:
swift run WaveformScreenshotsWhen upgrading to version 15.0.0, be aware of the following breaking changes and new features:
Waveform.Style.spectralTint(low:high:): A new style case has been added. If you use exhaustive switch statements over Waveform.Style, you must add this case or use @unknown default.Position.middle rendering: Waveforms centered with .middle now render smaller at verticalScalingFactor=1. They are constrained to fill exactly half the available canvas height in each direction. To achieve the previous visual size, increase the verticalScalingFactor.Waveform.AmplitudeScaling: A new enum has been introduced. It defaults to .absolute to preserve prior behavior. You can configure this using the amplitudeScaling: parameter in Waveform.Configuration.init or with(...).WaveformAnalyzer.analyze(...): This method now returns both amplitudes and per-slot spectral centroids in a single pass.LinearWaveformRenderer: Now conforms to the SpectralAwareWaveformRenderer protocol.Add the package via Swift Package Manager using the following URL. It supports versions up to the next major version from 14.0.0.
https://github.com/dmrschmidt/DSWaveformImageAfter adding the package, import the modules based on your needs:
import DSWaveformImage: Core functionality (drawer, analyzer, renderers, types).import DSWaveformImageViews: UI components (UIKit and SwiftUI views).import DSWaveformImage // core: drawer, analyzer, renderers, types
import DSWaveformImageViews // UIKit + SwiftUI views (optional)Key changes in version 13.0.0:
dampening has been renamed to damping throughout the library (specifically in Waveform.Configuration)..outlined and .gradientOutlined were added to Waveform.Style.Waveform.Position was removed. Positioning responsibility has been moved to the parent view.Key changes in version 11.0.0:
DSWaveformImage and DSWaveformImageViews. If you use the native SwiftUI/UIKit views, you must add import DSWaveformImageViews to your file.Binding to using plain values.Key changes in version 12.0.0:
WaveformRenderer protocol.CircularWaveformRenderer was introduced.position was removed from Waveform.Configuration.Depending on your integration layer, use the following patterns to render waveforms:
SwiftUI
Use the WaveformView component.
UIKit
Use the WaveformImageView component.
Raw API
Use WaveformImageDrawer to generate a UIImage or NSImage directly.
// SwiftUI
WaveformView(audioURL: url)
// UIKit
let view = WaveformImageView(frame: .init(x: 0, y: 0, width: 500, height: 300))
view.waveformAudioURL = url
// Raw UIImage / NSImage
let image = try await WaveformImageDrawer().waveformImage(
fromAudioAt: url,
with: .init(size: size, style: .filled(.black))
)Key changes in version 14.0.0:
WaveformAnalyzer and WaveformImageDrawer now return a Result<[Float] | DSImage, Error> type when using completion handlers.WaveformAnalyzer API: The analyzer is now stateless. Instead of passing the URL to the constructor, use the samples(fromAudioAt:count:qos:) method.WaveformView: A new constructor is available that exposes the underlying WaveformShape.For real-time rendering of a [Float] sample stream, use the live view components. These should be paired with a source like AVAudioRecorder that provides per-frame amplitudes.
SwiftUI
Use WaveformLiveCanvas(samples:shouldDrawSilencePadding:).
UIKit
Use WaveformLiveView and call .add(sample:) as new amplitudes arrive.
// SwiftUI
WaveformLiveCanvas(samples: recorder.samples, shouldDrawSilencePadding: true)
// UIKit
let view = WaveformLiveView()
recorder.updateMeters()
let amplitude = 1 - pow(10, recorder.averagePower(forChannel: 0) / 20)
view.add(sample: amplitude)To capture and crop screenshots from the iOS simulator for use in documentation, follow these steps using xcrun and ImageMagick:
xcrun simctl launch <udid> de.dmrschmidt.DSWaveformImageExample-iOS -tab 2xcrun simctl io <udid> screenshot raw.pngmagick:
magick raw.png -crop 1206x2343+0+177 +repage live-recording.pngxcrun simctl launch <udid> de.dmrschmidt.DSWaveformImageExample-iOS -tab 2
xcrun simctl io <udid> screenshot raw.png
magick raw.png -crop 1206x2343+0+177 +repage live-recording.png.spectralTint(low:high:) colors each amplitude column based on its spectral centroid. Bass-heavy columns use the low color, while treble-heavy columns use the high color, with smooth interpolation between them.
Note: This requires a renderer that conforms to SpectralAwareWaveformRenderer. LinearWaveformRenderer conforms by default. If a renderer does not support spectral data, it will fall back to filling with the low color.
WaveformView(audioURL: url, configuration: .init(
style: .spectralTint(low: .systemBlue, high: .systemRed)
))Waveform.Damping fades the envelope toward zero at one or both ends. This is useful for live capture to avoid hard cuts at the leading or trailing edges.
Use Damping(percentage:sides:) where percentage is the fade amount and sides can be .both, .up, or .down. You can also provide a custom easing: closure to shape the falloff.
.init(style: .filled(.indigo), damping: .init(percentage: 0.18, sides: .both))