comparison audioio/AudioPortAudioTarget.cpp @ 0:cd5d7ff8ef38

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