AudioToolbox / AudioUnits(AudioFileWriteBytes)在Swift中不可用?

时间:2015-08-02 11:59:56

标签: xcode swift

Apple的文档:

AudioToolbox框架参考&gt; <音频文件服务参考&gt;读取和写入音频文件&gt; AudioFileWriteBytes

Declaration Swift func AudioFileWriteBytes(_ inAudioFile: AudioFileID,
                   _ inUseCache: Boolean,
                   _ inStartingByte: Int64,
                   _ ioNumBytes: UnsafeMutablePointer<UInt32>,
                   _ inBuffer: UnsafePointer<Void>) -> OSStatus

XCode版本7.0 beta 4(7A165t)中的代码

audioErr = AudioFileWriteBytes(audioFile, false, Int64(sampleCount * 2), bytesToWriteMem, sampleMem as! UnsafePointer<Void>)

XCode的回应:

Cannot invoke 'AudioFileWriteBytes' with an argument list of type '(AudioFileID, Bool, Int64, UnsafeMutablePointer<UInt32>, UnsafePointer<Void>)'

有什么想法吗?

编辑: 感谢Martin R的回复,这是我的完整代码,我不明白为什么AudioFileWriteBytes调用会返回错误...:

import Foundation
import AudioToolbox
import Darwin
import AudioUnit
import CoreFoundation

extension Int {
    func format (f:String) -> String {
        return NSString(format:"%\(f)d", self) as String
    }
}


let SAMPLE_RATE:Float64 = 44100                             // 1
let DURATION = 0.1                                          // 2
// #define FILENAME_FORMAT @"%0.3f-square.aif"                 3 skipped

if (Process.arguments.count < 2) {
    print("Usage: CAToneFileGenerator n\n(where n is tone in Hz)")
    exit(0)
}

var hz:Double = atof(Process.arguments[1])                  // 4 (atof convert ASCII string to double)
assert(hz > 0)
print("generating \(hz) tone")
var fileName:String = String(format:"%d-square.aif", hz)    // 5
var filePath:String = NSFileManager.defaultManager().currentDirectoryPath.stringByAppendingPathComponent(fileName)
var fileURL:NSURL = NSURL.fileURLWithPath(filePath)     // the Audio File Services functions take URLs, not file paths

// Prepare the format

var asbd = AudioStreamBasicDescription()                    // 6
memset(&asbd, 0, sizeof(AudioStreamBasicDescription))       // 7
asbd.mSampleRate = SAMPLE_RATE                              // 8
asbd.mFormatID = AudioFormatID(kAudioFormatLinearPCM)
asbd.mFormatFlags = AudioFormatFlags(kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked)
asbd.mBitsPerChannel = 16
asbd.mChannelsPerFrame = 1
asbd.mFramesPerPacket = 1
asbd.mBytesPerFrame = 2
asbd.mBytesPerPacket = 2

// Set up the file

var audioFile:AudioFileID = AudioFileID()
var audioErr:OSStatus = noErr
audioErr = AudioFileCreateWithURL(fileURL,                  // 9
                                  AudioFileTypeID(kAudioFileAIFFType),
                                  &asbd,
                                  .EraseFile,
                                  &audioFile)

// 1 -> AudioFileFlags(kAudioFileFlags_EraseFile)
assert(audioErr == noErr)

// Start writing samples

var maxSampleCount:CLong = CLong(SAMPLE_RATE * DURATION)    // 10
var sampleCount:CLong = 0

var bytesToWrite:UInt32 = 2
/*
var bytesToWriteMem = UnsafeMutablePointer<UInt32>.alloc(1)
bytesToWriteMem.initialize(bytesToWrite)
*/
var wavelengthInSamples:Double = SAMPLE_RATE / hz           // 11

var sample:UInt16
//var sampleMem = UnsafeMutablePointer<UInt16>.alloc(1)
//sampleMem.initialize(sample)


while sampleCount < maxSampleCount {
    for i in 0..<Int(wavelengthInSamples) {
        // Square wave
        if ( i < Int(wavelengthInSamples/2)) {              // 12
            sample = UInt16.max                             // 13
        } else {
            sample = UInt16.min
        }

        //let bytesToWrite2 = bytesToWrite
        audioErr = AudioFileWriteBytes(audioFile,           // 14
                                       false,
                                       Int64(sampleCount * 2),
                                       &bytesToWrite,               //UnsafeMutablePointer<UInt32>
                                       &sample)                     //UnsafePointer<Void>
        assert(audioErr == noErr)
        sampleCount++                                       // 15

    }
}
/*
bytesToWriteMem.destroy()
bytesToWriteMem.dealloc(1)
sampleMem.destroy()
sampleMem.dealloc(1)
*/
audioErr = AudioFileClose(audioFile)                        // 16
assert(audioErr == noErr)
print("wrote \(sampleCount) samples")

1 个答案:

答案 0 :(得分:2)

这很难找到,因为错误消息根本没有帮助。 问题是AudioFileWriteBytes()的第二个参数的类型是Boolean,而不是Bool

audioErr = AudioFileWriteBytes(audioFile,
            Boolean(0), // <--- HERE
            Int64(sampleCount * 2),
            &bytesToWrite,
            &sample)

有关BooleanBool之间差异的详细信息 例如,见Type 'Boolean' does not conform to protocol 'BooleanType'

更新: Swift 2 / Xcode 7 开始,映射了Mac类型Boolean 到了Swift Bool,所以你现在必须通过falsetrue

audioErr = AudioFileWriteBytes(audioFile,
            false, // <--- HERE
            Int64(sampleCount * 2),
            &bytesToWrite,
            &sample)
相关问题