예제 #1
0
  public int atracDecodeData(int atracID, int address, int channels) {
    int samples = 0;
    boolean isEnded = false;

    if (checkMediaEngineState()) {
      if (me.getContainer() == null && atracChannel != null) {
        if (requireAllAtracData) {
          if (atracChannel.length() >= atracFileSize) {
            requireAllAtracData = false;
            if (checkMediaEngineState() && ExternalDecoder.isEnabled()) {
              String decodedFile =
                  externalDecoder.decodeAtrac(
                      atracChannel, atracBufferAddress, atracFileSize, atracHash);
              if (decodedFile != null) {
                Modules.log.info(
                    "AT3+ data decoded by the external decoder (all AT3+ data retrieved).");
                me.finish();
                atracChannel = null;
                me.init(new FileProtocolHandler(decodedFile), false, true, 0, 0);
                atracEndSample = -1;
              } else {
                Modules.log.info(
                    "AT3+ data could not be decoded by the external decoder, even after retrieving all AT3+ data.");
                me = null;
              }
            } else {
              Modules.log.info(
                  "AT3+ data could not be decoded by the external decoder, even after retrieving all AT3+ data.");
              me = null;
            }
            if (me == null) {
              return atracDecodeData(atracID, address, channels);
            }
          } else {
            // Fake returning 1 sample with remainFrames == 0
            // to force a call to sceAtracAddStreamData.
            samples = 1;
            Memory.getInstance().memset(address, (byte) 0, samples * bytesPerSample);
          }
        } else if (atracChannel.length() >= getAtracChannelStartLength()
            || atracChannel.length() >= atracFileSize) {
          me.init(atracChannel, false, true, 0, 0);
        } else {
          // Fake returning 1 sample with remainFrames == 0
          // to force a call to sceAtracAddStreamData.
          samples = 1;
          Memory.getInstance().memset(address, (byte) 0, samples * bytesPerSample);
        }
      }
      setChannels(channels);
      if (me.stepAudio(atracMaxSamples * bytesPerSample, channels)) {
        samples = copySamplesToMem(address);
      }
      if (samples == 0) {
        isEnded = true;
      }
    } else if (decodedStream != null) {
      try {
        int length = decodedStream.read(atracDecodeBuffer);
        if (length > 0) {
          samples = length / 4;
          Memory.getInstance()
              .copyToMemory(address, ByteBuffer.wrap(atracDecodeBuffer, 0, length), length);
          long restLength = decodedStream.length() - decodedStream.getFilePointer();
          if (restLength <= 0) {
            isEnded = true;
          }
        } else {
          isEnded = true;
        }
      } catch (IOException e) {
        Modules.log.warn(e);
      }
    } else {
      samples = -1;
      isEnded = true;
    }

    if (isEnded) {
      atracEnd = 1;
    } else {
      atracEnd = 0;
    }

    return samples;
  }
예제 #2
0
  public void atracSetData(
      int atracID, int codecType, int address, int length, int atracFileSize, int atracHash) {
    this.atracFileSize = atracFileSize;
    this.atracBufferAddress = address;
    this.atracHash = atracHash;
    id = generateID(address, length, atracFileSize);
    closeStreams();
    atracEndSample = -1;
    requireAllAtracData = false;

    int memoryCodecType = sceAtrac3plus.getCodecType(address);
    if (memoryCodecType != codecType && memoryCodecType != 0) {
      Modules.log.info(
          String.format(
              "Different CodecType received %d != %d, assuming %d",
              codecType, memoryCodecType, memoryCodecType));
      codecType = memoryCodecType;
    }

    if (codecType == 0x00001001) {
      Modules.log.info("Decodable AT3 data detected.");
      if (checkMediaEngineState()) {
        me.finish();
        atracChannel = new PacketChannel();
        atracChannel.setTotalStreamSize(atracFileSize);
        atracChannel.setFarRewindAllowed(true);
        atracChannel.write(address, length);
        // Defer the initialization of the MediaEngine until atracDecodeData()
        // to ensure we have enough data into the channel.
        atracEndSample = 0;
        return;
      }
    } else if (codecType == 0x00001000) {
      if (checkMediaEngineState() && ExternalDecoder.isEnabled()) {
        String decodedFile =
            externalDecoder.decodeAtrac(address, length, atracFileSize, atracHash, this);
        if (decodedFile != null) {
          Modules.log.info("AT3+ data decoded by the external decoder.");
          me.finish();
          atracChannel = null;
          me.init(new FileProtocolHandler(decodedFile), false, true, 0, 0);
          atracEndSample = -1;
          return;
        } else if (requireAllAtracData) {
          // The external decoder requires all the atrac data
          // before it can try to decode the atrac.
          me.finish();
          atracChannel = new PacketChannel();
          atracChannel.setTotalStreamSize(atracFileSize);
          atracChannel.write(address, length);
          return;
        }
        Modules.log.info("AT3+ data could not be decoded by the external decoder.");
      } else {
        Modules.log.info("Undecodable AT3+ data detected.");
      }
    }
    me = null;

    File decodedFile = new File(getCompleteFileName(decodedAtracSuffix));

    if (!decodedFile.canRead()) {
      // Try to read the decoded file using an alternate file name,
      // without HashCode. These files can be generated by external tools
      // decoding the Atrac3+ files. These tools can't generate the HashCode.
      //
      // Use the following alternate file name scheme:
      //       Atrac-SSSSSSSS-NNNNNNNN-DDDDDDDD.at3.decoded
      // where SSSSSSSS is the file size in Hex
      //       NNNNNNNN is the number of samples in Hex found in the "fact" Chunk
      //       DDDDDDDD are the first 32-bit in Hex found in the "data" Chunk
      int numberOfSamples = 0;
      int data = 0;

      // Scan the Atrac data for NNNNNNNN and DDDDDDDD values
      Memory mem = Memory.getInstance();
      int scanAddress = address + 12;
      int endScanAddress = address + length;
      while (scanAddress < endScanAddress) {
        int chunkHeader = mem.read32(scanAddress);
        int chunkSize = mem.read32(scanAddress + 4);

        if (chunkHeader == waveFactChunkHeader) {
          numberOfSamples = mem.read32(scanAddress + 8);
        } else if (chunkHeader == waveDataChunkHeader) {
          data = mem.read32(scanAddress + 8);
          break;
        }

        // Go to the next Chunk
        scanAddress += chunkSize + 8;
      }

      File alternateDecodedFile =
          new File(
              String.format(
                  "%sAtrac-%08X-%08X-%08X%s",
                  getBaseDirectory(), atracFileSize, numberOfSamples, data, decodedAtracSuffix));
      if (alternateDecodedFile.canRead()) {
        decodedFile = alternateDecodedFile;
      }
    }

    File atracFile = new File(getCompleteFileName(atracSuffix));
    if (decodedFile.canRead()) {
      try {
        decodedStream = new RandomAccessFile(decodedFile, "r");
        atracEndSample = (int) (decodedFile.length() / 4);
      } catch (FileNotFoundException e) {
        // Decoded file should already be present
        Modules.log.warn(e);
      }
    } else if (atracFile.canRead() && atracFile.length() == atracFileSize) {
      // Atrac file is already written, no need to write it again
    } else if (sceAtrac3plus.isEnableConnector()) {
      commandFileDirty = true;
      displayInstructions();
      new File(getBaseDirectory()).mkdirs();

      try {
        atracStream = new FileOutputStream(getCompleteFileName(atracSuffix));
        byte[] buffer = new byte[length];
        IMemoryReader memoryReader = MemoryReader.getMemoryReader(address, length, 1);
        for (int i = 0; i < length; i++) {
          buffer[i] = (byte) memoryReader.readNext();
        }
        atracStream.write(buffer);
      } catch (IOException e) {
        Modules.log.warn(e);
      }
      generateCommandFile();
    }
  }