golang调用sdl2,播放pcm音频,报错signal arrived during external code execution。

Posted 福大大架构师每日一题

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang调用sdl2,播放pcm音频,报错signal arrived during external code execution。相关的知识,希望对你有一定的参考价值。

golang调用sdl2,播放pcm音频,报错signal arrived during external code execution。

win10 x64下测试成功,其他操作系统下不保证成功。

采用的是syscall方式,不是cgo方式。

见地址
在go1.16.15编译后然后执行,会报如下错。换成go1.18就不报错了。

Exception 0xc0000005 0x0 0xc000442000 0x7ff96da8db50
PC=0x7ff96da8db50
signal arrived during external code execution

syscall.Syscall6(0x7ff96daa7440, 0x4, 0x20d6354a0a0, 0xc000442000, 0x1000, 0x10, 0x0, 0x0, 0x0, 0x0, …)
D:/Program Files/Go/go1.16.15/src/runtime/syscall_windows.go:347 +0xf2
syscall.(*Proc).Call(0xc000599b40, 0xc0001207c0, 0x4, 0x4, 0x20, 0xa6ffa0, 0x20d6354a001, 0xc0001207c0)
D:/Program Files/Go/go1.16.15/src/syscall/dll_windows.go:188 +0x385
syscall.(*LazyProc).Call(0xc00007fc50, 0xc0001207c0, 0x4, 0x4, 0x3, 0x3, 0x20d6354a0a0, 0x0)
D:/Program Files/Go/go1.16.15/src/syscall/dll_windows.go:339 +0x78
github.com/moonfdd/sdl2-go/sdl.SDL_MixAudio(0x20d6354a0a0, 0xc000442000, 0x1000001000)
D:/mysetup/gopath/src/sdl2-go/sdl/SDL_audio.go:1185 +0xf1
main.fill_audio_pcm(0xc00010ff48, 0x20d6354a0a0, 0x1000, 0x0)
D:/mysetup/gopath/src/sdl2-go/examples/a06-sdl-pcm/main1.go:33 +0x125

goroutine 1 [chan receive]:
main.main()
D:/mysetup/gopath/src/sdl2-go/examples/a06-sdl-pcm/main1.go:66 +0x288
rax 0x20d6354a0a0
rbx 0xc0000086e0
rcx 0x20d6354a0a0
rdi 0xecaa4c3000
rsi 0xc0000439c0
rbp 0xc000043960
rsp 0xecabbffb50
r8 0x8010
r9 0x20d6354b0a0
r10 0x10
r11 0x4
r12 0xa7b800
r13 0x0
r14 0x0
r15 0x2030001
rip 0x7ff96da8db50
rflags 0x10206
cs 0x33
fs 0x53
gs 0x2b

golang代码如下:

package main

import (
	"fmt"
	"github.com/moonfdd/sdl2-go/sdl"
	"github.com/moonfdd/sdl2-go/sdlcommon"
	"io/ioutil"
	"sync"
	"syscall"
	"unsafe"
)

var o sync.Once

//音频设备回调函数
func fill_audio_pcm(udata sdlcommon.FVoidP, stream *sdlcommon.FUint8T, len1 sdlcommon.FInt) uintptr 
	info := (*Info)(unsafe.Pointer(udata))
	if info.isStop 
		return 0
	
	if info.Start >= info.Len 
		info.isStop = true
		o.Do(func() 
			ch <- struct
		)
		return 0
	
	sdl.SDL_memset(uintptr(unsafe.Pointer(stream)), 0, uint64(len1))
	if len1 > int32(info.Len-info.Start) 
		fmt.Println("不足len", len1, info.Len-info.Start)
		len1 = int32(info.Len - info.Start)
	
	sdl.SDL_MixAudio(stream, &info.Data[info.Start], uint32(len1), sdl.SDL_MIX_MAXVOLUME/8)
	info.Start += int(len1)
	return 0


var ch = make(chan struct, 1)

func main() 
	sdlcommon.SetSDL2Path("SDL2.dll")
	var spec sdl.SDL_Audiospec
	sdl.SDL_Init(sdl.SDL_INIT_AUDIO)
	spec.Freq = 44100
	spec.Format = sdl.AUDIO_S16SYS // 采样点格式
	spec.Channels = 2              // 2通道
	spec.Silence = 0
	spec.Userdata = uintptr(0)
	spec.Samples = 1024                                 // 23.2ms -> 46.4ms 每次读取的采样数量,多久产生一次回调和 samples
	spec.Callback = syscall.NewCallback(fill_audio_pcm) // 回调函数

	fileData, err := ioutil.ReadFile("44100_16bit_2ch.pcm")
	if err != nil 
		fmt.Println("读取文件失败", err)
		return
	
	info := new(Info)
	info.Data = fileData
	info.Len = len(fileData)
	spec.Userdata = uintptr(unsafe.Pointer(info))
	if sdl.SDL_OpenAudio(&spec, nil) != 0 
		fmt.Println("打开音频设备失败")
		return
	
	sdl.SDL_PauseAudio(0)
	<-ch
	fmt.Println("关闭")
	sdl.SDL_CloseAudio()
	sdl.SDL_Quit()


type Info struct 
	Data   []byte
	Len    int
	Start  int
	isStop bool


执行结果如下:

以上是关于golang调用sdl2,播放pcm音频,报错signal arrived during external code execution。的主要内容,如果未能解决你的问题,请参考以下文章

VLC如何在普通PC上播放24位PCM音频?

最简单的视音频播放演示样例7:SDL2播放RGB/YUV

如何将 PCM 音频流转换为在线播放

如何播放 PCM-24 音频?

使用WindowsAPI实现播放PCM音频的方法

PCM音频实时播放:音频字节数组(16/8位)转为PCM ArrayBuffer流