void AudioPortAudio::applyQualitySettings() { if( hqAudio() ) { setSampleRate( Engine::mixer()->processingSampleRate() ); int samples = mixer()->framesPerPeriod(); PaError err = Pa_OpenStream( &m_paStream, supportsCapture() ? &m_inputParameters : NULL, // The input parameter &m_outputParameters, // The outputparameter sampleRate(), samples, paNoFlag, // Don't use any flags _process_callback, // our callback function this ); if( err != paNoError ) { printf( "Couldn't open PortAudio: %s\n", Pa_GetErrorText( err ) ); return; } } AudioDevice::applyQualitySettings(); }
int AudioPortAudio::process_callback( const float *_inputBuffer, float * _outputBuffer, unsigned long _framesPerBuffer ) { if( supportsCapture() ) { mixer()->pushInputFrames( (sampleFrame*)_inputBuffer, _framesPerBuffer ); } if( m_stopped ) { memset( _outputBuffer, 0, _framesPerBuffer * channels() * sizeof(float) ); return paComplete; } while( _framesPerBuffer ) { if( m_outBufPos == 0 ) { // frames depend on the sample rate const fpp_t frames = getNextBuffer( m_outBuf ); if( !frames ) { m_stopped = true; m_stopSemaphore.release(); memset( _outputBuffer, 0, _framesPerBuffer * channels() * sizeof(float) ); return paComplete; } m_outBufSize = frames; } const int min_len = qMin( (int)_framesPerBuffer, m_outBufSize - m_outBufPos ); float master_gain = mixer()->masterGain(); for( fpp_t frame = 0; frame < min_len; ++frame ) { for( ch_cnt_t chnl = 0; chnl < channels(); ++chnl ) { ( _outputBuffer + frame * channels() )[chnl] = Mixer::clip( m_outBuf[frame][chnl] * master_gain ); } } _outputBuffer += min_len * channels(); _framesPerBuffer -= min_len; m_outBufPos += min_len; m_outBufPos %= m_outBufSize; } return paContinue; }
SoundRecorder *SoundEngineOpenAL::createSoundRecorder(std::string device) { if (!supportsCapture()) return 0; // Create recorder SoundRecorderOpenAL *recorder = new SoundRecorderOpenAL(this); if (!recorder->create(device)) { delete recorder; return 0; } // Add recorder to the recorder list for updates recorders.push_back(recorder); return recorder; }
std::vector<SoundDevice> SoundEngineOpenAL::getRecorderDevices() { if (!supportsCapture()) return std::vector<SoundDevice>(); // Get device list const char *devicelist = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); // Split list std::vector<SoundDevice> devices; while (*devicelist) { devices.push_back(SoundDevice(devicelist, devicelist)); devicelist += strlen(devicelist) + 1; } return devices; }
AudioPortAudio::AudioPortAudio( bool & _success_ful, Mixer * _mixer ) : AudioDevice( tLimit<ch_cnt_t>( ConfigManager::inst()->value( "audioportaudio", "channels" ).toInt(), DEFAULT_CHANNELS, SURROUND_CHANNELS ), _mixer ), m_paStream( NULL ), m_wasPAInitError( false ), m_outBuf( new surroundSampleFrame[mixer()->framesPerPeriod()] ), m_outBufPos( 0 ), m_stopSemaphore( 1 ) { _success_ful = false; m_outBufSize = mixer()->framesPerPeriod(); PaError err = Pa_Initialize(); if( err != paNoError ) { printf( "Couldn't initialize PortAudio: %s\n", Pa_GetErrorText( err ) ); m_wasPAInitError = true; return; } if( Pa_GetDeviceCount() <= 0 ) { return; } const QString& backend = ConfigManager::inst()->value( "audioportaudio", "backend" ); const QString& device = ConfigManager::inst()->value( "audioportaudio", "device" ); PaDeviceIndex inDevIdx = -1; PaDeviceIndex outDevIdx = -1; const PaDeviceInfo * di; for( int i = 0; i < Pa_GetDeviceCount(); ++i ) { di = Pa_GetDeviceInfo( i ); if( di->name == device && Pa_GetHostApiInfo( di->hostApi )->name == backend ) { inDevIdx = i; outDevIdx = i; } } if( inDevIdx < 0 ) { inDevIdx = Pa_GetDefaultInputDevice(); } if( outDevIdx < 0 ) { outDevIdx = Pa_GetDefaultOutputDevice(); } if( inDevIdx < 0 || outDevIdx < 0 ) { return; } double inLatency = 0;//(double)mixer()->framesPerPeriod() / (double)sampleRate(); double outLatency = 0;//(double)mixer()->framesPerPeriod() / (double)sampleRate(); //inLatency = Pa_GetDeviceInfo( inDevIdx )->defaultLowInputLatency; //outLatency = Pa_GetDeviceInfo( outDevIdx )->defaultLowOutputLatency; const int samples = mixer()->framesPerPeriod(); // Configure output parameters. m_outputParameters.device = outDevIdx; m_outputParameters.channelCount = channels(); m_outputParameters.sampleFormat = paFloat32; // 32 bit floating point output m_outputParameters.suggestedLatency = outLatency; m_outputParameters.hostApiSpecificStreamInfo = NULL; // Configure input parameters. m_inputParameters.device = inDevIdx; m_inputParameters.channelCount = DEFAULT_CHANNELS; m_inputParameters.sampleFormat = paFloat32; // 32 bit floating point input m_inputParameters.suggestedLatency = inLatency; m_inputParameters.hostApiSpecificStreamInfo = NULL; // Open an audio I/O stream. err = Pa_OpenStream( &m_paStream, supportsCapture() ? &m_inputParameters : NULL, // The input parameter &m_outputParameters, // The outputparameter sampleRate(), samples, paNoFlag, // Don't use any flags _process_callback, // our callback function this ); if( err == paInvalidDevice && sampleRate() < 48000 ) { printf("Pa_OpenStream() failed with 44,1 KHz, trying again with 48 KHz\n"); // some backends or drivers do not allow 32 bit floating point data // with a samplerate of 44100 Hz setSampleRate( 48000 ); err = Pa_OpenStream( &m_paStream, supportsCapture() ? &m_inputParameters : NULL, // The input parameter &m_outputParameters, // The outputparameter sampleRate(), samples, paNoFlag, // Don't use any flags _process_callback, // our callback function this ); } if( err != paNoError ) { printf( "Couldn't open PortAudio: %s\n", Pa_GetErrorText( err ) ); return; } printf( "Input device: '%s' backend: '%s'\n", Pa_GetDeviceInfo( inDevIdx )->name, Pa_GetHostApiInfo( Pa_GetDeviceInfo( inDevIdx )->hostApi )->name ); printf( "Output device: '%s' backend: '%s'\n", Pa_GetDeviceInfo( outDevIdx )->name, Pa_GetHostApiInfo( Pa_GetDeviceInfo( outDevIdx )->hostApi )->name ); m_stopSemaphore.acquire(); // TODO: debug Mixer::pushInputFrames() //m_supportsCapture = true; _success_ful = true; }