package main // typedef unsigned char Uint8; // void AudioCallback(void *userdata, Uint8 *stream, int len); import "C" import ( "io/ioutil" "log" "net/http" "reflect" "unsafe" "github.com/veandco/go-sdl2/sdl" ) const ( sampleHz = 48000 ) var ( audioData []byte ) //export AudioCallback func AudioCallback(userdata unsafe.Pointer, stream *C.Uint8, length C.int) { n := int(length) hdr := reflect.SliceHeader{Data: uintptr(unsafe.Pointer(stream)), Len: n, Cap: n} buf := *(*[]C.Uint8)(unsafe.Pointer(&hdr)) if len(audioData) == 0 { for i := 0; i < n; i++ { buf[i] = 0 } } else { for i := 0; i < n; i++ { if i >= len(audioData) { break } buf[i] = C.Uint8(audioData[i]) } if n <= len(audioData) { // Remove processed audio data audioData = audioData[n:] } else { // Clear audio data audioData = audioData[len(audioData):] } } } // Handle audio data that is sent through HTTP // Must be stereo unsigned 8-bit audio data at 48000Hz to play correctly func audioHandler(w http.ResponseWriter, r *http.Request) { data, err := ioutil.ReadAll(r.Body) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } audioData = append(audioData, data...) w.WriteHeader(http.StatusOK) } func main() { if err := sdl.Init(sdl.INIT_AUDIO); err != nil { log.Println(err) return } defer sdl.Quit() spec := &sdl.AudioSpec{ Freq: sampleHz, Format: sdl.AUDIO_U8, Channels: 2, Samples: sampleHz, Callback: sdl.AudioCallback(C.AudioCallback), } if err := sdl.OpenAudio(spec, nil); err != nil { log.Println(err) return } defer sdl.CloseAudio() sdl.PauseAudio(false) http.HandleFunc("/audio", audioHandler) log.Fatal(http.ListenAndServe(":8080", nil)) }