dmrschmidt / DSWaveformImage

Generate waveform images from audio files on iOS, macOS & visionOS in Swift. Native SwiftUI & UIKit views.
MIT License
978 stars 109 forks source link

Error on macOS #89

Open rokach opened 5 months ago

rokach commented 5 months ago

Hi, I'm using Xcode 14.2 on macOS 12.6.5 and the project "not found" the library I tried version 14.2.1 and 14.0

I import DSWaveformImage and DSWaveformImageViews

Screen Shot 2024-01-10 at 12 37 10 PM Screen Shot 2024-01-10 at 12 36 59 PM
dmrschmidt commented 5 months ago

Hey, yeah Xcode 14.2 is not supported currently with the latest version. I think 13 was the last one where it was, maybe even 12.

so the solution would be to update to latest Xcode 15.x (15.2 is the current one at this point).

is that an option for you, or why are you still on Xcode 14?

rokach commented 5 months ago

Ok, yeah I'm using Xcode 14 becuase I'm using MacBook Pro 2015 and macOS 12 is the last version for it so I can't update to macOS 13/14 and Xcode 15

dmrschmidt commented 5 months ago

Hmm ok, that’s of course a good reason. If I’m not mistaken though, isn’t Xcode 15 required (soon?) to publish to the AppStore though anyway? Or will Xcode 14 keep being supported for a longer time?

I suppose there should be another way to do the visionOS checks backwards compatible… just not sure right now how. I’d have to check for that.

rokach commented 5 months ago

Hmm ok, that’s of course a good reason. If I’m not mistaken though, isn’t Xcode 15 required (soon?) to publish to the AppStore though anyway? Or will Xcode 14 keep being supported for a longer time?

I suppose there should be another way to do the visionOS checks backwards compatible… just not sure right now how. I’d have to check for that.

My app can't submit to the AppStore because I'm using Apple private framework. I don't know about Xcode 15 required but I also have M1 Pro so I don't want to make you hard work Can we talk on email or twitter (@avirok1)? Thank you for your quick replay and help

dmrschmidt commented 5 months ago

Sure, happy to continue conversation on twitter. Seems like I can't message you there however due to your privacy settings. I'm @dmrschmidt there, too.

So, I'm now finally on my laptop and wanted to have a closer look at the issue. And I guess I was simply led astray by the warning in the first screenshot. That doesn't actually cause the problem. The issue is, that WaveformImageView is iOS only. For macOS, the only currently supported utility views are SwiftUI. That's because WaveformImageView inherits from UIImageView. I'm not a macOS developer myself, so not sure what the equivalent there would be, but I assume that the approach would be equally straightforward for a lightweight subclass of NSImageView.

So all things considered, depending on your use case, I'd suggest you either just use images with WaveformImageDrawer directly, or you add your own small convenience NS[Image]View subclass around it. I wouldn't be surprised if the code translates almost 1:1 with only replacing UI for NS prefixes. If you have a look at WaveformImageView, it's really just a dead simple wrapper.

If your app requires any scrolling etc, it's not a great choice anyway, as it's not handling any caching and whatnot. It's designed to be a quick drop in for the majority of simple cases. Any more sophisticated use cases in table or scroll views etc should be implemented with WaveformImageDrawer.

dmrschmidt commented 5 months ago

Following up on our twitter conversation, to simulate a basic "speech sensitive" view, you could go with something like the following.

You need a WaveformRenderer that ignores the lastOffset to avoid the waveform from scrolling as new samples come in. This can be done easily via composing the existing LinearWaveformRenderer like so:

struct StaticWaveformRenderer: WaveformRenderer {
    let baseRenderer = LinearWaveformRenderer()

    func path(samples: [Float], with configuration: Waveform.Configuration, lastOffset: Int, position: Waveform.Position) -> CGPath {
        return baseRenderer.path(samples: samples, with: configuration, lastOffset: 0)
    }

    func render(samples: [Float], on context: CGContext, with configuration: Waveform.Configuration, lastOffset: Int, position: Waveform.Position) {
        baseRenderer.render(samples: samples, on: context, with: configuration, lastOffset: 0)
    }
}

Then all you need is to use that one in a narrowed-down WaveformLiveCanvas with strong damping on both side, like so:

WaveformLiveCanvas(
    samples: samples,
    configuration: configuration.with(damping: .init(percentage: 0.4, sides: .both)),
    renderer: StaticWaveformRenderer(),
    shouldDrawSilencePadding: true
)
.frame(width: 48, height: 32)

This will result in something like I'd already shared with you:

https://github.com/dmrschmidt/DSWaveformImage/assets/69365/6ffd9d91-2cd5-42bc-b6a1-9a6911cd61c7

rokach commented 5 months ago

Thank you so much Dennis! your support is awesome I definitely try it