diff options
| author | 2017-01-30 02:52:25 -0500 | |
|---|---|---|
| committer | 2017-01-29 23:52:25 -0800 | |
| commit | ff28080091aed21d216fb6794652d4938776ca5c (patch) | |
| tree | 872fcc2e6e031eff04976b10a6e4e65e9ffa140e /src | |
| parent | Merge pull request #2368 from wwylele/camera-2 (diff) | |
| download | yuzu-ff28080091aed21d216fb6794652d4938776ca5c.tar.gz yuzu-ff28080091aed21d216fb6794652d4938776ca5c.tar.xz yuzu-ff28080091aed21d216fb6794652d4938776ca5c.zip | |
Support looping HLE audio (#2422)
* Support looping HLE audio
* DSP: Fix dirty bit clears, handle nonmonotonically incrementing IDs
* DSP: Add start offset support
Diffstat (limited to '')
| -rw-r--r-- | src/audio_core/hle/source.cpp | 44 | ||||
| -rw-r--r-- | src/audio_core/hle/source.h | 2 |
2 files changed, 35 insertions, 11 deletions
diff --git a/src/audio_core/hle/source.cpp b/src/audio_core/hle/source.cpp index 2bbf7146e..92484c526 100644 --- a/src/audio_core/hle/source.cpp +++ b/src/audio_core/hle/source.cpp | |||
| @@ -158,6 +158,14 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config, | |||
| 158 | static_cast<size_t>(state.mono_or_stereo)); | 158 | static_cast<size_t>(state.mono_or_stereo)); |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | u32_dsp play_position = {}; | ||
| 162 | if (config.play_position_dirty && config.play_position != 0) { | ||
| 163 | config.play_position_dirty.Assign(0); | ||
| 164 | play_position = config.play_position; | ||
| 165 | // play_position applies only to the embedded buffer, and defaults to 0 w/o a dirty bit | ||
| 166 | // This will be the starting sample for the first time the buffer is played. | ||
| 167 | } | ||
| 168 | |||
| 161 | if (config.embedded_buffer_dirty) { | 169 | if (config.embedded_buffer_dirty) { |
| 162 | config.embedded_buffer_dirty.Assign(0); | 170 | config.embedded_buffer_dirty.Assign(0); |
| 163 | state.input_queue.emplace(Buffer{ | 171 | state.input_queue.emplace(Buffer{ |
| @@ -171,9 +179,18 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config, | |||
| 171 | state.mono_or_stereo, | 179 | state.mono_or_stereo, |
| 172 | state.format, | 180 | state.format, |
| 173 | false, | 181 | false, |
| 182 | play_position, | ||
| 183 | false, | ||
| 174 | }); | 184 | }); |
| 175 | LOG_TRACE(Audio_DSP, "enqueuing embedded addr=0x%08x len=%u id=%hu", | 185 | LOG_TRACE(Audio_DSP, "enqueuing embedded addr=0x%08x len=%u id=%hu start=%u", |
| 176 | config.physical_address, config.length, config.buffer_id); | 186 | config.physical_address, config.length, config.buffer_id, |
| 187 | static_cast<u32>(config.play_position)); | ||
| 188 | } | ||
| 189 | |||
| 190 | if (config.loop_related_dirty && config.loop_related != 0) { | ||
| 191 | config.loop_related_dirty.Assign(0); | ||
| 192 | LOG_WARNING(Audio_DSP, "Unhandled complex loop with loop_related=0x%08x", | ||
| 193 | static_cast<u32>(config.loop_related)); | ||
| 177 | } | 194 | } |
| 178 | 195 | ||
| 179 | if (config.buffer_queue_dirty) { | 196 | if (config.buffer_queue_dirty) { |
| @@ -192,6 +209,8 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config, | |||
| 192 | state.mono_or_stereo, | 209 | state.mono_or_stereo, |
| 193 | state.format, | 210 | state.format, |
| 194 | true, | 211 | true, |
| 212 | {}, // 0 in u32_dsp | ||
| 213 | false, | ||
| 195 | }); | 214 | }); |
| 196 | LOG_TRACE(Audio_DSP, "enqueuing queued %zu addr=0x%08x len=%u id=%hu", i, | 215 | LOG_TRACE(Audio_DSP, "enqueuing queued %zu addr=0x%08x len=%u id=%hu", i, |
| 197 | b.physical_address, b.length, b.buffer_id); | 216 | b.physical_address, b.length, b.buffer_id); |
| @@ -247,18 +266,18 @@ bool Source::DequeueBuffer() { | |||
| 247 | if (state.input_queue.empty()) | 266 | if (state.input_queue.empty()) |
| 248 | return false; | 267 | return false; |
| 249 | 268 | ||
| 250 | const Buffer buf = state.input_queue.top(); | 269 | Buffer buf = state.input_queue.top(); |
| 251 | state.input_queue.pop(); | 270 | |
| 271 | // if we're in a loop, the current sound keeps playing afterwards, so leave the queue alone | ||
| 272 | if (!buf.is_looping) { | ||
| 273 | state.input_queue.pop(); | ||
| 274 | } | ||
| 252 | 275 | ||
| 253 | if (buf.adpcm_dirty) { | 276 | if (buf.adpcm_dirty) { |
| 254 | state.adpcm_state.yn1 = buf.adpcm_yn[0]; | 277 | state.adpcm_state.yn1 = buf.adpcm_yn[0]; |
| 255 | state.adpcm_state.yn2 = buf.adpcm_yn[1]; | 278 | state.adpcm_state.yn2 = buf.adpcm_yn[1]; |
| 256 | } | 279 | } |
| 257 | 280 | ||
| 258 | if (buf.is_looping) { | ||
| 259 | LOG_ERROR(Audio_DSP, "Looped buffers are unimplemented at the moment"); | ||
| 260 | } | ||
| 261 | |||
| 262 | const u8* const memory = Memory::GetPhysicalPointer(buf.physical_address); | 281 | const u8* const memory = Memory::GetPhysicalPointer(buf.physical_address); |
| 263 | if (memory) { | 282 | if (memory) { |
| 264 | const unsigned num_channels = buf.mono_or_stereo == MonoOrStereo::Stereo ? 2 : 1; | 283 | const unsigned num_channels = buf.mono_or_stereo == MonoOrStereo::Stereo ? 2 : 1; |
| @@ -305,10 +324,13 @@ bool Source::DequeueBuffer() { | |||
| 305 | break; | 324 | break; |
| 306 | } | 325 | } |
| 307 | 326 | ||
| 308 | state.current_sample_number = 0; | 327 | // the first playthrough starts at play_position, loops start at the beginning of the buffer |
| 309 | state.next_sample_number = 0; | 328 | state.current_sample_number = (!buf.has_played) ? buf.play_position : 0; |
| 329 | state.next_sample_number = state.current_sample_number; | ||
| 310 | state.current_buffer_id = buf.buffer_id; | 330 | state.current_buffer_id = buf.buffer_id; |
| 311 | state.buffer_update = buf.from_queue; | 331 | state.buffer_update = buf.from_queue && !buf.has_played; |
| 332 | |||
| 333 | buf.has_played = true; | ||
| 312 | 334 | ||
| 313 | LOG_TRACE(Audio_DSP, "source_id=%zu buffer_id=%hu from_queue=%s current_buffer.size()=%zu", | 335 | LOG_TRACE(Audio_DSP, "source_id=%zu buffer_id=%hu from_queue=%s current_buffer.size()=%zu", |
| 314 | source_id, buf.buffer_id, buf.from_queue ? "true" : "false", | 336 | source_id, buf.buffer_id, buf.from_queue ? "true" : "false", |
diff --git a/src/audio_core/hle/source.h b/src/audio_core/hle/source.h index 3d725f2a3..ccb7f064f 100644 --- a/src/audio_core/hle/source.h +++ b/src/audio_core/hle/source.h | |||
| @@ -76,6 +76,8 @@ private: | |||
| 76 | Format format; | 76 | Format format; |
| 77 | 77 | ||
| 78 | bool from_queue; | 78 | bool from_queue; |
| 79 | u32_dsp play_position; // = 0; | ||
| 80 | bool has_played; // = false; | ||
| 79 | }; | 81 | }; |
| 80 | 82 | ||
| 81 | struct BufferOrder { | 83 | struct BufferOrder { |