gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] /srv/bzr/gnash/trunk r11059: Implement inPoint/outPoint a


From: Sandro Santilli
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r11059: Implement inPoint/outPoint and Sound.start(<secs_offset>) for event sounds.
Date: Wed, 10 Jun 2009 13:27:47 +0200
User-agent: Bazaar (1.13.1)

------------------------------------------------------------
revno: 11059
committer: Sandro Santilli <address@hidden>
branch nick: trunk
timestamp: Wed 2009-06-10 13:27:47 +0200
message:
  Implement inPoint/outPoint and Sound.start(<secs_offset>) for event sounds.
  Drop delaySeek implementation as it proved wrong 
(http://wiki.gnashdev.org/MP3_Sound_tags#Embedded_Event_sounds).
  NOTE: there's no automated test yet so please try not to break it.
  I'll try to work on extending the eventSoundTest1
modified:
  libcore/Button.cpp
  libcore/asobj/flash/media/Sound_as.cpp
  libcore/asobj/flash/media/Sound_as.h
  libcore/swf/SoundInfoRecord.cpp
  libcore/swf/SoundInfoRecord.h
  libcore/swf/StartSoundTag.cpp
  libcore/swf/tag_loaders.cpp
  libsound/EmbedSound.cpp
  libsound/EmbedSound.h
  libsound/EmbedSoundInst.cpp
  libsound/EmbedSoundInst.h
  libsound/sound_handler.cpp
  libsound/sound_handler.h
  testsuite/misc-ming.all/eventSoundTest1.c
=== modified file 'libcore/Button.cpp'
--- a/libcore/Button.cpp        2009-06-09 14:04:51 +0000
+++ b/libcore/Button.cpp        2009-06-10 11:27:47 +0000
@@ -553,9 +553,10 @@
 
             s->startSound(bs.sample->m_sound_handler_id,
                     bs.soundInfo.loopCount,
-                    0, // secs offset
                     env, // envelopes
-                    !sinfo.noMultiple // allow multiple instances ?
+                    !sinfo.noMultiple, // allow multiple instances ?
+                    sinfo.inPoint,
+                    sinfo.outPoint
                     );
         }
 

=== modified file 'libcore/asobj/flash/media/Sound_as.cpp'
--- a/libcore/asobj/flash/media/Sound_as.cpp    2009-06-09 17:32:44 +0000
+++ b/libcore/asobj/flash/media/Sound_as.cpp    2009-06-10 11:27:47 +0000
@@ -463,7 +463,7 @@
 }
 
 void
-Sound_as::start(int offset, int loops)
+Sound_as::start(double secOff, int loops)
 {
     if ( ! _soundHandler )
     {
@@ -479,10 +479,10 @@
             return;
         }
 
-        if (offset > 0)
+        if (secOff > 0)
         {
-            _startTime=offset*1000;
-            boost::uint32_t seekms = boost::uint32_t(offset*1000);
+            _startTime = secOff * 1000;
+            boost::uint32_t seekms = boost::uint32_t(secOff * 1000);
             // TODO: boost::mutex::scoped_lock parserLock(_parserMutex);
             _mediaParser->seek(seekms); // well, we try...
         }
@@ -511,12 +511,20 @@
     }
     else
     {
+        unsigned int inPoint = 0;
+
+        if ( secOff > 0 ) {
+            inPoint = (secOff*44100);
+        }
+
+        log_debug("Sound.start: secOff:%d", secOff);
+
         _soundHandler->startSound(
                     soundId,
                     loops,
-                    offset, // in seconds
                     0, // envelopes
-                    true // allow multiple instances (checked)
+                    true, // allow multiple instances (checked)
+                    inPoint
                     );
     }
 }
@@ -825,10 +833,10 @@
     )
     boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
     int loop = 0;
-    int secondOffset = 0;
+    double secondOffset = 0;
 
     if (fn.nargs > 0) {
-        secondOffset = (int) fn.arg(0).to_number();
+        secondOffset = fn.arg(0).to_number();
 
         if (fn.nargs > 1) {
             loop = (int) fn.arg(1).to_number() - 1;

=== modified file 'libcore/asobj/flash/media/Sound_as.h'
--- a/libcore/asobj/flash/media/Sound_as.h      2009-06-09 17:32:44 +0000
+++ b/libcore/asobj/flash/media/Sound_as.h      2009-06-10 11:27:47 +0000
@@ -91,7 +91,7 @@
     void loadSound(const std::string& file, bool streaming);
     void setPan();
     void setTransform();
-    void start(int offset, int loops);
+    void start(double secsStart, int loops);
     void stop(int si);
     unsigned int getDuration();
     unsigned int getPosition();

=== modified file 'libcore/swf/SoundInfoRecord.cpp'
--- a/libcore/swf/SoundInfoRecord.cpp   2009-05-20 08:16:47 +0000
+++ b/libcore/swf/SoundInfoRecord.cpp   2009-06-10 11:27:47 +0000
@@ -44,12 +44,10 @@
     in.ensureBytes(hasInPoint * 4 + hasOutPoint * 4 + hasLoops * 2);
 
        if (hasInPoint) {
-               LOG_ONCE( log_unimpl(_("SoundInfo record with in point")) );
                inPoint = in.read_u32();
        }
 
        if (hasOutPoint) {
-               LOG_ONCE( log_unimpl(_("SoundInfo record with out point")) );
                outPoint = in.read_u32();
        }
 

=== modified file 'libcore/swf/SoundInfoRecord.h'
--- a/libcore/swf/SoundInfoRecord.h     2009-02-25 22:33:03 +0000
+++ b/libcore/swf/SoundInfoRecord.h     2009-06-10 11:27:47 +0000
@@ -22,6 +22,8 @@
 
 #include "sound_handler.h" // sound::SoundEnvelopes
 
+#include <limits>
+
 namespace gnash {
     class SWFStream;
 }
@@ -38,7 +40,7 @@
         :
         loopCount(0),
         inPoint(0),
-        outPoint(0)
+        outPoint(std::numeric_limits<unsigned int>::max())
     {}
 
     bool noMultiple;
@@ -63,11 +65,19 @@
        ///
        bool stopPlayback;
 
-       /// In/Out points, currently unsupported
-       //
-       /// See http://sswf.sourceforge.net/SWFalexref.html#swf_soundinfo
-    boost::uint32_t inPoint;
-    boost::uint32_t outPoint;
+       /// In point, 44100 for one second
+       //
+       /// See http://sswf.sourceforge.net/SWFalexref.html#swf_soundinfo
+    ///
+    unsigned int inPoint;
+
+       /// Out point, 44100 for one second
+       //
+       /// See http://sswf.sourceforge.net/SWFalexref.html#swf_soundinfo
+    ///
+    /// NOTE: std::numeric_limits<unsigned int>::max() means none
+    ///
+    unsigned int outPoint;
 
        /// Sound effects (envelopes) for this start of the sound
        //

=== modified file 'libcore/swf/StartSoundTag.cpp'
--- a/libcore/swf/StartSoundTag.cpp     2009-06-09 14:04:51 +0000
+++ b/libcore/swf/StartSoundTag.cpp     2009-06-10 11:27:47 +0000
@@ -27,6 +27,8 @@
 #include "SoundInfoRecord.h"
 #include "MovieClip.h"
 
+#include <limits>
+
 namespace gnash {
 namespace SWF {
 
@@ -94,9 +96,10 @@
 
             handler->startSound(m_handler_id,
                     _soundInfo.loopCount,
-                    0, // secs offset
                     env, // envelopes
-                    !_soundInfo.noMultiple // allow multiple instances ?
+                    !_soundInfo.noMultiple, // allow multiple instances ?
+                    _soundInfo.inPoint,
+                    _soundInfo.outPoint
                     );
         }
     }

=== modified file 'libcore/swf/tag_loaders.cpp'
--- a/libcore/swf/tag_loaders.cpp       2009-06-08 00:47:06 +0000
+++ b/libcore/swf/tag_loaders.cpp       2009-06-10 11:27:47 +0000
@@ -1126,11 +1126,6 @@
         {
             in.ensureBytes(2);
             latency = in.read_s16(); 
-            if ( latency )
-            {
-                LOG_ONCE ( log_unimpl("MP3 stream latency seek") );
-                // TODO: should we pass as 'delaySeek' to SoundInfo ?
-            }
         }
         catch (ParserException& ex)
         {
@@ -1156,7 +1151,7 @@
 
     // Store all the data in a SoundInfo object
     std::auto_ptr<media::SoundInfo> sinfo;
-    sinfo.reset(new media::SoundInfo(format, streamSoundStereo, 
streamSoundRate, sampleCount, streamSound16bit));
+    sinfo.reset(new media::SoundInfo(format, streamSoundStereo, 
streamSoundRate, sampleCount, streamSound16bit, latency));
 
     // Stores the sounddata in the soundhandler, and the ID returned
     // can be used to starting, stopping and deleting that sound

=== modified file 'libsound/EmbedSound.cpp'
--- a/libsound/EmbedSound.cpp   2009-02-25 22:33:03 +0000
+++ b/libsound/EmbedSound.cpp   2009-06-10 11:27:47 +0000
@@ -100,14 +100,17 @@
 
 std::auto_ptr<EmbedSoundInst>
 EmbedSound::createInstance(media::MediaHandler& mh,
-            unsigned long blockOffset, unsigned int secsOffset,
+            unsigned long blockOffset,
+            unsigned int inPoint,
+            unsigned int outPoint,
             const SoundEnvelopes* envelopes,
             unsigned int loopCount)
 {
     std::auto_ptr<EmbedSoundInst> ret ( new EmbedSoundInst(
                                 *this,
                                 mh, blockOffset,
-                                secsOffset, envelopes,
+                                inPoint, outPoint,
+                                envelopes,
                                 loopCount) );
 
     boost::mutex::scoped_lock lock(_soundInstancesMutex);

=== modified file 'libsound/EmbedSound.h'
--- a/libsound/EmbedSound.h     2009-02-25 22:33:03 +0000
+++ b/libsound/EmbedSound.h     2009-06-10 11:27:47 +0000
@@ -162,10 +162,16 @@
     ///     to refer to a specific StreamSoundBlock.
     ///     @see gnash::swf::StreamSoundBlockTag
     ///
-    /// @param secsOffset
-    ///     Offset, in seconds, this instance should start playing
-    ///     from. @todo take samples (for easier implementation of
-    ///     seekSamples in streaming sound).
+    /// @param inPoint
+    ///     Offset in output samples this instance should start
+    ///     playing from. These are post-resampling samples from
+    ///     the start of the specified blockId.
+    ///     
+    ///
+    /// @param outPoint
+    ///     Offset in output samples this instance should stop
+    ///     playing at. These are post-resampling samples from
+    ///     the start of the specified blockId.
     ///
     /// @param envelopes
     ///     SoundEnvelopes to apply to this sound. May be 0 for none.
@@ -181,7 +187,8 @@
     /// Locks the _soundInstancesMutex when pushing to it
     ///
     std::auto_ptr<EmbedSoundInst> createInstance( media::MediaHandler& mh,
-            unsigned long blockOffset, unsigned int secsOffset,
+            unsigned long blockOffset,
+            unsigned int inPoint, unsigned int outPoint,
             const SoundEnvelopes* envelopes, unsigned int loopCount);
 
     /// Volume for AS-sounds, range: 0-100.

=== modified file 'libsound/EmbedSoundInst.cpp'
--- a/libsound/EmbedSoundInst.cpp       2009-06-09 14:04:51 +0000
+++ b/libsound/EmbedSoundInst.cpp       2009-06-10 11:27:47 +0000
@@ -52,7 +52,8 @@
 EmbedSoundInst::EmbedSoundInst(EmbedSound& soundData,
             media::MediaHandler& mediaHandler,
             sound_handler::StreamBlockId blockOffset,
-            unsigned int secsOffset,
+            unsigned int inPoint,
+            unsigned int outPoint,
             const SoundEnvelopes* env,
             unsigned int loopCount)
         :
@@ -60,11 +61,20 @@
         // should store blockOffset somewhere else too, for resetting
         decodingPosition(blockOffset),
 
-        // should change based on offSecs I guess ?
-        playbackPosition(0),
-
         loopCount(loopCount),
-        offSecs(secsOffset),
+
+        // parameter is in stereo samples (44100 per second)
+        // we double to take 2 channels into account
+        // and double again to use bytes
+        _inPoint(inPoint*4),
+
+        // parameter is in stereo samples (44100 per second)
+        // we double to take 2 channels into account
+        // and double again to use bytes
+        _outPoint( outPoint == std::numeric_limits<unsigned int>::max() ?
+                   std::numeric_limits<unsigned long>::max()
+                   : outPoint * 4),
+
         envelopes(env),
         current_env(0),
         _samplesFetched(0),
@@ -73,6 +83,8 @@
         _soundDef(soundData),
         _decodedData(0)
 {
+    playbackPosition = _inPoint; 
+
     createDecoder(mediaHandler);
 }
 
@@ -112,6 +124,15 @@
     else return 0;
 }
 
+bool
+EmbedSoundInst::reachedCustomEnd() const
+{
+    if ( _outPoint == std::numeric_limits<unsigned long>::max() )
+            return false;
+    if ( playbackPosition >= _outPoint ) return true;
+    return false;
+}
+
 unsigned int 
 EmbedSoundInst::fetchSamples(boost::int16_t* to, unsigned int nSamples)
 {
@@ -161,10 +182,8 @@
         // We haven't finished fetching yet, so see if we
         // have more to decode or not
 
-        if ( decodingCompleted() )
+        if ( decodingCompleted() || reachedCustomEnd() )
         {
-            // No more to decode, see if we want to loop...
-
             if ( loopCount )
             {
 #ifdef GNASH_DEBUG_SOUNDS_MANAGEMENT
@@ -175,14 +194,23 @@
                 // position and keep looping
                 --loopCount;
 
-                // @todo playbackPosition is not necessarely 0
-                //       if we were asked to start somewhere after that!!
-                playbackPosition=0;
+                // Start next loop
+                playbackPosition = _inPoint; 
 
                 continue;
             }
 
-            log_debug("Decoding completed and no looping, sound is over");
+#ifdef GNASH_DEBUG_SOUNDS_MANAGEMENT
+            if ( reachedCustomEnd() )
+            {
+                log_debug("Reached custom end (pos:%d out:%d) and no looping, "
+                          "sound is over", playbackPosition, _outPoint);
+            }
+            else
+            {
+                log_debug("Decoding completed and no looping, sound is over");
+            }
+#endif
             break; // fetched what possible, filled with silence the rest
         }
 
@@ -207,7 +235,7 @@
     // Doing so we know what's the sample number
     // of the first sample in the newly decoded block.
     //
-    assert(playbackPosition >= decodedDataSize() );
+    assert( playbackPosition >= decodedDataSize() );
 
     boost::uint32_t inputSize = 0; // or blockSize
     bool parse = true; // need to parse ?
@@ -402,7 +430,7 @@
 {
     // it isn't threaded, but just in case, we call decodingCompleted first
     // and we also check loopCount... (over paranoid?)
-    return ( decodingCompleted() && !loopCount && !decodedSamplesAhead() );
+    return ( ( decodingCompleted() || reachedCustomEnd() ) && !loopCount && 
!decodedSamplesAhead() );
 }
 
 EmbedSoundInst::~EmbedSoundInst()
@@ -416,67 +444,9 @@
     if ( ! _decodedData.get() )
     {
         _decodedData.reset( new SimpleBuffer );
-
-        // Skip samples if requested and we're at the start
-        const media::SoundInfo& sinfo = *(_soundDef.soundinfo);
-        boost::int16_t delaySeek = sinfo.getDelaySeek();
-
-        if ( delaySeek > 0 )
-        {
-            // seek the specified number of samples and throw them away
-
-            // each sample is 2 bytes per channel, and we're stereo
-            unsigned int off = delaySeek*4;
-
-            // delaySeek refers to pre-resampled state so we need to
-            // take that into account.
-            //
-            // NOTE: this was tested with inputs:
-            //     - isStereo?0 is16bit()?1 sampleRate?22050
-            //     - isStereo?1 is16bit()?1 sampleRate?22050
-            //     - isStereo?1 is16bit()?1 sampleRate?44100
-            // TODO: test with other sample sizes !
-            //log_debug("NOTE: isStereo?%d is16bit()?%d sampleRate?%d",
-            //  sinfo.isStereo(), sinfo.is16bit(), sinfo.getSampleRate());
-            //
-            off *= 44100/sinfo.getSampleRate();
-
-
-            if ( off < size )
-            {
-                log_debug("Skipping first %d samples of event sound", off/2);
-                _decodedData->append(data+off, size-off);
-            }
-            else
-            {
-                // TODO: could be there'll be more samples later
-                //       so we need to keep track of how many we decoded
-                //       at this stage
-                log_error("delaySeek (%d) >= initial block samples (%d)",
-                    delaySeek, size/2);
-            }
-        }
-        else if ( delaySeek < 0 )
-        {
-            // insert delaySeek samples of silence here
-
-            // TODO: use a stack-allocated buffer and a loop here
-            unsigned int silenceSize = -delaySeek*2; // we talk 8bit
-            boost::scoped_array<boost::uint8_t> silence (
-                new boost::uint8_t[silenceSize]
-            );
-            _decodedData->append(silence.get(), silenceSize);
-            _decodedData->append(data, size);
-        }
-        else
-        {
-            _decodedData->append(data, size);
-        }
-    }
-    else
-    {
-        _decodedData->append(data, size);
-    }
+    }
+
+    _decodedData->append(data, size);
 
     delete [] data; // ownership transferred...
 }

=== modified file 'libsound/EmbedSoundInst.h'
--- a/libsound/EmbedSoundInst.h 2009-06-09 14:04:51 +0000
+++ b/libsound/EmbedSoundInst.h 2009-06-10 11:27:47 +0000
@@ -66,23 +66,32 @@
     ///
     /// @param blockId
     ///     Identifier of the encoded block to start decoding from.
-    ///     @see gnash::swf::StreamBlockIdTag
-    ///
-    /// @param secsOffset
-    ///     Offset, in seconds, this instance should start playing
-    ///     from. @todo take samples (for easier implementation of
-    ///     seekSamples in streaming sound).
+    ///     @see gnash::swf::StreamSoundBlockTag
+    ///
+    /// @param inPoint
+    ///     Offset in output samples this instance should start
+    ///     playing from. These are post-resampling samples (44100 
+    ///     for one second of samples).
+    ///
+    /// @param outPoint
+    ///     Offset in output samples this instance should stop
+    ///     playing at. These are post-resampling samples (44100 
+    ///     for one second of samples).
+    ///     Use numeric_limits<unsigned int>::max() for never
     ///
     /// @param envelopes
     ///     SoundEnvelopes to apply to this sound. May be 0 for none.
     ///
     /// @param loopCount
     ///     Number of times this instance should loop over the defined sound.
-    ///     @todo document if every loop starts at secsOffset !
+    ///     Note that every loop begins and ends at the range given by
+    ///     inPoint and outPoint.
     ///
     EmbedSoundInst(EmbedSound& def, media::MediaHandler& mh,
             sound_handler::StreamBlockId blockId,
-            unsigned int secsOffset, const SoundEnvelopes* envelopes,
+            unsigned int inPoint,
+            unsigned int outPoint,
+            const SoundEnvelopes* envelopes,
             unsigned int loopCount);
 
     // See dox in sound_handler.h (InputStream)
@@ -112,11 +121,13 @@
     /// For every loop completed, it is decremented.
     long loopCount;
 
-    /// Offset in seconds to make playback start in-sync
-    //
-    /// only used with mp3 streams.
-    ///
-    unsigned int offSecs;
+    /// Offset in bytes samples from start of the block
+    /// to begin playback from
+    unsigned long _inPoint;
+
+    /// Offset in bytes to end playback at
+    /// Never if numeric_limits<unsigned long>::max()
+    unsigned long _outPoint;
 
     /// Sound envelopes for the current sound, which determine the volume level
     /// from a given position. Only used with event sounds.
@@ -220,13 +231,24 @@
     /// from playback position on
     unsigned int decodedSamplesAhead() const
     {
-        unsigned int bytesAhead = decodedDataSize() - playbackPosition;
+        unsigned int dds = decodedDataSize();
+        if ( dds <= playbackPosition ) return 0; 
+        unsigned int bytesAhead = dds - playbackPosition;
         assert(!(bytesAhead%2));
 
+        if ( _outPoint < std::numeric_limits<unsigned long>::max() )
+        {
+            unsigned int toCustomEnd = _outPoint-playbackPosition;
+            if ( toCustomEnd < bytesAhead ) bytesAhead = toCustomEnd;
+        }
+
         unsigned int samplesAhead = bytesAhead/2;
+
         return samplesAhead;
     }
 
+    bool reachedCustomEnd() const;
+
     /// Return true if there's nothing more to decode
     bool decodingCompleted() const
     {

=== modified file 'libsound/sound_handler.cpp'
--- a/libsound/sound_handler.cpp        2009-06-09 14:04:51 +0000
+++ b/libsound/sound_handler.cpp        2009-06-10 11:27:47 +0000
@@ -332,27 +332,49 @@
 
 }
 
+/*static private*/
+unsigned int
+sound_handler::swfToOutSamples(const media::SoundInfo& sinfo,
+                                      unsigned int swfSamples)
+{
+    // swf samples refers to pre-resampled state so we need to
+    // take that into account.
+
+
+    static const unsigned int outSampleRate = 44100;
+
+    unsigned int outSamples = swfSamples *
+                                (outSampleRate/sinfo.getSampleRate());
+
+    // NOTE: this was tested with inputs:
+    //     - isStereo?0 is16bit()?1 sampleRate?11025
+    //     - isStereo?0 is16bit()?1 sampleRate?22050
+    //     - isStereo?1 is16bit()?1 sampleRate?22050
+    //     - isStereo?0 is16bit()?1 sampleRate?44100
+    //     - isStereo?1 is16bit()?1 sampleRate?44100
+    //
+    // TODO: test with other sample sizes !
+    //
+#if 1
+    log_debug("NOTE: isStereo?%d is16bit()?%d sampleRate?%d",
+              sinfo.isStereo(), sinfo.is16bit(), sinfo.getSampleRate());
+#endif
+
+
+    return outSamples;
+}
+
+
+
 void
-sound_handler::playSound(int sound_handle, int loopCount, int offSecs,
-                            StreamBlockId blockId,
-                            const SoundEnvelopes* envelopes,
-                            bool allowMultiples)
+sound_handler::playSound(int sound_handle, int loopCount,
+                         unsigned int inPoint,
+                         unsigned int outPoint,
+                         StreamBlockId blockId,
+                         const SoundEnvelopes* envelopes,
+                         bool allowMultiples)
 {
-    // Check if the sound exists
-    if (sound_handle < 0 || static_cast<unsigned int>(sound_handle) >= 
_sounds.size())
-    {
-        log_error("Invalid (%d) sound_handle passed to playSound, "
-                  "doing nothing", sound_handle);
-        return;
-    }
-
-    // parameter checking
-    if (offSecs < 0)
-    {
-        log_error("Negative (%d) seconds offset passed to playSound, "
-                  "taking as zero ", offSecs);
-        offSecs = 0;
-    }
+    assert (sound_handle >= 0 && static_cast<unsigned int>(sound_handle) < 
_sounds.size());
 
     EmbedSound& sounddata = *(_sounds[sound_handle]);
 
@@ -385,11 +407,6 @@
         return;
     }
 
-    if (offSecs)
-    {
-        LOG_ONCE(log_unimpl("Time based sound start offset"));
-    }
-
     // Make a "EmbedSoundInst" for this sound which is later placed
     // on the vector of instances of this sound being played
     //
@@ -404,10 +421,8 @@
             // Sound block identifier
             blockId, 
 
-            // Seconds offset
-            // WARNING: this is wrong, offset is passed as seconds !!
-            // (currently unused anyway)
-            (sounddata.soundinfo->isStereo() ? offSecs : offSecs*2),
+            // Samples range
+            inPoint, outPoint,
 
             // Volume envelopes to use for this instance
             envelopes,
@@ -424,16 +439,74 @@
 void
 sound_handler::playStream(int soundId, StreamBlockId blockId)
 {
-    playSound(soundId, 0, 0, blockId, 0, false);
+    unsigned int inPoint=0;
+    unsigned int outPoint=std::numeric_limits<unsigned int>::max();
+
+    playSound(soundId, 0, inPoint, outPoint, blockId, 0, false);
 }
 
 /*public*/
 void
-sound_handler::startSound(int soundId, int loops, int secsOffset,
+sound_handler::startSound(int soundId, int loops, 
                       const SoundEnvelopes* env,
-                      bool allowMultiple)
+                      bool allowMultiple, unsigned int inPoint,
+                   unsigned int outPoint)
 {
-    playSound(soundId, loops, secsOffset, 0, env, allowMultiple);
+    // Check if the sound exists
+    if (soundId < 0 ||
+        static_cast<unsigned int>(soundId) >= _sounds.size())
+    {
+        log_error("Invalid (%d) sound_handle passed to startSound, "
+                  "doing nothing", soundId);
+        return;
+    }
+
+
+    // Handle delaySeek
+
+    EmbedSound& sounddata = *(_sounds[soundId]);
+    const media::SoundInfo& sinfo = *(sounddata.soundinfo);
+
+    int swfDelaySeek = sinfo.getDelaySeek(); 
+    if ( swfDelaySeek )
+    {
+        // NOTE: differences between delaySeek and inPoint:
+        //
+        //      - Sample count semantic:
+        //        inPoint uses output sample rate (44100 for one second)
+        //        while delaySeek uses source sample rate
+        //        (SoundInfo.getSampleRate() for one second)
+        //
+        //      - Loop-back semantic:
+        //        An event sound always loops-back from inPoint with no gaps
+        //        When delaySeek is specified it is still used as a start
+        //        for the initial playback but when it comes to looping back
+        //        it seems to play silence instead of samples for the amount
+        //        skipped:
+        //
+        //               [ delaySeekTime ]
+        //        loop1                  *****************
+        //        loop2  ----------------*****************
+        //        loop3  ----------------*****************
+        //
+        //               [ inPoint ]
+        //        loop1             *****************
+        //        loop2             *****************
+        //        loop3             *****************
+        //
+        LOG_ONCE(log_unimpl("MP3 delaySeek"));
+#if 0
+        unsigned int outDelaySeek = swfToOutSamples(sinfo, swfDelaySeek);
+
+        log_debug("inPoint(%d) + delaySeek(%d -> %d) == %d",
+                  inPoint, swfDelaySeek, outDelaySeek,
+                  inPoint+outDelaySeek);
+
+        inPoint += outDelaySeek;
+#endif
+    }
+
+    playSound(soundId, loops, inPoint, outPoint, 0, env, allowMultiple);
 }
 
 void

=== modified file 'libsound/sound_handler.h'
--- a/libsound/sound_handler.h  2009-06-09 14:53:45 +0000
+++ b/libsound/sound_handler.h  2009-06-10 11:27:47 +0000
@@ -37,6 +37,7 @@
 #include <memory>
 #include <cassert>
 #include <cstring>
+#include <limits>
 #include <set> // for composition
 
 namespace gnash {
@@ -163,11 +164,17 @@
     /// @param loops
     ///     loops == 0 means play the sound once (1 means play it twice, etc)
     ///
-    /// @param secsOffset
-    ///     When starting event sounds there sometimes is a offset to make
-    ///     the sound start at the exact right moment. Gnash supports this
-    ///     through 'Sound' AS class only, not from the actual control tag
-    ///     (StartSound). Units given in seconds.
+    /// @param inPoint
+    ///     Offset in output samples this instance should start
+    ///     playing from. These are post-resampling samples (44100 
+    ///     for one second of samples).
+    ///
+    /// @param outPoint
+    ///     Offset in output samples this instance should stop
+    ///     playing at. These are post-resampling samples (44100 
+    ///     for one second of samples).
+    ///     Use std::numeric_limits<unsigned int>::max() for no limit
+    ///     (default if missing)
     ///
     /// @param env
     ///     Some eventsounds have some volume control mechanism called
@@ -178,12 +185,11 @@
     ///     If false, the sound will not be scheduled if there's another
     ///     instance of it already playing.
     ///
-    /// TODO: add inPoint and outPoint parameters
-    ///       (pre-resampling samples offset of start and end)
-    ///       or take SWF::SoundInfoRecord& directly !
-    void startSound(int id, int loops, int secsOffset,
+    ///
+    void startSound(int id, int loops, 
                    const SoundEnvelopes* env,
-                   bool allowMultiple);
+                   bool allowMultiple, unsigned int inPoint=0,
+                   unsigned int outPoint=std::numeric_limits<unsigned 
int>::max());
 
     /// Start playback of a streaming sound, if not playing already
     //
@@ -504,11 +510,15 @@
     /// @param loops
     ///     loops == 0 means play the sound once (1 means play it twice, etc)
     ///
-    /// @param secsOffset
-    ///     When starting event sounds there sometimes is a offset to make
-    ///     the sound start at the exact right moment. Gnash supports this
-    ///     through 'Sound' AS class only, not from the actual control tag
-    ///     (StartSound). Units given in seconds.
+    /// @param inPoint
+    ///     Offset in output samples this instance should start
+    ///     playing from. These are post-resampling samples (44100 
+    ///     for one second of samples).
+    ///
+    /// @param outPoint
+    ///     Offset in output samples this instance should stop
+    ///     playing at. These are post-resampling samples (44100 
+    ///     for one second of samples).
     ///
     /// @param blockId
     ///     When starting a soundstream from a random frame, this tells which
@@ -525,12 +535,30 @@
     ///     If false, the sound will not be scheduled if there's another
     ///     instance of it already playing.
     ///
-    /// TODO: add out_point parameter (when to stop playing the sound)
-    ///
-    void playSound(int id, int loops, int secsOffset,
+    void playSound(int id, int loops,
+                   unsigned int inPoint,
+                   unsigned int outPoint,
                    StreamBlockId blockId, const SoundEnvelopes* env,
                    bool allowMultiple);
 
+    /// Convert SWF-specified number of samples to output number of samples
+    //
+    /// SWF-specified number of samples are: delaySeek in DEFINESOUND,
+    /// latency in STREAMSOUNDHEAD and seekSamples in STREAMSOUNDBLOCK.
+    /// These refer to samples at the sampleRate of input.
+    ///
+    /// As gnash will resample the sounds to match expected output
+    /// (44100 Hz, stereo 16bit) this function is handy to convert
+    /// for simpler use later.
+    ///
+    /// It is non-static in the event we'll one day allow different
+    /// sound_handler instances to be configured with different output
+    /// sample rate (would need a lot more changes atm but let's keep
+    /// that in mind).
+    ///
+    unsigned int swfToOutSamples(const media::SoundInfo& sinfo,
+                                          unsigned int swfSamples);
+
 };
 
 // TODO: move to appropriate specific sound handlers

=== modified file 'testsuite/misc-ming.all/eventSoundTest1.c'
--- a/testsuite/misc-ming.all/eventSoundTest1.c 2009-06-10 11:08:18 +0000
+++ b/testsuite/misc-ming.all/eventSoundTest1.c 2009-06-10 11:27:47 +0000
@@ -323,6 +323,9 @@
   pauseForNextTest(mo);
   runAttachedSoundsTest(mo, so, &frame);
 
+  // TODO: test inPoint/outPoint (+ with loop ?)
+  // TODO: test start(<sec_offset>) (+ with loop ?)
+
   endOfTests(mo);
 
   //Output movie


reply via email to

[Prev in Thread] Current Thread [Next in Thread]