Skip to content

Instantly share code, notes, and snippets.

@rygorous
Created October 30, 2014 20:11
Show Gist options
  • Save rygorous/58358f18ce59bc79f360 to your computer and use it in GitHub Desktop.
Save rygorous/58358f18ce59bc79f360 to your computer and use it in GitHub Desktop.
Weak handles for audio
// ---- INTERFACE
// Sound handle. This is a weak reference; they automatically go invalid as voices
// stop playing and get reused. You don't need to worry about leaks.
struct SoundHandle
{
uint32_t opaque; // Mixer decides what this means (but 0=null)
explicit SoundHandle(uint32_t handle=0) : opaque(handle) {}
bool is_null() const { return opaque == 0; }
bool operator ==(const SoundHandle& x) const { return opaque == x.opaque; }
bool operator !=(const SoundHandle& x) const { return opaque != x.opaque; }
};
// ---- IMPLEMENTATION
// Handle is concat(valid,voice,counter)
// "valid" is a single bit (0 or 1)
// "voice" is the voice ID (as many bits as required for kMaxVoices)
// "counter" is the rest and gets incremented each time a voice is used (with wrap-around).
Mixer::Voice* Mixer::voice_from_handle(SoundHandle h)
{
// is valid?
if ((h.opaque & 1) == 0)
return nullptr;
Voice& v = new_app_state->voice[(h.opaque >> 1) & (kMaxVoices - 1)];
if (v.handle == h)
return &v;
else
return nullptr;
}
void Mixer::assign_new_handle(Voice& v, int voice_id)
{
assert(voice_id >= 0 && voice_id < kMaxVoices);
// counter bit mask
static const uint32_t counter_bit_mask = ~((kMaxVoices << 1) - 1);
// increment counter by 1 (using unsigned wraparound) while setting "valid"
// and "voice" bits.
v.handle.opaque = ((v.handle.opaque - counter_bit_mask) & counter_bit_mask)
| ((voice_id << 1) | 1); // voice/vald bits.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment