samplein.c
上传用户:bjsgzm
上传日期:2007-01-08
资源大小:256k
文件大小:14k
源码类别:

mpeg/mp3

开发平台:

Visual C++

  1. /*
  2. (c) Copyright 1998, 1999 - Tord Jansson
  3. =======================================
  4. This file is part of the BladeEnc MP3 Encoder, based on
  5. ISO's reference code for MPEG Layer 3 compression.
  6. This file doesn't contain any of the ISO reference code and
  7. is copyright Tord Jansson (tord.jansson@swipnet.se).
  8. BladeEnc is free software; you can redistribute this file
  9. and/or modify it under the terms of the GNU Lesser General Public
  10. License as published by the Free Software Foundation; either
  11. version 2.1 of the License, or (at your option) any later version.
  12. */
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include "system.h"
  16. #include "samplein.h"
  17. /* Errorcodes
  18.   -------------
  19.     0 = No Error (OK).
  20.    -1 = Unsupported filetype.
  21.    -2 = Couldn't open file.
  22.    -3 = Unexpected end of file.
  23.    -4 = (Input file is not in the format the file-extension says).
  24.    -5 = Important chunk missing.
  25.    -6 = Samples are in unsupported (compressed?) format.
  26. */
  27. #define STR_COMM 0x4d4d4f43
  28. #define STR_SSND 0x444e5353
  29. #define STR_FORM 0x4d524f46
  30. #define STR_AIFF 0x46464941
  31. #define STR_RIFF 0x46464952
  32. #define STR_WAVE 0x45564157
  33. #define STR_fmt 0x20746d66
  34. #define STR_data 0x61746164
  35. /*____ Function Prototypes ____________________________________________________*/
  36. static int initWAV( SplIn * psInfo );
  37. static uint readWAVSamples( SplIn * psInfo, int nSamples, short * wpSamples );
  38. static int initRAW( SplIn * psInfo );
  39. static uint readRAWSamples( SplIn * psInfo, int nSamples, short * wpSamples );
  40. static int initAIFF( SplIn * psInfo );
  41. static uint readAIFFSamples( SplIn * psInfo, int nSamples, short * wpSamples );
  42. static int myFseek( FILE * fp, int offset );
  43. uint INLINE intlLong( char iLong[4] );
  44. uint INLINE mcLong( char mcLong[4] );
  45. ushort INLINE intlShort( char iShort[2] );
  46. ushort INLINE mcShort( char mcShort[2] );
  47. /*____ Static Data ____________________________________________________________*/
  48. /*____ openInput() ____________________________________________________________*/
  49. int openInput( SplIn * psInfo, char * pFileName )
  50. {
  51. int x;
  52. char header[3*4];
  53. psInfo->errcode = 0;
  54. psInfo->nPreReadBytes = 0;
  55. /* Set Filepointer */
  56. if( pFileName == NULL )
  57. {
  58. psInfo->fp = stdin;
  59. }
  60. else
  61. {
  62. psInfo->fp = fopen( pFileName, "rb" );
  63. if( psInfo->fp == NULL ) goto couldNotOpen;
  64. }
  65. /* Read and analyze header */
  66. if( fread( header, 4, 3, psInfo->fp ) != 3 ) goto couldNotOpen;
  67. if( intlLong(&header[0]) == STR_RIFF && intlLong(&header[8]) == STR_WAVE )
  68. x = initWAV( psInfo );
  69. else if( intlLong(&header[0]) == STR_FORM && intlLong(&header[8]) == STR_AIFF )
  70. x = initAIFF( psInfo );
  71. else
  72. {
  73. memcpy( psInfo->preReadBuffer, header, 12 );
  74. psInfo->nPreReadBytes = 12;
  75. x = initRAW( psInfo );
  76. }
  77. if( x == FALSE )
  78. {
  79. if( psInfo->fp != stdin )
  80. fclose( psInfo->fp );
  81. psInfo->samplesLeft = 0;
  82. return FALSE;
  83. }
  84. /* Set some flags */
  85. if( psInfo->fReadStereo )
  86. psInfo->outputType = STEREO;
  87. else
  88. psInfo->outputType = DOWNMIX_MONO;
  89. psInfo->outputFreq = psInfo->freq;
  90. return TRUE;
  91. couldNotOpen:
  92. psInfo->errcode = -2;
  93. psInfo->samplesLeft = 0;
  94. return FALSE;
  95. }
  96. /*____ readSamples() __________________________________________________________*/
  97. int readSamples( SplIn * psInfo, uint nSamples, short * wpSamples )
  98. {
  99. int retVal = 0;
  100. uint i;
  101. uint readSamples;
  102. char temp;
  103. short tmp;
  104. if( psInfo->fReadStereo == TRUE && (psInfo->outputType == DOWNMIX_MONO
  105.                                     || psInfo->outputType == LEFT_CHANNEL_MONO || psInfo->outputType == RIGHT_CHANNEL_MONO) )
  106. readSamples = nSamples*2;
  107. else
  108. readSamples = nSamples;
  109. if( psInfo->samplesLeft == 0 )
  110. return 0;
  111. if( psInfo->samplesLeft != 0xFFFFFFFF )
  112. {
  113. if( readSamples < psInfo->samplesLeft )
  114. psInfo->samplesLeft -= readSamples;
  115. else
  116. {
  117. readSamples = psInfo->samplesLeft;
  118. psInfo->samplesLeft = 0;
  119. }
  120. }
  121. if( psInfo->filetype == WAV )
  122. retVal = readWAVSamples( psInfo, readSamples, wpSamples );
  123. else if( psInfo->filetype == AIFF )
  124. retVal = readAIFFSamples( psInfo, readSamples, wpSamples );
  125. else if( psInfo->filetype == RAW )
  126. retVal = readRAWSamples( psInfo, readSamples, wpSamples );
  127. if( psInfo->samplesLeft == 0 || retVal == FALSE )
  128. {
  129. psInfo->samplesLeft = 0;
  130. if( psInfo->fp != stdin )
  131. fclose( psInfo->fp );
  132. }
  133. /* Possibly swap byteorder */
  134. if( psInfo->bits == 16 && psInfo->byteorder != BYTEORDER )
  135. {
  136. for( i = 0 ; i < readSamples ; i++ )
  137. {
  138. temp = ((char *)wpSamples)[i*2];
  139. ((char *)wpSamples)[i*2] = ((char *)wpSamples)[i*2+1];
  140. ((char *)wpSamples)[i*2+1] = temp;
  141. }
  142. }
  143. /* Convert between 8/16-bit */
  144. if( psInfo->bits == 8 )
  145. {
  146. for( i = readSamples-1 ; i > 0 ; i-- )
  147. wpSamples[i] = ((short)((unsigned char *) wpSamples)[i]) << 8;
  148. wpSamples[i] = ((short)((unsigned char *) wpSamples)[i]) << 8;
  149. }
  150. /* Convert unsigned to signed */
  151. if( psInfo->fSign == FALSE )
  152. {
  153. for( i = 0 ; i < readSamples ; i++ )
  154. wpSamples[i] ^= 0x8000;
  155. }
  156. /* Convert from Stereo to Mono or inverse stereo in a number of ways */
  157. if( psInfo->outputType != STEREO && psInfo->fReadStereo == TRUE )
  158. {
  159. if( psInfo->outputType == DOWNMIX_MONO )
  160. for( i = 0 ; i < readSamples/2 ; i++ )
  161. wpSamples[i] = (short)((((int)wpSamples[i*2]) + ((int)wpSamples[i*2+1])) >> 1);
  162. if( psInfo->outputType == LEFT_CHANNEL_MONO )
  163. for( i = 0 ; i < readSamples/2 ; i++ )
  164. wpSamples[i] = wpSamples[i*2];
  165. if( psInfo->outputType == RIGHT_CHANNEL_MONO )
  166. for( i = 0 ; i < readSamples/2 ; i++ )
  167. wpSamples[i] = wpSamples[i*2+1];
  168. if( psInfo->outputType == INVERSE_STEREO )
  169. {
  170. for( i = 0 ; i < readSamples ; i += 2 )
  171. {
  172. tmp = wpSamples[i];
  173. wpSamples[i] = wpSamples[i+1];
  174. wpSamples[i+1] = tmp;
  175. }
  176. }
  177. }
  178. return retVal;
  179. }
  180. /*____ closeInput() ___________________________________________________________*/
  181. int closeInput( SplIn * psInfo )
  182. {
  183. if( psInfo->samplesLeft != 0 )
  184. {
  185. if( psInfo->fp != stdin )
  186. fclose( psInfo->fp );
  187. psInfo->samplesLeft = 0;
  188. return TRUE;
  189. }
  190. return FALSE;
  191. }
  192. /*____ initWAV() ______________________________________________________________*/
  193. static int initWAV( SplIn * psInfo )
  194. {
  195. char header[3*4];
  196. int fFmtChunkFound = FALSE;
  197. struct
  198. {
  199. short wFormatTag; /* Format category */
  200. short wChannels; /* Number of channels */
  201. int dwSamplesPerSec; /* Sampling rate */
  202. int dwAvgBytesPerSec; /* For buffer estimation */
  203. short wBlockAlign; /* Data block size */
  204. short bitsPerSample; /* Actually a PCM-specific additional byte... */
  205. } sFmtChunk;
  206. char aTemp[sizeof( sFmtChunk )];
  207. /* Go through the chunks until we have found 'data'. */
  208. if( fread( header, 4, 2, psInfo->fp ) != 2 ) goto unexpEndOfFile;
  209. while( intlLong( &header[0] ) != STR_data )
  210. {
  211. if( intlLong( &header[0] ) == STR_fmt )
  212. {
  213. if( fread( aTemp, sizeof( sFmtChunk ), 1, psInfo->fp ) != 1 )
  214. goto unexpEndOfFile;
  215. myFseek( psInfo->fp, intlLong( &header[4] ) - sizeof( sFmtChunk ) );
  216. fFmtChunkFound = TRUE;
  217. }
  218. else
  219. myFseek( psInfo->fp, intlLong( &header[4] ) );
  220. if( fread( header, 4, 2, psInfo->fp ) != 2 ) goto unexpEndOfFile;
  221. }
  222. /* Fill in sFmtChunk */
  223. sFmtChunk.wFormatTag = intlShort( aTemp );
  224. sFmtChunk.wChannels = intlShort( aTemp + 2);
  225. sFmtChunk.dwSamplesPerSec = intlLong( aTemp + 4 );
  226. sFmtChunk.dwAvgBytesPerSec = intlLong( aTemp + 8 );
  227. sFmtChunk.wBlockAlign = intlShort( aTemp + 12 );
  228. sFmtChunk.bitsPerSample = intlShort( aTemp + 14 );
  229. /* Process the data in sFmtChunk */
  230. if( fFmtChunkFound != TRUE )
  231. {
  232. psInfo->errcode = -5;
  233. return FALSE;
  234. }
  235. if( sFmtChunk.wFormatTag != 1 )
  236. {
  237. psInfo->errcode = -6;
  238. return FALSE; /* Not a PCM-sample. */
  239. }
  240. if( sFmtChunk.wChannels > 2 )
  241. {
  242. psInfo->errcode = -6;
  243. return FALSE; /* More than two channels. */
  244. }
  245. psInfo->freq = sFmtChunk.dwSamplesPerSec;
  246. psInfo->fReadStereo = sFmtChunk.wChannels - 1;
  247. psInfo->bits = sFmtChunk.bitsPerSample;
  248. if( sFmtChunk.bitsPerSample == 8 )
  249. psInfo->fSign = FALSE;
  250. else
  251. psInfo->fSign = TRUE;
  252. psInfo->length = intlLong(&header[4]);
  253. if( sFmtChunk.bitsPerSample == 16 )
  254. psInfo->length /= 2;
  255. psInfo->samplesLeft = psInfo->length;
  256. psInfo->byteorder = LITTLE_ENDIAN;
  257. psInfo->filetype = WAV;
  258. return TRUE;
  259. unexpEndOfFile:
  260. psInfo->errcode = -3;
  261. return FALSE;
  262. }
  263. /*____ readWAVsamples() _______________________________________________________*/
  264. static uint readWAVSamples( SplIn * psInfo, int nSamples, short * wpSamples )
  265. {
  266. return fread( wpSamples, psInfo->bits/8, nSamples, psInfo->fp );
  267. }
  268. /*____ initRAW() ______________________________________________________________*/
  269. static int initRAW( SplIn * psInfo )
  270. {
  271. /* By default we think it is ... */
  272. psInfo->freq = 44100;
  273. psInfo->length = 0xFFFFFFFF;
  274. psInfo->samplesLeft = 0xFFFFFFFF;
  275. psInfo->fReadStereo = TRUE;
  276. psInfo->bits = 16;
  277. psInfo->fSign = TRUE;
  278. psInfo->byteorder = BYTEORDER;
  279. psInfo->filetype = RAW;
  280. return TRUE;
  281. }
  282. /*____ readRAWsamples() _______________________________________________________*/
  283. static uint readRAWSamples( SplIn * psInfo, int nSamples, short * wpSamples )
  284. {
  285. int nPreReadSamples = 0;
  286. if( psInfo->nPreReadBytes != 0 )
  287. {
  288. memcpy( wpSamples, psInfo->preReadBuffer, psInfo->nPreReadBytes );
  289. wpSamples += psInfo->nPreReadBytes / 2;
  290. nPreReadSamples = psInfo->nPreReadBytes / (psInfo->bits/8);
  291. psInfo->nPreReadBytes =  0;
  292. }
  293. return fread( wpSamples, psInfo->bits/8, nSamples - nPreReadSamples, psInfo->fp ) + nPreReadSamples;
  294. }
  295. /*____ initAIFF() _____________________________________________________________*/
  296. static int initAIFF( SplIn * psInfo )
  297. {
  298. char header[3*4];
  299. int fPosAtSample = FALSE;
  300. int fCommChunkFound = FALSE;
  301. uchar * pFreq;
  302. int expo;
  303. double sampleRate;
  304. struct
  305. {
  306. short           numChannels;
  307. unsigned int    numSampleFrames;
  308. short           sampleSize;
  309. /*    char sampleRate[10]; */
  310. } sCommChunk;
  311. char aTemp[18];
  312. /* Go through the file and get COMM and SSND chunks */
  313. while( fPosAtSample == FALSE )
  314. {
  315. if( fread( header, 4, 2, psInfo->fp ) != 2 ) goto unexpEndOfFile;
  316. switch( intlLong( &header[0] ) )
  317. {
  318. case STR_COMM:
  319. if( fread( aTemp, 18, 1, psInfo->fp ) != 1 )
  320. goto unexpEndOfFile;
  321. fCommChunkFound = TRUE;
  322. break;
  323. case STR_SSND:
  324. myFseek( psInfo->fp, 8 );
  325. fPosAtSample = TRUE;
  326. break;
  327. default:
  328. myFseek( psInfo->fp, (mcLong( &header[4] ) + 1) &0xFFFFFFFE );
  329. }
  330. }
  331. if( fPosAtSample != TRUE || fCommChunkFound != TRUE )
  332. return FALSE;
  333. /* Fill in sCommChunk */
  334. sCommChunk.numChannels = mcShort( aTemp );
  335. sCommChunk.numSampleFrames = mcLong( aTemp + 2 );
  336. sCommChunk.sampleSize = mcShort( aTemp + 6 );
  337. /* Read Samplerate */
  338. pFreq = (uchar *) aTemp + 8;
  339. sampleRate = pFreq[9];
  340. sampleRate /= 256;
  341. sampleRate += pFreq[8];
  342. sampleRate /= 256;
  343. sampleRate += pFreq[7];
  344. sampleRate /= 256;
  345. sampleRate += pFreq[6];
  346. sampleRate /= 256;
  347. sampleRate += pFreq[5];
  348. sampleRate /= 256;
  349. sampleRate += pFreq[4];
  350. sampleRate /= 256;
  351. sampleRate += pFreq[3];
  352. sampleRate /= 256;
  353. sampleRate += pFreq[2];
  354. sampleRate /= 256;
  355. expo = (pFreq[0] << 8) + pFreq[1];
  356. expo -= 16383;
  357. expo += 1;
  358. while( expo != 0 )
  359. {
  360. if( expo < 0 )
  361. {
  362. sampleRate /= 2;
  363. expo++;
  364. }
  365. else
  366. {
  367. sampleRate *= 2;
  368. expo--;
  369. }
  370. }
  371. /* compensate for some apps or Macs which write slightly off sample rates */
  372. if ((sampleRate == 44099) || (sampleRate == 44101))
  373. sampleRate = 44100;
  374. if ((sampleRate == 31999) || (sampleRate == 32001))
  375. sampleRate = 32000;
  376. if ((sampleRate == 47999) || (sampleRate == 48001))
  377. sampleRate = 48000;
  378. /* Check number of channles and samplesize, just to be sure... */
  379. if( sCommChunk.numChannels > 2 )
  380. {
  381. psInfo->errcode = -6;
  382. return FALSE; /* More than two channels. */
  383. }
  384. if( sCommChunk.sampleSize != 16 && sCommChunk.sampleSize != 8 )
  385. {
  386. psInfo->errcode = -6;
  387. return FALSE; /* Strange samplesize. */
  388. }
  389. /* Fill in psInfo-struct */
  390. psInfo->freq = (int) (sampleRate + 0.5);
  391. psInfo->fReadStereo = sCommChunk.numChannels - 1;
  392. psInfo->bits = sCommChunk.sampleSize;
  393. psInfo->fSign = TRUE; /* Always signed ? */
  394. psInfo->length = sCommChunk.numSampleFrames * sCommChunk.numChannels;
  395. psInfo->samplesLeft = psInfo->length;
  396. psInfo->byteorder = BIG_ENDIAN;
  397. psInfo->filetype = AIFF;
  398. return TRUE;
  399. unexpEndOfFile:
  400. psInfo->errcode = -3;
  401. return FALSE;
  402. }
  403. /*____ readAIFFsamples() ______________________________________________________*/
  404. static uint readAIFFSamples( SplIn * psInfo, int nSamples, short * wpSamples )
  405. {
  406. return fread( wpSamples, psInfo->bits/8, nSamples, psInfo->fp );
  407. }
  408. /*____ intlLong() _____________________________________________________________*/
  409. uint INLINE intlLong( char iLong[4] )
  410. {
  411. return ((uint)((uchar*)iLong)[0]) + (((uint)((uchar*)iLong)[1]) << 8)
  412.        + (((uint)((uchar*)iLong)[2]) << 16) + (((uint)((uchar*)iLong)[3]) << 24);
  413. }
  414. /*____ mcLong() _______________________________________________________________*/
  415. uint INLINE mcLong( char mcLong[4] )
  416. {
  417. return ((uint)((uchar*)mcLong)[3]) + (((uint)((uchar*)mcLong)[2]) << 8 )
  418.        + (((uint)((uchar*)mcLong)[1]) << 16) + (((uint)((uchar*)mcLong)[0]) << 24);
  419. }
  420. /*____ intlShort() ____________________________________________________________*/
  421. ushort INLINE intlShort( char iShort[2] )
  422. {
  423. return ((ushort)((uchar*)iShort)[0]) + (((ushort)((uchar*)iShort)[1]) << 8);
  424. }
  425. /*____ mcShort() ______________________________________________________________*/
  426. ushort INLINE mcShort( char mcShort[2] )
  427. {
  428. return ((ushort)((uchar*)mcShort)[1]) + (((ushort)((uchar*)mcShort)[0]) << 8);
  429. }
  430. /*____ myFseek() ______________________________________________________________*/
  431. /* We can't use the real fseek() since you can't seek in a stream (stdin) */
  432. int myFseek( FILE * fp, int offset )
  433. {
  434. char dummy[256];
  435. while( offset / 256 )
  436. {
  437. fread( dummy, 256, 1, fp );
  438. offset -= 256;
  439. }
  440. if( offset )
  441. fread( dummy, offset, 1, fp );
  442. return 0;
  443. }