Swift iOS,使用 AVAudioPlayer 从数组中顺序播放曲目,每个曲目之间有一些功能?
Swift iOS, Play tracks sequentially from array using AVAudioPlayer, with some function in between each track?
我有一组音频指令,我想随机化、播放(一次一个),并在每条指令之间做一些数据记录。
使用下面的代码,我有一个触发 beginTest() 的按钮按下,但指令轨道同时播放。它永远不会到达 startRecord()。
我试过将 startRecord() 放在 audioPlayerDidFinishPlaying 中;在这种情况下,它确实会到达第一首曲目的 startRecord(),但不会继续到调用 playScript() 的 beginTest() 内循环的下一次迭代。
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool)
{
self.player = nil
print("finished playing this file")
}
func playScript(c: String)
{
let path = Bundle.main.path(forResource: c, ofType:"m4a")!
let url = URL(fileURLWithPath: path)
do {
self.player = try AVAudioPlayer(contentsOf: url)
self.player?.delegate = self
self.player?.play()
print(c)
print("playing script for " + c)
} catch {
print("couldn't load script")
}
}
func beginTest()
{
for c in conditions.shuffled()
{
playScript(c: c)
if self.player == nil
{
startRecord()
print("started data recording")
}
}
exportData()
}
我猜 beginTest() 在 audioPlayerDidFinishPlaying 将播放器重置为 nil 之前一直沿着 for 循环移动,但我不知道如何停止它。
使用audioPlayerDidFinishPlaying(_:,successfully:)
的方法是正确的。在您的代码中,当您调用 playScript(c:)
时,您将遍历 conditions
数组中的所有音频文件并在播放第一个音频时非常快速地调用 startRecord
方法。所有声音将被放入一个队列中并一个一个地播放。我不知道 startRecord
方法的内容,但我不认为应该这样调用它。
为了避免这些问题,您需要调用 playScript(c:)
然后等待方法 startRecord()
完成,然后再次调用 playScript(c:)
。所以你可以尝试这样的事情:
import AVFoundation
class SomeClass: NSObject, AVAudioPlayerDelegate {
var player: AVAudioPlayer?
var conditions = [String]()
var instructions: [() -> ()] = []
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
print("finished playing \(player.url)")
startRecord {
playNextInstruction()
}
}
func playScript(c: String)
{
let path = Bundle.main.path(forResource: c, ofType:"m4a")!
let url = URL(fileURLWithPath: path)
do {
self.player = try AVAudioPlayer(contentsOf: url)
self.player?.delegate = self
self.player?.play()
print(c)
print("playing script for " + c)
} catch {
print("couldn't load script")
}
}
func beginTest() {
instructions = conditions.shuffled().map { [unowned self] condition in
return {
self.playScript(c: condition)
}
}
playNextInstruction()
}
func playNextInstruction() {
if instructions.count != 0 {
instructions.remove(at: 0)()
} else {
exportData()
}
}
func exportData() {
}
func startRecord(completion: (() -> ())) {
}
}
如果它不起作用,那么我建议尝试在您的代码中的其他地方搜索问题。
我有一组音频指令,我想随机化、播放(一次一个),并在每条指令之间做一些数据记录。
使用下面的代码,我有一个触发 beginTest() 的按钮按下,但指令轨道同时播放。它永远不会到达 startRecord()。
我试过将 startRecord() 放在 audioPlayerDidFinishPlaying 中;在这种情况下,它确实会到达第一首曲目的 startRecord(),但不会继续到调用 playScript() 的 beginTest() 内循环的下一次迭代。
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool)
{
self.player = nil
print("finished playing this file")
}
func playScript(c: String)
{
let path = Bundle.main.path(forResource: c, ofType:"m4a")!
let url = URL(fileURLWithPath: path)
do {
self.player = try AVAudioPlayer(contentsOf: url)
self.player?.delegate = self
self.player?.play()
print(c)
print("playing script for " + c)
} catch {
print("couldn't load script")
}
}
func beginTest()
{
for c in conditions.shuffled()
{
playScript(c: c)
if self.player == nil
{
startRecord()
print("started data recording")
}
}
exportData()
}
我猜 beginTest() 在 audioPlayerDidFinishPlaying 将播放器重置为 nil 之前一直沿着 for 循环移动,但我不知道如何停止它。
使用audioPlayerDidFinishPlaying(_:,successfully:)
的方法是正确的。在您的代码中,当您调用 playScript(c:)
时,您将遍历 conditions
数组中的所有音频文件并在播放第一个音频时非常快速地调用 startRecord
方法。所有声音将被放入一个队列中并一个一个地播放。我不知道 startRecord
方法的内容,但我不认为应该这样调用它。
为了避免这些问题,您需要调用 playScript(c:)
然后等待方法 startRecord()
完成,然后再次调用 playScript(c:)
。所以你可以尝试这样的事情:
import AVFoundation
class SomeClass: NSObject, AVAudioPlayerDelegate {
var player: AVAudioPlayer?
var conditions = [String]()
var instructions: [() -> ()] = []
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
print("finished playing \(player.url)")
startRecord {
playNextInstruction()
}
}
func playScript(c: String)
{
let path = Bundle.main.path(forResource: c, ofType:"m4a")!
let url = URL(fileURLWithPath: path)
do {
self.player = try AVAudioPlayer(contentsOf: url)
self.player?.delegate = self
self.player?.play()
print(c)
print("playing script for " + c)
} catch {
print("couldn't load script")
}
}
func beginTest() {
instructions = conditions.shuffled().map { [unowned self] condition in
return {
self.playScript(c: condition)
}
}
playNextInstruction()
}
func playNextInstruction() {
if instructions.count != 0 {
instructions.remove(at: 0)()
} else {
exportData()
}
}
func exportData() {
}
func startRecord(completion: (() -> ())) {
}
}
如果它不起作用,那么我建议尝试在您的代码中的其他地方搜索问题。