go-audio / wav

Battle tested Wav decoder/encoder
Apache License 2.0
300 stars 46 forks source link

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

Open adammfrank opened 4 years ago

adammfrank commented 4 years ago
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 commented 4 years ago

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 commented 4 years ago

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

AlmogBaku commented 4 years ago

did you manage to make them work together?

dyc3 commented 3 years ago

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 commented 3 years ago

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