summaryrefslogtreecommitdiff
path: root/songdbj/org/tritonus/file/AiffAudioOutputStream.java
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2007-01-08 23:53:00 +0000
committerBjörn Stenberg <bjorn@haxx.se>2007-01-08 23:53:00 +0000
commit7039a05147b8bbfc829babea1c65bd436450b505 (patch)
tree4ba555eb84ed97b72b0575034d5b0530a393713e /songdbj/org/tritonus/file/AiffAudioOutputStream.java
parent6d4c19707ef95942e323cbdc89fbbfdbe45e7cc5 (diff)
downloadrockbox-7039a05147b8bbfc829babea1c65bd436450b505.tar.gz
rockbox-7039a05147b8bbfc829babea1c65bd436450b505.zip
Splitting out songdbj
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11953 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'songdbj/org/tritonus/file/AiffAudioOutputStream.java')
-rw-r--r--songdbj/org/tritonus/file/AiffAudioOutputStream.java205
1 files changed, 0 insertions, 205 deletions
diff --git a/songdbj/org/tritonus/file/AiffAudioOutputStream.java b/songdbj/org/tritonus/file/AiffAudioOutputStream.java
deleted file mode 100644
index d0006ebfe0..0000000000
--- a/songdbj/org/tritonus/file/AiffAudioOutputStream.java
+++ /dev/null
@@ -1,205 +0,0 @@
1/*
2 * AiffAudioOutputStream.java
3 *
4 * This file is part of Tritonus: http://www.tritonus.org/
5 */
6
7/*
8 * Copyright (c) 2000 by Florian Bomers <http://www.bomers.de>
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Library General Public License as published
13 * by the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * You should have received a copy of the GNU Library General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26
27/*
28|<--- this code is formatted to fit into 80 columns --->|
29*/
30
31package org.tritonus.sampled.file;
32
33import java.io.IOException;
34import javax.sound.sampled.AudioFormat;
35import javax.sound.sampled.AudioFileFormat;
36import javax.sound.sampled.AudioSystem;
37import org.tritonus.share.TDebug;
38import org.tritonus.share.sampled.file.TAudioOutputStream;
39import org.tritonus.share.sampled.file.TDataOutputStream;
40
41
42/**
43 * AudioOutputStream for AIFF and AIFF-C files.
44 *
45 * @author Florian Bomers
46 */
47public class AiffAudioOutputStream extends TAudioOutputStream {
48
49 // this constant is used for chunk lengths when the length is not known yet
50 private static final int LENGTH_NOT_KNOWN=-1;
51
52 private AudioFileFormat.Type m_FileType;
53
54 public AiffAudioOutputStream(AudioFormat audioFormat,
55 AudioFileFormat.Type fileType,
56 long lLength,
57 TDataOutputStream dataOutputStream) {
58 super(audioFormat,
59 lLength,
60 dataOutputStream,
61 lLength == AudioSystem.NOT_SPECIFIED
62 && dataOutputStream.supportsSeek());
63 // AIFF files cannot exceed 2GB
64 if (lLength != AudioSystem.NOT_SPECIFIED && lLength>0x7FFFFFFFl) {
65 throw new IllegalArgumentException(
66 "AIFF files cannot be larger than 2GB.");
67 }
68 // IDEA: write AIFF file instead of AIFC when encoding=PCM ?
69 m_FileType=fileType;
70 if (!audioFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)
71 && !audioFormat.getEncoding().equals(AudioFormat.Encoding.PCM_UNSIGNED)) {
72 // only AIFC files can handle non-pcm data
73 m_FileType=AudioFileFormat.Type.AIFC;
74 }
75 }
76
77 protected void writeHeader()
78 throws IOException {
79 if (TDebug.TraceAudioOutputStream) {
80 TDebug.out("AiffAudioOutputStream.writeHeader(): called.");
81 }
82 AudioFormat format = getFormat();
83 boolean bIsAifc = m_FileType.equals(AudioFileFormat.Type.AIFC);
84 long lLength = getLength();
85 TDataOutputStream dos = getDataOutputStream();
86 int nCommChunkSize=18;
87 int nFormatCode=AiffTool.getFormatCode(format);
88 if (bIsAifc) {
89 // encoding takes 4 bytes
90 // encoding name takes at minimum 2 bytes
91 nCommChunkSize+=6;
92 }
93 int nHeaderSize=4 // magic
94 +8+nCommChunkSize // COMM chunk
95 +8; // header of SSND chunk
96 if (bIsAifc) {
97 // add length for FVER chunk
98 nHeaderSize+=12;
99 }
100 // if patching the header, and the length has not been known at first
101 // writing of the header, just truncate the size fields, don't throw an exception
102 if (lLength != AudioSystem.NOT_SPECIFIED && lLength+nHeaderSize>0x7FFFFFFFl) {
103 lLength=0x7FFFFFFFl-nHeaderSize;
104 }
105 // chunks must be on word-boundaries
106 long lSSndChunkSize=(lLength!=AudioSystem.NOT_SPECIFIED)?
107 (lLength+(lLength%2)+8):AudioSystem.NOT_SPECIFIED;
108
109 // write IFF container chunk
110 dos.writeInt(AiffTool.AIFF_FORM_MAGIC);
111 dos.writeInt((lLength!=AudioSystem.NOT_SPECIFIED)?
112 ((int) (lSSndChunkSize+nHeaderSize)):LENGTH_NOT_KNOWN);
113 if (bIsAifc) {
114 dos.writeInt(AiffTool.AIFF_AIFC_MAGIC);
115 // write FVER chunk
116 dos.writeInt(AiffTool.AIFF_FVER_MAGIC);
117 dos.writeInt(4);
118 dos.writeInt(AiffTool.AIFF_FVER_TIME_STAMP);
119 } else {
120 dos.writeInt(AiffTool.AIFF_AIFF_MAGIC);
121 }
122
123 // write COMM chunk
124 dos.writeInt(AiffTool.AIFF_COMM_MAGIC);
125 dos.writeInt(nCommChunkSize);
126 dos.writeShort((short) format.getChannels());
127 dos.writeInt((lLength!=AudioSystem.NOT_SPECIFIED)?
128 ((int) (lLength / format.getFrameSize())):LENGTH_NOT_KNOWN);
129 if (nFormatCode==AiffTool.AIFF_COMM_ULAW) {
130 // AIFF ulaw states 16 bits for ulaw data
131 dos.writeShort(16);
132 } else {
133 dos.writeShort((short) format.getSampleSizeInBits());
134 }
135 writeIeeeExtended(dos, format.getSampleRate());
136 if (bIsAifc) {
137 dos.writeInt(nFormatCode);
138 dos.writeShort(0); // no encoding name
139 // TODO: write encoding.toString() ??
140 }
141
142 // write header of SSND chunk
143
144
145
146 dos.writeInt(AiffTool.AIFF_SSND_MAGIC);
147 // don't use lSSndChunkSize here !
148 dos.writeInt((lLength!=AudioSystem.NOT_SPECIFIED)
149 ?((int) (lLength+8)):LENGTH_NOT_KNOWN);
150 // 8 information bytes of no interest
151 dos.writeInt(0); // offset
152 dos.writeInt(0); // blocksize
153 }
154
155
156
157
158 protected void patchHeader()
159 throws IOException {
160 TDataOutputStream tdos = getDataOutputStream();
161 tdos.seek(0);
162 setLengthFromCalculatedLength();
163 writeHeader();
164 }
165
166 public void close() throws IOException {
167 long nBytesWritten=getCalculatedLength();
168
169 if ((nBytesWritten % 2)==1) {
170 if (TDebug.TraceAudioOutputStream) {
171 TDebug.out("AiffOutputStream.close(): adding padding byte");
172 }
173 // extra byte for to align on word boundaries
174 TDataOutputStream tdos = getDataOutputStream();
175 tdos.writeByte(0);
176 // DON'T adjust calculated length !
177 }
178
179
180
181 super.close();
182 }
183
184 public void writeIeeeExtended(TDataOutputStream dos, float sampleRate) throws IOException {
185 // currently, only integer sample rates are written
186 // TODO: real conversion
187 // I don't know exactly how much I have to shift left the mantisse for normalisation
188 // now I do it so that there are any bits set in the first 5 bits
189 int nSampleRate=(int) sampleRate;
190 short ieeeExponent=0;
191 while ((nSampleRate!=0) && (nSampleRate & 0x80000000)==0) {
192 ieeeExponent++;
193 nSampleRate<<=1;
194 }
195 dos.writeShort(16414-ieeeExponent); // exponent
196 dos.writeInt(nSampleRate); // mantisse high double word
197 dos.writeInt(0); // mantisse low double word
198 }
199
200
201
202
203}
204
205/*** AiffAudioOutputStream.java ***/