OpenShot Audio Library | OpenShotAudio  0.6.0
juce_AudioSourcePlayer.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2022 - Raw Material Software Limited
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
27 {
28 }
29 
31 {
32  setSource (nullptr);
33 }
34 
36 {
37  if (source != newSource)
38  {
39  auto* oldSource = source;
40 
41  if (newSource != nullptr && bufferSize > 0 && sampleRate > 0)
42  newSource->prepareToPlay (bufferSize, sampleRate);
43 
44  {
45  const ScopedLock sl (readLock);
46  source = newSource;
47  }
48 
49  if (oldSource != nullptr)
50  oldSource->releaseResources();
51  }
52 }
53 
54 void AudioSourcePlayer::setGain (const float newGain) noexcept
55 {
56  gain = newGain;
57 }
58 
59 void AudioSourcePlayer::audioDeviceIOCallbackWithContext (const float* const* inputChannelData,
60  int totalNumInputChannels,
61  float* const* outputChannelData,
62  int totalNumOutputChannels,
63  int numSamples,
64  [[maybe_unused]] const AudioIODeviceCallbackContext& context)
65 {
66  // these should have been prepared by audioDeviceAboutToStart()...
67  jassert (sampleRate > 0 && bufferSize > 0);
68 
69  const ScopedLock sl (readLock);
70 
71  if (source != nullptr)
72  {
73  int numActiveChans = 0, numInputs = 0, numOutputs = 0;
74 
75  // messy stuff needed to compact the channels down into an array
76  // of non-zero pointers..
77  for (int i = 0; i < totalNumInputChannels; ++i)
78  {
79  if (inputChannelData[i] != nullptr)
80  {
81  inputChans [numInputs++] = inputChannelData[i];
82  if (numInputs >= numElementsInArray (inputChans))
83  break;
84  }
85  }
86 
87  for (int i = 0; i < totalNumOutputChannels; ++i)
88  {
89  if (outputChannelData[i] != nullptr)
90  {
91  outputChans [numOutputs++] = outputChannelData[i];
92  if (numOutputs >= numElementsInArray (outputChans))
93  break;
94  }
95  }
96 
97  if (numInputs > numOutputs)
98  {
99  // if there aren't enough output channels for the number of
100  // inputs, we need to create some temporary extra ones (can't
101  // use the input data in case it gets written to)
102  tempBuffer.setSize (numInputs - numOutputs, numSamples,
103  false, false, true);
104 
105  for (int i = 0; i < numOutputs; ++i)
106  {
107  channels[numActiveChans] = outputChans[i];
108  memcpy (channels[numActiveChans], inputChans[i], (size_t) numSamples * sizeof (float));
109  ++numActiveChans;
110  }
111 
112  for (int i = numOutputs; i < numInputs; ++i)
113  {
114  channels[numActiveChans] = tempBuffer.getWritePointer (i - numOutputs);
115  memcpy (channels[numActiveChans], inputChans[i], (size_t) numSamples * sizeof (float));
116  ++numActiveChans;
117  }
118  }
119  else
120  {
121  for (int i = 0; i < numInputs; ++i)
122  {
123  channels[numActiveChans] = outputChans[i];
124  memcpy (channels[numActiveChans], inputChans[i], (size_t) numSamples * sizeof (float));
125  ++numActiveChans;
126  }
127 
128  for (int i = numInputs; i < numOutputs; ++i)
129  {
130  channels[numActiveChans] = outputChans[i];
131  zeromem (channels[numActiveChans], (size_t) numSamples * sizeof (float));
132  ++numActiveChans;
133  }
134  }
135 
136  AudioBuffer<float> buffer (channels, numActiveChans, numSamples);
137 
138  AudioSourceChannelInfo info (&buffer, 0, numSamples);
139  source->getNextAudioBlock (info);
140 
141  for (int i = info.buffer->getNumChannels(); --i >= 0;)
142  buffer.applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain);
143 
144  lastGain = gain;
145  }
146  else
147  {
148  for (int i = 0; i < totalNumOutputChannels; ++i)
149  if (outputChannelData[i] != nullptr)
150  zeromem (outputChannelData[i], (size_t) numSamples * sizeof (float));
151  }
152 }
153 
155 {
157  device->getCurrentBufferSizeSamples());
158 }
159 
160 void AudioSourcePlayer::prepareToPlay (double newSampleRate, int newBufferSize)
161 {
162  sampleRate = newSampleRate;
163  bufferSize = newBufferSize;
164  zeromem (channels, sizeof (channels));
165 
166  if (source != nullptr)
167  source->prepareToPlay (bufferSize, sampleRate);
168 }
169 
171 {
172  if (source != nullptr)
173  source->releaseResources();
174 
175  sampleRate = 0.0;
176  bufferSize = 0;
177 
178  tempBuffer.setSize (2, 8);
179 }
180 
181 } // namespace juce
void setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
Type * getWritePointer(int channelNumber) noexcept
int getNumChannels() const noexcept
void applyGainRamp(int channel, int startSample, int numSamples, Type startGain, Type endGain) noexcept
virtual double getCurrentSampleRate()=0
virtual int getCurrentBufferSizeSamples()=0
void setGain(float newGain) noexcept
void setSource(AudioSource *newSource)
void audioDeviceIOCallbackWithContext(const float *const *inputChannelData, int totalNumInputChannels, float *const *outputChannelData, int totalNumOutputChannels, int numSamples, const AudioIODeviceCallbackContext &context) override
void prepareToPlay(double sampleRate, int blockSize)
void audioDeviceAboutToStart(AudioIODevice *device) override
virtual void releaseResources()=0
virtual void prepareToPlay(int samplesPerBlockExpected, double sampleRate)=0
virtual void getNextAudioBlock(const AudioSourceChannelInfo &bufferToFill)=0
AudioBuffer< float > * buffer