AV(Queued)Player seekToTime: jumping to zero - macos

I am using an AVQueuedPlayer to playback SoudCloud files. If I use seekToTime:(CMTime)time on the AVQueuedPlayer the player just jumps to 0 and starts playing again. Any ideas how to fix this?
I tried to paste the MP3 URL into other players and all of them can seek, so it does not seem to be an server issue.
Bests,
Philip

OK to make this clear: You should use something like this:
- (void)advanceToTime:(float)timeToGo {
int32_t timeScale = self.audioPlayer.currentItem.asset.duration.timescale;
CMTime time = CMTimeMakeWithSeconds(timeToGo, timeScale);
[self.audioPlayer seekToTime:time completionHandler:^(BOOL finished) {
NSLog(#"Finished %#",finished ? #"NO" : #"YES");
}];
}

Related

MultiRoute Audio Input in iOS

We've been working with AudioUnits in Core Audio. It is simultaniously a very powerful audio framework, and one of the worst documented which makes it both a joy and a frustration to work with.
We want to accomplish something we know iPads had been able to do since iOS 6.0 - Multiple audio inputs.
So far - from the 2012 Developer Talk - It appears you have to set the audio session to MultiRoute. We've done this. If I plug in an a soundcard from a keyboard. I can see that there are two inputs. Great. We're then told that we need to set a ChannelMap on a Remote I/O unit.
To what? Well... here's where it gets vague. We need to set all the channels we don't want to -1 and the channels we want to 0 and 1 (for stereo input or for mono?).
We attempt this and... nothing. Sound still plays through on the 'last in wins' principle. Microphone if everything plugged out, soundcard if that's the one plugged in. But we can't switch between them.
This setup code is always run before the other function listed
func setupAudioSession() {
self.audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSessionCategoryMultiRoute, with: [.mixWithOthers])
try audioSession.setActive(true)
audioSessionWasSetup = true
} catch let error {
//TODO: Implement something here
print(error)
audioSessionWasSetup = false
}
}
We then have a remote I/O with an associated audiograph set up. This has been tested and works beautifully. But we need to be able to set where it's pulling sound from.
I've attempted to do it with this, but not only doesn't it have any effect... nothing happens.
Am I missing something?
private func setChannelMap(onAudioUnit audioUnit: AudioUnit?, toChannel channelIndex: Int = 0) {
var channelMap: [Int32] = []
if audioUnit == nil {
return
}
var numberOfInputChannels: UInt32 = 4 // Two stereo inputs? - I'm just guessing here
let mapSize: UInt32 = numberOfInputChannels * UInt32(MemoryLayout<Int32>.size);
for _ in 0...(numberOfInputChannels) {
channelMap.append(-1)
}
channelMap[2 * channelIndex] = 0;
channelMap[2 * channelIndex + 1] = 1;
let status = AudioUnitSetProperty(audioUnit!,
kAudioOutputUnitProperty_ChannelMap,
kAudioUnitScope_Input,
0,
&channelMap,
mapSize);
self.checkError(status, "Failed to set Channel Map on input unit")
}
There isn't any documentation on this at all as far as I've been able to find. Nor any code examples.
I hope you can help us.

phayser can not stop sound loop in firefox

music = game.sound.play('loop4');
music.loopFull();
music.stop();
thiese code work well in chrome except firefox
how can I play loop sound in fireFox and then stop it
Try this:
//Add sound
var music = game.add.audio('loop4');
//Start loop
music.loopFull();
//Stop loop
music.stop();
I don't know, it could be a bug. But it's also weird that you start and then immediately on the next line stop the music. Maybe that is not the intended use. If you try something like this, does it then start playing and stop after 2 seconds?
music = game.sound.play('loop4');
music.loopFull();
// wait 2 seconds then stop
game.time.events.add(Phaser.Timer.SECOND * 2, doStopMusic, this);
// separate function to stop music
function doStopMusic() {
// note: music must be global variable
music.stop();
}

AVAudioPlayer sounds will not play under 1 second apart

