mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
AudioPlayHead: Use more descriptive FrameRate type
This commit is contained in:
parent
221a137526
commit
718307b516
4 changed files with 138 additions and 41 deletions
|
|
@ -4,6 +4,26 @@ JUCE breaking changes
|
|||
develop
|
||||
=======
|
||||
|
||||
Change
|
||||
------
|
||||
AudioFrameRate::frameRate is now a class type instead of an enum.
|
||||
|
||||
Possible Issues
|
||||
---------------
|
||||
Code that read the old enum value will not compile.
|
||||
|
||||
Workaround
|
||||
----------
|
||||
Call frameRate.getType() to fetch the old enum type. Alternatively, use the new
|
||||
getBaseRate(), isDrop(), isPullDown(), and getEffectiveRate() functions. The
|
||||
new functions provide a more accurate description of the host's frame rate.
|
||||
|
||||
Rationale
|
||||
---------
|
||||
The old enum-based interface was not flexible enough to describe all the frame
|
||||
rates that might be reported by a plugin host.
|
||||
|
||||
|
||||
Change
|
||||
------
|
||||
FlexItem::alignSelf now defaults to "autoAlign" rather than "stretch".
|
||||
|
|
|
|||
|
|
@ -60,6 +60,98 @@ public:
|
|||
fpsUnknown = 99
|
||||
};
|
||||
|
||||
/** More descriptive frame rate type. */
|
||||
class JUCE_API FrameRate
|
||||
{
|
||||
public:
|
||||
/** Creates a frame rate with a base rate of 0. */
|
||||
FrameRate() = default;
|
||||
|
||||
/** Creates a FrameRate instance from a FrameRateType. */
|
||||
FrameRate (FrameRateType type) : FrameRate (fromType (type)) {}
|
||||
|
||||
/** Gets the FrameRateType that matches the state of this FrameRate.
|
||||
|
||||
Returns fpsUnknown if this FrameRate cannot be represented by any of the
|
||||
other enum fields.
|
||||
*/
|
||||
FrameRateType getType() const
|
||||
{
|
||||
switch (base)
|
||||
{
|
||||
case 24: return pulldown ? fps23976 : fps24;
|
||||
case 25: return fps25;
|
||||
case 30: return pulldown ? (drop ? fps2997drop : fps2997)
|
||||
: (drop ? fps30drop : fps30);
|
||||
case 60: return drop ? fps60drop : fps60;
|
||||
}
|
||||
|
||||
return fpsUnknown;
|
||||
}
|
||||
|
||||
/** Returns the plain rate, without taking pulldown into account. */
|
||||
int getBaseRate() const { return base; }
|
||||
|
||||
/** Returns true if drop-frame timecode is in use. */
|
||||
bool isDrop() const { return drop; }
|
||||
|
||||
/** Returns true if the effective framerate is actually equal to the base rate divided by 1.001 */
|
||||
bool isPullDown() const { return pulldown; }
|
||||
|
||||
/** Returns the actual rate described by this object, taking pulldown into account. */
|
||||
double getEffectiveRate() const { return pulldown ? (double) base / 1.001 : (double) base; }
|
||||
|
||||
/** Returns a copy of this object with the specified base rate. */
|
||||
FrameRate withBaseRate (int x) const { return with (&FrameRate::base, x); }
|
||||
|
||||
/** Returns a copy of this object with drop frames enabled or disabled, as specified. */
|
||||
FrameRate withDrop (bool x = true) const { return with (&FrameRate::drop, x); }
|
||||
|
||||
/** Returns a copy of this object with pulldown enabled or disabled, as specified. */
|
||||
FrameRate withPullDown (bool x = true) const { return with (&FrameRate::pulldown, x); }
|
||||
|
||||
/** Returns true if this instance is equal to other. */
|
||||
bool operator== (const FrameRate& other) const
|
||||
{
|
||||
const auto tie = [] (const FrameRate& x) { return std::tie (x.base, x.drop, x.pulldown); };
|
||||
return tie (*this) == tie (other);
|
||||
}
|
||||
|
||||
/** Returns true if this instance is not equal to other. */
|
||||
bool operator!= (const FrameRate& other) const { return ! (*this == other); }
|
||||
|
||||
private:
|
||||
static FrameRate fromType (FrameRateType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case fps23976: return FrameRate().withBaseRate (24).withPullDown();
|
||||
case fps24: return FrameRate().withBaseRate (24);
|
||||
case fps25: return FrameRate().withBaseRate (25);
|
||||
case fps2997: return FrameRate().withBaseRate (30).withPullDown();
|
||||
case fps30: return FrameRate().withBaseRate (30);
|
||||
case fps2997drop: return FrameRate().withBaseRate (30).withDrop().withPullDown();
|
||||
case fps30drop: return FrameRate().withBaseRate (30).withDrop();
|
||||
case fps60: return FrameRate().withBaseRate (60);
|
||||
case fps60drop: return FrameRate().withBaseRate (60).withDrop();
|
||||
case fpsUnknown: break;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename Member, typename Value>
|
||||
FrameRate with (Member&& member, Value&& value) const
|
||||
{
|
||||
auto copy = *this;
|
||||
copy.*member = std::forward<Value> (value);
|
||||
return copy;
|
||||
}
|
||||
|
||||
int base = 0;
|
||||
bool drop = false, pulldown = false;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** This structure is filled-in by the AudioPlayHead::getCurrentPosition() method.
|
||||
*/
|
||||
|
|
@ -95,7 +187,7 @@ public:
|
|||
double ppqPositionOfLastBarStart = 0;
|
||||
|
||||
/** The video frame rate, if applicable. */
|
||||
FrameRateType frameRate = FrameRateType::fps23976;
|
||||
FrameRate frameRate = FrameRateType::fps23976;
|
||||
|
||||
/** True if the transport is currently playing. */
|
||||
bool isPlaying = false;
|
||||
|
|
@ -124,7 +216,7 @@ public:
|
|||
//==============================================================================
|
||||
bool operator== (const CurrentPositionInfo& other) const noexcept
|
||||
{
|
||||
auto tie = [] (const CurrentPositionInfo& i)
|
||||
const auto tie = [] (const CurrentPositionInfo& i)
|
||||
{
|
||||
return std::tie (i.timeInSamples,
|
||||
i.ppqPosition,
|
||||
|
|
|
|||
|
|
@ -271,20 +271,9 @@ static void toProcessContext (Vst::ProcessContext& context, AudioPlayHead* playH
|
|||
context.cycleStartMusic = position.ppqLoopStart;
|
||||
context.cycleEndMusic = position.ppqLoopEnd;
|
||||
|
||||
switch (position.frameRate)
|
||||
{
|
||||
case AudioPlayHead::fps23976: fr.framesPerSecond = 24; fr.flags = FrameRate::kPullDownRate; break;
|
||||
case AudioPlayHead::fps24: fr.framesPerSecond = 24; fr.flags = 0; break;
|
||||
case AudioPlayHead::fps25: fr.framesPerSecond = 25; fr.flags = 0; break;
|
||||
case AudioPlayHead::fps2997: fr.framesPerSecond = 30; fr.flags = FrameRate::kPullDownRate; break;
|
||||
case AudioPlayHead::fps2997drop: fr.framesPerSecond = 30; fr.flags = FrameRate::kPullDownRate | FrameRate::kDropRate; break;
|
||||
case AudioPlayHead::fps30: fr.framesPerSecond = 30; fr.flags = 0; break;
|
||||
case AudioPlayHead::fps30drop: fr.framesPerSecond = 30; fr.flags = FrameRate::kDropRate; break;
|
||||
case AudioPlayHead::fps60: fr.framesPerSecond = 60; fr.flags = 0; break;
|
||||
case AudioPlayHead::fps60drop: fr.framesPerSecond = 60; fr.flags = FrameRate::kDropRate; break;
|
||||
case AudioPlayHead::fpsUnknown: break;
|
||||
default: jassertfalse; break; // New frame rate?
|
||||
}
|
||||
context.frameRate.framesPerSecond = (Steinberg::uint32) position.frameRate.getBaseRate();
|
||||
context.frameRate.flags = (Steinberg::uint32) ((position.frameRate.isDrop() ? FrameRate::kDropRate : 0)
|
||||
| (position.frameRate.isPullDown() ? FrameRate::kPullDownRate : 0));
|
||||
|
||||
if (position.isPlaying) context.state |= ProcessContext::kPlaying;
|
||||
if (position.isRecording) context.state |= ProcessContext::kRecording;
|
||||
|
|
|
|||
|
|
@ -2396,21 +2396,29 @@ private:
|
|||
else
|
||||
vstHostTime.flags &= ~Vst2::kVstTransportChanged;
|
||||
|
||||
switch (position.frameRate)
|
||||
struct OptionalFrameRate
|
||||
{
|
||||
case AudioPlayHead::fps24: setHostTimeFrameRate (Vst2::kVstSmpte24fps, 24.0, position.timeInSeconds); break;
|
||||
case AudioPlayHead::fps25: setHostTimeFrameRate (Vst2::kVstSmpte25fps, 25.0, position.timeInSeconds); break;
|
||||
case AudioPlayHead::fps30: setHostTimeFrameRate (Vst2::kVstSmpte30fps, 30.0, position.timeInSeconds); break;
|
||||
case AudioPlayHead::fps60: setHostTimeFrameRate (Vst2::kVstSmpte60fps, 60.0, position.timeInSeconds); break;
|
||||
bool valid;
|
||||
Vst2::VstInt32 rate;
|
||||
};
|
||||
|
||||
case AudioPlayHead::fps23976: setHostTimeFrameRateDrop (Vst2::kVstSmpte239fps, 24.0, position.timeInSeconds); break;
|
||||
case AudioPlayHead::fps2997: setHostTimeFrameRateDrop (Vst2::kVstSmpte2997fps, 30.0, position.timeInSeconds); break;
|
||||
case AudioPlayHead::fps2997drop: setHostTimeFrameRateDrop (Vst2::kVstSmpte2997dfps, 30.0, position.timeInSeconds); break;
|
||||
case AudioPlayHead::fps30drop: setHostTimeFrameRateDrop (Vst2::kVstSmpte30dfps, 30.0, position.timeInSeconds); break;
|
||||
case AudioPlayHead::fps60drop: setHostTimeFrameRateDrop (Vst2::kVstSmpte599fps, 60.0, position.timeInSeconds); break;
|
||||
case AudioPlayHead::fpsUnknown:
|
||||
default: break;
|
||||
}
|
||||
const auto optionalFrameRate = [&fr = position.frameRate]() -> OptionalFrameRate
|
||||
{
|
||||
switch (fr.getBaseRate())
|
||||
{
|
||||
case 24: return { true, fr.isPullDown() ? Vst2::kVstSmpte239fps : Vst2::kVstSmpte24fps };
|
||||
case 25: return { true, fr.isPullDown() ? Vst2::kVstSmpte249fps : Vst2::kVstSmpte25fps };
|
||||
case 30: return { true, fr.isPullDown() ? (fr.isDrop() ? Vst2::kVstSmpte2997dfps : Vst2::kVstSmpte2997fps)
|
||||
: (fr.isDrop() ? Vst2::kVstSmpte30dfps : Vst2::kVstSmpte30fps) };
|
||||
case 60: return { true, fr.isPullDown() ? Vst2::kVstSmpte599fps : Vst2::kVstSmpte60fps };
|
||||
}
|
||||
|
||||
return { false, Vst2::VstSmpteFrameRate{} };
|
||||
}();
|
||||
|
||||
vstHostTime.flags |= optionalFrameRate.valid ? Vst2::kVstSmpteValid : 0;
|
||||
vstHostTime.smpteFrameRate = optionalFrameRate.rate;
|
||||
vstHostTime.smpteOffset = (int32) (position.timeInSeconds * 80.0 * position.frameRate.getEffectiveRate() + 0.5);
|
||||
|
||||
if (position.isLooping)
|
||||
{
|
||||
|
|
@ -2506,18 +2514,6 @@ private:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
void setHostTimeFrameRate (long frameRateIndex, double frameRate, double currentTime) noexcept
|
||||
{
|
||||
vstHostTime.flags |= Vst2::kVstSmpteValid;
|
||||
vstHostTime.smpteFrameRate = (int32) frameRateIndex;
|
||||
vstHostTime.smpteOffset = (int32) (currentTime * 80.0 * frameRate + 0.5);
|
||||
}
|
||||
|
||||
void setHostTimeFrameRateDrop (long frameRateIndex, double frameRate, double currentTime) noexcept
|
||||
{
|
||||
setHostTimeFrameRate (frameRateIndex, frameRate * 1000.0 / 1001.0, currentTime);
|
||||
}
|
||||
|
||||
bool restoreProgramSettings (const fxProgram* const prog)
|
||||
{
|
||||
if (compareMagic (prog->chunkMagic, "CcnK")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue