go-sdl2 icon indicating copy to clipboard operation
go-sdl2 copied to clipboard

How to play 32 bit floating point audio

Open svenskmand opened this issue 1 year ago • 1 comments

Go version: 1.20.4 Go-SDL2 version: v0.4.35 SDL2 version: 2.0.20+dfsg-2build1 OS: Ubuntu 22.04 Architecture: 64 Bit

I am trying to follow the example on how to play audio, and the example works fine, but I would really want to use another format than 8 bit sound. How do I use 32 bit floating point?:

package main

// void SineWave(void *userdata, float *stream, int len);
import "C"
import (
	"log"
	"math"
	"reflect"
	"unsafe"

	"github.com/veandco/go-sdl2/sdl"
)

const (
	toneHz   = 220
	sampleHz = 48000
	dPhase   = 2 * math.Pi * toneHz / sampleHz
)

//export SineWave
func SineWave(userdata unsafe.Pointer, stream *C.float, length C.int) {
	n := int(length)
	hdr := reflect.SliceHeader{Data: uintptr(unsafe.Pointer(stream)), Len: n, Cap: n}
	buf := *(*[]C.float)(unsafe.Pointer(&hdr))

	var phase float64
	for i := 0; i < n; i += 2 {
		phase += dPhase
		sample := C.float((math.Sin(phase) + 0.999999) * 128)
		buf[i] = sample
		buf[i+1] = sample
	}
}

func playTone() {
	if err := sdl.Init(sdl.INIT_AUDIO); err != nil {
		log.Println(err)
		return
	}
	defer sdl.Quit()

	spec := &sdl.AudioSpec{
		Freq:     sampleHz,
		Format:   sdl.AUDIO_F32SYS,
		Channels: 2,
		Samples:  sampleHz,
		Callback: sdl.AudioCallback(C.SineWave),
	}
	if err := sdl.OpenAudio(spec, nil); err != nil {
		log.Println(err)
		return
	}
	sdl.PauseAudio(false)
	sdl.Delay(1000) // play audio for long enough to understand whether it works
	sdl.CloseAudio()
}

func main() {
	// foo := 2.12312
	// var bar C.float = 2.123
	// fmt.Println(foo, bar)
	playTone()
}

I tried simply changing all references to the type C.Uint8 with C.float as this should be the 32 bit floating point number in C, and then i changed the Format field in the AudioSpec to sdl.AUDIO_F32SYS, but unfortunately it does not work, then I just get this segfault when running the program:

unexpected fault address 0x7f9cc205b000
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x2 addr=0x7f9cc205b000 pc=0x4a6015]

goroutine 17 [running, locked to thread]:
runtime.throw({0x4cdc90?, 0x0?})
        /snap/go/current/src/runtime/panic.go:1047 +0x5d fp=0xc000064d58 sp=0xc000064d28 pc=0x447c5d
runtime.sigpanic()
        /snap/go/current/src/runtime/signal_unix.go:851 +0x28a fp=0xc000064db8 sp=0xc000064d58 pc=0x45c26a
main.SineWave(0xc00002a0c0?, 0x0?, 0x1?)
        /home/kejlberg/Documents/dawl/main.go:30 +0xb5 fp=0xc000064e10 sp=0xc000064db8 pc=0x4a6015
_cgoexp_9411f897d225_SineWave(0x4d6928?)
        _cgo_gotypes.go:48 +0x26 fp=0xc000064e38 sp=0xc000064e10 pc=0x4a6286
runtime.cgocallbackg1(0x4a6260, 0x0?, 0x0)
        /snap/go/current/src/runtime/cgocall.go:315 +0x2b1 fp=0xc000064f00 sp=0xc000064e38 pc=0x419911
runtime.cgocallbackg(0x0?, 0x0?, 0x0?)
        /snap/go/current/src/runtime/cgocall.go:234 +0x109 fp=0xc000064f90 sp=0xc000064f00 pc=0x4195c9
runtime.cgocallbackg(0x4a6260, 0x7f9cc1fccc60, 0x0)
        <autogenerated>:1 +0x2f fp=0xc000064fb8 sp=0xc000064f90 pc=0x47724f
runtime.cgocallback(0x0, 0x0, 0x0)
        /snap/go/current/src/runtime/asm_amd64.s:998 +0xb4 fp=0xc000064fe0 sp=0xc000064fb8 pc=0x474b54
runtime.goexit()
        /snap/go/current/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000064fe8 sp=0xc000064fe0 pc=0x474d81

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x4acc80, 0xc000065f20)
        /snap/go/current/src/runtime/cgocall.go:157 +0x5c fp=0xc000065ef8 sp=0xc000065ec0 pc=0x41941c
