2015-10-23 5 views
2

я сумел настроек уже перевести этот код, чтобы вынести обратный вызов вызывается: http://www.cocoawithlove.com/2010/10/ios-tone-generator-introduction-to.htmlПеревести Цель - C Введение в AudioUnits в Swift

Я уверен, что мой метод отрисовки обратного вызова не прав реализован, потому что я либо получить никакого звука вообще или я получаю довольно ужасный шум из моих наушников. Я также не вижу связи между моей аудиосессией в viewDidLoad и остальной частью кода.

Есть ли кто-нибудь, кто может мне помочь?

private func performRender(
inRefCon: UnsafeMutablePointer<Void>, 
ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>, 
inTimeStamp: UnsafePointer<AudioTimeStamp>, 
inBufNumber: UInt32, 
inNumberFrames: UInt32, 
ioData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus 
{ 

// get object 
let vc = unsafeBitCast(inRefCon, ViewController.self) 
print("callback") 

let thetaIncrement = 2.0 * M_PI * vc.kFrequency/vc.kSampleRate 
var theta = vc.theta 

// var sinValues = [Int32]() 
let amplitude : Double = 0.25 

let abl = UnsafeMutableAudioBufferListPointer(ioData) 
    for buffer in abl 
    { 
     let val : Int32 = Int32((sin(theta) * amplitude)) 
    //  sinValues.append(val) 
     theta += thetaIncrement 

     memset(buffer.mData, val, Int(buffer.mDataByteSize)) 
    } 

vc.theta = theta 

return noErr 
} 

class ViewController: UIViewController 
{ 
let kSampleRate : Float64 = 44100 
let kFrequency : Double = 440 
var theta : Double = 0 

private var toneUnit = AudioUnit() 
private let kInputBus = AudioUnitElement(1) 
private let kOutputBus = AudioUnitElement(0) 

@IBAction func tooglePlay(sender: UIButton) 
{ 
    if(toneUnit != nil) 
    { 
     AudioOutputUnitStop(toneUnit) 
     AudioUnitInitialize(toneUnit) 
     AudioComponentInstanceDispose(toneUnit) 
     toneUnit = nil 
    } 
    else 
    { 
     createToneUnit() 
     var err = AudioUnitInitialize(toneUnit) 
     assert(err == noErr, "error initializing audiounit!") 
     err = AudioOutputUnitStart(toneUnit) 
     assert(err == noErr, "error starting audiooutput unit!")  
    } 
} 

func createToneUnit() 
{ 
    var defaultOutputDescription = AudioComponentDescription(
     componentType: kAudioUnitType_Output, 
     componentSubType: kAudioUnitSubType_RemoteIO, 
     componentManufacturer: kAudioUnitManufacturer_Apple, 
     componentFlags: 0, 
     componentFlagsMask: 0) 

    let defaultOutput = AudioComponentFindNext(nil,&defaultOutputDescription) 


    let fourBytesPerFloat : UInt32 = 4 
    let eightBitsPerByte : UInt32 = 8 

    var err = AudioComponentInstanceNew(defaultOutput, &toneUnit) 
    assert(err == noErr, "error setting audio component instance!") 
    var input = AURenderCallbackStruct(inputProc: performRender,  inputProcRefCon: UnsafeMutablePointer(unsafeAddressOf(self))) 

    err = AudioUnitSetProperty(toneUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, kOutputBus, &input, UInt32(sizeof(AURenderCallbackStruct))) 
    assert(err == noErr, "error setting render callback!") 

    var streamFormat = AudioStreamBasicDescription(
     mSampleRate: kSampleRate, 
     mFormatID: kAudioFormatLinearPCM, 
     mFormatFlags: kAudioFormatFlagsNativeFloatPacked, 
     mBytesPerPacket: fourBytesPerFloat, 
     mFramesPerPacket: 1, 
     mBytesPerFrame: fourBytesPerFloat, 
     mChannelsPerFrame: 1, 
     mBitsPerChannel: fourBytesPerFloat*eightBitsPerByte, 
     mReserved: 0) 

    err = AudioUnitSetProperty(toneUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &streamFormat, UInt32(sizeof(AudioStreamBasicDescription))) 
    assert(err == noErr, "error setting audiounit property!") 
} 

override func viewDidLoad() 
{ 
    super.viewDidLoad() 
    let audioSession = AVAudioSession.sharedInstance() 

    do 
    { 
     try audioSession.setCategory(AVAudioSessionCategoryPlayback) 
    } 
    catch 
    { 
     print("Audio session setCategory failed") 
    } 

    do 
    { 
     try audioSession.setPreferredSampleRate(kSampleRate) 
    } 
    catch 
    { 
     print("Audio session samplerate error") 
    } 

    do 
    { 
     try audioSession.setPreferredIOBufferDuration(0.005) 
    } 
    catch 
    { 
     print("Audio session bufferduration error") 
    } 

    do 
    { 
     try audioSession.setActive(true) 
    } 
    catch 
    { 
     print("Audio session activate failure") 
    } 
} 
+0

Спасибо, что задали этот вопрос, я искал тот же код, и он спас меня от преобразования Swift самостоятельно :) – Ash

+0

да, я закончил использовать цель c для такой задачи низкого уровня. Я согласился с тем, что быстрый выбор для этого не является хорошим выбором. – bob

ответ

0
  • vc.theta не инкрементируется
  • memset занимает всего стоит БАЙТОМ о val
  • AudioUnit ожидает float с, но вы храните Int32 сек
  • диапазон аудио данные выглядят смешно - почему бы не сохранить их в диапазоне [-1, 1]?
  • нет необходимости ограничивать theta либо, sin может сделать это хорошо.

Вы уверены, что это работало в объективе-c?

+0

Да, 32767 не должен был быть там. Первым и последним пунктом были также хорошие намеки ^^. Но memset ожидает Int32, поэтому я должен использовать memset для этого? Код object-c работает нормально. Я загрузил проект Xcode с веб-сайта, упомянутого выше. – bob

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

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