当前位置:网站首页>golang調用sdl2,播放pcm音頻,報錯signal arrived during external code execution。

golang調用sdl2,播放pcm音頻,報錯signal arrived during external code execution。

2022-06-22 06:51:00 福大大架構師每日一題

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
}

執行結果如下:
在這裏插入圖片描述

原网站

版权声明
本文为[福大大架構師每日一題]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/173/202206220650367402.html