Генерация формы волны из любого музыкального файла ios

Ищу, как нарисовать звуковые волны в соответствии с музыкой.

Я хочу такие волны, как это изображение

введите описание изображения здесь

вот обсуждение отображения волн из музыки

  1. WaveForm в IOS
  2. рендеринг формы волны на iphone
  3. визуализация звуковой волны с помощью iPhone

Примеры ссылок на Github

Но, не имея представления об этом типе волн, можно ли нарисовать волны, подобные этому изображению?


person Vishal Khatri    schedule 31.10.2013    source источник
comment
Ваше изображение не имеет никакого отношения к реальной форме волны. Где ты это видишь?   -  person    schedule 31.10.2013
comment
я хочу отображать wavefrom вот так. Проверьте это изображение, markhadleyuk.com/wp-content / uploads / 2012/01 /   -  person Vishal Khatri    schedule 11.11.2013
comment
Нет ресурсов о том, как сгенерировать сигнал, подобный тем, что на ваших изображениях, потому что они поддельные. Форма звуковой волны из песни на это не похожа. Изображение в вашем OP выглядит как синусоидальные волны с оконной функцией. Ссылка в вашем комментарии может быть настоящими аудиоданными с фильтром нижних частот, но если вы здесь спрашиваете, как это сделать, то это далеко не у вас. Прости. В размещенных вами ссылках и в Интернете содержится множество информации. Я не понимаю, что вы хотите от ответа.   -  person Radiodef    schedule 12.11.2013
comment
вы можете сослаться на этот stackoverflow.com/questions/5032775/ и может вносить изменения в генерацию кода изображения   -  person S S    schedule 13.11.2013


Ответы (3)


Заявление об ограничении ответственности: многое из этого было обнаружено методом проб и ошибок, у меня могут быть серьезные ложные предположения:

Вам нужно будет использовать структуру AudioUnits. При инициализации воспроизведения вы можете создать AURenderCallbackStruct. Вы можете указать в этой структуре функцию обратного вызова воспроизведения, которая предоставляет вам несколько аргументов, которые будут содержать необходимую информацию.

функция обратного вызова будет иметь такую ​​подпись:

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

Здесь есть массив аудиоданных, которые можно использовать для получения амплитуды звукового буфера для каждого частотного бина или для вычисления значения DB для частотного бина.

Я не знаю, что показывает этот график, но мне он кажется сглаженным отображением амплитуд каждой из выборок.

Аудиоустройства не просты, но с ними стоит поиграть, пока вы не освоитесь.

Вот скелет моей функции обратного вызова, чтобы вы могли лучше понять, что я имею в виду:

РЕДАКТИРОВАТЬ: удалена мертвая ссылка, я потерял этот код, извините

person JConway    schedule 10.11.2013
comment
Если вы воспроизводите мультимедиа в реальном времени, это правильный ответ, вы можете получить аудиоданные, выводимые через этот обратный вызов. - person keji; 13.06.2014

Я тоже искренне пытался последние три месяца, но не нашел решения. Пока что я использовал статические изображения в зависимости от типа песни (песни со статическими данными). Я добавил изображения в UIScrollView и изменил contentOffset в зависимости от текущей позиции аудио.

person Tendulkar    schedule 31.10.2013

Немного рефакторинга из приведенных выше ответов


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))
person Learner    schedule 01.07.2021