ios - swift 2 : AVAssetReader and NSInputStream Audio Graph

标签 ios avfoundation swift2 nsinputstream avassetreader

我正在尝试转换 Bob McCune 的 Learning AVFoundation 一书中的示例,但在使用 AVAssetReader 和 NSInputStream 时遇到了一些问题。该图应该是一个纯正弦波,但这些值似乎以某种方式反射(reflect)在 X 轴上。

我已经尝试了所有我能想到的字节交换迭代,但都没有用。

Playground 在此处发布到 github: https://github.com/justinlevi/AVAssetReader

//: Playground - noun: a place where people can play

import UIKit
import AVFoundation
import XCPlayground

func plotArrayInPlayground<T>(arrayToPlot:Array<T>, title:String) {
  for currentValue in arrayToPlot {
    XCPCaptureValue(title, value: currentValue)
  }
}

class SSSampleDataFilter {
  var sampleData:NSData?

  init(data:NSData) {
    sampleData = data
  }

  func filteredSamplesForSize(size:CGSize) -> [Int]{
    var filterSamples = [UInt16]()

    if let sampleData = sampleData {
      let sampleCount = sampleData.length
      let binSize = CGFloat(sampleCount) / size.width

      let stream = NSInputStream(data: sampleData)
      stream.open()

      var readBuffer = Array<UInt8>(count: 16 * 1024, repeatedValue: 0)
      var totalBytesRead = 0

      let size = sizeof(UInt16)
      while (totalBytesRead < sampleData.length) {
        let numberOfBytesRead = stream.read(&readBuffer, maxLength: size)
        let u16: UInt16 = UnsafePointer<UInt16>(readBuffer).memory

        var sampleBin = [UInt16]()
        for _ in 0..<Int(binSize) {
          sampleBin.append(u16)
        }

        filterSamples.append(sampleBin.maxElement()!)
        totalBytesRead += numberOfBytesRead
      }

      //plotArrayInPlayground(filterSamples, title: "Samples")
    }

    return [0]

  }
}

let sineURL = NSBundle.mainBundle().URLForResource("440.0-sine", withExtension: "aif")!
let asset = AVAsset(URL: sineURL)
var assetReader:AVAssetReader

do{
  assetReader = try AVAssetReader(asset: asset)
}catch{
  fatalError("Unable to read Asset: \(error) : \(__FUNCTION__).")
}

let track = asset.tracksWithMediaType(AVMediaTypeAudio).first
let outputSettings: [String:Int] =
  [ AVFormatIDKey: Int(kAudioFormatLinearPCM),
    AVLinearPCMIsBigEndianKey: 0,
    AVLinearPCMIsFloatKey: 0,
    AVLinearPCMBitDepthKey: 16,
    AVLinearPCMIsNonInterleaved: 0]

let trackOutput = AVAssetReaderTrackOutput(track: track!, outputSettings: outputSettings)

assetReader.addOutput(trackOutput)
assetReader.startReading()

var sampleData = NSMutableData()

while assetReader.status == AVAssetReaderStatus.Reading {
  if let sampleBufferRef = trackOutput.copyNextSampleBuffer() {
    if let blockBufferRef = CMSampleBufferGetDataBuffer(sampleBufferRef) {
      let bufferLength = CMBlockBufferGetDataLength(blockBufferRef)
      var data = NSMutableData(length: bufferLength)
      CMBlockBufferCopyDataBytes(blockBufferRef, 0, bufferLength, data!.mutableBytes)
      var samples = UnsafeMutablePointer<Int16>(data!.mutableBytes)
      sampleData.appendBytes(samples, length: bufferLength)
      CMSampleBufferInvalidate(sampleBufferRef)
    }
  }
}

let view = UIView(frame: CGRectMake(0, 0, 375.0, 667.0))
//view.backgroundColor = UIColor.lightGrayColor()

if assetReader.status == AVAssetReaderStatus.Completed {
  print("complete")

  let filter = SSSampleDataFilter(data: sampleData)
  let filteredSamples = filter.filteredSamplesForSize(view.bounds.size)
}

//XCPShowView("Bezier Path", view: view)
XCPSetExecutionShouldContinueIndefinitely(true)

图表应该是这样的(取自 Audacity) Sine wave graph of audio file

这是 playground 中的图形

enter image description here

最佳答案

不幸的是,你的 Playground 在 Xcode7b5 中没有为我呈现任何东西,但是你要求 AVAssetReaderTrackOutput 给你签名的 16 位整数,但你的代码将它们视为未签名的 UInt16s(并且您的 Audacity 文件使用 float )。

在您的 playground 中将 UInt16 的所有实例更改为 Int16 似乎可以打印看起来合理的正弦数据。

关于ios - swift 2 : AVAssetReader and NSInputStream Audio Graph,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32148972/

相关文章:

ios - 更改 UISearchBar 中的取消按钮字体

iphone - 让 UIView 始终在应用程序的顶部?

swift - 拆分 AVMutableComposition 并导出为多个较小的组合

swift - iPhone X、iPhone XS 等相机变焦问题

ios - Swift 中的子类不继承其父类(super class)的初始化程序

ios - 我们可以使用自定义 iOS 应用程序中的 Alexa 技能吗?

ios - 可达性无法通过 swift 3 中的蜂窝连接进行连接

ios - AVAssetExportSession 在输出视频的右侧和底部给我一个绿色边框

ios - Swift 将具有特定格式的字符串转换为 NSDate

ios - .removeFromSuperview 不适用于 UIImageView