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代码如下:

    1. package main
    2. import (
    3. "fmt"
    4. "github.com/moonfdd/sdl2-go/sdl"
    5. "github.com/moonfdd/sdl2-go/sdlcommon"
    6. "io/ioutil"
    7. "sync"
    8. "syscall"
    9. "unsafe"
    10. )
    11. var o sync.Once
    12. //音频设备回调函数
    13. func fill_audio_pcm(udata sdlcommon.FVoidP, stream *sdlcommon.FUint8T, len1 sdlcommon.FInt) uintptr {
    14. info := (*Info)(unsafe.Pointer(udata))
    15. if info.isStop {
    16. return 0
    17. }
    18. if info.Start >= info.Len {
    19. info.isStop = true
    20. o.Do(func() {
    21. ch <- struct{}{}
    22. })
    23. return 0
    24. }
    25. sdl.SDL_memset(uintptr(unsafe.Pointer(stream)), 0, uint64(len1))
    26. if len1 > int32(info.Len-info.Start) {
    27. fmt.Println("不足len", len1, info.Len-info.Start)
    28. len1 = int32(info.Len - info.Start)
    29. }
    30. sdl.SDL_MixAudio(stream, &info.Data[info.Start], uint32(len1), sdl.SDL_MIX_MAXVOLUME/8)
    31. info.Start += int(len1)
    32. return 0
    33. }
    34. var ch = make(chan struct{}, 1)
    35. func main() {
    36. sdlcommon.SetSDL2Path("SDL2.dll")
    37. var spec sdl.SDL_AudioSpec
    38. sdl.SDL_Init(sdl.SDL_INIT_AUDIO)
    39. spec.Freq = 44100
    40. spec.Format = sdl.AUDIO_S16SYS // 采样点格式
    41. spec.Channels = 2 // 2通道
    42. spec.Silence = 0
    43. spec.Userdata = uintptr(0)
    44. spec.Samples = 1024 // 23.2ms -> 46.4ms 每次读取的采样数量,多久产生一次回调和 samples
    45. spec.Callback = syscall.NewCallback(fill_audio_pcm) // 回调函数
    46. fileData, err := ioutil.ReadFile("44100_16bit_2ch.pcm")
    47. if err != nil {
    48. fmt.Println("读取文件失败", err)
    49. return
    50. }
    51. info := new(Info)
    52. info.Data = fileData
    53. info.Len = len(fileData)
    54. spec.Userdata = uintptr(unsafe.Pointer(info))
    55. if sdl.SDL_OpenAudio(&spec, nil) != 0 {
    56. fmt.Println("打开音频设备失败")
    57. return
    58. }
    59. sdl.SDL_PauseAudio(0)
    60. <-ch
    61. fmt.Println("关闭")
    62. sdl.SDL_CloseAudio()
    63. sdl.SDL_Quit()
    64. }
    65. type Info struct {
    66. Data []byte
    67. Len int
    68. Start int
    69. isStop bool
    70. }

    执行结果如下:
    golang调用sdl2,播放pcm音频,报错signal arrived during external code execution。 - 图1