Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create Waves Visulization Song Swift

Here is what I am trying to do:

Screen Shot

The screenshot is taken from a 6s iPhone.

Screen Shot

I have been working in AVAudioPlayer and I would like to draw a waveform which looks look like the first screenshot. I am using FDWAVEFORMVIEW Github pods to draw waves. but I m confused how to draw same waves.

Code:

 @IBOutlet weak var soundWaveView: FDWaveformView!

  func createSoundWave() {
    soundWaveView.delegate = self
    soundWaveView.alpha = 0.0
    soundWaveView.audioURL = mainTrackURL
    soundWaveView.zoomSamples = 0 ..< soundWaveView.totalSamples / 3
    soundWaveView.doesAllowScrubbing = true
    soundWaveView.doesAllowStretch = true
    soundWaveView.doesAllowScroll = true
    soundWaveView.wavesColor = .lightGray
    soundWaveView.progressColor = UIColor.init(red: 46/255, green: 188/255, blue: 191/255, alpha: 1.0)
}

func waveformViewWillRender(_ waveformView: FDWaveformView) {
    startRendering = Date()
}

func waveformViewDidRender(_ waveformView: FDWaveformView) {
    endRendering = Date()
    NSLog("FDWaveformView rendering done, took %0.3f seconds", endRendering.timeIntervalSince(startRendering))
    profileResult.append(String(format: " render %0.3f ", endRendering.timeIntervalSince(startRendering)))
    UIView.animate(withDuration: 0.25, animations: {() -> Void in
        waveformView.alpha = 1.0
    })
}  

func waveformViewWillLoad(_ waveformView: FDWaveformView) {
    startLoading = Date()
}

func waveformViewDidLoad(_ waveformView: FDWaveformView) {
    endLoading = Date()
    NSLog("FDWaveformView loading done, took %0.3f seconds", endLoading.timeIntervalSince(startLoading))
    profileResult.append(String(format: " load %0.3f ", endLoading.timeIntervalSince(startLoading)))
}

Question: How to show the same waves as the original image(first screenshot)?

Can someone please explain to me how to draw same, I've tried to draw these waves but no results yet.

Any help would be greatly appreciated.

Thanks in advance.

like image 351
Sam Avatar asked Aug 26 '19 06:08

Sam


1 Answers

Ah, waveform drawing... From the looks of it, you're probably going to need to fork this and make your changes, because the FDWaveformRenderOperation doesn't support this style.

It looks like you can modify the plotWaveformGraph method in FDWaveformRenderOperation to achieve this. Currently, it iterates over every sample in the buffer, but if instead, you maintain an index that's incremented every nth sample (the bar "width") plus the bar "spacing," you can get this appearance. This is a naive approach, to be clear. Ideally, you'd average the samples in a "bar" and draw that value.

This is NOT compiling code, but should give you a place to start.

let barWidth: CGFloat = 2.0
let barSpacing: CGFloat = 2.0

var x = 0
while x < samples.count { {
   let sample = samples[x]
   let height = (sample - min) * sampleDrawingScale
   context.move(to: CGPoint(x: CGFloat(x), y: verticalMiddle - height))
   context.addLine(to: CGPoint(x: CGFloat(x), y: verticalMiddle + height))
   context.setLineWidth(barWidth) // note: stroke width straddles the path, so play with this
   context.strokePath();
   x += barWidth + barSpacing
}

Humble plug, but you can see how I do this in my waveform drawing framework. This is generally proof of concept and unoptimized. :)

like image 194
Corey W. Avatar answered Oct 17 '22 20:10

Corey W.