33 const void *inputBuffer,
35 unsigned long framesPerBuffer,
36 const PaStreamCallbackTimeInfo* timeInfo,
37 PaStreamCallbackFlags statusFlags,
40 float *out = (
float* )outputBuffer;
42 if ( pDriver ==
nullptr ) {
47 while ( framesPerBuffer > 0 ) {
48 unsigned long nFrames = std::min( (
unsigned long)
MAX_BUFFER_SIZE, framesPerBuffer );
51 for (
unsigned i = 0; i < nFrames; i++ ) {
55 framesPerBuffer -= nFrames;
115 if ( HostAPI.isNull() || HostAPI ==
"" ) {
117 auto pInfo = Pa_GetHostApiInfo( Pa_GetDefaultHostApi() );
118 if ( pInfo ==
nullptr ) {
119 ERRORLOG(
"Unable to obtain default Host API" );
123 HostAPI = pInfo->name;
126 int nDevices = Pa_GetDeviceCount();
127 for (
int nDevice = 0; nDevice < nDevices; nDevice++ ) {
128 const PaDeviceInfo *pDeviceInfo = Pa_GetDeviceInfo( nDevice );
129 if ( pDeviceInfo ==
nullptr ) {
134 auto pInfo = Pa_GetHostApiInfo( pDeviceInfo->hostApi );
135 if ( pInfo ==
nullptr || pInfo->name != HostAPI ) {
138 if ( pDeviceInfo->maxOutputChannels >= 2 ) {
139 devices.push_back( QString( pDeviceInfo->name ) );
158 bool bUseDefaultStream =
true;
175 err = Pa_Initialize();
177 if ( err != paNoError ) {
178 ERRORLOG(
"Portaudio error in Pa_Initialize: " + QString( Pa_GetErrorText( err ) ) );
187 int nDevices = Pa_GetDeviceCount();
188 const PaDeviceInfo *pDeviceInfo;
189 for (
int nDevice = 0; nDevice < nDevices; nDevice++ ) {
190 pDeviceInfo = Pa_GetDeviceInfo( nDevice );
191 if ( pDeviceInfo ==
nullptr ) {
197 auto pInfo = Pa_GetHostApiInfo( pDeviceInfo->hostApi );
203 if ( pDeviceInfo->maxOutputChannels >= 2
204 && ( QString::compare(
m_sDevice, pDeviceInfo->name, Qt::CaseInsensitive ) == 0 ||
206 PaStreamParameters outputParameters;
207 memset( &outputParameters,
'\0',
sizeof( outputParameters ) );
208 outputParameters.channelCount = 2;
209 outputParameters.device = nDevice;
210 outputParameters.hostApiSpecificStreamInfo =
nullptr;
211 outputParameters.sampleFormat = paFloat32;
215 outputParameters.suggestedLatency =
216 Pa_GetDeviceInfo( nDevice )->defaultHighInputLatency;
226 if ( err != paNoError ) {
227 ERRORLOG( QString(
"Found but can't open device '%1' (max %3 in, %4 out): %2" )
228 .arg(
m_sDevice ).arg( Pa_GetErrorText( err ) )
229 .arg( pDeviceInfo->maxInputChannels ).arg( pDeviceInfo->maxOutputChannels ) );
234 bUseDefaultStream =
false;
238 if ( bUseDefaultStream ) {
239 ERRORLOG( QString(
"Can't use device '%1', using default stream" )
244 if ( bUseDefaultStream ) {
247 err = Pa_OpenDefaultStream(
253 paFramesPerBufferUnspecified,
258 if ( err != paNoError ) {
259 ERRORLOG(
"Portaudio error in Pa_OpenDefaultStream: " + QString( Pa_GetErrorText( err ) ) );
268 const PaStreamInfo *pStreamInfo = Pa_GetStreamInfo(
m_pStream );
269 if ( pStreamInfo ==
nullptr ) {
275 ERRORLOG( QString(
"Couldn't get sample rate %d, using %d instead" ).arg(
m_nSampleRate ).arg( pStreamInfo->sampleRate ) );
278 INFOLOG( QString(
"PortAudio outpot latency: %1 s" ).arg( pStreamInfo->outputLatency ) );
283 if ( err != paNoError ) {
284 ERRORLOG(
"Portaudio error in Pa_StartStream: " + QString( Pa_GetErrorText( err ) ) );
int portAudioCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData)