AVAudioPlayer трескается и появляется

У меня есть Simon-подобная игра памяти, в которой воспроизводится последовательность тонов, и пользователь пытается повторить тоны. Проблема в том, что время от времени я получаю ужасный, потрескивающий звук. Это может быть только после нескольких нот или целых двадцать. Звуки - это все файлы wav, длина которых составляет две секунды. Я прохожу через десять игроков, чтобы ни один из звуков не был обрезан. (Я пробовал до 50, но это ничего не помогло.) Я также попытался реализовать audioPlayerDidFinishPlaying, чтобы я мог остановить плеер после завершения звука, но это тоже не помогло. И, наконец, я добавил prepareToPlay() - к сожалению, никакой разницы.

Одна интересная проблема, которая может быть или не быть связана, заключается в том, что после последовательности из 15 заметок аудио перестает работать вместе. Приложение работает как обычно, но без звука.

Вот часть аудио кода:

func playSound(_ soundID: Int) {
        var soundName = ""

        switch soundID {
        case 0:
            soundName = "beep1"
        case 1:
            soundName = "beep2"
        case 2:
            soundName = "beep3"
        case 3:
            soundName = "beep4"
        case 4:
            soundName = "swish3"
        default:
            soundName = "clank"
        }

        guard let url = Bundle.main.url(forResource: soundName, withExtension: "wav") else { return }

        do {
            buttonSound.insert(try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.wav.rawValue), at: playerIndex)
            buttonSound[playerIndex].prepareToPlay()
            buttonSound[playerIndex].delegate = self

            if playerIndex < 10 {
                buttonSound[playerIndex].play()
                playerIndex += 1
            } else {
                buttonSound[playerIndex].play()
                playerIndex = 0
            }

        } catch {
            // error
        }
    }

    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        if flag {
            player.stop()
        }
    }

/******** ОБНОВЛЕНИЕ *********/

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

Вот класс для создания AVAudioPlayers по мере необходимости:

import UIKit
import AVFoundation

private var players: [AVAudioPlayer] = []

class AVAudioPlayerPool: NSObject {

    class func playerWithURL(url: URL) -> AVAudioPlayer? {

        let availablePlayers = players.filter { (player) -> Bool in
            return player.isPlaying == false && player.url == url
        }

        if let playerToUse = availablePlayers.first {
            playerToUse.prepareToPlay()
            return playerToUse
        }

        do {
            let newPlayer = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.wav.rawValue)
            players.append(newPlayer)
            newPlayer.prepareToPlay()
            return newPlayer

        } catch {
            return nil
        }
    }
}

Прослушивание звука прост:

func playSound(_ soundID: Int) {
    var soundName = ""

    switch soundID {
    case 0:
        soundName = "tt1"
    case 1:
        soundName = "tt2"
    case 2:
        soundName = "tt3"
    case 3:
        soundName = "tt4"
    case 4:
        soundName = "swish3"
    default:
        soundName = "clank"
    }

    guard let url = Bundle.main.url(forResource: soundName, withExtension: "wav") else { return }
    let player = AVAudioPlayerPool.playerWithURL(url: url)
    player?.play()

}

Если у кого-то есть мысли - даже если это просто следующий шаг, вы можете попробовать...

Ответ 1

После многих часов экспериментов я собираюсь сказать, что проблема была вызвана выбранным мной звуком - большим, пустым, прямоугольным звуком с реверберацией. Сначала я попытался уменьшить уровень мышления, которое могло бы помочь. Затем я пробовал всевозможные звуки, но все трещало. Я думаю, что это больше связано с тем, как я назначал игроков. Как только я исправил проблему с игроком, я не думал возвращаться и повторять разные звуки. До тех пор, пока я не... и это работает!

Ответ 2

По моему мнению, ваша основная проблема заключается в том, что звуковая нагрузка выполняется внутри той же функции, которая должна воспроизводить сам звук. Концептуально неправильно, чтобы вы могли воспроизводить звук так быстро, как можете, вы должны загружать раз и навсегда ваши звуки вне функции воспроизведения. Эта функция должна просто играть, и что она.

Ответ 3

Мы только что столкнулись с проблемой в нашей команде. В нашем случае искаженная звуковая ошибка может быть воспроизведена только, если приложение запущено на устройстве с прикрепленным отладчиком. Как только мы отсоединяем приложение от трещин отладчика, исчезают. Также похоже, что проблема впервые появилась в новом Xcode 9.2 (9C40b).