/src/vlc/contrib/contrib-build/speex/libspeex/speex_header.c
Line | Count | Source |
1 | | /* Copyright (C) 2002 Jean-Marc Valin |
2 | | File: speex_header.c |
3 | | Describes the Speex header |
4 | | |
5 | | Redistribution and use in source and binary forms, with or without |
6 | | modification, are permitted provided that the following conditions |
7 | | are met: |
8 | | |
9 | | - Redistributions of source code must retain the above copyright |
10 | | notice, this list of conditions and the following disclaimer. |
11 | | |
12 | | - Redistributions in binary form must reproduce the above copyright |
13 | | notice, this list of conditions and the following disclaimer in the |
14 | | documentation and/or other materials provided with the distribution. |
15 | | |
16 | | - Neither the name of the Xiph.org Foundation nor the names of its |
17 | | contributors may be used to endorse or promote products derived from |
18 | | this software without specific prior written permission. |
19 | | |
20 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
21 | | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
22 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
23 | | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR |
24 | | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
25 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
26 | | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
27 | | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
28 | | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
29 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
30 | | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | | |
32 | | */ |
33 | | |
34 | | #ifdef HAVE_CONFIG_H |
35 | | #include "config.h" |
36 | | #endif |
37 | | |
38 | | #include "arch.h" |
39 | | #include "speex/speex_header.h" |
40 | | #include "speex/speex.h" |
41 | | #include "os_support.h" |
42 | | |
43 | | #ifndef NULL |
44 | | #define NULL 0 |
45 | | #endif |
46 | | |
47 | | /** Convert little endian */ |
48 | | static inline spx_int32_t le_int(spx_int32_t i) |
49 | 176 | { |
50 | | #if !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) ) |
51 | | spx_uint32_t ui, ret; |
52 | | ui = i; |
53 | | ret = ui>>24; |
54 | | ret |= (ui>>8)&0x0000ff00; |
55 | | ret |= (ui<<8)&0x00ff0000; |
56 | | ret |= (ui<<24); |
57 | | return ret; |
58 | | #else |
59 | 176 | return i; |
60 | 176 | #endif |
61 | 176 | } |
62 | | |
63 | 176 | #define ENDIAN_SWITCH(x) {x=le_int(x);} |
64 | | |
65 | | |
66 | | /* |
67 | | typedef struct SpeexHeader { |
68 | | char speex_string[8]; |
69 | | char speex_version[SPEEX_HEADER_VERSION_LENGTH]; |
70 | | int speex_version_id; |
71 | | int header_size; |
72 | | int rate; |
73 | | int mode; |
74 | | int mode_bitstream_version; |
75 | | int nb_channels; |
76 | | int bitrate; |
77 | | int frame_size; |
78 | | int vbr; |
79 | | int frames_per_packet; |
80 | | int extra_headers; |
81 | | int reserved1; |
82 | | int reserved2; |
83 | | } SpeexHeader; |
84 | | */ |
85 | | |
86 | | EXPORT void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const SpeexMode *m) |
87 | 0 | { |
88 | 0 | int i; |
89 | 0 | const char *h="Speex "; |
90 | | /* |
91 | | strncpy(header->speex_string, "Speex ", 8); |
92 | | strncpy(header->speex_version, SPEEX_VERSION, SPEEX_HEADER_VERSION_LENGTH-1); |
93 | | header->speex_version[SPEEX_HEADER_VERSION_LENGTH-1]=0; |
94 | | */ |
95 | 0 | for (i=0;i<8;i++) |
96 | 0 | header->speex_string[i]=h[i]; |
97 | 0 | for (i=0;i<SPEEX_HEADER_VERSION_LENGTH-1 && SPEEX_VERSION[i];i++) |
98 | 0 | header->speex_version[i]=SPEEX_VERSION[i]; |
99 | 0 | for (;i<SPEEX_HEADER_VERSION_LENGTH;i++) |
100 | 0 | header->speex_version[i]=0; |
101 | |
|
102 | 0 | header->speex_version_id = 1; |
103 | 0 | header->header_size = sizeof(SpeexHeader); |
104 | |
|
105 | 0 | header->rate = rate; |
106 | 0 | header->mode = m->modeID; |
107 | 0 | header->mode_bitstream_version = m->bitstream_version; |
108 | 0 | if (m->modeID<0) |
109 | 0 | speex_warning("This mode is meant to be used alone"); |
110 | 0 | header->nb_channels = nb_channels; |
111 | 0 | header->bitrate = -1; |
112 | 0 | speex_mode_query(m, SPEEX_MODE_FRAME_SIZE, &header->frame_size); |
113 | 0 | header->vbr = 0; |
114 | |
|
115 | 0 | header->frames_per_packet = 0; |
116 | 0 | header->extra_headers = 0; |
117 | 0 | header->reserved1 = 0; |
118 | 0 | header->reserved2 = 0; |
119 | 0 | } |
120 | | |
121 | | EXPORT char *speex_header_to_packet(SpeexHeader *header, int *size) |
122 | 0 | { |
123 | 0 | SpeexHeader *le_header; |
124 | 0 | le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader)); |
125 | |
|
126 | 0 | SPEEX_COPY(le_header, header, 1); |
127 | | |
128 | | /*Make sure everything is now little-endian*/ |
129 | 0 | ENDIAN_SWITCH(le_header->speex_version_id); |
130 | 0 | ENDIAN_SWITCH(le_header->header_size); |
131 | 0 | ENDIAN_SWITCH(le_header->rate); |
132 | 0 | ENDIAN_SWITCH(le_header->mode); |
133 | 0 | ENDIAN_SWITCH(le_header->mode_bitstream_version); |
134 | 0 | ENDIAN_SWITCH(le_header->nb_channels); |
135 | 0 | ENDIAN_SWITCH(le_header->bitrate); |
136 | 0 | ENDIAN_SWITCH(le_header->frame_size); |
137 | 0 | ENDIAN_SWITCH(le_header->vbr); |
138 | 0 | ENDIAN_SWITCH(le_header->frames_per_packet); |
139 | 0 | ENDIAN_SWITCH(le_header->extra_headers); |
140 | |
|
141 | 0 | *size = sizeof(SpeexHeader); |
142 | 0 | return (char *)le_header; |
143 | 0 | } |
144 | | |
145 | | EXPORT SpeexHeader *speex_packet_to_header(char *packet, int size) |
146 | 16 | { |
147 | 16 | int i; |
148 | 16 | SpeexHeader *le_header; |
149 | 16 | const char *h = "Speex "; |
150 | | |
151 | | /*FIXME: Do we allow larger headers?*/ |
152 | 16 | if (size < (int)sizeof(SpeexHeader)) |
153 | 0 | { |
154 | 0 | speex_notify("Speex header too small"); |
155 | 0 | return NULL; |
156 | 0 | } |
157 | | |
158 | | |
159 | 144 | for (i=0;i<8;i++) |
160 | 128 | if (packet[i]!=h[i]) |
161 | 0 | { |
162 | | /* This doesn't look like a Speex file */ |
163 | 0 | return NULL; |
164 | 0 | } |
165 | | |
166 | 16 | le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader)); |
167 | | |
168 | 16 | SPEEX_COPY(le_header, (SpeexHeader*)packet, 1); |
169 | | |
170 | | /*Make sure everything is converted correctly from little-endian*/ |
171 | 16 | ENDIAN_SWITCH(le_header->speex_version_id); |
172 | 16 | ENDIAN_SWITCH(le_header->header_size); |
173 | 16 | ENDIAN_SWITCH(le_header->rate); |
174 | 16 | ENDIAN_SWITCH(le_header->mode); |
175 | 16 | ENDIAN_SWITCH(le_header->mode_bitstream_version); |
176 | 16 | ENDIAN_SWITCH(le_header->nb_channels); |
177 | 16 | ENDIAN_SWITCH(le_header->bitrate); |
178 | 16 | ENDIAN_SWITCH(le_header->frame_size); |
179 | 16 | ENDIAN_SWITCH(le_header->vbr); |
180 | 16 | ENDIAN_SWITCH(le_header->frames_per_packet); |
181 | 16 | ENDIAN_SWITCH(le_header->extra_headers); |
182 | | |
183 | 16 | if (le_header->mode >= SPEEX_NB_MODES || le_header->mode < 0) |
184 | 0 | { |
185 | 0 | speex_notify("Invalid mode specified in Speex header"); |
186 | 0 | speex_free (le_header); |
187 | 0 | return NULL; |
188 | 0 | } |
189 | | |
190 | 16 | if (le_header->nb_channels>2) |
191 | 0 | le_header->nb_channels = 2; |
192 | 16 | if (le_header->nb_channels<1) |
193 | 0 | le_header->nb_channels = 1; |
194 | | |
195 | 16 | return le_header; |
196 | | |
197 | 16 | } |
198 | | |
199 | | EXPORT void speex_header_free(void *ptr) |
200 | 24 | { |
201 | 24 | speex_free(ptr); |
202 | 24 | } |