nativeaudio

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

commit 666898492c80aabd1195ba8856066b0858b57189
parent d1e38c3868005fe442299772d84306c7960571f6
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date:   Tue, 26 Oct 2021 16:45:01 +0800

nativeaudio: introduce decode api to macos and linux

FFmpeg functions are exported because they are needed in the benchmarks.

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

Diffstat:
Maudio_ffmpeg.go | 41+++++++++++++++++++++++++++++++++++------
Maudio_linux.go | 11++++++++---
Maudio_macos.go | 9+++++++--
3 files changed, 50 insertions(+), 11 deletions(-)

diff --git a/audio_ffmpeg.go b/audio_ffmpeg.go @@ -9,17 +9,18 @@ package nativeaudio import ( "bytes" "fmt" + "os" "os/exec" ) -// play an audio file with ffplay. +// FFmpegPlay an audio file with ffplay. // // ffplay -vn <path> -nodisp -autoexit // // -vn: no video, // -nodisp: do not launch graphical window, // -autoexit: exit the process after playback is complete. -func ffmpegPlay(path string) error { +func FFmpegPlay(path string) error { if out, err := exec.Command( "ffplay", "-vn", @@ -32,13 +33,13 @@ func ffmpegPlay(path string) error { return nil } -// load raw PCM with ffmpeg. +// FFmpegLoad raw PCM with ffmpeg. // // ffmpeg -i <path> -f s16le - // // s16le is the PCM format specifier, the final dash means "pipe to // stdout". -func ffmpegLoad(path string) ([]byte, error) { +func FFmpegLoad(path string) ([]byte, Format, error) { buffer := bytes.NewBuffer(nil) cmd := exec.Command( "ffmpeg", @@ -48,7 +49,35 @@ func ffmpegLoad(path string) ([]byte, error) { ) cmd.Stdout = buffer if err := cmd.Run(); err != nil { - return nil, fmt.Errorf("ffmpeg: %w", err) + return nil, Format{}, fmt.Errorf("ffmpeg: %w", err) } - return buffer.Bytes(), nil + return buffer.Bytes(), Format{}, nil +} + +// FFmpegDecode raw PCM with ffmpeg. +// +// ffmpeg -f m4a -i pipe: -f s16le - +// +// s16le is the PCM format specifier, the final dash means "pipe to +// stdout". +// +// NOTE(jfm): unfortunately, some formats cannot be piped, so we will +// create a temporary file instead. +func FFmpegDecode(by []byte) ([]byte, Format, error) { + if err := os.WriteFile("tmp", by, 0644); err != nil { + return nil, Format{}, fmt.Errorf("creating tmp file: %w", err) + } + defer os.Remove("tmp") + buffer := bytes.NewBuffer(nil) + cmd := exec.Command( + "ffmpeg", + "-i", "tmp", + "-f", "s16le", + "-", + ) + cmd.Stdout = buffer + if err := cmd.Run(); err != nil { + return nil, Format{}, fmt.Errorf("ffmpeg: %w", err) + } + return buffer.Bytes(), Format{}, nil } diff --git a/audio_linux.go b/audio_linux.go @@ -4,10 +4,15 @@ package nativeaudio // play stub for Linux. func play(path string) error { - return ffmpegPlay(path) + return FFmpegPlay(path) } // load stub for Linux. -func load(path string) ([]byte, error) { - return ffmpegLoad(path) +func load(path string) ([]byte, Format, error) { + return FFmpegLoad(path) +} + +// decode stub for Linux. +func decode(by []byte) ([]byte, Format, error) { + return FFmpegDecode(by) } diff --git a/audio_macos.go b/audio_macos.go @@ -4,10 +4,15 @@ package nativeaudio // play stub for macOS. func play(path string) error { - return ffmpegPlay(path) + return FFmpegPlay(path) } // load stub for macOS. func load(path string) ([]byte, error) { - return ffmpegLoad(path) + return FFmpegLoad(path) +} + +// decode stub for macOS. +func decode(by []byte) ([]byte, Format, error) { + return FFmpegDecode(by) }