2016-12-29 13 views
2

Я не могу понять, как я должен использовать UnsafeMutablePointer в Swift 3. Особенно в AURenderCallback.UnsafeMutablePointer в AURenderCallback

Стараюсь ниже код:

import Foundation 
import AudioToolbox 

let sineFrequency = 880.0 

// MARK: User data struct 
struct SineWavePlayer { 
    var outputUnit: AudioUnit? = nil 
    var startingFrameCount: Double = 0 
} 

// MARK: Callback function 
let SineWaveRenderProc: AURenderCallback = {(inRefCon, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData) -> OSStatus in 

    var player = UnsafeMutablePointer<SineWavePlayer>(inRefCon) 


    var j = player.pointee.startingFrameCount 
    let cycleLength = 44100/sineFrequency 

    for frame in 0..<inNumberFrames { 
     var buffers = UnsafeMutableAudioBufferListPointer(ioData) 

     UnsafeMutablePointer<Float32>(buffers[0].mData)[Int(frame)] = Float32(sin(2 * M_PI * (j/cycleLength))) 
     UnsafeMutablePointer<Float32>(buffers[1].mData)[Int(frame)] = Float32(sin(2 * M_PI * (j/cycleLength))) 

     // Or iterate through array: 
//  for buffer in buffers { 
//   UnsafeMutablePointer<Float32>(buffer.mData)[Int(frame)] = Float32(sin(2 * M_PI * (j/cycleLength))) 
//  } 

     j++ 
     if j > cycleLength { 
      j -= cycleLength 
     } 
    } 

    player.pointee.startingFrameCount = j 
    return noErr 
} 

// MARK: Utility function 
func CheckError(_ error: OSStatus, operation: String) { 
    guard error != noErr else { 
     return 
    } 

    var result: String = "" 
    var char = Int(error.bigEndian) 

    for _ in 0..<4 { 
     guard isprint(Int32(char&255)) == 1 else { 
      result = "\(error)" 
      break 
     } 
     result.append(String(describing: UnicodeScalar(char&255))) 
     char = char/256 
    } 

    print("Error: \(operation) (\(result))") 

    exit(1) 
} 

func CreateAndConnectOutputUnit(_ player: inout SineWavePlayer) { 
    // Generate a description that matches the output device (speakers) 
    var outputcd = AudioComponentDescription(componentType: kAudioUnitType_Output, componentSubType: kAudioUnitSubType_DefaultOutput, componentManufacturer: kAudioUnitManufacturer_Apple, componentFlags: 0, componentFlagsMask: 0) 

    let comp = AudioComponentFindNext(nil, &outputcd) 

    if comp == nil { 
     print("Can't get output unit") 
     exit(-1) 
    } 

    CheckError(AudioComponentInstanceNew(comp!, &player.outputUnit), 
     operation: "Couldn't open component for outputUnit") 

    // Register the render callback 
    var input = AURenderCallbackStruct(inputProc: SineWaveRenderProc, inputProcRefCon: &player) 

    CheckError(AudioUnitSetProperty(player.outputUnit!, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, UInt32(MemoryLayout<AURenderCallbackStruct>.size)), 
     operation: "AudioUnitSetProperty failed") 

    // Initialize the unit 
    CheckError(AudioUnitInitialize(player.outputUnit!), 
     operation: "Couldn't initialize output unit") 
} 

func main() { 
    var player = SineWavePlayer() 

    // Set up output unit and callback 
    CreateAndConnectOutputUnit(&player) 

    // Start playing 
    CheckError(AudioOutputUnitStart(player.outputUnit!), 
     operation: "Couldn't start output unit") 

    // Play for 5 seconds 
    sleep(5) 

    // Clean up 
    AudioOutputUnitStop(player.outputUnit!) 
    AudioUnitUninitialize(player.outputUnit!) 
    AudioComponentInstanceDispose(player.outputUnit!) 
} 

main() 

Но эта строка кода

var player = UnsafeMutablePointer<SineWavePlayer>(inRefCon) 

не работает. Как перевести эту строку в Swift 3?

Пожалуйста, помогите мне.

+0

Вы можете использовать тот же подход, что и в http://stackoverflow.com/a/30788165/1187415. –

+0

@MartinR, 'SineWavePlayer' является структурой, поэтому такой же подход не будет работать. – OOPer

+0

@OOPer: refcon - это указатель, поэтому создание 'SineWavePlayer' класса имеет смысл в любом случае. –

ответ

4

