1 Star 0 Fork 0

rocket049/randrepeater-go

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
audio.go 2.96 KB
一键复制 编辑 原始数据 按行查看 历史
rocket049 提交于 2025-03-28 19:02 +08:00 . null
package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"sync"
"sync/atomic"
"time"
"github.com/gordonklaus/portaudio"
)
var input *portaudio.Stream
const sampleRate = 44100
const bufferLen = 22050
var in = make([]int16, bufferLen) // 44100是采样率,根据需要调整大小和采样率
var rdLocker = &sync.Mutex{}
var playCtrlStop chan int
var playFlag = &atomic.Bool{}
var mutexPlayer = &sync.Mutex{}
func init() {
playFlag.Store(false)
var err error
err = portaudio.Initialize()
if err != nil {
ErrPanic(err)
}
input, err = portaudio.OpenDefaultStream(1, 0, sampleRate, len(in), in)
if err != nil {
ErrPanic(err)
}
input.Start()
go func() {
for {
rdLocker.Lock()
err := input.Read()
rdLocker.Unlock()
if err != nil {
break
}
}
}()
playCtrlStop = make(chan int)
}
func startRecord(filename string, ctrl chan int8) error {
os.MkdirAll("audios", os.ModePerm)
name := filepath.Join("audios", filename)
recordFlag.Store(true)
defer recordFlag.Store(false)
writer := NewAudioFile()
err := writer.Create(name)
if err != nil {
return err
}
defer writer.Close()
rdLocker.Lock()
defer rdLocker.Unlock()
loop:
for {
err := writer.Write(in)
if err != nil {
fmt.Println("保存数据失败:", err)
return err
}
select {
case <-ctrl:
ctrl <- 1
break loop
default:
}
//println("record...")
err = input.Read() // 读取数据到缓冲区
if err != nil {
fmt.Println("读取数据失败:", err)
return err
}
}
return nil
}
func stopRecord(ctrl chan int8) error {
ctrl <- 0
<-ctrl
return nil
}
func stopPlay() {
if playFlag.Load() {
playCtrlStop <- 1
<-playCtrlStop
//println("stop ok")
}
}
func stopPlayForRecord() {
if playFlag.Load() {
playCtrlStop <- 1
<-playCtrlStop
time.Sleep(time.Millisecond * 500)
//println("stop ok")
}
}
func playAudio(filename string) error {
if playFlag.Load() {
return errors.New("Playing other audio")
}
name := filepath.Join("audios", filename)
reader := NewAudioFile()
err := reader.Open(name)
if err != nil {
return err
}
defer reader.Close()
mutexPlayer.Lock()
defer mutexPlayer.Unlock()
playFlag.Store(true)
defer playFlag.Store(false)
//打开pa播放流
out := make([]int16, bufferLen)
output, err := portaudio.OpenDefaultStream(0, 1, sampleRate, len(out), out)
if err != nil {
fmt.Println("打开输出流失败:", err)
return err
}
defer output.Close() // 关闭输出流
output.Start()
defer output.Close()
n, err := reader.Read(out)
if err != nil {
return nil
}
for {
output.Write()
d := time.Duration(float64(time.Second) * float64(n) / float64(sampleRate))
after := time.After(d)
//利用等待时间读取下一段数据,使播放效果更流畅
n, err = reader.Read(out)
select {
case <-playCtrlStop:
playCtrlStop <- 2
//println("stop play not complete")
return nil
case <-after:
//println("stop play complete:", d)
}
if err != nil {
return nil
}
}
//pa播放
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/rocket049/randrepeater-go.git
git@gitee.com:rocket049/randrepeater-go.git
rocket049
randrepeater-go
randrepeater-go
master

搜索帮助