swift 在Apple CoreAudio中播放固定频率正弦波时音调发生变化

lsmepo6l  于 2023-03-07  发布在  Swift
关注(0)|答案(1)|浏览(142)

谢谢你阅读我的问题。
我当时正在使用Apple CoreAudio真实的渲染一个简单的440Hz正弦波,在渲染的前128秒,我还能听到好听的440Hz正弦波,但128秒后,声音的音调突然变低,然后,在播放256秒后,声音的音调变得高于440Hz,最后,当播放时间达到512秒时,声音就听不见了。2下面的代码是我运行的。3这个代码和下面网站上写的代码相似。4(虽然是日语)
Website that I saw

import SwiftUI
import AVFoundation

var player = Player(engine: &box)

@main
struct MyApp: App {
    init() {
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord)
            let ioBufferDuration = 128.0 / 44100.0
            try AVAudioSession.sharedInstance().setPreferredIOBufferDuration(ioBufferDuration)
        } catch {
            assertionFailure("AVAudioSession setup error: \(error)")
        }
    }
    
    var body: some Scene {
        WindowGroup {
            MyView()
        }
    }
}
import Foundation
import AVFoundation

class Player {
    var audioUnit: AudioUnit?
    var audioEngine: AVAudioEngine = AVAudioEngine()
    var sampleRate: Float = 440.0
    var time: Float = 0
    var deltaTime: Float = 0
    var mainMixer: AVAudioMixerNode?
    var outputNode: AVAudioOutputNode?
    var format: AVAudioFormat?
    var engine: Box?

    private lazy var sourceNode = AVAudioSourceNode { (_, _, frameCount, outputData) -> OSStatus in
        let ablPointer = UnsafeMutableAudioBufferListPointer(outputData)
        for frame in 0..<Int(frameCount) {
            let sampleVal = sin(440.0 * 2.0 * Float(Double.pi) * self.time)
            self.time += self.deltaTime
            for buffer in ablPointer {
                let buf: UnsafeMutableBufferPointer<Float> = UnsafeMutableBufferPointer(buffer)
                buf[frame] = sampleVal
            }
        }
        return noErr
    }

    init(engine: inout Box) {
        mainMixer = audioEngine.mainMixerNode
        outputNode = audioEngine.outputNode
        format = outputNode!.inputFormat(forBus: 0)
        sampleRate = Float(format!.sampleRate)
        deltaTime = 1 / Float(sampleRate)
        
        self.engine = engine

        let inputFormat = AVAudioFormat(commonFormat: format!.commonFormat, sampleRate: Double(sampleRate), channels: 1, interleaved: format!.isInterleaved)
        audioEngine.attach(sourceNode)
        audioEngine.connect(sourceNode, to: mainMixer!, format: inputFormat!)
        audioEngine.connect(mainMixer!, to: outputNode!, format: nil)
        mainMixer?.outputVolume = 1
    }

    func start() {
        do {
            try audioEngine.start()
        } catch {
            fatalError("Coud not start engine: \(error.localizedDescription)")
        }
    }

    func stop() {
        audioEngine.stop()
    }
}
nimxete2

nimxete21#

您的Floattime超出精度范围。请将其转换为Double,以便以后出现相同的问题,或者将self.time替换为使用已处理样本数的表达式:

var sampleCount: Int64 = 0  // instance variable

// in sourceNode callback:
let sampleVal = sin(440.0 * 2.0 * Double.pi * Double(sampleCount) / Double(sampleRate) )
sampleCount += 1

相关问题