ios AudioQueue streaming multiple songs - iphone

I am using AudioQueue to stream audio from an arbitrary source (the class basically just needs a delegate that provides it with packets), I've made a class that wraps all the functionality lets call is AudioQueueClass, I am using this class to play many songs, in between each song I release my class and create a new AudioQueueClass instance to play the next song, I am seeing two problems which I haven't been able to find the cause maybe some of you have run into these issues and can shed a light on it
1- Every now and the AudioQueue plays a few seconds of a previous song and then comes back to the current song, not sure why this could be happening as I am creating a new queue for each song, and I believe I am disposing of my queues appropriately --some code to follow
2- This one is even worse, sometimes when I'm into the 3rd or 4th song the audio queue stops playing... I believe the problem is that AudioQueueInputCallback inCallbackProc stops being called, which I guess is because the queue stopped playing and processing packets, but cannot find out why...Another thing to note is that this only happens when I stream to the device from an outside source, if I merely get the file data locally and use that as packets I hear a "stutter" in the music but it recovers and plays fine, whereas in the streaming case the sound just stops (pretty weird)
Here is the code I am using to dispose of the audio queue, not posting any more because not sure what relevant parts to post, please let me know if you want to see any of the code and ill post it
AudioQueueFlush(audioQueue);
AudioQueueStop(audioQueue, true);
if (audioFileStream)
{
err = AudioFileStreamClose(audioFileStream);
audioFileStream = nil;
if (err)
{
[self failWithErrorCode:AS_FILE_STREAM_CLOSE_FAILED];
}
}
//
// Dispose of the Audio Queue
//
if (audioQueue)
{
err = AudioQueueDispose(audioQueue, true);
audioQueue = nil;
if (err)
{
[self failWithErrorCode:AS_AUDIO_QUEUE_DISPOSE_FAILED];
}
}

Turns out not surprisingly the error was not in the Audio streamer at all, it was the way i was writing the music to be streamed...after i fixed it everything worked out alright...
Thanks Again
Daniel

Related

Unity VideoPlayer and WebGLMovieTexture cant play two videos in a row

I'm trying to play videos in Unity WebGL in the browser, but having lots of problems.
I tried two different video players and none of them work fully.
The WebGLMovieTexture player works like this
public WebGLStreamingVideoPlugin _videoPlugin = new WebGLStreamingVideoPlugin("http://www.example.net/video.mp4");
_videoPlugin.Play();
Basically when you want to play a video you create a new instance and give it the URL like above, and it plays great!!
The problem is when you want to stop that video, and play a different video, it seems impossible because there is no way dispose of the first video because there is only a Stop() in the API, which stops the playback but it continues to stream the video data from the internet in the background.
There is no way to delete the instance because Destroy() cant be called since that WebGLMovieTexture is not derived from monodevelop, and C# does not seem to give a way to delete an object (how silly). Even setting it to null doesnt do it, it continues to stream the video in the background.
So if you create a new instance in order to play a different video, you end up with TWO video streams, and if you do it again to play a third, you end up with THREE, and so on, so quickly you can see how bad that will end up.
My question is how to dispose of or destroy the first WebGLMovieTexture player, or maybe tell it to stop streaming the first video and start playing a different one?
The second player I tried is the VideoPlayer for WebGL in Unity Version 5.6.0b4, with this one I can only get it to play a video if I hardcode the URL in the inspector, if I put the URL in code it doesn't play it in the browser.
vPlayer = gameObject.GetComponent<UnityEngine.Video.VideoPlayer>();
if (vPlayer.isPlaying) {
Debug.Log("STOPPING PLAY");
vPlayer.Stop();
}
vPlayer.url = url;
vPlayer.isLooping = true;
vPlayer.frame = 0;
vPlayer.targetCameraAlpha = 1F;
vPlayer.Prepare();
vPlayer.Play();
And to get it to play a second video I suspect I will have the same problems as the other one.
Anybody have any ideas that can help me?

Playing sounds in perfect succession on the iPhone

