Skip to content
This repository was archived by the owner on Feb 21, 2026. It is now read-only.
This repository was archived by the owner on Feb 21, 2026. It is now read-only.

Play sample loud and choppy #16

@brydavis

Description

@brydavis

Trying to use PortAudio to play... It's super loud and choppy.

package main

import (
	"flag"
	"fmt"
	"io"
	"os"

	"strings"

	"github.com/go-audio/audio"
	"github.com/go-audio/wav"
	"github.com/gordonklaus/portaudio"
)

var (
	flagInput  = flag.String("input", "/Users/brydavis/sounds/The Malinchak Show Episode 108.wav", "The file to convert")
	flagFormat = flag.String("format", "wav", "The format to convert to (wav or aiff)")
	flagOutput = flag.String("output", "out", "The output filename")
)

func main() {
	flag.Parse()
	if *flagInput == "" {
		fmt.Println("Provide an input file using the -input flag")
		os.Exit(1)
	}
	switch strings.ToLower(*flagFormat) {
	case "aiff", "aif":
		*flagFormat = "aiff"
	case "wave", "wav":
		*flagFormat = "wav"
	default:
		fmt.Println("Provide a valid -format flag")
		os.Exit(1)
	}
	f, err := os.Open(*flagInput)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	var buf *audio.IntBuffer

	wd := wav.NewDecoder(f)

	if !wd.WasPCMAccessed() {
		err := wd.FwdToPCM()
		if err != nil {
			panic(err)
		}
	}

	framePerBuffer := 2048

	buf = &audio.IntBuffer{Format: wd.Format(), Data: make([]int, framePerBuffer)}
	var n int
	var doneReading bool

	portaudio.Initialize()
	defer portaudio.Terminate()

	out := make([]float32, framePerBuffer)

	stream, err := portaudio.OpenDefaultStream(0, 2, 44100, framePerBuffer, &out)

	if err != nil {
		fmt.Printf("unable to open port audio stream for playback: %s\n", err.Error())
		os.Exit(1)
		return
	}

	defer stream.Close()

	if err := stream.Start(); err != nil {
		fmt.Printf("unable to open port audio stream for playback: %s\n", err.Error())
		os.Exit(1)
		return
	}

	defer stream.Stop()

	for err == nil {
		n, err = wd.PCMBuffer(buf)
		if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
			fmt.Println(err)
		}

		if n != len(buf.Data) {
			buf.Data = buf.Data[:n]
			doneReading = true
		}

		intToF32Copy(out, buf.Data)

		// write to the stream
		if err := stream.Write(); err != nil {
			fmt.Println(err)
		}

		if doneReading {
			break
		}
	}

}

// portaudio doesn't support float64 so we need to copy our data over to the
// destination buffer.
func intToF32Copy(dst []float32, src []int) {
	for i := range src {
		dst[i] = float32(src[i])
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions