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 <algorithm> | ||||||
| #include <cstring> | #include <cstring> | ||||||
| #include <mutex> |  | ||||||
| 
 |  | ||||||
| #include "audio_core/cubeb_sink.h" | #include "audio_core/cubeb_sink.h" | ||||||
| #include "audio_core/stream.h" | #include "audio_core/stream.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/ring_buffer.h" | ||||||
| 
 | 
 | ||||||
| namespace AudioCore { | namespace AudioCore { | ||||||
| 
 | 
 | ||||||
| class SinkStreamImpl final : public SinkStream { | class CubebSinkStream final : public SinkStream { | ||||||
| public: | 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) |                     const std::string& name) | ||||||
|         : ctx{ctx}, num_channels{num_channels_} { |         : 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, |         if (cubeb_stream_init(ctx, &stream_backend, name.c_str(), nullptr, nullptr, output_device, | ||||||
|                               ¶ms, std::max(512u, minimum_latency), |                               ¶ms, std::max(512u, minimum_latency), | ||||||
|                               &SinkStreamImpl::DataCallback, &SinkStreamImpl::StateCallback, |                               &CubebSinkStream::DataCallback, &CubebSinkStream::StateCallback, | ||||||
|                               this) != CUBEB_OK) { |                               this) != CUBEB_OK) { | ||||||
|             LOG_CRITICAL(Audio_Sink, "Error initializing cubeb stream"); |             LOG_CRITICAL(Audio_Sink, "Error initializing cubeb stream"); | ||||||
|             return; |             return; | ||||||
| @ -50,7 +49,7 @@ public: | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ~SinkStreamImpl() { |     ~CubebSinkStream() { | ||||||
|         if (!ctx) { |         if (!ctx) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @ -63,33 +62,27 @@ public: | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void EnqueueSamples(u32 num_channels, const std::vector<s16>& samples) override { |     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) { |         if (is_6_channel) { | ||||||
|             // Downsample 6 channels to 2
 |             // Downsample 6 channels to 2
 | ||||||
|             const size_t sample_count_copy_size = samples.size() * 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) { |             for (size_t i = 0; i < samples.size(); i += num_channels) { | ||||||
|                 queue.push_back(samples[i]); |                 buf.push_back(samples[i]); | ||||||
|                 queue.push_back(samples[i + 1]); |                 buf.push_back(samples[i + 1]); | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             // Copy as-is
 |  | ||||||
|             std::copy(samples.begin(), samples.end(), std::back_inserter(queue)); |  | ||||||
|             } |             } | ||||||
|  |             queue.Push(buf); | ||||||
|  |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     size_t SamplesInQueue(u32 num_channels) const { |         queue.Push(samples); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     size_t SamplesInQueue(u32 num_channels) const override { | ||||||
|         if (!ctx) |         if (!ctx) | ||||||
|             return 0; |             return 0; | ||||||
| 
 | 
 | ||||||
|         return queue.size() / num_channels; |         return queue.Size() / num_channels; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     u32 GetNumChannels() const { |     u32 GetNumChannels() const { | ||||||
| @ -104,8 +97,7 @@ private: | |||||||
|     u32 num_channels{}; |     u32 num_channels{}; | ||||||
|     bool is_6_channel{}; |     bool is_6_channel{}; | ||||||
| 
 | 
 | ||||||
|     std::mutex queue_mutex; |     Common::RingBuffer<s16, 0x10000> queue; | ||||||
|     std::vector<s16> queue; |  | ||||||
| 
 | 
 | ||||||
|     static long DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, |     static long DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, | ||||||
|                              void* output_buffer, long num_frames); |                              void* output_buffer, long num_frames); | ||||||
| @ -151,38 +143,32 @@ CubebSink::~CubebSink() { | |||||||
| SinkStream& CubebSink::AcquireSinkStream(u32 sample_rate, u32 num_channels, | SinkStream& CubebSink::AcquireSinkStream(u32 sample_rate, u32 num_channels, | ||||||
|                                          const std::string& name) { |                                          const std::string& name) { | ||||||
|     sink_streams.push_back( |     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(); |     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) { |                                   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); |     u8* buffer = reinterpret_cast<u8*>(output_buffer); | ||||||
| 
 | 
 | ||||||
|     if (!impl) { |     if (!impl) { | ||||||
|         return {}; |         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{ |     if (samples_written < max_samples_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) { |  | ||||||
|         // Fill the rest of the frames with silence
 |         // Fill the rest of the frames with silence
 | ||||||
|         memset(buffer + frames_to_write * sizeof(s16) * impl->GetNumChannels(), 0, |         std::memset(buffer + samples_written * sizeof(s16), 0, | ||||||
|                (num_frames - frames_to_write) * sizeof(s16) * impl->GetNumChannels()); |                     (max_samples_to_write - samples_written) * sizeof(s16)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return num_frames; |     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> ListCubebSinkDevices() { | ||||||
|     std::vector<std::string> device_list; |     std::vector<std::string> device_list; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 MerryMage
						MerryMage