Skip to content

Commit 8d0edbb

Browse files
authored
Merge pull request #2 from sahaRatul/difference-coding-implmentation
Difference coding implemented
2 parents f892eab + 6f5a42a commit 8d0edbb

File tree

4 files changed

+130
-36
lines changed

4 files changed

+130
-36
lines changed

src/main/java/org/sela/data/SelaFile.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ private void read(final ByteBuffer buffer) throws FileException {
7878
for (int j = 0; j < channels; j++) {
7979
// Get channel
8080
final byte subFrameChannel = buffer.get();
81+
final byte subFrameType = buffer.get();
82+
final byte parentChannelNumber = buffer.get();
8183

8284
// Get Reflection data
8385
final byte reflectionCoefficientRiceParam = buffer.get();
@@ -103,7 +105,8 @@ private void read(final ByteBuffer buffer) throws FileException {
103105
optimumLpcOrder, encodedReflectionCoefficients);
104106
final RiceEncodedData residueData = new RiceEncodedData(residueRiceParam, samplesPerChannel,
105107
encodedResidues);
106-
final SubFrame subFrame = new SubFrame(subFrameChannel, reflectionData, residueData);
108+
final SubFrame subFrame = new SubFrame(subFrameChannel, subFrameType, parentChannelNumber,
109+
reflectionData, residueData);
107110
frame.subFrames.add(subFrame);
108111
}
109112
frames.add(frame);

src/main/java/org/sela/data/SubFrame.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
public final class SubFrame {
66
// Audio Channel number - 1, 2, etc
77
public byte channel;
8+
// 0 - Subframe is independent, 1 - SubFrame uses difference coding and is
9+
// dependent on another channel
10+
public byte subFrameType;
11+
// Incase subFrame uses difference coding, the channel from which difference is
12+
// generated will be stored here
13+
public byte parentChannelNumber;
814

915
// Reflection coefficient data
1016
public byte reflectionCoefficientRiceParam;
@@ -18,9 +24,12 @@ public final class SubFrame {
1824
public short samplesPerChannel;
1925
public int[] encodedResidues;
2026

21-
public SubFrame(final byte channel, final RiceEncodedData reflectionData, final RiceEncodedData residueData) {
27+
public SubFrame(final byte channel, final byte subFrameType, final byte parentChannelNumber,
28+
final RiceEncodedData reflectionData, final RiceEncodedData residueData) {
2229
this.channel = channel;
23-
30+
this.subFrameType = subFrameType;
31+
this.parentChannelNumber = parentChannelNumber;
32+
2433
this.reflectionCoefficientRiceParam = (byte) reflectionData.optimumRiceParam;
2534
this.reflectionCoefficientRequiredInts = (short) reflectionData.encodedData.length;
2635
this.optimumLpcOrder = (byte) reflectionData.dataCount;
@@ -33,11 +42,13 @@ public SubFrame(final byte channel, final RiceEncodedData reflectionData, final
3342
}
3443

3544
public int getByteCount() {
36-
return 10 + (4 * (encodedReflectionCoefficients.length + encodedResidues.length));
45+
return 12 + (4 * (encodedReflectionCoefficients.length + encodedResidues.length));
3746
}
3847

3948
public void write(final ByteBuffer buffer) {
4049
buffer.put(channel);
50+
buffer.put(subFrameType);
51+
buffer.put(parentChannelNumber);
4152

4253
buffer.put(reflectionCoefficientRiceParam);
4354
buffer.putShort(reflectionCoefficientRequiredInts);

src/main/java/org/sela/frame/FrameDecoder.java

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,58 @@ public FrameDecoder(final Frame frame) {
1414
public WavFrame process() {
1515
final int[][] samples = new int[frame.subFrames.size()][];
1616

17-
// Foreach subFrame
17+
// Foreach independent subFrame
1818
for (final SubFrame subFrame : frame.subFrames) {
19-
// Stage 1 - Extract data from subFrame
20-
final byte channel = subFrame.channel;
21-
final byte optimumLpcOrder = subFrame.optimumLpcOrder;
22-
final RiceEncodedData reflectionData = new RiceEncodedData(subFrame.reflectionCoefficientRiceParam,
23-
subFrame.optimumLpcOrder, subFrame.encodedReflectionCoefficients);
24-
final RiceEncodedData residueData = new RiceEncodedData(subFrame.residueRiceParam,
25-
subFrame.samplesPerChannel, subFrame.encodedResidues);
26-
27-
// Stage 2 - Decompress data
28-
final RiceDecodedData decodedReflectionData = (new RiceDecoder(reflectionData)).process();
29-
final RiceDecodedData decodedResidueData = (new RiceDecoder(residueData)).process();
30-
31-
// Stage 3 - Generate Samples
32-
final LpcEncodedData encodedData = new LpcEncodedData(optimumLpcOrder, decodedReflectionData.decodedData,
33-
decodedResidueData.decodedData);
34-
final LpcDecodedData decoded = (new SampleGenerator(encodedData)).process();
35-
samples[channel] = decoded.samples;
19+
if (subFrame.subFrameType == 0) {
20+
// Stage 1 - Extract data from subFrame
21+
final byte channel = subFrame.channel;
22+
final byte optimumLpcOrder = subFrame.optimumLpcOrder;
23+
final RiceEncodedData reflectionData = new RiceEncodedData(subFrame.reflectionCoefficientRiceParam,
24+
subFrame.optimumLpcOrder, subFrame.encodedReflectionCoefficients);
25+
final RiceEncodedData residueData = new RiceEncodedData(subFrame.residueRiceParam,
26+
subFrame.samplesPerChannel, subFrame.encodedResidues);
27+
28+
// Stage 2 - Decompress data
29+
final RiceDecodedData decodedReflectionData = (new RiceDecoder(reflectionData)).process();
30+
final RiceDecodedData decodedResidueData = (new RiceDecoder(residueData)).process();
31+
32+
// Stage 3 - Generate Samples
33+
final LpcEncodedData encodedData = new LpcEncodedData(optimumLpcOrder,
34+
decodedReflectionData.decodedData, decodedResidueData.decodedData);
35+
final LpcDecodedData decoded = (new SampleGenerator(encodedData)).process();
36+
samples[channel] = decoded.samples;
37+
}
38+
}
39+
40+
// Foreach dependent subFrame
41+
for (final SubFrame subFrame : frame.subFrames) {
42+
if (subFrame.subFrameType == 1) {
43+
// Stage 1 - Extract data from subFrame
44+
final byte channel = subFrame.channel;
45+
final byte parentChannelNumber = subFrame.parentChannelNumber;
46+
final byte optimumLpcOrder = subFrame.optimumLpcOrder;
47+
final RiceEncodedData reflectionData = new RiceEncodedData(subFrame.reflectionCoefficientRiceParam,
48+
subFrame.optimumLpcOrder, subFrame.encodedReflectionCoefficients);
49+
final RiceEncodedData residueData = new RiceEncodedData(subFrame.residueRiceParam,
50+
subFrame.samplesPerChannel, subFrame.encodedResidues);
51+
52+
// Stage 2 - Decompress data
53+
final RiceDecodedData decodedReflectionData = (new RiceDecoder(reflectionData)).process();
54+
final RiceDecodedData decodedResidueData = (new RiceDecoder(residueData)).process();
55+
56+
// Stage 3 - Generate Difference signal
57+
final LpcEncodedData encodedData = new LpcEncodedData(optimumLpcOrder,
58+
decodedReflectionData.decodedData, decodedResidueData.decodedData);
59+
final LpcDecodedData difference = (new SampleGenerator(encodedData)).process();
60+
61+
int[] decoded = new int[difference.samples.length];
62+
63+
//Stage 4 Generate samples
64+
for (int i = 0; i < decoded.length; i++) {
65+
decoded[i] = samples[parentChannelNumber][i] - difference.samples[i];
66+
}
67+
samples[channel] = decoded;
68+
}
3669
}
3770
return new WavFrame(frame.getIndex(), samples);
3871
}

src/main/java/org/sela/frame/FrameEncoder.java

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,67 @@ public Frame process() {
1818

1919
// Foreach channel
2020
for (byte i = 0; i < wavFrame.samples.length; i++) {
21-
// Stage 1 - Generate residues and reflection coefficients
22-
final ResidueGenerator residueGenerator = new ResidueGenerator(new LpcDecodedData(wavFrame.samples[i]));
23-
final LpcEncodedData residues = residueGenerator.process();
24-
25-
// Stage 2 - Compress residues and reflection coefficients
26-
final RiceEncoder reflectionRiceEncoder = new RiceEncoder(
27-
new RiceDecodedData(residues.quantizedReflectionCoefficients));
28-
final RiceEncoder residueRiceEncoder = new RiceEncoder(new RiceDecodedData(residues.residues));
29-
final RiceEncodedData reflectionData = reflectionRiceEncoder.process();
30-
final RiceEncodedData residueData = residueRiceEncoder.process();
31-
32-
// Stage 3 - Generate Subframes
33-
final SubFrame subFrame = new SubFrame(i, reflectionData, residueData);
34-
subFrames.add(subFrame);
21+
if (i == 1 && ((i + 1) == wavFrame.samples.length)) {
22+
// Stage 1 - Generate difference signal
23+
int[] differenceSignal = new int[wavFrame.samples[i].length];
24+
for (int j = 0; j < differenceSignal.length; j++) {
25+
differenceSignal[j] = wavFrame.samples[i - 1][j] - wavFrame.samples[i][j];
26+
}
27+
28+
// Stage 2 - Generate residues and reflection coefficients for difference as
29+
// well as actual signal
30+
final ResidueGenerator residueGeneratorDifference = new ResidueGenerator(
31+
new LpcDecodedData(differenceSignal));
32+
final LpcEncodedData residuesDifference = residueGeneratorDifference.process();
33+
34+
final ResidueGenerator residueGeneratorActual = new ResidueGenerator(
35+
new LpcDecodedData(wavFrame.samples[i]));
36+
final LpcEncodedData residuesActual = residueGeneratorActual.process();
37+
38+
// Stage 3 - Compress residues and reflection coefficients for difference and
39+
// actual signal
40+
final RiceEncoder reflectionRiceEncoderDifference = new RiceEncoder(
41+
new RiceDecodedData(residuesDifference.quantizedReflectionCoefficients));
42+
final RiceEncoder residueRiceEncoderDifference = new RiceEncoder(
43+
new RiceDecodedData(residuesDifference.residues));
44+
final RiceEncodedData reflectionDataDifference = reflectionRiceEncoderDifference.process();
45+
final RiceEncodedData residueDataDifference = residueRiceEncoderDifference.process();
46+
47+
final RiceEncoder reflectionRiceEncoderActual = new RiceEncoder(
48+
new RiceDecodedData(residuesActual.quantizedReflectionCoefficients));
49+
final RiceEncoder residueRiceEncoderActual = new RiceEncoder(
50+
new RiceDecodedData(residuesActual.residues));
51+
final RiceEncodedData reflectionDataActual = reflectionRiceEncoderActual.process();
52+
final RiceEncodedData residueDataActual = residueRiceEncoderActual.process();
53+
54+
// Stage 4 - Compare sizes of both types and generate subFrame
55+
int differenceDataSize = reflectionDataDifference.encodedData.length
56+
+ residueDataDifference.encodedData.length;
57+
int actualDataSize = reflectionDataActual.encodedData.length + residueDataActual.encodedData.length;
58+
if (differenceDataSize < actualDataSize) {
59+
final SubFrame subFrame = new SubFrame(i, (byte) 1, (byte) (i - 1), reflectionDataDifference,
60+
residueDataDifference);
61+
subFrames.add(subFrame);
62+
} else {
63+
final SubFrame subFrame = new SubFrame(i, (byte) 0, i, reflectionDataActual, residueDataActual);
64+
subFrames.add(subFrame);
65+
}
66+
} else {
67+
// Stage 1 - Generate residues and reflection coefficients
68+
final ResidueGenerator residueGenerator = new ResidueGenerator(new LpcDecodedData(wavFrame.samples[i]));
69+
final LpcEncodedData residues = residueGenerator.process();
70+
71+
// Stage 2 - Compress residues and reflection coefficients
72+
final RiceEncoder reflectionRiceEncoder = new RiceEncoder(
73+
new RiceDecodedData(residues.quantizedReflectionCoefficients));
74+
final RiceEncoder residueRiceEncoder = new RiceEncoder(new RiceDecodedData(residues.residues));
75+
final RiceEncodedData reflectionData = reflectionRiceEncoder.process();
76+
final RiceEncodedData residueData = residueRiceEncoder.process();
77+
78+
// Stage 3 - Generate Subframes
79+
final SubFrame subFrame = new SubFrame(i, (byte) 0, i, reflectionData, residueData);
80+
subFrames.add(subFrame);
81+
}
3582
}
3683

3784
return new Frame(subFrames, wavFrame.getIndex());

0 commit comments

Comments
 (0)