py::array_t readInteger()

in pedalboard/io/ReadableAudioFile.h [450:564]


  py::array_t<SampleType> readInteger(long long numSamples) {
    const juce::ScopedReadLock readLock(objectLock);
    if (reader->usesFloatingPointData) {
      throw std::runtime_error(
          "Can't call readInteger with a floating point file!");
    }

    // Allocate a buffer to return of up to numSamples:
    long long numChannels = reader->numChannels;
    numSamples =
        std::min(numSamples, (reader->lengthInSamples +
                              (lengthCorrection ? *lengthCorrection : 0)) -
                                 currentPosition);
    py::array_t<SampleType> buffer = py::array_t<SampleType>(
        {(long long)numChannels, (long long)numSamples});

    py::buffer_info outputInfo = buffer.request();

    {
      py::gil_scoped_release release;
      if (reader->bitsPerSample > 16) {
        if (sizeof(SampleType) < 4) {
          throw std::runtime_error("Output array not wide enough to store " +
                                   std::to_string(reader->bitsPerSample) +
                                   "-bit integer data.");
        }

        std::memset((void *)outputInfo.ptr, 0,
                    numChannels * numSamples * sizeof(SampleType));

        int **channelPointers = (int **)alloca(numChannels * sizeof(int *));
        for (long long c = 0; c < numChannels; c++) {
          channelPointers[c] = ((int *)outputInfo.ptr) + (numSamples * c);
        }

        bool readResult = false;
        {
          ScopedTryWriteLock scopedTryWriteLock(objectLock);
          if (!scopedTryWriteLock.isLocked()) {
            throw std::runtime_error(
                "Another thread is currently reading from this AudioFile. Note "
                "that using multiple concurrent readers on the same AudioFile "
                "object will produce nondeterministic results.");
          }
          readResult = reader->readSamples(channelPointers, numChannels, 0,
                                           currentPosition, numSamples);
        }

        if (!readResult) {
          PythonException::raise();
          throwReadError(currentPosition, numSamples);
        }
      } else {
        // Read the file in smaller chunks, converting from int32 to the
        // appropriate output format as we go:
        std::vector<std::vector<int>> intBuffers;
        intBuffers.resize(numChannels);

        int **channelPointers = (int **)alloca(numChannels * sizeof(int *));
        for (long long startSample = 0; startSample < numSamples;
             startSample += DEFAULT_AUDIO_BUFFER_SIZE_FRAMES) {
          long long samplesToRead =
              std::min(numSamples - startSample,
                       (long long)DEFAULT_AUDIO_BUFFER_SIZE_FRAMES);

          for (long long c = 0; c < numChannels; c++) {
            intBuffers[c].resize(samplesToRead);
            channelPointers[c] = intBuffers[c].data();
          }

          bool readResult = false;
          {
            ScopedTryWriteLock scopedTryWriteLock(objectLock);
            if (!scopedTryWriteLock.isLocked()) {
              throw std::runtime_error(
                  "Another thread is currently reading from this AudioFile. "
                  "Note that using multiple concurrent readers on the same "
                  "AudioFile object will produce nondeterministic results.");
            }

            readResult = reader->readSamples(channelPointers, numChannels, 0,
                                             currentPosition + startSample,
                                             samplesToRead);
          }

          if (!readResult) {
            PythonException::raise();
            throw std::runtime_error("Failed to read from file.");
          }

          // Convert the data in intBuffers to the output format:
          char shift = 32 - reader->bitsPerSample;
          for (long long c = 0; c < numChannels; c++) {
            SampleType *outputChannelPointer =
                (((SampleType *)outputInfo.ptr) + (c * numSamples));
            for (long long i = 0; i < samplesToRead; i++) {
              outputChannelPointer[startSample + i] = intBuffers[c][i] >> shift;
            }
          }
        }
      }
    }

    PythonException::raise();

    ScopedTryWriteLock scopedTryWriteLock(objectLock);
    if (!scopedTryWriteLock.isLocked()) {
      throw std::runtime_error(
          "Another thread is currently reading from this AudioFile. "
          "Note that using multiple concurrent readers on the same "
          "AudioFile object will produce nondeterministic results.");
    }
    currentPosition += numSamples;
    return buffer;
  }