mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	cubeb_sink: Use RingBuffer
This commit is contained in:
		
							parent
							
								
									112351d557
								
							
						
					
					
						commit
						6d9dd1dc6d
					
				| @ -4,17 +4,16 @@ | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <cstring> | ||||
| #include <mutex> | ||||
| 
 | ||||
| #include "audio_core/cubeb_sink.h" | ||||
| #include "audio_core/stream.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/ring_buffer.h" | ||||
| 
 | ||||
| namespace AudioCore { | ||||
| 
 | ||||
| class SinkStreamImpl final : public SinkStream { | ||||
| class CubebSinkStream final : public SinkStream { | ||||
| public: | ||||
|     SinkStreamImpl(cubeb* ctx, u32 sample_rate, u32 num_channels_, cubeb_devid output_device, | ||||
|     CubebSinkStream(cubeb* ctx, u32 sample_rate, u32 num_channels_, cubeb_devid output_device, | ||||
|                     const std::string& name) | ||||
|         : ctx{ctx}, num_channels{num_channels_} { | ||||
| 
 | ||||
| @ -38,7 +37,7 @@ public: | ||||
| 
 | ||||
|         if (cubeb_stream_init(ctx, &stream_backend, name.c_str(), nullptr, nullptr, output_device, | ||||
|                               ¶ms, std::max(512u, minimum_latency), | ||||
|                               &SinkStreamImpl::DataCallback, &SinkStreamImpl::StateCallback, | ||||
|                               &CubebSinkStream::DataCallback, &CubebSinkStream::StateCallback, | ||||
|                               this) != CUBEB_OK) { | ||||
|             LOG_CRITICAL(Audio_Sink, "Error initializing cubeb stream"); | ||||
|             return; | ||||
| @ -50,7 +49,7 @@ public: | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     ~SinkStreamImpl() { | ||||
|     ~CubebSinkStream() { | ||||
|         if (!ctx) { | ||||
|             return; | ||||
|         } | ||||
| @ -63,33 +62,27 @@ public: | ||||
|     } | ||||
| 
 | ||||
|     void EnqueueSamples(u32 num_channels, const std::vector<s16>& samples) override { | ||||
|         if (!ctx) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         std::lock_guard lock{queue_mutex}; | ||||
| 
 | ||||
|         queue.reserve(queue.size() + samples.size() * GetNumChannels()); | ||||
| 
 | ||||
|         if (is_6_channel) { | ||||
|             // Downsample 6 channels to 2
 | ||||
|             const size_t sample_count_copy_size = samples.size() * 2; | ||||
|             queue.reserve(sample_count_copy_size); | ||||
|             std::vector<s16> buf; | ||||
|             buf.reserve(sample_count_copy_size); | ||||
|             for (size_t i = 0; i < samples.size(); i += num_channels) { | ||||
|                 queue.push_back(samples[i]); | ||||
|                 queue.push_back(samples[i + 1]); | ||||
|             } | ||||
|         } else { | ||||
|             // Copy as-is
 | ||||
|             std::copy(samples.begin(), samples.end(), std::back_inserter(queue)); | ||||
|                 buf.push_back(samples[i]); | ||||
|                 buf.push_back(samples[i + 1]); | ||||
|             } | ||||
|             queue.Push(buf); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|     size_t SamplesInQueue(u32 num_channels) const { | ||||
|         queue.Push(samples); | ||||
|     } | ||||
| 
 | ||||
|     size_t SamplesInQueue(u32 num_channels) const override { | ||||
|         if (!ctx) | ||||
|             return 0; | ||||
| 
 | ||||
|         return queue.size() / num_channels; | ||||
|         return queue.Size() / num_channels; | ||||
|     } | ||||
| 
 | ||||
|     u32 GetNumChannels() const { | ||||
| @ -104,8 +97,7 @@ private: | ||||
|     u32 num_channels{}; | ||||
|     bool is_6_channel{}; | ||||
| 
 | ||||
|     std::mutex queue_mutex; | ||||
|     std::vector<s16> queue; | ||||
|     Common::RingBuffer<s16, 0x10000> queue; | ||||
| 
 | ||||
|     static long DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, | ||||
|                              void* output_buffer, long num_frames); | ||||
| @ -151,38 +143,32 @@ CubebSink::~CubebSink() { | ||||
| SinkStream& CubebSink::AcquireSinkStream(u32 sample_rate, u32 num_channels, | ||||
|                                          const std::string& name) { | ||||
|     sink_streams.push_back( | ||||
|         std::make_unique<SinkStreamImpl>(ctx, sample_rate, num_channels, output_device, name)); | ||||
|         std::make_unique<CubebSinkStream>(ctx, sample_rate, num_channels, output_device, name)); | ||||
|     return *sink_streams.back(); | ||||
| } | ||||
| 
 | ||||
| long SinkStreamImpl::DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, | ||||
| long CubebSinkStream::DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, | ||||
|                                   void* output_buffer, long num_frames) { | ||||
|     SinkStreamImpl* impl = static_cast<SinkStreamImpl*>(user_data); | ||||
|     CubebSinkStream* impl = static_cast<CubebSinkStream*>(user_data); | ||||
|     u8* buffer = reinterpret_cast<u8*>(output_buffer); | ||||
| 
 | ||||
|     if (!impl) { | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     std::lock_guard lock{impl->queue_mutex}; | ||||
|     const size_t max_samples_to_write = impl->GetNumChannels() * num_frames; | ||||
|     const size_t samples_written = impl->queue.Pop(buffer, max_samples_to_write); | ||||
| 
 | ||||
|     const size_t frames_to_write{ | ||||
|         std::min(impl->queue.size() / impl->GetNumChannels(), static_cast<size_t>(num_frames))}; | ||||
| 
 | ||||
|     memcpy(buffer, impl->queue.data(), frames_to_write * sizeof(s16) * impl->GetNumChannels()); | ||||
|     impl->queue.erase(impl->queue.begin(), | ||||
|                       impl->queue.begin() + frames_to_write * impl->GetNumChannels()); | ||||
| 
 | ||||
|     if (frames_to_write < num_frames) { | ||||
|     if (samples_written < max_samples_to_write) { | ||||
|         // Fill the rest of the frames with silence
 | ||||
|         memset(buffer + frames_to_write * sizeof(s16) * impl->GetNumChannels(), 0, | ||||
|                (num_frames - frames_to_write) * sizeof(s16) * impl->GetNumChannels()); | ||||
|         std::memset(buffer + samples_written * sizeof(s16), 0, | ||||
|                     (max_samples_to_write - samples_written) * sizeof(s16)); | ||||
|     } | ||||
| 
 | ||||
|     return num_frames; | ||||
| } | ||||
| 
 | ||||
| void SinkStreamImpl::StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state) {} | ||||
| void CubebSinkStream::StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state) {} | ||||
| 
 | ||||
| std::vector<std::string> ListCubebSinkDevices() { | ||||
|     std::vector<std::string> device_list; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 MerryMage
						MerryMage