nativeaudio

audio playback for Go
Log | Files | Refs | README | LICENSE

commit 8a39e04d75ff38b156b0817f64a8f1f767ad1caf
parent 8e6998c8994381afcacf51d9a0fe6c6f8b101597
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date:   Tue, 26 Oct 2021 16:57:36 +0800

nativeaudio: [windows] avoid buffer allocating calling into C

We can pass the raw slice to C and avoid using C.CBytes which performs
an allocation.

Result is a very minor improvement, almost negligible but it's a trival
change so we can keep it.

BEFORE
======

goos: windows
goarch: amd64
pkg: git.sr.ht/~jackmordaunt/nativeaudio/internal/test
cpu: AMD Ryzen 5 3600 6-Core Processor
BenchmarkDecode/native-load-12         	       4	 311614425 ns/op	  606240 B/op	       3 allocs/op
BenchmarkDecode/native-decode-12       	       4	 263828450 ns/op	  606250 B/op	       3 allocs/op
BenchmarkDecode/ffmpeg-load-12         	      19	  59440921 ns/op	 2279943 B/op	    1498 allocs/op

AFTER
=====

goos: windows
goarch: amd64
pkg: git.sr.ht/~jackmordaunt/nativeaudio/internal/test
cpu: AMD Ryzen 5 3600 6-Core Processor
BenchmarkDecode/native-load-12         	       4	 316714700 ns/op	  606240 B/op	       3 allocs/op
BenchmarkDecode/native-decode-12       	       4	 258123650 ns/op	  606226 B/op	       2 allocs/op
BenchmarkDecode/ffmpeg-load-12         	      19	  59983868 ns/op	 2279907 B/op	    1498 allocs/op

Signed-off-by: Jack Mordaunt <jackmordaunt.dev@gmail.com>

Diffstat:
Maudio_windows.go | 4+---
Minternal/test/audio_test.go | 14++++++++++++--
2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/audio_windows.go b/audio_windows.go @@ -57,11 +57,9 @@ func load(path string) ([]byte, Format, error) { // decode compressed data, returning the uncompressed data as PCM data // (s16le) and details about the PCM required to playback correctly. -// -// TODO(jfm) [perf]: avoid copying buffer in (CBytes does a copy). func decode(compressed []byte) (uncompressed []byte, format Format, err error) { defer runtime.KeepAlive(compressed) - r := C.Decode((*C.uchar)(C.CBytes(compressed)), C.uint(len(compressed))) + r := C.Decode((*C.uchar)(unsafe.Pointer(&compressed[0])), C.uint(len(compressed))) if r.Err != nil && r.Err.Str != nil { defer C.ErrorFree(r.Err) return nil, format, collectErrors(r.Err) diff --git a/internal/test/audio_test.go b/internal/test/audio_test.go @@ -124,7 +124,7 @@ func abs(n int) int { } func BenchmarkDecode(b *testing.B) { - b.Run("native", func(b *testing.B) { + b.Run("native-load", func(b *testing.B) { for ii := 0; ii < b.N; ii++ { by, f, err := nativeaudio.Load("compressed.m4a") if err != nil { @@ -134,7 +134,17 @@ func BenchmarkDecode(b *testing.B) { _ = f } }) - b.Run("ffmpeg", func(b *testing.B) { + b.Run("native-decode", func(b *testing.B) { + for ii := 0; ii < b.N; ii++ { + by, f, err := nativeaudio.Decode(compressed) + if err != nil { + b.Fatalf("unexpected error during decode: %v", err) + } + _ = by + _ = f + } + }) + b.Run("ffmpeg-load", func(b *testing.B) { for ii := 0; ii < b.N; ii++ { by, f, err := nativeaudio.FFmpegLoad("compressed.m4a") if err != nil {