summaryrefslogtreecommitdiffstats
path: root/mpeglib/lib/tplay/wav.cpp
blob: ca284c3737411effabfd22f4971ede3414febbac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/* 
 * tplay - buffered audio player
 *
 * (c) 1997 ilkka karvinen <ik@iki.fi>
 *
 * Copyright under the GNU GENERAL PUBLIC LICENSE
 *   (see the file COPYING in this directory)
 *
 * 
 *   RIFF/WAVE file header checking.
 *   check_wav returns zero if RIFF/WAVE file format is found.
 *   Reference: http://www.wotsit.demon.co.uk/formats/wav/wav.txt
 */

#include "tplayfunctions.h"

#include <iostream>

using namespace std;

int read_wav(struct info_struct* info, char * buffer) {
   WORD format, channels, bits;
   DWORD magic, samples_per_second, length, data_length;

   magic = read_little_endian_long(buffer);
   if (magic != RIFF_MAGIC)	/* RIFF file? */
      return (1);
   magic = read_little_endian_long(buffer + 0x08);
   if (magic != WAVE_MAGIC)	/* WAVE file? */
      return (1);
   magic = read_little_endian_long(buffer + 0x24);
   if ((magic != DATA_MAGIC) && (magic != INFO_MAGIC)) {	/* data-portion there? */
     cout << "Unknown WAV-header magic. Continuing anyway."<<endl;
   }

   length = read_little_endian_long(buffer + 0x10);

   /* Subchunk length should be 16 here */
   if (length != 16)
      errdie("Unknown RIFF/WAVE header");

   format = read_little_endian_word(buffer + 0x14);

   switch (format) {
   case 0x0001:		/* PCM format */
      break;
   case 0x0101:		/* mu-law */
      die("Mu-law RIFF/WAVE audio file not supported");
      break;
   case 0x0102:		/* a-law */
      die("A-law RIFF/WAVE audio file not supported");
      break;
   case 0x0103:		/* ADPCM */
      die("ADPCM RIFF/WAVE audio file not supported");
      break;
   default:
      errdie("Unknown RIFF/WAVE audio file format");
      break;
   }

   info->filetype = RIFF_FILE;

   channels = read_little_endian_word(buffer + 0x16);
   samples_per_second = read_little_endian_long(buffer + 0x18);
   cout << "samples_per_second:"<<samples_per_second<<endl;
   bits = read_little_endian_word(buffer + 0x22);

   if (bits == 12)
      die("12 bits per sample not supported");

   data_length = read_little_endian_long(buffer + 0x28);

   /* Set audio parameters */
   info->speed = (int) samples_per_second;
   info->bits = (int) bits;
   info->channels = (int) channels;
   
   if (info->verbose)
      printf("RIFF/WAVE audio file: %ld samples/s, %d bits, %d channel(s).\n",
	     info->speed, info->bits, info->channels);

   /* Move data to start from the beginning of the buffer.            */
   /* This is to ensure the correct behaviour of rounding when 16bits */
   /* and/or stereo sample is to be played.                           */
   memmove(buffer, buffer + 0x2c, info->blocksize - 0x2c);

   /* Save audio sample starting point */
   info->headerskip = 0x2c;

   return (0);
}