annotate audioio/AudioPortAudioTarget.cpp @ 21:ebe07d3560e6

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