wav.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: wav.c 543 2006-01-07 22:06:24Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../common/common.h"
  24. #include "wav.h"
  25. typedef struct wav_t
  26. {
  27. format_base Format;
  28. filepos_t FileSize;
  29. filepos_t DataPos;
  30. filepos_t DataEnd;
  31. int Samples;
  32. } wav;
  33. #define ALIGN2(x) (((x)+1)&~1)
  34. static int Init(wav* p)
  35. {
  36. p->DataPos = -1;
  37. p->DataEnd = -1;
  38. p->FileSize = 0;
  39. p->Samples = -1;
  40. return ERR_NONE;
  41. }
  42. static NOINLINE void BeginData(wav* p,format_reader* Reader,int Length)
  43. {
  44. p->DataPos = Reader->FilePos;
  45. p->DataEnd = Length + Reader->FilePos;
  46. p->Format.HeaderLoaded = 1;
  47. if (p->Format.StreamCount)
  48. {
  49. tick_t Duration = 0;
  50. format_stream* Stream = p->Format.Streams[0];
  51. if (p->Samples >= 0)
  52. Duration = Scale(p->Samples,TICKSPERSEC,Stream->Format.Format.Audio.SampleRate);
  53. else
  54. if (Stream->Format.ByteRate)
  55. Duration = Scale(Length,TICKSPERSEC,Stream->Format.ByteRate);
  56. if (Duration>0 && p->Format.Duration<Duration)
  57. p->Format.Duration = Duration;
  58. }
  59. }
  60. static NOINLINE int Comment(wav* p,format_reader* Reader,int Id,int Len)
  61. {
  62. char s8[256];
  63. tchar_t s[256];
  64. if (p->Format.Comment.Node)
  65. {
  66. Len = Reader->Read(Reader,s8,min(Len,sizeof(s8)-1));
  67. if (Len>0)
  68. {
  69. s8[Len] = 0;
  70. tcscpy_s(s,TSIZEOF(s),PlayerComment(Id));
  71. tcscat_s(s,TSIZEOF(s),T("="));
  72. StrToTcs(s+tcslen(s),TSIZEOF(s)-tcslen(s),s8);
  73. p->Format.Comment.Node->Set(p->Format.Comment.Node,p->Format.Comment.No,s,(tcslen(s)+1)*sizeof(tchar_t));
  74. }
  75. else
  76. Len=0;
  77. }
  78. else
  79. Len = 0;
  80. return Len;
  81. }
  82. static int ReadExtendedBE(format_reader* Reader)
  83. {
  84. int exp = 0x403E - Reader->ReadBE16(Reader);
  85. uint64_t v = Reader->ReadBE64(Reader);
  86. return (int)(v>>exp);
  87. }
  88. static int ReadPacket(wav* p, format_reader* Reader, format_packet* Packet)
  89. {
  90. format_stream* Stream;
  91. int Type,Length,DataLength,Offset;
  92. if (p->DataPos < 0 || Reader->FilePos < p->DataPos)
  93. {
  94. if (p->Format.Format.Class == WAV_ID)
  95. {
  96. Type = Reader->ReadLE32(Reader);
  97. DataLength = Reader->ReadLE32(Reader);
  98. Length = ALIGN2(DataLength);
  99. switch (Type)
  100. {
  101. case FOURCCLE('R','M','P','3'):
  102. case FOURCCLE('R','I','F','F'):
  103. case FOURCCLE('S','D','S','S'):
  104. p->FileSize = Length + 8;
  105. Reader->ReadLE32(Reader); // 'WAVE'
  106. return ERR_NONE;
  107. case FOURCCLE('f','m','t',' '):
  108. Stream = Format_AddStream(&p->Format,sizeof(format_stream));
  109. if (Stream)
  110. {
  111. Format_WaveFormat(Reader,Stream,Length);
  112. Stream->Fragmented = 0;
  113. Format_PrepairStream(&p->Format,Stream);
  114. }
  115. else
  116. Reader->Skip(Reader,Length);
  117. return ERR_NONE;
  118. case FOURCCLE('f','a','c','t'):
  119. p->Samples = Reader->ReadLE32(Reader);
  120. Length -= 4;
  121. break;
  122. case FOURCCLE('d','a','t','a'):
  123. BeginData(p,Reader,DataLength);
  124. return ERR_NONE;
  125. }
  126. }
  127. else
  128. {
  129. Type = Reader->ReadLE32(Reader);
  130. DataLength = Reader->ReadBE32(Reader);
  131. Length = ALIGN2(DataLength);
  132. switch (Type)
  133. {
  134. case FOURCCLE('F','O','R','M'):
  135. p->FileSize = Length + 8;
  136. Reader->ReadLE32(Reader); // 'AIFF' or 'AIFC'
  137. return ERR_NONE;
  138. case FOURCCLE('C','O','M','M'):
  139. Stream = Format_AddStream(&p->Format,sizeof(format_stream));
  140. if (Stream)
  141. {
  142. PacketFormatClear(&Stream->Format);
  143. Stream->Format.Type = PACKET_AUDIO;
  144. Stream->Format.Format.Audio.Format = AUDIOFMT_PCM;
  145. #ifndef IS_BIG_ENDIAN
  146. Stream->Format.Format.Audio.Flags = PCM_SWAPEDBYTES;
  147. #endif
  148. Stream->Format.Format.Audio.Channels = Reader->ReadBE16(Reader);
  149. p->Samples = Reader->ReadBE32(Reader);
  150. Stream->Format.Format.Audio.Bits = (Reader->ReadBE16(Reader)+7) & ~7;
  151. Stream->Format.Format.Audio.SampleRate = ReadExtendedBE(Reader);
  152. Length -= 2+4+2+10;
  153. if (Length>=4)
  154. {
  155. //compression
  156. uint32_t Type = Reader->ReadLE32(Reader);
  157. Length -= 4;
  158. switch (Type)
  159. {
  160. case FOURCCLE('i','m','a','4'):
  161. Stream->Format.Format.Audio.Format = AUDIOFMT_ADPCM_IMA;
  162. break;
  163. case FOURCCLE('u','l','a','w'):
  164. Stream->Format.Format.Audio.Format = AUDIOFMT_MULAW;
  165. break;
  166. case FOURCCLE('a','l','a','w'):
  167. Stream->Format.Format.Audio.Format = AUDIOFMT_ALAW;
  168. break;
  169. }
  170. }
  171. PacketFormatDefault(&Stream->Format);
  172. Stream->Format.Format.Audio.Flags &= ~PCM_UNSIGNED;
  173. Stream->Fragmented = 0;
  174. Format_PrepairStream(&p->Format,Stream);
  175. }
  176. break;
  177. case FOURCCLE('N','A','M','E'):
  178. Length -= Comment(p,Reader,COMMENT_TITLE,DataLength);
  179. break;
  180. case FOURCCLE('(','c',')',' '):
  181. Length -= Comment(p,Reader,COMMENT_COPYRIGHT,DataLength);
  182. break;
  183. case FOURCCLE('A','U','T','H'):
  184. Length -= Comment(p,Reader,COMMENT_AUTHOR,DataLength);
  185. break;
  186. case FOURCCLE('S','S','N','D'):
  187. Offset = Reader->ReadBE32(Reader);
  188. Reader->ReadBE32(Reader); //blocksize
  189. Reader->Skip(Reader,Offset);
  190. BeginData(p,Reader,DataLength-8-Offset);
  191. return ERR_NONE;
  192. }
  193. }
  194. if (Reader->FilePos + Length < p->FileSize)
  195. Reader->Skip(Reader,Length);
  196. }
  197. else
  198. {
  199. if (Reader->FilePos >= p->DataEnd)
  200. return ERR_END_OF_FILE;
  201. if (p->Format.StreamCount)
  202. {
  203. int Length;
  204. Stream = p->Format.Streams[0];
  205. if (Reader->FilePos == p->DataPos)
  206. Packet->RefTime = 0;
  207. else
  208. if (Stream->Format.ByteRate)
  209. Packet->RefTime = Scale(Reader->FilePos - p->DataPos,TICKSPERSEC,Stream->Format.ByteRate);
  210. else
  211. Packet->RefTime = TIME_UNKNOWN;
  212. Length = p->DataEnd - Reader->FilePos;
  213. if (Length > 4096) Length = 4096;
  214. Packet->Data = Reader->ReadAsRef(Reader,-Length);
  215. Packet->Stream = Stream;
  216. }
  217. }
  218. return ERR_NONE;
  219. }
  220. static int Seek(wav* p, tick_t Time, filepos_t FilePos,bool_t PrevKey)
  221. {
  222. format_stream* Stream;
  223. if (p->DataPos < 0 || !p->Format.StreamCount)
  224. {
  225. // no avi header yet, only seek to the beginning supported
  226. if (Time > 0 || FilePos > 0)
  227. return ERR_NOT_SUPPORTED;
  228. return Format_Seek(&p->Format,0,SEEK_SET);
  229. }
  230. Stream = p->Format.Streams[0];
  231. if (FilePos < 0)
  232. {
  233. if (Time > 0 && !Stream->Format.ByteRate)
  234. return ERR_NOT_SUPPORTED;
  235. FilePos = Scale(Time,Stream->Format.ByteRate,TICKSPERSEC);
  236. }
  237. if (Stream->Format.Format.Audio.BlockAlign > 1)
  238. FilePos = (FilePos / Stream->Format.Format.Audio.BlockAlign) * Stream->Format.Format.Audio.BlockAlign;
  239. if (FilePos<0) FilePos=0;
  240. if (FilePos>p->DataEnd-p->DataPos) FilePos=p->DataEnd-p->DataPos;
  241. return Format_Seek(&p->Format,p->DataPos+FilePos,SEEK_SET);
  242. }
  243. static int Create(wav* p)
  244. {
  245. p->Format.Init = (fmtfunc)Init;
  246. p->Format.Seek = (fmtseek)Seek;
  247. p->Format.ReadPacket = (fmtreadpacket)ReadPacket;
  248. return ERR_NONE;
  249. }
  250. static const nodedef WAV = 
  251. {
  252. sizeof(wav),
  253. WAV_ID,
  254. FORMATBASE_CLASS,
  255. PRI_DEFAULT-5,
  256. (nodecreate)Create,
  257. NULL,
  258. };
  259. static const nodedef AIFF = 
  260. {
  261. 0,
  262. AIFF_ID,
  263. WAV_ID,
  264. PRI_DEFAULT-5,
  265. };
  266. void WAV_Init()
  267. {
  268.  NodeRegisterClass(&WAV);
  269.  NodeRegisterClass(&AIFF);
  270. }
  271. void WAV_Done()
  272. {
  273. NodeUnRegisterClass(AIFF_ID);
  274. NodeUnRegisterClass(WAV_ID);
  275. }