As Panda’s distribution maintainer, I’d love to see a free audio library connected to panda. Unfortunately, I can’t do it myself.
I’m interested in the development of these tutorials. Perhaps someday we’ll integrate these into the distribution.
I’m certainly wrong but i though Fmod was free as long as you don’t sell your game?
It is. He mentioned that if you want to sell your game FMOD starts to get expensive.
I modified IPKNIGHTLY’s code so that it now runs in 1.3.2
#----------------------------------------------------------------------------# # # # File: musicBox.py # # # # Description: This module incorporates PyGame.Mixer with Pand3D code. # # # # Needed: Panda 1.0.5 w/ Python2.4, models\MusicBox.egg, models\box.jpg # # models\panda.jpg, music\musicbox.mp3, music\openclose.mp3 # # music\close.wav, music\open.wav, music\musicbox.wav # # pygame-1.7.1release.win32-py2.4.exe # # # # # # # # # # PyGame specific and misc code written by David Lettier. The rest was # # written by the authors listed below. # # # # musicbox.wav, open.wav, and close.wav converted and edited by David # # Lettier. Audacity was used. # # # # # # # # All files provided "as is" without warranties expressed or implied. # # # # (C) 2005 David Lettier. # # # #----------------------------------------------------------------------------# # Author: Shao Zhang, Phil Saltzman, and Elan Ruskin # Last Updated: 4/20/2005 # # This tutorial shows how to load, play, and manipulate sounds # and sound intervals in a panda project. import direct import sys , os from direct.showbase.DirectObject import DirectObject from direct.gui.DirectSlider import DirectSlider import direct.directbase.DirectStart from pandac.PandaModules import * from direct.interval.IntervalGlobal import * from direct.gui.DirectGui import * import pygame # import the pygame module from pygame.locals import * # here we check if the SDL_Mixer is available if not pygame.mixer: print 'Warning, sound disabled' # want to use PyGame.Mixer instead of FMOD? usePyGame = True # yes class World( DirectObject ): def __init__( self ): #Our standard title and instructions text self.title = OnscreenText( text = "Panda3D: Tutorial - Musicbox(sounds)", style = 1, fg = ( 1, 1, 1, 1), pos = ( 0.8, -0.95 ), scale = .07 ) self.escapeEventText = OnscreenText( text = "ESC: Quit", style = 1, fg = ( 1, 1, 1, 1 ), pos = ( -1.3, 0.95 ), align = TextNode.ALeft, scale = .05 ) #Set up the key input self.accept( 'escape', sys.exit ) # set the background color to black base.setBackgroundColor( 0, 0, 0 ) # create a point light plight = PointLight( 'plight' ) # new point light plight.setColor( VBase4( 0.8, 0.8, 0.8, 1 ) ) # set the color plnp = render.attachNewNode( plight.upcastToPandaNode( ) ) # attach it to the render plnp.setPos( 0, -70, 10 ) # set it's position 10 units before the music box and render.setLight( plnp ) # turn on the light if usePyGame: # if we are using pygame self.pyGameInit( ) # initialize pygame so we can use it print "Using PyGame." else: print "Using Panda3D default sound library." #Fix the camera position base.disableMouse( ) #Loading sounds is done in a similar way to loading other things #Loading the main music box song if usePyGame: # if we are using pygame pygame.mixer.music.load( 'music/musicbox.wav' ) # load the music box song # pygame needs it to be wav instead of mp3 pygame.mixer.music.set_volume( .5 ) # set the volume to half way pygame.mixer.music.play( -1 ) # loop it for ever pygame.mixer.music.pause( ) # pause for now so we can resume later else: self.musicBoxSound = base.loadMusic( 'music/musicbox.mp3' ) self.musicBoxSound.setVolume( .5 ) #Volume is a percentage from 0 to 1 self.musicBoxSound.setLoopCount( 0 ) #0 means loop forever, 1 (default) means #play once. 2 or higher means play that #many times #Sound objects do not have a pause function, just play and stop. So we will #Use this variable to keep track of where the sound is at when it was stoped #to impliment pausing self.musicTime = 0 if usePyGame: # if we are using pygame self.lidSfxOpen = self.pyGameLoadSound( 'music/open.wav' ) # load the open sound # i broke up the openclose sound # because pygame.mixer didn't have a # start pos argument # plus this is just easier and makes sense IMO # also it needed to be wav instead of mp3 self.lidSfxClose = self.pyGameLoadSound( 'music/close.wav' ) # same # on an interesting side note: this sound effect seems to be the same # one used in the game 'The Elder Scrolls 3: Morrowind' else: #Loading the open/close effect #loadSFX and loadMusic are identical. They are often used for organization #(loadMusic is used for background music, loadSfx is used for other effects) self.lidSfx = base.loadSfx( 'music/openclose.mp3' ) #The open/close file has both effects in it. Fortunatly we can use intervals #to easily define parts of a sound file to play self.lidOpenSfx = SoundInterval( self.lidSfx, duration = 2, startTime = 0 ) self.lidCloseSfx = SoundInterval( self.lidSfx, startTime = 5 ) #For this tutorial, it seemed appropriate to have on screen controls. The #following code creates them #The slider itself. It calls self.setMusicBoxVolume when changed self.slider = DirectSlider( pos = Vec3( 0, 0, .7 ), value = .50, command = self.setMusicBoxVolume ) #This is a label for a slider # here i changed it a bit to display what the actual volume is on screen self.sliderText = OnscreenText( "Volume " + str( self.slider.guiItem.getValue( ) ), style = 1, fg = ( 1, 1, 1, 1 ), shadow = ( .9, .9, .9, .5 ), pos = (0, 0.8 ), scale = .07 ) #A button that calls self.toggleMusicBox when pressed self.button = DirectButton( pos = Vec3( .7, 0, .7 ), text = "Open Box", scale = .1, pad = ( .5, .5 ), rolloverSound = None, clickSound = None, command = self.toggleMusicBox ) #A variable to represent the state of the simulation. It starts closed self.boxOpen = False #Here we load and set up the music box. It was modeled in a complex way, so #setting it up will be complicated self.musicBox = loader.loadModel( 'models/MusicBox' ) self.musicBox.setPos( 0, 60, -10 ) self.musicBox.reparentTo( render ) #Just like the scene graph contains hierarchies of nodes, so can #models. You can get the NodePath for the node using the find #function, and then you can animate the model by moving its parts #To see the hierarchy of a model, use, the ls function #self.musicBox.ls() prints out the entire hierarchy of the model #Finding pieces of the model self.Lid = self.musicBox.find( '**/lid' ) self.Panda = self.musicBox.find( '**/turningthing' ) #This model was made with the hinge in the wrong place #this is here so we have something to turn self.HingeNode = self.musicBox.find( '**/box' ).attachNewNode( 'nHingeNode' ) self.HingeNode.setPos( .8659, 6.5, 5.4 ) #WRT - ie with respect to. Reparents the object without changing #its position, size, or orientation self.Lid.wrtReparentTo( self.HingeNode ) self.HingeNode.setHpr( 0, 90, 0 ) if usePyGame: # if we are using pygame # here we are not using 'self.lidClose/OpenSfx' so we don't need to use a Parallel #This sets up an interval to play the close sound and actually close the box #at the same time. self.lidClose = LerpFunc( self.HingeNode.setP, duration = 2, fromData = 0, toData = 90, blendType = 'easeInOut' ) #Same thing for opening the box self.lidOpen = LerpFunc( self.HingeNode.setP, duration = 2, fromData = 90, toData = 0, blendType = 'easeInOut' ) else: #This sets up an interval to play the close sound and actually close the box #at the same time. self.lidClose = Parallel( self.lidCloseSfx, LerpFunc( self.HingeNode.setP, duration = 2, fromData = 0, toData = 90, blendType = 'easeInOut' ) ) #Same thing for opening the box self.lidOpen = Parallel( self.lidOpenSfx, LerpFunc( self.HingeNode.setP, duration = 2, fromData = 90, toData = 0, blendType ='easeInOut' ) ) #The interval for turning the panda self.PandaTurn = self.Panda.hprInterval( 7, Vec3( 360, 0, 0 ) ) #Do a quick loop and pause to set it as a looping interval so it can be #started with resume and loop properly self.PandaTurn.loop( ) self.PandaTurn.pause( ) # begin the pyGameInit member function # this intializes pygame for us def pyGameInit( self ): pygame.init( ) # end pyGameInit # begin the pyGameLoadSound member function def pyGameLoadSound( self, filename ): # accept filename as an argument class NoneSound: # dummy class def play( self ): pass # so there is no error is we call .play( ) # this is because sdl mixer may not exist # here we check if pygame.mixer was initialized if not pygame.mixer or not pygame.mixer.get_init( ): return NoneSound( ) # if not then return the dummy class try: # try to load the sound file sound = pygame.mixer.Sound( filename ) except pygame.error, message: # can't do it print 'Cannot load sound:', filename # print the file we can't load raise SystemExit, message # there is a problem so exit return sound # everything is fine so return the new sound object # end pyGameLoadSound def setMusicBoxVolume( self ): if usePyGame: # if we are using pygame # same as for default Panda3D sound library newVol = self.slider.guiItem.getValue( ) # get value pygame.mixer.music.set_volume( newVol ) # set the new volume else: #Simply reads the current value from the slider and sets it in the sound newVol = self.slider.guiItem.getValue( ) self.musicBoxSound.setVolume( newVol ) # here we update the volume level on screen self.sliderText.destroy( ) # must destroy what was there # or it would just write over it making it unreadable self.sliderText = OnscreenText( "Volume " + str( self.slider.guiItem.getValue() ), style = 1, fg = ( 1, 1, 1, 1 ), shadow = ( .9, .9, .9, .5 ), pos = (0, 0.8 ), scale = .07 ) def toggleMusicBox( self ): if self.boxOpen: #close the box self.lidClose.start() #Start the close box interval self.PandaTurn.pause() #Pause the figurine turning if usePyGame: # if we are using pygame.mixer self.lidSfxClose.play( ) # play the close sound effect # here is what you could do to resemble the original tutorial #self.musicTime = pygame.mixer.music.get_pos( ) pygame.mixer.music.pause( ) # pause the streaming music # fortunately pygame music module # has pause and unpause functions # however you can only stream # one piece of music at one time # unless you queue them else: #Save the current time of the music box song self.musicTime = self.musicBoxSound.getTime( ) self.musicBoxSound.stop( ) #Stop the music box song self.button[ 'text' ] = "Open Box" #Prepare to change button label else: #open the box self.lidOpen.start( ) #Start the open box interval self.PandaTurn.resume( ) #Resume the figuring turning if usePyGame: # if we are using pygame.mixer self.lidSfxOpen.play( ) # play the open sound pygame.mixer.music.unpause( ) # resume the streamed music else: #Reset the time of the music box song so it starts where it left off self.musicBoxSound.setTime( self.musicTime ) self.musicBoxSound.play( ) #Play the music box song self.button[ 'text' ] = "Close Box" #Prepare to change button label self.button.setText( ) #Actually change the button label self.boxOpen = not self.boxOpen #Set our state to opposite what it was #(closed to open or open to closed) # and we can run! w = World() run() # In the end the player doesn't know the difference, however, we do. # Now we don't need to use FMOD (which is what Panda3D uses) so we can # save money, which is important if your an independent game developer with # a low budget (or none for that matter). Hopefully, Panda3D will latter support # sdl_mixer or OpenAL in future versions. It already supports Miles and FMOD.
Sorry for bumping into an old thread, but since it’s among P3d’s sample projects in the documentation, I was wondering if anyone has still got a copy of lettier’s project around, and if updated to latest V 1.54 even better!
There aren’t many audio samples for the engine so I think this exapmple shouldn’t be left into oblivion.
regards, and thanks for any help.
It’s a bit unnecessary now that we have the OpenAL library to use in addition to FMOD, although OpenAL on Linux seems to be fraught with difficulties as well.
Yeah there is no need for this thing any more.
However, I do agree that there could be more audio samples/tutorials. As I am a sound designer, it’s one thing I’ve been focusing on, so I’ve collected a good amount of info on it. I’ve been thinking about writing a tutorial (or a few) on it, if anyone thinks they could use help with it, as I’d love to finally have a way to give back to the community that has helped me so much.
On the subject, what would be the best form for a tutorial. I feel that just throwing a heavily commented .py file with necessary media into a zip file can be pretty limited. HTML feels like it might be overkill though, and not as convenient, but maybe I’m wrong there. Any suggestions for a tutorial medium?
I’m interested in your tutorial
An HTML page sounds good for me…
Sweet, at least one person will benefit, I’ll get to work on it tonight then.
It’ll be nice to have a reference I can go back to too, once my audio code is obscured by the rest of my game. Might even be an opportunity to brush up on some HTML, I’ll try and make it look pretty.
I haven’t yet used it myself, so I’m not speaking from experience, but I thought I read that Panda’s OpenAl implementation is slow and a resource hog, even on Windows. Is this not true?
Its not without its problems but i would not say its a resource hog and super slow.
The 1.6.0 release will speed OpenAL a bit up and fix a few bugs here and there. Although I tried it without much problems, I still recommend FMOD for non-commercial games.
I agree completely. OpenAL is fine for basic sound needs, and it’s nice to be able to release the game commercially if that’s what you’re going for, but FMOD is better in a lot of ways, and is a standard in game audio.
Also, I only get DSP with FMOD. Is this simply a limitation of OpenAL? I’ve never used it before with anything else, so I don’t know if OpenAL does any DSP at all.
Cool to see all these new replies.
And I’m glad the news about P3d 1.60 let foresee a better future on the sound part. Let’s hope they include some updated examples on OpenAL, I’m really looking forward to testing this new release out.
@AamesxDavid: I’d also be interested in your tutorials. From your perspective (as a sound designer), you must be doing some interesting things in the audio field. Please let us know if you ever release them.
regards, and thanks for all the interesting ideas posted.
More then one person. IN FACT if its printable (margins not over the page e.t.c) I will convert it to a pdf and send it back to you for posting.
That would be great, thanks.
I appreciate all of the responses; the tutorial-making is in full swing now, and will be finished in a couple of days.
Does HTML count as printable? There aren’t really margins for that, by default anyway. I got a response saying that it was a good format for a tutorial. I can put it in .doc format also if that would work better for pdf-ing.
Also, any input on more things to include would be great. As of now I have:
Making Sounds 3D
Moving 3D Sounds
And one example that mixes them all together. There are subdivisions for a lot of things, but those are the overarching ideas. Anything in particular you’d like focus on, or a new category you’d like, I’d be happy to add it in. Thanks again for the interest!
Sounds very good!