Disable unused options
[platform/upstream/alure.git] / src / codec_aiff.cpp
1 /*
2  * ALURE  OpenAL utility library
3  * Copyright (c) 2009-2010 by Chris Robinson.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to
7  * deal in the Software without restriction, including without limitation the
8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9  * sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23
24 #include "config.h"
25
26 #include "main.h"
27
28 #include <string.h>
29 #include <assert.h>
30
31 #include <istream>
32
33
34 struct aiffStream : public alureStream {
35 private:
36     ALenum format;
37     int samplerate;
38     int blockAlign;
39     int sampleSize;
40     int channels;
41     long dataStart;
42     long dataLen;
43     size_t remLen;
44
45 public:
46     static void Init() { }
47     static void Deinit() { }
48
49     virtual bool IsValid()
50     { return (dataStart > 0 && format != AL_NONE); }
51
52     virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
53     {
54         *fmt = format;
55         *frequency = samplerate;
56         *blockalign = blockAlign;
57         return true;
58     }
59
60     virtual ALuint GetData(ALubyte *data, ALuint bytes)
61     {
62         std::streamsize rem = ((remLen >= bytes) ? bytes : remLen) / blockAlign;
63         fstream->read(reinterpret_cast<char*>(data), rem*blockAlign);
64
65         std::streamsize got = fstream->gcount();
66         got -= got%blockAlign;
67         remLen -= got;
68
69         if(LittleEndian)
70         {
71             if(sampleSize == 2)
72             {
73                 for(std::streamsize i = 0;i < got;i+=2)
74                     swap(data[i], data[i+1]);
75             }
76             else if(sampleSize == 4)
77             {
78                 for(std::streamsize i = 0;i < got;i+=4)
79                 {
80                     swap(data[i+0], data[i+3]);
81                     swap(data[i+1], data[i+2]);
82                 }
83             }
84         }
85
86         return got;
87     }
88
89     virtual bool Rewind()
90     {
91         fstream->clear();
92         if(fstream->seekg(dataStart))
93         {
94             remLen = dataLen;
95             return true;
96         }
97
98         SetError("Seek failed");
99         return false;
100     }
101
102     virtual alureInt64 GetLength()
103     {
104         alureInt64 ret = dataLen;
105         return ret / channels * 8 / sampleSize;
106     }
107
108     aiffStream(std::istream *_fstream)
109       : alureStream(_fstream), format(0), dataStart(0)
110     {
111         ALubyte buffer[25];
112         int length;
113
114         if(!fstream->read(reinterpret_cast<char*>(buffer), 12) ||
115            memcmp(buffer, "FORM", 4) != 0 || memcmp(buffer+8, "AIFF", 4) != 0)
116             return;
117
118         while(!dataStart || format == AL_NONE)
119         {
120             char tag[4];
121             if(!fstream->read(tag, 4))
122                 break;
123
124             /* read chunk length */
125             length = read_be32(fstream);
126
127             if(memcmp(tag, "COMM", 4) == 0 && length >= 18)
128             {
129                 /* mono or stereo data */
130                 channels = read_be16(fstream);
131
132                 /* number of sample frames */
133                 fstream->ignore(4);
134
135                 /* bits per sample */
136                 sampleSize = read_be16(fstream) / 8;
137
138                 /* sample frequency */
139                 samplerate = read_be80extended(fstream);
140
141                 /* block alignment */
142                 blockAlign = channels * sampleSize;
143
144                 format = GetSampleFormat(channels, sampleSize*8, false);
145
146                 length -= 18;
147             }
148             else if(memcmp(tag, "SSND", 4) == 0)
149             {
150                 dataStart = fstream->tellg();
151                 dataStart += 8;
152                 dataLen = remLen = length - 8;
153             }
154
155             fstream->seekg(length, std::ios_base::cur);
156         }
157
158         if(dataStart > 0 && format != AL_NONE)
159             fstream->seekg(dataStart);
160     }
161
162     virtual ~aiffStream()
163     { }
164 };
165 // Priority = 9, prefer this decoder over external ones (but not the wave decoder)
166 static DecoderDecl<aiffStream,9> aiffStream_decoder;
167 Decoder &alure_init_aiff(void)
168 { return aiffStream_decoder; }