stupid linker bug... why?

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6211 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
shatty
2004-01-21 11:21:49 +00:00
parent a2d20d9daa
commit f9df549e6f
4 changed files with 64 additions and 37 deletions
@@ -3,7 +3,7 @@
bool SpeexSettings::perceptual_post_filter = true; bool SpeexSettings::perceptual_post_filter = true;
speex_mode SpeexSettings::preferred_band = automatic_band; speex_mode SpeexSettings::preferred_band = automatic_band;
speex_channels SpeexSettings::preferred_channels = automatic_channels; speex_channels SpeexSettings::preferred_channels = automatic_channels;
float SpeexSettings::sampling_rate = 0; int SpeexSettings::sampling_rate = 0;
SpeexSettings::SpeexSettings() SpeexSettings::SpeexSettings()
{ {
@@ -28,7 +28,7 @@ SpeexSettings::PreferredChannels(void)
} }
// if non-zero, specifies a sampling rate in Hertz // if non-zero, specifies a sampling rate in Hertz
/* static */ float /* static */ int
SpeexSettings::SamplingRate(void) SpeexSettings::SamplingRate(void)
{ {
return sampling_rate; return sampling_rate;
@@ -20,11 +20,11 @@ public:
static speex_mode PreferredBand(void); static speex_mode PreferredBand(void);
static speex_channels PreferredChannels(void); static speex_channels PreferredChannels(void);
// if non-zero, specifies a sampling rate in Hertz // if non-zero, specifies a sampling rate in Hertz
static float SamplingRate(void); static int SamplingRate(void);
private: private:
static bool perceptual_post_filter; static bool perceptual_post_filter;
static speex_mode preferred_band; static speex_mode preferred_band;
static speex_channels preferred_channels; static speex_channels preferred_channels;
static float sampling_rate; static int sampling_rate;
}; };
@@ -31,8 +31,9 @@ speexDecoder::speexDecoder()
speex_bits_init(&fBits); speex_bits_init(&fBits);
fDecoderState = 0; fDecoderState = 0;
fHeader = 0; fHeader = 0;
fStereoState = 0;
fSpeexFrameSize = 0; fSpeexFrameSize = 0;
fSpeexBytesRemaining = 0; fSpeexBuffer = 0;
fStartTime = 0; fStartTime = 0;
fFrameSize = 0; fFrameSize = 0;
fOutputBufferSize = 0; fOutputBufferSize = 0;
@@ -42,6 +43,8 @@ speexDecoder::speexDecoder()
speexDecoder::~speexDecoder() speexDecoder::~speexDecoder()
{ {
TRACE("speexDecoder::~speexDecoder\n"); TRACE("speexDecoder::~speexDecoder\n");
delete fStereoState;
delete fSpeexBuffer;
speex_bits_destroy(&fBits); speex_bits_destroy(&fBits);
speex_decoder_destroy(fDecoderState); speex_decoder_destroy(fDecoderState);
} }
@@ -51,6 +54,7 @@ status_t
speexDecoder::Setup(media_format *inputFormat, speexDecoder::Setup(media_format *inputFormat,
const void *infoBuffer, int32 infoSize) const void *infoBuffer, int32 infoSize)
{ {
debugger("speexDecoder::Setup");
if (inputFormat->type != B_MEDIA_ENCODED_AUDIO) { if (inputFormat->type != B_MEDIA_ENCODED_AUDIO) {
TRACE("speexDecoder::Setup not called with audio stream: not speex\n"); TRACE("speexDecoder::Setup not called with audio stream: not speex\n");
return B_ERROR; return B_ERROR;
@@ -81,37 +85,54 @@ speexDecoder::Setup(media_format *inputFormat,
fHeader = 0; fHeader = 0;
return B_ERROR; return B_ERROR;
} }
if (fHeader->mode >= SPEEX_NB_MODES) { // modify header to reflect settings
TRACE("speexDecoder::Setup failed: unknown speex mode\n");
return B_ERROR;
}
// setup mode
SpeexMode * mode;
switch (SpeexSettings::PreferredBand()) { switch (SpeexSettings::PreferredBand()) {
case narrow_band: case narrow_band:
mode = &speex_nb_mode; fHeader->mode = 0;
break; break;
case wide_band: case wide_band:
mode = &speex_wb_mode; fHeader->mode = 1;
break; break;
case ultra_wide_band: case ultra_wide_band:
mode = &speex_uwb_mode; fHeader->mode = 2;
break; break;
case automatic_band: case automatic_band:
default: default:
mode = speex_mode_list[fHeader->mode];
break; break;
} }
switch (SpeexSettings::PreferredChannels()) {
case mono_channels:
fHeader->nb_channels = 1;
break;
case stereo_channels:
fHeader->nb_channels = 2;
break;
case automatic_channels:
default:
break;
}
if (SpeexSettings::SamplingRate() != 0) {
fHeader->rate = SpeexSettings::SamplingRate();
}
// sanity checks
#ifdef STRICT_SPEEX #ifdef STRICT_SPEEX
if (header->speex_version_id > 1) { if (header->speex_version_id > 1) {
TRACE("speexDecoder::Setup failed: version id too new"); TRACE("speexDecoder::Setup failed: version id too new");
return B_ERROR; return B_ERROR;
} }
#endif
if (fHeader->mode >= SPEEX_NB_MODES) {
TRACE("speexDecoder::Setup failed: unknown speex mode\n");
return B_ERROR;
}
// setup from header
SpeexMode * mode = speex_mode_list[fHeader->mode];
#ifdef STRICT_SPEEX
if (mode->bitstream_version != fHeader->mode_bitstream_version) { if (mode->bitstream_version != fHeader->mode_bitstream_version) {
TRACE("speexDecoder::Setup failed: bitstream version mismatch"); TRACE("speexDecoder::Setup failed: bitstream version mismatch");
return B_ERROR; return B_ERROR;
} }
#endif // STRICT_SPEEX #endif
fDecoderState = speex_decoder_init(mode); fDecoderState = speex_decoder_init(mode);
if (fDecoderState == NULL) { if (fDecoderState == NULL) {
TRACE("speexDecoder::Setup failed to initialize the decoder state"); TRACE("speexDecoder::Setup failed to initialize the decoder state");
@@ -119,11 +140,22 @@ speexDecoder::Setup(media_format *inputFormat,
} }
if (SpeexSettings::PerceptualPostFilter()) { if (SpeexSettings::PerceptualPostFilter()) {
int enabled = 1; int enabled = 1;
speex_decoder_ctl(fDecoderState,SPEEX_SET_ENH,&enabled); speex_decoder_ctl(fDecoderState, SPEEX_SET_ENH, &enabled);
} }
speex_decoder_ctl(fDecoderState,SPEEX_GET_FRAME_SIZE,&fSpeexFrameSize); speex_decoder_ctl(fDecoderState, SPEEX_GET_FRAME_SIZE, &fSpeexFrameSize);
if (fHeader->nb_channels == 2) {
SpeexCallback callback;
SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT;
callback.callback_id = SPEEX_INBAND_STEREO;
callback.func = speex_std_stereo_request_handler;
fStereoState = new SpeexStereoState(stereo);
callback.data = fStereoState;
speex_decoder_ctl(fDecoderState, SPEEX_SET_HANDLER, &callback);
fSpeexFrameSize *= 2;
}
delete fSpeexBuffer;
fSpeexBuffer = new float[fSpeexFrameSize]; fSpeexBuffer = new float[fSpeexFrameSize];
speex_decoder_ctl(fDecoderState, SPEEX_SET_SAMPLING_RATE, &fHeader->rate);
// fill out the encoding format // fill out the encoding format
CopyInfoToEncodedFormat(inputFormat); CopyInfoToEncodedFormat(inputFormat);
return B_OK; return B_OK;
@@ -137,6 +169,9 @@ void speexDecoder::CopyInfoToEncodedFormat(media_format * format) {
= (media_encoded_audio_format::audio_encoding)'Spee'; = (media_encoded_audio_format::audio_encoding)'Spee';
if (fHeader->bitrate > 0) { if (fHeader->bitrate > 0) {
format->u.encoded_audio.bit_rate = fHeader->bitrate; format->u.encoded_audio.bit_rate = fHeader->bitrate;
} else {
speex_decoder_ctl(fDecoderState, SPEEX_GET_BITRATE, &fHeader->bitrate);
format->u.encoded_audio.bit_rate = fHeader->bitrate;
} }
if (fHeader->nb_channels == 1) { if (fHeader->nb_channels == 1) {
format->u.encoded_audio.multi_info.channel_mask = B_CHANNEL_LEFT; format->u.encoded_audio.multi_info.channel_mask = B_CHANNEL_LEFT;
@@ -154,6 +189,7 @@ void speexDecoder::CopyInfoToDecodedFormat(media_raw_audio_format * raf) {
raf->byte_order = B_MEDIA_HOST_ENDIAN; // XXX should support other endain, too raf->byte_order = B_MEDIA_HOST_ENDIAN; // XXX should support other endain, too
if (raf->buffer_size < 512 || raf->buffer_size > 65536) { if (raf->buffer_size < 512 || raf->buffer_size > 65536) {
raf->buffer_size = AudioBufferSize(raf); raf->buffer_size = AudioBufferSize(raf);
raf->buffer_size = (1 + raf->buffer_size / fSpeexFrameSize) * fSpeexFrameSize;
} }
// setup output variables // setup output variables
fFrameSize = (raf->format & 0xf) * raf->channel_count; fFrameSize = (raf->format & 0xf) * raf->channel_count;
@@ -205,21 +241,7 @@ speexDecoder::Decode(void *buffer, int64 *frameCount,
//TRACE("speexDecoder: Decoding start time %.6f\n", fStartTime / 1000000.0); //TRACE("speexDecoder: Decoding start time %.6f\n", fStartTime / 1000000.0);
// debugger("speexDecoder::Decode"); // debugger("speexDecoder::Decode");
while (out_bytes_needed > 0) { while (out_bytes_needed >= fSpeexFrameSize) {
if (fSpeexBytesRemaining > 0) {
if (fSpeexBytesRemaining < out_bytes_needed) {
memcpy(out_buffer,fSpeexBuffer,fSpeexBytesRemaining);
out_buffer += fSpeexBytesRemaining;
out_bytes_needed -= fSpeexBytesRemaining;
} else {
memcpy(out_buffer,fSpeexBuffer,out_bytes_needed);
memcpy(fSpeexBuffer,&fSpeexBuffer[fSpeexBytesRemaining],
fSpeexBytesRemaining-out_bytes_needed);
out_buffer += out_bytes_needed;
out_bytes_needed = 0;
break;
}
}
// get a new packet // get a new packet
void *chunkBuffer; void *chunkBuffer;
int32 chunkSize; int32 chunkSize;
@@ -238,8 +260,12 @@ speexDecoder::Decode(void *buffer, int64 *frameCount,
} }
ogg_packet * packet = static_cast<ogg_packet*>(chunkBuffer); ogg_packet * packet = static_cast<ogg_packet*>(chunkBuffer);
speex_bits_read_from(&fBits, (char*)packet->packet, packet->bytes); speex_bits_read_from(&fBits, (char*)packet->packet, packet->bytes);
speex_decode(fDecoderState, &fBits, fSpeexBuffer); speex_decode(fDecoderState, &fBits, (float*)out_buffer);
fSpeexBytesRemaining = fSpeexFrameSize; if (fHeader->nb_channels == 2) {
speex_decode_stereo((float*)out_buffer, fSpeexFrameSize, fStereoState);
}
out_buffer += fSpeexFrameSize;
out_bytes_needed -= fSpeexFrameSize;
} }
done: done:
@@ -1,6 +1,7 @@
#include "DecoderPlugin.h" #include "DecoderPlugin.h"
#include "speex.h" #include "speex.h"
#include "speex_header.h" #include "speex_header.h"
#include "speex_stereo.h"
#include "speex_callbacks.h" #include "speex_callbacks.h"
class speexDecoder : public Decoder class speexDecoder : public Decoder
@@ -29,10 +30,10 @@ private:
SpeexBits fBits; SpeexBits fBits;
void * fDecoderState; void * fDecoderState;
SpeexHeader * fHeader; SpeexHeader * fHeader;
SpeexStereoState * fStereoState;
int fSpeexFrameSize; int fSpeexFrameSize;
float * fSpeexBuffer; float * fSpeexBuffer;
int fSpeexBytesRemaining;
bigtime_t fStartTime; bigtime_t fStartTime;
int fFrameSize; int fFrameSize;