diff options
author | Christian Pointner <equinox@helsinki.at> | 2016-07-13 20:43:20 (GMT) |
---|---|---|
committer | Christian Pointner <equinox@helsinki.at> | 2016-07-13 20:43:20 (GMT) |
commit | 49b85d32a9c5a56191fff6ab554d1d748fbf9baf (patch) | |
tree | 6d5b9345bfc5c0f19479ef4f8537c17e8249b6c8 | |
parent | 384aa393acd021eb2a76816b3cc9bad35cd49ba7 (diff) |
implemented actual normalizer
-rw-r--r-- | rhimport/normalizer.go | 74 |
1 files changed, 71 insertions, 3 deletions
diff --git a/rhimport/normalizer.go b/rhimport/normalizer.go index 15f71ed..d99984c 100644 --- a/rhimport/normalizer.go +++ b/rhimport/normalizer.go @@ -25,12 +25,72 @@ package rhimport import ( + "fmt" + "io" "os" + "os/exec" + "path" + "path/filepath" + "strings" ) +type ffmpegResult struct { + output string + err error +} + +func runNormalizer(ctx *Context, src *os.File, size int64) (err error) { + if ctx.DeleteSourceFile { + defer os.Remove(src.Name()) + } + + basepath, filename := filepath.Split(src.Name()) + ext := filepath.Ext(filename) + destName := strings.TrimSuffix(filename, ext) + "_normalized.flac" + rhl.Printf("NormalizeFile: '%s' -> '%s', using gain = %.2f dB", filename, destName, ctx.LoudnessCorr) + + ctx.SourceFile = basepath + destName + + ffmpeg := exec.Command("ffmpeg", "-loglevel", "warning", "-i", "-", "-filter:a", fmt.Sprintf("volume=%fdB", ctx.LoudnessCorr), "-map_metadata", "0", "-f", "flac", ctx.SourceFile) + var ffstdin io.WriteCloser + if ffstdin, err = ffmpeg.StdinPipe(); err != nil { + return + } + + ffresult := make(chan ffmpegResult) + go func() { + output, err := ffmpeg.CombinedOutput() + ffresult <- ffmpegResult{strings.TrimSpace(string(output)), err} + }() + + var written int64 + for { + var w int64 + w, err = io.CopyN(ffstdin, src, 512*1024) + if err != nil { + break + } + written += w + if ctx.ProgressCallBack != nil { + if keep := ctx.ProgressCallBack(2, "normalizing", float64(written), float64(size), ctx.ProgressCallBackData); !keep { + ctx.ProgressCallBack = nil + } + } + } + ffstdin.Close() + res := <-ffresult + if res.err != nil { + return fmt.Errorf("normalizer exited with error: %q, ffmpeg output: %s", res.err, res.output) + } + if err != nil && err != io.EOF { + return + } + return nil +} + func NormalizeFile(ctx *Context) (err error) { if ctx.LoudnessCorr == 0.0 { - rhdl.Println("NormalizeFile: skipping normalization since the gain = 0.0dB") + rhl.Println("NormalizeFile: skipping normalization since the gain = 0.0dB") if ctx.ProgressCallBack != nil { if keep := ctx.ProgressCallBack(2, "normalizing", 1.0, 1.0, ctx.ProgressCallBackData); !keep { ctx.ProgressCallBack = nil @@ -39,7 +99,6 @@ func NormalizeFile(ctx *Context) (err error) { return } - rhl.Printf("NormalizeFile: using gain = %.2f dB", ctx.LoudnessCorr) ctx.NormalizationLevel = 0 // don't do double normalization var src *os.File @@ -61,7 +120,16 @@ func NormalizeFile(ctx *Context) (err error) { } } - // TODO: call ffmpeg + if err = runNormalizer(ctx, src, size); err != nil { + rhl.Println("NormalizeFile error:", err) + if ctx.DeleteSourceFile { + os.Remove(ctx.SourceFile) + if ctx.DeleteSourceDir { + os.Remove(path.Dir(ctx.SourceFile)) + } + } + return + } if ctx.ProgressCallBack != nil { if keep := ctx.ProgressCallBack(2, "normalizing", float64(size), float64(size), ctx.ProgressCallBackData); !keep { |