annotate audioio/AudioPortAudioTarget.cpp @ 16:ba31fa322f93

* Fix a crash in PortAudio output for mono data * Don't construct a chromagram in TonalChangeDetect plugin ctor * Update layer show/hide/dormancy for multi-view-capable layers -- the dormancy concept doesn't really work with these constraints any more
author Chris Cannam
date Fri, 03 Mar 2006 17:52:21 +0000
parents df5923e33d01
children c606d3ffa397
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 A waveform viewer and audio annotation editor.
Chris@2 5 Chris Cannam, Queen Mary University of London, 2005-2006
Chris@0 6
Chris@0 7 This is experimental software. Not for distribution.
Chris@0 8 */
Chris@0 9
Chris@0 10 #ifdef HAVE_PORTAUDIO
Chris@0 11
Chris@0 12 #include "AudioPortAudioTarget.h"
Chris@0 13 #include "AudioCallbackPlaySource.h"
Chris@0 14
Chris@0 15 #include <iostream>
Chris@0 16 #include <cassert>
Chris@0 17 #include <cmath>
Chris@0 18
Chris@0 19 //#define DEBUG_AUDIO_PORT_AUDIO_TARGET 1
Chris@0 20
Chris@0 21 AudioPortAudioTarget::AudioPortAudioTarget(AudioCallbackPlaySource *source) :
Chris@0 22 AudioCallbackPlayTarget(source),
Chris@0 23 m_stream(0),
Chris@0 24 m_bufferSize(0),
Chris@0 25 m_sampleRate(0),
Chris@0 26 m_latency(0)
Chris@0 27 {
Chris@0 28 PaError err;
Chris@0 29
Chris@0 30 err = Pa_Initialize();
Chris@0 31 if (err != paNoError) {
Chris@0 32 std::cerr << "ERROR: AudioPortAudioTarget: Failed to initialize PortAudio" << std::endl;
Chris@0 33 return;
Chris@0 34 }
Chris@0 35
Chris@0 36 m_bufferSize = 1024;
Chris@0 37 m_sampleRate = 44100;
Chris@0 38 if (m_source && (m_source->getSourceSampleRate() != 0)) {
Chris@0 39 m_sampleRate = m_source->getSourceSampleRate();
Chris@0 40 }
Chris@0 41
Chris@0 42 m_latency = Pa_GetMinNumBuffers(m_bufferSize, m_sampleRate) * m_bufferSize;
Chris@0 43
Chris@0 44 err = Pa_OpenDefaultStream(&m_stream, 0, 2, paFloat32,
Chris@0 45 m_sampleRate, m_bufferSize, 0,
Chris@0 46 processStatic, this);
Chris@0 47
Chris@0 48 if (err != paNoError) {
Chris@0 49 std::cerr << "ERROR: AudioPortAudioTarget: Failed to open PortAudio stream" << std::endl;
Chris@0 50 m_stream = 0;
Chris@0 51 Pa_Terminate();
Chris@0 52 return;
Chris@0 53 }
Chris@0 54
Chris@0 55 err = Pa_StartStream(m_stream);
Chris@0 56
Chris@0 57 if (err != paNoError) {
Chris@0 58 std::cerr << "ERROR: AudioPortAudioTarget: Failed to start PortAudio stream" << std::endl;
Chris@0 59 Pa_CloseStream(m_stream);
Chris@0 60 m_stream = 0;
Chris@0 61 Pa_Terminate();
Chris@0 62 return;
Chris@0 63 }
Chris@0 64
Chris@0 65 if (m_source) {
Chris@0 66 std::cerr << "AudioPortAudioTarget: block size " << m_bufferSize << std::endl;
Chris@0 67 m_source->setTargetBlockSize(m_bufferSize);
Chris@0 68 m_source->setTargetSampleRate(m_sampleRate);
Chris@0 69 m_source->setTargetPlayLatency(m_latency);
Chris@0 70 }
Chris@0 71 }
Chris@0 72
Chris@0 73 AudioPortAudioTarget::~AudioPortAudioTarget()
Chris@0 74 {
Chris@0 75 if (m_stream) {
Chris@0 76 PaError err;
Chris@0 77 err = Pa_CloseStream(m_stream);
Chris@0 78 if (err != paNoError) {
Chris@0 79 std::cerr << "ERROR: AudioPortAudioTarget: Failed to close PortAudio stream" << std::endl;
Chris@0 80 }
Chris@0 81 Pa_Terminate();
Chris@0 82 }
Chris@0 83 }
Chris@0 84
Chris@0 85 bool
Chris@0 86 AudioPortAudioTarget::isOK() const
Chris@0 87 {
Chris@0 88 return (m_stream != 0);
Chris@0 89 }
Chris@0 90
Chris@0 91 int
Chris@0 92 AudioPortAudioTarget::processStatic(void *input, void *output,
Chris@0 93 unsigned long nframes,
Chris@0 94 PaTimestamp outTime, void *data)
Chris@0 95 {
Chris@0 96 return ((AudioPortAudioTarget *)data)->process(input, output,
Chris@0 97 nframes, outTime);
Chris@0 98 }
Chris@0 99
Chris@0 100 void
Chris@0 101 AudioPortAudioTarget::sourceModelReplaced()
Chris@0 102 {
Chris@0 103 m_source->setTargetSampleRate(m_sampleRate);
Chris@0 104 }
Chris@0 105
Chris@0 106 int
Chris@0 107 AudioPortAudioTarget::process(void *inputBuffer, void *outputBuffer,
Chris@0 108 unsigned long nframes,
Chris@0 109 PaTimestamp)
Chris@0 110 {
Chris@0 111 #ifdef DEBUG_AUDIO_PORT_AUDIO_TARGET
Chris@0 112 std::cout << "AudioPortAudioTarget::process(" << nframes << ")" << std::endl;
Chris@0 113 #endif
Chris@0 114
Chris@0 115 if (!m_source) return 0;
Chris@0 116
Chris@0 117 float *output = (float *)outputBuffer;
Chris@0 118
Chris@0 119 assert(nframes <= m_bufferSize);
Chris@0 120
Chris@0 121 static float **tmpbuf = 0;
Chris@0 122 static size_t tmpbufch = 0;
Chris@0 123 static size_t tmpbufsz = 0;
Chris@0 124
Chris@0 125 size_t sourceChannels = m_source->getSourceChannelCount();
Chris@0 126
Chris@16 127 // Because we offer pan, we always want at least 2 channels
Chris@16 128 if (sourceChannels < 2) sourceChannels = 2;
Chris@16 129
Chris@0 130 if (!tmpbuf || tmpbufch != sourceChannels || tmpbufsz < m_bufferSize) {
Chris@0 131
Chris@0 132 if (tmpbuf) {
Chris@0 133 for (size_t i = 0; i < tmpbufch; ++i) {
Chris@0 134 delete[] tmpbuf[i];
Chris@0 135 }
Chris@0 136 delete[] tmpbuf;
Chris@0 137 }
Chris@0 138
Chris@0 139 tmpbufch = sourceChannels;
Chris@0 140 tmpbufsz = m_bufferSize;
Chris@0 141 tmpbuf = new float *[tmpbufch];
Chris@0 142
Chris@0 143 for (size_t i = 0; i < tmpbufch; ++i) {
Chris@0 144 tmpbuf[i] = new float[tmpbufsz];
Chris@0 145 }
Chris@0 146 }
Chris@0 147
Chris@0 148 m_source->getSourceSamples(nframes, tmpbuf);
Chris@0 149
Chris@0 150 float peakLeft = 0.0, peakRight = 0.0;
Chris@0 151
Chris@0 152 for (size_t ch = 0; ch < 2; ++ch) {
Chris@0 153
Chris@0 154 float peak = 0.0;
Chris@0 155
Chris@0 156 if (ch < sourceChannels) {
Chris@0 157
Chris@0 158 // PortAudio samples are interleaved
Chris@0 159 for (size_t i = 0; i < nframes; ++i) {
Chris@0 160 output[i * 2 + ch] = tmpbuf[ch][i] * m_outputGain;
Chris@0 161 float sample = fabsf(output[i * 2 + ch]);
Chris@0 162 if (sample > peak) peak = sample;
Chris@0 163 }
Chris@0 164
Chris@0 165 } else if (ch == 1 && sourceChannels == 1) {
Chris@0 166
Chris@0 167 for (size_t i = 0; i < nframes; ++i) {
Chris@0 168 output[i * 2 + ch] = tmpbuf[0][i] * m_outputGain;
Chris@0 169 float sample = fabsf(output[i * 2 + ch]);
Chris@0 170 if (sample > peak) peak = sample;
Chris@0 171 }
Chris@0 172
Chris@0 173 } else {
Chris@0 174 for (size_t i = 0; i < nframes; ++i) {
Chris@0 175 output[i * 2 + ch] = 0;
Chris@0 176 }
Chris@0 177 }
Chris@0 178
Chris@0 179 if (ch == 0) peakLeft = peak;
Chris@0 180 if (ch > 0 || sourceChannels == 1) peakRight = peak;
Chris@0 181 }
Chris@0 182
Chris@0 183 m_source->setOutputLevels(peakLeft, peakRight);
Chris@0 184
Chris@0 185 return 0;
Chris@0 186 }
Chris@0 187
Chris@0 188 #ifdef INCLUDE_MOCFILES
Chris@0 189 #include "AudioPortAudioTarget.moc.cpp"
Chris@0 190 #endif
Chris@0 191
Chris@0 192 #endif /* HAVE_PORTAUDIO */
Chris@0 193