前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >golang调用sdl2,播放pcm音频,报错signal arrived during external code execution。

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

原创
作者头像
福大大架构师每日一题
发布2022-06-21 21:10:37
4950
发布2022-06-21 21:10:37
举报
文章被收录于专栏:福大大架构师每日一题

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

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

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

见地址

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

代码语言:javascript
复制
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代码如下:

代码语言:go
复制
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
}

执行结果如下:

在这里插入图片描述
在这里插入图片描述

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档