SoundManager 32-sound ceiling hit error - soundmanager2

When playing the same long sounds in a 100 interval, after few seconds I start getting a “No sound hardware, or 32-sound ceiling hit” error.
To repro this issue:
1- Open a browser (I used IE10 and Chrome)
2- Launch its developer tool (F12) and go to the Console Tab.
3- Make sure the volume is low as a sound will start playing as soon as you hit the following link.
4- Hit this URL: https://googledrive.com/host/0B92G3ib2ozRVcS1RcHI5eGpzOXc/default.htm
5- Sound will start playing and then there will be a silence. During the silence you will be getting the error “test: play(): No sound hardware, or 32-sound ceiling hit” in the console. (SoundManager is in debugging mode so you will get a lot of logged messages before)

There is a limit of 32 simultaneous sounds. If you are playing a new sound every 100ms, you will hit that limit in 3.2 seconds. That's what the 32-sound ceiling means.

I worked this around by checking if the sound playState is == 0 before playing the same sound and setting its position to 0 if playState is != 0.
Code looks like this:
if (this.sounds[id].playState == 0) {
this.sounds[id].play({ volume: this.volume * 100.0 });
} else {
// if sound is already playing then move it to the beginning
this.sounds[id].setPosition(0);
}
Sound feels a little choppy though. If there is a better way to fix this, please let me know.

Related

How to start AVAudioPlayer without loading full buffer?

I want to use the AVAudioPlayer to play a previously recorded file. That recording works fine, and I saved the file to the temp directory.
The problem is, as soon as I setup the AVAudioPlayer, it starts buffering and will not start playing before fully buffering that recording. Now it may work fine with recordings of about 30 seconds, but I also want it to work with like 1 hour long recordings. I am talking about > 1 minute of waiting.
How do I force AVAudioPlayer to just begin playing with the current buffer?
Like I can tell AVPlayer with player.automaticallyWaitsToMinimizeStalling = false
because I don't expect there to be any stalling issue.
Or how do I get something like averagePower()->Float from AVPlayer?
I could not use AVPlayer because I need something like AVAudioPlayer's func averagePower(forChannel channelNumber: Int) -> Float to show a visualized presentation of the recording. If you know how to get to those averagePower values from AVPlayer, -Item, -Asset or -Track, that would be fine too, I could not find anything fitting.
I found that, if you use AVAudioPlayer but call player.play() on another thread, it is not waiting for the buffer and starts playing right away.
DispatchQueue.global(qos: .background).async {
self.player.play()
}
But this comes with some restrictions, because now I can't use player.play(at: TimeInverval) because that seems to interrupt building the buffer and then the file will not be played to its full duration. I worked around that by setting player.currentTime before player.play(), which does not to bother the buffer.

For how long does the AVPlayer continues to buffer from an URL after a pause?

I was reading the AVPlayer class documentation and I couldn't find the answer for my question.
I'm playing a streamed audio from the Internet on my iPhone app and I'd like to know if after a [myAVPlayer pause]; invocation myAVPlayer will keep downloading the audio file on the background for a long time.
If the user pushes the "Pause" button, invoking [myAVPlayer pause]; and then leaves the app, will myAVPlayer keep downloading a large amount of data?
I'm concerned about this when the user is on 3G Network.
I am faced with the same question and have done some experimentation. My observations are only valid for video, but if they are also valid for audio, then AVPlayer will try to buffer around 30s of content when you press pause. If you have access to the webserver, you could run tcpdump/wireshark and see how long after you press pause that the server continues to send data.
You can manage how long AVPlayer continues to buffer.
You need to manage preferredForwardBufferDuration of avplayer currentItem. If you want to stop buffering set value to 1 because if you set it to 0 it will be set up automatically
self.avPlayer.currentItem.preferredForwardBufferDuration = 1;
From Apple documentation: This property defines the preferred forward buffer duration in seconds. If set to 0, the player will choose an appropriate level of buffering for most use cases. Setting this property to a low value will increase the chance that playback will stall and re-buffer, while setting it to a high value will increase demand on system resources.

Trying to play an audio file

