Mercurial > hg > svapp
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 |