PortAudio:默认帧缓冲时的播放延迟

huangapple go评论87阅读模式
英文:

PortAudio: Playback lag at default frames-per-buffer

问题

我正在尝试在Go中使用PortAudio异步播放音频。据我所知,PortAudio处理自己的线程,所以我不需要使用Go的内置并发功能。我正在使用libsndfile加载文件(也是Go绑定)。以下是我的代码:

type Track struct {
    stream   *portaudio.Stream
    playhead int
    buffer   []int32
}

func LoadTrackFilesize(filename string, loop bool, bytes int) *Track {
    // 加载文件
    var info sndfile.Info
    soundFile, err := sndfile.Open(filename, sndfile.Read, &info)
    if err != nil {
        fmt.Printf("无法打开文件:%s\n", filename)
        panic(err)
    }
    buffer := make([]int32, bytes)
    numRead, err := soundFile.ReadItems(buffer)
    if err != nil {
        fmt.Printf("从文件中读取错误:%s\n", filename)
        panic(err)
    }
    defer soundFile.Close()

    // 创建音轨
    track := Track{
        buffer: buffer[:numRead],
    }

    // 创建流
    stream, err := portaudio.OpenDefaultStream(
        0, 2, float64(44100), portaudio.FramesPerBufferUnspecified, track.playCallback,
    )
    if err != nil {
        fmt.Printf("无法获取文件的流:%s\n", filename)
    }
    track.stream = stream

    return &track
}

func (t *Track) playCallback(out []int32) {
    for i := range out {
        out[i] = t.buffer[(t.playhead+i)%len(t.buffer)]
    }
    t.playhead += len(out) % len(t.buffer)
}

func (t *Track) Play() {
    t.stream.Start()
}

使用这些函数,在初始化PortAudio和其他一切之后,播放我提供的音轨,但是有非常严重的延迟,并且会减慢我的应用程序(游戏循环)的运行速度。

然而,如果我将每个缓冲区的帧数从FramesPerBufferUnspecified更改为较高的值,比如1024,音频就可以正常播放,并且不会干扰我的应用程序的其他部分。

为什么会这样?PortAudio文档建议使用未指定的值会“选择最佳延迟值”,但我明显没有看到这一点。

此外,当使用非常高的值时,我注意到音频中会出现一些微小的伪像-小的“爆裂”声。

我的回调函数或其他任何地方是否有问题,可能导致这两个问题之一或两个问题同时出现?

我正在使用OSX 10.10.5,Go 1.3.3以及来自Homebrew的libsndfile和portaudio。

谢谢。

英文:

I'm trying to play audio in Go, asynchronously, using PortAudio. As far as I'm aware PortAudio handles its own threading, so I don't need to use any of Go's build-in concurrency stuff. I'm using libsndfile to load the file (also Go bindings). Here is my code:

type Track struct {
stream   *portaudio.Stream
playhead int
buffer   []int32
}
func LoadTrackFilesize(filename string, loop bool, bytes int) *Track {
// Load file
var info sndfile.Info
soundFile, err := sndfile.Open(filename, sndfile.Read, &info)
if err != nil {
fmt.Printf("Could not open file: %s\n", filename)
panic(err)
}
buffer := make([]int32, bytes)
numRead, err := soundFile.ReadItems(buffer)
if err != nil {
fmt.Printf("Error reading from file: %s\n", filename)
panic(err)
}
defer soundFile.Close()
// Create track
track := Track{
buffer: buffer[:numRead],
}
// Create stream
stream, err := portaudio.OpenDefaultStream(
0, 2, float64(44100), portaudio.FramesPerBufferUnspecified, track.playCallback,
)
if err != nil {
fmt.Printf("Couldn't get stream for file: %s\n", filename)
}
track.stream = stream
return &track
}
func (t *Track) playCallback(out []int32) {
for i := range out {
out[i] = t.buffer[(t.playhead+i)%len(t.buffer)]
}
t.playhead += len(out) % len(t.buffer)
}
func (t *Track) Play() {
t.stream.Start()
}

Using these functions, after initialising PortAudio and all the rest, plays the audio track I supply - just. It's very laggy, and slows down the rest of my application (a game loop).

However, if I change the frames per buffer value from FramesPerBufferUnspecified to something high, say, 1024, the audio plays fine and doesn't interfere with the rest of my application.

Why is this? The PortAudio documentation suggests that using the unspecified value will 'choose a value for optimum latency', but I'm definitely not seeing that.

Additionally, when playing with this very high value, I notice some tiny artefacts - little 'popping' noises - in the audio.

Is there something wrong with my callback function, or anything else, that could be causing one or both of these problems?

I'm using OSX 10.10.5, with Go 1.3.3 and the libsndfile and portaudio from Homebrew.

Thanks.

答案1

得分: 1

将评论移动到答案中:

始终使用最新版本的Go进行测试。

此外,@Joel 发现您需要使用 float32 而不是 int32

英文:

Moving to the comment to an answer:

Always test with the latest version of Go.

Also, @Joel figured out that you need to use float32 instead of int32.

huangapple
  • 本文由 发表于 2015年9月1日 04:57:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/32319854.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定