I'm trying to play an audio file in a cocos2d application. Here is the line which tries to play the sound:
[[SimpleAudioEngine sharedEngine] playEffect:#"pig_squeal.wav"];
If I put a log near this line, the log appears, and I can play the sound with iTunes. But when the sound should be played, there is a message displayed:
AudioStreamBasicDescription: 2 ch, 44100 Hz, 'lpcm' (0x00000C2C) 8.24-bit little-endian signed integer, deinterleaved
What's the problem?
This was discussed in comments but I've amalgamated all the possibilities of why it may not work here.:
That's not an error message, just some information.
Is the sound definitely in your library and a part of the target?
You haven't changed the volume of the SimpleAudioEngine or the volume of your device isn't all the way down?
Click the sound in your library. Press Option+Command+1 to bring up the file editor. Scroll down to "Target Membership" and ensure the sound is checked for your target.
Try a different sound effect too? Try and narrow the problem down to "is it SimpleAudioEngine".
Also try and playBackgroundMusic for a sound (This was the solution in this case)
And try an mp3
There isn't a problem. It's a status message written to the log when you initialise the current OpenAL context using alcMakeContextCurrent. As far as I'm aware, you can't get rid of the message.
There is no problems with your code for the Playing of the Sound. Please check the Sound file has been added to the project also do check the format of the sound. It should play the Sound whenever you call the Play Effect. Please also try to PRELOAD the sound effect in the init method.
that message means the song was read correctly and should be playing. possible reasons you don't hear it?
volume turned down.
device malfunctioning
audio has silence in it
audio file is large and will take a long time to load.
sound has been redirect to come out of the headphones or the ear piece (even if not attached)
But the sound is loading and most likely playing.
If you are getting a crash while running in device from xcode pls try this(worked for me). Dissconnect the device from Xcode and run the app in the device. I dont know why it worked like that. But when I did this there was no crash.

Using AVAudioPlayer, my sounds (sporadically!) play weird

I've done a simple audio playback GUI implemented using AVAudioPlayer.
When playing my sound, I use a UISlider to provide playback feedback...
Here's where it gets weird.
I have a problem that happens very (very) sporadically - and mostly it doesn't happen, making it really hard to debug.
The problem is that sometime, once the sound ends, and I play it again, it's as if it starts looping (as if I set numberOfLoops to -1), without ever calling audioPlayerDidFinishPlaying.
Now, no where is my code do I "touch" numberOfLoops - it defaults to 0, and I leave it that way.
To make the problem weirder, then once this problem happens, I don't "hear" the audio - though it does appear to play (i have a timer function that provides the visual feedback, and it checks the sound is playing...)
Any ideas? Directions?
I faced the same issue once and I got around the issue by increasing the updating timer interval to .25 seconds,which was earlier .1 seconds. Also I tried to avoid files with very small duration. Hope this helps you to some extend. Please try it and let me know if it worked for you.

How to play sound at precise moments on iPhone?

I'm working on creating a simple metronome on the iPhone. What the app does right now is to run a timer, entering the timer's function every 1/1000th of second. Then it checks the current time vs time of starting the app (I'm using CACurrentMediaTime() function).
CFTimeInterval currentTime = CACurrentMediaTime();
if (self.beatingStartTime == 0) {
self.beatingStartTime = currentTime;
}
if ( (currentTime - self.beatingStartTime) >= self.timeIntevalBetweenTicks * self.internalTimerCounter ) {
self.internalTimerCounter ++;
// ...
}
If there is a good moment to play audio, the code using OpenAL to play it gets fired.
Basicly that's it. I checked the sounds played when running both in simulator as well as on 2 devices (iPad and jailbroken iPhone 3GS) and there is a problem - when I recorded the sound and reviewed the waveform in Reaper software, some sounds play a bit too late, and some of them - bit too early (even I could understand the "too late" part, I don't really get how it can play earlier then it should - since the app checks the number of seconds every time, it basicly can't be ealier then specified time - yet it is, according to my recods).
At the same time there are some metronome apps that are known for being "rock-solid" when it comes to timing, so I guess there is a way. I just wonder what I'm missing...
edit: Changing timer call from 1/1000th second to, for example 1/100th doesn't help.
edit 2: When I switched from timer to threads (and I put the thread to sleep for specified time) I still get a strange behavior. The tempo moves around and while I could understand a little lag and playing some sounds too late, the problem is some of them do play too early - it means time distance between 2 beats is less then the time that should pass.
The diffrence is about 3%, which translates to about 10-15 miliseconds, which is quite a lot for me. Anyone got an idea why the sound can play earlier? I tried it both on iPhone simulator and on iPad actual device, and my only guess is there's something wrong with the timer - CACurrentMediaTime() returning more seconds that it should. Is it even possible?
Try using an NSSound, and load it up as an instance variable and don't release it unless your metronome isn't running. Delays can be caused by loading the file into memory on the loop. The other thing to consider is that a metronome probably doesn't need to poll every 1/1000th of a second. If you do it less often, you're less likely to saturate the CPU and you might get more consistent results.
Lastly, check out how Apple's demo works: http://developer.apple.com/library/ios/#samplecode/Metronome/Introduction/Intro.html
Might give you a better idea how to accomplish what you're trying to do :)
What you want is COCOS DENSHION which is a simple reliable easy to use sound library, that we have found solves all problems.
I (just personally) don't like "Cocos2D" but you can just take and use CocosDenshion.
Secondly -- 1000th of a second is ridiculous for a timer. Just totally forget it.
Thirdly -- AVAudioPlayer is worthless as you found.
Note - "ObjectAL" is a new, perhaps better, alternative
to CocosDenshion. Check it out.