comparison audioio/AudioPortAudioTarget.cpp @ 0:db6fcbd4405c

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