Browse Source

audiofile plugin: add option to load quad channel files

Signed-off-by: falkTX <falktx@falktx.com>
fix-audiofile-buffering
falkTX 2 years 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; 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) const uint32_t previewDataSize, float* previewData)
{ {
CARLA_SAFE_ASSERT_RETURN(filename != nullptr && *filename != '\0', false); CARLA_SAFE_ASSERT_RETURN(filename != nullptr && *filename != '\0', false);
@@ -176,10 +176,10 @@ public:
ad_dump_nfo(99, &fFileNfo); ad_dump_nfo(99, &fFileNfo);


// invalid // 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) if (fFileNfo.frames <= 0)
carla_stderr("loadFilename(\"%s\", ...) has 0 frames", filename); carla_stderr("loadFilename(\"%s\", ...) has 0 frames", filename);
@@ -216,6 +216,8 @@ public:
numResampledFrames = numFileFrames; numResampledFrames = numFileFrames;
} }


fQuad2ndChannels = quad2ndChannels;

if (fFileNfo.can_seek == 0 || numResampledFrames <= sampleRate * kMinLengthSeconds) if (fFileNfo.can_seek == 0 || numResampledFrames <= sampleRate * kMinLengthSeconds)
{ {
// read and cache the first few seconds of the file if seekable // 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 float previewDataSizeF = static_cast<float>(previewDataSize);
const uint samplesPerRun = fFileNfo.channels; const uint samplesPerRun = fFileNfo.channels;
const uint maxSampleToRead = fileNumFrames - samplesPerRun; 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; previewDataSize -= 1;


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


if (channels == 1)
switch (channels)
{ {
case 1:
fRingBufferL.writeCustomData(rbuffer, r * sizeof(float)); fRingBufferL.writeCustomData(rbuffer, r * sizeof(float));
fRingBufferR.writeCustomData(rbuffer, r * sizeof(float)); fRingBufferR.writeCustomData(rbuffer, r * sizeof(float));
}
else
{
break;
case 2:
for (ssize_t i=0; i < r;) for (ssize_t i=0; i < r;)
{ {
fRingBufferL.writeCustomData(&rbuffer[i++], sizeof(float)); fRingBufferL.writeCustomData(&rbuffer[i++], sizeof(float));
fRingBufferR.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(); fRingBufferL.commitWrite();
@@ -596,18 +608,26 @@ public:
if (r == 0) if (r == 0)
break; break;


if (channels == 1)
switch (channels)
{ {
case 1:
fRingBufferL.writeCustomData(buffer, r * sizeof(float)); fRingBufferL.writeCustomData(buffer, r * sizeof(float));
fRingBufferR.writeCustomData(buffer, r * sizeof(float)); fRingBufferR.writeCustomData(buffer, r * sizeof(float));
}
else
{
break;
case 2:
for (ssize_t i=0; i < r;) for (ssize_t i=0; i < r;)
{ {
fRingBufferL.writeCustomData(&buffer[i++], sizeof(float)); fRingBufferL.writeCustomData(&buffer[i++], sizeof(float));
fRingBufferR.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(); fRingBufferL.commitWrite();
@@ -621,6 +641,7 @@ public:


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


if (channels == 1)
switch (channels)
{ {
case 1:
for (ssize_t i=0; i < rv; ++i) for (ssize_t i=0; i < rv; ++i)
fInitialMemoryPool.buffer[0][i] = fInitialMemoryPool.buffer[1][i] = resampledBuffer[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) for (ssize_t i=0, j=0; i < rv; ++j)
{ {
fInitialMemoryPool.buffer[0][j] = resampledBuffer[i++]; fInitialMemoryPool.buffer[0][j] = resampledBuffer[i++];
fInitialMemoryPool.buffer[1][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, kParameterHostSync,
kParameterVolume, kParameterVolume,
kParameterEnabled, kParameterEnabled,
kParameterQuadChannels,
kParameterInfoChannels, kParameterInfoChannels,
kParameterInfoBitRate, kParameterInfoBitRate,
kParameterInfoBitDepth, kParameterInfoBitDepth,
@@ -192,6 +193,24 @@ protected:
param.ranges.max = 1.0f; param.ranges.max = 1.0f;
param.designation = NATIVE_PARAMETER_DESIGNATION_ENABLED; param.designation = NATIVE_PARAMETER_DESIGNATION_ENABLED;
break; 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: case kParameterInfoChannels:
param.name = "Num Channels"; param.name = "Num Channels";
param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE| param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMATABLE|
@@ -279,6 +298,8 @@ protected:
return fHostSync ? 1.f : 0.f; return fHostSync ? 1.f : 0.f;
case kParameterEnabled: case kParameterEnabled:
return fEnabled ? 1.f : 0.f; return fEnabled ? 1.f : 0.f;
case kParameterQuadChannels:
return fQuad2ndChannels ? 1.f : 0.f;
case kParameterVolume: case kParameterVolume:
return fVolume * 100.f; return fVolume * 100.f;
case kParameterInfoPosition: case kParameterInfoPosition:
@@ -336,6 +357,13 @@ protected:
fEnabled = b; fEnabled = b;
} }
break; break;
case kParameterQuadChannels:
if (fQuad2ndChannels != b)
{
fQuad2ndChannels = b;
fPendingFileReload = true;
hostRequestIdle();
}
default: default:
break; break;
} }
@@ -475,15 +503,27 @@ protected:
} }
#endif #endif


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

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


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

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


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


constexpr uint32_t kPreviewDataLen = sizeof(fPreviewData)/sizeof(float); 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; fInternalTransportFrame = 0;
fDoProcess = true; fDoProcess = true;


Loading…
Cancel
Save