Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 7 additions & 19 deletions cmd/media/fingerprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"fmt"
"os"
"time"

// Packages
chromaprint "github.com/mutablelogic/go-media/pkg/chromaprint"
Expand All @@ -18,10 +19,11 @@ type FingerprintCommands struct {
}

type MatchMusic struct {
Path string `arg:"" type:"path" help:"File"`
APIKey string `env:"CHROMAPRINT_KEY" help:"API key for the music matching service (https://acoustid.org/login)"`
Type []string `cmd:"" help:"Type of match to perform" enum:"any,recording,release,releasegroup,track" default:"any"`
Score float64 `cmd:"" help:"Minimum match scoreto perform" default:"0.9"`
Path string `arg:"" type:"path" help:"File"`
APIKey string `env:"CHROMAPRINT_KEY" help:"API key for the music matching service (https://acoustid.org/login)"`
Type []string `cmd:"" help:"Type of match to perform" enum:"any,recording,release,releasegroup,track" default:"any"`
Score float64 `cmd:"" help:"Minimum match scoreto perform" default:"0.9"`
Duration time.Duration `cmd:"" help:"Length of audio to use for fingerprinting" default:"30s"`
}

///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -62,7 +64,7 @@ func (cmd *MatchMusic) Run(app server.Cmd) error {
}

// Create the matches
matches, err := client.Match(app.Context(), r, meta)
matches, err := client.Match(app.Context(), r, cmd.Duration, meta)
if err != nil {
return err
}
Expand All @@ -78,17 +80,3 @@ func (cmd *MatchMusic) Run(app server.Cmd) error {
fmt.Println(result)
return nil
}

/*

META_RECORDING Meta = (1 << iota)
META_RECORDINGID
META_RELEASE
META_RELEASEID
META_RELEASEGROUP
META_RELEASEGROUPID
META_TRACK
META_COMPRESS
META_USERMETA
META_SOURCE
*/
21 changes: 15 additions & 6 deletions pkg/chromaprint/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ const (

// defaultQps rate limits number of requests per second
defaultQps = 3

// sample rate used for fingerprinting
sampleRate = 32000
)

///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -94,10 +97,11 @@ func (c *Client) Lookup(fingerprint string, duration time.Duration, flags Meta)
////////////////////////////////////////////////////////////////////////////////
// FINGERPRINT

// Match a media file and lookup any matches
func (c *Client) Match(ctx context.Context, r io.Reader, flags Meta) ([]*ResponseMatch, error) {
// Match a media file and lookup any matches, using up to "dur" seconds
// to fingerprint (or zero for no limit). The fingerprint is calculated
func (c *Client) Match(ctx context.Context, r io.Reader, dur time.Duration, flags Meta) ([]*ResponseMatch, error) {
// Create a segmenter
segmenter, err := segmenter.NewReader(r, 0, 32000)
segmenter, err := segmenter.NewReader(r, dur, sampleRate)
if err != nil {
return nil, err
}
Expand All @@ -111,13 +115,17 @@ func (c *Client) Match(ctx context.Context, r io.Reader, flags Meta) ([]*Respons
defer fp.Free()

// Start the fingerprinting
if err := fp.Start(32000, 1); err != nil {
if err := fp.Start(sampleRate, 1); err != nil {
return nil, err
}

// Perform fingerprinting
// Perform fingerprinting. Segment the audio into 'dur' segments, only feed
// the fingerprinter when the timestamp is less than 'dur'
if err := segmenter.DecodeInt16(ctx, func(timestamp time.Duration, data []int16) error {
return fp.WritePtr(uintptr(unsafe.Pointer(&data[0])), len(data))
if dur == 0 || timestamp < dur {
return fp.WritePtr(uintptr(unsafe.Pointer(&data[0])), len(data))
}
return nil
}); err != nil {
return nil, err
}
Expand All @@ -127,6 +135,7 @@ func (c *Client) Match(ctx context.Context, r io.Reader, flags Meta) ([]*Respons
return nil, err
}

// Get fingerprint value
value, err := fp.GetFingerprint()
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion pkg/chromaprint/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func Test_client_004(t *testing.T) {
}
defer r.Close()

matches, err := client.Match(context.Background(), r, META_ALL)
matches, err := client.Match(context.Background(), r, 0, META_ALL)
assert.NoError(err)
t.Log(matches)
}
6 changes: 3 additions & 3 deletions pkg/segmenter/segmenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func (s *Segmenter) Close() error {

// Return current timestamp
func (s *Segmenter) Duration() time.Duration {
return s.ts
return s.reader.Duration()
}

// Segments are output through a callback, with the samples and a timestamp
Expand All @@ -109,7 +109,7 @@ func (s *Segmenter) DecodeFloat32(ctx context.Context, fn SegmentFuncFloat32) er

// Allocate the buffer
if s.n > 0 {
s.buf_flt = make([]float32, s.n)
s.buf_flt = make([]float32, 0, s.n)
}

// Decode samples and segment
Expand Down Expand Up @@ -174,7 +174,7 @@ func (s *Segmenter) DecodeInt16(ctx context.Context, fn SegmentFuncInt16) error

// Allocate the buffer
if s.n > 0 {
s.buf_s16 = make([]int16, s.n)
s.buf_s16 = make([]int16, 0, s.n)
}

// Decode samples and segment
Expand Down
Loading