Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
adammfrank opened this issue Oct 13, 2019 · 5 comments

Comments

@adammfrank
Copy link

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?

@mattetti
Copy link
Member

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
Copy link
Member

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

@AlmogBaku
Copy link

did you manage to make them work together?

@dyc3
Copy link

dyc3 commented Nov 8, 2020

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
Copy link

dyc3 commented Nov 8, 2020

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))
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants