annotate audioio/AudioPortAudioTarget.cpp @ 12:ee967635c728

* Some work on making the time stretcher squash as well as stretch
author Chris Cannam
date Tue, 12 Sep 2006 16:43:00 +0000
parents cd5d7ff8ef38
children 52409ab73526
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 Sonic Visualiser
Chris@0 5 An audio file viewer and annotation editor.
Chris@0 6 Centre for Digital Music, Queen Mary, University of London.
Chris@0 7 This file copyright 2006 Chris Cannam.
Chris@0 8
Chris@0 9 This program is free software; you can redistribute it and/or
Chris@0 10 modify it under the terms of the GNU General Public License as
Chris@0 11 published by the Free Software Foundation; either version 2 of the
Chris@0 12 License, or (at your option) any later version. See the file
Chris@0 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 std::cerr << "\n\n\nLATENCY= " << m_latency << std::endl;
Chris@0 51
Chris@0 52 err = Pa_OpenDefaultStream(&m_stream, 0, 2, paFloat32,
Chris@0 53 m_sampleRate, m_bufferSize, 0,
Chris@0 54 processStatic, this);
Chris@0 55
Chris@0 56 if (err != paNoError) {
Chris@0 57 std::cerr << "ERROR: AudioPortAudioTarget: Failed to open PortAudio stream" << std::endl;
Chris@0 58 m_stream = 0;
Chris@0 59 Pa_Terminate();
Chris@0 60 return;
Chris@0 61 }
Chris@0 62
Chris@0 63 err = Pa_StartStream(m_stream);
Chris@0 64
Chris@0 65 if (err != paNoError) {
Chris@0 66 std::cerr << "ERROR: AudioPortAudioTarget: Failed to start PortAudio stream" << std::endl;
Chris@0 67 Pa_CloseStream(m_stream);
Chris@0 68 m_stream = 0;
Chris@0 69 Pa_Terminate();
Chris@0 70 return;
Chris@0 71 }
Chris@0 72
Chris@0 73 if (m_source) {
Chris@0 74 std::cerr << "AudioPortAudioTarget: block size " << m_bufferSize << std::endl;
Chris@0 75 m_source->setTargetBlockSize(m_bufferSize);
Chris@0 76 m_source->setTargetSampleRate(m_sampleRate);
Chris@0 77 m_source->setTargetPlayLatency(m_latency);
Chris@0 78 }
Chris@0 79 }
Chris@0 80
Chris@0 81 AudioPortAudioTarget::~AudioPortAudioTarget()
Chris@0 82 {
Chris@0 83 if (m_stream) {
Chris@0 84 PaError err;
Chris@0 85 err = Pa_CloseStream(m_stream);
Chris@0 86 if (err != paNoError) {
Chris@0 87 std::cerr << "ERROR: AudioPortAudioTarget: Failed to close PortAudio stream" << std::endl;
Chris@0 88 }
Chris@0 89 Pa_Terminate();
Chris@0 90 }
Chris@0 91 }
Chris@0 92
Chris@0 93 bool
Chris@0 94 AudioPortAudioTarget::isOK() const
Chris@0 95 {
Chris@0 96 return (m_stream != 0);
Chris@0 97 }
Chris@0 98
Chris@0 99 int
Chris@0 100 AudioPortAudioTarget::processStatic(void *input, void *output,
Chris@0 101 unsigned long nframes,
Chris@0 102 PaTimestamp outTime, void *data)
Chris@0 103 {
Chris@0 104 return ((AudioPortAudioTarget *)data)->process(input, output,
Chris@0 105 nframes, outTime);
Chris@0 106 }
Chris@0 107
Chris@0 108 void
Chris@0 109 AudioPortAudioTarget::sourceModelReplaced()
Chris@0 110 {
Chris@0 111 m_source->setTargetSampleRate(m_sampleRate);
Chris@0 112 }
Chris@0 113
Chris@0 114 int
Chris@0 115 AudioPortAudioTarget::process(void *inputBuffer, void *outputBuffer,
Chris@0 116 unsigned long nframes,
Chris@0 117 PaTimestamp)
Chris@0 118 {
Chris@0 119 #ifdef DEBUG_AUDIO_PORT_AUDIO_TARGET
Chris@0 120 std::cout << "AudioPortAudioTarget::process(" << nframes << ")" << std::endl;
Chris@0 121 #endif
Chris@0 122
Chris@0 123 if (!m_source) return 0;
Chris@0 124
Chris@0 125 float *output = (float *)outputBuffer;
Chris@0 126
Chris@0 127 assert(nframes <= m_bufferSize);
Chris@0 128
Chris@0 129 static float **tmpbuf = 0;
Chris@0 130 static size_t tmpbufch = 0;
Chris@0 131 static size_t tmpbufsz = 0;
Chris@0 132
Chris@0 133 size_t sourceChannels = m_source->getSourceChannelCount();
Chris@0 134
Chris@0 135 // Because we offer pan, we always want at least 2 channels
Chris@0 136 if (sourceChannels < 2) sourceChannels = 2;
Chris@0 137
Chris@0 138 if (!tmpbuf || tmpbufch != sourceChannels || tmpbufsz < m_bufferSize) {
Chris@0 139
Chris@0 140 if (tmpbuf) {
Chris@0 141 for (size_t i = 0; i < tmpbufch; ++i) {
Chris@0 142 delete[] tmpbuf[i];
Chris@0 143 }
Chris@0 144 delete[] tmpbuf;
Chris@0 145 }
Chris@0 146
Chris@0 147 tmpbufch = sourceChannels;
Chris@0 148 tmpbufsz = m_bufferSize;
Chris@0 149 tmpbuf = new float *[tmpbufch];
Chris@0 150
Chris@0 151 for (size_t i = 0; i < tmpbufch; ++i) {
Chris@0 152 tmpbuf[i] = new float[tmpbufsz];
Chris@0 153 }
Chris@0 154 }
Chris@0 155
Chris@0 156 m_source->getSourceSamples(nframes, tmpbuf);
Chris@0 157
Chris@0 158 float peakLeft = 0.0, peakRight = 0.0;
Chris@0 159
Chris@0 160 for (size_t ch = 0; ch < 2; ++ch) {
Chris@0 161
Chris@0 162 float peak = 0.0;
Chris@0 163
Chris@0 164 if (ch < sourceChannels) {
Chris@0 165
Chris@0 166 // PortAudio samples are interleaved
Chris@0 167 for (size_t i = 0; i < nframes; ++i) {
Chris@0 168 output[i * 2 + ch] = tmpbuf[ch][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 if (ch == 1 && sourceChannels == 1) {
Chris@0 174
Chris@0 175 for (size_t i = 0; i < nframes; ++i) {
Chris@0 176 output[i * 2 + ch] = tmpbuf[0][i] * m_outputGain;
Chris@0 177 float sample = fabsf(output[i * 2 + ch]);
Chris@0 178 if (sample > peak) peak = sample;
Chris@0 179 }
Chris@0 180
Chris@0 181 } else {
Chris@0 182 for (size_t i = 0; i < nframes; ++i) {
Chris@0 183 output[i * 2 + ch] = 0;
Chris@0 184 }
Chris@0 185 }
Chris@0 186
Chris@0 187 if (ch == 0) peakLeft = peak;
Chris@0 188 if (ch > 0 || sourceChannels == 1) peakRight = peak;
Chris@0 189 }
Chris@0 190
Chris@0 191 m_source->setOutputLevels(peakLeft, peakRight);
Chris@0 192
Chris@0 193 return 0;
Chris@0 194 }
Chris@0 195
Chris@0 196 #ifdef INCLUDE_MOCFILES
Chris@0 197 #include "AudioPortAudioTarget.moc.cpp"
Chris@0 198 #endif
Chris@0 199
Chris@0 200 #endif /* HAVE_PORTAUDIO */
Chris@0 201