Mercurial > hg > svapp
comparison audioio/AudioPulseAudioTarget.cpp @ 120:2aa263b384f8
* Fix to PulseAudio output -- it works rather better now it's being fed
the right number of samples and not 8 times as many
| author | Chris Cannam |
|---|---|
| date | Fri, 23 May 2008 15:36:20 +0000 |
| parents | 1ba557a20ca3 |
| children | 4c9c04645685 |
comparison
equal
deleted
inserted
replaced
| 119:1ba557a20ca3 | 120:2aa263b384f8 |
|---|---|
| 22 | 22 |
| 23 #include <iostream> | 23 #include <iostream> |
| 24 #include <cassert> | 24 #include <cassert> |
| 25 #include <cmath> | 25 #include <cmath> |
| 26 | 26 |
| 27 #define DEBUG_AUDIO_PULSE_AUDIO_TARGET 1 | 27 //#define DEBUG_AUDIO_PULSE_AUDIO_TARGET 1 |
| 28 | 28 |
| 29 AudioPulseAudioTarget::AudioPulseAudioTarget(AudioCallbackPlaySource *source) : | 29 AudioPulseAudioTarget::AudioPulseAudioTarget(AudioCallbackPlaySource *source) : |
| 30 AudioCallbackPlayTarget(source), | 30 AudioCallbackPlayTarget(source), |
| 31 m_mutex(QMutex::Recursive), | 31 m_mutex(QMutex::Recursive), |
| 32 m_loop(0), | 32 m_loop(0), |
| 147 | 147 |
| 148 target->streamWrite(length); | 148 target->streamWrite(length); |
| 149 } | 149 } |
| 150 | 150 |
| 151 void | 151 void |
| 152 AudioPulseAudioTarget::streamWrite(size_t nframes) | 152 AudioPulseAudioTarget::streamWrite(size_t requested) |
| 153 { | 153 { |
| 154 #ifdef DEBUG_AUDIO_PULSE_AUDIO_TARGET | 154 #ifdef DEBUG_AUDIO_PULSE_AUDIO_TARGET |
| 155 std::cout << "AudioPulseAudioTarget::streamWrite(" << nframes << ")" << std::endl; | 155 std::cout << "AudioPulseAudioTarget::streamWrite(" << requested << ")" << std::endl; |
| 156 #endif | 156 #endif |
| 157 if (m_done) return; | 157 if (m_done) return; |
| 158 | 158 |
| 159 QMutexLocker locker(&m_mutex); | 159 QMutexLocker locker(&m_mutex); |
| 160 | 160 |
| 169 int latframes = (latency / 1000000.f) * float(m_sampleRate); | 169 int latframes = (latency / 1000000.f) * float(m_sampleRate); |
| 170 std::cerr << "that's " << latframes << " frames" << std::endl; | 170 std::cerr << "that's " << latframes << " frames" << std::endl; |
| 171 m_source->setTargetPlayLatency(latframes); //!!! buh | 171 m_source->setTargetPlayLatency(latframes); //!!! buh |
| 172 } | 172 } |
| 173 | 173 |
| 174 if (nframes > m_bufferSize) { | |
| 175 std::cerr << "WARNING: AudioPulseAudioTarget::streamWrite: nframes " << nframes << " > m_bufferSize " << m_bufferSize << std::endl; | |
| 176 } | |
| 177 | |
| 178 static float *output = 0; | 174 static float *output = 0; |
| 179 static float **tmpbuf = 0; | 175 static float **tmpbuf = 0; |
| 180 static size_t tmpbufch = 0; | 176 static size_t tmpbufch = 0; |
| 181 static size_t tmpbufsz = 0; | 177 static size_t tmpbufsz = 0; |
| 182 | 178 |
| 183 size_t sourceChannels = m_source->getSourceChannelCount(); | 179 size_t sourceChannels = m_source->getSourceChannelCount(); |
| 184 | 180 |
| 185 // Because we offer pan, we always want at least 2 channels | 181 // Because we offer pan, we always want at least 2 channels |
| 186 if (sourceChannels < 2) sourceChannels = 2; | 182 if (sourceChannels < 2) sourceChannels = 2; |
| 183 | |
| 184 size_t nframes = requested / (sourceChannels * sizeof(float)); | |
| 185 | |
| 186 if (nframes > m_bufferSize) { | |
| 187 std::cerr << "WARNING: AudioPulseAudioTarget::streamWrite: nframes " << nframes << " > m_bufferSize " << m_bufferSize << std::endl; | |
| 188 } | |
| 189 | |
| 190 #ifdef DEBUG_AUDIO_PULSE_AUDIO_TARGET | |
| 191 std::cout << "AudioPulseAudioTarget::streamWrite: nframes = " << nframes << std::endl; | |
| 192 #endif | |
| 187 | 193 |
| 188 if (!tmpbuf || tmpbufch != sourceChannels || int(tmpbufsz) < nframes) { | 194 if (!tmpbuf || tmpbufch != sourceChannels || int(tmpbufsz) < nframes) { |
| 189 | 195 |
| 190 if (tmpbuf) { | 196 if (tmpbuf) { |
| 191 for (size_t i = 0; i < tmpbufch; ++i) { | 197 for (size_t i = 0; i < tmpbufch; ++i) { |
| 209 output = new float[tmpbufsz * tmpbufch]; | 215 output = new float[tmpbufsz * tmpbufch]; |
| 210 } | 216 } |
| 211 | 217 |
| 212 size_t received = m_source->getSourceSamples(nframes, tmpbuf); | 218 size_t received = m_source->getSourceSamples(nframes, tmpbuf); |
| 213 | 219 |
| 220 #ifdef DEBUG_AUDIO_PULSE_AUDIO_TARGET | |
| 214 std::cerr << "requested " << nframes << ", received " << received << std::endl; | 221 std::cerr << "requested " << nframes << ", received " << received << std::endl; |
| 222 | |
| 215 if (received < nframes) { | 223 if (received < nframes) { |
| 216 std::cerr << "*** WARNING: Wrong number of frames received" << std::endl; | 224 std::cerr << "*** WARNING: Wrong number of frames received" << std::endl; |
| 217 } | 225 } |
| 226 #endif | |
| 218 | 227 |
| 219 float peakLeft = 0.0, peakRight = 0.0; | 228 float peakLeft = 0.0, peakRight = 0.0; |
| 220 | 229 |
| 221 for (size_t ch = 0; ch < 2; ++ch) { | 230 for (size_t ch = 0; ch < 2; ++ch) { |
| 222 | 231 |
| 255 | 264 |
| 256 if (ch == 0) peakLeft = peak; | 265 if (ch == 0) peakLeft = peak; |
| 257 if (ch > 0 || sourceChannels == 1) peakRight = peak; | 266 if (ch > 0 || sourceChannels == 1) peakRight = peak; |
| 258 } | 267 } |
| 259 | 268 |
| 269 #ifdef DEBUG_AUDIO_PULSE_AUDIO_TARGET | |
| 270 std::cerr << "calling pa_stream_write with " | |
| 271 << nframes * tmpbufch * sizeof(float) << " bytes" << std::endl; | |
| 272 #endif | |
| 273 | |
| 260 pa_stream_write(m_stream, output, nframes * tmpbufch * sizeof(float), | 274 pa_stream_write(m_stream, output, nframes * tmpbufch * sizeof(float), |
| 261 0, 0, PA_SEEK_RELATIVE); | 275 0, 0, PA_SEEK_RELATIVE); |
| 262 | 276 |
| 263 m_source->setOutputLevels(peakLeft, peakRight); | 277 m_source->setOutputLevels(peakLeft, peakRight); |
| 264 | 278 |
| 337 m_stream = pa_stream_new(m_context, "stream", &m_spec, 0); | 351 m_stream = pa_stream_new(m_context, "stream", &m_spec, 0); |
| 338 assert(m_stream); //!!! | 352 assert(m_stream); //!!! |
| 339 | 353 |
| 340 pa_stream_set_state_callback(m_stream, streamStateChangedStatic, this); | 354 pa_stream_set_state_callback(m_stream, streamStateChangedStatic, this); |
| 341 pa_stream_set_write_callback(m_stream, streamWriteStatic, this); | 355 pa_stream_set_write_callback(m_stream, streamWriteStatic, this); |
| 356 pa_stream_set_overflow_callback(m_stream, streamOverflowStatic, this); | |
| 357 pa_stream_set_underflow_callback(m_stream, streamUnderflowStatic, this); | |
| 342 | 358 |
| 343 if (pa_stream_connect_playback | 359 if (pa_stream_connect_playback |
| 344 (m_stream, 0, 0, | 360 (m_stream, 0, 0, |
| 345 pa_stream_flags_t(PA_STREAM_INTERPOLATE_TIMING | | 361 pa_stream_flags_t(PA_STREAM_INTERPOLATE_TIMING | |
| 346 PA_STREAM_AUTO_TIMING_UPDATE), | 362 PA_STREAM_AUTO_TIMING_UPDATE), |
| 387 //!!! do something... | 403 //!!! do something... |
| 388 break; | 404 break; |
| 389 } | 405 } |
| 390 } | 406 } |
| 391 | 407 |
| 408 void | |
| 409 AudioPulseAudioTarget::streamOverflowStatic(pa_stream *, void *) | |
| 410 { | |
| 411 std::cerr << "AudioPulseAudioTarget::streamOverflowStatic: Overflow!" << std::endl; | |
| 412 } | |
| 413 | |
| 414 void | |
| 415 AudioPulseAudioTarget::streamUnderflowStatic(pa_stream *, void *) | |
| 416 { | |
| 417 std::cerr << "AudioPulseAudioTarget::streamUnderflowStatic: Underflow!" << std::endl; | |
| 418 } | |
| 419 | |
| 392 #endif /* HAVE_PULSEAUDIO */ | 420 #endif /* HAVE_PULSEAUDIO */ |
| 393 | 421 |
