Mercurial > hg > vamp-live-host
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 |