Skip to content

Instantly share code, notes, and snippets.

@Luigi-Pizzolito
Created February 11, 2024 20:18
Show Gist options
  • Save Luigi-Pizzolito/4d8c5b97536b3059e6f93aac05f1449f to your computer and use it in GitHub Desktop.
Save Luigi-Pizzolito/4d8c5b97536b3059e6f93aac05f1449f to your computer and use it in GitHub Desktop.
Plays a raw wav file from stdin, mono, 16kHz.
package main
import (
"bytes"
"time"
"os"
"io/ioutil"
"github.com/ebitengine/oto/v3"
"github.com/youpy/go-wav"
)
func main() {
// Read the WAV file from stdin
rawBytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
panic("Failed to read WAV input: "+err.Error())
}
// Convert the pure bytes into a reader object that can be used with the mp3 decoder
// fileBytesReader := bytes.NewReader(fileBytes)
fileBytesReader := bytes.NewReader(rawBytes)
// Decode file
decodedWav := wav.NewReader(fileBytesReader)
// Prepare an Oto context (this will use your default audio device) that will
// play all our sounds. Its configuration can't be changed later.
op := &oto.NewContextOptions{}
// Usually 44100 or 48000. Other values might cause distortions in Oto
op.SampleRate = 16000
// Number of channels (aka locations) to play sounds from. Either 1 or 2.
// 1 is mono sound, and 2 is stereo (most speakers are stereo).
op.ChannelCount = 1
// Format of the source. go-mp3's format is signed 16bit integers.
op.Format = oto.FormatSignedInt16LE
// Remember that you should **not** create more than one context
otoCtx, readyChan, err := oto.NewContext(op)
if err != nil {
panic("oto.NewContext failed: " + err.Error())
}
// It might take a bit for the hardware audio devices to be ready, so we wait on the channel.
<-readyChan
// Create a new 'player' that will handle our sound. Paused by default.
player := otoCtx.NewPlayer(decodedWav)
// Play starts playing the sound and returns without waiting for it (Play() is async).
player.Play()
// We can wait for the sound to finish playing using something like this
for player.IsPlaying() {
time.Sleep(time.Millisecond)
}
time.Sleep(time.Millisecond*100)
// If you don't want the player/sound anymore simply close
err = player.Close()
if err != nil {
panic("player.Close failed: " + err.Error())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment