mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +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
					
				@ -158,6 +158,14 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config,
 | 
			
		||||
                  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) {
 | 
			
		||||
        config.embedded_buffer_dirty.Assign(0);
 | 
			
		||||
        state.input_queue.emplace(Buffer{
 | 
			
		||||
@ -171,9 +179,18 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config,
 | 
			
		||||
            state.mono_or_stereo,
 | 
			
		||||
            state.format,
 | 
			
		||||
            false,
 | 
			
		||||
            play_position,
 | 
			
		||||
            false,
 | 
			
		||||
        });
 | 
			
		||||
        LOG_TRACE(Audio_DSP, "enqueuing embedded addr=0x%08x len=%u id=%hu",
 | 
			
		||||
                  config.physical_address, config.length, config.buffer_id);
 | 
			
		||||
        LOG_TRACE(Audio_DSP, "enqueuing embedded addr=0x%08x len=%u id=%hu start=%u",
 | 
			
		||||
                  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) {
 | 
			
		||||
@ -192,6 +209,8 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config,
 | 
			
		||||
                    state.mono_or_stereo,
 | 
			
		||||
                    state.format,
 | 
			
		||||
                    true,
 | 
			
		||||
                    {}, // 0 in u32_dsp
 | 
			
		||||
                    false,
 | 
			
		||||
                });
 | 
			
		||||
                LOG_TRACE(Audio_DSP, "enqueuing queued %zu addr=0x%08x len=%u id=%hu", i,
 | 
			
		||||
                          b.physical_address, b.length, b.buffer_id);
 | 
			
		||||
@ -247,18 +266,18 @@ bool Source::DequeueBuffer() {
 | 
			
		||||
    if (state.input_queue.empty())
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    const Buffer buf = state.input_queue.top();
 | 
			
		||||
    state.input_queue.pop();
 | 
			
		||||
    Buffer buf = state.input_queue.top();
 | 
			
		||||
 | 
			
		||||
    // 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) {
 | 
			
		||||
        state.adpcm_state.yn1 = buf.adpcm_yn[0];
 | 
			
		||||
        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);
 | 
			
		||||
    if (memory) {
 | 
			
		||||
        const unsigned num_channels = buf.mono_or_stereo == MonoOrStereo::Stereo ? 2 : 1;
 | 
			
		||||
@ -305,10 +324,13 @@ bool Source::DequeueBuffer() {
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    state.current_sample_number = 0;
 | 
			
		||||
    state.next_sample_number = 0;
 | 
			
		||||
    // the first playthrough starts at play_position, loops start at the beginning of the buffer
 | 
			
		||||
    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.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",
 | 
			
		||||
              source_id, buf.buffer_id, buf.from_queue ? "true" : "false",
 | 
			
		||||
 | 
			
		||||
@ -76,6 +76,8 @@ private:
 | 
			
		||||
        Format format;
 | 
			
		||||
 | 
			
		||||
        bool from_queue;
 | 
			
		||||
        u32_dsp play_position; // = 0;
 | 
			
		||||
        bool has_played;       // = false;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct BufferOrder {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user