tizen 2.3.1 release
[external/opencore-amr.git] / test / wavreader.c
1 /* ------------------------------------------------------------------
2  * Copyright (C) 2009 Martin Storsjo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18
19 #include "wavreader.h"
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdint.h>
24
25 #define TAG(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
26
27 struct wav_reader {
28         FILE *wav;
29         uint32_t data_length;
30
31         int format;
32         int sample_rate;
33         int bits_per_sample;
34         int channels;
35         int byte_rate;
36         int block_align;
37 };
38
39 static uint32_t read_tag(struct wav_reader* wr) {
40         uint32_t tag = 0;
41         tag = (tag << 8) | fgetc(wr->wav);
42         tag = (tag << 8) | fgetc(wr->wav);
43         tag = (tag << 8) | fgetc(wr->wav);
44         tag = (tag << 8) | fgetc(wr->wav);
45         return tag;
46 }
47
48 static uint32_t read_int32(struct wav_reader* wr) {
49         uint32_t value = 0;
50         value |= fgetc(wr->wav) <<  0;
51         value |= fgetc(wr->wav) <<  8;
52         value |= fgetc(wr->wav) << 16;
53         value |= fgetc(wr->wav) << 24;
54         return value;
55 }
56
57 static uint16_t read_int16(struct wav_reader* wr) {
58         uint16_t value = 0;
59         value |= fgetc(wr->wav) << 0;
60         value |= fgetc(wr->wav) << 8;
61         return value;
62 }
63
64 void* wav_read_open(const char *filename) {
65         struct wav_reader* wr = (struct wav_reader*) malloc(sizeof(*wr));
66         long data_pos = 0;
67         memset(wr, 0, sizeof(*wr));
68
69         wr->wav = fopen(filename, "rb");
70         if (wr->wav == NULL) {
71                 free(wr);
72                 return NULL;
73         }
74
75         while (1) {
76                 uint32_t tag, tag2, length;
77                 tag = read_tag(wr);
78                 if (feof(wr->wav))
79                         break;
80                 length = read_int32(wr);
81                 if (tag != TAG('R', 'I', 'F', 'F') || length < 4) {
82                         fseek(wr->wav, length, SEEK_CUR);
83                         continue;
84                 }
85                 tag2 = read_tag(wr);
86                 length -= 4;
87                 if (tag2 != TAG('W', 'A', 'V', 'E')) {
88                         fseek(wr->wav, length, SEEK_CUR);
89                         continue;
90                 }
91                 // RIFF chunk found, iterate through it
92                 while (length >= 8) {
93                         uint32_t subtag, sublength;
94                         subtag = read_tag(wr);
95                         if (feof(wr->wav))
96                                 break;
97                         sublength = read_int32(wr);
98                         length -= 8;
99                         if (length < sublength)
100                                 break;
101                         if (subtag == TAG('f', 'm', 't', ' ')) {
102                                 if (sublength < 16) {
103                                         // Insufficient data for 'fmt '
104                                         break;
105                                 }
106                                 wr->format          = read_int16(wr);
107                                 wr->channels        = read_int16(wr);
108                                 wr->sample_rate     = read_int32(wr);
109                                 wr->byte_rate       = read_int32(wr);
110                                 wr->block_align     = read_int16(wr);
111                                 wr->bits_per_sample = read_int16(wr);
112                         } else if (subtag == TAG('d', 'a', 't', 'a')) {
113                                 data_pos = ftell(wr->wav);
114                                 wr->data_length = sublength;
115                                 fseek(wr->wav, sublength, SEEK_CUR);
116                         } else {
117                                 fseek(wr->wav, sublength, SEEK_CUR);
118                         }
119                         length -= sublength;
120                 }
121                 if (length > 0) {
122                         // Bad chunk?
123                         fseek(wr->wav, length, SEEK_CUR);
124                 }
125         }
126         fseek(wr->wav, data_pos, SEEK_SET);
127         return wr;
128 }
129
130 void wav_read_close(void* obj) {
131         struct wav_reader* wr = (struct wav_reader*) obj;
132         fclose(wr->wav);
133         free(wr);
134 }
135
136 int wav_get_header(void* obj, int* format, int* channels, int* sample_rate, int* bits_per_sample, unsigned int* data_length) {
137         struct wav_reader* wr = (struct wav_reader*) obj;
138         if (format)
139                 *format = wr->format;
140         if (channels)
141                 *channels = wr->channels;
142         if (sample_rate)
143                 *sample_rate = wr->sample_rate;
144         if (bits_per_sample)
145                 *bits_per_sample = wr->bits_per_sample;
146         if (data_length)
147                 *data_length = wr->data_length;
148         return wr->format && wr->sample_rate;
149 }
150
151 int wav_read_data(void* obj, unsigned char* data, unsigned int length) {
152         struct wav_reader* wr = (struct wav_reader*) obj;
153         int n;
154         if (wr->wav == NULL)
155                 return -1;
156         if (length > wr->data_length)
157                 length = wr->data_length;
158         n = fread(data, 1, length, wr->wav);
159         wr->data_length -= length;
160         return n;
161 }
162