1
// SoundMad.cpp: Play sounds using libmad (MP3 audio decoder), for Gnash.
3
// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5
// This program is free software; you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation; either version 3 of the License, or
8
// (at your option) any later version.
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
// GNU General Public License for more details.
15
// You should have received a copy of the GNU General Public License
16
// along with this program; if not, write to the Free Software
17
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
#include "gnashconfig.h"
26
#include "sound_definition.h" // for sound_sample
27
#include "movie_definition.h"
28
#include "sprite_instance.h"
30
#include "GnashException.h"
31
#include "builtin_function.h"
32
#include "utility.h" // for convert_raw_data
39
SoundMad::readPacket(boost::uint8_t* buf, int buf_size)
42
size_t ret = connection->read(static_cast<void*>(buf), buf_size);
49
SoundMad::seekMedia(int offset, int whence){
51
// Offset is absolute new position in the file
52
if (whence == SEEK_SET) {
53
connection->seek(offset);
56
// New position is offset + old position
57
} else if (whence == SEEK_CUR) {
58
connection->seek(inputPos + offset);
59
inputPos = inputPos + offset;
61
// // New position is offset + end of file
62
} else if (whence == SEEK_END) {
63
// This is (most likely) a streamed file, so we can't seek to the end!
64
// Instead we seek to 50.000 bytes... seems to work fine...
65
connection->seek(50000);
75
SoundMad::setupDecoder(SoundMad* so)
78
boost::intrusive_ptr<NetConnection> nc = so->connection;
81
// Pass stuff from/to the NetConnection object.
83
if ( !nc->openConnection(so->externalURL) ) {
84
log_error(_("Gnash could not open audio url: %s"), so->externalURL.c_str());
91
// Init the mad decoder
92
mad_stream_init(&so->stream);
93
mad_frame_init(&so->frame);
94
mad_synth_init(&so->synth);
96
// Decode a single frame to decode the header
98
// Fetch data from the file
99
so->seekMedia(0, SEEK_SET);
100
boost::uint8_t* buf = new boost::uint8_t[1024];
101
int bufSize = so->readPacket(buf, 1024);
103
// Setup the mad decoder
104
mad_stream_buffer(&so->stream, buf, bufSize);
111
ret = mad_frame_decode(&so->frame, &so->stream);
114
// There is always some junk in front of the data,
115
// so we continue until we get past it.
116
if (ret && so->stream.error == MAD_ERROR_LOSTSYNC) continue;
118
// Error handling is done by relooping (max. 8 times) and just hooping that it will work...
119
if (loops > 8) break;
120
if (ret == -1 && so->stream.error != MAD_ERROR_BUFLEN && MAD_RECOVERABLE(so->stream.error)) {
121
log_error(_("Recoverable error while decoding MP3, MAD error: %s"), mad_stream_errorstr (&so->stream));
126
so->bitrate = so->frame.header.bitrate;
128
so->seekMedia(0, SEEK_SET);
131
// By deleting this lock we allow start() to start playback
136
// audio callback is running in sound handler thread
137
bool SoundMad::getAudio(void* owner, boost::uint8_t* stream, int len)
139
SoundMad* so = static_cast<SoundMad*>(owner);
141
unsigned int pos = 0;
143
// First use the data left over from last time
144
if (so->leftOverSize > 0) {
146
// If we have enough "leftover" data to fill the buffer,
147
// we don't bother to decode some new.
148
if (so->leftOverSize >= len) {
149
memcpy(stream, so->leftOverData, len);
150
int rest = so->leftOverSize - len;
152
delete[] so->leftOverData;
153
so->leftOverSize = 0;
155
boost::uint8_t* buf = new boost::uint8_t[rest];
156
memcpy(stream, so->leftOverData+len, rest);
157
delete[] so->leftOverData;
158
so->leftOverData = buf;
159
so->leftOverSize -= len;
163
memcpy(stream, so->leftOverData, so->leftOverSize);
164
pos += so->leftOverSize;
165
so->leftOverSize = 0;
166
delete[] so->leftOverData;
170
boost::uint8_t* buf = new boost::uint8_t[8192];
171
int bufSize = so->readPacket(buf, 8192);
172
int orgBufSize = bufSize;
175
boost::uint8_t* ptr = new boost::uint8_t[8192];
178
media::sound_handler* s = get_sound_handler();
182
boost::uint8_t* tmp_raw_buffer;
183
unsigned int tmp_raw_buffer_size;
188
// Setup the mad decoder
189
mad_stream_buffer(&so->stream, buf+(orgBufSize-bufSize), bufSize);
192
const unsigned char* old_next_frame = so->stream.next_frame;
196
ret = mad_frame_decode(&so->frame, &so->stream);
199
// There is always some junk in front of the data,
200
// so we continue until we get past it.
201
if (ret && so->stream.error == MAD_ERROR_LOSTSYNC) continue;
203
// Error handling is done by relooping (max. 8 times) and just hooping that it will work...
204
if (loops > 8) break;
205
if (ret == -1 && so->stream.error != MAD_ERROR_BUFLEN && MAD_RECOVERABLE(so->stream.error)) {
206
log_error(_("Recoverable error while decoding MP3, MAD error: %s"), mad_stream_errorstr (&so->stream));
213
if (ret == -1 && so->stream.error != MAD_ERROR_BUFLEN) {
214
log_error(_("Unrecoverable error while decoding MP3, MAD error: %s"), mad_stream_errorstr (&so->stream));
217
} else if (ret == -1 && so->stream.error == MAD_ERROR_BUFLEN) {
218
// the buffer is empty, no more to decode!
222
bufSize -= so->stream.next_frame - old_next_frame;
225
mad_synth_frame (&so->synth, &so->frame);
227
outsize = so->synth.pcm.length * ((so->frame.header.mode) ? 4 : 2);
229
tmp_raw_buffer = new boost::uint8_t[outsize];
232
boost::int16_t* dst = reinterpret_cast<boost::int16_t*>(tmp_raw_buffer);
234
// transfer the decoded samples into the sound-struct, and do some
235
// scaling while we're at it.
236
for(int f = 0; f < so->synth.pcm.length; f++)
238
for (int e = 0; e < ((so->frame.header.mode) ? 2 : 1); e++){ // channels (stereo/mono)
240
mad_fixed_t mad_sample = so->synth.pcm.samples[e][f];
243
mad_sample += (1L << (MAD_F_FRACBITS - 16));
246
if (mad_sample >= MAD_F_ONE) mad_sample = MAD_F_ONE - 1;
247
else if (mad_sample < -MAD_F_ONE) mad_sample = -MAD_F_ONE;
250
sample = mad_sample >> (MAD_F_FRACBITS + 1 - 16);
252
if ( sample != static_cast<boost::int16_t>(sample) ) sample = sample < 0 ? -32768 : 32767;
258
// If we need to convert samplerate or/and from mono to stereo...
259
if (outsize > 0 && (so->frame.header.samplerate != 44100 || !so->frame.header.mode)) {
261
boost::int16_t* adjusted_data = 0;
262
int adjusted_size = 0;
263
int sample_count = outsize / ((so->frame.header.mode) ? 4 : 2);
265
// Convert to needed samplerate
266
convert_raw_data(&adjusted_data, &adjusted_size, tmp_raw_buffer, sample_count, 2,
267
so->frame.header.samplerate, so->frame.header.mode,
268
44100, true/*stereo*/);
270
// Hopefully this won't happen
271
if (!adjusted_data) {
272
log_error(_("Error in sound sample convertion"));
276
// Move the new data to the sound-struct
277
delete[] tmp_raw_buffer;
278
tmp_raw_buffer = reinterpret_cast<boost::uint8_t*>(adjusted_data);
279
tmp_raw_buffer_size = adjusted_size;
282
tmp_raw_buffer_size = outsize;
288
// Copy the data to buffer
289
// If the decoded data isn't enough to fill the buffer, we put the decoded
290
// data into the buffer, and continues decoding.
291
if (tmp_raw_buffer_size <= len-pos) {
292
memcpy(stream+pos, tmp_raw_buffer, tmp_raw_buffer_size);
293
pos += tmp_raw_buffer_size;
295
// If we can fill the buffer, and still have "leftovers", we save them
296
// and use them later.
298
so->leftOverSize = tmp_raw_buffer_size - rest;
299
memcpy(stream+pos, tmp_raw_buffer, rest);
300
so->leftOverData = new boost::uint8_t[so->leftOverSize];
301
memcpy(so->leftOverData, (tmp_raw_buffer)+rest, so->leftOverSize);
305
delete[] tmp_raw_buffer;
308
} else { // bufSize > 0
309
// If we should loop we make sure we do.
310
if (so->remainingLoops != 0) {
311
so->remainingLoops--;
313
// Seek to begining of file
314
so->seekMedia(0, SEEK_SET);
316
// Stops playback by returning false which makes the soundhandler
317
// detach this sound.
319
so->isAttached = false;
322
so->seekMedia(-bufSize, SEEK_CUR);
327
SoundMad::~SoundMad() {
328
if (leftOverData && leftOverSize) delete[] leftOverData;
331
mad_synth_finish(&synth);
332
mad_frame_finish(&frame);
333
mad_stream_finish(&stream);
335
media::sound_handler* s = get_sound_handler();
337
s->detach_aux_streamer(this);
344
SoundMad::loadSound(std::string file, bool streaming)
351
log_error(_("This sound already has a connection? (We try to handle this by overriding the old one...)"));
355
connection = new NetConnection();
357
externalSound = true;
358
isStreaming = streaming;
360
lock = new boost::mutex::scoped_lock(setupMutex);
362
// To avoid blocking while connecting, we use a thread.
363
setupThread = new boost::thread(boost::bind(SoundMad::setupDecoder, this));
368
SoundMad::start(int offset, int loops)
370
boost::mutex::scoped_lock lock(setupMutex);
373
seekMedia((bitrate*offset)/8, SEEK_SET);
375
// Save how many loops to do
377
remainingLoops = loops;
382
media::sound_handler* s = get_sound_handler();
387
s->attach_aux_streamer(getAudio, (void*) this);
391
s->play_sound(soundId, loops, offset, 0, NULL);
397
SoundMad::stop(int si)
400
media::sound_handler* s = get_sound_handler();
405
s->detach_aux_streamer(this);
407
s->stop_sound(soundId);
416
SoundMad::getDuration()
418
// If this is a event sound get the info from the soundhandler
419
if (!externalSound) {
420
media::sound_handler* s = get_sound_handler();
422
return (s->get_duration(soundId));
424
return 0; // just in case
428
// Return the duration of the file in milliseconds
429
/* if (formatCtx && audioIndex) {
430
return static_cast<unsigned int>(formatCtx->duration * 1000);
438
SoundMad::getPosition()
441
// If this is a event sound get the info from the soundhandler
442
if (!externalSound) {
443
media::sound_handler* s = get_sound_handler();
445
return s->get_position(soundId);
447
return 0; // just in case
451
// Return the position in the file in milliseconds
452
return inputPos/bitrate/8*1000;
455
} // end of gnash namespace