godub

package module
v0.1.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2020 License: MIT Imports: 13 Imported by: 0

README

godub

godub lets you manipulate audio in an easy and elegant way. It's ported from the excellent project pydub.

Why

There are some audio packages in the Go world, but we believe that pydub provides a better way to do stuff to audios. Therefore, here we have godub! However, due to limited time and personal ability, not all the features of pydub are supported.

Features

  • Load audio files, supports mp3/m4a/wav...
  • Export/convert audio with custom configs.
  • Slice an audio.
  • Concatenate two or more audios.
  • Repeat an audio.
  • Overlay with other audios.
  • Reverse an audio.
  • ...

Quickstart

Load

func main() {
	filePath := path.Join(dataDirectory(), "code-geass.mp3")
	segment, _ := godub.NewLoader().Load(filePath)
	fmt.Println(segment)

	buf, _ := ioutil.ReadAll()

	// Load from buffer, load also accepts `io.Reader` type.
	segment, _ = godub.NewLoader().Load(bytes.NewReader(buf))
	fmt.Println(segment)
}

Export

func main() {
	filePath := path.Join(dataDirectory(), "code-geass.mp3")
	segment, _ := godub.NewLoader().Load(filePath)

	// Export as a mp3 file.
	toFilePath := path.Join(dataDirectory(), "converted", "code-geass.mp3")
	err := godub.NewExporter(toFilePath).
		WithDstFormat("mp3").
		WithBitRate(128000).
		Export(segment)
	if err != nil {
		log.Fatal(err)
	}

	// Let's check it.
	segment, _ = godub.NewLoader().Load(toFilePath)
	fmt.Println(segment)
}

Convert

func main() {
	filePath := path.Join(dataDirectory(), "code-geass.mp3")
	toFilePath := path.Join(dataDirectory(), "converted", "code-geass.m4a")
	w, _ := os.Create(toFilePath)

	err := audio.NewConverter(w).
		WithBitRate(64000).
		WithDstFormat("m4a").
		Convert(filePath)
	if err != nil {
		log.Fatal(err)
	}

	segment, _ := godub.NewLoader().Load(toFilePath)
	fmt.Println(segment)
}

Slice

func slice() {
	filePath := path.Join(dataDirectory(), "code-geass.mp3")
	segment, _ := godub.NewLoader().Load(filePath)

	// Slice from 0 sec to 100 secs.
	slicedSegment, _ := segment.Slice(0, 100*time.Second)

	// Then export it as mp3 file.
	slicedPath := path.Join(dataDirectory(), "slice", "code-geass.mp3")
	godub.NewExporter(slicedPath).WithDstFormat("mp3").Export(slicedSegment)
}

Concatenate

func main() {
	filePath := path.Join(dataDirectory(), "code-geass.mp3")
	segment, _ := godub.NewLoader().Load(filePath)

	// Yep, you can append more than one segment.
	newSeg, err := segment.Append(segment, segment)
	if err != nil {
		log.Fatal(err)
	}

	// Save the newly created audio segment as mp3 file.
	newPth := path.Join(dataDirectory(), "append", "code-geass.mp3")
	godub.NewExporter(newPth).WithDstFormat("mp3").WithBitRate(audio.MP3BitRatePerfect).Export(newSeg)
}

Overlay

func main() {
	segment, _ := godub.NewLoader().Load(path.Join(dataDirectory(), "code-geass.mp3"))
	otherSegment, _ := godub.NewLoader().Load(path.Join(dataDirectory(), "ring.mp3"))

	overlaidSeg, err := segment.Overlay(otherSegment, &godub.OverlayConfig{LoopToEnd: true})
	if err != nil {
		log.Fatal(err)
	}

	godub.NewExporter(destPath).WithDstFormat("wav").Export(path.Join(tmpDataDirectory(), "overlay-ring.wav"))
}

Split on Silence

func SplitOnSilence(seg *AudioSegment, minSilenceLen int, silenceThresh Volume, keepSilence int, seekStep int) ([]*AudioSegment, [][]float32)

Args: seg - a AudioSegment object minSilenceLen - the minimum silence lenght in milliseconds on which to segment the audios silenceThresh - the threshold in dB below which everything is considered silence keepSilence - the silence in milliseconds to keep at both ends of a segment seekStep - the step in milliseconds

Returns: chunks - an array of AudioSegments timings - an array with the start and end times in seconds

Takes a AudioSegment as input and return two arrays with chunks and their timing info The timing returned is in reference to the original segment and is measured in seconds. So if you combine the chunks, the timing will reflect the segment in the original audio, not the lenght of the new chunk you've created.

