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

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: waveout.c 548 2006-01-08 22:41:57Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "common.h"
  24. void VolumeMul(int Vol,void* Dst,int DstLength,const audio* Format)
  25. {
  26. uint8_t *u8,*u8e;
  27. int16_t *s16,*s16e;
  28. switch (Format->Bits)
  29. {
  30. case 8:
  31. u8=Dst;
  32. u8e=u8+DstLength;
  33. for (;u8!=u8e;++u8)
  34. {
  35. int i = (((*u8 - 0x80) * Vol) >> 8) + 0x80;
  36. *u8 = (uint8_t)(i>255?255:(i<0?0:i));
  37. }
  38. break;
  39. case 16:
  40. s16=Dst;
  41. s16e=s16+(DstLength>>1);
  42. for (;s16!=s16e;++s16)
  43. {
  44. int i = (*s16 * Vol) >> 8;
  45. *s16 = (int16_t)(i>32767?32767:(i<-32768?-32768:i));
  46. }
  47. break;
  48. }
  49. }
  50. int VolumeRamp(int Ramp,void* Dst,int DstLength,const audio* Format)
  51. {
  52. uint8_t *u8,*u8e;
  53. int16_t *s16,*s16e;
  54. int Inc = (10*(1<<RAMPSIZE)) / (Format->Channels * Format->SampleRate);
  55. if (Inc<=0) Inc=1;
  56. switch (Format->Bits)
  57. {
  58. case 8:
  59. u8=Dst;
  60. u8e=u8+DstLength;
  61. for (;u8!=u8e && Ramp<RAMPLIMIT;++u8,Ramp+=Inc)
  62. *u8 = (uint8_t)((((*u8 - 0x80) * Ramp) >> RAMPSIZE) + 0x80);
  63. break;
  64. case 16:
  65. s16=Dst;
  66. s16e=s16+(DstLength>>1);
  67. for (;s16!=s16e && Ramp<RAMPLIMIT;++s16,Ramp+=Inc)
  68. *s16 = (int16_t)((*s16 * Ramp) >> RAMPSIZE);
  69. break;
  70. default:
  71. Ramp = RAMPLIMIT;
  72. break;
  73. }
  74. return Ramp;
  75. }
  76. static void AlignRate(int* Rate,int Target)
  77. {
  78. if (*Rate > Target-16 && *Rate < Target+16)
  79. *Rate = Target;
  80. }
  81. static int UpdateInput(waveout_base* p)
  82. {
  83. if (p->Done)
  84. p->Done(p);
  85. p->Total = 0;
  86. p->Dropped = 0;
  87. if (p->Input.Type == PACKET_AUDIO)
  88. {
  89. int Result = ERR_NONE;
  90. int Try;
  91. if (p->Input.Format.Audio.Format != AUDIOFMT_PCM) 
  92. {
  93. PacketFormatClear(&p->Input);
  94. return ERR_INVALID_DATA;
  95. }
  96. if (p->Input.Format.Audio.Channels == 0 ||
  97. p->Input.Format.Audio.SampleRate == 0)
  98. return ERR_NONE;
  99. AlignRate(&p->Input.Format.Audio.SampleRate,8000);
  100. AlignRate(&p->Input.Format.Audio.SampleRate,11025);
  101. AlignRate(&p->Input.Format.Audio.SampleRate,16000);
  102. AlignRate(&p->Input.Format.Audio.SampleRate,22050);
  103. AlignRate(&p->Input.Format.Audio.SampleRate,44100);
  104. PacketFormatClear(&p->Output);
  105. p->Output.Type = PACKET_AUDIO;
  106. p->Output.Format.Audio = p->Input.Format.Audio;
  107. p->Output.Format.Audio.Flags = 0;
  108. p->Dither = 0;
  109. if (p->Stereo==STEREO_SWAPPED)
  110. p->Output.Format.Audio.Flags |= PCM_SWAPPEDSTEREO;
  111. else
  112. if (p->Stereo!=STEREO_NORMAL)
  113. {
  114. p->Output.Format.Audio.Channels = 1;
  115. if (p->Stereo==STEREO_LEFT)
  116. p->Output.Format.Audio.Flags |= PCM_ONLY_LEFT;
  117. if (p->Stereo==STEREO_RIGHT)
  118. p->Output.Format.Audio.Flags |= PCM_ONLY_RIGHT;
  119. }
  120. switch (p->Quality)
  121. {
  122. case 0: // low quality for very poor devices
  123. p->Output.Format.Audio.Bits = 8;
  124. p->Output.Format.Audio.FracBits = 7;
  125. p->Output.Format.Audio.Channels = 1;
  126. p->Output.Format.Audio.SampleRate = 22050;
  127. break;
  128. case 1: // no dither and only standard samplerate
  129. if (p->Output.Format.Audio.Bits > 8)
  130. {
  131. p->Output.Format.Audio.Bits = 16;
  132. p->Output.Format.Audio.FracBits = 15;
  133. }
  134. else
  135. {
  136. p->Output.Format.Audio.Bits = 8;
  137. p->Output.Format.Audio.FracBits = 7;
  138. }
  139. if (p->Output.Format.Audio.SampleRate >= 44100)
  140. p->Output.Format.Audio.SampleRate = 44100;
  141. else
  142. p->Output.Format.Audio.SampleRate = 22050;
  143. break;
  144. default:
  145. case 2: // original samplerate 
  146. if (p->Output.Format.Audio.Bits > 8)
  147. {
  148. p->Output.Format.Audio.Bits = 16;
  149. p->Output.Format.Audio.FracBits = 15;
  150. }
  151. else
  152. {
  153. p->Output.Format.Audio.Bits = 8;
  154. p->Output.Format.Audio.FracBits = 7;
  155. }
  156. p->Dither = 1;
  157. break;
  158. }
  159. for (Try=0;;++Try)
  160. {
  161. if (p->Output.Format.Audio.Bits <= 8)
  162. p->Output.Format.Audio.Flags |= PCM_UNSIGNED;
  163. Result = p->Init(p);
  164. if (Result == ERR_NONE)
  165. break;
  166. if (p->Done)
  167. p->Done(p);
  168. if (Try==0)
  169. {
  170. if (p->Output.Format.Audio.SampleRate > 36000)
  171. p->Output.Format.Audio.SampleRate = 44100;
  172. else
  173. ++Try;
  174. }
  175. if (Try==1)
  176. {
  177. if (p->Output.Format.Audio.SampleRate != 22050)
  178. p->Output.Format.Audio.SampleRate = 22050;
  179. else
  180. ++Try;
  181. }
  182. #ifdef TARGET_SYMBIAN
  183. if (Try==2)
  184. {
  185. if (p->Output.Format.Audio.SampleRate != 16000)
  186. p->Output.Format.Audio.SampleRate = 16000;
  187. else
  188. ++Try;
  189. }
  190. if (Try==3)
  191. {
  192. if (p->Output.Format.Audio.SampleRate != 11025)
  193. p->Output.Format.Audio.SampleRate = 11025;
  194. else
  195. ++Try;
  196. }
  197. if (Try==4)
  198. {
  199. if (p->Output.Format.Audio.SampleRate != 8000)
  200. p->Output.Format.Audio.SampleRate = 8000;
  201. else
  202. ++Try;
  203. }
  204. if (Try==5)
  205. break;
  206. #else
  207. if (Try==2)
  208. {
  209. if (p->Output.Format.Audio.Channels > 1)
  210. p->Output.Format.Audio.Channels = 1;
  211. else
  212. ++Try;
  213. }
  214. if (Try==3)
  215. {
  216. if (p->Output.Format.Audio.Bits != 8)
  217. {
  218. p->Output.Format.Audio.Bits = 8;
  219. p->Output.Format.Audio.FracBits = 7;
  220. }
  221. else
  222. ++Try;
  223. }
  224. if (Try==4)
  225. break;
  226. #endif
  227. }
  228. if (Try==5)
  229. {
  230. PacketFormatClear(&p->Input);
  231. if (Result == ERR_DEVICE_ERROR)
  232. ShowError(p->Node.Class,ERR_ID,Result);
  233. return Result;
  234. }
  235. }
  236. else
  237. if (p->Input.Type != PACKET_NONE)
  238. return ERR_INVALID_DATA;
  239. return ERR_NONE;
  240. }
  241. int WaveOutPCM(waveout_base* p)
  242. {
  243. PCMRelease(p->PCM);
  244. p->PCM = PCMCreate(&p->Output.Format.Audio,&p->Input.Format.Audio,p->Dither,0);
  245. return p->PCM ? ERR_NONE:ERR_OUT_OF_MEMORY;
  246. }
  247. int WaveOutBaseGet(waveout_base* p, int No, void* Data, int Size)
  248. {
  249. int Result = ERR_INVALID_PARAM;
  250. switch (No)
  251. {
  252. case OUT_INPUT: GETVALUE(p->Pin,pin); break;
  253. case OUT_INPUT|PIN_FORMAT: GETVALUE(p->Input,packetformat); break;
  254. case OUT_INPUT|PIN_PROCESS: GETVALUE(p->Input.Format.Audio.Channels?p->Process:DummyProcess,packetprocess); break;
  255. case OUT_OUTPUT|PIN_FORMAT: GETVALUE(p->Output,packetformat); break;
  256. case OUT_TOTAL:GETVALUE(p->Total,int); break;
  257. case OUT_DROPPED:GETVALUE(p->Dropped,int); break;
  258. case AOUT_STEREO: GETVALUE(p->Stereo,int); break; 
  259. case AOUT_QUALITY: GETVALUE(p->Quality,int); break;
  260. case AOUT_TIMER: GETVALUE(&p->Timer,node*); break;
  261. }
  262. return Result;
  263. }
  264. int WaveOutBaseSet(waveout_base* p, int No, const void* Data, int Size)
  265. {
  266. int Result = ERR_INVALID_PARAM;
  267. switch (No)
  268. {
  269. case OUT_INPUT|PIN_FORMAT: 
  270. if (PacketFormatSimilarAudio(&p->Input,(const packetformat*)Data))
  271. {
  272. PacketFormatCopy(&p->Input,(const packetformat*)Data);
  273. return WaveOutPCM(p);
  274. }
  275. else
  276. SETPACKETFORMATCMP(p->Input,packetformat,UpdateInput(p)); 
  277. break;
  278. case OUT_INPUT: SETVALUE(p->Pin,pin,ERR_NONE); break;
  279. case OUT_TOTAL: SETVALUE(p->Total,int,ERR_NONE); break;
  280. case OUT_DROPPED: SETVALUE(p->Dropped,int,ERR_NONE); break;
  281. case AOUT_STEREO: SETVALUECMP(p->Stereo,int,UpdateInput(p),EqInt); break; 
  282. case AOUT_QUALITY: SETVALUECMP(p->Quality,int,UpdateInput(p),EqInt); break;
  283. }
  284. return Result;
  285. }