comparison audioio/AudioGenerator.cpp @ 4:5865094175ea

* Fix update and play limits for play-selection mode when not looping * Fix playback in loop mode when no selection -- but the GUI update for this is still wrong on the flyback * Various fixes and improvements to making selections, particularly during playback * Draw selection under non-opaque non-scrollable layers, so as to improve cacheing * Show selection limits as text when drawing selection * Allow user to find missing audio files when loading session * Cross-fade selections when in play-selection mode -- mostly. We don't cross-fade on a processing block boundary, and unfortunately with short selections the selection boundary is quite likely to coincide with a block boundary.
author Chris Cannam
date Wed, 25 Jan 2006 17:46:28 +0000
parents df5923e33d01
children 2edc0757ca75
comparison
equal deleted inserted replaced
3:75c3ea1c3a32 4:5865094175ea
148 return m_pluginBlockSize; 148 return m_pluginBlockSize;
149 } 149 }
150 150
151 size_t 151 size_t
152 AudioGenerator::mixModel(Model *model, size_t startFrame, size_t frameCount, 152 AudioGenerator::mixModel(Model *model, size_t startFrame, size_t frameCount,
153 float **buffer) 153 float **buffer, size_t fadeIn, size_t fadeOut)
154 { 154 {
155 if (m_sourceSampleRate == 0) { 155 if (m_sourceSampleRate == 0) {
156 std::cerr << "WARNING: AudioGenerator::mixModel: No base source sample rate available" << std::endl; 156 std::cerr << "WARNING: AudioGenerator::mixModel: No base source sample rate available" << std::endl;
157 return frameCount; 157 return frameCount;
158 } 158 }
167 float pan = parameters->getPlayPan(); 167 float pan = parameters->getPlayPan();
168 168
169 DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model); 169 DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model);
170 if (dtvm) { 170 if (dtvm) {
171 return mixDenseTimeValueModel(dtvm, startFrame, frameCount, 171 return mixDenseTimeValueModel(dtvm, startFrame, frameCount,
172 buffer, gain, pan); 172 buffer, gain, pan, fadeIn, fadeOut);
173 } 173 }
174 174
175 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *> 175 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *>
176 (model); 176 (model);
177 if (sodm) { 177 if (sodm) {
178 return mixSparseOneDimensionalModel(sodm, startFrame, frameCount, 178 return mixSparseOneDimensionalModel(sodm, startFrame, frameCount,
179 buffer, gain, pan); 179 buffer, gain, pan, fadeIn, fadeOut);
180 } 180 }
181 181
182 return frameCount; 182 return frameCount;
183 } 183 }
184 184
185 size_t 185 size_t
186 AudioGenerator::mixDenseTimeValueModel(DenseTimeValueModel *dtvm, 186 AudioGenerator::mixDenseTimeValueModel(DenseTimeValueModel *dtvm,
187 size_t startFrame, size_t frames, 187 size_t startFrame, size_t frames,
188 float **buffer, float gain, float pan) 188 float **buffer, float gain, float pan,
189 size_t fadeIn, size_t fadeOut)
189 { 190 {
190 static float *channelBuffer = 0; 191 static float *channelBuffer = 0;
191 static size_t channelBufSiz = 0; 192 static size_t channelBufSiz = 0;
192 193
193 if (channelBufSiz < frames) { 194 size_t totalFrames = frames + fadeIn/2 + fadeOut/2;
195
196 if (channelBufSiz < totalFrames) {
194 delete[] channelBuffer; 197 delete[] channelBuffer;
195 channelBuffer = new float[frames]; 198 channelBuffer = new float[totalFrames];
196 channelBufSiz = frames; 199 channelBufSiz = totalFrames;
197 } 200 }
198 201
199 size_t got = 0; 202 size_t got = 0;
200 203
201 for (size_t c = 0; c < m_targetChannelCount && c < dtvm->getChannelCount(); ++c) { 204 for (size_t c = 0; c < m_targetChannelCount && c < dtvm->getChannelCount(); ++c) {
202 got = dtvm->getValues(c, startFrame, startFrame + frames, channelBuffer); 205
203 for (size_t i = 0; i < frames; ++i) { 206 got = dtvm->getValues
204 buffer[c][i] += gain * channelBuffer[i]; 207 (c, startFrame - fadeIn/2, startFrame + frames + fadeOut/2,
208 channelBuffer);
209
210 for (size_t i = 0; i < fadeIn/2; ++i) {
211 float *back = buffer[c];
212 back -= fadeIn/2;
213 back[i] += (gain * channelBuffer[i] * i) / fadeIn;
214 }
215
216 for (size_t i = 0; i < frames + fadeOut/2; ++i) {
217 float mult = gain;
218 if (i < fadeIn/2) {
219 mult = (mult * i) / fadeIn;
220 }
221 if (i > frames - fadeOut/2) {
222 mult = (mult * ((frames + fadeOut/2) - i)) / fadeOut;
223 }
224 buffer[c][i] += mult * channelBuffer[i];
205 } 225 }
206 } 226 }
207 227
208 return got; 228 return got;
209 } 229 }
210 230
211 size_t 231 size_t
212 AudioGenerator::mixSparseOneDimensionalModel(SparseOneDimensionalModel *sodm, 232 AudioGenerator::mixSparseOneDimensionalModel(SparseOneDimensionalModel *sodm,
213 size_t startFrame, size_t frames, 233 size_t startFrame, size_t frames,
214 float **buffer, float gain, float pan) 234 float **buffer, float gain, float pan,
235 size_t /* fadeIn */,
236 size_t /* fadeOut */)
215 { 237 {
216 RealTimePluginInstance *plugin = m_synthMap[sodm]; 238 RealTimePluginInstance *plugin = m_synthMap[sodm];
217 if (!plugin) return 0; 239 if (!plugin) return 0;
218 240
219 size_t latency = plugin->getLatency(); 241 size_t latency = plugin->getLatency();