mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-26 05:02:31 -06:00
165 lines
6.4 KiB
Python
165 lines
6.4 KiB
Python
"""SoundInterval module: contains the SoundInterval class"""
|
|
|
|
__all__ = ['SoundInterval']
|
|
|
|
from pandac.PandaModules import *
|
|
from direct.directnotify.DirectNotifyGlobal import *
|
|
import Interval
|
|
import random
|
|
|
|
class SoundInterval(Interval.Interval):
|
|
# Name counter
|
|
soundNum = 1
|
|
# create SoundInterval DirectNotify category
|
|
notify = directNotify.newCategory('SoundInterval')
|
|
# Class methods
|
|
# Create a sound interval
|
|
# If loop = 0, sound will play once, duration of the interval
|
|
# equals the duration of the sound
|
|
# If loop = 1, the sound will loop for the specified duration
|
|
# If no duration is specified, sound will loop for the duration
|
|
# of the sound, i.e. it will only play once.....usually, there
|
|
# seems to be some timing in the audio such that the stop doesn't
|
|
# kill the looping sound until the next time around if duration
|
|
# of the interval equals duration of the sound
|
|
# seamlessloop will let the audio system loop the sound rather
|
|
# than explicitly restarting the sound every time around. This
|
|
# prevents a skip in the sound at every repetition (the gap in
|
|
# the sound is caused by the delay between the end of the sound
|
|
# and the next taskMgr cycle). There still seems to be a skip
|
|
# in Miles when looping MP3s. =(
|
|
# RAU 03/01/07 add listenerNode in case we don't want to
|
|
# use base.camera as the listener, node must not be None
|
|
def __init__(self, sound, loop = 0, duration = 0.0, name = None,
|
|
volume = 1.0, startTime = 0.0, node=None,
|
|
seamlessLoop=True, listenerNode = None, cutOff = None):
|
|
"""__init__(sound, loop, name)
|
|
"""
|
|
# Generate unique name
|
|
id = 'Sound-%d' % SoundInterval.soundNum
|
|
SoundInterval.soundNum += 1
|
|
# Record instance variables
|
|
self.sound = sound
|
|
if sound:
|
|
self.soundDuration = sound.length()
|
|
else:
|
|
self.soundDuration = 0
|
|
self.fLoop = loop
|
|
self.volume = volume
|
|
self.startTime = startTime
|
|
self.node = node
|
|
self.listenerNode = listenerNode
|
|
self.cutOff = cutOff
|
|
self._seamlessLoop = seamlessLoop
|
|
if self._seamlessLoop:
|
|
self._fLoop = True
|
|
self._soundPlaying = False
|
|
self._reverse = False
|
|
# If no duration given use sound's duration as interval's duration
|
|
if float(duration) == 0.0 and self.sound != None:
|
|
duration = max(self.soundDuration - self.startTime, 0)
|
|
#if (duration == 0):
|
|
# self.notify.warning('zero length duration!')
|
|
|
|
# MPG - hack for Miles bug
|
|
#duration += 1.5
|
|
|
|
# DCR - hack for Miles bug - adding 1.5 seconds caused
|
|
# problems for MG_neg_buzzer.wav
|
|
|
|
# DCR - what this is all about: Miles is under-reporting the
|
|
# length of MP3 files, and they're getting cut off too early.
|
|
# This is a temporary hack. We could:
|
|
# - hack Miles to fix its MP3 length calculation
|
|
# - complain louder about this to RAD
|
|
# - precompute MP3 durations and store them in a table
|
|
|
|
# drose - ok, I've put in a lower-level workaround in the
|
|
# MilesAudioManager. This is no longer necessary up here,
|
|
# where it pollutes SoundInterval for everyone.
|
|
#duration += min(duration * 2.4, 1.5)
|
|
|
|
# Generate unique name if necessary
|
|
if (name == None):
|
|
name = id
|
|
# Initialize superclass
|
|
Interval.Interval.__init__(self, name, duration)
|
|
|
|
def privInitialize(self, t):
|
|
# If it's within a 10th of a second of the start,
|
|
# start at the beginning
|
|
self._reverse = False
|
|
t1 = t + self.startTime
|
|
if (t1 < 0.1):
|
|
t1 = 0.0
|
|
if (t1 < self.soundDuration) and not (self._seamlessLoop and self._soundPlaying):
|
|
base.sfxPlayer.playSfx(
|
|
self.sound, self.fLoop, 1, self.volume, t1, self.node,
|
|
listenerNode = self.listenerNode, cutoff = self.cutOff)
|
|
self._soundPlaying = True
|
|
self.state = CInterval.SStarted
|
|
self.currT = t
|
|
|
|
def privInstant(self):
|
|
pass
|
|
|
|
def privStep(self, t):
|
|
## if self._reverse:
|
|
## # Don't attempt to play the sound backwards.
|
|
## return
|
|
|
|
if self.state == CInterval.SPaused:
|
|
# Restarting from a pause.
|
|
t1 = t + self.startTime
|
|
if t1 < self.soundDuration:
|
|
base.sfxPlayer.playSfx(
|
|
self.sound, self.fLoop, 1, self.volume, t1, self.node,
|
|
listenerNode = self.listenerNode)
|
|
if self.listenerNode and not self.listenerNode.isEmpty() and \
|
|
self.node and not self.node.isEmpty():
|
|
base.sfxPlayer.setFinalVolume(self.sound, self.node, self.volume,
|
|
self.listenerNode, self.cutOff)
|
|
|
|
self.state = CInterval.SStarted
|
|
self.currT = t
|
|
|
|
def finish(self, *args, **kArgs):
|
|
self._inFinish = True
|
|
Interval.Interval.finish(self, *args, **kArgs)
|
|
del self._inFinish
|
|
|
|
def privFinalize(self):
|
|
# if we're just coming to the end of a seamlessloop, leave the sound alone,
|
|
# let the audio subsystem loop it
|
|
if (self._seamlessLoop and self._soundPlaying and self.getLoop()
|
|
and not hasattr(self, '_inFinish')):
|
|
base.sfxPlayer.setFinalVolume(self.sound, self.node, self.volume,
|
|
self.listenerNode, self.cutOff)
|
|
return
|
|
elif self.sound != None:
|
|
self.sound.stop()
|
|
self._soundPlaying = False
|
|
self.currT = self.getDuration()
|
|
self.state = CInterval.SFinal
|
|
|
|
def privReverseInitialize(self, t):
|
|
self._reverse = True
|
|
|
|
def privReverseInstant(self):
|
|
self.state = CInterval.SInitial
|
|
|
|
def privReverseFinalize(self):
|
|
self._reverse = False
|
|
self.state = CInterval.SInitial
|
|
|
|
def privInterrupt(self):
|
|
if self.sound != None:
|
|
self.sound.stop()
|
|
self._soundPlaying = False
|
|
self.state = CInterval.SPaused
|
|
|
|
def loop(self, startT = 0.0, endT = -1.0, playRate = 1.0, stagger=False):
|
|
self.fLoop = 1
|
|
Interval.Interval.loop(self, startT, endT, playRate)
|
|
if stagger:
|
|
self.setT(random.random() * self.getDuration())
|