116 lines
2.4 KiB
Go
116 lines
2.4 KiB
Go
//go:build cgo
|
|
|
|
package replaygain
|
|
|
|
import (
|
|
"errors"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio"
|
|
libebur128 "git.gammaspectra.live/S.O.N.G/go-ebur128"
|
|
"sync"
|
|
)
|
|
|
|
const referenceLevel = -18.0
|
|
|
|
//GetTrackReplayGain calculates track ReplayGain 2.0
|
|
func GetTrackReplayGain(source audio.Source) (gain, peak float64, err error) {
|
|
state := libebur128.NewState(source.Channels, source.SampleRate, libebur128.LoudnessGlobalMomentary|libebur128.SamplePeak)
|
|
if state == nil {
|
|
err = errors.New("could not initialize state")
|
|
return
|
|
}
|
|
defer state.Close()
|
|
|
|
for block := range source.Blocks {
|
|
if err = state.AddFloat(block); err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
var loudness float64
|
|
var peakSlice []float64
|
|
|
|
if loudness, err = state.GetLoudnessGlobal(); err != nil {
|
|
return
|
|
}
|
|
if peakSlice, err = state.GetSamplePeak(); err != nil {
|
|
return
|
|
}
|
|
|
|
for _, p := range peakSlice {
|
|
if p > peak {
|
|
peak = p
|
|
}
|
|
}
|
|
|
|
gain = referenceLevel - loudness
|
|
|
|
return
|
|
}
|
|
|
|
//GetAlbumReplayGain calculates album and tracks ReplayGain 2.0
|
|
func GetAlbumReplayGain(sources []audio.Source) (albumGain, albumPeak float64, trackGains []float64, trackPeaks []float64, err error) {
|
|
var states []*libebur128.State
|
|
var wg sync.WaitGroup
|
|
defer func() {
|
|
wg.Wait()
|
|
for _, state := range states {
|
|
state.Close()
|
|
}
|
|
}()
|
|
|
|
for _, source := range sources {
|
|
state := libebur128.NewState(source.Channels, source.SampleRate, libebur128.LoudnessGlobalMomentary|libebur128.SamplePeak)
|
|
if state == nil {
|
|
err = errors.New("could not initialize state")
|
|
return
|
|
}
|
|
states = append(states, state)
|
|
|
|
wg.Add(1)
|
|
go func(source audio.Source) {
|
|
defer wg.Done()
|
|
for block := range source.Blocks {
|
|
if err = state.AddFloat(block); err != nil {
|
|
return
|
|
}
|
|
}
|
|
}(source)
|
|
}
|
|
|
|
wg.Wait()
|
|
|
|
var albumLoudness float64
|
|
var peakSlice []float64
|
|
var trackLoudness float64
|
|
|
|
if albumLoudness, err = libebur128.GetLoudnessGlobalMultiple(states); err != nil {
|
|
return
|
|
}
|
|
for _, state := range states {
|
|
if trackLoudness, err = state.GetLoudnessGlobal(); err != nil {
|
|
return
|
|
}
|
|
if peakSlice, err = state.GetSamplePeak(); err != nil {
|
|
return
|
|
}
|
|
|
|
var tPeak float64
|
|
|
|
for _, p := range peakSlice {
|
|
if p > albumPeak {
|
|
albumPeak = p
|
|
}
|
|
if p > tPeak {
|
|
tPeak = p
|
|
}
|
|
}
|
|
|
|
trackGains = append(trackGains, referenceLevel-trackLoudness)
|
|
trackPeaks = append(trackPeaks, tPeak)
|
|
}
|
|
|
|
albumGain = referenceLevel - albumLoudness
|
|
|
|
return
|
|
}
|