玖叶教程网

前端编程开发入门

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

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

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

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

[见地址](https://github.com/moonfdd/sdl2-go/blob/main/examples/a06-sdl-pcm/main1.go)

在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
}

执行结果如下:


发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言