speexcodec.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:6k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*****************************************************************************
  2.  *
  3.  * This program is free software ; you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation; either version 2 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  16.  *
  17.  * $Id: speexcodec.c 620 2006-01-31 14:46:34Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../common/common.h"
  24. #include "speex.h"
  25. #include <speex/speex_header.h>
  26. #include <speex/speex_stereo.h>
  27. #include <speex/speex_callbacks.h>
  28. #define MAX_FRAME_SIZE 2000
  29. typedef struct speex
  30. {
  31. codec Codec;
  32. int ExtraHeaders;
  33. int AfterFlush;
  34. int FrameSize;
  35. int Frames;
  36. int FramesPerPacket;
  37. void *Decoder;
  38. SpeexBits Bits;
  39. SpeexStereoState Stereo;
  40. spx_int16_t Output[MAX_FRAME_SIZE];
  41. } speex;
  42. static int UpdateInput(speex* p)
  43. {
  44. if (p->Decoder)
  45. {
  46. speex_decoder_destroy(p->Decoder);
  47. speex_bits_destroy(&p->Bits);
  48. p->Decoder = NULL;
  49. }
  50. if (p->Codec.In.Format.Type == PACKET_AUDIO)
  51. {
  52. int Enabled = 1;
  53. const SpeexMode *Mode;
  54. SpeexHeader *Header;
  55. SpeexCallback Callback;
  56. if (p->Codec.In.Format.ExtraLength < 8)
  57. {
  58. if (p->Codec.In.Format.Format.Audio.SampleRate > 25000)
  59. Mode = &speex_uwb_mode; // ideal 32000hz
  60. else if (p->Codec.In.Format.Format.Audio.SampleRate > 12500)
  61. Mode = &speex_wb_mode; // ideal 16000hz
  62. else 
  63. Mode = &speex_nb_mode; // ideal 8000hz
  64. Header = malloc(sizeof(SpeexHeader));
  65. if (Header)
  66. speex_init_header(Header, p->Codec.In.Format.Format.Audio.SampleRate, p->Codec.In.Format.Format.Audio.Channels, Mode);
  67. }
  68. else
  69. Header = speex_packet_to_header(p->Codec.In.Format.Extra,p->Codec.In.Format.ExtraLength);
  70. if (!Header || Header->mode >= SPEEX_NB_MODES || Header->speex_version_id > 1)
  71. {
  72. free(Header);
  73. return ERR_NOT_SUPPORTED;
  74. }
  75. Mode = speex_lib_get_mode(Header->mode);
  76. if (Mode->bitstream_version != Header->mode_bitstream_version)
  77. {
  78. free(Header);
  79. return ERR_NOT_SUPPORTED;
  80. }
  81. p->Decoder = speex_decoder_init(Mode);
  82. if (!p->Decoder)
  83. {
  84. free(Header);
  85. return ERR_OUT_OF_MEMORY;
  86. }
  87. p->FramesPerPacket = max(1,Header->frames_per_packet);
  88. p->ExtraHeaders = Header->extra_headers;
  89. speex_decoder_ctl(p->Decoder, SPEEX_SET_ENH, &Enabled);
  90. speex_decoder_ctl(p->Decoder, SPEEX_GET_FRAME_SIZE, &p->FrameSize);
  91. #ifdef NO_FLOATINGPOINT
  92. Header->nb_channels = 1; //force mono. stereo would need floating point calculations
  93. #endif
  94. p->Codec.In.Format.Format.Audio.SampleRate = Header->rate;
  95. p->Codec.In.Format.Format.Audio.Channels = Header->nb_channels;
  96. if (Header->nb_channels != 1)
  97. {
  98. Callback.callback_id = SPEEX_INBAND_STEREO;
  99. Callback.func = speex_std_stereo_request_handler;
  100. Callback.data = &p->Stereo;
  101. speex_decoder_ctl(p->Decoder, SPEEX_SET_HANDLER, &Callback);
  102. }
  103. speex_decoder_ctl(p->Decoder, SPEEX_SET_SAMPLING_RATE, &Header->rate);
  104. speex_bits_init(&p->Bits);
  105. PacketFormatPCM(&p->Codec.Out.Format,&p->Codec.In.Format,15);
  106. free(Header);
  107. }
  108. return ERR_NONE;
  109. }
  110. static int Process(speex* p, const packet* Packet, const flowstate* State)
  111. {
  112. int Result;
  113. if (Packet)
  114. {
  115. if (Packet->RefTime >= 0)
  116. {
  117. if (Packet->RefTime == 0)
  118. p->AfterFlush = 0;
  119. p->Codec.Packet.RefTime = Packet->RefTime;
  120. }
  121. if (p->ExtraHeaders>0)
  122. {
  123. --p->ExtraHeaders;
  124. return ERR_NEED_MORE_DATA;
  125. }
  126. speex_bits_read_from(&p->Bits, (char*)Packet->Data[0], Packet->Length);
  127. p->Frames = p->FramesPerPacket;
  128. }
  129. else
  130. p->Codec.Packet.RefTime = TIME_UNKNOWN;
  131. if (p->Frames<=0)
  132. return ERR_NEED_MORE_DATA;
  133.     Result = speex_decode_int(p->Decoder, &p->Bits, p->Output);
  134. if (Result==-1)
  135. {
  136. p->Frames = 0;
  137. return ERR_NEED_MORE_DATA;
  138. }
  139. if (Result==-2 || speex_bits_remaining(&p->Bits)<0)
  140. {
  141. p->Frames = 0;
  142. return ERR_INVALID_DATA;
  143. }
  144. if (p->Codec.In.Format.Format.Audio.Channels==2)
  145. speex_decode_stereo_int(p->Output, p->FrameSize, &p->Stereo);
  146. p->Codec.Packet.Length = p->FrameSize * p->Codec.In.Format.Format.Audio.Channels * sizeof(int16_t);
  147. p->Codec.Packet.Data[0] = p->Output;
  148. --p->Frames;
  149. if (p->AfterFlush)
  150. {
  151. // don't output this frame
  152. --p->AfterFlush;
  153. return Process(p,NULL,State);
  154. }
  155. return ERR_NONE;
  156. }
  157. static int Flush(speex* p)
  158. {
  159. p->AfterFlush = 4;
  160. p->Frames = 0;
  161. return ERR_NONE;
  162. }
  163. static int Create(speex* p)
  164. {
  165. p->Codec.Process = (packetprocess)Process;
  166. p->Codec.UpdateInput = (nodefunc)UpdateInput;
  167. p->Codec.Flush = (nodefunc)Flush;
  168. return ERR_NONE;
  169. }
  170. static const nodedef Speex =
  171. {
  172. sizeof(speex),
  173. SPEEX_ID,
  174. CODEC_CLASS,
  175. PRI_DEFAULT,
  176. (nodecreate)Create,
  177. NULL,
  178. };
  179. static const nodedef SPX_HQ = 
  180. {
  181. 0, // parent size
  182. SPX_HQ_ID,
  183. FOURCC('O','G','H','V'),
  184. PRI_DEFAULT,
  185. NULL,
  186. };
  187. static const nodedef SPX_LQ = 
  188. {
  189. 0, // parent size
  190. SPX_LQ_ID,
  191. FOURCC('O','G','G','V'),
  192. PRI_DEFAULT,
  193. NULL,
  194. };
  195. void Speex_Init()
  196. {
  197. NodeRegisterClass(&Speex);
  198. NodeRegisterClass(&SPX_LQ);
  199. NodeRegisterClass(&SPX_HQ);
  200. }
  201. void Speex_Done()
  202. {
  203. NodeUnRegisterClass(SPEEX_ID);
  204. NodeUnRegisterClass(SPX_LQ_ID);
  205. NodeUnRegisterClass(SPX_HQ_ID);
  206. }