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;
}