diff options
Diffstat (limited to 'songdbj/org/tritonus/share/sampled/convert/TSimpleFormatConversionProvider.java')
-rw-r--r-- | songdbj/org/tritonus/share/sampled/convert/TSimpleFormatConversionProvider.java | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/songdbj/org/tritonus/share/sampled/convert/TSimpleFormatConversionProvider.java b/songdbj/org/tritonus/share/sampled/convert/TSimpleFormatConversionProvider.java new file mode 100644 index 0000000000..71b055ff79 --- /dev/null +++ b/songdbj/org/tritonus/share/sampled/convert/TSimpleFormatConversionProvider.java | |||
@@ -0,0 +1,367 @@ | |||
1 | /* | ||
2 | * TSimpleFormatConversionProvider.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 1999 - 2004 by Matthias Pfisterer | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Library General Public License as published | ||
12 | * by the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU Library General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Library General Public | ||
21 | * License along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | /* | ||
27 | |<--- this code is formatted to fit into 80 columns --->| | ||
28 | */ | ||
29 | |||
30 | package org.tritonus.share.sampled.convert; | ||
31 | |||
32 | import java.util.Collection; | ||
33 | import java.util.Iterator; | ||
34 | |||
35 | import javax.sound.sampled.AudioFormat; | ||
36 | import javax.sound.sampled.AudioSystem; | ||
37 | |||
38 | import org.tritonus.share.sampled.AudioFormats; | ||
39 | import org.tritonus.share.ArraySet; | ||
40 | import org.tritonus.share.TDebug; | ||
41 | |||
42 | |||
43 | /** | ||
44 | * This is a base class for FormatConversionProviders that can convert | ||
45 | * from each source encoding/format to each target encoding/format. | ||
46 | * If this is not the case, use TEncodingFormatConversionProvider. | ||
47 | * | ||
48 | * <p>Overriding classes must | ||
49 | * provide a constructor that calls the protected constructor of this class and override | ||
50 | * <code>AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream sourceStream)</code>. | ||
51 | * The latter method should be able to handle the case that all fields are NOT_SPECIFIED | ||
52 | * and provide appropriate default values. | ||
53 | * | ||
54 | * @author Matthias Pfisterer | ||
55 | */ | ||
56 | |||
57 | // todo: | ||
58 | // - declare a constant ALL_BUT_SAME_VALUE (==-2) or so that can be used in format lists | ||
59 | // - consistent implementation of replacing NOT_SPECIFIED when not given in conversion | ||
60 | |||
61 | public abstract class TSimpleFormatConversionProvider | ||
62 | extends TFormatConversionProvider | ||
63 | { | ||
64 | private Collection<AudioFormat.Encoding> m_sourceEncodings; | ||
65 | private Collection<AudioFormat.Encoding> m_targetEncodings; | ||
66 | private Collection<AudioFormat> m_sourceFormats; | ||
67 | private Collection<AudioFormat> m_targetFormats; | ||
68 | |||
69 | |||
70 | |||
71 | protected TSimpleFormatConversionProvider( | ||
72 | Collection<AudioFormat> sourceFormats, | ||
73 | Collection<AudioFormat> targetFormats) | ||
74 | { | ||
75 | m_sourceEncodings = new ArraySet<AudioFormat.Encoding>(); | ||
76 | m_targetEncodings = new ArraySet<AudioFormat.Encoding>(); | ||
77 | m_sourceFormats = sourceFormats; | ||
78 | m_targetFormats = targetFormats; | ||
79 | collectEncodings(m_sourceFormats, m_sourceEncodings); | ||
80 | collectEncodings(m_targetFormats, m_targetEncodings); | ||
81 | } | ||
82 | |||
83 | |||
84 | |||
85 | /** Disables this FormatConversionProvider. | ||
86 | This may be useful when e.g. native libraries are not present. | ||
87 | TODO: enable method, better implementation | ||
88 | */ | ||
89 | protected void disable() | ||
90 | { | ||
91 | if (TDebug.TraceAudioConverter) { TDebug.out("TSimpleFormatConversionProvider.disable(): disabling " + getClass().getName()); } | ||
92 | m_sourceEncodings = new ArraySet<AudioFormat.Encoding>(); | ||
93 | m_targetEncodings = new ArraySet<AudioFormat.Encoding>(); | ||
94 | m_sourceFormats = new ArraySet<AudioFormat>(); | ||
95 | m_targetFormats = new ArraySet<AudioFormat>(); | ||
96 | } | ||
97 | |||
98 | |||
99 | |||
100 | private static void collectEncodings(Collection<AudioFormat> formats, | ||
101 | Collection<AudioFormat.Encoding> encodings) | ||
102 | { | ||
103 | Iterator<AudioFormat> iterator = formats.iterator(); | ||
104 | while (iterator.hasNext()) | ||
105 | { | ||
106 | AudioFormat format = iterator.next(); | ||
107 | encodings.add(format.getEncoding()); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | |||
112 | |||
113 | public AudioFormat.Encoding[] getSourceEncodings() | ||
114 | { | ||
115 | return m_sourceEncodings.toArray(EMPTY_ENCODING_ARRAY); | ||
116 | } | ||
117 | |||
118 | |||
119 | |||
120 | public AudioFormat.Encoding[] getTargetEncodings() | ||
121 | { | ||
122 | return m_targetEncodings.toArray(EMPTY_ENCODING_ARRAY); | ||
123 | } | ||
124 | |||
125 | |||
126 | |||
127 | // overwritten of FormatConversionProvider | ||
128 | public boolean isSourceEncodingSupported(AudioFormat.Encoding sourceEncoding) | ||
129 | { | ||
130 | return m_sourceEncodings.contains(sourceEncoding); | ||
131 | } | ||
132 | |||
133 | |||
134 | |||
135 | // overwritten of FormatConversionProvider | ||
136 | public boolean isTargetEncodingSupported(AudioFormat.Encoding targetEncoding) | ||
137 | { | ||
138 | return m_targetEncodings.contains(targetEncoding); | ||
139 | } | ||
140 | |||
141 | |||
142 | |||
143 | /** | ||
144 | * This implementation assumes that the converter can convert | ||
145 | * from each of its source encodings to each of its target | ||
146 | * encodings. If this is not the case, the converter has to | ||
147 | * override this method. | ||
148 | */ | ||
149 | public AudioFormat.Encoding[] getTargetEncodings(AudioFormat sourceFormat) | ||
150 | { | ||
151 | if (isAllowedSourceFormat(sourceFormat)) | ||
152 | { | ||
153 | return getTargetEncodings(); | ||
154 | } | ||
155 | else | ||
156 | { | ||
157 | return EMPTY_ENCODING_ARRAY; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | |||
162 | |||
163 | /** | ||
164 | * This implementation assumes that the converter can convert | ||
165 | * from each of its source formats to each of its target | ||
166 | * formats. If this is not the case, the converter has to | ||
167 | * override this method. | ||
168 | */ | ||
169 | public AudioFormat[] getTargetFormats(AudioFormat.Encoding targetEncoding, AudioFormat sourceFormat) | ||
170 | { | ||
171 | if (isConversionSupported(targetEncoding, sourceFormat)) | ||
172 | { | ||
173 | return m_targetFormats.toArray(EMPTY_FORMAT_ARRAY); | ||
174 | } | ||
175 | else | ||
176 | { | ||
177 | return EMPTY_FORMAT_ARRAY; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | |||
182 | // TODO: check if necessary | ||
183 | protected boolean isAllowedSourceEncoding(AudioFormat.Encoding sourceEncoding) | ||
184 | { | ||
185 | return m_sourceEncodings.contains(sourceEncoding); | ||
186 | } | ||
187 | |||
188 | |||
189 | |||
190 | protected boolean isAllowedTargetEncoding(AudioFormat.Encoding targetEncoding) | ||
191 | { | ||
192 | return m_targetEncodings.contains(targetEncoding); | ||
193 | } | ||
194 | |||
195 | |||
196 | |||
197 | protected boolean isAllowedSourceFormat(AudioFormat sourceFormat) | ||
198 | { | ||
199 | Iterator<AudioFormat> iterator = m_sourceFormats.iterator(); | ||
200 | while (iterator.hasNext()) | ||
201 | { | ||
202 | AudioFormat format = iterator.next(); | ||
203 | if (AudioFormats.matches(format, sourceFormat)) | ||
204 | { | ||
205 | return true; | ||
206 | } | ||
207 | } | ||
208 | return false; | ||
209 | } | ||
210 | |||
211 | |||
212 | |||
213 | protected boolean isAllowedTargetFormat(AudioFormat targetFormat) | ||
214 | { | ||
215 | Iterator<AudioFormat> iterator = m_targetFormats.iterator(); | ||
216 | while (iterator.hasNext()) | ||
217 | { | ||
218 | AudioFormat format = iterator.next(); | ||
219 | if (AudioFormats.matches(format, targetFormat)) | ||
220 | { | ||
221 | return true; | ||
222 | } | ||
223 | } | ||
224 | return false; | ||
225 | } | ||
226 | |||
227 | // $$fb 2000-04-02 added some convenience methods for overriding classes | ||
228 | protected Collection<AudioFormat.Encoding> getCollectionSourceEncodings() | ||
229 | { | ||
230 | return m_sourceEncodings; | ||
231 | } | ||
232 | |||
233 | protected Collection<AudioFormat.Encoding> getCollectionTargetEncodings() | ||
234 | { | ||
235 | return m_targetEncodings; | ||
236 | } | ||
237 | |||
238 | protected Collection<AudioFormat> getCollectionSourceFormats() { | ||
239 | return m_sourceFormats; | ||
240 | } | ||
241 | |||
242 | protected Collection<AudioFormat> getCollectionTargetFormats() { | ||
243 | return m_targetFormats; | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * Utility method to check whether these values match, | ||
248 | * taking into account AudioSystem.NOT_SPECIFIED. | ||
249 | * @return true if any of the values is AudioSystem.NOT_SPECIFIED | ||
250 | * or both values have the same value. | ||
251 | */ | ||
252 | //$$fb 2000-08-16: moved from TEncodingFormatConversionProvider | ||
253 | protected static boolean doMatch(int i1, int i2) { | ||
254 | return i1==AudioSystem.NOT_SPECIFIED | ||
255 | || i2==AudioSystem.NOT_SPECIFIED | ||
256 | || i1==i2; | ||
257 | } | ||
258 | |||
259 | /** | ||
260 | * @see #doMatch(int,int) | ||
261 | */ | ||
262 | //$$fb 2000-08-16: moved from TEncodingFormatConversionProvider | ||
263 | protected static boolean doMatch(float f1, float f2) { | ||
264 | return f1==AudioSystem.NOT_SPECIFIED | ||
265 | || f2==AudioSystem.NOT_SPECIFIED | ||
266 | || Math.abs(f1 - f2) < 1.0e-9; | ||
267 | } | ||
268 | |||
269 | /** | ||
270 | * Utility method, replaces all occurences of AudioSystem.NOT_SPECIFIED | ||
271 | * in <code>targetFormat</code> with the corresponding value in <code>sourceFormat</code>. | ||
272 | * If <code>targetFormat</code> does not contain any fields with AudioSystem.NOT_SPECIFIED, | ||
273 | * it is returned unmodified. The endian-ness and encoding remain the same in all cases. | ||
274 | * <p> | ||
275 | * If any of the fields is AudioSystem.NOT_SPECIFIED in both <code>sourceFormat</code> and | ||
276 | * <code>targetFormat</code>, it will remain not specified. | ||
277 | * <p> | ||
278 | * This method uses <code>getFrameSize(...)</code> (see below) to set the new frameSize, | ||
279 | * if a new AudioFormat instance is created. | ||
280 | * <p> | ||
281 | * This method isn't used in TSimpleFormatConversionProvider - it is solely there | ||
282 | * for inheriting classes. | ||
283 | */ | ||
284 | //$$fb 2000-08-16: moved from TEncodingFormatConversionProvider | ||
285 | protected AudioFormat replaceNotSpecified(AudioFormat sourceFormat, AudioFormat targetFormat) { | ||
286 | boolean bSetSampleSize=false; | ||
287 | boolean bSetChannels=false; | ||
288 | boolean bSetSampleRate=false; | ||
289 | boolean bSetFrameRate=false; | ||
290 | if (targetFormat.getSampleSizeInBits()==AudioSystem.NOT_SPECIFIED | ||
291 | && sourceFormat.getSampleSizeInBits()!=AudioSystem.NOT_SPECIFIED) { | ||
292 | bSetSampleSize=true; | ||
293 | } | ||
294 | if (targetFormat.getChannels()==AudioSystem.NOT_SPECIFIED | ||
295 | && sourceFormat.getChannels()!=AudioSystem.NOT_SPECIFIED) { | ||
296 | bSetChannels=true; | ||
297 | } | ||
298 | if (targetFormat.getSampleRate()==AudioSystem.NOT_SPECIFIED | ||
299 | && sourceFormat.getSampleRate()!=AudioSystem.NOT_SPECIFIED) { | ||
300 | bSetSampleRate=true; | ||
301 | } | ||
302 | if (targetFormat.getFrameRate()==AudioSystem.NOT_SPECIFIED | ||
303 | && sourceFormat.getFrameRate()!=AudioSystem.NOT_SPECIFIED) { | ||
304 | bSetFrameRate=true; | ||
305 | } | ||
306 | if (bSetSampleSize || bSetChannels || bSetSampleRate || bSetFrameRate | ||
307 | || (targetFormat.getFrameSize()==AudioSystem.NOT_SPECIFIED | ||
308 | && sourceFormat.getFrameSize()!=AudioSystem.NOT_SPECIFIED)) { | ||
309 | // create new format in place of the original target format | ||
310 | float sampleRate=bSetSampleRate? | ||
311 | sourceFormat.getSampleRate():targetFormat.getSampleRate(); | ||
312 | float frameRate=bSetFrameRate? | ||
313 | sourceFormat.getFrameRate():targetFormat.getFrameRate(); | ||
314 | int sampleSize=bSetSampleSize? | ||
315 | sourceFormat.getSampleSizeInBits():targetFormat.getSampleSizeInBits(); | ||
316 | int channels=bSetChannels? | ||
317 | sourceFormat.getChannels():targetFormat.getChannels(); | ||
318 | int frameSize=getFrameSize( | ||
319 | targetFormat.getEncoding(), | ||
320 | sampleRate, | ||
321 | sampleSize, | ||
322 | channels, | ||
323 | frameRate, | ||
324 | targetFormat.isBigEndian(), | ||
325 | targetFormat.getFrameSize()); | ||
326 | targetFormat= new AudioFormat( | ||
327 | targetFormat.getEncoding(), | ||
328 | sampleRate, | ||
329 | sampleSize, | ||
330 | channels, | ||
331 | frameSize, | ||
332 | frameRate, | ||
333 | targetFormat.isBigEndian()); | ||
334 | } | ||
335 | return targetFormat; | ||
336 | } | ||
337 | |||
338 | /** | ||
339 | * Calculates the frame size for the given format description. | ||
340 | * The default implementation returns AudioSystem.NOT_SPECIFIED | ||
341 | * if either <code>sampleSize</code> or <code>channels</code> is AudioSystem.NOT_SPECIFIED, | ||
342 | * otherwise <code>sampleSize*channels/8</code> is returned. | ||
343 | * <p> | ||
344 | * If this does not reflect the way to calculate the right frame size, | ||
345 | * inheriting classes should overwrite this method if they use | ||
346 | * replaceNotSpecified(...). It is not used elsewhere in this class. | ||
347 | */ | ||
348 | //$$fb 2000-08-16: added | ||
349 | protected int getFrameSize( | ||
350 | AudioFormat.Encoding encoding, | ||
351 | float sampleRate, | ||
352 | int sampleSize, | ||
353 | int channels, | ||
354 | float frameRate, | ||
355 | boolean bigEndian, | ||
356 | int oldFrameSize) { | ||
357 | if (sampleSize==AudioSystem.NOT_SPECIFIED || channels==AudioSystem.NOT_SPECIFIED) { | ||
358 | return AudioSystem.NOT_SPECIFIED; | ||
359 | } | ||
360 | return sampleSize*channels/8; | ||
361 | } | ||
362 | |||
363 | |||
364 | |||
365 | } | ||
366 | |||
367 | /*** TSimpleFormatConversionProvider.java ***/ | ||