void CASpeexDecoder::InitializeCompressionSettings() { if (mCookie == NULL) return; if (mCompressionInitialized) { memset(&mSpeexHeader, 0, sizeof(mSpeexHeader)); mSpeexStereoState.balance = 1.0; mSpeexStereoState.e_ratio = 0.5; mSpeexStereoState.smooth_left = 1.0; mSpeexStereoState.smooth_right = 1.0; if (mSpeexDecoderState != NULL) { speex_decoder_destroy(mSpeexDecoderState); mSpeexDecoderState = NULL; } } mCompressionInitialized = false; OggSerialNoAtom *atom = reinterpret_cast<OggSerialNoAtom*> (mCookie); Byte *ptrheader = mCookie + EndianU32_BtoN(atom->size); CookieAtomHeader *aheader = reinterpret_cast<CookieAtomHeader*> (ptrheader); // scan quickly through the cookie, check types and packet sizes if (EndianS32_BtoN(atom->type) != kCookieTypeOggSerialNo || static_cast<UInt32> (ptrheader - mCookie) > mCookieSize) return; ptrheader += EndianU32_BtoN(aheader->size); if (EndianS32_BtoN(aheader->type) != kCookieTypeSpeexHeader || static_cast<UInt32> (ptrheader - mCookie) > mCookieSize) return; // we ignore the rest: comments and extra headers // all OK, back to the first speex packet aheader = reinterpret_cast<CookieAtomHeader*> (mCookie + EndianU32_BtoN(atom->size)); SpeexHeader *inheader = reinterpret_cast<SpeexHeader *> (&aheader->data[0]); // TODO: convert, at some point, mSpeexHeader to a pointer? mSpeexHeader.bitrate = EndianS32_LtoN(inheader->bitrate); mSpeexHeader.extra_headers = EndianS32_LtoN(inheader->extra_headers); mSpeexHeader.frame_size = EndianS32_LtoN(inheader->frame_size); mSpeexHeader.frames_per_packet = EndianS32_LtoN(inheader->frames_per_packet); mSpeexHeader.header_size = EndianS32_LtoN(inheader->header_size); mSpeexHeader.mode = EndianS32_LtoN(inheader->mode); mSpeexHeader.mode_bitstream_version = EndianS32_LtoN(inheader->mode_bitstream_version); mSpeexHeader.nb_channels = EndianS32_LtoN(inheader->nb_channels); mSpeexHeader.rate = EndianS32_LtoN(inheader->rate); mSpeexHeader.reserved1 = EndianS32_LtoN(inheader->reserved1); mSpeexHeader.reserved2 = EndianS32_LtoN(inheader->reserved2); mSpeexHeader.speex_version_id = EndianS32_LtoN(inheader->speex_version_id); mSpeexHeader.vbr = EndianS32_LtoN(inheader->vbr); if (mSpeexHeader.mode >= SPEEX_NB_MODES) CODEC_THROW(kAudioCodecUnsupportedFormatError); //TODO: check bitstream version here mSpeexDecoderState = speex_decoder_init(speex_lib_get_mode(mSpeexHeader.mode)); if (!mSpeexDecoderState) CODEC_THROW(kAudioCodecUnsupportedFormatError); //TODO: fix some of the header fields here int enhzero = 0; speex_decoder_ctl(mSpeexDecoderState, SPEEX_SET_ENH, &enhzero); if (mSpeexHeader.nb_channels == 2) { SpeexCallback callback; callback.callback_id = SPEEX_INBAND_STEREO; callback.func = speex_std_stereo_request_handler; callback.data = &mSpeexStereoState; speex_decoder_ctl(mSpeexDecoderState, SPEEX_SET_HANDLER, &callback); } mCompressionInitialized = true; }
int process_first_packet__speex(StreamInfo *si, ogg_page *op, ogg_packet *opckt) { unsigned long serialnoatom[3] = { EndianU32_NtoB(sizeof(serialnoatom)), EndianU32_NtoB(kCookieTypeOggSerialNo), EndianS32_NtoB(ogg_page_serialno(op)) }; unsigned long atomhead[2] = { EndianU32_NtoB(opckt->bytes + sizeof(atomhead)), EndianU32_NtoB(kCookieTypeSpeexHeader) }; SpeexHeader *inheader = (SpeexHeader *) opckt->packet; si->si_speex.header.bitrate = EndianS32_LtoN(inheader->bitrate); si->si_speex.header.extra_headers = EndianS32_LtoN(inheader->extra_headers); si->si_speex.header.frame_size = EndianS32_LtoN(inheader->frame_size); si->si_speex.header.frames_per_packet = EndianS32_LtoN(inheader->frames_per_packet); si->si_speex.header.header_size = EndianS32_LtoN(inheader->header_size); si->si_speex.header.mode = EndianS32_LtoN(inheader->mode); si->si_speex.header.mode_bitstream_version = EndianS32_LtoN(inheader->mode_bitstream_version); si->si_speex.header.nb_channels = EndianS32_LtoN(inheader->nb_channels); si->si_speex.header.rate = EndianS32_LtoN(inheader->rate); si->si_speex.header.reserved1 = EndianS32_LtoN(inheader->reserved1); si->si_speex.header.reserved2 = EndianS32_LtoN(inheader->reserved2); si->si_speex.header.speex_version_id = EndianS32_LtoN(inheader->speex_version_id); si->si_speex.header.vbr = EndianS32_LtoN(inheader->vbr); //si->si_speex.header. = EndianS32_LtoN(inheader->); dbg_printf("! -- - speex_first_packet: ch: %d, rate: %ld\n", si->si_speex.header.nb_channels, si->si_speex.header.rate); si->numChannels = si->si_speex.header.nb_channels; si->rate = si->si_speex.header.rate; //si->lastMediaInserted = 0; si->mediaLength = 0; PtrAndHand(serialnoatom, si->soundDescExtension, sizeof(serialnoatom)); //check errors? PtrAndHand(atomhead, si->soundDescExtension, sizeof(atomhead)); //check errors? PtrAndHand(opckt->packet, si->soundDescExtension, opckt->bytes); //check errors? si->si_speex.state = kSStateReadingComments; return 0; };