依赖库
# 安装工具pkg
sudo apt install pkg-config
# 安装 alsa 开发库
sudo apt-get install libalsa-ocaml-dev
主要代码
package main
import (
"log"
"os"
"time"
"github.com/faiface/beep"
"github.com/faiface/beep/mp3"
"github.com/faiface/beep/speaker"
)
func main() {
f, err := os.Open("./Lame_Drivers_-_01_-_Frozen_Egg.mp3")
if err != nil {
log.Fatal(err)
}
streamer, format, err := mp3.Decode(f)
if err != nil {
log.Fatal(err)
}
defer streamer.Close()
speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
done := make(chan bool)
speaker.Play(beep.Seq(streamer, beep.Callback(func() {
done <- true
})))
<-done
}
获取系统的音频设备
// Copyright 2021 The Oto Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !android && !darwin && !js && !windows && !nintendosdk
package main
// #cgo pkg-config: alsa
//
// #include <alsa/asoundlib.h>
import "C"
import (
"fmt"
"sync"
"unsafe"
)
type context struct {
channelCount int
suspended bool
handle *C.snd_pcm_t
cond *sync.Cond
ready chan struct{}
}
var theContext *context
func alsaError(name string, err C.int) error {
return fmt.Errorf("oto: ALSA error at %s: %s", name, C.GoString(C.snd_strerror(err)))
}
func deviceCandidates() []string {
const getAllDevices = -1
cPCMInterfaceName := C.CString("pcm")
defer C.free(unsafe.Pointer(cPCMInterfaceName))
var hints *unsafe.Pointer
err := C.snd_device_name_hint(getAllDevices, cPCMInterfaceName, &hints)
if err != 0 {
return []string{"default", "plug:default"}
}
defer C.snd_device_name_free_hint(hints)
var devices []string
cIoHintName := C.CString("IOID")
defer C.free(unsafe.Pointer(cIoHintName))
cNameHintName := C.CString("NAME")
defer C.free(unsafe.Pointer(cNameHintName))
for it := hints; *it != nil; it = (*unsafe.Pointer)(unsafe.Pointer(uintptr(unsafe.Pointer(it)) + unsafe.Sizeof(uintptr(0)))) {
io := C.snd_device_name_get_hint(*it, cIoHintName)
defer func() {
if io != nil {
C.free(unsafe.Pointer(io))
}
}()
if C.GoString(io) == "Input" {
continue
}
name := C.snd_device_name_get_hint(*it, cNameHintName)
defer func() {
if name != nil {
C.free(unsafe.Pointer(name))
}
}()
if name == nil {
continue
}
goName := C.GoString(name)
if goName == "null" {
continue
}
if goName == "default" {
continue
}
devices = append(devices, goName)
}
devices = append([]string{"default", "plug:default"}, devices...)
return devices
}
func main() {
deviceList := deviceCandidates()
for idx,device := range deviceList {
println(idx)
println(device)
}
}