Beispiel #1
0
func update() {
	lock.Lock()
	defer lock.Unlock()

	_, write, err := dsound.GetPlayAndWriteCursors()
	if err != nil {
		lastError = err
		return
	}
	if write != writeCursor {
		var delta uint
		if write > writeCursor {
			delta = write - writeCursor
		} else {
			// wrap-around happened in DirectSound's ring buffer
			delta = write + dsound.BufferSize() - writeCursor
		}
		advanceSoundsByBytes(int(delta))

		// rewrite the whole look-ahead with newly mixed data
		lastError = dsound.WriteToSoundBuffer(mix(), write)
		if lastError != nil {
			return
		}
	}
	writeCursor = write
}
Beispiel #2
0
// Init sets up DirectSound and prepares for mixing and playing sounds. It
// starts a Go routine that periodically writes to the sound buffer to output
// to the sound card.
// Call Close when you are done with the mixer.
func Init() error {
	initLock.Lock()
	defer initLock.Unlock()
	if inited {
		return nil
	}

	if err := dsound.Init(44100); err != nil {
		return err
	}

	writeAheadByteCount := bytesPerSecond / 10 // buffer 100ms
	// make sure it is evenly dividable into samples
	writeAheadByteCount -= writeAheadByteCount % bytesPerSample
	writeAheadBuffer = make([]byte, writeAheadByteCount)
	mixBuffer = make([]float32, writeAheadByteCount/2) // 2 bytes form one value
	leftBuffer = mixBuffer[:len(mixBuffer)/2]
	rightBuffer = mixBuffer[len(mixBuffer)/2:]
	volume = 1

	// initially write silence to sound buffer
	if err := dsound.WriteToSoundBuffer(writeAheadBuffer, 0); err != nil {
		return err
	}
	if err := dsound.StartSound(); err != nil {
		return err
	}

	stop = make(chan bool)
	go func() {
		pulse := time.Tick(10 * time.Millisecond)
		for {
			select {
			case <-pulse:
				update()
				if lastError != nil {
					return
				}
			case <-stop:
				return
			default:
				time.Sleep(1 * time.Millisecond)
			}
		}
	}()

	inited = true

	return nil
}