Browse Source

audiofile plugin: add option to load quad channel files

Signed-off-by: falkTX <falktx@falktx.com>
fix-audiofile-buffering
falkTX 1 year ago
parent
commit
a197fd76cc
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
2 changed files with 95 additions and 22 deletions
  1. +49
    -19
      source/native-plugins/audio-base.hpp
  2. +46
    -3
      source/native-plugins/audio-file.cpp

+ 49
- 19
source/native-plugins/audio-base.hpp View File

@@ -157,7 +157,7 @@ public:
return fFileNfo;
}

bool loadFilename(const char* const filename, const uint32_t sampleRate,
bool loadFilename(const char* const filename, const uint32_t sampleRate, const bool quad2ndChannels,
const uint32_t previewDataSize, float* previewData)
{
CARLA_SAFE_ASSERT_RETURN(filename != nullptr && *filename != '\0', false);
@@ -176,10 +176,10 @@ public:
ad_dump_nfo(99, &fFileNfo);

// invalid
if ((fFileNfo.channels != 1 && fFileNfo.channels != 2) || fFileNfo.frames <= 0)
if ((fFileNfo.channels != 1 && fFileNfo.channels != 2 && fFileNfo.channels != 4) || fFileNfo.frames <= 0)
{
if (fFileNfo.channels != 1 && fFileNfo.channels != 2)
carla_stderr("loadFilename(\"%s\", ...) has not 1 or 2 channels", filename);
if (fFileNfo.channels != 1 && fFileNfo.channels != 2 && fFileNfo.channels != 4)
carla_stderr("loadFilename(\"%s\", ...) has not 1, 2 or 4 channels", filename);

if (fFileNfo.frames <= 0)
carla_stderr("loadFilename(\"%s\", ...) has 0 frames", filename);
@@ -216,6 +216,8 @@ public:
numResampledFrames = numFileFrames;
}

fQuad2ndChannels = quad2ndChannels;

if (fFileNfo.can_seek == 0 || numResampledFrames <= sampleRate * kMinLengthSeconds)
{
// read and cache the first few seconds of the file if seekable
@@ -439,10 +441,12 @@ public:
const float previewDataSizeF = static_cast<float>(previewDataSize);
const uint samplesPerRun = fFileNfo.channels;
const uint maxSampleToRead = fileNumFrames - samplesPerRun;
CARLA_SAFE_ASSERT_INT_RETURN(samplesPerRun == 1 || samplesPerRun == 2, samplesPerRun,);
float tmp[2] = { 0.0f, 0.0f };
CARLA_SAFE_ASSERT_INT_RETURN(samplesPerRun == 1 || samplesPerRun == 2 || samplesPerRun == 4, samplesPerRun,);
float tmp[4];

if (samplesPerRun == 2)
if (samplesPerRun == 4)
previewDataSize -= 3;
else if (samplesPerRun == 2)
previewDataSize -= 1;

for (uint i=0; i<previewDataSize; ++i)
@@ -552,18 +556,26 @@ public:
if (r == 0)
break;

if (channels == 1)
switch (channels)
{
case 1:
fRingBufferL.writeCustomData(rbuffer, r * sizeof(float));
fRingBufferR.writeCustomData(rbuffer, r * sizeof(float));
}
else
{
break;
case 2:
for (ssize_t i=0; i < r;)
{
fRingBufferL.writeCustomData(&rbuffer[i++], sizeof(float));
fRingBufferR.writeCustomData(&rbuffer[i++], sizeof(float));
}
break;
case 4:
for (ssize_t i=fQuad2ndChannels?2:0; i < r; i += 4)
{
fRingBufferL.writeCustomData(&rbuffer[i], sizeof(float));
fRingBufferR.writeCustomData(&rbuffer[i+1], sizeof(float));
}
break;
}

fRingBufferL.commitWrite();
@@ -596,18 +608,26 @@ public:
if (r == 0)
break;

if (channels == 1)
switch (channels)
{
case 1:
fRingBufferL.writeCustomData(buffer, r * sizeof(float));
fRingBufferR.writeCustomData(buffer, r * sizeof(float));
}
else
{
break;
case 2:
for (ssize_t i=0; i < r;)
{
fRingBufferL.writeCustomData(&buffer[i++], sizeof(float));
fRingBufferR.writeCustomData(&buffer[i++], sizeof(float));
}
break;
case 4:
for (ssize_t i=fQuad2ndChannels?2:0; i < r; i += 4)
{
fRingBufferL.writeCustomData(&buffer[i], sizeof(float));
fRingBufferR.writeCustomData(&buffer[i+1], sizeof(float));
}
break;
}

fRingBufferL.commitWrite();
@@ -621,6 +641,7 @@ public:

private:
bool fEntireFileLoaded = false;
bool fQuad2ndChannels = false;
int fCurrentBitRate = 0;
float fLastPlayPosition = 0.f;
int64_t fNextFileReadPos = -1;
@@ -713,18 +734,27 @@ private:
// lock, and put data asap
const CarlaMutexLocker cml(fInitialMemoryPool.mutex);

if (channels == 1)
switch (channels)
{
case 1:
for (ssize_t i=0; i < rv; ++i)
fInitialMemoryPool.buffer[0][i] = fInitialMemoryPool.buffer[1][i] = resampledBuffer[i];
}
else
{
break;
case 2:
for (ssize_t i=0, j=0; i < rv; ++j)
{
fInitialMemoryPool.buffer[0][j] = resampledBuffer[i++];
fInitialMemoryPool.buffer[1][j] = resampledBuffer[i++];
}
break;
case 4:
for (ssize_t i=fQuad2ndChannels?2:0, j=0; i < rv; ++j)
{
fInitialMemoryPool.buffer[0][j] = resampledBuffer[i];
fInitialMemoryPool.buffer[1][j] = resampledBuffer[i+1];
i += 4;
}
break;
}
}



+ 46
- 3
source/native-plugins/audio-file.cpp View File

@@ -106,6 +106,7 @@ public:
kParameterHostSync,
kParameterVolume,
kParameterEnabled,
kParameterQuadChannels,
kParameterInfoChannels,
kParameterInfoBitRate,
kParameterInfoBitDepth,
@@ -192,6 +193,24 @@ protected:
param.ranges.max = 1.0f;
param.designation = NATIVE_PARAMETER_DESIGNATION_ENABLED;
break;
case kParameterQuadChannels:
param.name = "Quad Channels";
param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
NATIVE_PARAMETER_IS_ENABLED|
NATIVE_PARAMETER_IS_INTEGER|
NATIVE_PARAMETER_USES_SCALEPOINTS);
param.ranges.def = 0.0f;
param.ranges.min = 0.0f;
param.ranges.max = 1.0f;
{
static const NativeParameterScalePoint scalePoints[2] = {
{ "Channels 1 + 2", 0 },
{ "Channels 3 + 4", 1 }
};
param.scalePointCount = 2;
param.scalePoints = scalePoints;
}
break;
case kParameterInfoChannels:
param.name = "Num Channels";
param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
@@ -279,6 +298,8 @@ protected:
return fHostSync ? 1.f : 0.f;
case kParameterEnabled:
return fEnabled ? 1.f : 0.f;
case kParameterQuadChannels:
return fQuad2ndChannels ? 1.f : 0.f;
case kParameterVolume:
return fVolume * 100.f;
case kParameterInfoPosition:
@@ -336,6 +357,13 @@ protected:
fEnabled = b;
}
break;
case kParameterQuadChannels:
if (fQuad2ndChannels != b)
{
fQuad2ndChannels = b;
fPendingFileReload = true;
hostRequestIdle();
}
default:
break;
}
@@ -475,15 +503,27 @@ protected:
}
#endif

