comparison audioio/ClipMixer.cpp @ 441:aa6fb3516e28 tonioni

Merge from cxx11 branch
author Chris Cannam
date Mon, 23 Mar 2015 11:26:28 +0000
parents 72c662fe7ea3
children 88ae0e53a5da
comparison
equal deleted inserted replaced
440:2185d52b4758 441:aa6fb3516e28
18 #include <sndfile.h> 18 #include <sndfile.h>
19 #include <cmath> 19 #include <cmath>
20 20
21 #include "base/Debug.h" 21 #include "base/Debug.h"
22 22
23 ClipMixer::ClipMixer(int channels, int sampleRate, int blockSize) : 23 ClipMixer::ClipMixer(int channels, sv_samplerate_t sampleRate, sv_frame_t blockSize) :
24 m_channels(channels), 24 m_channels(channels),
25 m_sampleRate(sampleRate), 25 m_sampleRate(sampleRate),
26 m_blockSize(blockSize), 26 m_blockSize(blockSize),
27 m_clipData(0), 27 m_clipData(0),
28 m_clipLength(0), 28 m_clipLength(0),
41 { 41 {
42 m_channels = channels; 42 m_channels = channels;
43 } 43 }
44 44
45 bool 45 bool
46 ClipMixer::loadClipData(QString path, float f0, float level) 46 ClipMixer::loadClipData(QString path, double f0, double level)
47 { 47 {
48 if (m_clipData) { 48 if (m_clipData) {
49 cerr << "ClipMixer::loadClipData: Already have clip loaded" << endl; 49 cerr << "ClipMixer::loadClipData: Already have clip loaded" << endl;
50 return false; 50 return false;
51 } 51 }
52 52
53 SF_INFO info; 53 SF_INFO info;
54 SNDFILE *file; 54 SNDFILE *file;
55 float *tmpFrames; 55 float *tmpFrames;
56 int i; 56 sv_frame_t i;
57 57
58 info.format = 0; 58 info.format = 0;
59 file = sf_open(path.toLocal8Bit().data(), SFM_READ, &info); 59 file = sf_open(path.toLocal8Bit().data(), SFM_READ, &info);
60 if (!file) { 60 if (!file) {
61 cerr << "ClipMixer::loadClipData: Failed to open file path \"" 61 cerr << "ClipMixer::loadClipData: Failed to open file path \""
81 81
82 for (i = 0; i < info.frames; ++i) { 82 for (i = 0; i < info.frames; ++i) {
83 int j; 83 int j;
84 m_clipData[i] = 0.0f; 84 m_clipData[i] = 0.0f;
85 for (j = 0; j < info.channels; ++j) { 85 for (j = 0; j < info.channels; ++j) {
86 m_clipData[i] += tmpFrames[i * info.channels + j] * level; 86 m_clipData[i] += tmpFrames[i * info.channels + j] * float(level);
87 } 87 }
88 } 88 }
89 89
90 free(tmpFrames); 90 free(tmpFrames);
91 91
100 ClipMixer::reset() 100 ClipMixer::reset()
101 { 101 {
102 m_playing.clear(); 102 m_playing.clear();
103 } 103 }
104 104
105 float 105 double
106 ClipMixer::getResampleRatioFor(float frequency) 106 ClipMixer::getResampleRatioFor(double frequency)
107 { 107 {
108 if (!m_clipData || !m_clipRate) return 1.0; 108 if (!m_clipData || !m_clipRate) return 1.0;
109 float pitchRatio = m_clipF0 / frequency; 109 double pitchRatio = m_clipF0 / frequency;
110 float resampleRatio = m_sampleRate / m_clipRate; 110 double resampleRatio = m_sampleRate / m_clipRate;
111 return pitchRatio * resampleRatio; 111 return pitchRatio * resampleRatio;
112 } 112 }
113 113
114 int 114 sv_frame_t
115 ClipMixer::getResampledClipDuration(float frequency) 115 ClipMixer::getResampledClipDuration(double frequency)
116 { 116 {
117 return int(ceil(m_clipLength * getResampleRatioFor(frequency))); 117 return sv_frame_t(ceil(double(m_clipLength) * getResampleRatioFor(frequency)));
118 } 118 }
119 119
120 void 120 void
121 ClipMixer::mix(float **toBuffers, 121 ClipMixer::mix(float **toBuffers,
122 float gain, 122 float gain,
144 144
145 for (int c = 0; c < m_channels; ++c) { 145 for (int c = 0; c < m_channels; ++c) {
146 levels[c] = note.level * gain; 146 levels[c] = note.level * gain;
147 } 147 }
148 if (note.pan != 0.0 && m_channels == 2) { 148 if (note.pan != 0.0 && m_channels == 2) {
149 levels[0] *= 1.0 - note.pan; 149 levels[0] *= 1.0f - note.pan;
150 levels[1] *= note.pan + 1.0; 150 levels[1] *= note.pan + 1.0f;
151 } 151 }
152 152
153 int start = note.frameOffset; 153 sv_frame_t start = note.frameOffset;
154 int durationHere = m_blockSize; 154 sv_frame_t durationHere = m_blockSize;
155 if (start > 0) durationHere = m_blockSize - start; 155 if (start > 0) durationHere = m_blockSize - start;
156 156
157 bool ending = false; 157 bool ending = false;
158 158
159 foreach (NoteEnd end, endingNotes) { 159 foreach (NoteEnd end, endingNotes) {
165 if (start > 0) durationHere = end.frameOffset - start; 165 if (start > 0) durationHere = end.frameOffset - start;
166 break; 166 break;
167 } 167 }
168 } 168 }
169 169
170 int clipDuration = getResampledClipDuration(note.frequency); 170 sv_frame_t clipDuration = getResampledClipDuration(note.frequency);
171 if (start + clipDuration > 0) { 171 if (start + clipDuration > 0) {
172 if (start < 0 && start + clipDuration < durationHere) { 172 if (start < 0 && start + clipDuration < durationHere) {
173 durationHere = start + clipDuration; 173 durationHere = start + clipDuration;
174 } 174 }
175 if (durationHere > 0) { 175 if (durationHere > 0) {
197 197
198 void 198 void
199 ClipMixer::mixNote(float **toBuffers, 199 ClipMixer::mixNote(float **toBuffers,
200 float *levels, 200 float *levels,
201 float frequency, 201 float frequency,
202 int sourceOffset, 202 sv_frame_t sourceOffset,
203 int targetOffset, 203 sv_frame_t targetOffset,
204 int sampleCount, 204 sv_frame_t sampleCount,
205 bool isEnd) 205 bool isEnd)
206 { 206 {
207 if (!m_clipData) return; 207 if (!m_clipData) return;
208 208
209 float ratio = getResampleRatioFor(frequency); 209 double ratio = getResampleRatioFor(frequency);
210 210
211 float releaseTime = 0.01; 211 double releaseTime = 0.01;
212 int releaseSampleCount = round(releaseTime * m_sampleRate); 212 sv_frame_t releaseSampleCount = sv_frame_t(round(releaseTime * m_sampleRate));
213 if (releaseSampleCount > sampleCount) { 213 if (releaseSampleCount > sampleCount) {
214 releaseSampleCount = sampleCount; 214 releaseSampleCount = sampleCount;
215 } 215 }
216 float releaseFraction = 1.f/releaseSampleCount; 216 double releaseFraction = 1.0/double(releaseSampleCount);
217 217
218 for (int i = 0; i < sampleCount; ++i) { 218 for (sv_frame_t i = 0; i < sampleCount; ++i) {
219 219
220 int s = sourceOffset + i; 220 sv_frame_t s = sourceOffset + i;
221 221
222 float os = s / ratio; 222 double os = double(s) / ratio;
223 int osi = int(floor(os)); 223 sv_frame_t osi = sv_frame_t(floor(os));
224 224
225 //!!! just linear interpolation for now (same as SV's sample 225 //!!! just linear interpolation for now (same as SV's sample
226 //!!! player). a small sinc kernel would be better and 226 //!!! player). a small sinc kernel would be better and
227 //!!! probably "good enough" 227 //!!! probably "good enough"
228 float value = 0.f; 228 double value = 0.0;
229 if (osi < m_clipLength) { 229 if (osi < m_clipLength) {
230 value += m_clipData[osi]; 230 value += m_clipData[osi];
231 } 231 }
232 if (osi + 1 < m_clipLength) { 232 if (osi + 1 < m_clipLength) {
233 value += (m_clipData[osi + 1] - m_clipData[osi]) * (os - osi); 233 value += (m_clipData[osi + 1] - m_clipData[osi]) * (os - double(osi));
234 } 234 }
235 235
236 if (isEnd && i + releaseSampleCount > sampleCount) { 236 if (isEnd && i + releaseSampleCount > sampleCount) {
237 value *= releaseFraction * (sampleCount - i); // linear ramp for release 237 value *= releaseFraction * double(sampleCount - i); // linear ramp for release
238 } 238 }
239 239
240 for (int c = 0; c < m_channels; ++c) { 240 for (int c = 0; c < m_channels; ++c) {
241 toBuffers[c][targetOffset + i] += levels[c] * value; 241 toBuffers[c][targetOffset + i] += float(levels[c] * value);
242 } 242 }
243 } 243 }
244 } 244 }
245 245
246 246