Skip to content

Commit f4f5b4d

Browse files
author
David Foerster
committed
v0.3.1
0 parents commit f4f5b4d

37 files changed

+8786
-0
lines changed

COPYING

Lines changed: 502 additions & 0 deletions
Large diffs are not rendered by default.

README

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright (C) 2010 Preston Lacey http://javaflacencoder.sourceforge.net/
3+
* All Rights Reserved.
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 2.1 of the License, or (at your option) any later version.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
The javaFlacEncoder project provides a FLAC encoder implemented in java.
21+
It is designed to enable easy addition of FLAC encoding support in java
22+
applications, though a command line file encoding utility is included as well.
23+
For usage of the command line encoder, see the "Console Usage" section below.
24+
25+
For more information, go to http://javaflacencoder.sourceforge.net.
26+
See javadocs for information on how to make use of this library in your own
27+
application.
28+
29+
30+
31+
Console Usage:
32+
<commandName> [options] inputFilename outputFilename
33+
note: <commandName> will depend on how your version is packaged, if it's
34+
in a tar file, it will be similar to
35+
java -classpath <path/to/file.jar> javaFlacEncoder/FLAC_ConsoleFileEncoder
36+
37+
options:
38+
-bmin <x> minimum block size, where <x> is an integer in range (16-65535)
39+
-bmax <x> maximum block size, where <x> is an integer in range (16-65535)
40+
-lpcmin <x> minimum LPC order, where <x> is an integer in range (1-32)
41+
-lpcmax <x> maximum LPC order, where <x> is an integer in range (1-32)
42+
-Threads <x> Specify whether to use threads. 0 turns threading off, greater
43+
than 0 turns threading on
44+
-sf <type> Specify which subframe type to use, where <type> may be:
45+
exhaustive(this is default and recommended)
46+
fixed
47+
lpc
48+
verbatim;
49+
50+
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (C) 2010 Preston Lacey http://javaflacencoder.sourceforge.net/
3+
* All Rights Reserved.
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 2.1 of the License, or (at your option) any later version.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package javaFlacEncoder;
21+
22+
import java.util.concurrent.LinkedBlockingQueue;
23+
24+
/**
25+
* The purpose of this class is to provide a source for reusable int arrays.
26+
* When using large numbers of arrays in succession, it is inefficient to
27+
* constantly go in an allocate/free loop. This way, we may pass a single,
28+
* thread-safe recycler to all objects. No matter where the arrays end their
29+
* life, we can then add it to the same resource store.
30+
*
31+
* @author Preston Lacey
32+
*/
33+
public class ArrayRecycler {
34+
LinkedBlockingQueue<int[]> usedIntArrays = null;
35+
36+
ArrayRecycler() {
37+
usedIntArrays = new LinkedBlockingQueue<int[]>();
38+
}
39+
40+
public void add(int[] array) {
41+
usedIntArrays.add(array);
42+
}
43+
44+
/**
45+
*
46+
* @param size
47+
* @return
48+
*/
49+
public int[] getArray(int size) {
50+
int[] result = usedIntArrays.poll();
51+
if(result == null) {
52+
result = new int[size];
53+
}
54+
else if(result.length < size) {
55+
usedIntArrays.offer(result);
56+
result = new int[size];
57+
}
58+
return result;
59+
}
60+
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
* Copyright (C) 2010 Preston Lacey http://javaflacencoder.sourceforge.net/
3+
* All Rights Reserved.
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 2.1 of the License, or (at your option) any later version.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package javaFlacEncoder;
21+
import javax.sound.sampled.AudioInputStream;
22+
import javax.sound.sampled.AudioFormat;
23+
import javax.sound.sampled.AudioSystem;
24+
import java.io.IOException;
25+
26+
/**
27+
* AudioStreamEncoder provides commonly needed methods for encoding with a
28+
* FLACEncoder from an AudioInputStream.
29+
*
30+
* @author preston
31+
*/
32+
public class AudioStreamEncoder {
33+
34+
public static final int SUPPORTED = 0;
35+
public static final int UNSUPPORTED_CHANNELCOUNT = 1;
36+
public static final int UNSUPPORTED_SAMPLESIZE = 2;
37+
public static final int UNSUPPORTED_SAMPLERATE = 4;
38+
public static final int UNSUPPORTED_ENCODINGTYPE = 8;
39+
40+
/**
41+
* Encodes the given AudioInputStream, using the given FLACEncoder.
42+
* FLACEncoder must be in a state to accept samples and encode(FLACOutputStream,
43+
* EncodingConfiguration, and StreamConfiguration have been set, and FLAC stream
44+
* has been opened).
45+
* @param sin
46+
* @return
47+
* @throws IOException
48+
* @throws IllegalArgumentException thrown if input sample size is not supported
49+
*/
50+
public static int encodeAudioInputStream(AudioInputStream sin, int maxRead,
51+
FLACEncoder flac, boolean useThreads) throws IOException, IllegalArgumentException {
52+
AudioFormat format = sin.getFormat();
53+
int frameSize = format.getFrameSize();
54+
int sampleSize = format.getSampleSizeInBits();
55+
int bytesPerSample = sampleSize/8;
56+
if(sampleSize %8 != 0) {
57+
//end processing now
58+
throw new IllegalArgumentException("Unsupported Sample Size: size = "+sampleSize);
59+
}
60+
int channels = format.getChannels();
61+
boolean bigEndian = format.isBigEndian();
62+
boolean isSigned = format.getEncoding() == AudioFormat.Encoding.PCM_SIGNED;
63+
byte[] samplesIn = new byte[(int)maxRead];
64+
int samplesRead;
65+
int framesRead;
66+
int[] sampleData = new int[maxRead*channels/frameSize];
67+
int unencodedSamples = 0;
68+
int totalSamples = 0;
69+
while((samplesRead = sin.read(samplesIn, 0, maxRead)) > 0 ) {
70+
framesRead = samplesRead/(frameSize);
71+
if(bigEndian) {
72+
for(int i = 0; i < framesRead*channels; i++) {
73+
int lower8Mask = 255;
74+
int temp = 0;
75+
int totalTemp = 0;
76+
for(int x = bytesPerSample-1; x >= 0; x++) {
77+
int upShift = 8*x;
78+
if(x == 0)//don't mask...we want sign
79+
temp = ((samplesIn[bytesPerSample*i+x]) << upShift);
80+
else
81+
temp = ((samplesIn[bytesPerSample*i+x] & lower8Mask) << upShift);
82+
totalTemp = totalTemp | temp;
83+
}
84+
if(!isSigned) {
85+
int reducer = 1 << (bytesPerSample*8-1);
86+
totalTemp -= reducer;
87+
}
88+
sampleData[i] = totalTemp;
89+
}
90+
}
91+
else {
92+
for(int i = 0; i < framesRead*channels; i++) {
93+
int lower8Mask = 255;
94+
int temp = 0;
95+
int totalTemp = 0;
96+
for(int x = 0; x < bytesPerSample; x++) {
97+
int upShift = 8*x;
98+
if(x == bytesPerSample-1 && isSigned)//don't mask...we want sign
99+
temp = ((samplesIn[bytesPerSample*i+x]) << upShift);
100+
else
101+
temp = ((samplesIn[bytesPerSample*i+x] & lower8Mask) << upShift);
102+
totalTemp = totalTemp | temp;
103+
}
104+
if(!isSigned) {
105+
int reducer = 1 << (bytesPerSample*8-1);
106+
totalTemp -= reducer;
107+
}
108+
sampleData[i] = totalTemp;
109+
}
110+
}
111+
if(framesRead > 0) {
112+
flac.addSamples(sampleData, framesRead);
113+
unencodedSamples += framesRead;
114+
}
115+
116+
if(useThreads)
117+
unencodedSamples -= flac.t_encodeSamples(unencodedSamples, false, 5);
118+
else
119+
unencodedSamples -= flac.encodeSamples(unencodedSamples, false);
120+
totalSamples += unencodedSamples;
121+
}
122+
totalSamples += unencodedSamples;
123+
if(useThreads)
124+
unencodedSamples -= flac.t_encodeSamples(unencodedSamples, true, 5);
125+
else
126+
unencodedSamples -= flac.encodeSamples(unencodedSamples, true);
127+
return totalSamples;
128+
}
129+
130+
/**
131+
* Checks whether the given AudioFormat can be properly encoded by this
132+
* FLAC library.
133+
* @param format AudioFormat to test for support.
134+
* @return Bit positions set according to issue:
135+
* Bit Position : Problem-area
136+
* 0 : Channel count unsupported
137+
* 1 : Sample size unsupported
138+
* 2 : Sample Rate unsupported
139+
* 3 : Encoding Type Unsupported
140+
* 4-7: unused, always zero.
141+
* return value of 0 means supported
142+
*/
143+
public static int getDataFormatSupport(AudioFormat format) {
144+
int result = SUPPORTED;
145+
float sampleRate = format.getSampleRate();
146+
AudioFormat.Encoding encoding = format.getEncoding();
147+
if(format.getChannels() > 8 || format.getChannels() < 1)
148+
result |= UNSUPPORTED_CHANNELCOUNT;
149+
if(format.getSampleSizeInBits() > 24 || format.getSampleSizeInBits()%8 != 0)
150+
result |= UNSUPPORTED_SAMPLESIZE;
151+
if(sampleRate <= 0 || sampleRate > 655350 || sampleRate == AudioSystem.NOT_SPECIFIED)
152+
result |= UNSUPPORTED_SAMPLERATE;
153+
if ( !(AudioFormat.Encoding.ALAW.equals(encoding) ||
154+
AudioFormat.Encoding.ULAW.equals(encoding) ||
155+
AudioFormat.Encoding.PCM_SIGNED.equals(encoding) ||
156+
AudioFormat.Encoding.PCM_UNSIGNED.equals(encoding) ) )
157+
result |= UNSUPPORTED_ENCODINGTYPE;
158+
return result;
159+
}
160+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright (C) 2010 Preston Lacey http://javaflacencoder.sourceforge.net/
3+
* All Rights Reserved.
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 2.1 of the License, or (at your option) any later version.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package javaFlacEncoder;
21+
/**
22+
* BlockEncodeRequests are used to store a full block and necessary information
23+
* to encode such block. It is assumed member variables will be accessed
24+
* directly(for speed considerations). This Class simply gathers all values
25+
* into a single object, but handles no encoding logic itself.
26+
* @author Preston Lacey
27+
*/
28+
public class BlockEncodeRequest {
29+
/* Sample data, may be interleaved if multiple channels exist.*/
30+
volatile int[] samples;
31+
/* Number of valid samples in this request */
32+
volatile int count;
33+
/* Index of samples[] where the first valid sample exists */
34+
volatile int start;
35+
/* Number of indices to skip between valid samples */
36+
volatile int skip;
37+
/* Frame-number this block is assigned */
38+
volatile long frameNumber;
39+
/* Location to store results to. For safety, use an empty element*/
40+
volatile EncodedElement result;
41+
/* Stores whether the result should be valid */
42+
volatile boolean valid;
43+
/* Number of elements actually encoded. */
44+
volatile int encodedSamples;
45+
46+
/**
47+
* Set all values, preparing this object to be sent to an encoder. Member
48+
* variable "valid" is set to false by this call.
49+
*
50+
* @param samples Sample data, interleaved if multiple channels are used
51+
* @param count Number of valid samples
52+
* @param start Index of first valid sample
53+
* @param skip Number of samples to skip between samples(this should be
54+
* equal to number-of-channels minus 1.
55+
* @param frameNumber Framenumber assigned to this block.
56+
* @param result Location to store result of encode.
57+
*/
58+
public void setAll(int[] samples, int count, int start, int skip,
59+
long frameNumber, EncodedElement result) {
60+
// assert(start == 0);
61+
this.samples = samples;
62+
this.count = count;
63+
this.start = start;
64+
this.skip = skip;
65+
this.frameNumber = frameNumber;
66+
this.result = result;
67+
valid = false;
68+
this.encodedSamples = 0;
69+
}
70+
71+
public int addInterleavedSamples(int[] newSamples, int offset, int addCount, int max) {
72+
//System.err.println("offset:addCount:max :: " +offset+":"+addCount+":"+max);
73+
assert(max <= this.samples.length/(this.skip+1));
74+
if(max > this.samples.length)
75+
max = this.samples.length/(skip+1);
76+
77+
int remaining = count;
78+
int spaceLeft = max - count;
79+
int toEncode = (addCount < spaceLeft) ? addCount:spaceLeft;
80+
remaining = addCount-toEncode;
81+
82+
int[] src = newSamples;
83+
int[] dest = samples;
84+
int destPos = count*(skip+1);
85+
int srcPos = offset;
86+
int length = toEncode*(skip+1);
87+
System.arraycopy(src, srcPos, dest, destPos, length);
88+
89+
this.count = count+toEncode;
90+
return remaining;
91+
}
92+
93+
public boolean isFull(int max) {
94+
boolean full = false;
95+
if(this.count >= max)
96+
full = true;
97+
return full;
98+
}
99+
}

0 commit comments

Comments
 (0)