mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Support looping HLE audio (#2422)
* Support looping HLE audio * DSP: Fix dirty bit clears, handle nonmonotonically incrementing IDs * DSP: Add start offset support
This commit is contained in:
		
							parent
							
								
									1410aa1824
								
							
						
					
					
						commit
						ff28080091
					
				
					 2 changed files with 35 additions and 11 deletions
				
			
		|  | @ -158,6 +158,14 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config, | ||||||
|                   static_cast<size_t>(state.mono_or_stereo)); |                   static_cast<size_t>(state.mono_or_stereo)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     u32_dsp play_position = {}; | ||||||
|  |     if (config.play_position_dirty && config.play_position != 0) { | ||||||
|  |         config.play_position_dirty.Assign(0); | ||||||
|  |         play_position = config.play_position; | ||||||
|  |         // play_position applies only to the embedded buffer, and defaults to 0 w/o a dirty bit
 | ||||||
|  |         // This will be the starting sample for the first time the buffer is played.
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     if (config.embedded_buffer_dirty) { |     if (config.embedded_buffer_dirty) { | ||||||
|         config.embedded_buffer_dirty.Assign(0); |         config.embedded_buffer_dirty.Assign(0); | ||||||
|         state.input_queue.emplace(Buffer{ |         state.input_queue.emplace(Buffer{ | ||||||
|  | @ -171,9 +179,18 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config, | ||||||
|             state.mono_or_stereo, |             state.mono_or_stereo, | ||||||
|             state.format, |             state.format, | ||||||
|             false, |             false, | ||||||
|  |             play_position, | ||||||
|  |             false, | ||||||
|         }); |         }); | ||||||
|         LOG_TRACE(Audio_DSP, "enqueuing embedded addr=0x%08x len=%u id=%hu", |         LOG_TRACE(Audio_DSP, "enqueuing embedded addr=0x%08x len=%u id=%hu start=%u", | ||||||
|                   config.physical_address, config.length, config.buffer_id); |                   config.physical_address, config.length, config.buffer_id, | ||||||
|  |                   static_cast<u32>(config.play_position)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (config.loop_related_dirty && config.loop_related != 0) { | ||||||
|  |         config.loop_related_dirty.Assign(0); | ||||||
|  |         LOG_WARNING(Audio_DSP, "Unhandled complex loop with loop_related=0x%08x", | ||||||
|  |                     static_cast<u32>(config.loop_related)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (config.buffer_queue_dirty) { |     if (config.buffer_queue_dirty) { | ||||||
|  | @ -192,6 +209,8 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config, | ||||||
|                     state.mono_or_stereo, |                     state.mono_or_stereo, | ||||||
|                     state.format, |                     state.format, | ||||||
|                     true, |                     true, | ||||||
|  |                     {}, // 0 in u32_dsp
 | ||||||
|  |                     false, | ||||||
|                 }); |                 }); | ||||||
|                 LOG_TRACE(Audio_DSP, "enqueuing queued %zu addr=0x%08x len=%u id=%hu", i, |                 LOG_TRACE(Audio_DSP, "enqueuing queued %zu addr=0x%08x len=%u id=%hu", i, | ||||||
|                           b.physical_address, b.length, b.buffer_id); |                           b.physical_address, b.length, b.buffer_id); | ||||||
|  | @ -247,18 +266,18 @@ bool Source::DequeueBuffer() { | ||||||
|     if (state.input_queue.empty()) |     if (state.input_queue.empty()) | ||||||
|         return false; |         return false; | ||||||
| 
 | 
 | ||||||
|     const Buffer buf = state.input_queue.top(); |     Buffer buf = state.input_queue.top(); | ||||||
|     state.input_queue.pop(); | 
 | ||||||
|  |     // if we're in a loop, the current sound keeps playing afterwards, so leave the queue alone
 | ||||||
|  |     if (!buf.is_looping) { | ||||||
|  |         state.input_queue.pop(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (buf.adpcm_dirty) { |     if (buf.adpcm_dirty) { | ||||||
|         state.adpcm_state.yn1 = buf.adpcm_yn[0]; |         state.adpcm_state.yn1 = buf.adpcm_yn[0]; | ||||||
|         state.adpcm_state.yn2 = buf.adpcm_yn[1]; |         state.adpcm_state.yn2 = buf.adpcm_yn[1]; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (buf.is_looping) { |  | ||||||
|         LOG_ERROR(Audio_DSP, "Looped buffers are unimplemented at the moment"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     const u8* const memory = Memory::GetPhysicalPointer(buf.physical_address); |     const u8* const memory = Memory::GetPhysicalPointer(buf.physical_address); | ||||||
|     if (memory) { |     if (memory) { | ||||||
|         const unsigned num_channels = buf.mono_or_stereo == MonoOrStereo::Stereo ? 2 : 1; |         const unsigned num_channels = buf.mono_or_stereo == MonoOrStereo::Stereo ? 2 : 1; | ||||||
|  | @ -305,10 +324,13 @@ bool Source::DequeueBuffer() { | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     state.current_sample_number = 0; |     // the first playthrough starts at play_position, loops start at the beginning of the buffer
 | ||||||
|     state.next_sample_number = 0; |     state.current_sample_number = (!buf.has_played) ? buf.play_position : 0; | ||||||
|  |     state.next_sample_number = state.current_sample_number; | ||||||
|     state.current_buffer_id = buf.buffer_id; |     state.current_buffer_id = buf.buffer_id; | ||||||
|     state.buffer_update = buf.from_queue; |     state.buffer_update = buf.from_queue && !buf.has_played; | ||||||
|  | 
 | ||||||
|  |     buf.has_played = true; | ||||||
| 
 | 
 | ||||||
|     LOG_TRACE(Audio_DSP, "source_id=%zu buffer_id=%hu from_queue=%s current_buffer.size()=%zu", |     LOG_TRACE(Audio_DSP, "source_id=%zu buffer_id=%hu from_queue=%s current_buffer.size()=%zu", | ||||||
|               source_id, buf.buffer_id, buf.from_queue ? "true" : "false", |               source_id, buf.buffer_id, buf.from_queue ? "true" : "false", | ||||||
|  |  | ||||||
|  | @ -76,6 +76,8 @@ private: | ||||||
|         Format format; |         Format format; | ||||||
| 
 | 
 | ||||||
|         bool from_queue; |         bool from_queue; | ||||||
|  |         u32_dsp play_position; // = 0;
 | ||||||
|  |         bool has_played;       // = false;
 | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     struct BufferOrder { |     struct BufferOrder { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue