go-ebur128/libebur128.go

201 lines
5.6 KiB
Go

package libebur128
/*
#cgo pkg-config: libebur128
#include <ebur128.h>
*/
import "C"
import (
"fmt"
"time"
)
type Ebur128Mode int
const (
LoudnessMomentary Ebur128Mode = C.EBUR128_MODE_M
LoudnessShortTerm Ebur128Mode = C.EBUR128_MODE_S
LoudnessGlobalMomentary Ebur128Mode = C.EBUR128_MODE_I
LoudnessRange Ebur128Mode = C.EBUR128_MODE_LRA
SamplePeak Ebur128Mode = C.EBUR128_MODE_SAMPLE_PEAK
TruePeak Ebur128Mode = C.EBUR128_MODE_TRUE_PEAK
Histogram Ebur128Mode = C.EBUR128_MODE_HISTOGRAM
)
func GetVersion() (major, minor, patch int) {
var i, j, k C.int
C.ebur128_get_version(&i, &j, &k)
return int(i), int(j), int(k)
}
type State struct {
p *C.ebur128_state
channels int
}
func NewState(channels, sampleRate int, mode Ebur128Mode) *State {
p := C.ebur128_init(C.uint(channels), C.ulong(sampleRate), C.int(mode))
if p == nil {
return nil
}
return &State{
p: p,
channels: channels,
}
}
//GetSamplePeak Get maximum sample peak from all frames that have been processed.
func (s *State) GetSamplePeak() (out []float64, err error) {
var j C.double
for i := 0; i < s.channels; i++ {
ret := C.ebur128_sample_peak(s.p, C.uint(i), &j)
if ret != C.EBUR128_SUCCESS {
return nil, fmt.Errorf("error calculating peak: %d", ret)
}
out = append(out, float64(j))
}
return
}
//GetPreviousSamplePeak Get maximum sample peak from the last call to Add*()
func (s *State) GetPreviousSamplePeak() (out []float64, err error) {
var j C.double
for i := 0; i < s.channels; i++ {
ret := C.ebur128_prev_sample_peak(s.p, C.uint(i), &j)
if ret != C.EBUR128_SUCCESS {
return nil, fmt.Errorf("error calculating peak: %d", ret)
}
out = append(out, float64(j))
}
return
}
//GetTruePeak Get maximum true peak from all frames that have been processed.
func (s *State) GetTruePeak() (out []float64, err error) {
var j C.double
for i := 0; i < s.channels; i++ {
ret := C.ebur128_true_peak(s.p, C.uint(i), &j)
if ret != C.EBUR128_SUCCESS {
return nil, fmt.Errorf("error calculating peak: %d", ret)
}
out = append(out, float64(j))
}
return
}
//GetPreviousTruePeak Get maximum true peak from the last call to Add*()
func (s *State) GetPreviousTruePeak() (out []float64, err error) {
var j C.double
for i := 0; i < s.channels; i++ {
ret := C.ebur128_prev_true_peak(s.p, C.uint(i), &j)
if ret != C.EBUR128_SUCCESS {
return nil, fmt.Errorf("error calculating peak: %d", ret)
}
out = append(out, float64(j))
}
return
}
//GetLoudnessGlobal Get global integrated loudness in LUFS.
func (s *State) GetLoudnessGlobal() (out float64, err error) {
var i C.double
ret := C.ebur128_loudness_global(s.p, &i)
if ret != C.EBUR128_SUCCESS {
return float64(i), fmt.Errorf("error calculating loudness: %d", ret)
}
return float64(i), nil
}
//GetLoudnessGlobalMultiple Get global integrated loudness in LUFS across multiple instances.
func GetLoudnessGlobalMultiple(states []*State) (out float64, err error) {
slice := make([]*C.ebur128_state, len(states))
for i, s := range states {
slice[i] = s.p
}
var i C.double
ret := C.ebur128_loudness_global_multiple(&slice[0], C.ulong(len(slice)), &i)
if ret != C.EBUR128_SUCCESS {
return float64(i), fmt.Errorf("error calculating loudness: %d", ret)
}
return float64(i), nil
}
//SetMaxWindow Set the maximum window duration.
func (s *State) SetMaxWindow(window time.Duration) (err error) {
ret := C.ebur128_set_max_window(s.p, C.ulong(window.Milliseconds()))
if ret != C.EBUR128_SUCCESS {
return fmt.Errorf("error calculating loudness: %d", ret)
}
return nil
}
//GetLoudnessWindow Get loudness of the specified window in LUFS.
func (s *State) GetLoudnessWindow(window time.Duration) (out float64, err error) {
var i C.double
ret := C.ebur128_loudness_window(s.p, C.ulong(window.Milliseconds()), &i)
if ret != C.EBUR128_SUCCESS {
return float64(i), fmt.Errorf("error calculating loudness: %d", ret)
}
return float64(i), nil
}
//GetLoudnessMomentary Get momentary loudness (last 400ms) in LUFS.
func (s *State) GetLoudnessMomentary() (out float64, err error) {
var i C.double
ret := C.ebur128_loudness_momentary(s.p, &i)
if ret != C.EBUR128_SUCCESS {
return float64(i), fmt.Errorf("error calculating loudness: %d", ret)
}
return float64(i), nil
}
//GetLoudnessShortTerm Get short-term loudness (last 3s) in LUFS.
func (s *State) GetLoudnessShortTerm() (out float64, err error) {
var i C.double
ret := C.ebur128_loudness_shortterm(s.p, &i)
if ret != C.EBUR128_SUCCESS {
return float64(i), fmt.Errorf("error calculating loudness: %d", ret)
}
return float64(i), nil
}
func (s *State) AddFloat(src []float32) error {
ret := C.ebur128_add_frames_float(s.p, (*C.float)(&src[0]), C.size_t(len(src)/s.channels))
if ret != C.EBUR128_SUCCESS {
return fmt.Errorf("error adding frames: %d", ret)
}
return nil
}
func (s *State) AddDouble(src []float64) error {
ret := C.ebur128_add_frames_double(s.p, (*C.double)(&src[0]), C.size_t(len(src)/s.channels))
if ret != C.EBUR128_SUCCESS {
return fmt.Errorf("error adding frames: %d", ret)
}
return nil
}
func (s *State) AddShort(src []int16) error {
ret := C.ebur128_add_frames_short(s.p, (*C.short)(&src[0]), C.size_t(len(src)/s.channels))
if ret != C.EBUR128_SUCCESS {
return fmt.Errorf("error adding frames: %d", ret)
}
return nil
}
func (s *State) AddInt(src []int32) error {
ret := C.ebur128_add_frames_int(s.p, (*C.int)(&src[0]), C.size_t(len(src)/s.channels))
if ret != C.EBUR128_SUCCESS {
return fmt.Errorf("error adding frames: %d", ret)
}
return nil
}
func (s *State) Close() {
if s.p != nil {
C.ebur128_destroy(&s.p)
s.p = nil
}
}