Source code: com/anotherbigidea/flash/sound/RawHelper.java
1 /****************************************************************
2 * Copyright (c) 2001, David N. Main, All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the
6 * following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
16 *
17 * 3. The name of the author may not be used to endorse or
18 * promote products derived from this software without specific
19 * prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 ****************************************************************/
34 package com.anotherbigidea.flash.sound;
35
36 import java.io.*;
37 import java.util.*;
38 import com.anotherbigidea.io.*;
39 import com.anotherbigidea.flash.*;
40 import com.anotherbigidea.flash.movie.*;
41 import com.anotherbigidea.flash.structs.*;
42 import com.anotherbigidea.flash.interfaces.*;
43 import com.anotherbigidea.flash.writers.*;
44 import javax.sound.sampled.*;
45
46 /**
47 * Raw Audio Utilities
48 */
49 public class RawHelper
50 {
51 /**
52 * Read an audio input file that is supported by the Java Sound API
53 * @param soundBlocks used to return the sound blocks (byte[]) - can be null
54 */
55 public static SoundStreamHead streamingBlocks( InputStream audioFile,
56 int framesPerSecond,
57 ArrayList soundBlocks )
58 throws IOException, UnsupportedAudioFileException
59 {
60 AudioInputStream audioIn = AudioSystem.getAudioInputStream( audioFile );
61 //audioIn = AudioSystem.getAudioInputStream( format, audioIn );
62
63 AudioFormat format = audioIn.getFormat();
64 int frameSize = format.getFrameSize();
65 boolean isStereo = format.getChannels() == 2;
66 boolean is16Bit = format.getSampleSizeInBits() > 8;
67 int sampleRate = (int)format.getSampleRate();
68
69 //System.out.println( format );
70
71 int rate = SWFConstants.SOUND_FREQ_5_5KHZ;
72
73 if ( sampleRate >= 44000 ) sampleRate = 44000;
74 else if( sampleRate >= 22000 ) sampleRate = 22000;
75 else if( sampleRate >= 11000 ) sampleRate = 11000;
76 else sampleRate = 5500;
77
78 if ( sampleRate == 44000 ) rate = SWFConstants.SOUND_FREQ_44KHZ;
79 else if( sampleRate == 22000 ) rate = SWFConstants.SOUND_FREQ_22KHZ;
80 else if( sampleRate == 11000 ) rate = SWFConstants.SOUND_FREQ_11KHZ;
81
82 int samplesPerFrame = sampleRate / framesPerSecond;
83 int blockSize = samplesPerFrame * (is16Bit ? 2 : 1 ) * (isStereo ? 2 : 1 );
84
85 SoundStreamHead soundHead = new SoundStreamHead( rate, is16Bit, isStereo,
86 SWFConstants.SOUND_FORMAT_RAW,
87 rate, is16Bit, isStereo,
88 samplesPerFrame );
89
90 if( soundBlocks == null ) return soundHead;
91
92 ByteArrayOutputStream bout = new ByteArrayOutputStream( blockSize + 1000 );
93
94 while( true )
95 {
96 bout.reset();
97
98 byte[] b = new byte[ frameSize ];
99 int num = 0;
100 int read = 0;
101
102 while( num < blockSize )
103 {
104 read = 0;
105
106 while( (read = audioIn.read( b, read, frameSize-read )) < frameSize && read != -1 );
107
108 if( read == -1 ) break;
109
110 bout.write( b );
111 num += read;
112 }
113
114 //pad the block with zeroes
115 while( num < blockSize )
116 {
117 bout.write(0x80);
118 num++;
119 }
120
121 soundBlocks.add( bout.toByteArray() );
122
123 if( read == -1 ) break;
124 }
125
126 return soundHead;
127 }
128
129 public static Sound getSoundDefinition( InputStream audioFile, int framesPerSecond)
130 throws IOException, UnsupportedAudioFileException
131 {
132 AudioInputStream audioIn = AudioSystem.getAudioInputStream( new BufferedInputStream( audioFile ));
133 //audioIn = AudioSystem.getAudioInputStream( format, audioIn );
134
135 AudioFormat format = audioIn.getFormat();
136 int frameSize = format.getFrameSize();
137 boolean isStereo = format.getChannels() == 2;
138 boolean is16bit = format.getSampleSizeInBits() > 8;
139 int sampleRate = (int)format.getSampleRate();
140
141 //System.out.println( format );
142
143 int rate = SWFConstants.SOUND_FREQ_5_5KHZ;
144
145 if ( sampleRate >= 44000 ) sampleRate = 44000;
146 else if( sampleRate >= 22000 ) sampleRate = 22000;
147 else if( sampleRate >= 11000 ) sampleRate = 11000;
148 else sampleRate = 5500;
149
150 if ( sampleRate == 44000 ) rate = SWFConstants.SOUND_FREQ_44KHZ;
151 else if( sampleRate == 22000 ) rate = SWFConstants.SOUND_FREQ_22KHZ;
152 else if( sampleRate == 11000 ) rate = SWFConstants.SOUND_FREQ_11KHZ;
153
154 ByteArrayOutputStream bout = new ByteArrayOutputStream();
155 ADPCMHelper.FramedInputStream in = new ADPCMHelper.FramedInputStream( audioIn, frameSize );
156 int b = 0;
157 int count = 0;
158
159 while( (b = in.read()) >= 0 )
160 {
161 count++;
162 bout.write( b );
163 }
164
165 int sampleCount = count;
166 if( is16bit ) sampleCount /= 2;
167 if( isStereo ) sampleCount /= 2;
168
169 byte[] soundData = bout.toByteArray();
170 return new Sound( SWFConstants.SOUND_FORMAT_RAW, rate, is16bit, isStereo, sampleCount, soundData );
171 }
172
173 /**
174 * Makes a streaming SWF from a Java Sound compatible audio file.
175 * args[0] = audio in filename
176 * args[1] = SWF out filename
177 */
178 public static void main( String[] args ) throws Exception
179 {
180 InputStream audioFile = new BufferedInputStream( new FileInputStream( args[0] ));
181 SWFWriter swfwriter = new SWFWriter( args[1] );
182
183 SWFTagTypes tags = new TagWriter( swfwriter );
184
185 tags.header( 5, -1, 200, 200, 12, -1 );
186 tags.tagSetBackgroundColor( new Color(255,255,255));
187
188 ArrayList blocks = new ArrayList();
189
190 SoundStreamHead header = streamingBlocks( audioFile, 12, blocks );
191 audioFile.close();
192
193 header.write( tags );
194
195 for( Iterator it = blocks.iterator(); it.hasNext(); )
196 {
197 byte[] data = (byte[])it.next();
198
199 tags.tagSoundStreamBlock( data );
200 tags.tagShowFrame();
201 }
202
203 tags.tagEnd();
204 }
205 }