Files
engine/ring_audio.go
2021-06-14 22:15:25 +08:00

124 lines
2.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package engine
import (
"bytes"
"sync"
"sync/atomic"
"time"
)
type RingItem_Audio struct {
AudioPack
sync.WaitGroup
*bytes.Buffer
UpdateTime time.Time
}
// Ring 环形缓冲,使用数组实现
type Ring_Audio struct {
Current *RingItem_Audio
buffer []RingItem_Audio
Index byte
Flag int32 // 0:不在写入1正在写入2已销毁
}
func (r *Ring_Audio) SubRing(index byte) *Ring_Audio {
result := &Ring_Audio{
buffer: r.buffer,
}
result.GoTo(index)
return result
}
// NewRing 创建Ring
func NewRing_Audio() (r *Ring_Audio) {
r = &Ring_Audio{
buffer: make([]RingItem_Audio, 256),
}
r.GoTo(0)
r.Current.Add(1)
return
}
// GoTo 移动到指定索引处
func (r *Ring_Audio) GoTo(index byte) {
r.Index = index
r.Current = &r.buffer[index]
}
// GetAt 获取指定索引处的引用
func (r *Ring_Audio) GetAt(index byte) *RingItem_Audio {
return &r.buffer[index]
}
// GetNext 获取下一个位置的引用
func (r *Ring_Audio) GetNext() *RingItem_Audio {
return &r.buffer[r.Index+1]
}
// GetLast 获取上一个位置的引用
func (r *Ring_Audio) GetLast() *RingItem_Audio {
return &r.buffer[r.Index-1]
}
// GoNext 移动到下一个位置
func (r *Ring_Audio) GoNext() {
r.Index = r.Index + 1
r.Current = &r.buffer[r.Index]
}
// GoBack 移动到上一个位置
func (r *Ring_Audio) GoBack() {
r.Index = r.Index - 1
r.Current = &r.buffer[r.Index]
}
// NextW 写下一个
func (r *Ring_Audio) NextW() {
item := r.Current
item.UpdateTime = time.Now()
if atomic.CompareAndSwapInt32(&r.Flag, 0, 1) {
r.GoNext()
r.Current.Add(1)
item.Done()
if !atomic.CompareAndSwapInt32(&r.Flag, 1, 0) {
r.Current.Done()
}
}
}
func (r *Ring_Audio) Dispose() {
if atomic.CompareAndSwapInt32(&r.Flag, 0, 2) {
r.Current.Done()
} else if atomic.CompareAndSwapInt32(&r.Flag, 1, 2) {
} else if atomic.CompareAndSwapInt32(&r.Flag, 0, 2) {
r.Current.Done()
}
}
// NextR 读下一个
func (r *Ring_Audio) NextR() bool {
r.GoNext()
r.Current.Wait()
return r.Flag != 2 // 2代表已经销毁
}
func (r *Ring_Audio) GetBuffer() *bytes.Buffer {
if r.Current.Buffer == nil {
r.Current.Payload = []byte{}
r.Current.Buffer = bytes.NewBuffer(r.Current.Payload)
} else {
r.Current.Reset()
}
return r.Current.Buffer
}
// Timeout 发布者是否超时了
func (r *Ring_Audio) Timeout(t time.Duration) bool {
// 如果设置为0则表示永不超时
if t == 0 {
return false
}
return time.Since(r.Current.UpdateTime) > t
}