speexcodec.c
资源名称:tcpmp.rar [点击查看]
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:6k
源码类别:
Windows CE
开发平台:
C/C++
- /*****************************************************************************
- *
- * This program is free software ; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: speexcodec.c 620 2006-01-31 14:46:34Z picard $
- *
- * The Core Pocket Media Player
- * Copyright (c) 2004-2005 Gabor Kovacs
- *
- ****************************************************************************/
- #include "../common/common.h"
- #include "speex.h"
- #include <speex/speex_header.h>
- #include <speex/speex_stereo.h>
- #include <speex/speex_callbacks.h>
- #define MAX_FRAME_SIZE 2000
- typedef struct speex
- {
- codec Codec;
- int ExtraHeaders;
- int AfterFlush;
- int FrameSize;
- int Frames;
- int FramesPerPacket;
- void *Decoder;
- SpeexBits Bits;
- SpeexStereoState Stereo;
- spx_int16_t Output[MAX_FRAME_SIZE];
- } speex;
- static int UpdateInput(speex* p)
- {
- if (p->Decoder)
- {
- speex_decoder_destroy(p->Decoder);
- speex_bits_destroy(&p->Bits);
- p->Decoder = NULL;
- }
- if (p->Codec.In.Format.Type == PACKET_AUDIO)
- {
- int Enabled = 1;
- const SpeexMode *Mode;
- SpeexHeader *Header;
- SpeexCallback Callback;
- if (p->Codec.In.Format.ExtraLength < 8)
- {
- if (p->Codec.In.Format.Format.Audio.SampleRate > 25000)
- Mode = &speex_uwb_mode; // ideal 32000hz
- else if (p->Codec.In.Format.Format.Audio.SampleRate > 12500)
- Mode = &speex_wb_mode; // ideal 16000hz
- else
- Mode = &speex_nb_mode; // ideal 8000hz
- Header = malloc(sizeof(SpeexHeader));
- if (Header)
- speex_init_header(Header, p->Codec.In.Format.Format.Audio.SampleRate, p->Codec.In.Format.Format.Audio.Channels, Mode);
- }
- else
- Header = speex_packet_to_header(p->Codec.In.Format.Extra,p->Codec.In.Format.ExtraLength);
- if (!Header || Header->mode >= SPEEX_NB_MODES || Header->speex_version_id > 1)
- {
- free(Header);
- return ERR_NOT_SUPPORTED;
- }
- Mode = speex_lib_get_mode(Header->mode);
- if (Mode->bitstream_version != Header->mode_bitstream_version)
- {
- free(Header);
- return ERR_NOT_SUPPORTED;
- }
- p->Decoder = speex_decoder_init(Mode);
- if (!p->Decoder)
- {
- free(Header);
- return ERR_OUT_OF_MEMORY;
- }
- p->FramesPerPacket = max(1,Header->frames_per_packet);
- p->ExtraHeaders = Header->extra_headers;
- speex_decoder_ctl(p->Decoder, SPEEX_SET_ENH, &Enabled);
- speex_decoder_ctl(p->Decoder, SPEEX_GET_FRAME_SIZE, &p->FrameSize);
- #ifdef NO_FLOATINGPOINT
- Header->nb_channels = 1; //force mono. stereo would need floating point calculations
- #endif
- p->Codec.In.Format.Format.Audio.SampleRate = Header->rate;
- p->Codec.In.Format.Format.Audio.Channels = Header->nb_channels;
- if (Header->nb_channels != 1)
- {
- Callback.callback_id = SPEEX_INBAND_STEREO;
- Callback.func = speex_std_stereo_request_handler;
- Callback.data = &p->Stereo;
- speex_decoder_ctl(p->Decoder, SPEEX_SET_HANDLER, &Callback);
- }
- speex_decoder_ctl(p->Decoder, SPEEX_SET_SAMPLING_RATE, &Header->rate);
- speex_bits_init(&p->Bits);
- PacketFormatPCM(&p->Codec.Out.Format,&p->Codec.In.Format,15);
- free(Header);
- }
- return ERR_NONE;
- }
- static int Process(speex* p, const packet* Packet, const flowstate* State)
- {
- int Result;
- if (Packet)
- {
- if (Packet->RefTime >= 0)
- {
- if (Packet->RefTime == 0)
- p->AfterFlush = 0;
- p->Codec.Packet.RefTime = Packet->RefTime;
- }
- if (p->ExtraHeaders>0)
- {
- --p->ExtraHeaders;
- return ERR_NEED_MORE_DATA;
- }
- speex_bits_read_from(&p->Bits, (char*)Packet->Data[0], Packet->Length);
- p->Frames = p->FramesPerPacket;
- }
- else
- p->Codec.Packet.RefTime = TIME_UNKNOWN;
- if (p->Frames<=0)
- return ERR_NEED_MORE_DATA;
- Result = speex_decode_int(p->Decoder, &p->Bits, p->Output);
- if (Result==-1)
- {
- p->Frames = 0;
- return ERR_NEED_MORE_DATA;
- }
- if (Result==-2 || speex_bits_remaining(&p->Bits)<0)
- {
- p->Frames = 0;
- return ERR_INVALID_DATA;
- }
- if (p->Codec.In.Format.Format.Audio.Channels==2)
- speex_decode_stereo_int(p->Output, p->FrameSize, &p->Stereo);
- p->Codec.Packet.Length = p->FrameSize * p->Codec.In.Format.Format.Audio.Channels * sizeof(int16_t);
- p->Codec.Packet.Data[0] = p->Output;
- --p->Frames;
- if (p->AfterFlush)
- {
- // don't output this frame
- --p->AfterFlush;
- return Process(p,NULL,State);
- }
- return ERR_NONE;
- }
- static int Flush(speex* p)
- {
- p->AfterFlush = 4;
- p->Frames = 0;
- return ERR_NONE;
- }
- static int Create(speex* p)
- {
- p->Codec.Process = (packetprocess)Process;
- p->Codec.UpdateInput = (nodefunc)UpdateInput;
- p->Codec.Flush = (nodefunc)Flush;
- return ERR_NONE;
- }
- static const nodedef Speex =
- {
- sizeof(speex),
- SPEEX_ID,
- CODEC_CLASS,
- PRI_DEFAULT,
- (nodecreate)Create,
- NULL,
- };
- static const nodedef SPX_HQ =
- {
- 0, // parent size
- SPX_HQ_ID,
- FOURCC('O','G','H','V'),
- PRI_DEFAULT,
- NULL,
- };
- static const nodedef SPX_LQ =
- {
- 0, // parent size
- SPX_LQ_ID,
- FOURCC('O','G','G','V'),
- PRI_DEFAULT,
- NULL,
- };
- void Speex_Init()
- {
- NodeRegisterClass(&Speex);
- NodeRegisterClass(&SPX_LQ);
- NodeRegisterClass(&SPX_HQ);
- }
- void Speex_Done()
- {
- NodeUnRegisterClass(SPEEX_ID);
- NodeUnRegisterClass(SPX_LQ_ID);
- NodeUnRegisterClass(SPX_HQ_ID);
- }