I am developing a game for the iPhone and iPad using cocos2d, and I need to be able to play a sound exactly when another one completes.
I have a soundtrack that is chopped up in smaller pieces, and there are no room for the tinyest gap between playback when one finishes and one starts.
Btw. I cannot glue the sounds together into a single file and just play that since the order of the files will be rearranged runtime.
How can I achieve this?
With CocosDenshion you can register a delegate with
[[CDAudioManager sharedManager] setBackgroundMusicCompletionListener:self
selector:#selector(musicDidFinish)];
CDAudioManager class reference
This delegate will be called whenever the background music ends. This of course only works if you play your sound files as background music (with the playBackgroundMusic method).
If that doesn't work for you, have a look at ObjectAL. You'll have more options and greater flexibility. For example, with ALSource you can queue multiple ALBuffer objects which represent sound files. That means whenever the source's buffer count decreases to 1 you just queue the next buffer to achieve uninterrupted, sequential playback of multiple sound files (any format).
Because ObjectAL is so awesome (well, I think so :) ) it's included and ready to use in Kobold2D.
You can use a single Audio Queue or the RemoteIO Audio Unit, and just fill the callback buffers with raw/PCM audio samples from any file in any order.

Recording Chunked Audio in Background iOS

I am trying to figure out a way to record audio in the background of an iOS application and have it streamed to the server.
I have pretty much got this working for when the app is in the foreground. I use AVAudioRecorder to record input for X seconds. Once I get the callback that this has finished, I record for another X seconds. Each recording session gets stored to a different file and I send these files asynchronously to the server.
However, this doesn't seem to work while my app goes into background mode.
When going into the background, the current record session continues recording until the X seconds are up, however my app gets suspended, before I can start another recording session.
Any ideas?
Here's the code for my callback:
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)aRecorder successfully:(BOOL)flag {
NSLog(#"hello");
[self initRecorder];
[recorder recordForDuration:5];
}
You can't restart recording in the background.
So use the Audio Queue or Audio Unit RemoteIO APIs instead, which will give you smaller "chunks" (callback buffer blocks) of audio without stopping the audio recording.
Concatenate small audio callback chunks into larger file chunks if needed for your network protocol.
Background audio playing is supported with multitasking but it's not very clear that background audio recording is. However, I have not tried it. The Audio Unit API might let you continue to record audio while the application is in the background. However, this is kind of a trick and I Imagine it might get pulled out at some point.

How to use NSOperation and NSOperationQueue

I made an app which plays the song on clicking on the image of artist.(see image attached). Each artist image is implemented on button and on clicking this button, a function is being called which first downloads and then plays the song. I passed this method(function) in a thread but problem is that every time when I click on the image of artist(button) new threads starts running and then multiple songs gets started playing concurrently. How can I use "NSOperation and NSOperationQueue" so that only one song will run at a time . Please help.
Thanks in advance
NSOperation and NSOperationQueue aren't going to directly solve your problem.
If I were pursuing a dead simple approach, I would have a global AudioPlayer object that has a method startPlaying: whose argument is the song to play (represented however needed; URL, NSData, whatever you need).
In that method, I'd stop playing whatever is currently playing and start the new track.
If I remember correctly, I don't think you even need a thread for this; the audio APIs are generally quite adept at taking care of playback in the background.
In any case, if you do need a thread, then I'd hide that thread in my AudioPlayer object and let it take care of telling the music to stop/start playing in said thread. A queue of some kind -- operation or GCD -- could be used for that, yes.

How do you send messages between two instances of a custom UITableViewCell?

I have a UITableView populated with a bunch of music players that I've made using a custom UITableViewCell. (as shown in the screenshot linked here: screenshot).
The problem with the way I have it coded is that since each cell is completely independent, there's no way for one tableviewcell to check if any other the other cells have audio playing. This means that when I run my app, I am able to play more than one audio file at the same time.
Ultimately, how would I go about putting some sort of check in place so that when the user hits the play button, the app first checks to see if any other cell is playing audio, and, if so, stops them before playing its own audio file?
Please let me know if you would like me to post my project.
Thank you!
For starters I can't think of any good reason the cells themselves should be responsible for playing the audio. They should be responsible for telling some other object (like whatever controller is responsible for the UITableView) to play the audio. That controller would obviously then know to stop whatever it was already playing before playing something else.
In general, it's not a great idea to be putting that much logic into a 'view.'
It would probably be easiest to use notifications (NSNotification and NSNotificationCenter).
Use a common notification name for starting and stopping.
MusicPlayerWillPlay
MusicPlayerWillStop
When you create each player, register for both notifications. Then when playerA is going to play, it posts a MusicPlayerWillPlay notification. playerB, playerC and playerD, will get this notification, and if they are playing, will stop.
One caveat is that each player is unaware of the others, so you have to register with a nil object, which means playerA will get it's own notification. So in your notification method, you'll probably want to do something like
{
//...
if (sender == self)
return;
//...
}