func main(){
	segment, _ := godub.NewLoader().Load(path.Join(dataDirectory(), "code-geass.mp3"))
	//threshold := godub.NewVolumeFromRatio(segment.DBFS().ToRatio(false)*0.15, 0, false) // Setting threshold as a ratio
	threshold := godub.Volume(-23) //Setting a threshold manually

	chunks, timings := godub.SplitOnSilence(segment, 1000, threshold, 1000, 1)
	for i := range segs {
		toFilePath := path.Join(tFP, "seg-"+strconv.Itoa(i))
		godub.NewExporter(toFilePath).WithDstFormat("wav").WithBitRate(8000).Export(chunks[i])

	}
}

Dependency

godub uses ffmpeg as its backend to support encoding, decoding and conversion.

References

  1. go-binary-pack
  2. Python struct
  3. Digital Audio - Creating a WAV (RIFF) file
  4. ffmpeg tutorial
  5. Python: manipulate raw audio data with audioop
  6. ffmpeg Documentation

Similar Projects

  1. cryptix/wav
  2. mdlayher/waveform
  3. go-audio

TODO

  • Audio effects.
  • As always, test test test!

License

godub is licensed under the MIT license. Please feel free and have fun.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ValidChannels = utils.NewSet(1, 2)
)

Functions

This section is empty.

Types

type AudioSegment

type AudioSegment struct {
	// contains filtered or unexported fields
}

AudioSegment represents an segment of audio that can be manipulated using Go code. AudioSegment is **immutable**.

func NewAudioSegment

func NewAudioSegment(data []byte, opts ...AudioSegmentOption) (*AudioSegment, error)

Factory functions

func NewAudioSegmentFromWaveAudio

func NewAudioSegmentFromWaveAudio(waveAudio *wav.WaveAudio) (*AudioSegment, error)

func NewEmptyAudioSegment

func NewEmptyAudioSegment() (*AudioSegment, error)

func NewSilentAudioSegment

func NewSilentAudioSegment(duration int, frameRate uint32) (*AudioSegment, error)

func SplitOnSilence added in v0.1.2

func SplitOnSilence(seg *AudioSegment, minSilenceLen int, silenceThresh Volume, keepSilence int, seekStep int) ([]*AudioSegment, [][]float32, error)

SplitOnSilence ...

func (*AudioSegment) Add

func (seg *AudioSegment) Add(other *AudioSegment) (*AudioSegment, error)

func (*AudioSegment) Append

func (seg *AudioSegment) Append(segments ...*AudioSegment) (*AudioSegment, error)

func (*AudioSegment) ApplyGain

func (seg *AudioSegment) ApplyGain(volumeChange Volume) (*AudioSegment, error)

func (*AudioSegment) AsWaveAudio

func (seg *AudioSegment) AsWaveAudio() *wav.WaveAudio

func (*AudioSegment) Channels

func (seg *AudioSegment) Channels() uint16

func (*AudioSegment) DBFS

func (seg *AudioSegment) DBFS() Volume

DBFS returns the value of dB Full Scale

func (*AudioSegment) Duration

func (seg *AudioSegment) Duration() time.Duration

func (*AudioSegment) Equal

func (seg *AudioSegment) Equal(other *AudioSegment) bool

func (*AudioSegment) ForkWithChannels

func (seg *AudioSegment) ForkWithChannels(channels uint16) (*AudioSegment, error)

func (*AudioSegment) ForkWithFrameRate

func (seg *AudioSegment) ForkWithFrameRate(frameRate int) (*AudioSegment, error)

func (*AudioSegment) ForkWithSampleWidth

func (seg *AudioSegment) ForkWithSampleWidth(sampleWidth int) (*AudioSegment, error)

func (*AudioSegment) FrameCount

func (seg *AudioSegment) FrameCount() float64

func (*AudioSegment) FrameCountIn

func (seg *AudioSegment) FrameCountIn(d time.Duration) float64

func (*AudioSegment) FrameRate

func (seg *AudioSegment) FrameRate() uint32

func (*AudioSegment) FrameWidth

func (seg *AudioSegment) FrameWidth() uint32

func (*AudioSegment) Len added in v0.1.2

func (seg *AudioSegment) Len() int

func (*AudioSegment) Max

func (seg *AudioSegment) Max() float64

func (*AudioSegment) MaxDBFS

func (seg *AudioSegment) MaxDBFS() Volume

func (*AudioSegment) MaxPossibleAmplitude

func (seg *AudioSegment) MaxPossibleAmplitude() float64

