Index: src/jpcsp/connector/AtracCodec.java =================================================================== --- src/jpcsp/connector/AtracCodec.java (revision 1736) +++ src/jpcsp/connector/AtracCodec.java (working copy) @@ -35,6 +35,14 @@ import org.apache.log4j.Logger; +import java.io.ByteArrayInputStream; +import com.xuggle.xuggler.IContainer; +import com.xuggle.xuggler.IStream; +import com.xuggle.xuggler.IStreamCoder; +import com.xuggle.xuggler.IAudioSamples; +import com.xuggle.xuggler.IPacket; +import com.xuggle.xuggler.IError; + /** * @author gid15 * @@ -54,8 +62,19 @@ protected static boolean commandFileDirty = true; public static int waveFactChunkHeader = 0x74636166; // "fact" public static int waveDataChunkHeader = 0x61746164; // "data" + + protected IContainer xcontainer; + protected IStreamCoder xuggleCoder; + protected IAudioSamples xsamples; + protected IPacket xpacket; + protected int xoffset, at3offset; + protected byte[] at3buf; public AtracCodec() { + xsamples = IAudioSamples.make(jpcsp.HLE.modules150.sceAtrac3plus.maxSamples, + 2, IAudioSamples.Format.FMT_S16); + at3offset=0; + xoffset=-1; atracDecodeBuffer = new byte[jpcsp.HLE.modules150.sceAtrac3plus.maxSamples * 4]; generateCommandFile(); } @@ -130,12 +149,45 @@ } public void atracSetData(int address, int length, int atracFileSize, boolean extract) { - id = generateID(address, length, atracFileSize); + System.err.printf("atracSetData %s %s %s %s", address, length, atracFileSize, extract); + + id = generateID(address, length, atracFileSize); closeStreams(); atracEndSample = -1; - + + { + IMemoryReader memoryReader = MemoryReader.getMemoryReader(address, length, 1); + at3buf = new byte[atracFileSize]; + ByteArrayInputStream at3stream = new ByteArrayInputStream(at3buf); + at3offset=0; + for (int i = 0; i < length; i++) { + at3buf[at3offset++]=(byte) memoryReader.readNext(); + } + xcontainer = IContainer.make(); + xcontainer.setInputBufferLength(1024*8); // Try to make ffmpeg not outrun us + xcontainer.open(at3stream, null); + System.err.println(xcontainer.getNumStreams()); + IStream xstream = xcontainer.getStream(0); + if (xstream != null) { + System.err.println("Yay, got a stream!"); + xuggleCoder = xstream.getStreamCoder(); + xuggleCoder.open(); + /* samples = IAudioSamples.make(xstream.getDuration(), + xuggleCoder.getChannels(), + xuggleCoder.getSampleFormat());*/ + atracEndSample = (int)xstream.getDuration(); + xpacket = IPacket.make(); + xoffset = -1; + System.err.println(xuggleCoder.getCodec()); + if (xuggleCoder != null) + return; + } + else + System.err.println("Aww, got no stream."); + } + File decodedFile = new File(getCompleteFileName(decodedAtracSuffix)); if (!decodedFile.canRead()) { @@ -201,19 +253,21 @@ } catch (FileNotFoundException e) { } catch (IOException e) { } - generateCommandFile(); - } + generateCommandFile(); + } } public void atracAddStreamData(int address, int length) { - if (atracStream != null) { + if (atracStream != null || at3buf != null) { try { byte[] buffer = new byte[length]; IMemoryReader memoryReader = MemoryReader.getMemoryReader(address, length, 1); for (int i = 0; i < length; i++) { buffer[i] = (byte) memoryReader.readNext(); + at3buf[at3offset++]=buffer[i]; } - atracStream.write(buffer); + if (atracStream != null) + atracStream.write(buffer); } catch (IOException e) { Modules.log.error(e); } @@ -222,7 +276,53 @@ public int atracDecodeData(int address) { int samples = 0; - if (decodedStream != null) { + if (xuggleCoder != null) { + int decoded=-1; + do { + if (xoffset < 0) { + int errno; + errno=xcontainer.readNextPacket(xpacket); + if (errno<0) { + IError err=IError.make(errno); + System.err.println(err); + if (err.getType()==IError.Type.ERROR_INTERRUPTED) { + System.err.println("interrupted"); + continue; + } + System.err.println("Packets stopped coming!"); + break; + } + System.err.println(xpacket); + if (xpacket.getStreamIndex()!=0) { + System.err.println("Alien packet! I don't have another channel!?"); + continue; + } + System.err.println("Got a packet."); + System.err.printf("AT3 write pos %d cont %s\n", + at3offset, xcontainer); + xoffset = 0; + } + decoded=xuggleCoder.decodeAudio(xsamples, xpacket, xoffset); + if (decoded<0) + throw new RuntimeException("Failed to decode audio"); + else + xoffset += decoded; + if (xoffset==xpacket.getSize()) + xoffset = -1; // time to fetch next packet + } while (!xsamples.isComplete()); + if (decoded>0) { + System.err.println("Decoded something.."); + System.err.println(xsamples.getNumSamples()); + System.err.println(jpcsp.HLE.modules150.sceAtrac3plus.maxSamples); + samples = (int)xsamples.getNumSamples(); + if (samples>jpcsp.HLE.modules150.sceAtrac3plus.maxSamples) + samples = jpcsp.HLE.modules150.sceAtrac3plus.maxSamples; + ByteBuffer buf=xsamples.getByteBuffer().slice(); + buf.limit(samples*4); + Memory.getInstance().copyToMemory(address, buf, samples*4); + } + } + else if (decodedStream != null) { try { int length = decodedStream.read(atracDecodeBuffer); if (length > 0) { @@ -243,6 +343,10 @@ } public void atracResetPlayPosition(int sample) { + if (xuggleCoder != null) { + xcontainer.seekKeyFrame(0, 0, IContainer.SEEK_FLAG_FRAME); + xoffset=-1; + } else if (decodedStream != null) { try { decodedStream.seek(sample * 4);