comparison audioio/AudioPortAudioSource.cpp @ 0:a6020bf991cd

* Initial import of what may or may not become a simple live visual-response host for causal Vamp plugins
author cannam
date Thu, 19 Oct 2006 16:53:48 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:a6020bf991cd
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 #ifdef HAVE_PORTAUDIO
4
5 #include "AudioPortAudioSource.h"
6 #include "AudioCallbackRecordTarget.h"
7
8 #include <iostream>
9 #include <cassert>
10 #include <cmath>
11
12 //#define DEBUG_AUDIO_PORT_AUDIO_SOURCE 1
13
14 AudioPortAudioSource::AudioPortAudioSource(AudioCallbackRecordTarget *target) :
15 AudioCallbackRecordSource(target),
16 m_stream(0),
17 m_bufferSize(0),
18 m_sampleRate(0),
19 m_latency(0)
20 {
21 PaError err;
22
23 err = Pa_Initialize();
24 if (err != paNoError) {
25 std::cerr << "ERROR: AudioPortAudioSource: Failed to initialize PortAudio" << std::endl;
26 return;
27 }
28
29 m_bufferSize = 1024;
30 m_sampleRate = 44100;
31 if (m_target && (m_target->getPreferredSampleRate() != 0)) {
32 m_sampleRate = m_target->getPreferredSampleRate();
33 }
34
35 m_latency = Pa_GetMinNumBuffers(m_bufferSize, m_sampleRate) * m_bufferSize;
36
37 err = Pa_OpenDefaultStream(&m_stream, m_target->getChannelCount(),
38 0, paFloat32,
39 m_sampleRate, m_bufferSize, 0,
40 processStatic, this);
41
42 if (err != paNoError) {
43 std::cerr << "ERROR: AudioPortAudioSource: Failed to open PortAudio stream" << std::endl;
44 m_stream = 0;
45 Pa_Terminate();
46 return;
47 }
48
49 err = Pa_StartStream(m_stream);
50
51 if (err != paNoError) {
52 std::cerr << "ERROR: AudioPortAudioSource: Failed to start PortAudio stream" << std::endl;
53 Pa_CloseStream(m_stream);
54 m_stream = 0;
55 Pa_Terminate();
56 return;
57 }
58
59 if (m_target) {
60 std::cerr << "AudioPortAudioSource: block size " << m_bufferSize << std::endl;
61 m_target->setSourceBlockSize(m_bufferSize);
62 m_target->setSourceSampleRate(m_sampleRate);
63 m_target->setSourceRecordLatency(m_latency);
64 }
65 }
66
67 AudioPortAudioSource::~AudioPortAudioSource()
68 {
69 if (m_stream) {
70 PaError err;
71 err = Pa_CloseStream(m_stream);
72 if (err != paNoError) {
73 std::cerr << "ERROR: AudioPortAudioSource: Failed to close PortAudio stream" << std::endl;
74 }
75 Pa_Terminate();
76 }
77 }
78
79 bool
80 AudioPortAudioSource::isOK() const
81 {
82 return (m_stream != 0);
83 }
84
85 int
86 AudioPortAudioSource::processStatic(void *input, void *output,
87 unsigned long nframes,
88 PaTimestamp outTime, void *data)
89 {
90 return ((AudioPortAudioSource *)data)->process(input, output,
91 nframes, outTime);
92 }
93
94 int
95 AudioPortAudioSource::process(void *inputBuffer,
96 void *outputBuffer,
97 unsigned long nframes,
98 PaTimestamp)
99 {
100 #ifdef DEBUG_AUDIO_PORT_AUDIO_SOURCE
101 std::cout << "AudioPortAudioSource::process(" << nframes << ")" << std::endl;
102 #endif
103
104 if (!m_target) return 0;
105
106 float *input = (float *)inputBuffer;
107
108 assert(nframes <= m_bufferSize);
109
110 static float **tmpbuf = 0;
111 static size_t tmpbufch = 0;
112 static size_t tmpbufsz = 0;
113
114 size_t channels = m_target->getChannelCount();
115
116 if (!tmpbuf || tmpbufch != channels || tmpbufsz < m_bufferSize) {
117
118 if (tmpbuf) {
119 for (size_t i = 0; i < tmpbufch; ++i) {
120 delete[] tmpbuf[i];
121 }
122 delete[] tmpbuf;
123 }
124
125 tmpbufch = channels;
126 tmpbufsz = m_bufferSize;
127 tmpbuf = new float *[tmpbufch];
128
129 for (size_t i = 0; i < tmpbufch; ++i) {
130 tmpbuf[i] = new float[tmpbufsz];
131 }
132 }
133
134 float peakLeft = 0.0, peakRight = 0.0;
135
136 for (size_t ch = 0; ch < 2; ++ch) {
137
138 float peak = 0.0;
139
140 if (ch < channels) {
141
142 // PortAudio samples are interleaved
143 for (size_t i = 0; i < nframes; ++i) {
144 tmpbuf[ch][i] = input[i * 2 + ch];
145 float sample = fabsf(input[i * 2 + ch]);
146 if (sample > peak) peak = sample;
147 }
148
149 } else if (ch == 1 && channels == 1) {
150
151 for (size_t i = 0; i < nframes; ++i) {
152 tmpbuf[0][i] = input[i * 2 + ch];
153 float sample = fabsf(input[i * 2 + ch]);
154 if (sample > peak) peak = sample;
155 }
156
157 } else {
158 for (size_t i = 0; i < nframes; ++i) {
159 tmpbuf[ch][i] = 0;
160 }
161 }
162
163 if (ch == 0) peakLeft = peak;
164 if (ch > 0 || channels == 1) peakRight = peak;
165 }
166
167 m_target->putSamples(nframes, tmpbuf);
168 m_target->setInputLevels(peakLeft, peakRight);
169
170 return 0;
171 }
172
173 #endif /* HAVE_PORTAUDIO */
174