func (*AudioSegment) Overlay

func (seg *AudioSegment) Overlay(other *AudioSegment, config *OverlayConfig) (*AudioSegment, error)

Overlay overlays the given audio segment on the current segment.

func (*AudioSegment) RMS

func (seg *AudioSegment) RMS() float64

RMS returns the value of root mean square

func (*AudioSegment) RawData

func (seg *AudioSegment) RawData() []byte

func (*AudioSegment) Repeat

func (seg *AudioSegment) Repeat(count int) (*AudioSegment, error)

func (*AudioSegment) Reverse

func (seg *AudioSegment) Reverse() (*AudioSegment, error)

func (*AudioSegment) SampleWidth

func (seg *AudioSegment) SampleWidth() uint16

func (*AudioSegment) Slice

func (seg *AudioSegment) Slice(start, end time.Duration) (*AudioSegment, error)

Operations

func (*AudioSegment) SliceIndex added in v0.1.2

func (seg *AudioSegment) SliceIndex(startIndex, endIndex int) (*AudioSegment, error)

func (*AudioSegment) String

func (seg *AudioSegment) String() string

type AudioSegmentError

type AudioSegmentError struct {
	// contains filtered or unexported fields
}

func NewAudioSegmentError

func NewAudioSegmentError(format string, args ...interface{}) AudioSegmentError

func (AudioSegmentError) Error

func (e AudioSegmentError) Error() string

type AudioSegmentOption

type AudioSegmentOption func(*AudioSegment)

func Channels

func Channels(v uint16) AudioSegmentOption

func FrameRate

func FrameRate(v uint32) AudioSegmentOption

func FrameWidth

func FrameWidth(v uint32) AudioSegmentOption

func SampleWidth

func SampleWidth(v uint16) AudioSegmentOption

type Exporter

type Exporter struct {
	// contains filtered or unexported fields
}

func NewExporter

func NewExporter(dst interface{}) *Exporter

func (*Exporter) Export

func (e *Exporter) Export(segment *AudioSegment) error

func (*Exporter) WithBitRate

func (e *Exporter) WithBitRate(rate int) *Exporter

func (*Exporter) WithCodec

func (e *Exporter) WithCodec(c string) *Exporter

func (*Exporter) WithCover

func (e *Exporter) WithCover(c string) *Exporter

func (*Exporter) WithDstFormat

func (e *Exporter) WithDstFormat(f string) *Exporter

func (*Exporter) WithID3TagVersion

func (e *Exporter) WithID3TagVersion(v int) *Exporter

func (*Exporter) WithParams

func (e *Exporter) WithParams(p ...string) *Exporter

func (*Exporter) WithSampleRate

func (e *Exporter) WithSampleRate(rate int) *Exporter

func (*Exporter) WithTags

func (e *Exporter) WithTags(tags map[string]string) *Exporter

type InvalidFile added in v0.1.6

type InvalidFile struct {
	OriginalError string
}

InvalidFile error type

func (*InvalidFile) Error added in v0.1.6

func (invalidFile *InvalidFile) Error() string

type Loader

type Loader struct {
	// contains filtered or unexported fields
}

func NewLoader

func NewLoader() *Loader

NewLoader create a new loader

func (*Loader) Load

func (la *Loader) Load(src interface{}) (*AudioSegment, error)

Load ...

func (*Loader) WithParams

func (l *Loader) WithParams(params ...string) *Loader

type OverlayConfig

type OverlayConfig struct {
	// Position to start overlaying
	Position time.Duration
	// LoopToEnd indicates whether it's necessary to match the original segment's length
	LoopToEnd bool
	// LoopCount indicates that we should loop the segment for `LoopCount` times
	// until it matches the original segment length, default to 1.
	LoopCount         int
	GainDuringOverlay Volume
}

type Volume

type Volume float64

Volume is the quantity of three-dimensional space enclosed by a closed surface. Volume unit is dBFS.

func NewVolumeFromRatio

func NewVolumeFromRatio(ratio float64, denominator float64, useAmplitude bool) Volume

func (Volume) String

func (volume Volume) String() string

func (Volume) ToRatio

func (volume Volume) ToRatio(useAmplitude bool) float64

ToFloat64 converts db to a float, which represents the equivalent ratio in power

Directories

Path Synopsis
_examples
Package audioop provides some useful operations on sound fragments by manipulating raw audio data.
Package audioop provides some useful operations on sound fragments by manipulating raw audio data.
Package wav defines WAV audio struct and Chunk struct.
Package wav defines WAV audio struct and Chunk struct.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL