| 291 | //----------------------------------------------------------------------------- |
| 292 | |
| 293 | void SFXVoice::setPosition( U32 inSample ) |
| 294 | { |
| 295 | // Clamp to sample range. |
| 296 | const U32 sample = inSample % ( mBuffer->getFormat().getSampleCount( mBuffer->getDuration() ) - 1 ); |
| 297 | |
| 298 | // Don't perform a seek when we already are at the |
| 299 | // given position. Especially avoids a costly stream |
| 300 | // clone when seeking on a streamed voice. |
| 301 | |
| 302 | if( getPosition() == sample ) |
| 303 | return; |
| 304 | |
| 305 | if( !mBuffer->isStreaming() ) |
| 306 | { |
| 307 | // Non-streaming sound. Just seek in the device buffer. |
| 308 | |
| 309 | _seek( sample ); |
| 310 | } |
| 311 | else |
| 312 | { |
| 313 | // Streaming sound. Reset the stream and playback. |
| 314 | // |
| 315 | // Unfortunately, the logic here is still prone to subtle timing dependencies |
| 316 | // in relation to the buffer updates. In retrospect, I feel that solving all issues |
| 317 | // of asynchronous operation on a per-voice/buffer level has greatly complicated |
| 318 | // the system. It seems now that it would have been a lot simpler to have a single |
| 319 | // asynchronous buffer/voice manager that manages the updates of all voices and buffers |
| 320 | // currently in the system in one spot. Packet reads could still be pushed out to |
| 321 | // the thread pool but queue updates would all be handled centrally in one spot. This |
| 322 | // would do away with problems like those (mostly) solved by the multi-step procedure |
| 323 | // here. |
| 324 | |
| 325 | // Go into transition. |
| 326 | |
| 327 | SFXStatus oldStatus; |
| 328 | while( true ) |
| 329 | { |
| 330 | oldStatus = mStatus; |
| 331 | if( oldStatus != SFXStatusTransition && |
| 332 | dCompareAndSwap( ( U32& ) mStatus, oldStatus, SFXStatusTransition ) ) |
| 333 | break; |
| 334 | } |
| 335 | |
| 336 | // Switch the stream. |
| 337 | |
| 338 | _resetStream( sample, false ); |
| 339 | |
| 340 | // Come out of transition. |
| 341 | |
| 342 | SFXStatus newStatus = oldStatus; |
| 343 | if( oldStatus == SFXStatusPlaying ) |
| 344 | newStatus = SFXStatusBlocked; |
| 345 | |
| 346 | dCompareAndSwap( ( U32& ) mStatus, SFXStatusTransition, newStatus ); |
| 347 | |
| 348 | // Trigger an update. |
| 349 | |
| 350 | SFXInternal::TriggerUpdate(); |
no test coverage detected