golang轻量级音频处理库插件malgo的使用

golang轻量级音频处理库插件malgo的使用

malgo简介

malgo是miniaudio库的Go语言绑定,它是一个轻量级的音频处理库。该库需要cgo支持,但在Windows/macOS上不需要链接任何额外库,在Linux/BSD系统上只需要链接-ldl

安装

go get -u github.com/gen2brain/malgo

文档

可以在GoDoc上查看详细文档,也可以查看项目中的示例代码。

支持平台

  • Windows (WASAPI, DirectSound, WinMM)
  • Linux (PulseAudio, ALSA, JACK)
  • FreeBSD/NetBSD/OpenBSD (OSS/audio(4)/sndio)
  • macOS/iOS (CoreAudio)
  • Android (OpenSL|ES, AAudio)

示例代码

下面是一个使用malgo播放正弦波的完整示例:

package main

import (
	"math"
	"time"

	"github.com/gen2brain/malgo"
)

func main() {
	// 初始化上下文
	ctx, err := malgo.InitContext(nil, malgo.ContextConfig{}, func(message string) {
		// 日志回调函数
		println(message)
	})
	if err != nil {
		panic(err)
	}
	defer func() {
		_ = ctx.Uninit()
		ctx.Free()
	}()

	// 设备配置
	deviceConfig := malgo.DefaultDeviceConfig(malgo.Playback)
	deviceConfig.Playback.Format = malgo.FormatS16
	deviceConfig.Playback.Channels = 2
	deviceConfig.SampleRate = 44100
	deviceConfig.Alsa.NoMMap = 1

	// 正弦波参数
	frequency := 440.0 // Hz
	amplitude := 0.3
	phase := 0.0

	// 回调函数,生成正弦波
	sampleCount := 0
	onSamples := func(pOutputSample, pInputSamples []byte, framecount uint32) {
		samples := malgo.S16ToSamples(pOutputSample)
		for i := 0; i < len(samples); i += 2 {
			sample := int16(math.Sin(2*math.Pi*frequency*float64(sampleCount)/float64(deviceConfig.SampleRate)+phase) * int16(amplitude*32767.0)
			samples[i] = sample   // 左声道
			samples[i+1] = sample // 右声道
			sampleCount++
		}
	}

	// 创建设备
	device, err := malgo.InitDevice(ctx.Context, deviceConfig, malgo.DeviceCallbacks{
		Data: onSamples,
	})
	if err != nil {
		panic(err)
	}
	defer device.Uninit()

	// 启动设备
	err = device.Start()
	if err != nil {
		panic(err)
	}

	// 播放5秒钟
	time.Sleep(5 * time.Second)
}

另一个示例:录制音频

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/gen2brain/malgo"
)

func main() {
	// 初始化上下文
	ctx, err := malgo.InitContext(nil, malgo.ContextConfig{}, nil)
	if err != nil {
		panic(err)
	}
	defer func() {
		_ = ctx.Uninit()
		ctx.Free()
	}()

	// 创建输出文件
	file, err := os.Create("recording.raw")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	// 设备配置
	deviceConfig := malgo.DefaultDeviceConfig(malgo.Capture)
	deviceConfig.Capture.Format = malgo.FormatS16
	deviceConfig.Capture.Channels = 2
	deviceConfig.SampleRate = 44100

	// 回调函数,将音频数据写入文件
	onSamples := func(pOutputSample, pInputSamples []byte, framecount uint32) {
		_, err := file.Write(pInputSamples)
		if err != nil {
			panic(err)
		}
	}

	// 创建设备
	device, err := malgo.InitDevice(ctx.Context, deviceConfig, malgo.DeviceCallbacks{
		Data: onSamples,
	})
	if err != nil {
		panic(err)
	}
	defer device.Uninit()

	// 启动设备
	err = device.Start()
	if err != nil {
		panic(err)
	}

	fmt.Println("Recording... Press Enter to stop.")
	time.Sleep(5 * time.Second)
	fmt.Println("Recording stopped.")
}

这些示例展示了如何使用malgo进行基本的音频播放和录制。你可以根据需要修改这些代码来实现更复杂的音频处理功能。


更多关于golang轻量级音频处理库插件malgo的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang轻量级音频处理库插件malgo的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


malgo - Go语言轻量级音频处理库使用指南

malgo是一个Go语言绑定的miniaudio库,提供了轻量级的音频捕获和播放功能。下面我将详细介绍malgo的基本用法。

安装

首先安装malgo库:

go get github.com/gen2brain/malgo

基本使用示例

1. 初始化上下文

package main

import (
	"log"
	"github.com/gen2brain/malgo"
)

func main() {
	ctx, err := malgo.InitContext(nil, malgo.ContextConfig{}, func(message string) {
		log.Printf("LOG: %v", message)
	})
	if err != nil {
		log.Fatal(err)
	}
	defer func() {
		_ = ctx.Uninit()
		ctx.Free()
	}()
	
	// 其他操作...
}

2. 音频播放示例

func playAudio(ctx *malgo.AllocatedContext) error {
	deviceConfig := malgo.DefaultDeviceConfig(malgo.Playback)
	deviceConfig.Playback.Format = malgo.FormatS16
	deviceConfig.Playback.Channels = 2
	deviceConfig.SampleRate = 44100
	deviceConfig.Alsa.NoMMap = 1

	// 假设我们有一些PCM数据
	sampleData := generateSineWave(440, 5, 44100, 2)

	var playbackSampleCount uint32
	onSend := func(_, sampleCount uint32, pSamples []byte) uint32 {
		samplesToWrite := sampleCount * deviceConfig.Playback.Channels * 2 // 2 bytes per sample (S16)
		if playbackSampleCount+sampleCount > uint32(len(sampleData))/deviceConfig.Playback.Channels/2 {
			return 0
		}

		copy(pSamples, sampleData[playbackSampleCount*deviceConfig.Playback.Channels*2:])
		playbackSampleCount += sampleCount
		return samplesToWrite
	}

	device, err := malgo.InitDevice(ctx.Context, deviceConfig, malgo.DeviceCallbacks{
		Data: onSend,
	})
	if err != nil {
		return err
	}
	defer device.Uninit()

	err = device.Start()
	if err != nil {
		return err
	}

	// 等待播放完成
	for {
		if playbackSampleCount >= uint32(len(sampleData))/deviceConfig.Playback.Channels/2 {
			break
		}
	}

	return nil
}

func generateSineWave(freq float64, duration float64, sampleRate uint32, channels uint32) []byte {
	// 生成正弦波音频数据的实现...
}

3. 音频录制示例

func recordAudio(ctx *malgo.AllocatedContext, outputFile string) error {
	deviceConfig := malgo.DefaultDeviceConfig(malgo.Capture)
	deviceConfig.Capture.Format = malgo.FormatS16
	deviceConfig.Capture.Channels = 2
	deviceConfig.SampleRate = 44100

	var recordedData []byte
	onRecv := func(_, sampleCount uint32, pSamples []byte) uint32 {
		recordedData = append(recordedData, pSamples...)
		return sampleCount * deviceConfig.Capture.Channels * 2
	}

	device, err := malgo.InitDevice(ctx.Context, deviceConfig, malgo.DeviceCallbacks{
		Data: onRecv,
	})
	if err != nil {
		return err
	}
	defer device.Uninit()

	err = device.Start()
	if err != nil {
		return err
	}

	// 录制5秒
	time.Sleep(5 * time.Second)

	// 将recordedData写入WAV文件
	return writeWAVFile(outputFile, recordedData, deviceConfig)
}

func writeWAVFile(filename string, data []byte, config malgo.DeviceConfig) error {
	// 实现WAV文件写入...
}

高级功能

1. 枚举音频设备

func listDevices(ctx *malgo.AllocatedContext) {
	playbackDevices, err := ctx.Devices(malgo.Playback)
	if err != nil {
		log.Fatal(err)
	}

	log.Println("Playback devices:")
	for i, device := range playbackDevices {
		log.Printf("%d: %s (ID: %s)\n", i, device.Name(), device.ID)
	}

	captureDevices, err := ctx.Devices(malgo.Capture)
	if err != nil {
		log.Fatal(err)
	}

	log.Println("Capture devices:")
	for i, device := range captureDevices {
		log.Printf("%d: %s (ID: %s)\n", i, device.Name(), device.ID)
	}
}

2. 使用特定设备

func playWithSpecificDevice(ctx *malgo.AllocatedContext, deviceID string) {
	deviceConfig := malgo.DefaultDeviceConfig(malgo.Playback)
	deviceConfig.Playback.Format = malgo.FormatS16
	deviceConfig.Playback.Channels = 2
	deviceConfig.SampleRate = 44100
	deviceConfig.Playback.DeviceID = malgo.StringToDeviceID(deviceID)
	
	// 其余播放代码...
}

注意事项

  1. malgo是miniaudio的Go绑定,底层使用CGO,编译时需要C编译器
  2. 在Windows上可能需要安装DirectSound或WASAPI驱动
  3. 在Linux上需要ALSA或PulseAudio
  4. 实时音频处理需要注意缓冲区大小和延迟问题

malgo提供了轻量级的音频处理能力,适合需要基本音频输入输出的Go应用程序。对于更复杂的音频处理需求,可能需要结合其他专门的DSP库使用。

回到顶部