I have 0.2sec long sound file "beep.caf" that I am trying to get to play rapidly. If I set the sounds to play 1 second apart, they play just fine, but if I set them to play any less like 0.8, only the first sound plays. I have the same problem using AudioServicesPlaySystemSound too.
To play the sound twice rapidly I have the following function:
func runAfterDelay(delay: NSTimeInterval, block: dispatch_block_t) {
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
dispatch_after(time, dispatch_get_main_queue(), block)
}
I first setup my sound in the viewDidLoad with the following:
let path = NSBundle.mainBundle().pathForResource("beep", ofType: "caf")!
let url = NSURL(fileURLWithPath: path)
do{
self.startBeep = try AVAudioPlayer(contentsOfURL: url)
self.startBeep.prepareToPlay()
}catch{
print("Audio didn't load")
}
Then when a button is pressed the following code is run:
let start_time:Double = 1.0
let end_time:Double = start_time + 0.8
runAfterDelay(start_time ) {
self.startBeep.play()
}
runAfterDelay(end_time ) {
self.startBeep.play()
}
I have tried to stop the sound before the next play, but that doesn't help either. I have even duplicated the should file (beep & beepStop) to see if it had something to do with playing the same sound file and I get the same problems.
Any ideas??
The problem is with the time and not the players. The delay time was supposed to be in a 10th of a millisecond but was a 100th of a millisecond (.1 vs .01) which was so short of time between beeps that it often didn't fire accurately. A false positive was created when the time was set to 1.0 seconds.

Reverse Keyframe animation in Three.js

Really I would like to reverse a keyframe animation using THREE.KeyFrameAnimation.update with a negative number, appreciate this isn't supported natively, has anyone got any advice?
I actually found a solution to this for when you only want to play it once. I posted the full class here:
https://gist.github.com/rtpHarry/2d41811d04825935039dfc075116d0ad
The important bit is:
// will force the mixer to play in reverse no matter what
playClipReverseByIndex_Forced(index) {
this.action = this.mixer.clipAction(this.animations[index]);
if(this.action.time === 0) {
this.action.time = this.action.getClip().duration;
}
this.action.paused = false;
this.action.setLoop(THREE.LoopOnce);
this.action.timeScale = -1;
this.action.play();
}
Try setting animation.timeScale = -1;
But it works only when animation.loop = true;

AVPlayer gapless playback and seeking with multiple video files

I'm currently writing a small application which takes a folder containing many short video files (~1mn each) and plays them like they were ONE long video file.
I've been using AVQueuePlayer to play them all one after another but I was wondering if there were an alternative to this, because I'm running into some problems:
there is a small but noticeable gap when the player switches to the next file
I can't go back to the previous video file without having to remove all the items in the queue and put them back
I'd like to be able to go to any point in the video, just as if it were a single video file. Is AVPlayer the best approach for this?
I realize that it's been about 6 years since this was asked, but I found a solution to this shortly after seeing this question and maybe it will be helpful to someone else.
Instead of using a an AVQueuePlayer, I combined the clips in an AVMutableComposition (a subclass of AVAsset) which I could then play in a normal AVPlayer.
let assets: [AVAsset] = urlsOfVideos.map(AVAsset.init)
let composition = AVMutableComposition()
let compositionVideoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
let compositionAudioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
var insertTime = CMTime.zero
for asset in assets {
let range = CMTimeRange(start: .zero, duration: asset.duration)
guard let videoTrack = asset.tracks(withMediaType: .video).first,
let audioTrack = asset.tracks(withMediaType: .audio).first else {
continue
}
compositionVideoTrack?.preferredTransform = orientation!
try? compositionVideoTrack?.insertTimeRange(range, of: videoTrack, at: insertTime)
try? compositionAudioTrack?.insertTimeRange(range, of: audioTrack, at: insertTime)
insertTime = CMTimeAdd(insertTime, asset.duration)
}
Then you create the player like this
let player = AVPlayer(playerItem: AVPlayerItem(asset: composition))

Resources