Added automated channel detection for speaker devices
This commit is contained in:
		
							parent
							
								
									da07595337
								
							
						
					
					
						commit
						768e9b7bbb
					
				| @ -217,7 +217,10 @@ namespace tc::audio { | |||||||
| 
 | 
 | ||||||
|     bool AudioDeviceRecord::start(std::string &error) { |     bool AudioDeviceRecord::start(std::string &error) { | ||||||
|         std::lock_guard lock{this->state_lock}; |         std::lock_guard lock{this->state_lock}; | ||||||
|         if(this->running && !this->stream_invalid) return true; |         if(this->running && !this->stream_invalid) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         if(this->stream_invalid) { |         if(this->stream_invalid) { | ||||||
|             this->impl_stop(); |             this->impl_stop(); | ||||||
|             this->running = false; |             this->running = false; | ||||||
|  | |||||||
| @ -92,8 +92,9 @@ namespace tc::audio::pa { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         std::lock_guard lock{this->io_lock}; |         std::lock_guard lock{this->io_lock}; | ||||||
|         if(!this->_playback) |         if(!this->_playback) { | ||||||
|             this->_playback = std::make_shared<PortAudioPlayback>(this->_index, this->_info); |             this->_playback = std::make_shared<PortAudioPlayback>(this->_index, this->_info); | ||||||
|  |         } | ||||||
|         return this->_playback; |         return this->_playback; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -28,6 +28,8 @@ namespace tc::audio::pa { | |||||||
|             PaDeviceIndex index; |             PaDeviceIndex index; | ||||||
|             const PaDeviceInfo* info; |             const PaDeviceInfo* info; | ||||||
|             PaStream* stream{nullptr}; |             PaStream* stream{nullptr}; | ||||||
|  | 
 | ||||||
|  |             size_t source_channel_count{0}; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     class PortAudioRecord : public AudioDeviceRecord { |     class PortAudioRecord : public AudioDeviceRecord { | ||||||
|  | |||||||
| @ -32,7 +32,8 @@ bool PortAudioPlayback::impl_start(std::string &error) { | |||||||
|             unsigned long frameCount, |             unsigned long frameCount, | ||||||
|             const PaStreamCallbackTimeInfo* timeInfo, |             const PaStreamCallbackTimeInfo* timeInfo, | ||||||
|             PaStreamCallbackFlags statusFlags, |             PaStreamCallbackFlags statusFlags, | ||||||
|             void *userData) { |             void *userData | ||||||
|  |     ) { | ||||||
|         assert(output); |         assert(output); | ||||||
| 
 | 
 | ||||||
|         auto player = reinterpret_cast<PortAudioPlayback*>(userData); |         auto player = reinterpret_cast<PortAudioPlayback*>(userData); | ||||||
| @ -44,10 +45,19 @@ bool PortAudioPlayback::impl_start(std::string &error) { | |||||||
| 
 | 
 | ||||||
|     PaStreamParameters parameters{}; |     PaStreamParameters parameters{}; | ||||||
|     memset(¶meters, 0, sizeof(parameters)); |     memset(¶meters, 0, sizeof(parameters)); | ||||||
|     parameters.channelCount = (int) kChannelCount; |  | ||||||
|     parameters.device = this->index; |     parameters.device = this->index; | ||||||
|     parameters.sampleFormat = paFloat32; |     parameters.sampleFormat = paFloat32; | ||||||
|     parameters.suggestedLatency = this->info->defaultLowInputLatency; |     parameters.suggestedLatency = this->info->defaultLowInputLatency; | ||||||
|  | 
 | ||||||
|  |     if(this->info->maxOutputChannels < kChannelCount) { | ||||||
|  |         parameters.channelCount = (int) 1; | ||||||
|  |         this->source_channel_count = 1; | ||||||
|  |     } else { | ||||||
|  |         parameters.channelCount = (int) kChannelCount; | ||||||
|  |         this->source_channel_count = kChannelCount; | ||||||
|  |     } | ||||||
|  |     log_debug(category::audio, "Opening playback device {} (MaxChannels: {}, Channels: {})", this->info->name, this->info->maxOutputChannels, this->source_channel_count); | ||||||
|  | 
 | ||||||
|     auto err = Pa_OpenStream( |     auto err = Pa_OpenStream( | ||||||
|             &this->stream, |             &this->stream, | ||||||
|             nullptr, |             nullptr, | ||||||
| @ -56,7 +66,8 @@ bool PortAudioPlayback::impl_start(std::string &error) { | |||||||
|             (unsigned long) (kSampleRate * kTimeSpan), |             (unsigned long) (kSampleRate * kTimeSpan), | ||||||
|             paClipOff, |             paClipOff, | ||||||
|             proxied_write_callback, |             proxied_write_callback, | ||||||
|             this); |             this | ||||||
|  |     ); | ||||||
| 
 | 
 | ||||||
|     if(err != paNoError) { |     if(err != paNoError) { | ||||||
|         this->stream = nullptr; |         this->stream = nullptr; | ||||||
| @ -68,20 +79,23 @@ bool PortAudioPlayback::impl_start(std::string &error) { | |||||||
|     if(err != paNoError) { |     if(err != paNoError) { | ||||||
|         error = std::string{Pa_GetErrorText(err)} + "(start stream: " + std::to_string(err) + ")"; |         error = std::string{Pa_GetErrorText(err)} + "(start stream: " + std::to_string(err) + ")"; | ||||||
|         err = Pa_CloseStream(this->stream); |         err = Pa_CloseStream(this->stream); | ||||||
|         if(err != paNoError) |         if(err != paNoError) { | ||||||
|             log_critical(category::audio, tr("Failed to close opened pa stream. This will cause memory leaks. Error: {}/{}"), err, Pa_GetErrorText(err)); |             log_critical(category::audio, tr("Failed to close opened pa stream. This will cause memory leaks. Error: {}/{}"), err, Pa_GetErrorText(err)); | ||||||
|  |         } | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PortAudioPlayback::impl_stop() { | void PortAudioPlayback::impl_stop() { | ||||||
|     if(Pa_IsStreamActive(this->stream)) |     if(Pa_IsStreamActive(this->stream)) { | ||||||
|         Pa_AbortStream(this->stream); |         Pa_AbortStream(this->stream); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     auto error = Pa_CloseStream(this->stream); |     auto error = Pa_CloseStream(this->stream); | ||||||
|     if(error != paNoError) |     if(error != paNoError) { | ||||||
|         log_error(category::audio, tr("Failed to close PA stream: {}"), error); |         log_error(category::audio, tr("Failed to close PA stream: {}"), error); | ||||||
|  |     } | ||||||
|     this->stream = nullptr; |     this->stream = nullptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -91,5 +105,5 @@ size_t PortAudioPlayback::sample_rate() const { | |||||||
| 
 | 
 | ||||||
| void PortAudioPlayback::write_callback(void *output, unsigned long frameCount, | void PortAudioPlayback::write_callback(void *output, unsigned long frameCount, | ||||||
|                                     const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) { |                                     const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) { | ||||||
|     this->fill_buffer(output, frameCount, kChannelCount); |     this->fill_buffer(output, frameCount, this->source_channel_count); | ||||||
| } | } | ||||||
| @ -49,7 +49,7 @@ bool PortAudioRecord::impl_start(std::string &error) { | |||||||
|         parameters.channelCount = (int) kChannelCount; |         parameters.channelCount = (int) kChannelCount; | ||||||
|         this->source_channel_count = kChannelCount; |         this->source_channel_count = kChannelCount; | ||||||
|     } |     } | ||||||
|     log_debug(category::audio, "Opening device {} (MaxChannels: {}, MinChannels: {}, Channels: {})", this->info->name, this->info->maxInputChannels, this->info->maxInputChannels, this->source_channel_count); |     log_debug(category::audio, "Opening record device {} (MaxChannels: {}, Channels: {})", this->info->name, this->info->maxInputChannels, this->source_channel_count); | ||||||
| 
 | 
 | ||||||
|     parameters.device = this->index; |     parameters.device = this->index; | ||||||
|     parameters.sampleFormat = paFloat32; |     parameters.sampleFormat = paFloat32; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user