if (fPendingFileRead)
if (fPendingFileReload)
{
fPendingFileReload = fPendingFileRead = false;

if (char* const filename = fFilename.releaseBufferPointer())
{
loadFilename(filename);
std::free(filename);
}
}
else if (fPendingFileRead)
{
fPendingFileRead = false;
fReader.readPoll();
}
}

void sampleRateChanged(double) override
void sampleRateChanged(const double sampleRate) override
{
fVolumeFilter.setSampleRate(sampleRate);

if (char* const filename = fFilename.releaseBufferPointer())
{
loadFilename(filename);
@@ -615,6 +655,8 @@ private:
bool fEnabled = true;
bool fDoProcess = false;
bool fPendingFileRead = false;
bool fPendingFileReload = false;
bool fQuad2ndChannels = false;

uint32_t fInternalTransportFrame = 0;
float fLastPosition = 0.f;
@@ -668,7 +710,8 @@ private:

constexpr uint32_t kPreviewDataLen = sizeof(fPreviewData)/sizeof(float);

if (fReader.loadFilename(filename, static_cast<uint32_t>(getSampleRate()), kPreviewDataLen, fPreviewData))
if (fReader.loadFilename(filename, static_cast<uint32_t>(getSampleRate()), fQuad2ndChannels,
kPreviewDataLen, fPreviewData))
{
fInternalTransportFrame = 0;
fDoProcess = true;


Loading…
Cancel
Save