wav icon indicating copy to clipboard operation
wav copied to clipboard

What am I doing wrong trying to encode a stream from Portaudio as a .wav?

Open adammfrank opened this issue 6 years ago • 5 comments

func recordWav() string {

	audioFileName := "temp.wav" //os.Args[1]

	fmt.Println("Recording. Press ESC to quit.")

	waveFile, err := os.Create(audioFileName)
	chk(err)

	// www.people.csail.mit.edu/hubert/pyaudio/  - under the Record tab
	inputChannels := 1
	outputChannels := 0
	sampleRate := 44100

	// init PortAudio

	portaudio.Initialize()
	//defer portaudio.Terminate()

	encoder := wav.NewEncoder(waveFile, sampleRate, 16, 1, 1)

	format := &audio.Format{
		NumChannels: 1,
		SampleRate:  44100,
	}

	data := make([]int, 4096)

	buf := &audio.IntBuffer{Data: data, Format: format, SourceBitDepth: 16}
	buf32 := buf.AsFloat32Buffer()

	stream, err := portaudio.OpenDefaultStream(inputChannels, outputChannels, float64(sampleRate), 64, buf32.Data)
	chk(err)

	chk(stream.Start())

	for start := time.Now(); time.Since(start) < time.Second*7; {
		chk(stream.Read())

		log.Println("Recording...")

		// write to wave file
		err := encoder.Write(buf)
		chk(err)
	}

	stream.Close()
	portaudio.Terminate()

	return audioFileName
}

The only array type that portaudio and audio.IntBuffer both support is float32[]. When I run this code, nothing gets recorded. The file is silent. I don't know if this is the right place for this, but what the heck am I doing wrong? Is it something to do with converting to float32?

adammfrank avatar Oct 13 '19 15:10 adammfrank

I'm not in front of my computer but if I recall correctly, it doesn't seem that you are using the port audio API properly. Your buffer isn't 7s long and I believe port audio has some sort of callback mechanism when the buffer is ready to be dumped

mattetti avatar Oct 14 '19 14:10 mattetti

Also you need to close the encoder to add the right headers to the file

mattetti avatar Oct 14 '19 14:10 mattetti

did you manage to make them work together?

AlmogBaku avatar Mar 25 '20 01:03 AlmogBaku

This code successfully saves a wav file, but the resulting file has weird clicking in the audio.

NOTE: s.Audio is []int32

	audioFile, err := os.Create(path.Join(dir, "audio.wav"))
	if err != nil {
		return err
	}
	defer audioFile.Close()

	e := wav.NewEncoder(audioFile, sampleRate, 32, 1, 1)
	defer e.Close()
	buf := audio.IntBuffer{
		Format:         audio.FormatMono44100,
		SourceBitDepth: 32,
	}
	for _, sample := range s.Audio {
		buf.Data = append(buf.Data, int(sample))
	}
	err = e.Write(&buf)
	if err != nil {
		return err
	}

dyc3 avatar Nov 08 '20 17:11 dyc3

The problem I was having was that I wasn't waiting until there was enough audio to fill the buffer, and that was causing samples to get recorded twice.

for avail := 0; avail < len(in); avail, _ = stream.AvailableToRead() {
	time.Sleep(time.Second / sampleRate * time.Duration(len(in)-avail))
}

dyc3 avatar Nov 08 '20 19:11 dyc3