package flac import ( "bytes" "errors" "io" "github.com/go-audio/audio" "github.com/go-audio/wav" "github.com/mewkiz/flac" ) const wavAudioFormat = 1 type WriterSeeker struct { buf []byte pos int } func (ws *WriterSeeker) Bytes() []byte { return ws.buf } func (m *WriterSeeker) Write(p []byte) (n int, err error) { minCap := m.pos + len(p) if minCap > cap(m.buf) { // Make sure buf has enough capacity: buf2 := make([]byte, len(m.buf), minCap+len(p)) // add some extra copy(buf2, m.buf) m.buf = buf2 } if minCap > len(m.buf) { m.buf = m.buf[:minCap] } copy(m.buf[m.pos:], p) m.pos += len(p) return len(p), nil } func (m *WriterSeeker) Seek(offset int64, whence int) (int64, error) { newPos, offs := 0, int(offset) switch whence { case io.SeekStart: newPos = offs case io.SeekCurrent: newPos = m.pos + offs case io.SeekEnd: newPos = len(m.buf) + offs } if newPos < 0 { return 0, errors.New("negative result pos") } m.pos = newPos return int64(newPos), nil } // Decode takes a slice of flac and decodes to wav func Decode(buf []byte) ([]byte, error) { r := bytes.NewReader(buf) stream, err := flac.Parse(r) if err != nil { return nil, errors.New("Could not parse FLAC") } ws := &WriterSeeker{} enc := wav.NewEncoder(ws, int(stream.Info.SampleRate), int(stream.Info.BitsPerSample), int(stream.Info.NChannels), wavAudioFormat) defer enc.Close() var data []int for { // Decode FLAC audio samples. frame, err := stream.ParseNext() if err != nil { if err == io.EOF { break } return nil, err } // Encode WAV audio samples. data = data[:0] for i := 0; i < frame.Subframes[0].NSamples; i++ { for _, subframe := range frame.Subframes { data = append(data, int(subframe.Samples[i])) } } buf := &audio.IntBuffer{ Format: &audio.Format{ NumChannels: int(stream.Info.NChannels), SampleRate: int(stream.Info.SampleRate), }, Data: data, SourceBitDepth: int(stream.Info.BitsPerSample), } if err := enc.Write(buf); err != nil { return nil, err } } return ws.Bytes(), nil }