~ubuntu-branches/ubuntu/trusty/teeworlds/trusty-updates

« back to all changes in this revision

Viewing changes to src/engine/external/wavpack/wputils.c

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-08-05 15:02:49 UTC
  • mfrom: (1.2.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20110805150249-1kai5j7v29m13dl3
Tags: 0.6.1+dfsg-1
* New upstream release.
* Repackage upstream tarball to remove pre-compiled libraries.
* Update watch file.
* Refresh patches.
* Drop patches that have been applied upstream: fix-ftbfs-hurd.patch,
  fix-ftbfs-kfreebsd.patch and gcc-endianness.patch.
* Use dh_link to create the DejaVuSans.ttf symlink.
* Query dpkg-buildflags instead of relying on dpkg-buildpackage to set the
  environment variables.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
////////////////////////////////////////////////////////////////////////////
2
 
//                           **** WAVPACK ****                            //
3
 
//                  Hybrid Lossless Wavefile Compressor                   //
4
 
//              Copyright (c) 1998 - 2006 Conifer Software.               //
5
 
//                          All Rights Reserved.                          //
6
 
//      Distributed under the BSD Software License (see license.txt)      //
7
 
////////////////////////////////////////////////////////////////////////////
8
 
 
9
 
// wputils.c
10
 
 
11
 
// This module provides a high-level interface for decoding WavPack 4.0 audio
12
 
// streams and files. WavPack data is read with a stream reading callback. No
13
 
// direct seeking is provided for, but it is possible to start decoding
14
 
// anywhere in a WavPack stream. In this case, WavPack will be able to provide
15
 
// the sample-accurate position when it synchs with the data and begins
16
 
// decoding.
17
 
 
18
 
#include "wavpack.h"
19
 
 
20
 
#include <string.h>
21
 
 
22
 
///////////////////////////// local table storage ////////////////////////////
23
 
 
24
 
const uint32_t sample_rates [] = { 6000, 8000, 9600, 11025, 12000, 16000, 22050,
25
 
    24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 };
26
 
 
27
 
///////////////////////////// executable code ////////////////////////////////
28
 
 
29
 
static uint32_t read_next_header (read_stream infile, WavpackHeader *wphdr);
30
 
        
31
 
// This function reads data from the specified stream in search of a valid
32
 
// WavPack 4.0 audio block. If this fails in 1 megabyte (or an invalid or
33
 
// unsupported WavPack block is encountered) then an appropriate message is
34
 
// copied to "error" and NULL is returned, otherwise a pointer to a
35
 
// WavpackContext structure is returned (which is used to call all other
36
 
// functions in this module). This can be initiated at the beginning of a
37
 
// WavPack file, or anywhere inside a WavPack file. To determine the exact
38
 
// position within the file use WavpackGetSampleIndex(). For demonstration
39
 
// purposes this uses a single static copy of the WavpackContext structure,
40
 
// so obviously it cannot be used for more than one file at a time. Also,
41
 
// this function will not handle "correction" files, plays only the first
42
 
// two channels of multi-channel files, and is limited in resolution in some
43
 
// large integer or floating point files (but always provides at least 24 bits
44
 
// of resolution).
45
 
 
46
 
static WavpackContext wpc;
47
 
 
48
 
WavpackContext *WavpackOpenFileInput (read_stream infile, char *error)
49
 
{
50
 
    WavpackStream *wps = &wpc.stream;
51
 
    uint32_t bcount;
52
 
 
53
 
    CLEAR (wpc);
54
 
    wpc.infile = infile;
55
 
    wpc.total_samples = (uint32_t) -1;
56
 
    wpc.norm_offset = 0;
57
 
    wpc.open_flags = 0;
58
 
 
59
 
    // open the source file for reading and store the size
60
 
 
61
 
    while (!wps->wphdr.block_samples) {
62
 
 
63
 
        bcount = read_next_header (wpc.infile, &wps->wphdr);
64
 
 
65
 
        if (bcount == (uint32_t) -1) {
66
 
            strcpy (error, "not compatible with this version of WavPack file!");
67
 
            return NULL;
68
 
        }
69
 
 
70
 
        if (wps->wphdr.block_samples && wps->wphdr.total_samples != (uint32_t) -1)
71
 
            wpc.total_samples = wps->wphdr.total_samples;
72
 
 
73
 
        if (!unpack_init (&wpc)) {
74
 
            strcpy (error, wpc.error_message [0] ? wpc.error_message :
75
 
                "not compatible with this version of WavPack file!");
76
 
 
77
 
            return NULL;
78
 
        }
79
 
    }
80
 
 
81
 
    wpc.config.flags &= ~0xff;
82
 
    wpc.config.flags |= wps->wphdr.flags & 0xff;
83
 
    wpc.config.bytes_per_sample = (wps->wphdr.flags & BYTES_STORED) + 1;
84
 
    wpc.config.float_norm_exp = wps->float_norm_exp;
85
 
 
86
 
    wpc.config.bits_per_sample = (wpc.config.bytes_per_sample * 8) - 
87
 
        ((wps->wphdr.flags & SHIFT_MASK) >> SHIFT_LSB);
88
 
 
89
 
    if (wpc.config.flags & FLOAT_DATA) {
90
 
        wpc.config.bytes_per_sample = 3;
91
 
        wpc.config.bits_per_sample = 24;
92
 
    }
93
 
 
94
 
    if (!wpc.config.sample_rate) {
95
 
        if (!wps || !wps->wphdr.block_samples || (wps->wphdr.flags & SRATE_MASK) == SRATE_MASK)
96
 
            wpc.config.sample_rate = 44100;
97
 
        else
98
 
            wpc.config.sample_rate = sample_rates [(wps->wphdr.flags & SRATE_MASK) >> SRATE_LSB];
99
 
    }
100
 
 
101
 
    if (!wpc.config.num_channels) {
102
 
        wpc.config.num_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
103
 
        wpc.config.channel_mask = 0x5 - wpc.config.num_channels;
104
 
    }
105
 
 
106
 
    if (!(wps->wphdr.flags & FINAL_BLOCK))
107
 
        wpc.reduced_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
108
 
 
109
 
    return &wpc;
110
 
}
111
 
 
112
 
// This function obtains general information about an open file and returns
113
 
// a mask with the following bit values:
114
 
 
115
 
// MODE_LOSSLESS:  file is lossless (pure lossless only)
116
 
// MODE_HYBRID:  file is hybrid mode (lossy part only)
117
 
// MODE_FLOAT:  audio data is 32-bit ieee floating point (but will provided
118
 
//               in 24-bit integers for convenience)
119
 
// MODE_HIGH:  file was created in "high" mode (information only)
120
 
// MODE_FAST:  file was created in "fast" mode (information only)
121
 
 
122
 
int WavpackGetMode (WavpackContext *wpc)
123
 
{
124
 
    int mode = 0;
125
 
 
126
 
    if (wpc) {
127
 
        if (wpc->config.flags & CONFIG_HYBRID_FLAG)
128
 
            mode |= MODE_HYBRID;
129
 
        else if (!(wpc->config.flags & CONFIG_LOSSY_MODE))
130
 
            mode |= MODE_LOSSLESS;
131
 
 
132
 
        if (wpc->lossy_blocks)
133
 
            mode &= ~MODE_LOSSLESS;
134
 
 
135
 
        if (wpc->config.flags & CONFIG_FLOAT_DATA)
136
 
            mode |= MODE_FLOAT;
137
 
 
138
 
        if (wpc->config.flags & CONFIG_HIGH_FLAG)
139
 
            mode |= MODE_HIGH;
140
 
 
141
 
        if (wpc->config.flags & CONFIG_FAST_FLAG)
142
 
            mode |= MODE_FAST;
143
 
    }
144
 
 
145
 
    return mode;
146
 
}
147
 
 
148
 
// Unpack the specified number of samples from the current file position.
149
 
// Note that "samples" here refers to "complete" samples, which would be
150
 
// 2 longs for stereo files. The audio data is returned right-justified in
151
 
// 32-bit longs in the endian mode native to the executing processor. So,
152
 
// if the original data was 16-bit, then the values returned would be
153
 
// +/-32k. Floating point data will be returned as 24-bit integers (and may
154
 
// also be clipped). The actual number of samples unpacked is returned,
155
 
// which should be equal to the number requested unless the end of fle is
156
 
// encountered or an error occurs.
157
 
 
158
 
uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples)
159
 
{
160
 
    WavpackStream *wps = &wpc->stream;
161
 
    uint32_t bcount, samples_unpacked = 0, samples_to_unpack;
162
 
    int num_channels = wpc->config.num_channels;
163
 
 
164
 
    while (samples) {
165
 
        if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) ||
166
 
            wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples) {
167
 
                bcount = read_next_header (wpc->infile, &wps->wphdr);
168
 
 
169
 
                if (bcount == (uint32_t) -1)
170
 
                    break;
171
 
 
172
 
                if (!wps->wphdr.block_samples || wps->sample_index == wps->wphdr.block_index)
173
 
                    if (!unpack_init (wpc))
174
 
                        break;
175
 
        }
176
 
 
177
 
        if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) ||
178
 
            wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples)
179
 
                continue;
180
 
 
181
 
        if (wps->sample_index < wps->wphdr.block_index) {
182
 
            samples_to_unpack = wps->wphdr.block_index - wps->sample_index;
183
 
 
184
 
            if (samples_to_unpack > samples)
185
 
                samples_to_unpack = samples;
186
 
 
187
 
            wps->sample_index += samples_to_unpack;
188
 
            samples_unpacked += samples_to_unpack;
189
 
            samples -= samples_to_unpack;
190
 
 
191
 
            if (wpc->reduced_channels)
192
 
                samples_to_unpack *= wpc->reduced_channels;
193
 
            else
194
 
                samples_to_unpack *= num_channels;
195
 
 
196
 
            while (samples_to_unpack--)
197
 
                *buffer++ = 0;
198
 
 
199
 
            continue;
200
 
        }
201
 
 
202
 
        samples_to_unpack = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index;
203
 
 
204
 
        if (samples_to_unpack > samples)
205
 
            samples_to_unpack = samples;
206
 
 
207
 
        unpack_samples (wpc, buffer, samples_to_unpack);
208
 
 
209
 
        if (wpc->reduced_channels)
210
 
            buffer += samples_to_unpack * wpc->reduced_channels;
211
 
        else
212
 
            buffer += samples_to_unpack * num_channels;
213
 
 
214
 
        samples_unpacked += samples_to_unpack;
215
 
        samples -= samples_to_unpack;
216
 
 
217
 
        if (wps->sample_index == wps->wphdr.block_index + wps->wphdr.block_samples) {
218
 
            if (check_crc_error (wpc))
219
 
                wpc->crc_errors++;
220
 
        }
221
 
 
222
 
        if (wps->sample_index == wpc->total_samples)
223
 
            break;
224
 
    }
225
 
 
226
 
    return samples_unpacked;
227
 
}
228
 
 
229
 
// Get total number of samples contained in the WavPack file, or -1 if unknown
230
 
 
231
 
uint32_t WavpackGetNumSamples (WavpackContext *wpc)
232
 
{
233
 
    return wpc ? wpc->total_samples : (uint32_t) -1;
234
 
}
235
 
 
236
 
// Get the current sample index position, or -1 if unknown
237
 
 
238
 
uint32_t WavpackGetSampleIndex (WavpackContext *wpc)
239
 
{
240
 
    if (wpc)
241
 
        return wpc->stream.sample_index;
242
 
 
243
 
    return (uint32_t) -1;
244
 
}
245
 
 
246
 
// Get the number of errors encountered so far
247
 
 
248
 
int WavpackGetNumErrors (WavpackContext *wpc)
249
 
{
250
 
    return wpc ? wpc->crc_errors : 0;
251
 
}
252
 
 
253
 
// return TRUE if any uncorrected lossy blocks were actually written or read
254
 
 
255
 
int WavpackLossyBlocks (WavpackContext *wpc)
256
 
{
257
 
    return wpc ? wpc->lossy_blocks : 0;
258
 
}
259
 
 
260
 
// Returns the sample rate of the specified WavPack file
261
 
 
262
 
uint32_t WavpackGetSampleRate (WavpackContext *wpc)
263
 
