Fix two issues with streaming OGG/Vorbis

- In certain cases, padding was present at the end of streams causing noticeable clicking when looped. This is handled by truncating the stream to its actual size.
 - When playing an ogg stream without stream cache, an exception would be raised since the stream was closed prematurely
This commit is contained in:
shadowislord 2014-11-25 18:57:54 -05:00
parent 595eb56f9b
commit 9ce69eee62

View File

@ -63,15 +63,18 @@ public class OGGLoader implements AssetLoader {
private static class JOggInputStream extends InputStream { private static class JOggInputStream extends InputStream {
private boolean endOfStream = false; protected boolean endOfStream = false;
protected PhysicalOggStream ps; protected PhysicalOggStream ps;
protected LogicalOggStream ls; protected LogicalOggStream ls;
protected VorbisStream vs; protected VorbisStream vs;
protected int current = 0;
protected final int maximum;
public JOggInputStream(PhysicalOggStream ps, LogicalOggStream ls, VorbisStream vs){ public JOggInputStream(PhysicalOggStream ps, LogicalOggStream ls, VorbisStream vs, int maximum){
this.ps = ps; this.ps = ps;
this.ls = ls; this.ls = ls;
this.vs = vs; this.vs = vs;
this.maximum = maximum;
} }
@Override @Override
@ -94,25 +97,37 @@ public class OGGLoader implements AssetLoader {
assert length % 2 == 0; // read buffer should be even assert length % 2 == 0; // read buffer should be even
while (bytesRead < length) { while (bytesRead < length) {
if ((cnt = vs.readPcm(buf, offset + bytesRead, length - bytesRead)) <= 0) { try {
System.out.println("Read " + cnt + " bytes"); int toRead;
System.out.println("offset " + offset); if (maximum != -1) {
System.out.println("bytesRead " + bytesRead); if (current >= maximum) {
System.out.println("buf length " + length); endOfStream = true;
for (int i = 0; i < bytesRead; i++) { break;
System.out.print(buf[i]); }
int remainingInStream = maximum - current;
int remainingToBuffer = length - bytesRead;
toRead = Math.min(remainingInStream, remainingToBuffer);
} else {
toRead = length - bytesRead;
} }
System.out.println(""); if ((cnt = vs.readPcm(buf, offset + bytesRead, toRead)) <= 0) {
endOfStream = true;
System.out.println("EOS"); break;
}
} catch (EndOfOggStreamException ex) {
endOfStream = true; endOfStream = true;
break; break;
} }
bytesRead += cnt; bytesRead += cnt;
current += cnt;
} }
swapBytes(buf, offset, bytesRead); if (endOfStream && bytesRead <= 0) {
return bytesRead; return -1;
} else {
swapBytes(buf, offset, bytesRead);
return bytesRead;
}
} }
@Override @Override
@ -124,8 +139,8 @@ public class OGGLoader implements AssetLoader {
private static class SeekableJOggInputStream extends JOggInputStream implements SeekableStream { private static class SeekableJOggInputStream extends JOggInputStream implements SeekableStream {
public SeekableJOggInputStream(PhysicalOggStream ps, LogicalOggStream ls, VorbisStream vs){ public SeekableJOggInputStream(PhysicalOggStream ps, LogicalOggStream ls, VorbisStream vs, int maximum){
super(ps, ls, vs); super(ps, ls, vs, maximum);
} }
public void setTime(float time) { public void setTime(float time) {
@ -140,6 +155,8 @@ public class OGGLoader implements AssetLoader {
// an streaming OGG file via setTime(0). // an streaming OGG file via setTime(0).
ls = ((CachedOggStream) ps).reloadLogicalOggStream(); ls = ((CachedOggStream) ps).reloadLogicalOggStream();
vs = new VorbisStream(ls); vs = new VorbisStream(ls);
endOfStream = false;
current = 0;
} catch (IOException ex) { } catch (IOException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
@ -235,9 +252,10 @@ public class OGGLoader implements AssetLoader {
private InputStream readToStream(boolean seekable) { private InputStream readToStream(boolean seekable) {
if (seekable) { if (seekable) {
return new SeekableJOggInputStream(oggStream, loStream, vorbisStream); int maximum = getOggTotalBytes(Integer.MAX_VALUE);
return new SeekableJOggInputStream(oggStream, loStream, vorbisStream, maximum);
} else { } else {
return new JOggInputStream(oggStream, loStream, vorbisStream); return new JOggInputStream(oggStream, loStream, vorbisStream, -1);
} }
} }
@ -288,7 +306,12 @@ public class OGGLoader implements AssetLoader {
InputStream in = null; InputStream in = null;
try { try {
in = info.openStream(); in = info.openStream();
return load(in, readStream, streamCache); AudioData data = load(in, readStream, streamCache);
if (readStream && !streamCache) {
// we still need the stream in this case ..
in = null;
}
return data;
} finally { } finally {
if (in != null){ if (in != null){
in.close(); in.close();