Skip to content

Commit

Permalink
oto: use a single OS thread for Darwin
Browse files Browse the repository at this point in the history
Updates #242
  • Loading branch information
hajimehoshi committed Aug 5, 2024
1 parent ac8b8b4 commit e73becc
Showing 1 changed file with 42 additions and 6 deletions.
48 changes: 42 additions & 6 deletions driver_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package oto

import (
"fmt"
"runtime"
"sync"
"time"
"unsafe"
Expand Down Expand Up @@ -78,6 +79,9 @@ type context struct {

cond *sync.Cond

toPause bool
toResume bool

mux *mux.Mux
err atomicError
}
Expand Down Expand Up @@ -118,7 +122,8 @@ func newContext(sampleRate int, channelCount int, format mux.Format, bufferSizeI
}

go func() {
defer close(ready)
runtime.LockOSThread()
defer runtime.UnlockOSThread()

q, bs, err := newAudioQueue(sampleRate, channelCount, oneBufferSizeInBytes)
if err != nil {
Expand Down Expand Up @@ -146,7 +151,9 @@ func newContext(sampleRate int, channelCount int, format mux.Format, bufferSizeI
return
}

go c.loop()
close(ready)

c.loop()
}()

return c, ready, nil
Expand All @@ -156,7 +163,7 @@ func (c *context) wait() bool {
c.cond.L.Lock()
defer c.cond.L.Unlock()

for len(c.unqueuedBuffers) == 0 && c.err.Load() == nil {
for len(c.unqueuedBuffers) == 0 && c.err.Load() == nil && !c.toPause && !c.toResume {
c.cond.Wait()
}
return c.err.Load() == nil
Expand All @@ -180,6 +187,22 @@ func (c *context) appendBuffer(buf32 []float32) {
return
}

if c.toPause {
if err := c.pause(); err != nil {
c.err.TryStore(err)
}
c.toPause = false
return
}

if c.toResume {
if err := c.resume(); err != nil {
c.err.TryStore(err)
}
c.toResume = false
return
}

buf := c.unqueuedBuffers[0]
copy(c.unqueuedBuffers, c.unqueuedBuffers[1:])
c.unqueuedBuffers = c.unqueuedBuffers[:len(c.unqueuedBuffers)-1]
Expand All @@ -199,9 +222,9 @@ func (c *context) Suspend() error {
if err := c.err.Load(); err != nil {
return err.(error)
}
if osstatus := _AudioQueuePause(c.audioQueue); osstatus != noErr {
return fmt.Errorf("oto: AudioQueuePause failed: %d", osstatus)
}
c.toPause = true
c.toResume = false
c.cond.Signal()
return nil
}

Expand All @@ -212,7 +235,20 @@ func (c *context) Resume() error {
if err := c.err.Load(); err != nil {
return err.(error)
}
c.toPause = false
c.toResume = true
c.cond.Signal()
return nil
}

func (c *context) pause() error {
if osstatus := _AudioQueuePause(c.audioQueue); osstatus != noErr {
return fmt.Errorf("oto: AudioQueuePause failed: %d", osstatus)
}
return nil
}

func (c *context) resume() error {
var retryCount int
try:
if osstatus := _AudioQueueStart(c.audioQueue, nil); osstatus != noErr {
Expand Down

0 comments on commit e73becc

Please sign in to comment.