【问题标题】:Generating waveform from any music file ios从任何音乐文件 ios 生成波形
【发布时间】:2013-11-11 01:28:06
【问题描述】:

我正在寻找如何根据音乐绘制声波。

我想要这样的图片

这里有一些关于从音乐中显示 Waves 的讨论

  1. WaveForm on IOS
  2. rendering a waveform on an iphone
  3. audio waveform visualisation with iPhone

Github 示例链接

但对这种类型的wavefrom一无所知,是否可以绘制像这张图片一样的波浪?

【问题讨论】:

  • 您的图像似乎与实际波形没有任何关系。你在哪里看到的?
  • 我想像这样显示wavefrom。请检查这张图片,markhadleyuk.com/wp-content/uploads/2012/01/…
  • 没有关于如何生成与图像中的波形类似的波形的资源,因为它们是假的。歌曲的音频波形看起来不像那样。 OP 中的图像看起来像带有窗口函数的正弦波。您评论中的链接可能是带有低通滤波器的真实音频数据,但如果您在这里询问如何做到这一点,那就超出了您的范围。对不起。您发布的链接和网络上有大量信息。我不明白你想要什么答案。
  • 你可以参考这个stackoverflow.com/questions/5032775/…并且可以在生成图片代码时进行修改

标签: ios iphone signal-processing waveform wave


【解决方案1】:

过去三个月我也一直在真诚地尝试,但我没有找到解决方案。暂时我使用基于歌曲类型的静态图像(静态数据歌曲)。我将图像添加到UIScrollView,并根据音频的当前位置更改了contentOffset

【讨论】:

    【解决方案2】:

    免责声明:其中很多都是通过反复试验发现的,我在这里可能有一些严重的错误假设:

    您需要使用 AudioUnits 框架。初始化播放时,您可以创建一个 AURenderCallbackStruct。您可以在此结构中指定一个播放回调函数,该函数为您提供一些包含您需要的信息的参数。

    回调函数会有这样的签名:

    static OSStatus recordingCallback (void *inRefCon,
                                       AudioUnitRenderActionFlags *ioActionFlags,
                                       const AudioTimeStamp *inTimeStamp,
                                       UInt32 inBusNumber,
                                       UInt32 inNumberFrames,
                                       AudioBufferList *ioData) 
    

    这里有一个音频数据数组,可用于获取每个频点的音频缓冲区的幅度,或用于计算频点的 DB 值。

    我不知道该图显示的是什么,但在我看来,它就像是每个样本箱的幅度的平滑显示。

    音频单元并不简单,但值得玩一会儿,直到你掌握为止。

    这是我的回调函数的框架,因此您可以更好地理解我的意思:

    编辑:删除死链接,对不起,我丢失了这段代码

    【讨论】:

    • 如果您实时播放媒体这是正确的答案,您可以通过此回调获取正在输出的音频数据。
    【解决方案3】:

    根据上面的答案稍微重构一下

    
    import AVFoundation
    import CoreGraphics
    import Foundation
    import UIKit
    
    class WaveGenerator {
        private func readBuffer(_ audioUrl: URL) -> UnsafeBufferPointer<Float> {
            let file = try! AVAudioFile(forReading: audioUrl)
    
            let audioFormat = file.processingFormat
            let audioFrameCount = UInt32(file.length)
            guard let buffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: audioFrameCount)
            else { return UnsafeBufferPointer<Float>(_empty: ()) }
            do {
                try file.read(into: buffer)
            } catch {
                print(error)
            }
    
    //        let floatArray = Array(UnsafeBufferPointer(start: buffer.floatChannelData![0], count: Int(buffer.frameLength)))
            let floatArray = UnsafeBufferPointer(start: buffer.floatChannelData![0], count: Int(buffer.frameLength))
    
            return floatArray
        }
    
        private func generateWaveImage(
            _ samples: UnsafeBufferPointer<Float>,
            _ imageSize: CGSize,
            _ strokeColor: UIColor,
            _ backgroundColor: UIColor
        ) -> UIImage? {
            let drawingRect = CGRect(origin: .zero, size: imageSize)
    
            UIGraphicsBeginImageContextWithOptions(imageSize, false, 0)
    
            let middleY = imageSize.height / 2
    
            guard let context: CGContext = UIGraphicsGetCurrentContext() else { return nil }
    
            context.setFillColor(backgroundColor.cgColor)
            context.setAlpha(1.0)
            context.fill(drawingRect)
            context.setLineWidth(0.25)
    
            let max: CGFloat = CGFloat(samples.max() ?? 0)
            let heightNormalizationFactor = imageSize.height / max / 2
            let widthNormalizationFactor = imageSize.width / CGFloat(samples.count)
            for index in 0 ..< samples.count {
                let pixel = CGFloat(samples[index]) * heightNormalizationFactor
    
                let x = CGFloat(index) * widthNormalizationFactor
    
                context.move(to: CGPoint(x: x, y: middleY - pixel))
                context.addLine(to: CGPoint(x: x, y: middleY + pixel))
    
                context.setStrokeColor(strokeColor.cgColor)
                context.strokePath()
            }
            guard let soundWaveImage = UIGraphicsGetImageFromCurrentImageContext() else { return nil }
    
            UIGraphicsEndImageContext()
            return soundWaveImage
        }
    
        func generateWaveImage(from audioUrl: URL, in imageSize: CGSize) -> UIImage? {
            let samples = readBuffer(audioUrl)
            let img = generateWaveImage(samples, imageSize, UIColor.blue, UIColor.white)
            return img
        }
    }
    

    用法

    let url = Bundle.main.url(forResource: "TEST1.mp3", withExtension: "")!
    let img = waveGenerator.generateWaveImage(from: url, in: CGSize(width: 600, height: 200))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-08
      • 2012-11-16
      • 2013-03-30
      • 2018-11-27
      • 1970-01-01
      相关资源
      最近更新 更多