jhk727
jhk727

Reputation: 225

Sequencing sounds with a delay in Swift

Apologies if this has been posted before but I haven't had much luck searching around on this topic. I'm trying to build a morse code converter using Swift. As part of this I've made a function that accepts a string of dots and dashes, and will hopefully play the corresponding audio. I've already successfully loaded up 2 audio players for the short and long beeps.

I started by looping through the string and playing the corresponding sound for each character. However, that just played all the sounds in parallel. Now I'm trying to use dispatch_after, but still running into the same issue. My code is below.

func audioMorseMessage(message: String) {
    var time = dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC))
    for character in message.characters {
        if String(character) == "-" {
            dispatch_after(time,dispatch_get_main_queue()){
                self.longBeep.play()
            }
        }
        if String(character) == "." {
            dispatch_after(time,dispatch_get_main_queue()){
                self.shortBeep.play()
            }
        }
    }
}

Is this the right way to approach this? Is there another way where I can concatenate the audio files during the loop (with small gaps placed between beeps) and then play back the entire file once the loop has completed? Thanks for any help in advance.

Upvotes: 0

Views: 741

Answers (1)

Price Ringo
Price Ringo

Reputation: 3440

This seems like a great opportunity to use NSOperation and NSOperationQueue. I would recommend creating a serial queue and then loading your individual sound operations in sequence. The following code is not fully formed but is pretty close. Hopefully your dot and dash sound files already include the dot-lengthed space after each tone. If they don't then you will have to insert the additional spaces (pauses) yourself.

class LongBeep: NSOperation {
  override func main() {
    if self.cancelled { return }
    print("L", terminator: "")  // play long sound
  }
}

class ShortBeep: NSOperation {
  override func main() {
    if self.cancelled { return }
    print("S", terminator: "")  // play short sound
  }
}

class Pause: NSOperation {
  override func main() {
    if self.cancelled { return }
    print(" pause ", terminator: "")  // play empty sound or use actual delay
  }
}

func audioMorseMessage(message: String) {
  let queue = NSOperationQueue()
  queue.name = "morse-player"
  queue.maxConcurrentOperationCount = 1

  message.characters.map{code in
    switch code {
    case "-": queue.addOperation(LongBeep())
    case ".": queue.addOperation(ShortBeep())
    case " ": queue.addOperation(Pause())
    default:  break
    }
  }
}

enter image description here

Upvotes: 2

Related Questions