From f183b8a340f4531be1bf956d891dc00f8f0fa321 Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 4 Mar 2021 23:50:38 +0000 Subject: [PATCH] audiofile: add host sync, enable and volume parameters Signed-off-by: falkTX --- source/includes/CarlaNative.h | 10 +- source/native-plugins/audio-file.cpp | 161 ++++++++++++++++++++++----- 2 files changed, 143 insertions(+), 28 deletions(-) diff --git a/source/includes/CarlaNative.h b/source/includes/CarlaNative.h index ab228b808..95e8c4cb5 100644 --- a/source/includes/CarlaNative.h +++ b/source/includes/CarlaNative.h @@ -81,6 +81,11 @@ typedef enum { NATIVE_PLUGIN_SUPPORTS_EVERYTHING = (1 << 6)-1 } NativePluginSupports; +typedef enum { + NATIVE_PARAMETER_DESIGNATION_NONE = 0, + NATIVE_PARAMETER_DESIGNATION_ENABLED +} NativeParameterDesignations; + typedef enum { NATIVE_PARAMETER_IS_OUTPUT = 1 << 0, NATIVE_PARAMETER_IS_ENABLED = 1 << 1, @@ -89,7 +94,8 @@ typedef enum { NATIVE_PARAMETER_IS_INTEGER = 1 << 4, NATIVE_PARAMETER_IS_LOGARITHMIC = 1 << 5, NATIVE_PARAMETER_USES_SAMPLE_RATE = 1 << 6, - NATIVE_PARAMETER_USES_SCALEPOINTS = 1 << 7 + NATIVE_PARAMETER_USES_SCALEPOINTS = 1 << 7, + NATIVE_PARAMETER_USES_DESIGNATION = 1 << 8 } NativeParameterHints; typedef enum { @@ -153,6 +159,8 @@ typedef struct { const char* comment; const char* groupName; + + uint designation; } NativeParameter; typedef struct { diff --git a/source/native-plugins/audio-file.cpp b/source/native-plugins/audio-file.cpp index e1380de5b..479df0445 100644 --- a/source/native-plugins/audio-file.cpp +++ b/source/native-plugins/audio-file.cpp @@ -60,6 +60,9 @@ public: enum Parameters { kParameterLooping, + kParameterHostSync, + kParameterVolume, + kParameterEnabled, kParameterInfoChannels, kParameterInfoBitRate, kParameterInfoBitDepth, @@ -73,13 +76,21 @@ public: AudioFilePlugin(const NativeHostDescriptor* const host) : NativePluginWithMidiPrograms(host, fPrograms, 2), fLoopMode(true), +#ifdef __MOD_DEVICES__ + fHostSync(false), +#else + fHostSync(true), +#endif + fEnabled(true), fDoProcess(false), fWasPlayingBefore(false), fNeedsFileRead(false), fEntireFileLoaded(false), fMaxFrame(0), + fInternalTransportFrame(0), fLastPosition(0.0f), fLastPoolFill(0.0f), + fVolume(1.0f), fPool(), fReader(), fPrograms(hostGetFilePath("audio"), audiofilesWildcard), @@ -115,6 +126,7 @@ protected: param.ranges.step = 1.0f; param.ranges.stepSmall = 1.0f; param.ranges.stepLarge = 1.0f; + param.designation = NATIVE_PARAMETER_DESIGNATION_NONE; switch (index) { @@ -127,6 +139,41 @@ protected: param.ranges.min = 0.0f; param.ranges.max = 1.0f; break; + case kParameterHostSync: + param.name = "Host Sync"; + param.hints = static_cast(NATIVE_PARAMETER_IS_AUTOMABLE| + NATIVE_PARAMETER_IS_ENABLED| + NATIVE_PARAMETER_IS_BOOLEAN); +#ifdef __MOD_DEVICES__ + param.ranges.def = 0.0f; +#else + param.ranges.def = 1.0f; +#endif + param.ranges.min = 0.0f; + param.ranges.max = 1.0f; + break; + case kParameterVolume: + param.name = "Volume"; + param.hints = static_cast(NATIVE_PARAMETER_IS_AUTOMABLE| + NATIVE_PARAMETER_IS_ENABLED); + param.ranges.def = 100.0f; + param.ranges.min = 0.0f; + param.ranges.max = 127.0f; + param.ranges.stepSmall = 0.5f; + param.ranges.stepLarge = 10.0f; + param.unit = "%"; + break; + case kParameterEnabled: + param.name = "Enabled"; + param.hints = static_cast(NATIVE_PARAMETER_IS_AUTOMABLE| + NATIVE_PARAMETER_IS_ENABLED| + NATIVE_PARAMETER_IS_BOOLEAN| + NATIVE_PARAMETER_USES_DESIGNATION); + param.ranges.def = 1.0f; + param.ranges.min = 0.0f; + param.ranges.max = 1.0f; + param.designation = NATIVE_PARAMETER_DESIGNATION_ENABLED; + break; case kParameterInfoChannels: param.name = "Num Channels"; param.hints = static_cast(NATIVE_PARAMETER_IS_AUTOMABLE| @@ -206,10 +253,19 @@ protected: float getParameterValue(const uint32_t index) const override { - if (index == kParameterLooping) + switch (index) + { + case kParameterLooping: return fLoopMode ? 1.0f : 0.0f; - if (index == kParameterInfoBitRate) + case kParameterHostSync: + return fHostSync ? 1.0f : 0.0f; + case kParameterEnabled: + return fEnabled ? 1.0f : 0.0f; + case kParameterVolume: + return fVolume * 100.0f; + case kParameterInfoBitRate: return static_cast(fReader.getCurrentBitRate()); + } const ADInfo nfo = fReader.getFileInfo(); @@ -237,16 +293,40 @@ protected: void setParameterValue(const uint32_t index, const float value) override { - if (index != kParameterLooping) + if (index == kParameterVolume) + { + fVolume = value / 100.0f; return; + } - bool b = (value > 0.5f); - - if (b == fLoopMode) - return; + const bool b = (value > 0.5f); - fLoopMode = b; - fReader.setLoopingMode(b); + switch (index) + { + case kParameterLooping: + if (fLoopMode != b) + { + fLoopMode = b; + fReader.setLoopingMode(b); + } + break; + case kParameterHostSync: + if (fHostSync != b) + { + fInternalTransportFrame = 0; + fHostSync = b; + } + break; + case kParameterEnabled: + if (fEnabled != b) + { + fInternalTransportFrame = 0; + fEnabled = b; + } + break; + default: + break; + } } void setCustomData(const char* const key, const char* const value) override @@ -264,12 +344,28 @@ protected: void process2(const float* const*, float** const outBuffer, const uint32_t frames, const NativeMidiEvent*, uint32_t) override { - const NativeTimeInfo* const timePos(getTimeInfo()); const bool loopMode = fLoopMode; - - float* out1 = outBuffer[0]; - float* out2 = outBuffer[1]; + const float volume = fVolume; + float* const out1 = outBuffer[0]; + float* const out2 = outBuffer[1]; bool needsIdleRequest = false; + bool playing; + uint64_t frame; + + if (fHostSync) + { + const NativeTimeInfo* const timePos = getTimeInfo(); + playing = fEnabled && timePos->playing; + frame = timePos->frame; + } + else + { + playing = fEnabled; + frame = fInternalTransportFrame; + + if (playing) + fInternalTransportFrame += frames; + } const water::GenericScopedLock gsl(fPool.mutex); @@ -283,11 +379,11 @@ protected: } // not playing - if (! timePos->playing) + if (! playing) { // carla_stderr("P: not playing"); - if (timePos->frame == 0 && fWasPlayingBefore) - fReader.setNeedsRead(timePos->frame); + if (frame == 0 && fWasPlayingBefore) + fReader.setNeedsRead(frame); carla_zeroFloats(out1, frames); carla_zeroFloats(out2, frames); @@ -300,13 +396,13 @@ protected: } // out of reach - if ((timePos->frame < fPool.startFrame || timePos->frame >= fMaxFrame) && !loopMode) + if ((frame < fPool.startFrame || frame >= fMaxFrame) && !loopMode) { - if (timePos->frame < fPool.startFrame) + if (frame < fPool.startFrame) { needsIdleRequest = true; fNeedsFileRead = true; - fReader.setNeedsRead(timePos->frame); + fReader.setNeedsRead(frame); } carla_zeroFloats(out1, frames); @@ -329,19 +425,19 @@ protected: if (needsIdleRequest) hostRequestIdle(); - if (timePos->frame == 0) + if (frame == 0) fLastPosition = 0.0f; - else if (timePos->frame >= fMaxFrame) + else if (frame >= fMaxFrame) fLastPosition = 100.0f; else - fLastPosition = static_cast(timePos->frame) / static_cast(fMaxFrame) * 100.0f; + fLastPosition = static_cast(frame) / static_cast(fMaxFrame) * 100.0f; return; } if (fEntireFileLoaded) { - // NOTE: timePos->frame is always < fMaxFrame (or looping) - uint32_t targetStartFrame = static_cast(loopMode ? timePos->frame % fMaxFrame : timePos->frame); + // NOTE: frame is always < fMaxFrame (or looping) + uint32_t targetStartFrame = static_cast(loopMode ? frame % fMaxFrame : frame); for (uint32_t framesDone=0, framesToDo=frames, remainingFrames; framesDone < frames;) { @@ -380,7 +476,7 @@ protected: { const bool offline = isOffline(); - if (! fReader.tryPutData(fPool, out1, out2, timePos->frame, frames, loopMode, offline, needsIdleRequest)) + if (! fReader.tryPutData(fPool, out1, out2, frame, frames, loopMode, offline, needsIdleRequest)) { carla_zeroFloats(out1, frames); carla_zeroFloats(out2, frames); @@ -395,7 +491,7 @@ protected: needsIdleRequest = false; fReader.readPoll(); - if (! fReader.tryPutData(fPool, out1, out2, timePos->frame, frames, loopMode, offline, needsIdleRequest)) + if (! fReader.tryPutData(fPool, out1, out2, frame, frames, loopMode, offline, needsIdleRequest)) { carla_zeroFloats(out1, frames); carla_zeroFloats(out2, frames); @@ -406,7 +502,7 @@ protected: } } - const uint32_t modframe = static_cast(timePos->frame % fMaxFrame); + const uint32_t modframe = static_cast(frame % fMaxFrame); fLastPosition = static_cast(modframe) / static_cast(fMaxFrame) * 100.0f; if (modframe > fPool.startFrame) @@ -415,6 +511,12 @@ protected: fLastPoolFill = 100.0f; } + if (carla_isNotZero(volume-1.0f)) + { + carla_multiply(out1, volume, frames); + carla_multiply(out2, volume, frames); + } + #ifndef __MOD_DEVICES__ if (fInlineDisplay.writtenValues < 32) { @@ -593,14 +695,18 @@ protected: private: bool fLoopMode; + bool fHostSync; + bool fEnabled; bool fDoProcess; bool fWasPlayingBefore; volatile bool fNeedsFileRead; bool fEntireFileLoaded; uint32_t fMaxFrame; + uint32_t fInternalTransportFrame; float fLastPosition; float fLastPoolFill; + float fVolume; AudioFilePool fPool; AudioFileReader fReader; @@ -651,6 +757,7 @@ private: fDoProcess = false; fLastPoolFill = 0.0f; + fInternalTransportFrame = 0; fPool.destroy(); fReader.destroy();