I have some NSSound
objects that I'd like to convert to AVAudioPlayer
instances. I have file paths (NSURL
s) associated with the NSSound
objects, but the original file may not exist. Here is what I have so far:
class SoundObj: NSObject {
var path: NSURL?
var sound: NSSound?
var player: AVAudioPlayer
}
let aSound = SoundObj()
aSound.path = NSURL(fileURLWithPath: "file:///path/to/sound.m4a")
aSound.sound = NSSound(contentsOfURL: aSound.path)!
do {
try aSound.player = AVAudioPlayer(contentsOfURL: aSound.path)
} catch {
// perhaps use AVAudioPlayer(data: ...)?
}
How do I convert an NSSound
object to an AVAudioPlayer
instance?
So I didn't see a public interface to get the URL from an NSSound
object, so I went digging through the private headers to see what I could find. Turns out there are private instance method url
and _url
which return the URL of an NSSound
. Presumably these are getters for an NSURL
ivar or property.
With Objective-C this would be easy: we would just add the methods to a new interface or extension. With pure Swift things are a little trickier, and we need to expose the accessor via an Objective-C protocol:
@objc protocol NSSoundPrivate {
var url: NSURL? { get }
}
Since url
is an instance method, you may get better results with func url() -> NSURL?
instead of using a variable. Your milage may vary: using a var
to emulate the behavior of a read-only property seemed to work for me.
I wrote a new convenience initializer in an extension on AVAudioPlayer
:
extension AVAudioPlayer {
convenience init?(sound: NSSound) throws {
let privateSound = unsafeBitCast(sound, NSSoundPrivate.self)
guard let url = privateSound.url else { return nil }
do {
try self.init(contentsOfURL: url)
} catch {
throw error
}
}
}
Usage:
let url = NSURL(...)
if let sound = NSSound(contentsOfURL: url, byReference: true) {
do {
let player = try AVAudioPlayer(sound: sound)
player?.play()
} catch {
print(error)
}
}
After attempting to find anything related to NSData
in the ivars, instance methods, and properties of an NSSound, I have come to the conclusion that the data portion of whatever you use to initialize an NSSound
is obfuscated somewhere in the implementation of the class, and is not available like the URL is.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With