package flac import ( "bytes" "errors" "io" "github.com/go-audio/audio" "github.com/go-audio/wav" "github.com/mewkiz/flac" ) const wavAudioFormat = 1 type buffer struct { Buffer bytes.Buffer Index int64 } func (b *buffer) Bytes() []byte { return b.Buffer.Bytes() } func (b *buffer) Read(p []byte) (int, error) { n, err := bytes.NewBuffer(b.Buffer.Bytes()[b.Index:]).Read(p) if err == nil { if b.Index+int64(len(p)) < int64(b.Buffer.Len()) { b.Index += int64(len(p)) } else { b.Index = int64(b.Buffer.Len()) } } return n, err } func (b *buffer) Write(p []byte) (int, error) { n, err := b.Buffer.Write(p) if err == nil { b.Index = int64(b.Buffer.Len()) } return n, err } func (b *buffer) Seek(offset int64, whence int) (int64, error) { var err error var Index int64 = 0 switch whence { case 0: if offset >= int64(b.Buffer.Len()) || offset < 0 { err = errors.New("Invalid Offset.") } else { b.Index = offset Index = offset } default: err = errors.New("Unsupported Seek Method.") } return Index, err } // 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") } fb := &buffer{} enc := wav.NewEncoder(fb, 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 fb.Bytes(), nil }