1 /*
2 Copyright (C) 2003 Commonwealth Scientific and Industrial Research
3 Organisation (CSIRO) Australia
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 CSIRO Australia 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 A
23 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION 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 #include "config.h"
34
35 #include <stdio.h>
36 #include <string.h>
37
38 #include "private.h"
39
40 int
fish_sound_identify(unsigned char * buf,long bytes)41 fish_sound_identify (unsigned char * buf, long bytes)
42 {
43 if (bytes < 8) return FISH_SOUND_ERR_SHORT_IDENTIFY;
44
45 if (HAVE_VORBIS &&
46 fish_sound_vorbis_identify (buf, bytes) != FISH_SOUND_UNKNOWN)
47 return FISH_SOUND_VORBIS;
48
49 if (HAVE_SPEEX &&
50 fish_sound_speex_identify (buf, bytes) != FISH_SOUND_UNKNOWN)
51 return FISH_SOUND_SPEEX;
52
53 if (fish_sound_flac_identify (buf, bytes) != FISH_SOUND_UNKNOWN)
54 return FISH_SOUND_FLAC;
55
56 return FISH_SOUND_UNKNOWN;
57 }
58
59 int
fish_sound_set_format(FishSound * fsound,int format)60 fish_sound_set_format (FishSound * fsound, int format)
61 {
62 if (format == FISH_SOUND_VORBIS) {
63 fsound->codec = fish_sound_vorbis_codec ();
64 } else if (format == FISH_SOUND_SPEEX) {
65 fsound->codec = fish_sound_speex_codec ();
66 } else if (format == FISH_SOUND_FLAC) {
67 fsound->codec = fish_sound_flac_codec ();
68 } else {
69 return -1;
70 }
71
72 if (fsound->codec && fsound->codec->init)
73 if (fsound->codec->init (fsound) == NULL) return -1;
74
75 fsound->info.format = format;
76
77 return format;
78 }
79
80 FishSound *
fish_sound_new(int mode,FishSoundInfo * fsinfo)81 fish_sound_new (int mode, FishSoundInfo * fsinfo)
82 {
83 FishSound * fsound;
84
85 if (!FS_DECODE && mode == FISH_SOUND_DECODE) return NULL;
86
87 if (!FS_ENCODE && mode == FISH_SOUND_ENCODE) return NULL;
88
89 if (mode == FISH_SOUND_ENCODE) {
90 if (fsinfo == NULL) {
91 return NULL;
92 } else {
93 if (!(HAVE_VORBIS && HAVE_VORBISENC)) {
94 if (fsinfo->format == FISH_SOUND_VORBIS) return NULL;
95 }
96 if (!HAVE_SPEEX) {
97 if (fsinfo->format == FISH_SOUND_SPEEX) return NULL;
98 }
99 if (!HAVE_FLAC) {
100 if (fsinfo->format == FISH_SOUND_FLAC) return NULL;
101 }
102 }
103 } else if (mode != FISH_SOUND_DECODE) {
104 return NULL;
105 }
106
107 fsound = fs_malloc (sizeof (FishSound));
108 if (fsound == NULL) return NULL;
109
110 fsound->mode = mode;
111 fsound->interleave = 0;
112 fsound->frameno = 0;
113 fsound->next_granulepos = -1;
114 fsound->next_eos = 0;
115 fsound->codec = NULL;
116 fsound->codec_data = NULL;
117 fsound->callback.encoded = NULL;
118 fsound->user_data = NULL;
119
120 fish_sound_comments_init (fsound);
121
122 if (mode == FISH_SOUND_DECODE) {
123 fsound->info.samplerate = 0;
124 fsound->info.channels = 0;
125 fsound->info.format = FISH_SOUND_UNKNOWN;
126 } else if (mode == FISH_SOUND_ENCODE) {
127 fsound->info.samplerate = fsinfo->samplerate;
128 fsound->info.channels = fsinfo->channels;
129 fsound->info.format = fsinfo->format;
130
131 if (fish_sound_set_format (fsound, fsinfo->format) == -1) {
132 fs_free (fsound);
133 return NULL;
134 }
135 }
136
137 return fsound;
138 }
139
140 long
fish_sound_flush(FishSound * fsound)141 fish_sound_flush (FishSound * fsound)
142 {
143 if (fsound == NULL) return -1;
144
145 if (fsound->codec && fsound->codec->flush)
146 return fsound->codec->flush (fsound);
147
148 return 0;
149 }
150
151 int
fish_sound_reset(FishSound * fsound)152 fish_sound_reset (FishSound * fsound)
153 {
154 if (fsound == NULL) return -1;
155
156 if (fsound->codec && fsound->codec->reset)
157 return fsound->codec->reset (fsound);
158
159 return 0;
160 }
161
162 FishSound *
fish_sound_delete(FishSound * fsound)163 fish_sound_delete (FishSound * fsound)
164 {
165 if (fsound == NULL) return NULL;
166
167 if (fsound->codec && fsound->codec->del)
168 fsound->codec->del (fsound);
169
170 fs_free (fsound->codec);
171
172 fish_sound_comments_free (fsound);
173
174 fs_free (fsound);
175
176 return NULL;
177 }
178
179 int
fish_sound_command(FishSound * fsound,int command,void * data,int datasize)180 fish_sound_command (FishSound * fsound, int command, void * data, int datasize)
181 {
182 FishSoundInfo * fsinfo = (FishSoundInfo *)data;
183 int * pi = (int *)data;
184
185 if (fsound == NULL) return -1;
186
187 switch (command) {
188 case FISH_SOUND_GET_INFO:
189 memcpy (fsinfo, &fsound->info, sizeof (FishSoundInfo));
190 break;
191 case FISH_SOUND_GET_INTERLEAVE:
192 *pi = fsound->interleave;
193 break;
194 case FISH_SOUND_SET_INTERLEAVE:
195 fsound->interleave = (*pi ? 1 : 0);
196 break;
197 default:
198 if (fsound->codec && fsound->codec->command)
199 return fsound->codec->command (fsound, command, data, datasize);
200 break;
201 }
202
203 return 0;
204 }
205
206 int
fish_sound_get_interleave(FishSound * fsound)207 fish_sound_get_interleave (FishSound * fsound)
208 {
209 if (fsound == NULL) return -1;
210
211 return fsound->interleave;
212 }
213
214 #ifndef FS_DISABLE_DEPRECATED
215 int
fish_sound_set_interleave(FishSound * fsound,int interleave)216 fish_sound_set_interleave (FishSound * fsound, int interleave)
217 {
218 if (fsound == NULL) return -1;
219
220 fsound->interleave = (interleave ? 1 : 0);
221
222 return 0;
223 }
224 #endif
225
226 long
fish_sound_get_frameno(FishSound * fsound)227 fish_sound_get_frameno (FishSound * fsound)
228 {
229 if (fsound == NULL) return -1L;
230
231 return fsound->frameno;
232 }
233
234 int
fish_sound_set_frameno(FishSound * fsound,long frameno)235 fish_sound_set_frameno (FishSound * fsound, long frameno)
236 {
237 if (fsound == NULL) return -1;
238
239 fsound->frameno = frameno;
240
241 return 0;
242 }
243
244 int
fish_sound_prepare_truncation(FishSound * fsound,long next_granulepos,int next_eos)245 fish_sound_prepare_truncation (FishSound * fsound, long next_granulepos,
246 int next_eos)
247 {
248 if (fsound == NULL) return -1;
249
250 fsound->next_granulepos = next_granulepos;
251 fsound->next_eos = next_eos;
252
253 return 0;
254 }
255