{
264
 
    return wpc ? wpc->config.sample_rate : 44100;
265
 
}
266
 
 
267
 
// Returns the number of channels of the specified WavPack file. Note that
268
 
// this is the actual number of channels contained in the file, but this
269
 
// version can only decode the first two.
270
 
 
271
 
int WavpackGetNumChannels (WavpackContext *wpc)
272
 
{
273
 
    return wpc ? wpc->config.num_channels : 2;
274
 
}
275
 
 
276
 
// Returns the actual number of valid bits per sample contained in the
277
 
// original file, which may or may not be a multiple of 8. Floating data
278
 
// always has 32 bits, integers may be from 1 to 32 bits each. When this
279
 
// value is not a multiple of 8, then the "extra" bits are located in the
280
 
// LSBs of the results. That is, values are right justified when unpacked
281
 
// into longs, but are left justified in the number of bytes used by the
282
 
// original data.
283
 
 
284
 
int WavpackGetBitsPerSample (WavpackContext *wpc)
285
 
{
286
 
    return wpc ? wpc->config.bits_per_sample : 16;
287
 
}
288
 
 
289
 
// Returns the number of bytes used for each sample (1 to 4) in the original
290
 
// file. This is required information for the user of this module because the
291
 
// audio data is returned in the LOWER bytes of the long buffer and must be
292
 
// left-shifted 8, 16, or 24 bits if normalized longs are required.
293
 
 
294
 
int WavpackGetBytesPerSample (WavpackContext *wpc)
295
 
{
296
 
    return wpc ? wpc->config.bytes_per_sample : 2;
297
 
}
298
 
 
299
 
// This function will return the actual number of channels decoded from the
300
 
// file (which may or may not be less than the actual number of channels, but
301
 
// will always be 1 or 2). Normally, this will be the front left and right
302
 
// channels of a multi-channel file.
303
 
 
304
 
int WavpackGetReducedChannels (WavpackContext *wpc)
305
 
{
306
 
    if (wpc)
307
 
        return wpc->reduced_channels ? wpc->reduced_channels : wpc->config.num_channels;
308
 
    else
309
 
        return 2;
310
 
}
311
 
 
312
 
// Read from current file position until a valid 32-byte WavPack 4.0 header is
313
 
// found and read into the specified pointer. The number of bytes skipped is
314
 
// returned. If no WavPack header is found within 1 meg, then a -1 is returned
315
 
// to indicate the error. No additional bytes are read past the header and it
316
 
// is returned in the processor's native endian mode. Seeking is not required.
317
 
 
318
 
static uint32_t read_next_header (read_stream infile, WavpackHeader *wphdr)
319
 
{
320
 
    char buffer [sizeof (*wphdr)], *sp = buffer + sizeof (*wphdr), *ep = sp;
321
 
    uint32_t bytes_skipped = 0;
322
 
    int bleft;
323
 
 
324
 
    while (1) {
325
 
        if (sp < ep) {
326
 
            bleft = ep - sp;
327
 
            memcpy (buffer, sp, bleft);
328
 
        }
329
 
        else
330
 
            bleft = 0;
331
 
 
332
 
        if (infile (buffer + bleft, sizeof (*wphdr) - bleft) != (int32_t) sizeof (*wphdr) - bleft)
333
 
            return -1;
334
 
 
335
 
        sp = buffer;
336
 
 
337
 
        if (*sp++ == 'w' && *sp == 'v' && *++sp == 'p' && *++sp == 'k' &&
338
 
            !(*++sp & 1) && sp [2] < 16 && !sp [3] && sp [5] == 4 &&
339
 
            sp [4] >= (MIN_STREAM_VERS & 0xff) && sp [4] <= (MAX_STREAM_VERS & 0xff)) {
340
 
                memcpy (wphdr, buffer, sizeof (*wphdr));
341
 
                little_endian_to_native (wphdr, WavpackHeaderFormat);
342
 
                return bytes_skipped;
343
 
            }
344
 
 
345
 
        while (sp < ep && *sp != 'w')
346
 
            sp++;
347
 
 
348
 
        if ((bytes_skipped += sp - buffer) > 1048576L)
349
 
            return -1;
350
 
    }
351
 
}