golang实现跨平台音频输入输出处理的PortAudio插件库使用

Golang实现跨平台音频输入输出处理的PortAudio插件库使用

PortAudio简介

PortAudio是一个免费的跨平台音频I/O库,这个包提供了对PortAudio音频I/O库的Go语言接口。

安装要求

在构建这个包之前,你必须先安装PortAudio开发头文件和库。不同系统的安装方式:

  • Ubuntu/Debian系统: apt-get install portaudio19-dev
  • 其他系统可能需要从源代码安装

基本使用示例

下面是一个简单的PortAudio使用示例,演示如何录制和播放音频:

package main

import (
	"github.com/gordonklaus/portaudio"
	"log"
	"time"
)

func main() {
	// 初始化PortAudio
	err := portaudio.Initialize()
	if err != nil {
		log.Fatal(err)
	}
	defer portaudio.Terminate()

	// 打开默认输入流
	in := make([]float32, 64)
	stream, err := portaudio.OpenDefaultStream(1, 0, 44100, len(in), in)
	if err != nil {
		log.Fatal(err)
	}
	defer stream.Close()

	// 开始音频流
	err = stream.Start()
	if err != nil {
		log.Fatal(err)
	}

	// 录制5秒钟的音频
	log.Println("Recording...")
	time.Sleep(5 * time.Second)

	// 停止音频流
	err = stream.Stop()
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Recording stopped")
}

完整音频处理示例

下面是一个更完整的示例,演示如何同时进行音频输入和输出:

package main

import (
	"github.com/gordonklaus/portaudio"
	"log"
	"os"
	"os/signal"
)

func main() {
	// 初始化PortAudio
	err := portaudio.Initialize()
	if err != nil {
		log.Fatal(err)
	}
	defer portaudio.Terminate()

	// 音频缓冲区
	buffer := make([]float32, 64)
	
	// 打开音频流 (1个输入通道,1个输出通道,44100采样率)
	stream, err := portaudio.OpenDefaultStream(1, 1, 44100, len(buffer), func(in, out []float32) {
		// 简单的音频直通处理 - 将输入直接复制到输出
		for i := range out {
			out[i] = in[i]
		}
	})
	if err != nil {
		log.Fatal(err)
	}
	defer stream.Close()

	// 开始音频流
	err = stream.Start()
	if err != nil {
		log.Fatal(err)
	}
	defer stream.Stop()

	log.Println("Audio processing started (press Ctrl+C to stop)")

	// 等待中断信号
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, os.Kill)
	<-sig
}

设备枚举示例

PortAudio还支持枚举可用的音频设备:

package main

import (
	"fmt"
	"github.com/gordonklaus/portaudio"
	"log"
)

func main() {
	// 初始化PortAudio
	err := portaudio.Initialize()
	if err != nil {
		log.Fatal(err)
	}
	defer portaudio.Terminate()

	// 获取默认输入设备
	defaultIn, err := portaudio.DefaultInputDevice()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Default input device: %s\n", defaultIn.Name)

	// 获取默认输出设备
	defaultOut, err := portaudio.DefaultOutputDevice()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Default output device: %s\n", defaultOut.Name)

	// 列出所有可用设备
	devices, err := portaudio.Devices()
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("\nAvailable audio devices:")
	for i, device := range devices {
		fmt.Printf("%d: %s (in:%d out:%d)\n", i, device.Name, device.MaxInputChannels, device.MaxOutputChannels)
	}
}

注意事项

  1. 使用完毕后务必调用portaudio.Terminate()释放资源
  2. 音频处理回调函数中不要执行耗时操作,以免导致音频卡顿
  3. 不同平台的音频设备可能有不同的特性,建议在实际设备上测试

以上示例展示了PortAudio在Go中的基本用法,包括音频输入输出、设备枚举等功能。你可以根据实际需求扩展这些示例代码。


更多关于golang实现跨平台音频输入输出处理的PortAudio插件库使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现跨平台音频输入输出处理的PortAudio插件库使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用PortAudio实现跨平台音频处理的Golang指南

PortAudio是一个免费的跨平台开源音频I/O库,支持Windows、MacOS和Linux等操作系统。下面我将介绍如何在Golang中使用PortAudio进行跨平台音频输入输出处理。

1. 安装PortAudio绑定

Golang中最常用的PortAudio绑定是github.com/gordonklaus/portaudio

go get github.com/gordonklaus/portaudio

2. 基本音频输出示例

以下是一个简单的音频输出示例,播放440Hz的正弦波:

package main

import (
	"fmt"
	"math"
	"time"

	"github.com/gordonklaus/portaudio"
)

const sampleRate = 44100
const duration = 3 // seconds

