从任何音乐文件 ios 生成波形

Posted

技术标签:

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

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

我想要这样的图片

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

    WaveForm on ios rendering a waveform on an iphone audio waveform visualisation with iPhone

Github 示例链接

https://github.com/gyetvan-andras/cocoa-waveform https://github.com/benalavi/waveform https://github.com/JingWZ/WaveView https://github.com/gyetvan-andras/cocoa-waveform https://github.com/ioslovers/ATTabandHoldAudioRecord https://github.com/hezone/ECGWavesPlayer https://github.com/iluvcapra/JHWaveform

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

【问题讨论】:

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

【讨论】:

以上是关于从任何音乐文件 ios 生成波形的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flash 中创建一个音乐播放器来创建音频文件的波形?

flash导入mp3怎么弄???

那种边播放音乐边把音乐的波形显示出来的软件叫啥?

iOS 录音及播放 音波图波形

用Java获取音频文件的波形

如何将音乐添加到媒体 iOS [关闭]