iPhone Game Programming – Tutorial 9 – Sound Manager
In this tutorial I create a simple sound manager class that can play back multiple sounds using OpenAL. It also allows you to play background music as well using the AVAudioPlayer class.
The reason for writing my own sound manager was to see how OpenAL works. Commenters on this blog provided some great links, see the “Sound of music… explosions and lasers”, so I decided to work through them and get something working.
This class is simple and provides basic access to playing sounds in OpenAL. It also makes use of all 32 sources OpenAL sources available on the iPhone so that the same sound can be played simultaneously which is great for explosions and laser fire.
One item I have not yet got into the class is 3D sound. OpenAL give you the ability to position the listener in 3D space and to also position each source of sound in 3D space. OpenAL will then work out depending on where the listener is in relation to the sound source what the sound should sound like i.e. volume, pitch etc. The API for this looks simple enough but I’ve not had time to try it out and wanted to get the core class tutorial published. I will take a look at this area and post any changes I make to the class.
A big thanks goes to www.benbritten.com there is a great OpenAL tutorial on there about getting going with the basics needed and its this well written tutorial which got me off the ground, so a real thanks to Ben.
As usual, please post any questions, suggestions, or issues you spot with the code and I hope you enjoy the tutorial.
Mike
176 Comments
Eskema on May 26th, 2009
bob maybe its because the format 22050, or the compression used on the file
bob on May 26th, 2009
@eskema
I don’t think so, I tried it at different rates 44100 and what not and I also tried several different files, same thing. I’m still messing around with it. Have you tried a stereo file ?
mike on May 26th, 2009
Hi bob
I have tried it with stereo and it seemed to work fine. I’ve put up the file I used at http://www.71squared.co.uk/iPhone/laser.caf for you to download and try. Its around 1.3Mb as well as I wanted to see how OpenAL handled large sounds.
This sound effect plays fine but I’d be interested to see if you get the same results. If it works then it could be how the app you are using encodes the file. I generated my sound file in GarageBand, saved as AIFF and then used Audiacity to convert to a WAV, then from a WAV to a CAF using afconvert, so its been through a number of steps and works ok.
Let me know how it goes.
Mike
bob on May 26th, 2009
@Mike
I converted my caf files to wav using a free program called audacity which can be found here http://audacity.sourceforge.net/download/mac
Then I converted them to caf again using afconvert. That worked, It must have something to do with the way the original program I used to save them. I think I might buy QuickTime Pro..
bob on May 26th, 2009
@Mike
Well I fixed the sound by just putting them through afconvert. Without converting them to another format.
I used
afconvert -f caff -d LEI16 ocean.caf ocean.caf that did the trick. I think the program I originally used said it saved as caf format but I bet it didn’t do it correctly. The software I originally used was SOUND STUDIO3
Thanks alot for the Help.
mike on May 26th, 2009
Thanks for the update bob. I use Audiacity as well, its a good little app. I’m glad you got to the bottom of it anyway :o)
Mike
Thomas on May 27th, 2009
Hi
Hopefully you can help me, i’m using your tutorial 9 code as base for at game. It’s a simple pong tennis game just to get the hang of making games for iphone. I have a problem with a texture getting bigger then the actual size when i move it. It’s a bit hard to explain but if the texture is like this, try to emagine this is the pong bat
***
When i in updateScene move the x to fast it’s like it rendered one and a half time so i now is
****
a little wider.
If i in updateScene move it slowly it dosen’t do this.
Hope anyone has clue to what is going on.
mike on May 27th, 2009
Hi Thomas
That’s not one I’ve seen before. The only thing I can think of that would make the texture bigger is if the quad being drawn somehow was bigger as the texture inside it would be scaled up.
If you can send me a sample project with this problem I’d be happy to take a lool, mike@71squared.co.uk.
Mike
Jamie Hill on May 27th, 2009
Blimey… you’re banging these out one after another! …excellent news, I’ve got some catching up to do though ;)
CKJ on May 27th, 2009
Hi,
I don’t see the release of AVAudioPlayer
when i try to do it, i get gdb ;(
can you explain more about memory using about AVAudioPlayer.
Regards,
mike on May 27th, 2009
Hi CKJ, that is a good point. I’ve made some changes to the code which does now release the AVAAudioPlayer instance correctly and I’ve also spotted another bug with the release of the soundbuffers in the dealloc method.
When I get home tonight I’m going to put the changes into the Tutorial 9 project and let people know when its available for download.
Thanks for the feedback.
Mike
thomas on May 27th, 2009
Hi Mike
Just to let you know i found my error so i’m not sending you a email anyway..
thomas on May 27th, 2009
Just a quick question, how do i collision detect two images? I need to know if image one and two collide, i’m using your lession 9 as base so i’m using your image classes.
mike on May 27th, 2009
Hi Thomas, glad you got your problem sorted out. Collision detection is a tutorial I am going to be starting soon. There are many many different ways to do it.
The easiest way to do it is to check if the bounding box of each image intersect. If you create a CGRect with the location and dimensions of the images you can that use a method it has which check if that CGRect intersects with another, which you provide as part of the method call. If they do then you have collided.
If you go a google on collision detection you will find loads of info on it. The Image class at the moment does not have any specific functionality for collision detection. This is something that I will be building into the entity classes I will need. Again, I’m going to be covering this in tutorials to provide more detail.
Hope that helps
Mike
mike on May 27th, 2009
A new version of the Tutorial 9 project has been created which contains a couple of fixes. One which releases the backgroundMusicPlayer and the other which fixes a problem when trying to remove all OpenAL buffers. I was trying to look through a Dictionary as if it were an array DOH!!! :o)
Mike
Chris on May 28th, 2009
Hey Mike, quick question, and this may be a stupid one:
How would you stop background music from playing?
Thanks
Chris
RoberRM on May 28th, 2009
Hi Mike!
I’m not even close to this tutorial yet, but I’ve read your previous post and I have to ask: do you plan on releasing another “quick update” tutorial with this fixes?
You see, I’m following your tutorials, so I’m missing all this changes you introduce in your code but not in the videos. Don’t take me wrong: I’m not asking you to do anything extra (you are doing us a big favor already), this is just a question to let me know if I should check the final code when all the tutorials are finished (because there may be portions of code not included in the tutorials, such as this fixes) or not.
Thank you for your patience! :D
mike on May 28th, 2009
Hi RoberRM, yes, I’m going to do an update vid which will cover the fixes in the Sound Manager and also a couple of changes to the Image class as well :o)
Mike
mike on May 28th, 2009
@chris, there is a method called stopPlayingMusic which can be used. You will need to add that method to the header as well as I’ve spotted that it was missing.
Let me know if you have any issues with that.
Mike
Ant1 on May 28th, 2009
Thank you very much for another fantastic tutorial can’t wait for the next one!
Tom on May 28th, 2009
Hi Mike,
I had a little problem playing music using the AVAudioPlayer. When I ran my application in the simulator it crashed with the following error.
Error loading /Library/QuickTime/DivX Decoder.component/Contents/MacOS/DivX Decoder: dlopen(/Library/QuickTime/DivX Decoder.component/Contents/MacOS/DivX Decoder, 262): Symbol not found: _SCDynamicStoreCopyConsoleUser
You can quite easily fix this problem by moving all incompatible codecs out of the /Library/Quicktime folder to a temp folder for safe keeping.
The error message tells you which codec the iPhone simulator has a problem with. In the above example the erroneous codec is the divx decoder.
Jason on May 29th, 2009
Mike,
I love the sound manager, thanks for all the work on the tutorials.
Hey, I haven’t seen any tutorials or posts, but do you plan on doing something on the best way to handle user input (touches) in your iphone game?
Thanks
-Jason
RoberRM on June 2nd, 2009
Yet another great tutorial, Mike. :D Thank you very much!
I’ve seen that you didn’t get to fix that warning Xcode gives in the initWithContentsOfURL of the AVAudioPlayer. I’ve searched around the web and all I’ve seen is people passing nil instead of &error. I’ve tried other options but my knowledge of this things is quite limited yet (i.e. thanks to you I understood what the & sign meant :D ) and nothing else seemed to remove it.
I’d like to know your thoughts on this.
Once again, thank you for your help. ;)
Róber
lpbaker on June 6th, 2009
These tutorials have been HUGELY helpful, I can’t tell you how grateful I am to you for taking the time to do them and make it all so clear. Although I started writing games in 1980 and have written hundreds of them in multiple languages, trying to get my head around OpenGL was really aggravating – your tutorials have made it all seem so simple! I’ve sent you a small Paypal donation by way of thanks :)
One question; what’s your position on people taking this code and using it in commercial games? As in, if I write an iPhone game using your code and then sell it … ?
Thanks,
Lindsay
mike on June 6th, 2009
Hi Lindsay and thanks for the donation, it is always much appreciated :o)
I’m glad you are finding the tutorials useful. The aim is to make them as simple as I can and not get hung up in the complexity which its always possible to introduce into these topics.
As for the code, it is completely public domain. I should really clearly state that somewhere. If you want to use the code in a commercial game that’s great and you are free to do so. If you do manage to release something it would be good to hear about it as I’d love to see what people have managed to create with some of the code :o)
Good luck and always happy to answer questions, if I can ;o)
Mike
lpbaker on June 7th, 2009
That is hugely generous, Mike! If I do make a commercially successful game (big IF!) then I’ll definitely shoot a nicer donation your way.
I’ve just finished watching Tut#4 so I’ve got a ways to go before I start asking specific questions (especially since this is adapting as you go along and learn more). For now I’m just grateful to see what you’re doing, as it’s helping not only my OpenGL but it’s given me a few “aha” moments with Objective C as well :)
Linki i ciekawostki | appledev.pl on June 7th, 2009
[...] dla iPhone’a. Bardzo ciekawe i bardzo techniczne artykuÅ‚y (jak choć ten o OpenGL). iPhone Game Programming – Tutorial 9 – Sound Manager Tutorial pokazujÄ…cy jak korzystać z OpenAL. Avoiding iPhone App Rejection, Part 2 Kilka [...]
IPhoner on June 8th, 2009
Nice tutorials! I’ve noticed that many proffesional
games are displaying a little movie as intro, it would be cool if you showed us how to play a little movie before getting to the main screen where text and sprites are displayed.
Also, I have jailbreaked my ipod touch so I can easily deploy the compiled/linked result of you tutorials into the ipod touch, but I can’t figure out how to do that…. How can I test the Oglgame.app directly on ipod touch.
Thank you.
Daniel on June 9th, 2009
Hi Mike!
I’m having lots of trouble with my sharedsoundmanager instance.
when i call the line:
sharedSoundManager = [SingletonSoundManager sharedSoundManager];
it makes my app to crash. The odd thing about this code is that
it worked perfect when i tested it yesterday. I don’t know why it does this.
im running my app in the 2.2.1 simulator on my mac mini.
Do you have any ideas what causes this problem?
Thank you for these great tutorials. probably some of the most useful ones i’ve come across on the web:)
Daniel
Daniel on June 9th, 2009
Hi!
sorry about my last post. I solved the problem. it was caused by the soundproperties on my mac mini. now it runs perfectly:D
Thanks again for these great tutorials
Daniel
mike on June 9th, 2009
Hi Daniel
Glad you got it sorted and that your finding the tutorials useful :o)
Mike
Austin on June 9th, 2009
Hi Mike
I’m having trouble with this tutorial. My app keeps crashing and no sound will play. Even when I download the Tutorial 9 Project the app will play no sound and crash. Is there anything obvious I am missing?
Thank you!
Austin
mike on June 9th, 2009
Hi Austin
There is nothing that comes to mind, it should work ok. Daniel above has just posted about a problem he was having with his settings that made his app crash.
Daniel, can you share the changes you made as it could be the same problem Austin is having.
Mike
lpbaker on June 10th, 2009
I also can’t get the Tut9 project to run; here’s the console output:
[Session started at 2009-06-10 11:23:15 +1000.] 2009-06-10 11:23:16.640 OGLGame[3121:20b] AngelCodeFont: Initializing vertex arrays for font 'kerning' with capacity of '95' 2009-06-10 11:23:16.648 OGLGame[3121:20b] Tiled: Tilemap map dimensions are 100x6 2009-06-10 11:23:16.648 OGLGame[3121:20b] Tiled: Tilemap tile dimensions are 50x50 2009-06-10 11:23:16.648 OGLGame[3121:20b] Tiled: Tilemap property 'MyMapProp' found with value 'My Value' 2009-06-10 11:23:16.649 OGLGame[3121:20b] --> TILESET found named: Untitled, width=50, height=50, firstgid=1, spacing=0, id=0 2009-06-10 11:23:16.649 OGLGame[3121:20b] ----> Found source for tileset called 'tiles.png'. 2009-06-10 11:23:16.656 OGLGame[3121:20b] --> LAYER found called: Layer 0, width=100, height=6 2009-06-10 11:23:16.657 OGLGame[3121:20b] ----> Found '600' tile elements 2009-06-10 11:23:16.659 OGLGame[3121:20b] --> LAYER found called: Layer 1, width=100, height=6 2009-06-10 11:23:16.661 OGLGame[3121:20b] ----> Found '600' tile elements 2009-06-10 11:23:16.663 OGLGame[3121:20b] --> Initializing vertex arrays for '70' quads. 2009-06-10 11:23:16.664 OGLGame[3121:20b] Map Property value = 'My Value' [11:23:19.741 ] AQMEIOBase::DoStartIO: timeout [11:23:20.017 ] AQMEDevice::StartIO: AudioOutputUnitStart returned -66681 [11:23:20.017 ] AUIOClient_StartIO failed (-66681) 2009-06-10 11:23:20.036 OGLGame[3121:20b] Error loading /Library/QuickTime/LiveType.component/Contents/MacOS/LiveType: dlopen(/Library/QuickTime/LiveType.component/Contents/MacOS/LiveType, 262): Symbol not found: _SCDynamicStoreCopyConsoleUser Referenced from: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis Expected in: /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.2.1.sdk/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration
mike on June 10th, 2009
@lpbaker, thanks for the log output. This is something I have seen before as have some others on the blog. The problem is that there is a codec which is not compatible with the iPhone Simulator. From the log above, the codec which is causing the problem is LiveType.
If you copy the codec causing the problems out of the
/Library/QuickTime
folder to somewhere safe it should sort out the problem.
Let me know how that goes.
Mike
lpbaker on June 10th, 2009
@mike: I took out Livetype.component and tried again, this time it failed on the DivX decoder. Removed that too and the project worked :) Thanks for the quick answer.
Completely unrelated question: since you’ve mentioned it several times, I’ve been checking out Cocos2D, and although it’s a lot to take in initially, it does seem very powerful. I was wondering why you’re writing your own engine from scratch – is it just to learn how? Don’t get me wrong, I’m loving the videos and the project you’re building, I’m just curious!
Thanks,
Lindsay
mike on June 10th, 2009
Excellent, I’m glad that got things working.
As for Cocos2D, it is a great engine. For me, I just have to know how things work :o) I may well use Cocos2D in the future, but I’ve always felt that you get the most out of things like Cocos2D if you understand what is going on under the hood. If you just need to get something out quick then just using the engine is great, but certainly for me and it seems others as well, there is a real interest to understand how things work when using OpenGL.
Sorry for the ramble, but basically I just love learning about this stuff :O)
Mike
lpbaker on June 10th, 2009
@mike: I understand completely – I’m the same :)
Any chance you’ll be doing a tutorial on user input soon? It would be nice to be able to get things moving around the screen based on touches or tilts.
Thanks, Lindsay
Austin on June 10th, 2009
The DivX decoder was my problem too. Thank you Mike and Ipbaker for that!
barry on June 10th, 2009
Hi Mike,
Thanks for creating your Sound Manager tutorial. It’s excellent!
I’d really like to re-download the Tutorial 9 project when any of the following updates occur: 3D sound (to which you refer in your recent blog), a completed “stopSoundWithKey:” method, and/or a solution for the warning that Xcode periodically gives regarding the call to AVAudioPlayer’s “initWithContentsOfURL:error:” method.
Is there a list I can get on to be notified if you post any of these changes?
Thanks,
Barry
RoberRM on June 10th, 2009
@barry: The only solution I’ve found so far is to change the error:@error into error:nil. That eliminates the warning although you won’t be able to check for errors later. That’s what I’ve done because that’s what everybody else appears to be doing, but I don’t think that’s the correct approach.
Anonymous on June 17th, 2009
Mike,
Where did you find your sound effects?
Thanks
mike on June 17th, 2009
Finding sounds is always a pain. I normally just hunt around the internet until I find something I can use. One site I’ve got stuff from is http://www.grsites.com/sounds/
There are others, but I just tend to hunt around rather than have a favorite place.
Mike
dnsolo on June 24th, 2009
Hi Mike,
Thank you so much for all of your amazing tutorials, you have really helped me to understand much more about iPhone development, please keep up the great work!
I have now got your Sound Engine code working on my MacBook but I need to be able to stop the music tracks and also stop sound effects playing, could you please provide method implementations for the ‘stopPlayingMusic’ and ‘stopSoundWithKey’ method, many thanks.
Also, if you could publish another tutorial about ’3D sound’ and how to use it effectively in games then that would be brilliant.
Finally, a word of advice to other iPhone developers out there, I’ve experienced problems when recording sounds in AIF format and then changing their file extension to CAF. Sometimes these sounds do not play correctly, i.e. they are heavily distorted.
I now use the ‘AFConvert’ tool to convert all of my AIF sound files to CAF format and I have not experienced any problems with this new approach.
To do this, load up Terminal and enter the following command (changing the sound sample settings and filenames accordingly):
afconvert -f caff -d LEI16@44100 MyAIFfile.aif MyCafFile.caf
Dan
aslong on June 27th, 2009
Mike,
Wanted to let you know while I was following the tutorial I found a memory leak in the loadSoundWithKey method. When your are returning from AudioFileReadBytes failing the outData variable is not released. Maybe showing the code will help to explain this:
What the tutorial had:
// Load the byte data from the file into the data buffer
OSStatus result = noErr;
result = AudioFileReadBytes(fileID, FALSE, 0, &fileSize, outData);
AudioFileClose(fileID);
if (result != 0)
{
NSLog(@"ERROR SoundEngine: Cannot load sound:%@", theFileName);
return;
}
What it should have:
// Load the byte data from the file into the data buffer
OSStatus result = noErr;
result = AudioFileReadBytes(fileID, FALSE, 0, &fileSize, outData);
AudioFileClose(fileID);
if (result != 0)
{
NSLog(@"ERROR SoundEngine: Cannot load sound:%@", theFileName);
if (outData)
{
free(outData);
outData = NULL;
}
return;
}
Its minor and probably would not cause an issue. Just thought I would let you know. Keep up the great work Mike. I look forward to every tutorial.
Andrew
(Sorry for any weird formatting issues)
willc2 on July 5th, 2009
Hi Mike,
Thanks for sharing your knowledge via these tutorials, they’ve been very informative.
For people having sound format troubles like static or distortion, the problem is the endian-ness of the sound files. Amadeus Pro, which I use, will always save .caf files as big-endian, whereas Mike’s SingletonSoundManager requires little-endian data. You can inspect your files in Quicktime Pro to tell the difference. I made an AppleScript droplet app that calls afconvert and put it on my finder sidebar so I could easily fix my files after I finish editing them.
Blog » 71² » iPhone Game Programming – Tutorial 9 – Sound Manager on July 7th, 2009
[...] posted here: 71² » iPhone Game Programming – Tutorial 9 – Sound Manager Tags: jak-korzysta, jako-rozszerzenie, programming, sound-manager, swoich-kabinach, teatrze-dzia, [...]
David on July 19th, 2009
Hi Mike! I was curious to know what would be required to pause the music and return to the spot where it left off. Is it possible to do without writing a special function or would I need a variable to record the time position?
Thank you for all the hard work on this tutorial! I very much appreciate the time and dedication that has been spent on this.
barry on July 19th, 2009
Hi Mike,
Ditto! I’d love to know the answer to David’s question (posted today, on July 19) regarding pausing the music and returning to the spot where it left off. That would be a tremendous help!!
Thanks!
Mike on July 19th, 2009
Hi guys. I away at the moment so don’t have access to my code, but I’m sure that AVAudioplayer has a pause method you can call, I think it is is in a method I put in the sound class as well. If it is an openal sound you want to pause I would need to check.
Mike
barry on July 19th, 2009
Ah yes, Mike, you’re right — AVAudioPlayer has a pause method (and you did add the “pauseMusic” method to Tutorial 10). I haven’t tried it yet, but after pausing, I’m assuming that all we have to do is call AVAudioPlayer’s “play” method to resume.
Thanks Mike!
Mike on July 19th, 2009
@Barry, you got it, play will will resume from where it was paused.
dnsolo on July 20th, 2009
Hi Mike,
I would like to fade out the music rather than just stopping it, is there an easy way of doing this?
Thanks,
Dan
Mike on July 20th, 2009
Hi Dan, there are no api calls to do this for us that I know if, so I would create a new method in the sound manager called something like fadeOutMusic. This method could take the delta from the update method and use that to update the music volume as you can set the volume of the music and openal separately.
You can then use this method to pause the music when the volume gets to 0 so that I’d you had a fade in method the music will carry on from where it left off.
Not got my code with me as I’m on holiday but that should work ok :0)
Mike
Incredible iPhone Game Programming Tutorials With Video | iPhone Development Tutorials and Tips on July 31st, 2009
[...] 7 – Singleton Class iPhone Game Programming – Tutorial 8 – Particle Emitter iPhone Game Programming – Tutorial 9 – Sound Manager iPhone Game Programming – Tutorial 10 – Game [...]
mike on August 1st, 2009
@aslong, sorry for the delay in getting back to you on your comment. You are of course absolutely right about the memory leak. I’ve been making changes to the Sound Manager this week and I’m just posting on them. I’m going to add this fix to that post.
Thanks for spotting this and sharing, it really helps.
Mike
mike on August 1st, 2009
@dnsolo, thanks for the comments and I’ll certainly do something on 3D sound now I’ve got it working in my game :o)
I’ve only covered the basics in what I have written, but it should be enough to get you and others up and running. I’ll put it on the list and get something out ASAP.
Mike
Anonymous on August 2nd, 2009
Sweet. Thanks Mike for a great tutorial!
My question is – How do you stop audio playing
- (void) stopSoundWithKey:(NSString*)theSoundKey {
[?]
}
I assume its got something to do with
alSourceStop(sourceID)
but I don’t know hoe to find the right sourceID
Ant help would be greatly appreciated
Thanks!
Jonathan on August 2nd, 2009
Sorry , I didnt mean to be Anonymous
chrisk on August 5th, 2009
I’m new to iphone development & mac’s .
When Using your sound manager as a reference i’ve come across a odd problem. Some samples seem to crash the sound manger , all sound fx is lost but the music starts to play again after a 2+ second freeze.
I’m using audacity and then afconvert to make samples.. Any idea?
Its 100% a sample data problem but i’m a little confused as to what.
chrisk on August 5th, 2009
Update simulator works fine, device cause’s problem.
Also noticed that your example file photon.caf is report by afconvert at 44khz but you set it as 22050 in code. if you set it as 44khz it play incorrectly.
Chris
chrisk on August 5th, 2009
looks like a problem with this line
alBufferData(bufferID, AL_FORMAT_STEREO16, outData, fileSize, theFrequency);
as im loading a mono16 sample.
its also why your 44khz sample had to be set as 22050hz to play correctly.
Chris
anonymous on August 5th, 2009
awesome tutorial! Watched the whole thing now I’mm going to use it to make some kind of instrument app. Thanks a lot!
anonymous on August 6th, 2009
@Anonymous (or is it @Jonathan),
I solved this by just doing
NSUInteger soundID = [self nextAvailableSource]-1; //Then alSourceStop(soundID);
This way it just returns the last sound added then stops that sound. It only works if you have just one sound or know the order of the songs being added. This worked in my situation. In this case you can get rid of the WithKey:(NSString*)theSoundKey part in the method because it is not implemented.
I actually didn’t know about the alSourceStop call so you helped me out with that :)
Hope this helps.
MarsMan on August 9th, 2009
Your tutorials are freaking awesome! Thank you for generously sharing your newly acquires openAL knowledge with us!
Do you have any plans on adding the ability to dynamically modify sounds while they are playing? Additions like dynamic pitch change would be great for creating doppler effects (for moving cars, spacecraft, etc.) Dynamic volume change would be cool to use for creating release “envelopes” for sounds. For example, you could put a release on a long ray blaster sound which would play the long version of the sound as long as your finger is held on the screen, but quickly fades to zero as you take your finger off the screen).
mike on August 9th, 2009
Hi MarsMan
I’ve got a new version of the SoundManager which has a few bug fixes included that make it play nice when phone calls or alarms interrupt the sounds :o)
I’ve not done anything on dynamic pitch changing etc, but things like doppler are handled for you by OpenAL. You can set not only the location of a sound source, but its direction and speed. Based on the location of the listener, volume and doppler effects are calculate for you. There is a HUGE amount available in OpenAL and it just takes some configuring. Its worth checking out OpenAL docs to see what is possible.
If I get a chance I will post more on sounds, but I will be posting the new SoundManager shortly.
Mike
Jonathan on August 10th, 2009
Thanks! [anonymous on August 6th]
Unfortunately, I need to be able to target specific sounds to stop…as apposed to the last one added.
Is there a way stop the sound by targeting its key
eg… stopSoundWithKey:@”sound”
Thanks!
CC on August 19th, 2009
What about unloading sounds? If we know we don’t need a sound any more, what needs to be done in order to free up that memory?
More importantly, what are the best practices with regard to loading and unloading sets of sounds? For instance, if you have a set of sounds associated with “level one”, another for “level two”, and another for “main menu”, for instance, what’s the best way of swapping out these sets of sounds? Is it better to load all sounds up front during app initialization, as implied by the interface of your sound manager? Seems like that would be a bad idea in a resource-limited environment like the iPhone, but then, maybe the idea is to have no latency later…
Also, in init, don’t you need to release self before returning nil? You do it for the last “return nil” but not where you say “if(!result) return nil;”
mike on August 19th, 2009
Hi CC
Good point about the removal of sounds and music entries. I’ve added this to my latest version of the sound manager which I will upload when I get home.
As for loading the sounds, your of course right about the memory limits. I would say that if there are not that many sounds or they are relatively small, its ok to load them all at startup to remove any latency by creating them later. If they are level based and having them all in memory is not possible, then removing the old sounds and loading the new ones when the level loads before game play starts would be best, again to remove latency during game play.
Good spot on the missing [self release]. I will add this to the calls before I upload when I get home.
Thanks for the comments :o)
Mike
mike on August 19th, 2009
@Jonathan, that is a method I need to finish. I’ve had a stub in there reminding me to do it for a while :o) so I need to get it sorted.
It just requires some changes that allow the sourceID to be held against the sound key when the sound is played allowing us to stop that source if necessary.
The bit I’ve not sorted yet is the ability to know when a sound has finished so that the sourceID can disassociated from the sound key when the sound finishes playing, like a callback. If I don’t then I may end up stopping some other sound which is now using that sound source.
I’ll take a look and get back to you when I’ve come up with something. All suggestions welcome of course :O)
Mike
CC on August 19th, 2009
Thanks for looking into it. :)
For stopping sounds, the thing I did was loop through all the sound sources and see if they are using the buffer of the sound I want to remove. Not sure if this is the right approach, though. Here’s the code I used, and it seems to work (crossing fingers that formatting is preserved…):
- (void)stopSoundWithKey:(NSString*)theSoundKey {
// Get the buffer ID for the sound key
NSNumber *numVal = [soundLibrary objectForKey:theSoundKey];
if(numVal == nil) return;
NSUInteger bufferID = [numVal unsignedIntValue];
// Loop through the OpenAL sources and stop them
// if it is using the wanted buffer.
for(NSNumber *sourceIDVal in soundSources) {
NSUInteger sourceID = [sourceIDVal unsignedIntValue];
NSInteger bufferForSource;
alGetSourcei(sourceID, AL_BUFFER, &bufferForSource);
if (bufferForSource == bufferID) {
ALenum error;
alSourceStop( sourceID );
alSourcei( sourceID, AL_BUFFER, 0);
}
}
// Remove the object from the sound library
[soundLibrary removeObjectForKey:theSoundKey];
}
Jonathan on August 21st, 2009
Everyone he is awesome… very helpful!
@cc
Thanks for the stopping code. Great way of targeting a key and works well.
The only wierd thing I am getting, is an unused variable warning on
ALenum error;
What is this for?
Cheers
CC on August 21st, 2009
Oh. Sorry about that.
The ALenum error; is a leftover of some error-checking code I had in there to NSLog() any errors that come up. Since it was just NSLog()’ing and not doing anything different functionally, I took it out for clarity.
If you want to, you can put the error checking back in with little trouble – just call alError() after each call and log an error message based on the result.
MarsMan on September 7th, 2009
@CC wrote some great code for targeting and stopping a key.
Does anyone have a good method of stopping all playing sounds at once? I don’t see an openAL function which accomplishes this.
mike on September 7th, 2009
@MarsMan, your right that there is no single command to stop all OpenAL sounds. The easiest way would be to loop through all your sources stopping anything playing.
That’s the only way I can think of doing it.
Mike
Simon on September 12th, 2009
No sooner did I think I had it all worked out than this happened. I got the following error message when trying to build the project:
Undefined symbols:
"_AudioFileGetProperty", referenced from:
-[SoundManager audioFileSize:] in SoundManager.o
"_AudioFileReadBytes", referenced from:
-[SoundManager loadSoundWithKey:fileName:fileExt:frequency:] in SoundManager.o
"_AudioFileClose", referenced from:
-[SoundManager loadSoundWithKey:fileName:fileExt:frequency:] in SoundManager.o
"_AudioFileOpenURL", referenced from:
-[SoundManager openAudioFile:] in SoundManager.o
Any ideas what this means?
mike on September 12th, 2009
Looks like it’s a missing framework. Make sure that you have got the AudioToolbox framework added to your project.
Let me know if that does not work.
Mike
Simon on September 12th, 2009
First off thanks for the quick response. Second you were spot on.
Thanks again
Pascal on September 22nd, 2009
Hi Mike at first i would like to say thanks for your great Tutorials.
I saw that you still have no solution for the warning inside the allocating for the AVAudioPlayer.
I hope I can fix this problem with you.
The warning says “distinct Object-C type”. If you click on “Jump to Definition” for “initWithContentsOfURL:error:” you will see that there is no explicit definition for this.
AFAIK: The type of an [Class alloc] is id, that’s why the compiler doesn’t know which “initWithConentsOfURL:error:” he is supposed to use.
This new code will explicit cast the AVAudioPlayer class and fix the warning.
backgroundMusicPlayer = [(AVAudioPlayer *)[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
(I didn’t now the right syntax for posting code, but still hope this works ;)
Please tell me if I’am not 100% correct with my Opinion ;)
Regards
Pascal
mike on September 22nd, 2009
Hi Pascal
Thanks for your post. I’m currently using Xcode 3.2 and SDK 3.1 and I don’t get any errors when compiling the sound manager which contains the allocation of the audio player. Which version of the SDK are you using?
Mike
Pascal on September 22nd, 2009
Hi Mike
I currently using Xcode 3.1.3 and SDK 3.0 I downloaded the Project File and compiled this for SDK 2.2 and for SDK 3.0 . But I didn’t get any error I only get the warning which is also shown in your Tutorial Video at time 41:00 in Line 289.
I will download the new Version of XCode and the new SDK to test. But my post will fix the problem for the Tutorial ;)
Regards
Pascal
gN0Me on September 28th, 2009
Hi, Mike!
I have a problem with using Sound Manager for MP3 and AIFF files. I try to change value of frequency and format of buffer but everytime I got only noise. The same file in CAF of WAV format plays fine. Could you help me? Thanks.
BTW: I used Audacity to convert files.
gN0Me
iPhone Game Programming – Tutorial 9 – Sound Manager | 71² – The … | IPhoneMate on September 29th, 2009
[...] the original post: iPhone Game Programming – Tutorial 9 – Sound Manager | 71² – The … Share and [...]
Marsman on October 11th, 2009
Mike,
I thought you might like to see your SoundManager class on steroids. My app is currently awaiting Apples approval.
I get a few pops and clicks (some faintly audible in the YouTube demo). I’m sure it’s because I am taxing the limits of openAL and using long 44k samples.
B.T.W., if this app sells I will be sending you a gift!
jimbob1971 on October 15th, 2009
Apologies if you covered this in the tutorial – I’m on the early ones and just whizzed through, but where does the music track come from? It sounds like an old C64/Amiga game, but I can’t remember which. Thanks!
mike on October 15th, 2009
Hi jimbob1971, the sound track is a Bomb The Base track called Megablast. It was used in the Bitmap Brothers shooter called Xenon II – Megablast on the Commodore Amiga amongst other platforms :o)
Mike
Remi on October 28th, 2009
Just needed to say thanks!
Saved me from fighting with openAL for at least a couple of days.
Thorsten on November 2nd, 2009
Hi Mike,
thank you for your great tutorials. They gave me a brilliant starting point after struggling with iPhone development about half a year!
But I also have a question: Using the SoundManager class my little app doesn’t play Sounds after receiving calls or timer events. Where can I start to find a solution for this?
Thank you,
Thorsten
mike on November 2nd, 2009
Hi Thorsten
I’m glad that the tutorials have been useful. There is a fix for your sound problem. It is to do with recognising when an interruption has occurred such as an alarm or phone call and then dealing with it correctly.
I am going to create a forum entry in the Sound Tutorial topic which shows how to fix the problem. I may even post my latest sound engine which already has the necessary changes.
Check back soon and the info should be there.
Mike
Joe on November 2nd, 2009
Mike,
I present a modalview to allow the user to select and play music. When I dismiss the controller touches in the game loop are no longer detected. Any ideas?
Thanks!
Andrew on December 8th, 2009
Hey Mike
Thanks for the sound engine in tutorial 9 its been an unbelievably great assest in making my game for my masters.
One thing i do ask though is how do i make the audio fade out and fade in rather than pressing start game and it just stops??
I will also say you sound engine works great alongside the cocos2d package nicely!! If you could help me with the question it would certainly add a nice touch to my game.
Thanks again and keep up the good work
Andrew :)
jeff951 on December 15th, 2009
Hi Mike
I am currently working on a iPhone game and have especially found your tutorials very helpful they go though everything very well. But I was wondering in regards to this tutorial here do you know if there is a issue with 3.1 as i have the code that you have and it does not work and when i tried to run your code in 3.1 it would not work either. Any help you can give on this would be great!
Jeffrey
RRdaS on December 31st, 2009
Hi Mike. Thank you for your great tutorials!
I didn’t realize when you changed the routines, but if you uncomment the line in EAGLView.m:
[playerShip1 renderAtPoint:CGPointMake(140, 240) centerOfImage:YES];
It will cause a program crash, and this line of code was working in the past.
In my understanding, using getSubImageAtPoint is a good way to have an independent “enemy” with the same texture.
Should I consider getSubImageAtPoint obsolete in your routines?
Thanks.
RRdaS
iphone developer on January 4th, 2010
Mike,
Awesome tutorial! Only thing is I tried applying this to my latest project which is a game that is similar to an old school pong but with a different theme (im going to keep it a secret for now until its release, ill keep you posted).
I had some trouble getting OpenAL sound but eventually figured it out. Definitely sounds better when the user has headphones on. I set it up so you can hear sound from different ears based on where the ball hits. Anyways, definitely good knowledge here!
Thanks.
Barry on January 8th, 2010
Hi Mike,
Thanks for the Sound Manager tutorial. Great stuff! I’m using a slightly older version of your Sound Manager. However, I need to be able to unload sounds when I no longer need them. I have about 100 64K .MP3 files, and I only need to play one of them at a time; but my app is crashing after I have loaded about 40 of them. I’m assuming that it’s a memory problem, so I wanted to call the “removeSoundWithKey:” method (which you provided in SM) before I load each new sound file; but that method causes the app to crash. I noticed that this method is no longer in your latest version of SM. For your quick reference, I’ve included the code for the “removeSoundWithKey” method (un-modified). Is there an easy fix for this method, or should I be using another approach (or a different file format)?
Please advise ASAP. Thank you very much for your help.
Barry
********************
- (void)removeSoundWithKey:(NSString*)aSoundKey {
// Find the buffer which has been linked to the sound key provided
NSNumber *numVal = [soundLibrary objectForKey:aSoundKey];
// If the key is not found log it and finish
if(numVal == nil) {
NSLog(@”WARNING – SoundManager: No sound with key ‘%@’ was found so cannot be removed”, aSoundKey);
return;
}
// Get the buffer number form the sound library so that the sound buffer can be released
NSUInteger bufferID = [numVal unsignedIntValue];
glDeleteBuffers(1, &bufferID);
[soundLibrary removeObjectForKey:aSoundKey];
if(DEBUG) NSLog(@”INFO – SoundManager: Removed sound with key ‘%@’”, aSoundKey);
}
Barry on January 8th, 2010
Hi Mike,
Well, sometimes the answer is so easy that you don’t even notice it. I’m now using the AVAudioPlayer method s.t. when I load sounds, only the file paths are loaded (not the entire sound file). Problem solved.
BTW: If you do have a quick fix/idea for the “removeSoundWithKey:” method, I’d still love to know it.
Thanks,
Barry
mike on January 8th, 2010
Hi Barry
I’ve checked my current sound manager code and its using exactly the same code you posted to remove a sound. I’m using it in SLQ to remove sounds when you leave the main game to same memory and its working ok. I also tested it when removing a sound key that does not exist and that works ok as well.
Do you have more info on the crash you are getting. Is it EXC_BAD_ACCESS for example?
Mike
Jonathan on January 10th, 2010
Hi, Mike (and other 71squared Sound people)
I also am having trouble with “removeSoundWithKey” … At first it seems to do what it is meant to do – it removes the sound and I can’t access it again unless I reload it. BUT, when I test my apps dealloc’s with ‘Instruments’ it doesn’t show any deallocation. It doesn’t seem to free up the memory.
My app is a level based app, which loads and removes sounds for each individual level. Since removing sounds doesn’t seem to be releasing the memory my app eventually crashes with this message:
————————————-
Program received signal: “0”.
warning: check_safe_call: could not restore current frame
kill
quit
————————————-
In a desperate attempt to find a solution, I have even tried using your “shutdownSoundManager”
…But I don’t know how to force it to start again.
Any ideas?
Thank you very much for your help.
Jonathan on January 10th, 2010
Hi, its’s Jonathan again.
I have created a ultra simple, striped back version of your sound engine. It has a view with a loadSound, playSound and removeSound button.
You can download it here :
http://www.tuistudios.com/iphoneDev/
If you run it through an objectAlloc Instrument, you should notice that it doesn’t seem to release what it loaded. This eventually crashes my app.
Am I doing something wrong?
Does your removeSoundwithKey have these problems?
(Note: I used a ‘unloadSoundWithKey’ instead of ‘removeSound’ because the later doesn’t stop a sound if it is looping – as in this case)
Thank again.
mike on January 10th, 2010
Hi Jonathan, I’m sat working on the book at the moment so I’ll check this out now and get back to you shortly :o)
The next chapter I’m starting is on the sound engine so this is interesting to me as well.
Mike
mike on January 10th, 2010
Hi Jonathan
OK, this is odd. There were problems in the removeSoundWithKey method. An error was reported every time alDeleteBuffers was called which meant the buffer was not being destroyed.
I have re-written that method so that it now unbinds the buffer from any source that have played it or are playing it. Unbinding like this causes the alDeleteBuffers to work. It checked out the OpenAL dev guide and it does say in there that a buffer will not be deleted if it is still bound to a source, so I should have spotted that before.
One other odd thing I came across is that if a sound is playing in a source, you can query the source for the buffer which is playing. If a sound has played in a source and finished, the query will give you 0, even though you still have to unbind the buffer from that source else the delete buffer will fail.
I got round this by unbinding the buffer from all sources not playing anything, and from any sources playing that do have that buffer number returned. That side of things looks to be working ok.
Having done all that, I still see an allocation increase when removing and then loading a sound in your test app.
I’m stumped a little now. If the OpenAL calls are now working, then I’m not sure why allocations are not being removed. It could be caching that OpenAL is doing and it will eventually remove the data, but I’ve not read anything that says it works that way.
I’ve put the new sound manager class up at the following link. Take a look and see if that helps with your crashing.
If anyone else has any comments feel free to jump in :o)
Jonathan on January 11th, 2010
HI, Mike
Thanks for the response.
Yes, unfortunately, it still crashes my app.
I have uploaded the test app with your new code in it – SoundEngine_02.zip
http://www.tuistudios.com/iphoneDev/
I will keep researching.
Does anyone else have sounds releasing ok?
Thanks
Jonathan on January 11th, 2010
Well, I have worked something out!?
I haven’t solved it but I have managed to ‘free’ the buffer for a single sound. Which proves that it indeed can be done. I can see it being dealloc’ed in ‘Instruments’.
The problem is I can’t get it to work for multiple sounds. It only seems to remove the buffer for the last sound loaded.
Here is what I did :
——————————————
Soundmanager.h –
ALvoid *bufferData;
Soundmanager.m –
I removed: ALvoid *data;
I changed everything “data” to “bufferData”
Then I added a timer to trigger the below removeSoundWithKey
…
alSourcei(currentSourceID, AL_BUFFER, 0);
NSTimer *freeBuf = [NSTimer timerWithTimeInterval:0.2 target:self
selector:@selector(freeBuffer) userInfo: nil repeats: NO];
[[NSRunLoop currentRunLoop] addTimer:freeBuf forMode:NSDefaultRunLoopMode];
…
-(void)freeBuffer {
free(bufferData);
}
—————————————–
So, yeah…please dont think I am posting this because I am proud of it. I am actually embarrassed at how crap this is. But I thought I would post it in case it could be a clue to you as to what is going on with the buffers.
“free(bufferData);” (or the “data” loaded in loadSoundWithKey) does actually work. But my crap set up only deletes the most recently loaded.
Cheers
Barry on January 12th, 2010
Hi Mike,
Sorry for my delayed response (I’ve been unable to do further testing until now).
Thanks for the updated “removeSoundWithKey” method. But for some reason, it still crashes my app after calling the routine 50 or 60 times. I’m assuming that memory is maxing out due to the sounds not being released (?)
When it crashes, the console displays the following error:
“Program received signal: “0″. warning: check_safe_call: could not restore current frame.”
Thanks,
Barry
mike on January 18th, 2010
Hi Barry, I managed to find the memory leak in the sound manager class :o)
You may have already found it, but if not the problem was in the loadSoundWithKey method. I was setting data to be populated with the sound data from the sound file using
data = MyGetOpenALAudioData(fileURL, &size, &format, &freq);
and then was never freeing that memory again. I needed to add
if (data)
free(data);
after performing the alBufferDataStaticProc and also before
data = NULL;
Doing this stops the allocations rising and frees the memory correctly.
I hope this helps you as I feel real dumb for not spotting it sooner.
Let me know how you get on.
Mike
Jonathan on January 19th, 2010
Thank you Mike for keeping us in the loop!
However, I still can’t seem to get it to work.
The “free (data):” seems to clear the buffers before I can play them – So when I go to play the sound, the app crashes.
I have uploaded that simple sound engine app again with your adjustments.
http://www.tuistudios.com/iphonedev
I really don’t want to take too much of your time but could you please check to see if I have free’d the data in the right spot. I can’t seem to work it out?
Or are you able to re-upload your Sound Engine.
Thank you in advance.
mike on January 19th, 2010
Hi Jonathan
I’ve downloaded your project and the free is in the right place. The sound engine works fine for me without making any changes at all, on both the sim and the real device. The music plays, I can then remove it, load it and play it again. The same sound engine is also working ok in SLQ with those changes.
The only other change I would make in the loadSoundWithKey method is to change alBufferDataStaticProc to alBufferData. It works ok in your project if you use either, but alBufferData means OpenAL is responsible for the buffer data once it is loaded, alBufferDataStaticProc means we are responsible for the data which unless you need to control memory very very closely is not needed and is more hassle than its worth. I made the mistake of using that in my original sound engine but found that info out since.
When your app crashes what error are you getting and where.
I’ve posted my current sound engine at http://www.71squared.com/iPhone/SoundClasses.zip
Mike
Jonathan on January 19th, 2010
Hi, Mike and thank you for your quick response.
Below are the steps in the crash of the app.
1- The app loads and everything is fine
2- I press “play” and there is no sound
3- The “play” button hangs on highlighted state.
4 -Then the iPhone simulator drops behind all open apps, making Xcode active.
5- there is no errors in the console.
6- The debugger shows the app stops on all the stuff to do with playing:
alSourcePlay (sourceID);
0x0003654a jmp 0×36557
0x0003654c mov (%edx),%eax
7- If I force it to continue I get a “EXC_BAD_ACCESS” error
Having said all that, I changed alBufferDataStaticProc to alBufferData, as you suggested.
Which does seem to make everything work. That’s great, but it does seem strange I can’t use
alBufferDataStaticProc and you can?
Thanks for your help!
Marsman on January 19th, 2010
I experienced the same results as Jonathan when implementing the free(data) code. Sound trigger button hangs in the hi-lighted state. Sound does not play.
I am using xCode 3.2.1
Barry on January 20th, 2010
Nice catch, Mike! The changes you suggested for the loadSoundWithKey method worked perfectly. Thanks so much!
Barry
mike on January 20th, 2010
Hi Marsman/Jonathan
Have you tried the sound manager with the free(data) and also having changed alBufferDataStaticProc to just alBufferData. The static version means you control the buffer data so freeing the data will free the buffer contents giving you all sorts of problems. alBufferData means OpenAL controls the buffer and has its own copy, letting you free up the data.
Let me know
Mike
Jonathan on January 21st, 2010
Hi, Mike.
Yes. The alBufferData works. Thank you very much.
Jonathan.
Kev on February 25th, 2010
I want to be able to break up the conversion of long mp3s and display % complete.
Is there a way to append more data to an existing buffer along the lines of (in alBufferDataStaticProc) doing something like this (but with some sort of append call instead of starting again)?
if (proc)
{
int chunkSize = 100;
int chunk = size / chunkSize;
int offset = 0;
for (int i=0; i<chunkSize; ++i)
{
/*
call to update graphics with % complete
*/
proc(bid, format, data + offset, chunk, freq);
offset += chunk;
}
}
Obviously this just leave the last 1% of the track in the buffer.
Thanks,
Kev
Kev on February 25th, 2010
As a follow up to my post above: I am finding that when trying to play long MP3s the delay in getting the sound ready results in problems with the touch interface and accelerometers. By breaking up the conversion it prevents these problems (presumably by letting the OS get a look in frequently enough).
PS. Briliant article!
Simon on April 8th, 2010
Hi Mike,
I wanted to check that I was right in my thinking that the AVAudioSessionDelegate protocal cannot be used on older version of the OS such as 2.2.1.
I only ask as when I try and created a release version of my game for 2.2.1 I get an error message complaining that AVAudioSessionDelegate declaration cannot be found.
I just wondered if by including this I’m not excluding certain people from running my app.
Have you has a similar experience?
Please note I only get this error one building a release version and only if the release is for 2.2.1
TrevorNewsome on May 12th, 2010
In the sound manager there is no way to stopsoundwithkey function, is there a simple way of doing this? I have a sound on loop but I have no way of stopping it.
- (void) stopSoundWithKey:(NSString*)theSoundKey {
}
Best wishes Trevor.
mike on May 12th, 2010
Hi Trevor, try the method below which is what I use in the sound manager for SLQ.
- (void)stopSoundWithKey:(NSString*)aSoundKey {
// Reset errors in OpenAL
alError = alGetError();
alError = AL_NO_ERROR;
// Find the buffer which has been linked to the sound key provided
NSNumber *numVal = [soundLibrary objectForKey:aSoundKey];
// If the key is not found log it and finish
if(numVal == nil) {
NSLog(@"WARNING - SoundManager: No sound with key '%@' was found so cannot be stopped", aSoundKey);
return;
}
// Get the buffer number from
NSUInteger bufferID = [numVal unsignedIntValue];
NSInteger bufferForSource;
for(NSNumber *sourceID in soundSources) {
NSUInteger currentSourceID = [sourceID unsignedIntValue];
// Grab the buffer currently bound to this source
alGetSourcei(currentSourceID, AL_BUFFER, &bufferForSource);
// If the buffer matches the buffer we want to stop then stop the source and unbind it from the buffer
if(bufferForSource == bufferID) {
alSourceStop(currentSourceID);
alSourcei(currentSourceID, AL_BUFFER, 0);
}
}
// Check for any errors
if((alError = alGetError()) != AL_NO_ERROR)
NSLog(@"ERROR - SoundManager: Could not stop sound with key '%@' got error %x", aSoundKey, alError);
}
Let me know how you get on.
Mike
TrevorNewsome on May 12th, 2010
Hi Mike,
That works like a dream, thank you very much, my game is nearly complete and wouldn’t have been possible without your fantastic tutorials and snippets of help. I have made sure you have a mention in my credits with also a link to this website. As soon as I get the application submitted (hopefully in two weeks) I will post you a link to it.
Cheers again Trevor.
Anonymous on June 4th, 2010
Hi Mike,
I’ve been trying to get the stopSoundWithKey method to work and this is what I ended up with which seems to work so far.
- (void)stopSoundWithKey:(NSString *)key {
NSNumber *index = [soundLibrary objectForKey:key];
if (index == nil) return;
NSUInteger sourceID = [index unsignedIntValue];
alSourceStop(sourceID – 32);
}
It seems the reason the alSourceStop wasn’t working is because the original sourceID of the sound was 2400 when I checked, but the sourceID returned by the [soundLibrary objectForKey:key] call was 2432 which was wrong. I couldn’t figure out why the value was off by 32. The above solution is a hack but it seems to work.
Also awesome tutorials!
Barry on July 13th, 2010
Hi Mike,
I love your Sound Manager — great stuff! But I have a problem…
I was using a very old version of Sound Manager (one of your earliest versions), and all of the volume levels on my 16-bit sounds (some mono, some stereo) were balanced nicely. I then upgraded to the latest version of Sound Manager — which caused all of my MONO sounds to have very low volume levels (even though their gains are set to 1.0f, and the master sound FX volume is set to 1.0f).
It appears that all of the mono sounds are only coming out of the RIGHT channel (which is probably causing the low volume). However, with the old Sound Manager, the mono sounds were coming out of both the right and left channels.
How do I get the new Sound Manager to send the mono sounds to both channels?
Thanks for your help!
Barry
Barry on July 13th, 2010
CORRECTION:
It may be the LEFT channel to which the mono sounds are going. In any case, the mono sounds are only going to one of the channels, not both.
Thanks,
Barry
mike on July 14th, 2010
Hi Barry
Can you email an example of a sound file doing this to mike@71squared.com and I’ll take a look.
Thanks
Mike
PavanK on September 8th, 2010
PavanK on September 8th, 2010
Hi mike i would like to say a big thank you for taking the time and effort to create a video explaining exactly what youre code does. I’ve learnt more about OpenAl in the past 2 hours then i have in the past two days (that’s when i started)
I am creating a drum application at the moment for the iphone, and have been using PlaySystemSound obviously that is not apropriate for game sounds as it does not play straight away and sometimes doesnt even get played.
So i transitioned over to OpenAL to give it a go mainly because i can change the pitch of a sound live.
This morning i followed tutorial 9 – Sound Manager
All i did was start up a window based application, added 2 view controllers. on one of the view controllers i added abutton so i could play the sound.
I added the 2 sound manager files. And there were no errors upon build.
now i just needed to load the sounds.
I dont have a game loop so i couldnt initialise it there.
So in my BlueViewController i did this:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
sharedSoundManager = [SingletonSoundManager sharedSoundManager];
[sharedSoundManager loadSoundWithKey:@"NormalGe" fileName:@"NormalGe" fileExt:@".caf" frequency:22050];
[sharedSoundManager loadSoundWithKey:@"NormalNa" fileName:@"NormalNa" fileExt:@".caf" frequency:22050];
[sharedSoundManager loadSoundWithKey:@"NormalKe" fileName:@"NormalKe" fileExt:@".caf" frequency:22050];
[sharedSoundManager loadSoundWithKey:@"LoudGe" fileName:@"LoudGe" fileExt:@".caf" frequency:22050];
[sharedSoundManager loadSoundWithKey:@"LoudNa" fileName:@"LoudNe" fileExt:@".caf" frequency:22050];
[sharedSoundManager loadSoundWithKey:@"LoudKe" fileName:@"LoudKe" fileExt:@".caf" frequency:22050];
[sharedSoundManager loadSoundWithKey:@"LoudRa" fileName:@"LoudRa" fileExt:@".caf" frequency:22050];
}
return self;
}
I get no warnings the app gets succesfully installed on my iphone, but when it runs it. a SIGABRT error.
if i take the initialisation out of the sounds my app works fine.
could you please tell me whats going on?
thank you
and i appreciate everything that you are doing for the community
Simon on September 8th, 2010
How large are the sound files? It may be a memory issue!
I’m assuming you’ve added all the frameworks need to run the soundmanager.
#import
#import
#import
#import
And also included the items from
#import “Common.h”
that are necessary for it to work
Simon on September 8th, 2010
whoops the Frameworks
OpenAL
AudioToolbox
AVFoundation
Also if you’re trying it in the device check the stack trace in the debug console for more info – this can take a few moments to come through on screen.
PavanK on September 8th, 2010
Firstly i would like to thank you for your swift reply.
Ok simon, the sound files are very very small. They’re not large at all, not more than a second long.
they’re all simple drum sounds.
I definitely have all the sounds in place.
Heres my project
http://www.2shared.com/file/PX.....tcher.html
Click at the bottom right its in small writing that says “Save file to your PC: click here”
Now if you build the project everything works fine.
But then if you uncomment the code in the blueviewcontroller class initwithNibName section then build again the error gets produced
if you could have a look and maybe add the common.h file that would be great thanks
And no i have not added the common.h class as Mike in the video mentions that it is not needed?
hmmmt thats strange?!
its really frustrating. Ive been banging my head about this since morning.
PavanK on September 8th, 2010
Hi, simon I’ve even added the common.h file
and added the location input for one of the methods as i took that out before in the
- (NSUInteger) playSoundWithKey:(NSString*)theSoundKey gain:(ALfloat)theGain pitch:(ALfloat)thePitch location:(Vector2f)theLocation shouldLoop:(BOOL)theShouldLoop;
method.
but now ive changed it to that now. and still i get the SIGABRT error.
what can i do?!
Simon on September 8th, 2010
Re the Common.h i didn’t check if it was used, just saw that it was included. It’s been a while since I watched the vid.
Regarding the file, I tried to download it but that it just failed.
Have you checked the stack trace?
PavanK on September 8th, 2010
http://www.speedyshare.com/fil.....itcher.zip
hey i uploaded it to a different website
please give it a go.
download works fine ive tried it
and im still stuck on the same thing.
heres what the console says:
2010-09-08 21:58:29.681 View Switcher[4175:207] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[NSURL initFileURLWithPath:]: nil string parameter’
2010-09-08 21:58:29.728 View Switcher[4175:207] Stack: (
31904859,
2504496393,
31988795,
31988634,
350119,
349304,
13120,
12617,
10690,
8425,
4571522,
4579275,
2740390,
2779178,
2767752,
2750163,
2777269,
40001233,
31689600,
31685704,
2743913,
2781187
)
Simon on September 8th, 2010
Well I still can’t get it, but it sounds like a file is missing or not named correctly. Does the app run in simulator?
Either way do the following:
1) Check the sounds file names (they are case sensitive)
2) do a “clean all”
If it still doesn’t run, remove the sound files from your project (ensure you move to trash) and add them again to your project and clean and build.
PavanK on September 8th, 2010
simon i did everything you told me to do. and still it doesnt work.
you said that my file may be missing, and you emphasized that i need to check the console stack trace. Instead i put breakpoints throughout my project and i find that when this line gets called:
NSString* filePath = [[NSBundle mainBundle] pathForResource:theFileName ofType:theFileExt];
Thats where the error is.
now my files can be found because when the debugger stops at this line due to a breakpoint, i hover over the input names: theFileName and it tells me the correct file name and then i hover over the second input theFileExt, and it gives me the correct value it says .caf
but when i hover over the variable NSString *filePath it says nil! so when it goes onto the line
NSURL *afUrl = [NSURL fileURLWithPath:theFilePath];
it throws an exception as a NSURL cannot be created from a nil value. hence the reason i am getting this error!
now that weve been able to understand what the problem is, how do i get this:
NSString* filePath = [[NSBundle mainBundle] pathForResource:theFileName ofType:theFileExt];
to generate a proper NSString value rather than it being nil?
thanks a lot simon for your help so far
PavanK on September 8th, 2010
sorry one more thing; obviously the sound files can be located hence the values appear when i hover over the line during debugging mode. but when it tries to put that into a string into the variable filePath it doesnt work it says nil.
thats the problem
lol any help would be great.
The strange thing is that other guys in other forums like mike, ben britten have used the exact same line yet it produces an error with me?! lol
PavanK on September 9th, 2010
ok after spending non stop obviously having dinner and snack times inbetween with a movie as well, but other than that coding coding coding, ive managed to find out what the problem was.
its 1:30am in the morning and im glad ive been persistent and tenacious. See the problem was when i was loading the sounds
remember how i said this is what i wrote:
sharedSoundManager = [SingletonSoundManager sharedSoundManager];
[sharedSoundManager loadSoundWithKey:@"NormalGe" fileName:@"NormalGe" fileExt:@".caf" frequency:22050];
[sharedSoundManager loadSoundWithKey:@"NormalNa" fileName:@"NormalNa" fileExt:@".caf" frequency:22050];
[sharedSoundManager loadSoundWithKey:@"NormalKe" fileName:@"NormalKe" fileExt:@".caf" frequency:22050];
[sharedSoundManager loadSoundWithKey:@"LoudGe" fileName:@"LoudGe" fileExt:@".caf" frequency:22050];
[sharedSoundManager loadSoundWithKey:@"LoudNa" fileName:@"LoudNe" fileExt:@".caf" frequency:22050];
[sharedSoundManager loadSoundWithKey:@"LoudKe" fileName:@"LoudKe" fileExt:@".caf" frequency:22050];
[sharedSoundManager loadSoundWithKey:@"LoudRa" fileName:@"LoudRa" fileExt:@".caf" frequency:22050];
well for the second value which was the ‘fileExt’ input i typed in @”.caf” instead of @”caf” as it is an extension i dont need to have the fullstop before the word caf! thats where the problem was so it could find a fullpath and therefor was returning nul! but now it works.
now im just going to play the sound and see if it works! but other than that thanks a lot for your help simon. definitely did help me. thank you
Simon on September 9th, 2010
So it was the file names not being inputed correctly :)
Glad you got to the bottom of it all
PavanK on September 9th, 2010
Yeah you were totally right that i needed to check the names. how i named them in my code. you dont need a full stop.
and mike i just want to tell you that your code is EXACTLY what i needed.
there is absolutely near to 0 latency when i play the sounds. im alternating between my buttons on my soundboard really quickly and the files just get played exactly how ive been wanting to. so thanks.
im just having one problem!
im having th same problem as the first or second comment about the sounds not being played properly and its playing as if its been speeded up.
i tried different numbers it just makes it worse.
i then went back to the original sound file,
i have 16 bit uncompressed 44.1k sampled wavs. which i converted to caf using afconvert with the LEI16 thing.
now i put it back into the program and now there is no output at all?! any help?
ive debugged the program and the sounds are definitely being loaded and the right information being passed on when it comes to playing the sound.
i think its something to do with the frequency and something to do with the code in the loadSoundWithKey method where it says:
alBufferData(bufferID, AL_FORMAT_STEREO16, outData, fileSize, theFrequency);
especially the part with AL_FORMAT_STEREO16
and input i am giving for theFrequency which is a value of 22050
i know a few people have come across this, any suggestion would be greatly appreciated.
PavanK on September 9th, 2010
hi i followed ben brittens AFCONVERT
and that worked like a charm
/usr/bin/afconvert -f caff -d LEI16@44100 inputSoundFile.aiff outputSoundFile.caf
so puts the file into a nice Little Endian 16-bit 44,100 sample rate format.
so the frequency i changed it to 44100 as the input
and thats it. everything works nicely.
i can now design my app. since the fundamentals are working
thanks to simon ben and mike
thank you all
mike on September 9th, 2010
Hi PavanK, I’ve come into this conversation late and missed the juicy bits :o) although it looks like Simon has been providing great support.
I’m glad you got the problem resolved and can move onto getting your app started.
Mike
PavanK on September 12th, 2010
Hi mike how are you, great to speak to you.
I want to thank you for the support
i would like to give an update to my application.
The app is working in full working condition.
OpenAL ROCKS, i should instead say that the soundmanager class rocks.
from any viewcontroller that i am in i can access the soundmanager class and be able to invoke methods to play the sound i want played which is amazing.
my code is so much more cleaner thanks to you mike and also ben britten.
Mike is there any way i would be able to contact you directly as i would like to ask you a question about a ViewSwitcher class that i am trying to create and would like your assistance.
thanks in advance.
Another thing, I’ve just opened up xcode to carry on with my lovely project and to enhance the soundmanager class but xcode will not load up now
i come across this error..
I am using xcode 3.2.2, so i can build for my iphone 3.1.2.
File: /SourceCache/DevToolsBase/DevToolsBase-1648/pbxcore/Target.subproj/PBXTarget.m
Line: 1603
Object:
Method: createPropertyExpansionContextWithBuildState:
Platform failed to completely load. Examine Console Log for error messages.
Can you help me and maybe tell me what i can do. the internet is not coming up with anything!
thanks in advance.
iPhone Game Programming Tutorial 1 | Hardblog Cafe on October 6th, 2010
[...] iphone-game-programming-tutorial-8-particle-emitter iphone-game-programming-tutorial-9-sound-manager iphone-game-programming-tutorial-10-game-structure iphone-game-programming-tutorial-11-joypad [...]
raonboy on October 20th, 2010
great!
but i m suffering a lag when playing sound.
the sound did not play immediately when i call the play music.
Did it run smoothly on your project?
I’m on VMware
does it cause by VMware environemt?
And a lag between loops too, please help.
Thanks you very much.
Sorry for my bad English
raonboy on October 20th, 2010
Ur book is fantastic, i bought one online :D
THanks
Rana Hammad on October 22nd, 2010
Excellent Tutorial Mike!
I wanted to know whether have you tried to get hold of playing audio’s amplitude/wavelength or anything in order to create a wave with spikes.
Actually, I want to develop a music player with a sine wave which will have amplitudes of different heights based on music file’s beat.
Any guesses, how can I go about it?
Thanx for your concern. If possible, plz respond me via an email.
Player Profiles on October 30th, 2010
Best you could change the page name title iPhone Game Programming – Tutorial 9 – Sound Manager | 71² – The ramblings of two 30-something developers to more catching for your content you write. I enjoyed the blog post withal.
mike on October 30th, 2010
Hi Rana
To start creating your own tones etc you would need to look at the Audio Units API. There was a recent blog post on how to do this at
http://cocoawithlove.com/2010/.....on-to.html
Hope that helps.
Mike
Marsman on November 26th, 2010
Has anyone successfully created a callback which notifies when a sound has finished playing? In my app, I am triggering a sound with a button. I would like my button be hi-lighted until the sound stops playing.
Hank on December 2nd, 2010
You are a lifesafer! Searched around everywhere for a tutorial about sound. Keep up the good work!
callinfix on December 18th, 2010
Hi Mike,
The video tutorial is for singletonSoundManager but your most recent sound manager is posted on January 19th, 2010? So what are the differences?
How to pause and resume the sound when there is an interruption? How to implement it to the original singletonSoundManager?
callinfix on December 21st, 2010
Hi Mike,
I wonder how often you will read your tutorials’ comments?
mike on December 21st, 2010
Hi callinfix
Busy time of year at the moment with family and work, as I’m sure you’ll understand.
The latest sound manager basically fixes some memory leaks and does handle sound interruption correctly. I’ve been meaning to post the sound manager code I used in SLQ, which is the very latest version I have with all the bug fixes I and others have found.
It’s been a while since I worked on the sound manager class and can’t remember all the differences between the tutorial code and the latest version, but the latest code should be used and should just be a straight swap out for the older code.
Hope that helps.
Mike
callinfix on December 21st, 2010
Oh Mike,
thanks for your quick reply. For sure I understand your plate is full most of the time, not only this holiday season. That was just a question out of my curiosity. Oh, would you still show us tutorials for iphone or will move to other stuff?
By the way, will you publish other iphone game book? If yes, I hope you would include topics like how to handle multiple views and how to due with interruption, etc
Have a good holiday!
mike on December 21st, 2010
Thanks callinfix and a happy holiday to you as well :o)
I am definitely going to be doing more tutorials in the new year and I’ll look to cover the topics you have mentioned. There are so many things that could be covered, I’m spoilt for choice :o)
Mike
jon griffin on December 21st, 2010
Thanks for the Audacity recommendation. I’m beginning to work in game programming and it’s already helped me out a lot. Def stopping by here again to learn about more resources.
Rick on January 1st, 2011
Hi Mike,
I’d also like to thank you for this tutorial. It’s helped me quite a bit with my application!
Recently you mentioned (in the comments) that you planned on posting your latest SoundManager code. Do you still plan to do so?
I’ve been using the code from Jan, 18 2010. Most of the time it runs flawlessly, however I have seen a couple of instances where removeSoundWithKey throws an error when deleting the buffer.
Here’s the relevant part of the crash log:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0xd400183e
Crashed Thread: 0
Thread 0 Crashed:
0 OpenAL 0x000015c8 OALBuffer::CanBeRemovedFromBufferMap() + 64
1 OpenAL 0x00009f40 alDeleteBuffers + 316
2 iPlayByEar 0×00021386 -[SoundManager removeSoundWithKey:] (SoundManager.m:241)
…
Perhaps your latest code addresses this problem already. If so, I’d love to have it!
-Rick
mike on January 1st, 2011
Hi Rick
I’ll get the code posted tomorrow on the blog. I’ve not seen the error you have posted before, but if you have a set of actions that can reproduce it I’ll check it out.
Cheers
Mike
Rick on January 2nd, 2011
I look forward to getting the new code. Thanks, Mike!
As for the error, I’ve only seen it twice and have been unable to (intentionally) reproduce. My application has about 50 sounds that it has to play (like notes on a piano). Each sound is about 400KB, so to keep memory down, it only loads up about 12 sounds at any given point in time. If I need to play a sound that isn’t loaded, I unload some sounds with removeSoundWithKey, in order to make room for the new sounds. I’m not sure if there’s a better way to play a bunch of sounds, but I’ve tested all of this hundreds, if not thousands, of times and it normally works just fine… except for those couple of times when I got that alDeleteBuffers error.
-Rick
mike on January 3rd, 2011
Hi Rick
That is an odd error. Do you have any code in place to protect against deleting an empty buffer, just in case that is being done?
I’ve posted the very latest sound code http://www.71squared.com/2011/.....d-manager/
Let me know how you get on and it there are things you’d like to see added to the sound manager.
Mike
Rick on January 4th, 2011
Thanks again for posting the latest code. I didn’t see any changes that might prevent the buffer deleting problem, though. But I also wonder if perhaps it’s something that occurs only on the older iOS/equipment. I have several devices that I test on and the buffer error has only appeared on my 3GS iPhone which is running 4.0 (i.e. not the latest 4.x).
I don’t currently have any code to prevent the empty buffer deletes. Do you know offhand how I should go about that? If not, I guess I’ll figure something out.
-Rick
Nitz on February 20th, 2011
Hi,
In your code you are playing a single stereo sound buffer. When you try to play more than 2 or 3 stereo sound buffers, the program freezes.
I know that the problem is that ALC_STEREO_SOURCES is 3 by default. How can I set ALC_STEREO_SOURCES to 32?
Thanks for your tutorial, it is gold.
GemInEyeTwin on February 27th, 2011
Hello Mike,
I am currently using your older SingletonSoundManger class files.
Playing multiple sounds at the same time at the same gain (volume) works fine; however when I play two sounds at different volumes I have an issue where it appears a sound will during the playing of the different volume sound play at that volume too.
For example, I have a continuous animation where on the loop of the animation I play a buz sound. This sound volume is set based on how close the main character is to the animation. The main character has a walk sound at full gain. As the man walks and his walk sound plays at full volume, the buz sound will mostly play at the expected volume (say very low when the character is not close) but will briefly play at full volume which of course destroys the affect.
I did comment out the walk sound and the buz sound plays properly as the man moves closer or farther from the animation. When I add the walk sound, it is as if a sound takes on the volume of another.
As a test, I set my walk gain to be very low (0.01), which I never change once set. The walk is fine until I also play the higher gain buz sound. Then the walk sound has a higher volume and actually seems a little distorted. As soon as the buzz sound ends, the next walk sound still has the higher volume. Any walk sounds after this are back at the correct low gain again.
Has anyone else experienced this problem?
Should I be using your latest code you just posted instead?
If so, I used the old SingletonSoundManager and your new code is implemented differently. For example, would I need your “SynthesizeSingleton.h.
Any help would be appreciated.
Thanks
Tom
GemInEyeTwin on February 27th, 2011
Hello,
I did another test to play a sound at a very low gain when my main character “talks”. The sounds play at the expect low volume fine, until I play a sound at a higher gain. Once I have played this higher gain sound, my next character talk sound plays at the correct low gain but now is slightly distorted (has a noticeable popping sound at the start). The next sound played for the character “talking” is fine.
It just seems to be a problem with a sound played after a previous sound which had a different gain.
Anyone else having this same issue or the one I noted above?
Thanks
Tom
on April 1st, 2011
May I just say what a relief to discover someone who definitely realizes exactly what they’re talking about on the internet. You definitely find out how to take an issue to light and make it very important. Even more people require to learn this and understand this particular side of the story. I cant believe you are not more popular as you clearly have the gift.
Chris79 on April 9th, 2011
Hey Mike!
Good tutorial. Finally I understood how to make a singleton sound manager. thank you :) keep up the good work
I got 2 issues though when I tried out the tutorial
One is that the sound effect gets distorted when it plays (I´m using one of my own sfx). I tried to change the pitch value as well as the frequency and the gain value but the sound effect still won´t sound as it should, it either becomes slower or quieter, faster or louder.
the second issue is that I get warning messages when trying to use the [sharedSoundManager stopPlayingMusic]; and the [sharedSoundManager stopSoundWithKey:@"movingbricks"]; to stop the background music as well as the SFX.
the warning messages say SingletonSoundManager’ may not respond to ‘-stopPlayingMusic’ and SingletonSoundManager’ may not respond to ‘-stopSoundWithKey’.
Still it seems to work fine with the stopPlayingMusic (Im not sure for how long though). the music stops but when I use the stopSoundWithKey then the app crashes.
( I used the stopSoundWithKey code that you entered in a comment above)
What am I doing wrong?
Danegraphics on May 14th, 2011
Every time I launch my app with the sound manager. I get a leaked ‘GeneralBlock-512′ of size 512 bytes, this is leaked in the method initOpenAL. Do you know what this is?
Danegraphics on May 15th, 2011
@mike Every time I launch my app with the sound manager. I get a leaked ‘GeneralBlock-512′ of size 512 bytes, this is leaked in the method initOpenAL. Do you know what this is?
Danegraphics on May 15th, 2011
I found that it’s a leak from alcCreateContext(device, NULL)
I don’t think that’s your fault but can you find a way to fix it?
mike on May 15th, 2011
@danegraphics, I’ve also seen the leak you have spotted and it’s been commented on in many other threads and forums as well. I spent some time working out if it’s something I can fix but the problem is inside the Apple framework and is therefore not something we can fix.
I would log a bug with Apple. The more people who log the issue the more chance there is it will get fixed.
Sorry I can’t provide an answer on this one.
Mike
GemInEyeTwin on May 15th, 2011
Hello Mike,
I am currently using your older SingletonSoundManger class files.
Playing multiple sounds at the same time at the same gain (volume) works fine; however when I play two sounds at different volumes I have an issue where it appears a sound will during the playing of the different volume sound play at that volume too.
For example, I have a continuous animation where on the loop of the animation I play a buz sound. This sound volume is set based on how close the main character is to the animation. The main character has a walk sound at full gain. As the man walks and his walk sound plays at full volume, the buz sound will mostly play at the expected volume (say very low when the character is not close) but will briefly play at full volume which of course destroys the affect.
I did comment out the walk sound and the buz sound plays properly as the man moves closer or farther from the animation. When I add the walk sound, it is as if a sound takes on the volume of another.
As a test, I set my walk gain to be very low (0.01), which I never change once set. The walk is fine until I also play the higher gain buz sound. Then the walk sound has a higher volume and actually seems a little distorted. As soon as the buzz sound ends, the next walk sound still has the higher volume. Any walk sounds after this are back at the correct low gain again.
Has anyone else experienced this problem?
Should I be using your latest code you just posted instead?
If so, I used the old SingletonSoundManager and your new code is implemented differently. For example, would I need your “SynthesizeSingleton.h.
Any help would be appreciated.
Thanks
Tom
c0deman on May 26th, 2011
@GemInEyeTwin – did you ever resolve this? If so, how did you fix it? Thanks
GemInEyeTwin on May 27th, 2011
No. I did not resolve my issue mentioned above with the sound gain change/distortion.
IlyaK on June 21st, 2011
Hey Mike,
I’m still going through your tutorials. I just wanted to tell you (again) that both you and your tutorials rock. Thank you so much.
Ilya
Wayne green on July 11th, 2011
Excellent tutorial, I’m learning iPhone apps development these days. You inspired me!
Marsman on January 28th, 2012
Is anyone (beside me) experiencing a glitch when looping .wav sounds? My sound is perfectly looped (no clicks or glitches in it). Yet I hear a big “thud” every time the sound runs through the loop cycle.
here is the sound if anyone wants to play: http://www.mmprod.com/temp/
Marsman on January 28th, 2012
Loop issue solved. For some inexplicable reason, Sound Manager (or openAL) does not appreciate short loops. I experimented with creating longer WAV files in my sound program. The problem disappeared after my sound length was over 6 seconds in length.





bob on May 26th, 2009
@Mike,
Hi Mike, found a problem. The sound manager will play mono sounds but not stereo. I loaded your ‘laser sound’ into an editor and it is mono. I converted it to stereo and you get a lot of noise with the sound. I thought it was sound file but I don’t think it is. Any idea’s?