flac: add constant encoding of samples

This commit is contained in:
mewmew 2018-08-20 04:24:38 +09:00
parent 3e3f4b5fcf
commit a17e4ae49e
2 changed files with 51 additions and 19 deletions

View file

@ -100,23 +100,14 @@ func wav2flac(wavPath string, force bool) error {
}
subframes := make([]*frame.Subframe, nchannels)
subHdr := frame.SubHeader{
// Specifies the prediction method used to encode the audio sample of the
// subframe.
Pred: frame.PredVerbatim,
// Prediction order used by fixed and FIR linear prediction decoding.
Order: 0,
// Wasted bits-per-sample.
Wasted: 0,
}
for i := range subframes {
subframe := &frame.Subframe{
SubHeader: subHdr,
Samples: make([]int32, nsamplesPerChannel),
Samples: make([]int32, nsamplesPerChannel),
}
subframes[i] = subframe
}
for j := 0; !dec.EOF(); j++ {
for frameNum := 0; !dec.EOF(); frameNum++ {
fmt.Println("frame number:", frameNum)
// Decode WAV samples.
n, err := dec.PCMBuffer(buf)
if err != nil {
@ -126,6 +117,16 @@ func wav2flac(wavPath string, force bool) error {
break
}
for _, subframe := range subframes {
subHdr := frame.SubHeader{
// Specifies the prediction method used to encode the audio sample of the
// subframe.
Pred: frame.PredVerbatim,
// Prediction order used by fixed and FIR linear prediction decoding.
Order: 0,
// Wasted bits-per-sample.
Wasted: 0,
}
subframe.SubHeader = subHdr
subframe.NSamples = n / nchannels
subframe.Samples = subframe.Samples[:subframe.NSamples]
}
@ -133,7 +134,21 @@ func wav2flac(wavPath string, force bool) error {
subframe := subframes[i%nchannels]
subframe.Samples[i/nchannels] = int32(sample)
}
fmt.Println("j:", j)
// Check if the subframe may be encoded as constant; when all samples are
// the same.
for _, subframe := range subframes {
sample := subframe.Samples[0]
constant := true
for _, s := range subframe.Samples[1:] {
if sample != s {
constant = false
}
}
if constant {
fmt.Println("constant method")
subframe.SubHeader.Pred = frame.PredConstant
}
}
// Encode FLAC frame.
channels, err := getChannels(nchannels)

View file

@ -18,20 +18,20 @@ func encodeSubframe(bw bitio.Writer, hdr frame.Header, subframe *frame.Subframe)
// Encode audio samples.
switch subframe.Pred {
//case frame.PredConstant:
// if err := encodeConstantSamples(bw, samples); err != nil {
// return errutil.Err(err)
// }
case frame.PredConstant:
if err := encodeConstantSamples(bw, hdr.BitsPerSample, subframe.Samples); err != nil {
return errutil.Err(err)
}
case frame.PredVerbatim:
if err := encodeVerbatimSamples(bw, hdr, subframe.Samples); err != nil {
return errutil.Err(err)
}
//case frame.PredFixed:
// if err := encodeFixedSamples(bw, samples, subframe.Order); err != nil {
// if err := encodeFixedSamples(bw, hdr, subframe.Samples, subframe.Order); err != nil {
// return errutil.Err(err)
// }
//case frame.PredFIR:
// if err := encodeFIRSamples(bw, samples, subframe.Order); err != nil {
// if err := encodeFIRSamples(bw, hdr, subframe.Samples, subframe.Order); err != nil {
// return errutil.Err(err)
// }
default:
@ -92,6 +92,23 @@ func encodeSubframeHeader(bw bitio.Writer, hdr frame.SubHeader) error {
return nil
}
// --- [ Constant samples ] ----------------------------------------------------
// encodeConstantSamples stores the given constant sample, writing to bw.
func encodeConstantSamples(bw bitio.Writer, bps byte, samples []int32) error {
sample := samples[0]
for _, s := range samples[1:] {
if sample != s {
return errutil.Newf("constant sample mismatch; expected %v, got %v", sample, s)
}
}
// Unencoded constant value of the subblock, n = frame's bits-per-sample.
if err := bw.WriteBits(uint64(sample), bps); err != nil {
return errutil.Err(err)
}
return nil
}
// --- [ Verbatim samples ] ----------------------------------------------------
// encodeVerbatimSamples stores the given samples verbatim (uncompressed),