调节系统播放铃声的方案

需求背景:

最近有一个需求,需要新增一个系统铃声,并且可以支持调整铃声的大小。但是 iOS 系统其实是没有直接提供 API 来直接调整系统铃声的大小。我发现可以调整音频文件的声音大小,所以我们可以先调整 wav 文件的声音,然后再通过重复注册系统铃声,再通过注册的声音 id 进行播放就好了。

实现代码

调整 wav 文件音量的代码:

import Foundation
import AVFoundation

/// WAV 音频音量调节工具类
class DDWavVolumeAdjuster {
    
    /// 音量调节错误类型
    enum VolumeAdjustError: Error {
        case invalidURL
        case invalidFileFormat
        case readError
        case writeError
        case processingError
    }
    
    /// 调整 WAV 文件音量并生成新文件
    /// - Parameters:
    ///   - inputPath: 输入 WAV 文件路径
    ///   - outputPath: 输出 WAV 文件路径
    ///   - volumeMultiplier: 音量倍数 (0.0 ~ N.0,1.0 为原始音量)
    /// - Throws: VolumeAdjustError
    static func adjustVolume(inputURL: URL,
                             outputURL: URL,
                             volumeMultiplier: Float) throws {
        
        // 创建音频文件
        guard let audioFile = try? AVAudioFile(forReading: inputURL) else {
            throw VolumeAdjustError.invalidFileFormat
        }
        
        // 获取音频格式
        let format = audioFile.processingFormat
        let frameCount = UInt32(audioFile.length)
        
        // 创建 PCM 缓冲区
        guard let buffer = AVAudioPCMBuffer(pcmFormat: format,
                                            frameCapacity: frameCount) else {
            throw VolumeAdjustError.processingError
        }
        
        // 读取音频数据
        do {
            try audioFile.read(into: buffer)
        } catch {
            throw VolumeAdjustError.readError
        }
        
        // 调整音量
        if let floatChannelData = buffer.floatChannelData {
            let channelCount = Int(format.channelCount)
            let frameLength = Int(buffer.frameLength)
            
            for channel in 0..<channelCount {
                let channelData = floatChannelData[channel]
                for frame in 0..<frameLength {
                    channelData[frame] *= volumeMultiplier
                    
                    // 确保音频数据在有效范围内 (-1.0 到 1.0)
                    if channelData[frame] > 1.0 {
                        channelData[frame] = 1.0
                    } else if channelData[frame] < -1.0 {
                        channelData[frame] = -1.0
                    }
                }
            }
        }
        
        // 创建输出文件
        do {
            // 如果文件已存在,先删除
            try? FileManager.default.removeItem(at: outputURL)
            
            let outputFile = try AVAudioFile(
                forWriting: outputURL,
                settings: audioFile.fileFormat.settings
            )
            
            // 写入调整后的音频数据
            try outputFile.write(from: buffer)
        } catch {
            throw VolumeAdjustError.writeError
        }
    }
}

注册系统铃声:

// 播放器

    static var defaultSystemSoundID: SystemSoundID = 0

    class func setupSystemAudio() {
        
        if defaultSystemSoundID != 0 {
            AudioServicesRemoveSystemSoundCompletion(defaultSystemSoundID)
            defaultSystemSoundID = 0
        }
        
        let outputHitUrl = FileManager.appGroupSharedSupportDirectoryURL
            .appendingPathComponent(DingDingConstants.hitWAVFile, isDirectory: false)
        
        var soundID: SystemSoundID = 0
        AudioServicesCreateSystemSoundID(outputHitUrl as CFURL, &soundID)
        defaultSystemSoundID = soundID
        
        let completion: AudioServicesSystemSoundCompletionProc = { (soundID, _) in
            debugPrint("Sound \(soundID) finished playing!")
        }
        
        AudioServicesAddSystemSoundCompletion(soundID,
                                              CFRunLoopGetMain(),
                                              CFRunLoopMode.defaultMode.rawValue,
                                              completion,
                                              nil)
    }

播放系统声音:

        DispatchQueue.global().async {
            if 0 != StandardAudioFeedbackEngine.defaultSystemSoundID {
                AudioServicesPlaySystemSound(StandardAudioFeedbackEngine.defaultSystemSoundID)
            } else {
                AudioServicesPlaySystemSound(id)
            }
        }
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容