github.com/veandco/go-sdl2/sdl._Cfunc_SDL_Delay(0x3e8)
        _cgo_gotypes.go:3009 +0x45 fp=0xc000065f20 sp=0xc000065ef8 pc=0x4a2d25
github.com/veandco/go-sdl2/sdl.Delay(...)
        /home/kejlberg/GOPATH/pkg/mod/github.com/veandco/[email protected]/sdl/timer.go:54
main.playTone()
        /home/kejlberg/Documents/dawl/main.go:54 +0x13f fp=0xc000065f70 sp=0xc000065f20 pc=0x4a61bf
main.main()
        /home/kejlberg/Documents/dawl/main.go:62 +0x17 fp=0xc000065f80 sp=0xc000065f70 pc=0x4a6237
runtime.main()
        /snap/go/current/src/runtime/proc.go:250 +0x207 fp=0xc000065fe0 sp=0xc000065f80 pc=0x44a547
runtime.goexit()
        /snap/go/current/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000065fe8 sp=0xc000065fe0 pc=0x474d81

goroutine 2 [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /snap/go/current/src/runtime/proc.go:381 +0xd6 fp=0xc000052fb0 sp=0xc000052f90 pc=0x44a976
runtime.goparkunlock(...)
        /snap/go/current/src/runtime/proc.go:387
runtime.forcegchelper()
        /snap/go/current/src/runtime/proc.go:305 +0xb0 fp=0xc000052fe0 sp=0xc000052fb0 pc=0x44a7b0
runtime.goexit()
        /snap/go/current/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000052fe8 sp=0xc000052fe0 pc=0x474d81
created by runtime.init.6
        /snap/go/current/src/runtime/proc.go:293 +0x25

goroutine 3 [GC sweep wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /snap/go/current/src/runtime/proc.go:381 +0xd6 fp=0xc000053780 sp=0xc000053760 pc=0x44a976
runtime.goparkunlock(...)
        /snap/go/current/src/runtime/proc.go:387
runtime.bgsweep(0x0?)
        /snap/go/current/src/runtime/mgcsweep.go:278 +0x8e fp=0xc0000537c8 sp=0xc000053780 pc=0x4376ce
runtime.gcenable.func1()
        /snap/go/current/src/runtime/mgc.go:178 +0x26 fp=0xc0000537e0 sp=0xc0000537c8 pc=0x42cb86
runtime.goexit()
        /snap/go/current/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc0000537e8 sp=0xc0000537e0 pc=0x474d81
created by runtime.gcenable
        /snap/go/current/src/runtime/mgc.go:178 +0x6b

goroutine 4 [GC scavenge wait]:
runtime.gopark(0xc00001c0e0?, 0x4ec2e8?, 0x1?, 0x0?, 0x0?)
        /snap/go/current/src/runtime/proc.go:381 +0xd6 fp=0xc000053f70 sp=0xc000053f50 pc=0x44a976
runtime.goparkunlock(...)
        /snap/go/current/src/runtime/proc.go:387
runtime.(*scavengerState).park(0x579380)
        /snap/go/current/src/runtime/mgcscavenge.go:400 +0x53 fp=0xc000053fa0 sp=0xc000053f70 pc=0x4355f3
runtime.bgscavenge(0x0?)
        /snap/go/current/src/runtime/mgcscavenge.go:628 +0x45 fp=0xc000053fc8 sp=0xc000053fa0 pc=0x435bc5
runtime.gcenable.func2()
        /snap/go/current/src/runtime/mgc.go:179 +0x26 fp=0xc000053fe0 sp=0xc000053fc8 pc=0x42cb26
runtime.goexit()
        /snap/go/current/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000053fe8 sp=0xc000053fe0 pc=0x474d81
created by runtime.gcenable
        /snap/go/current/src/runtime/mgc.go:179 +0xaa

goroutine 5 [finalizer wait]:
runtime.gopark(0x1a0?, 0x5797c0?, 0x60?, 0x78?, 0xc000052770?)
        /snap/go/current/src/runtime/proc.go:381 +0xd6 fp=0xc000052628 sp=0xc000052608 pc=0x44a976
runtime.runfinq()
        /snap/go/current/src/runtime/mfinal.go:193 +0x107 fp=0xc0000527e0 sp=0xc000052628 pc=0x42bbc7
runtime.goexit()
        /snap/go/current/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc0000527e8 sp=0xc0000527e0 pc=0x474d81
created by runtime.createfing
        /snap/go/current/src/runtime/mfinal.go:163 +0x45

I have not work with Cgo before so I might be missing something completely trivial. Any help here would be awesome :)

svenskmand avatar May 11 '23 20:05 svenskmand