func main() {
	portaudio.Initialize()
	defer portaudio.Terminate()

	buffer := make([]float32, sampleRate*duration)
	for i := range buffer {
		buffer[i] = float32(math.Sin(2 * math.Pi * 440 * float64(i) / sampleRate))
	}

	stream, err := portaudio.OpenDefaultStream(0, 1, sampleRate, len(buffer), func(out []float32) {
		copy(out, buffer)
		buffer = buffer[len(out):]
	})
	if err != nil {
		panic(err)
	}
	defer stream.Close()

	if err := stream.Start(); err != nil {
		panic(err)
	}
	defer stream.Stop()

	fmt.Println("Playing 440Hz sine wave for 3 seconds...")
	time.Sleep(duration * time.Second)
}

3. 音频输入录制示例

以下示例展示如何录制音频并保存到文件:

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/gordonklaus/portaudio"
	"github.com/mjibson/go-dsp/wav"
)

const sampleRate = 44100
const duration = 5 // seconds

func main() {
	portaudio.Initialize()
	defer portaudio.Terminate()

	buffer := make([]float32, sampleRate*duration)
	stream, err := portaudio.OpenDefaultStream(1, 0, sampleRate, 0, func(in []float32) {
		for i := range in {
			buffer = append(buffer, in[i])
			if len(buffer) >= sampleRate*duration {
				stream.Close()
			}
		}
	})
	if err != nil {
		panic(err)
	}
	defer stream.Close()

	if err := stream.Start(); err != nil {
		panic(err)
	}
	defer stream.Stop()

	fmt.Println("Recording for 5 seconds...")
	time.Sleep(duration * time.Second)

	// Save as WAV file
	file, err := os.Create("recording.wav")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	w := wav.NewWriter(file, sampleRate, 16, 1, 1)
	if err := w.WriteSamples(buffer); err != nil {
		panic(err)
	}

	fmt.Println("Recording saved to recording.wav")
}

4. 实时音频处理示例

以下示例展示如何实时处理音频输入并输出:

package main

import (
	"fmt"
	"math"
	"time"

	"github.com/gordonklaus/portaudio"
)

const sampleRate = 44100
const bufferSize = 512

func main() {
	portaudio.Initialize()
	defer portaudio.Terminate()

	stream, err := portaudio.OpenDefaultStream(1, 1, sampleRate, bufferSize, processAudio)
	if err != nil {
		panic(err)
	}
	defer stream.Close()

	if err := stream.Start(); err != nil {
		panic(err)
	}
	defer stream.Stop()

	fmt.Println("Real-time audio processing running. Press Enter to stop.")
	fmt.Scanln()
}

func processAudio(in, out []float32) {
	for i := range out {
		// Simple processing: amplify input and add some distortion
		val := in[i] * 2.0
		if val > 1.0 {
			val = 1.0
		} else if val < -1.0 {
			val = -1.0
		}
		// Add some distortion
		out[i] = float32(math.Tanh(float64(val * 3.0)))
	}
}

5. 高级特性

设备枚举

func listDevices() {
	portaudio.Initialize()
	defer portaudio.Terminate()

	devices, err := portaudio.Devices()
	if err != nil {
		panic(err)
	}

	fmt.Println("Available audio devices:")
	for i, d := range devices {
		fmt.Printf("%d: %s (in:%d, out:%d)\n", i, d.Name, d.MaxInputChannels, d.MaxOutputChannels)
	}
}

自定义设备选择

func selectDevice() {
	portaudio.Initialize()
	defer portaudio.Terminate()

	host, err := portaudio.DefaultHostApi()
	if err != nil {
		panic(err)
	}

	inputDevice := host.DefaultInputDevice
	outputDevice := host.DefaultOutputDevice

	// 使用特定设备
	param := portaudio.StreamParameters{
		Input: portaudio.StreamDeviceParameters{
			Device:   inputDevice,
			Channels: 1,
			Latency:  inputDevice.DefaultLowInputLatency,
		},
		Output: portaudio.StreamDeviceParameters{
			Device:   outputDevice,
			Channels: 1,
			Latency:  outputDevice.DefaultLowOutputLatency,
		},
		SampleRate:      44100,
		FramesPerBuffer: 512,
		Flags:          portaudio.NoFlag,
	}

	stream, err := portaudio.OpenStream(param, processAudio)
	if err != nil {
		panic(err)
	}
	defer stream.Close()
}

6. 注意事项

  1. 延迟处理:PortAudio提供了不同延迟级别的设备参数,可以根据应用需求选择低延迟或高稳定性。

  2. 线程安全:PortAudio的回调函数在专用音频线程中运行,需要注意线程安全问题。

  3. 错误处理:音频处理中可能会出现各种错误(设备不可用、缓冲区不足等),需要妥善处理。

  4. 资源管理:确保在程序退出前正确关闭流和终止PortAudio。

  5. 跨平台差异:不同平台可能有不同的默认音频设备和行为,测试时应在目标平台上验证。

PortAudio为Golang提供了强大的跨平台音频处理能力,适用于从简单的音频播放到复杂的实时音频处理应用。

回到顶部