int decodeNextBlock()

in pedalboard/juce_overrides/juce_PatchedMP3AudioFormat.cpp [1809:1977]


  int decodeNextBlock(float *out0, float *out1, int &done) {
    if (!headerParsed) {
      auto nextFrameOffset = scanForNextFrameHeader(false);

      if (lastFrameSize == -1 || needToSyncBitStream) {
        needToSyncBitStream = false;
        readVBRHeader();

        if (vbrHeaderFound)
          return 1;
      }

      if (nextFrameOffset > 0) {
        wasFreeFormat = false;
        needToSyncBitStream = true;
        auto size =
            (int)(bufferPointer - (bufferSpace[bufferSpaceIndex] + 512));

        if (size > 2880) {
          size = 0;
          bufferPointer = bufferSpace[bufferSpaceIndex] + 512;
        }

        auto toSkip = (size + nextFrameOffset) - 2880;

        if (toSkip > 0) {
          stream.skipNextBytes(toSkip);
          nextFrameOffset -= toSkip;
        }

        stream.read(bufferPointer, nextFrameOffset);
        lastFrameSize += nextFrameOffset;
      }

      uint32 nextIntBigEndian = (uint32)stream.readIntBigEndian();

      static const uint32 LYRICS_HEADER_START = 0x4c595249;
      if (nextFrameOffset < 0) {
        if (nextIntBigEndian == LYRICS_HEADER_START) {
          // Looks like we've hit a Lyrics3 block; a non-standard MP3 extension.
          // Rather than explode, let's just return "we're done" and pretend
          // that this file is over:
          stream.skipNextBytes(stream.getTotalLength() - stream.getPosition());
          return 1;
        } else {
          return -1;
        }
      }

      const auto successful = frame.decodeHeader(nextIntBigEndian);

      if (successful == MP3Frame::ParseSuccessful::no)
        return -1;

      headerParsed = true;
      frameSize = frame.frameSize;
      isFreeFormat = (frameSize == 0);
      sideInfoSize = frame.lsf != 0 ? ((frame.numChannels == 1) ? 9 : 17)
                                    : ((frame.numChannels == 1) ? 17 : 32);

      if (frame.crc16FollowsHeader)
        sideInfoSize += 2;

      bufferSpaceIndex = 1 - bufferSpaceIndex;
      bufferPointer = bufferSpace[bufferSpaceIndex] + 512;
      bitIndex = 0;

      if (lastFrameSize < 0)
        return 1;
    }

    if (!sideParsed) {
      if (frame.layer == 3) {
        stream.read(bufferPointer, sideInfoSize);

        if (frame.crc16FollowsHeader)
          getBits(16);

        auto bits = jmax(0, decodeLayer3SideInfo());
        dataSize = (bits + 7) / 8;

        if (!isFreeFormat)
          dataSize = jmin(dataSize, frame.frameSize - sideInfoSize);
      } else {
        dataSize = frame.frameSize;
        sideInfoSize = 0;
      }

      sideParsed = true;
    }

    int result = 1;

    if (!dataParsed) {
      stream.read(bufferPointer, dataSize);

      if (out0 != nullptr) {
        if (frame.layer < 3 && frame.crc16FollowsHeader)
          getBits(16);

        switch (frame.layer) {
        case 1:
          decodeLayer1Frame(out0, out1, done);
          break;
        case 2:
          decodeLayer2Frame(out0, out1, done);
          break;
        case 3:
          decodeLayer3Frame(out0, out1, done);
          break;
        default:
          break;
        }
      }

      bufferPointer =
          bufferSpace[bufferSpaceIndex] + 512 + sideInfoSize + dataSize;
      dataParsed = true;
      result = 0;

      // We decoded a frame correctly, so increase the amount of patience
      // we have when scanning for the next frame header:
      if (maximumScanLength < 0xFFFFFFF) {
        maximumScanLength *= 2;
      }
    }

    if (isFreeFormat) {
      if (wasFreeFormat) {
        frameSize = lastFrameSizeNoPadding + frame.padding;
      } else {
        auto nextFrameOffset = scanForNextFrameHeader(true);

        wasFreeFormat = isFreeFormat;

        if (nextFrameOffset < 0) {
          lastFrameSize = frameSize;
          return result;
        }

        frameSize = nextFrameOffset + sideInfoSize + dataSize;
        lastFrameSizeNoPadding = frameSize - frame.padding;
      }
    }

    if (result == 0)
      return result;

    int bytes = frameSize - (sideInfoSize + dataSize);

    if (bytes > 0) {
      auto toSkip = bytes - 512;

      if (toSkip > 0) {
        stream.skipNextBytes(toSkip);
        bytes -= toSkip;
        frameSize -= toSkip;
      }

      stream.read(bufferPointer, bytes);
      bufferPointer += bytes;
    }

    lastFrameSize = frameSize;
    wasFreeFormat = isFreeFormat;
    frameSize = 0;
    headerParsed = sideParsed = dataParsed = false;
    return result;
  }