В Swift 3 инициализаторы не могут использоваться для преобразования типов указателей. В вашем случае тип inRefCon - UnsafeMutableRawPointer, поэтому вам необходимо использовать метод assumingMemoryBound(to:).

И еще один адрес player, переданный на обратный вызов, должен быть стабильным во время воспроизведения звука, адреса, взятые из аргументов inout (указанных в префиксе &), не удовлетворяют этому требованию.

две вещи выше фиксированы, ваш код будет выглядеть примерно так:

import Foundation 
import AudioToolbox 

let sineFrequency = 880.0 

// MARK: User data struct 
struct SineWavePlayer { 
    var outputUnit: AudioUnit? = nil 
    var startingFrameCount: Double = 0 
} 

// MARK: Callback function 
let SineWaveRenderProc: AURenderCallback = {(inRefCon, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData) -> OSStatus in 

    var player = inRefCon.assumingMemoryBound(to: SineWavePlayer.self) 


    var j = player.pointee.startingFrameCount 
    let cycleLength = 44100/sineFrequency 

    for frame in 0..<inNumberFrames { 
     var buffers = UnsafeMutableAudioBufferListPointer(ioData) 

     buffers?[0].mData?.assumingMemoryBound(to: Float32.self)[Int(frame)] = Float32(sin(2 * M_PI * (j/cycleLength))) 
     buffers?[1].mData?.assumingMemoryBound(to: Float32.self)[Int(frame)] = Float32(sin(2 * M_PI * (j/cycleLength))) 

     j += 1 
     if j > cycleLength { 
      j -= cycleLength 
     } 
    } 

    player.pointee.startingFrameCount = j 
    return noErr 
} 

// MARK: Utility function 
func CheckError(_ error: OSStatus, operation: String) { 
    guard error != noErr else { 
     return 
    } 

    var result: String = "" 
    var char = Int(error.bigEndian) 

    for _ in 0..<4 { 
     guard isprint(Int32(char&255)) == 1 else { 
      result = "\(error)" 
      break 
     } 
     result.append(String(describing: UnicodeScalar(char&255))) 
     char = char/256 
    } 

    print("Error: \(operation) (\(result))") 

    exit(1) 
} 

func CreateAndConnectOutputUnit(_ playerPtr: UnsafeMutablePointer<SineWavePlayer>) { 
    // Generate a description that matches the output device (speakers) 
    var outputcd = AudioComponentDescription(componentType: kAudioUnitType_Output, componentSubType: kAudioUnitSubType_DefaultOutput, componentManufacturer: kAudioUnitManufacturer_Apple, componentFlags: 0, componentFlagsMask: 0) 

    let comp = AudioComponentFindNext(nil, &outputcd) 

    if comp == nil { 
     print("Can't get output unit") 
     exit(-1) 
    } 

    CheckError(AudioComponentInstanceNew(comp!, &playerPtr.pointee.outputUnit), 
       operation: "Couldn't open component for outputUnit") 

    // Register the render callback 
    var input = AURenderCallbackStruct(inputProc: SineWaveRenderProc, inputProcRefCon: playerPtr) 

    CheckError(AudioUnitSetProperty(playerPtr.pointee.outputUnit!, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, UInt32(MemoryLayout<AURenderCallbackStruct>.size)), 
       operation: "AudioUnitSetProperty failed") 

    // Initialize the unit 
    CheckError(AudioUnitInitialize(playerPtr.pointee.outputUnit!), 
       operation: "Couldn't initialize output unit") 
} 

func main() { 
    let playerPtr = UnsafeMutablePointer<SineWavePlayer>.allocate(capacity: 1) 
    defer {playerPtr.deallocate(capacity: 1)} 
    playerPtr.initialize(to: SineWavePlayer()) 
    defer {playerPtr.deinitialize()} 

    // Set up output unit and callback 
    CreateAndConnectOutputUnit(playerPtr) 

    // Start playing 
    CheckError(AudioOutputUnitStart(playerPtr.pointee.outputUnit!), 
       operation: "Couldn't start output unit") 

    // Play for 5 seconds 
    sleep(5) 

    // Clean up 
    AudioOutputUnitStop(playerPtr.pointee.outputUnit!) 
    AudioUnitUninitialize(playerPtr.pointee.outputUnit!) 
    AudioComponentInstanceDispose(playerPtr.pointee.outputUnit!) 
} 
+0

Спасибо! Теперь я понимаю. Теперь все в порядке! – Ruslan

 Смежные вопросы

  • Нет связанных вопросов^_^