tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_GlueCode.h
Go to the documentation of this file.
1 /*
2 ,--. ,--. ,--. ,--.
3 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
4 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
5 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
6 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
7
8 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
9*/
10
11namespace tracktion { inline namespace graph
12{
13
14//==============================================================================
16inline juce::AudioBuffer<float> toAudioBuffer (choc::buffer::ChannelArrayView<float> view)
17{
18 return juce::AudioBuffer<float> (view.data.channels, (int) view.getNumChannels(), (int) view.data.offset, (int) view.getNumFrames());
19}
20
22template<typename SampleType>
23inline choc::buffer::BufferView<SampleType, choc::buffer::SeparateChannelLayout> toBufferView (juce::AudioBuffer<SampleType>& buffer)
24{
25 return choc::buffer::createChannelArrayView (buffer.getArrayOfWritePointers(),
26 (choc::buffer::ChannelCount) buffer.getNumChannels(),
27 (choc::buffer::FrameCount) buffer.getNumSamples());
28}
29
31inline choc::buffer::FrameRange createFrameRange (std::integral auto start, std::integral auto end)
32{
33 return { .start = static_cast<choc::buffer::FrameCount> (start),
34 .end = static_cast<choc::buffer::FrameCount> (end) };
35}
36
37
38//==============================================================================
40inline juce::MidiMessage toMidiMessage (const choc::midi::Sequence::Event& e)
41{
42 return { e.message.data(), (int) e.message.length(), e.timeStamp };
43}
44
45//==============================================================================
47template<typename BufferViewType, typename SampleType, typename SmoothingType>
48void multiplyBy (BufferViewType& view, juce::SmoothedValue<SampleType, SmoothingType>& value) noexcept
49{
50 if (! value.isSmoothing())
51 {
52 choc::buffer::applyGain (view, value.getTargetValue());
53 }
54 else
55 {
56 const auto numChannels = view.getNumChannels();
57 const auto numFrames = view.getNumFrames();
58
59 for (choc::buffer::FrameCount i = 0; i < numFrames; ++i)
60 {
61 const auto scaler = value.getNextValue();
62
63 for (choc::buffer::ChannelCount ch = 0; ch < numChannels; ++ch)
64 view.getSample (ch, i) *= scaler;
65 }
66 }
67}
68
70template<typename BufferType, typename GainType>
71void applyGainRamp (BufferType&& buffer,
72 GainType startGain, GainType endGain) noexcept
73{
74 if (juce::approximatelyEqual (startGain, endGain))
75 {
76 choc::buffer::applyGain (buffer, startGain);
77 }
78 else
79 {
80 auto size = buffer.getSize();
81 const auto increment = (endGain - startGain) / (float) size.getNumFrames();
82 choc::buffer::applyGainPerFrame (buffer,
83 [startGain, increment] (auto frameNum) { return startGain * (increment * frameNum); });
84 }
85}
86
88inline choc::buffer::FrameRange frameRangeWithStartAndLength (choc::buffer::FrameCount start, choc::buffer::FrameCount length)
89{
90 return { start, start + length };
91}
92
94inline choc::buffer::ChannelRange channelRangeWithStartAndLength (choc::buffer::ChannelCount start, choc::buffer::ChannelCount length)
95{
96 return { start, start + length };
97}
98
99
100//==============================================================================
101template<typename Buffer>
102void sanitise (Buffer& buffer)
103{
104 choc::buffer::setAllSamples (buffer,
105 [] (auto s)
106 {
107 return std::isnan (s) ? typename Buffer::Sample() : s;
108 });
109}
110
112template <typename SampleType, template<typename> typename LayoutType>
113void sanityCheckView (const choc::buffer::BufferView<SampleType, LayoutType>& view)
114{
115 if (view.getNumFrames() == 0)
116 return;
117
118 for (choc::buffer::ChannelCount channel = 0; channel < view.getNumChannels(); ++channel)
119 jassert (view.getIterator (channel).sample != nullptr);
120}
121
123template <typename DestBuffer, typename SourceBuffer, typename GainType>
124static void add (DestBuffer&& dest, const SourceBuffer& source, GainType gain)
125{
126 auto size = source.getSize();
127 CHOC_ASSERT (size == dest.getSize());
128
129 for (decltype (size.numChannels) chan = 0; chan < size.numChannels; ++chan)
130 {
131 auto src = source.getIterator (chan);
132 auto dst = dest.getIterator (chan);
133
134 for (decltype (size.numFrames) i = 0; i < size.numFrames; ++i)
135 {
136 *dst += static_cast<decltype (dst.get())> (src.get() * gain);
137 ++dst;
138 ++src;
139 }
140 }
141}
142
144template <typename DestBuffer, typename SourceBuffer, typename GainType>
145static void addApplyingGainRamp (DestBuffer&& dest, const SourceBuffer& source, GainType startGain, GainType endGain)
146{
147 auto size = source.getSize();
148 CHOC_ASSERT (size == dest.getSize());
149
150 const auto delta = (endGain - startGain) / size.numFrames;
151
152 for (decltype (size.numChannels) chan = 0; chan < size.numChannels; ++chan)
153 {
154 auto src = source.getIterator (chan);
155 auto dst = dest.getIterator (chan);
156 auto gain = startGain;
157
158 for (decltype (size.numFrames) i = 0; i < size.numFrames; ++i)
159 {
160 *dst += static_cast<decltype (dst.get())> (src.get() * gain);
161 ++dst;
162 ++src;
163 gain += delta;
164 }
165 }
166}
167
172template <typename DestBuffer, typename SourceBuffer>
173static void copyIfNotAliased (DestBuffer&& dest, const SourceBuffer& source)
174{
175 auto size = source.getSize();
176 CHOC_ASSERT (size == dest.getSize());
177
178 for (decltype (size.numChannels) chan = 0; chan < size.numChannels; ++chan)
179 {
180 auto src = source.getIterator (chan);
181 auto dst = dest.getIterator (chan);
182
183 if (src.sample == dst.sample)
184 continue;
185
186 for (decltype (size.numFrames) i = 0; i < size.numFrames; ++i)
187 {
188 *dst = static_cast<decltype (dst.get())> (src.get());
189 ++dst;
190 ++src;
191 }
192 }
193
194}
195
196}} // namespace tracktion
197
198#ifndef DOXYGEN
199template<>
200struct std::hash<juce::MidiMessageSequence>
201{
202 size_t operator() (const juce::MidiMessageSequence& sequence) const noexcept
203 {
204 size_t seed = 0;
205
206 for (auto meh : sequence)
207 {
208 auto& me = meh->message;
209 tracktion::hash_combine (seed, me.getTimeStamp());
210 tracktion::hash_range (seed, me.getRawData(), me.getRawData() + me.getRawDataSize());
211 }
212
213 return seed;
214 }
215};
216
217template<>
218struct std::hash<std::vector<juce::MidiMessageSequence>>
219{
220 size_t operator() (const std::vector<juce::MidiMessageSequence>& sequences) const noexcept
221 {
222 return tracktion::hash_range (sequences);
223 }
224};
225#endif
int getNumChannels() const noexcept
int getNumSamples() const noexcept
Type *const * getArrayOfWritePointers() noexcept
T is_pointer_v
T isnan(T... args)
#define jassert(expression)
typedef int
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
choc::buffer::BufferView< SampleType, choc::buffer::SeparateChannelLayout > toBufferView(juce::AudioBuffer< SampleType > &buffer)
Converts a juce::AudioBuffer<SampleType> to a choc::buffer::BufferView.
juce::AudioBuffer< float > toAudioBuffer(choc::buffer::ChannelArrayView< float > view)
Creates a juce::AudioBuffer from a choc::buffer::BufferView.
choc::buffer::FrameRange createFrameRange(std::integral auto start, std::integral auto end)
Creates a FrameRange from any integral type.
choc::buffer::ChannelRange channelRangeWithStartAndLength(choc::buffer::ChannelCount start, choc::buffer::ChannelCount length)
Returns a ChannelRange with a start and length.
void sanityCheckView(const choc::buffer::BufferView< SampleType, LayoutType > &view)
Checks that the channels have valid pointers if they have a non-zero number of frames.
void multiplyBy(BufferViewType &view, juce::SmoothedValue< SampleType, SmoothingType > &value) noexcept
Mutiplies a choc::buffer::BufferView by a juce::SmoothedValue.
juce::MidiMessage toMidiMessage(const choc::midi::Sequence::Event &e)
Converts a choc::midi event to a juce::MidiMessage.
void hash_combine(size_t &seed, const T &v)
Hashes a type with a given seed, modifying the seed.
std::size_t hash_range(It first, It last)
Hashes a range with a default seed and returns the new hash value.
void applyGainRamp(BufferType &&buffer, GainType startGain, GainType endGain) noexcept
Applies a gain ram to a choc::buffer::BufferView.
choc::buffer::FrameRange frameRangeWithStartAndLength(choc::buffer::FrameCount start, choc::buffer::FrameCount length)
Returns a FrameRange with a start and length.
T operator()(T... args)
T size(T... args)