Check return from std::string::find
[gnash.git] / libsound / EmbedSoundInst.h
blobb21ae7204427c49523f902a3d743dc8ca7fbdbfb
1 // EmbedSoundInst.h - instance of an embedded sound, for gnash
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
4 // Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #ifndef SOUND_EMBEDSOUNDINST_H
21 #define SOUND_EMBEDSOUNDINST_H
23 #include "InputStream.h" // for inheritance
24 #include "AudioDecoder.h" // for dtor visibility
25 #include "SoundEnvelope.h" // for SoundEnvelopes typedef
26 #include "SimpleBuffer.h" // for composition (decoded data)
27 #include "EmbedSound.h" // for inlines
28 #include "sound_handler.h" // for StreamBlockId typedef
30 #include <memory>
31 #include <cassert>
32 #include <boost/cstdint.hpp> // For C99 int types
35 // Forward declarations
36 namespace gnash {
37 namespace sound {
38 class EmbedSound;
40 namespace media {
41 class MediaHandler;
45 namespace gnash {
46 namespace sound {
48 /// Instance of a defined %sound (EmbedSound)
50 /// This class contains a pointer to the EmbedSound used for playing
51 /// and a SimpleBuffer to use when decoding is needed.
52 ///
53 /// When the SimpleBuffer is NULL we'll play the EmbedSound bytes directly
54 /// (we assume they are decoded already)
55 ///
56 class EmbedSoundInst : public InputStream
58 public:
60 /// Create an embedded %sound instance
62 /// @param def
63 /// The definition of this sound (where immutable data is kept)
64 ///
65 /// @param mh
66 /// The MediaHandler to use for on-demand decoding
67 ///
68 /// @param blockId
69 /// Identifier of the encoded block to start decoding from.
70 /// @see gnash::swf::StreamSoundBlockTag
71 ///
72 /// @param inPoint
73 /// Offset in output samples this instance should start
74 /// playing from. These are post-resampling samples (44100
75 /// for one second of samples).
76 ///
77 /// @param outPoint
78 /// Offset in output samples this instance should stop
79 /// playing at. These are post-resampling samples (44100
80 /// for one second of samples).
81 /// Use numeric_limits<unsigned int>::max() for never
82 ///
83 /// @param envelopes
84 /// SoundEnvelopes to apply to this sound. May be 0 for none.
85 ///
86 /// @param loopCount
87 /// Number of times this instance should loop over the defined sound.
88 /// Note that every loop begins and ends at the range given by
89 /// inPoint and outPoint.
90 ///
91 EmbedSoundInst(EmbedSound& def, media::MediaHandler& mh,
92 sound_handler::StreamBlockId blockId,
93 unsigned int inPoint,
94 unsigned int outPoint,
95 const SoundEnvelopes* envelopes,
96 unsigned int loopCount);
98 // See dox in sound_handler.h (InputStream)
99 unsigned int fetchSamples(boost::int16_t* to, unsigned int nSamples);
101 // See dox in sound_handler.h (InputStream)
102 unsigned int samplesFetched() const;
104 // See dox in sound_handler.h (InputStream)
105 bool eof() const;
107 /// Unregister self from the associated EmbedSound
109 /// WARNING: must be thread-safe!
111 ~EmbedSoundInst();
113 private:
115 /// Current decoding position in the encoded stream
116 unsigned long decodingPosition;
118 /// Current playback position in the decoded stream
119 unsigned long playbackPosition;
121 /// Numbers of loops: -1 means loop forever, 0 means play once.
122 /// For every loop completed, it is decremented.
123 long loopCount;
125 /// Offset in bytes samples from start of the block
126 /// to begin playback from
127 unsigned long _inPoint;
129 /// Offset in bytes to end playback at
130 /// Never if numeric_limits<unsigned long>::max()
131 unsigned long _outPoint;
133 /// Sound envelopes for the current sound, which determine the volume level
134 /// from a given position. Only used with event sounds.
135 const SoundEnvelopes* envelopes;
137 /// Index of current envelope.
138 boost::uint32_t current_env;
140 /// Number of samples fetched so far.
141 unsigned long _samplesFetched;
143 /// Get the sound definition this object is an instance of
144 const EmbedSound& getSoundData() {
145 return _soundDef;
148 /// Append size bytes to this raw data
150 /// @param data
151 /// Data bytes, allocated with new[]. Ownership transferred.
153 /// @param size
154 /// Size of the 'data' buffer.
156 void appendDecodedData(boost::uint8_t* data, unsigned int size);
158 /// Set decoded data
160 /// @param data
161 /// Data bytes, allocated with new[]. Ownership transferred.
163 /// @param size
164 /// Size of the 'data' buffer.
166 void setDecodedData(boost::uint8_t* data, unsigned int size)
168 if ( ! _decodedData.get() )
170 _decodedData.reset( new SimpleBuffer() );
173 _decodedData->resize(0); // shouldn't release memory
174 _decodedData->append(data, size);
175 delete [] data; // ownership transferred...
178 size_t encodedDataSize() const
180 return _soundDef.size();
183 /// Apply envelope-volume adjustments
186 /// Modified envelopes cursor (current_env)
188 /// @param samples
189 /// The samples to apply envelopes to
191 /// @param nSamples
192 /// Number of samples in the samples array.
193 /// (nSamples*2 bytes).
195 /// @param firstSampleNum
196 /// Logical position of first sample in the array.
197 /// This number gives the sample position referred to
198 /// by SoundEnvelope objects.
200 /// @param env
201 /// SoundEnvelopes to apply.
204 void applyEnvelopes(boost::int16_t* samples, unsigned int nSamples,
205 unsigned int firstSampleNum,
206 const SoundEnvelopes& env);
208 /// AS-volume adjustment
210 /// @param samples
211 /// The 16bit samples to adjust volume of
213 /// @param nSamples
214 /// Number of samples in the array
216 /// @param volume
217 /// Volume factor
219 static void adjustVolume(boost::int16_t* samples,
220 unsigned int nSamples, float volume);
222 /// Returns the data pointer in the encoded datastream
223 /// for the given position. Boundaries are checked.
225 /// Uses _samplesFetched and playbackPosition
227 /// @todo make private
229 const boost::uint8_t* getEncodedData(unsigned long int pos);
231 /// Return number of already-decoded samples available
232 /// from playback position on
233 unsigned int decodedSamplesAhead() const
235 unsigned int dds = decodedDataSize();
236 if ( dds <= playbackPosition ) return 0;
237 unsigned int bytesAhead = dds - playbackPosition;
238 assert(!(bytesAhead%2));
240 if ( _outPoint < std::numeric_limits<unsigned long>::max() )
242 unsigned int toCustomEnd = _outPoint-playbackPosition;
243 if ( toCustomEnd < bytesAhead ) bytesAhead = toCustomEnd;
246 unsigned int samplesAhead = bytesAhead/2;
248 return samplesAhead;
251 bool reachedCustomEnd() const;
253 /// Return true if there's nothing more to decode
254 bool decodingCompleted() const
256 // example: 10 bytes of encoded data, decodingPosition 8 : more to decode
257 // example: 10 bytes of encoded data, decodingPosition 10 : nothing more to decode
259 return ( decodingPosition >= encodedDataSize() );
263 /// The decoder object used to convert the data into the playable format
264 std::auto_ptr<media::AudioDecoder> _decoder;
266 /// Create a decoder for this instance
268 /// If decoder creation fails an error will
269 /// be logged, and _decoder won't be set
270 ///
271 void createDecoder(media::MediaHandler& mediaHandler);
273 /// Return full size of the decoded data buffer
274 size_t decodedDataSize() const
276 if ( _decodedData.get() )
278 return _decodedData->size();
280 else return 0;
283 /// \brief
284 /// Returns the data pointer in the decoded datastream
285 /// for the given byte-offset.
287 /// Boundaries are checked.
289 /// @param pos offsets in bytes. This should usually be
290 /// a multiple of two, since decoded data is
291 /// composed of signed 16bit PCM samples..
293 boost::int16_t* getDecodedData(unsigned long int pos);
295 /// The encoded data
297 /// It is non-const because we deregister ourselves
298 /// from its container of playing instances on destruction
300 EmbedSound& _soundDef;
302 /// The decoded buffer
304 /// If NULL, the _soundDef will be considered
305 /// decoded instead
307 std::auto_ptr<SimpleBuffer> _decodedData;
309 /// Decode next input block
311 /// It's assumed !decodingCompleted()
313 void decodeNextBlock();
317 } // gnash.sound namespace
318 } // namespace gnash
320 #endif // SOUND_EMBEDSOUNDINST_H