从任何音乐文件 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 生成波形的主要内容,如果未能解决你的问题,请参考以下文章